Repository: neovim/neovim
File: src/nvim/memline.c (C)

Code before:
  }
  ssize_t maxlen = (ssize_t)strlen(ptr);
  if (len == -1 || len > maxlen) {
    len = maxlen;
  }
  buf->deleted_bytes += (size_t)len + 1;
  buf->deleted_bytes2 += (size_t)len + 1;
  if (buf->update_need_codepoints) {
    mb_utflen(ptr, (size_t)len, &buf->deleted_codepoints,
              &buf->deleted_codeunits);
    buf->deleted_codepoints++;  // NL char
    buf->deleted_codeunits++;
  }
}

int ml_replace(linenr_T lnum, char *line, bool copy)
{
  return ml_replace_buf(curbuf, lnum, line, copy, false);
}

int ml_replace_len(linenr_T lnum, char *line, size_t len, bool copy)
{
  return ml_replace_buf_len(curbuf, lnum, line, len, copy, false);
}

/// Replace line "lnum", with buffering, in current buffer.
///
/// @param copy  if true, make a copy of the line, otherwise the line has been
///              copied to allocated memory already.
///              if false, the "line" may be freed to add text properties!
///
/// Do not use it after calling ml_replace().
///
/// Check: The caller of this function should probably also call
/// changed_lines(), unless update_screen(UPD_NOT_VALID) is used.
///
/// @return  FAIL for failure, OK otherwise
int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy, bool noalloc)
  FUNC_ATTR_NONNULL_ARG(1)
{
  size_t len = line != NULL ? strlen(line) : (size_t)-1;
  return ml_replace_buf_len(buf, lnum, line, len, copy, noalloc);
}

int ml_replace_buf_len(buf_T *buf, linenr_T lnum, char *line_arg, size_t len_arg, bool copy,
                       bool noalloc)
  FUNC_ATTR_NONNULL_ARG(1)
{
  char *line = line_arg;
  colnr_T len = (colnr_T)len_arg;


Review comment (suggestion):
`len` isn't suppose to account for `NUL`. `ml_replace_buf_len()` assumes `line[len] == NUL` and `xmemdupz(line, len_arg)` follows that assumption.

Code after:
  }
  ssize_t maxlen = (ssize_t)strlen(ptr);
  if (len == -1 || len > maxlen) {
    len = maxlen;
  }
  buf->deleted_bytes += (size_t)len + 1;
  buf->deleted_bytes2 += (size_t)len + 1;
  if (buf->update_need_codepoints) {
    mb_utflen(ptr, (size_t)len, &buf->deleted_codepoints,
              &buf->deleted_codeunits);
    buf->deleted_codepoints++;  // NL char
    buf->deleted_codeunits++;
  }
}

/// Replace line "lnum", with buffering, in current buffer.
int ml_replace(linenr_T lnum, char *line, bool copy)
{
  return ml_replace_buf(curbuf, lnum, line, copy, false);
}

/// Replace a line for the current buffer.  Like ml_replace() with:
/// "len" is the length of the text, excluding NUL.
int ml_replace_len(linenr_T lnum, char *line, size_t len, bool copy)
{
  return ml_replace_buf_len(curbuf, lnum, line, len, copy, false);
}

int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy, bool noalloc)
  FUNC_ATTR_NONNULL_ARG(1)
{
  size_t len = line != NULL ? strlen(line) : (size_t)-1;
  return ml_replace_buf_len(buf, lnum, line, len, copy, noalloc);
}

/// Replace line "lnum", with buffering.
///
/// @param copy  if true, make a copy of the line, otherwise the line has been
///              copied to allocated memory already.
///              if false, the "line" may be freed to add text properties!
/// @param len_arg  length of the text, excluding NUL
///
/// Do not use it after calling ml_replace().
///
/// Check: The caller of this function should probably also call
/// changed_lines(), unless update_screen(UPD_NOT_VALID) is used.
///
/// @return  FAIL for failure, OK otherwise
int ml_replace_buf_len(buf_T *buf, linenr_T lnum, char *line_arg, size_t len_arg, bool copy,
                       bool noalloc)
  FUNC_ATTR_NONNULL_ARG(1)