* search.c (find_newline): Rewrite to prefer offsets to pointers.
This avoids undefined behavior when subtracting pointers into different aways. On my platform it also makes the code a tad smaller and presumably faster.
This commit is contained in:
parent
8ee0219ffe
commit
5389db9e71
2 changed files with 45 additions and 60 deletions
|
@ -1,3 +1,10 @@
|
|||
2013-11-11 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
* search.c (find_newline): Rewrite to prefer offsets to pointers.
|
||||
This avoids undefined behavior when subtracting pointers into
|
||||
different aways. On my platform it also makes the code a tad
|
||||
smaller and presumably faster.
|
||||
|
||||
2013-11-11 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* keyboard.c (command_loop_1): Use region-extract-function.
|
||||
|
|
98
src/search.c
98
src/search.c
|
@ -720,58 +720,45 @@ find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
|
|||
|
||||
{
|
||||
/* The termination address of the dumb loop. */
|
||||
register unsigned char *ceiling_addr
|
||||
= BYTE_POS_ADDR (ceiling_byte) + 1;
|
||||
register unsigned char *cursor
|
||||
= BYTE_POS_ADDR (start_byte);
|
||||
unsigned char *base = cursor;
|
||||
unsigned char *lim_addr = BYTE_POS_ADDR (ceiling_byte) + 1;
|
||||
ptrdiff_t lim_byte = ceiling_byte + 1;
|
||||
|
||||
while (cursor < ceiling_addr)
|
||||
{
|
||||
/* Nonpositive offsets (relative to LIM_ADDR and LIM_BYTE)
|
||||
of the base, the cursor, and the next line. */
|
||||
ptrdiff_t base = start_byte - lim_byte;
|
||||
ptrdiff_t cursor, next;
|
||||
|
||||
for (cursor = base; cursor < 0; cursor = next)
|
||||
{
|
||||
/* The dumb loop. */
|
||||
unsigned char *nl = memchr (cursor, '\n', ceiling_addr - cursor);
|
||||
unsigned char *nl = memchr (lim_addr + cursor, '\n', - cursor);
|
||||
next = nl ? nl - lim_addr : 0;
|
||||
|
||||
/* If we're looking for newlines, cache the fact that
|
||||
the region from start to cursor is free of them. */
|
||||
this line's region is free of them. */
|
||||
if (newline_cache)
|
||||
{
|
||||
unsigned char *low = cursor;
|
||||
unsigned char *lim = nl ? nl : ceiling_addr;
|
||||
know_region_cache (current_buffer, newline_cache,
|
||||
BYTE_TO_CHAR (low - base + start_byte),
|
||||
BYTE_TO_CHAR (lim - base + start_byte));
|
||||
BYTE_TO_CHAR (lim_byte + cursor),
|
||||
BYTE_TO_CHAR (lim_byte + next));
|
||||
/* know_region_cache can relocate buffer text. */
|
||||
lim_addr = BYTE_POS_ADDR (ceiling_byte) + 1;
|
||||
}
|
||||
|
||||
if (! nl)
|
||||
break;
|
||||
next++;
|
||||
|
||||
if (--count == 0)
|
||||
{
|
||||
immediate_quit = 0;
|
||||
if (bytepos)
|
||||
*bytepos = nl + 1 - base + start_byte;
|
||||
return BYTE_TO_CHAR (nl + 1 - base + start_byte);
|
||||
*bytepos = lim_byte + next;
|
||||
return BYTE_TO_CHAR (lim_byte + next);
|
||||
}
|
||||
if (newline_cache)
|
||||
{
|
||||
/* The call to know_region_cache could have
|
||||
allocated memory and caused relocation of buffer
|
||||
text. If it did, adjust pointers into buffer
|
||||
text. */
|
||||
ptrdiff_t offset = BYTE_POS_ADDR (start_byte) - base;
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
cursor += offset;
|
||||
base += offset;
|
||||
ceiling_addr += offset;
|
||||
nl += offset;
|
||||
}
|
||||
}
|
||||
cursor = nl + 1;
|
||||
}
|
||||
|
||||
start_byte += ceiling_addr - base;
|
||||
start_byte = lim_byte;
|
||||
start = BYTE_TO_CHAR (start_byte);
|
||||
}
|
||||
}
|
||||
|
@ -810,24 +797,28 @@ find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
|
|||
|
||||
{
|
||||
/* The termination address of the dumb loop. */
|
||||
register unsigned char *ceiling_addr = BYTE_POS_ADDR (ceiling_byte);
|
||||
register unsigned char *cursor = BYTE_POS_ADDR (start_byte - 1);
|
||||
unsigned char *base = cursor;
|
||||
unsigned char *ceiling_addr = BYTE_POS_ADDR (ceiling_byte);
|
||||
|
||||
while (cursor >= ceiling_addr)
|
||||
/* Offsets (relative to CEILING_ADDR and CEILING_BYTE) of
|
||||
the base, the cursor, and the previous line. These
|
||||
offsets are at least -1. */
|
||||
ptrdiff_t base = start_byte - ceiling_byte;
|
||||
ptrdiff_t cursor, prev;
|
||||
|
||||
for (cursor = base; 0 < cursor; cursor = prev)
|
||||
{
|
||||
unsigned char *nl = memrchr (ceiling_addr, '\n',
|
||||
cursor + 1 - ceiling_addr);
|
||||
unsigned char *nl = memrchr (ceiling_addr, '\n', cursor);
|
||||
prev = nl ? nl - ceiling_addr : -1;
|
||||
|
||||
/* If we're looking for newlines, cache the fact that
|
||||
the region from after the cursor to start is free of them. */
|
||||
this line's region is free of them. */
|
||||
if (newline_cache)
|
||||
{
|
||||
unsigned char *low = nl ? nl : ceiling_addr - 1;
|
||||
unsigned char *lim = cursor;
|
||||
know_region_cache (current_buffer, newline_cache,
|
||||
BYTE_TO_CHAR (low - base + start_byte),
|
||||
BYTE_TO_CHAR (lim - base + start_byte));
|
||||
BYTE_TO_CHAR (ceiling_byte + prev + 1),
|
||||
BYTE_TO_CHAR (ceiling_byte + cursor));
|
||||
/* know_region_cache can relocate buffer text. */
|
||||
ceiling_addr = BYTE_POS_ADDR (ceiling_byte);
|
||||
}
|
||||
|
||||
if (! nl)
|
||||
|
@ -837,25 +828,12 @@ find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
|
|||
{
|
||||
immediate_quit = 0;
|
||||
if (bytepos)
|
||||
*bytepos = nl - base + start_byte;
|
||||
return BYTE_TO_CHAR (nl - base + start_byte);
|
||||
*bytepos = ceiling_byte + prev + 1;
|
||||
return BYTE_TO_CHAR (ceiling_byte + prev + 1);
|
||||
}
|
||||
if (newline_cache)
|
||||
{
|
||||
ptrdiff_t offset = BYTE_POS_ADDR (start_byte - 1) - base;
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
cursor += offset;
|
||||
base += offset;
|
||||
ceiling_addr += offset;
|
||||
nl += offset;
|
||||
}
|
||||
}
|
||||
cursor = nl - 1;
|
||||
}
|
||||
|
||||
start_byte += ceiling_addr - 1 - base;
|
||||
start_byte = ceiling_byte;
|
||||
start = BYTE_TO_CHAR (start_byte);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue