aboutsummaryrefslogtreecommitdiffstats
path: root/src/search.c
diff options
context:
space:
mode:
authorPaul Eggert2014-04-22 14:32:51 -0700
committerPaul Eggert2014-04-22 14:32:51 -0700
commit42e910349d699ee3f8024371ca1e60e015fc6aa7 (patch)
treeba589f3f7c278671f0ae9c5c8f15c241ae8dd674 /src/search.c
parent4f96579371290b201a973072a1c2f237755bb954 (diff)
parent34e856d5ac828753b7be20e2471f39fb613f7f40 (diff)
downloademacs-42e910349d699ee3f8024371ca1e60e015fc6aa7.tar.gz
emacs-42e910349d699ee3f8024371ca1e60e015fc6aa7.zip
Merge from emacs-24; up to 2014-04-22T20:19:17Z!eggert@cs.ucla.edu
Diffstat (limited to 'src/search.c')
-rw-r--r--src/search.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/search.c b/src/search.c
index 9bec825abcd..ee449213ace 100644
--- a/src/search.c
+++ b/src/search.c
@@ -3098,6 +3098,169 @@ DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,
3098 out - temp, 3098 out - temp,
3099 STRING_MULTIBYTE (string)); 3099 STRING_MULTIBYTE (string));
3100} 3100}
3101
3102/* Like find_newline, but doesn't use the cache, and only searches forward. */
3103static ptrdiff_t
3104find_newline1 (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
3105 ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *shortage,
3106 ptrdiff_t *bytepos, bool allow_quit)
3107{
3108 if (count > 0)
3109 {
3110 if (!end)
3111 end = ZV, end_byte = ZV_BYTE;
3112 }
3113 else
3114 {
3115 if (!end)
3116 end = BEGV, end_byte = BEGV_BYTE;
3117 }
3118 if (end_byte == -1)
3119 end_byte = CHAR_TO_BYTE (end);
3120
3121 if (shortage != 0)
3122 *shortage = 0;
3123
3124 immediate_quit = allow_quit;
3125
3126 if (count > 0)
3127 while (start != end)
3128 {
3129 /* Our innermost scanning loop is very simple; it doesn't know
3130 about gaps, buffer ends, or the newline cache. ceiling is
3131 the position of the last character before the next such
3132 obstacle --- the last character the dumb search loop should
3133 examine. */
3134 ptrdiff_t tem, ceiling_byte = end_byte - 1;
3135
3136 if (start_byte == -1)
3137 start_byte = CHAR_TO_BYTE (start);
3138
3139 /* The dumb loop can only scan text stored in contiguous
3140 bytes. BUFFER_CEILING_OF returns the last character
3141 position that is contiguous, so the ceiling is the
3142 position after that. */
3143 tem = BUFFER_CEILING_OF (start_byte);
3144 ceiling_byte = min (tem, ceiling_byte);
3145
3146 {
3147 /* The termination address of the dumb loop. */
3148 unsigned char *lim_addr = BYTE_POS_ADDR (ceiling_byte) + 1;
3149 ptrdiff_t lim_byte = ceiling_byte + 1;
3150
3151 /* Nonpositive offsets (relative to LIM_ADDR and LIM_BYTE)
3152 of the base, the cursor, and the next line. */
3153 ptrdiff_t base = start_byte - lim_byte;
3154 ptrdiff_t cursor, next;
3155
3156 for (cursor = base; cursor < 0; cursor = next)
3157 {
3158 /* The dumb loop. */
3159 unsigned char *nl = memchr (lim_addr + cursor, '\n', - cursor);
3160 next = nl ? nl - lim_addr : 0;
3161
3162 if (! nl)
3163 break;
3164 next++;
3165
3166 if (--count == 0)
3167 {
3168 immediate_quit = 0;
3169 if (bytepos)
3170 *bytepos = lim_byte + next;
3171 return BYTE_TO_CHAR (lim_byte + next);
3172 }
3173 }
3174
3175 start_byte = lim_byte;
3176 start = BYTE_TO_CHAR (start_byte);
3177 }
3178 }
3179
3180 immediate_quit = 0;
3181 if (shortage)
3182 *shortage = count;
3183 if (bytepos)
3184 {
3185 *bytepos = start_byte == -1 ? CHAR_TO_BYTE (start) : start_byte;
3186 eassert (*bytepos == CHAR_TO_BYTE (start));
3187 }
3188 return start;
3189}
3190
3191DEFUN ("newline-cache-check", Fnewline_cache_check, Snewline_cache_check,
3192 0, 1, 0,
3193 doc: /* Check the newline cache of BUFFER against buffer contents.
3194
3195BUFFER defaults to the current buffer.
3196
3197Value is an array of 2 sub-arrays of buffer positions for newlines,
3198the first based on the cache, the second based on actually scanning
3199the buffer. If the buffer doesn't have a cache, the value is nil. */)
3200 (Lisp_Object buffer)
3201{
3202 struct buffer *buf;
3203 ptrdiff_t shortage, nl_count_cache, nl_count_buf;
3204 Lisp_Object cache_newlines, buf_newlines, val;
3205 ptrdiff_t from, found, i;
3206
3207 if (NILP (buffer))
3208 buf = current_buffer;
3209 else
3210 {
3211 CHECK_BUFFER (buffer);
3212 buf = XBUFFER (buffer);
3213 }
3214 if (buf->base_buffer)
3215 buf = buf->base_buffer;
3216
3217 /* If the buffer doesn't have a newline cache, return nil. */
3218 if (NILP (BVAR (buf, cache_long_scans))
3219 || buf->newline_cache == NULL)
3220 return Qnil;
3221
3222 /* How many newlines are there according to the cache? */
3223 find_newline (BUF_BEG (buf), BUF_BEG_BYTE (buf),
3224 BUF_Z (buf), BUF_Z_BYTE (buf),
3225 TYPE_MAXIMUM (ptrdiff_t), &shortage, NULL, true);
3226 nl_count_cache = TYPE_MAXIMUM (ptrdiff_t) - shortage;
3227
3228 /* Create vector and populate it. */
3229 cache_newlines = make_uninit_vector (nl_count_cache);
3230 for (from = BUF_BEG( buf), found = from, i = 0;
3231 from < BUF_Z (buf);
3232 from = found, i++)
3233 {
3234 ptrdiff_t from_byte = CHAR_TO_BYTE (from);
3235
3236 found = find_newline (from, from_byte, 0, -1, 1, &shortage, NULL, true);
3237 if (shortage == 0)
3238 ASET (cache_newlines, i, make_number (found - 1));
3239 }
3240
3241 /* Now do the same, but without using the cache. */
3242 find_newline1 (BUF_BEG (buf), BUF_BEG_BYTE (buf),
3243 BUF_Z (buf), BUF_Z_BYTE (buf),
3244 TYPE_MAXIMUM (ptrdiff_t), &shortage, NULL, true);
3245 nl_count_buf = TYPE_MAXIMUM (ptrdiff_t) - shortage;
3246 buf_newlines = make_uninit_vector (nl_count_buf);
3247 for (from = BUF_BEG( buf), found = from, i = 0;
3248 from < BUF_Z (buf);
3249 from = found, i++)
3250 {
3251 ptrdiff_t from_byte = CHAR_TO_BYTE (from);
3252
3253 found = find_newline1 (from, from_byte, 0, -1, 1, &shortage, NULL, true);
3254 if (shortage == 0)
3255 ASET (buf_newlines, i, make_number (found - 1));
3256 }
3257
3258 /* Construct the value and return it. */
3259 val = make_uninit_vector (2);
3260 ASET (val, 0, cache_newlines);
3261 ASET (val, 1, buf_newlines);
3262 return val;
3263}
3101 3264
3102void 3265void
3103syms_of_search (void) 3266syms_of_search (void)
@@ -3170,4 +3333,5 @@ is to bind it with `let' around a small expression. */);
3170 defsubr (&Smatch_data); 3333 defsubr (&Smatch_data);
3171 defsubr (&Sset_match_data); 3334 defsubr (&Sset_match_data);
3172 defsubr (&Sregexp_quote); 3335 defsubr (&Sregexp_quote);
3336 defsubr (&Snewline_cache_check);
3173} 3337}