whitespace: replumb ws_fix_copy to take a strbuf *dst instead of char *dst
To implement --whitespace=fix for tab-in-indent, we have to allow for the possibility that whitespace can increase in size when it is fixed, expanding tabs to to multiple spaces in the initial indent. Signed-off-by: Chris Webb <chris@arachsys.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Chris Webb committed
Apr 3, 2010 at 00:37 UTC
d511bd330d66fe8f0be21855888e30af2f3e373b
3 files changed
+48
-54
builtin/apply.c
+39
-42
@@ -1854,6 +1854,8 @@ static int match_fragment(struct image *img,
1854
{
1855
int i;
1856
char *fixed_buf, *buf, *orig, *target;
1857
+ struct strbuf fixed;
1858
+ size_t fixed_len;
1859
int preimage_limit;
1860
1861
if (preimage->nr + try_lno <= img->nr) {
@@ -1977,12 +1979,12 @@ static int match_fragment(struct image *img,
1979
* use the whitespace from the preimage.
1980
*/
1981
extra_chars = preimage_end - preimage_eof;
1980
- fixed_buf = xmalloc(imgoff + extra_chars);
1981
- memcpy(fixed_buf, img->buf + try, imgoff);
1982
- memcpy(fixed_buf + imgoff, preimage_eof, extra_chars);
1983
- imgoff += extra_chars;
1982
+ strbuf_init(&fixed, imgoff + extra_chars);
1983
+ strbuf_add(&fixed, img->buf + try, imgoff);
1984
+ strbuf_add(&fixed, preimage_eof, extra_chars);
1985
+ fixed_buf = strbuf_detach(&fixed, &fixed_len);
1986
update_pre_post_images(preimage, postimage,
1985
- fixed_buf, imgoff, postlen);
1987
+ fixed_buf, fixed_len, postlen);
1988
return 1;
1989
}
1990
@@ -1999,27 +2001,22 @@ static int match_fragment(struct image *img,
2001
* but in this loop we will only handle the part of the
2002
* preimage that falls within the file.
2003
*/
2002
- fixed_buf = xmalloc(preimage->len + 1);
2003
- buf = fixed_buf;
2004
+ strbuf_init(&fixed, preimage->len + 1);
2005
orig = preimage->buf;
2006
target = img->buf + try;
2007
for (i = 0; i < preimage_limit; i++) {
2007
- size_t fixlen; /* length after fixing the preimage */
2008
size_t oldlen = preimage->line[i].len;
2009
size_t tgtlen = img->line[try_lno + i].len;
2010
- size_t tgtfixlen; /* length after fixing the target line */
2011
- char tgtfixbuf[1024], *tgtfix;
2010
+ size_t fixstart = fixed.len;
2011
+ struct strbuf tgtfix;
2012
int match;
2013
2014
/* Try fixing the line in the preimage */
2015
- fixlen = ws_fix_copy(buf, orig, oldlen, ws_rule, NULL);
2015
+ ws_fix_copy(&fixed, orig, oldlen, ws_rule, NULL);
2016
2017
/* Try fixing the line in the target */
2018
- if (sizeof(tgtfixbuf) > tgtlen)
2019
- tgtfix = tgtfixbuf;
2020
- else
2021
- tgtfix = xmalloc(tgtlen);
2022
- tgtfixlen = ws_fix_copy(tgtfix, target, tgtlen, ws_rule, NULL);
2018
+ strbuf_init(&tgtfix, tgtlen);
2019
+ ws_fix_copy(&tgtfix, target, tgtlen, ws_rule, NULL);
2020
2021
/*
2022
* If they match, either the preimage was based on
@@ -2031,15 +2028,15 @@ static int match_fragment(struct image *img,
2028
* so we might as well take the fix together with their
2029
* real change.
2030
*/
2034
- match = (tgtfixlen == fixlen && !memcmp(tgtfix, buf, fixlen));
2031
+ match = (tgtfix.len == fixed.len - fixstart &&
2032
+ !memcmp(tgtfix.buf, fixed.buf + fixstart,
2033
+ fixed.len - fixstart));
2034
2036
- if (tgtfix != tgtfixbuf)
2037
- free(tgtfix);
2035
+ strbuf_release(&tgtfix);
2036
if (!match)
2037
goto unmatch_exit;
2038
2039
orig += oldlen;
2042
- buf += fixlen;
2040
target += tgtlen;
2041
}
2042
@@ -2051,19 +2048,18 @@ static int match_fragment(struct image *img,
2048
* false).
2049
*/
2050
for ( ; i < preimage->nr; i++) {
2054
- size_t fixlen; /* length after fixing the preimage */
2051
+ size_t fixstart = fixed.len; /* start of the fixed preimage */
2052
size_t oldlen = preimage->line[i].len;
2053
int j;
2054
2055
/* Try fixing the line in the preimage */
2059
- fixlen = ws_fix_copy(buf, orig, oldlen, ws_rule, NULL);
2056
+ ws_fix_copy(&fixed, orig, oldlen, ws_rule, NULL);
2057
2061
- for (j = 0; j < fixlen; j++)
2062
- if (!isspace(buf[j]))
2058
+ for (j = fixstart; j < fixed.len; j++)
2059
+ if (!isspace(fixed.buf[j]))
2060
goto unmatch_exit;
2061
2062
orig += oldlen;
2066
- buf += fixlen;
2063
}
2064
2065
/*
@@ -2071,12 +2067,13 @@ static int match_fragment(struct image *img,
2067
* has whitespace breakages unfixed, and fixing them makes the
2068
* hunk match. Update the context lines in the postimage.
2069
*/
2070
+ fixed_buf = strbuf_detach(&fixed, &fixed_len);
2071
update_pre_post_images(preimage, postimage,
2075
- fixed_buf, buf - fixed_buf, 0);
2072
+ fixed_buf, fixed_len, 0);
2073
return 1;
2074
2075
unmatch_exit:
2079
- free(fixed_buf);
2076
+ strbuf_release(&fixed);
2077
return 0;
2078
}
2079
@@ -2244,7 +2241,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
2241
int match_beginning, match_end;
2242
const char *patch = frag->patch;
2243
int size = frag->size;
2247
- char *old, *new, *oldlines, *newlines;
2244
+ char *old, *oldlines;
2245
+ struct strbuf newlines;
2246
int new_blank_lines_at_end = 0;
2247
unsigned long leading, trailing;
2248
int pos, applied_pos;
@@ -2254,16 +2252,16 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
2252
memset(&preimage, 0, sizeof(preimage));
2253
memset(&postimage, 0, sizeof(postimage));
2254
oldlines = xmalloc(size);
2257
- newlines = xmalloc(size);
2255
+ strbuf_init(&newlines, size);
2256
2257
old = oldlines;
2260
- new = newlines;
2258
while (size > 0) {
2259
char first;
2260
int len = linelen(patch, size);
2264
- int plen, added;
2261
+ int plen;
2262
int added_blank_line = 0;
2263
int is_blank_context = 0;
2264
+ size_t start;
2265
2266
if (!len)
2267
break;
@@ -2293,7 +2291,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
2291
/* ... followed by '\No newline'; nothing */
2292
break;
2293
*old++ = '\n';
2296
- *new++ = '\n';
2294
+ strbuf_addch(&newlines, '\n');
2295
add_line_info(&preimage, "\n", 1, LINE_COMMON);
2296
add_line_info(&postimage, "\n", 1, LINE_COMMON);
2297
is_blank_context = 1;
@@ -2315,18 +2313,17 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
2313
if (first == '+' && no_add)
2314
break;
2315
2316
+ start = newlines.len;
2317
if (first != '+' ||
2318
!whitespace_error ||
2319
ws_error_action != correct_ws_error) {
2321
- memcpy(new, patch + 1, plen);
2322
- added = plen;
2320
+ strbuf_add(&newlines, patch + 1, plen);
2321
}
2322
else {
2325
- added = ws_fix_copy(new, patch + 1, plen, ws_rule, &applied_after_fixing_ws);
2323
+ ws_fix_copy(&newlines, patch + 1, plen, ws_rule, &applied_after_fixing_ws);
2324
}
2327
- add_line_info(&postimage, new, added,
2325
+ add_line_info(&postimage, newlines.buf + start, newlines.len - start,
2326
(first == '+' ? 0 : LINE_COMMON));
2329
- new += added;
2327
if (first == '+' &&
2328
(ws_rule & WS_BLANK_AT_EOF) &&
2329
ws_blank_line(patch + 1, plen, ws_rule))
@@ -2351,9 +2348,9 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
2348
}
2349
if (inaccurate_eof &&
2350
old > oldlines && old[-1] == '\n' &&
2354
- new > newlines && new[-1] == '\n') {
2351
+ newlines.len > 0 && newlines.buf[newlines.len - 1] == '\n') {
2352
old--;
2356
- new--;
2353
+ strbuf_setlen(&newlines, newlines.len - 1);
2354
}
2355
2356
leading = frag->leading;
@@ -2385,8 +2382,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
2382
pos = frag->newpos ? (frag->newpos - 1) : 0;
2383
preimage.buf = oldlines;
2384
preimage.len = old - oldlines;
2388
- postimage.buf = newlines;
2389
- postimage.len = new - newlines;
2385
+ postimage.buf = newlines.buf;
2386
+ postimage.len = newlines.len;
2387
preimage.line = preimage.line_allocated;
2388
postimage.line = postimage.line_allocated;
2389
@@ -2462,7 +2459,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
2459
}
2460
2461
free(oldlines);
2465
- free(newlines);
2462
+ strbuf_release(&newlines);
2463
free(preimage.line_allocated);
2464
free(postimage.line_allocated);
2465
cache.h
+1
-1
@@ -1049,7 +1049,7 @@ extern unsigned parse_whitespace_rule(const char *);
1049
extern unsigned ws_check(const char *line, int len, unsigned ws_rule);
1050
extern void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
1051
extern char *whitespace_error_string(unsigned ws);
1052
-extern int ws_fix_copy(char *, const char *, int, unsigned, int *);
1052
+extern void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
1053
extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
1054
1055
/* ls-files */
ws.c
+8
-11
@@ -271,8 +271,8 @@ int ws_blank_line(const char *line, int len, unsigned ws_rule)
271
return 1;
272
}
273
274
-/* Copy the line to the buffer while fixing whitespaces */
275
-int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *error_count)
274
+/* Copy the line onto the end of the strbuf while fixing whitespaces */
275
+void ws_fix_copy(struct strbuf *dst, const char *src, int len, unsigned ws_rule, int *error_count)
276
{
277
/*
278
* len is number of bytes to be copied from src, starting
@@ -286,7 +286,6 @@ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *erro
286
int last_tab_in_indent = -1;
287
int last_space_in_indent = -1;
288
int need_fix_leading_space = 0;
289
- char *buf;
289
290
/*
291
* Strip trailing whitespace
@@ -326,7 +325,6 @@ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *erro
325
break;
326
}
327
329
- buf = dst;
328
if (need_fix_leading_space) {
329
/* Process indent ourselves */
330
int consecutive_spaces = 0;
@@ -348,28 +346,27 @@ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *erro
346
char ch = src[i];
347
if (ch != ' ') {
348
consecutive_spaces = 0;
351
- *dst++ = ch;
349
+ strbuf_addch(dst, ch);
350
} else {
351
consecutive_spaces++;
352
if (consecutive_spaces == 8) {
355
- *dst++ = '\t';
353
+ strbuf_addch(dst, '\t');
354
consecutive_spaces = 0;
355
}
356
}
357
}
358
while (0 < consecutive_spaces--)
361
- *dst++ = ' ';
359
+ strbuf_addch(dst, ' ');
360
len -= last;
361
src += last;
362
fixed = 1;
363
}
364
367
- memcpy(dst, src, len);
365
+ strbuf_add(dst, src, len);
366
if (add_cr_to_tail)
369
- dst[len++] = '\r';
367
+ strbuf_addch(dst, '\r');
368
if (add_nl_to_tail)
371
- dst[len++] = '\n';
369
+ strbuf_addch(dst, '\n');
370
if (fixed && error_count)
371
(*error_count)++;
374
- return dst + len - buf;
372
}