builtin/apply: extract line_by_line_fuzzy_match() from match_fragment()

The match_fragment() function is very big and contains a big special case algorithm that does line by line fuzzy matching. So let's extract this algorithm in a separate line_by_line_fuzzy_match() function. Reviewed-by: Stefan Beller <sbeller@google.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Christian Couder committed May 11, 2016 at 15:16 UTC 7a3eb9e2224d883df229fe4adce51e762165573a
1 file changed +71 -55
builtin/apply.c
+71 -55
@@ -2242,6 +2242,74 @@ static void update_pre_post_images(struct image *preimage,
2242 postimage->nr -= reduced;
2243 }
2244
2245 +static int line_by_line_fuzzy_match(struct image *img,
2246 + struct image *preimage,
2247 + struct image *postimage,
2248 + unsigned long try,
2249 + int try_lno,
2250 + int preimage_limit)
2251 +{
2252 + int i;
2253 + size_t imgoff = 0;
2254 + size_t preoff = 0;
2255 + size_t postlen = postimage->len;
2256 + size_t extra_chars;
2257 + char *buf;
2258 + char *preimage_eof;
2259 + char *preimage_end;
2260 + struct strbuf fixed;
2261 + char *fixed_buf;
2262 + size_t fixed_len;
2263 +
2264 + for (i = 0; i < preimage_limit; i++) {
2265 + size_t prelen = preimage->line[i].len;
2266 + size_t imglen = img->line[try_lno+i].len;
2267 +
2268 + if (!fuzzy_matchlines(img->buf + try + imgoff, imglen,
2269 + preimage->buf + preoff, prelen))
2270 + return 0;
2271 + if (preimage->line[i].flag & LINE_COMMON)
2272 + postlen += imglen - prelen;
2273 + imgoff += imglen;
2274 + preoff += prelen;
2275 + }
2276 +
2277 + /*
2278 + * Ok, the preimage matches with whitespace fuzz.
2279 + *
2280 + * imgoff now holds the true length of the target that
2281 + * matches the preimage before the end of the file.
2282 + *
2283 + * Count the number of characters in the preimage that fall
2284 + * beyond the end of the file and make sure that all of them
2285 + * are whitespace characters. (This can only happen if
2286 + * we are removing blank lines at the end of the file.)
2287 + */
2288 + buf = preimage_eof = preimage->buf + preoff;
2289 + for ( ; i < preimage->nr; i++)
2290 + preoff += preimage->line[i].len;
2291 + preimage_end = preimage->buf + preoff;
2292 + for ( ; buf < preimage_end; buf++)
2293 + if (!isspace(*buf))
2294 + return 0;
2295 +
2296 + /*
2297 + * Update the preimage and the common postimage context
2298 + * lines to use the same whitespace as the target.
2299 + * If whitespace is missing in the target (i.e.
2300 + * if the preimage extends beyond the end of the file),
2301 + * use the whitespace from the preimage.
2302 + */
2303 + extra_chars = preimage_end - preimage_eof;
2304 + strbuf_init(&fixed, imgoff + extra_chars);
2305 + strbuf_add(&fixed, img->buf + try, imgoff);
2306 + strbuf_add(&fixed, preimage_eof, extra_chars);
2307 + fixed_buf = strbuf_detach(&fixed, &fixed_len);
2308 + update_pre_post_images(preimage, postimage,
2309 + fixed_buf, fixed_len, postlen);
2310 + return 1;
2311 +}
2312 +
2313 static int match_fragment(struct image *img,
2314 struct image *preimage,
2315 struct image *postimage,
@@ -2331,61 +2399,9 @@ static int match_fragment(struct image *img,
2399 * fuzzy matching. We collect all the line length information because
2400 * we need it to adjust whitespace if we match.
2401 */
2334 - if (ws_ignore_action == ignore_ws_change) {
2335 - size_t imgoff = 0;
2336 - size_t preoff = 0;
2337 - size_t postlen = postimage->len;
2338 - size_t extra_chars;
2339 - char *preimage_eof;
2340 - char *preimage_end;
2341 - for (i = 0; i < preimage_limit; i++) {
2342 - size_t prelen = preimage->line[i].len;
2343 - size_t imglen = img->line[try_lno+i].len;
2344 -
2345 - if (!fuzzy_matchlines(img->buf + try + imgoff, imglen,
2346 - preimage->buf + preoff, prelen))
2347 - return 0;
2348 - if (preimage->line[i].flag & LINE_COMMON)
2349 - postlen += imglen - prelen;
2350 - imgoff += imglen;
2351 - preoff += prelen;
2352 - }
2353 -
2354 - /*
2355 - * Ok, the preimage matches with whitespace fuzz.
2356 - *
2357 - * imgoff now holds the true length of the target that
2358 - * matches the preimage before the end of the file.
2359 - *
2360 - * Count the number of characters in the preimage that fall
2361 - * beyond the end of the file and make sure that all of them
2362 - * are whitespace characters. (This can only happen if
2363 - * we are removing blank lines at the end of the file.)
2364 - */
2365 - buf = preimage_eof = preimage->buf + preoff;
2366 - for ( ; i < preimage->nr; i++)
2367 - preoff += preimage->line[i].len;
2368 - preimage_end = preimage->buf + preoff;
2369 - for ( ; buf < preimage_end; buf++)
2370 - if (!isspace(*buf))
2371 - return 0;
2372 -
2373 - /*
2374 - * Update the preimage and the common postimage context
2375 - * lines to use the same whitespace as the target.
2376 - * If whitespace is missing in the target (i.e.
2377 - * if the preimage extends beyond the end of the file),
2378 - * use the whitespace from the preimage.
2379 - */
2380 - extra_chars = preimage_end - preimage_eof;
2381 - strbuf_init(&fixed, imgoff + extra_chars);
2382 - strbuf_add(&fixed, img->buf + try, imgoff);
2383 - strbuf_add(&fixed, preimage_eof, extra_chars);
2384 - fixed_buf = strbuf_detach(&fixed, &fixed_len);
2385 - update_pre_post_images(preimage, postimage,
2386 - fixed_buf, fixed_len, postlen);
2387 - return 1;
2388 - }
2402 + if (ws_ignore_action == ignore_ws_change)
2403 + return line_by_line_fuzzy_match(img, preimage, postimage,
2404 + try, try_lno, preimage_limit);
2405
2406 if (ws_error_action != correct_ws_error)
2407 return 0;