Function: compare-buffer-substrings

compare-buffer-substrings is a function defined in editfns.c.

Signature

(compare-buffer-substrings BUFFER1 START1 END1 BUFFER2 START2 END2)

Documentation

Compare two substrings of two buffers; return result as number.

Return -N if first string is less after N-1 chars, +N if first string is greater after N-1 chars, or 0 if strings match. The first substring is in BUFFER1 from START1 to END1 and the second is in BUFFER2 from START2 to END2. All arguments may be nil. If BUFFER1 or BUFFER2 is nil, the current buffer is used. If START1 or START2 is nil, the value of point-min in the respective buffers is used. If END1 or END2 is nil, the value of point-max in the respective buffers is used. The value of case-fold-search in the current buffer determines whether case is significant or ignored.

Source Code

// Defined in /usr/src/emacs/src/editfns.c
{
  register EMACS_INT begp1, endp1, begp2, endp2, temp;
  register struct buffer *bp1, *bp2;
  register Lisp_Object trt
    = (!NILP (BVAR (current_buffer, case_fold_search))
       ? BVAR (current_buffer, case_canon_table) : Qnil);
  ptrdiff_t chars = 0;
  ptrdiff_t i1, i2, i1_byte, i2_byte;

  /* Find the first buffer and its substring.  */

  if (NILP (buffer1))
    bp1 = current_buffer;
  else
    {
      Lisp_Object buf1;
      buf1 = Fget_buffer (buffer1);
      if (NILP (buf1))
	nsberror (buffer1);
      bp1 = XBUFFER (buf1);
      if (!BUFFER_LIVE_P (bp1))
	error ("Selecting deleted buffer");
    }

  begp1 = !NILP (start1) ? fix_position (start1) : BUF_BEGV (bp1);
  endp1 = !NILP (end1) ? fix_position (end1) : BUF_ZV (bp1);
  if (begp1 > endp1)
    temp = begp1, begp1 = endp1, endp1 = temp;

  if (!(BUF_BEGV (bp1) <= begp1
	&& begp1 <= endp1
        && endp1 <= BUF_ZV (bp1)))
    args_out_of_range (start1, end1);

  /* Likewise for second substring.  */

  if (NILP (buffer2))
    bp2 = current_buffer;
  else
    {
      Lisp_Object buf2;
      buf2 = Fget_buffer (buffer2);
      if (NILP (buf2))
	nsberror (buffer2);
      bp2 = XBUFFER (buf2);
      if (!BUFFER_LIVE_P (bp2))
	error ("Selecting deleted buffer");
    }

  begp2 = !NILP (start2) ? fix_position (start2) : BUF_BEGV (bp2);
  endp2 = !NILP (end2) ? fix_position (end2) : BUF_ZV (bp2);
  if (begp2 > endp2)
    temp = begp2, begp2 = endp2, endp2 = temp;

  if (!(BUF_BEGV (bp2) <= begp2
	&& begp2 <= endp2
        && endp2 <= BUF_ZV (bp2)))
    args_out_of_range (start2, end2);

  i1 = begp1;
  i2 = begp2;
  i1_byte = buf_charpos_to_bytepos (bp1, i1);
  i2_byte = buf_charpos_to_bytepos (bp2, i2);

  while (i1 < endp1 && i2 < endp2)
    {
      /* When we find a mismatch, we must compare the
	 characters, not just the bytes.  */
      int c1, c2;

      if (! NILP (BVAR (bp1, enable_multibyte_characters)))
	{
	  c1 = BUF_FETCH_MULTIBYTE_CHAR (bp1, i1_byte);
	  i1_byte += buf_next_char_len (bp1, i1_byte);
	  i1++;
	}
      else
	{
	  c1 = make_char_multibyte (BUF_FETCH_BYTE (bp1, i1));
	  i1++;
	}

      if (! NILP (BVAR (bp2, enable_multibyte_characters)))
	{
	  c2 = BUF_FETCH_MULTIBYTE_CHAR (bp2, i2_byte);
	  i2_byte += buf_next_char_len (bp2, i2_byte);
	  i2++;
	}
      else
	{
	  c2 = make_char_multibyte (BUF_FETCH_BYTE (bp2, i2));
	  i2++;
	}

      if (!NILP (trt))
	{
	  c1 = char_table_translate (trt, c1);
	  c2 = char_table_translate (trt, c2);
	}

      if (c1 != c2)
	return make_fixnum (c1 < c2 ? -1 - chars : chars + 1);

      chars++;
      rarely_quit (chars);
    }

  /* The strings match as far as they go.
     If one is shorter, that one is less.  */
  if (chars < endp1 - begp1)
    return make_fixnum (chars + 1);
  else if (chars < endp2 - begp2)
    return make_fixnum (- chars - 1);

  /* Same length too => they are equal.  */
  return make_fixnum (0);
}