Skip to content

Commit d511bd3

Browse files
arachsysgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b27eb49 commit d511bd3

File tree

3 files changed

+48
-54
lines changed

3 files changed

+48
-54
lines changed

builtin/apply.c

Lines changed: 39 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1854,6 +1854,8 @@ static int match_fragment(struct image *img,
18541854
{
18551855
int i;
18561856
char *fixed_buf, *buf, *orig, *target;
1857+
struct strbuf fixed;
1858+
size_t fixed_len;
18571859
int preimage_limit;
18581860

18591861
if (preimage->nr + try_lno <= img->nr) {
@@ -1977,12 +1979,12 @@ static int match_fragment(struct image *img,
19771979
* use the whitespace from the preimage.
19781980
*/
19791981
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);
19841986
update_pre_post_images(preimage, postimage,
1985-
fixed_buf, imgoff, postlen);
1987+
fixed_buf, fixed_len, postlen);
19861988
return 1;
19871989
}
19881990

@@ -1999,27 +2001,22 @@ static int match_fragment(struct image *img,
19992001
* but in this loop we will only handle the part of the
20002002
* preimage that falls within the file.
20012003
*/
2002-
fixed_buf = xmalloc(preimage->len + 1);
2003-
buf = fixed_buf;
2004+
strbuf_init(&fixed, preimage->len + 1);
20042005
orig = preimage->buf;
20052006
target = img->buf + try;
20062007
for (i = 0; i < preimage_limit; i++) {
2007-
size_t fixlen; /* length after fixing the preimage */
20082008
size_t oldlen = preimage->line[i].len;
20092009
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;
20122012
int match;
20132013

20142014
/* 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);
20162016

20172017
/* 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);
20232020

20242021
/*
20252022
* If they match, either the preimage was based on
@@ -2031,15 +2028,15 @@ static int match_fragment(struct image *img,
20312028
* so we might as well take the fix together with their
20322029
* real change.
20332030
*/
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));
20352034

2036-
if (tgtfix != tgtfixbuf)
2037-
free(tgtfix);
2035+
strbuf_release(&tgtfix);
20382036
if (!match)
20392037
goto unmatch_exit;
20402038

20412039
orig += oldlen;
2042-
buf += fixlen;
20432040
target += tgtlen;
20442041
}
20452042

@@ -2051,32 +2048,32 @@ static int match_fragment(struct image *img,
20512048
* false).
20522049
*/
20532050
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 */
20552052
size_t oldlen = preimage->line[i].len;
20562053
int j;
20572054

20582055
/* 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);
20602057

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]))
20632060
goto unmatch_exit;
20642061

20652062
orig += oldlen;
2066-
buf += fixlen;
20672063
}
20682064

20692065
/*
20702066
* Yes, the preimage is based on an older version that still
20712067
* has whitespace breakages unfixed, and fixing them makes the
20722068
* hunk match. Update the context lines in the postimage.
20732069
*/
2070+
fixed_buf = strbuf_detach(&fixed, &fixed_len);
20742071
update_pre_post_images(preimage, postimage,
2075-
fixed_buf, buf - fixed_buf, 0);
2072+
fixed_buf, fixed_len, 0);
20762073
return 1;
20772074

20782075
unmatch_exit:
2079-
free(fixed_buf);
2076+
strbuf_release(&fixed);
20802077
return 0;
20812078
}
20822079

@@ -2244,7 +2241,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
22442241
int match_beginning, match_end;
22452242
const char *patch = frag->patch;
22462243
int size = frag->size;
2247-
char *old, *new, *oldlines, *newlines;
2244+
char *old, *oldlines;
2245+
struct strbuf newlines;
22482246
int new_blank_lines_at_end = 0;
22492247
unsigned long leading, trailing;
22502248
int pos, applied_pos;
@@ -2254,16 +2252,16 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
22542252
memset(&preimage, 0, sizeof(preimage));
22552253
memset(&postimage, 0, sizeof(postimage));
22562254
oldlines = xmalloc(size);
2257-
newlines = xmalloc(size);
2255+
strbuf_init(&newlines, size);
22582256

22592257
old = oldlines;
2260-
new = newlines;
22612258
while (size > 0) {
22622259
char first;
22632260
int len = linelen(patch, size);
2264-
int plen, added;
2261+
int plen;
22652262
int added_blank_line = 0;
22662263
int is_blank_context = 0;
2264+
size_t start;
22672265

22682266
if (!len)
22692267
break;
@@ -2293,7 +2291,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
22932291
/* ... followed by '\No newline'; nothing */
22942292
break;
22952293
*old++ = '\n';
2296-
*new++ = '\n';
2294+
strbuf_addch(&newlines, '\n');
22972295
add_line_info(&preimage, "\n", 1, LINE_COMMON);
22982296
add_line_info(&postimage, "\n", 1, LINE_COMMON);
22992297
is_blank_context = 1;
@@ -2315,18 +2313,17 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
23152313
if (first == '+' && no_add)
23162314
break;
23172315

2316+
start = newlines.len;
23182317
if (first != '+' ||
23192318
!whitespace_error ||
23202319
ws_error_action != correct_ws_error) {
2321-
memcpy(new, patch + 1, plen);
2322-
added = plen;
2320+
strbuf_add(&newlines, patch + 1, plen);
23232321
}
23242322
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);
23262324
}
2327-
add_line_info(&postimage, new, added,
2325+
add_line_info(&postimage, newlines.buf + start, newlines.len - start,
23282326
(first == '+' ? 0 : LINE_COMMON));
2329-
new += added;
23302327
if (first == '+' &&
23312328
(ws_rule & WS_BLANK_AT_EOF) &&
23322329
ws_blank_line(patch + 1, plen, ws_rule))
@@ -2351,9 +2348,9 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
23512348
}
23522349
if (inaccurate_eof &&
23532350
old > oldlines && old[-1] == '\n' &&
2354-
new > newlines && new[-1] == '\n') {
2351+
newlines.len > 0 && newlines.buf[newlines.len - 1] == '\n') {
23552352
old--;
2356-
new--;
2353+
strbuf_setlen(&newlines, newlines.len - 1);
23572354
}
23582355

23592356
leading = frag->leading;
@@ -2385,8 +2382,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
23852382
pos = frag->newpos ? (frag->newpos - 1) : 0;
23862383
preimage.buf = oldlines;
23872384
preimage.len = old - oldlines;
2388-
postimage.buf = newlines;
2389-
postimage.len = new - newlines;
2385+
postimage.buf = newlines.buf;
2386+
postimage.len = newlines.len;
23902387
preimage.line = preimage.line_allocated;
23912388
postimage.line = postimage.line_allocated;
23922389

@@ -2462,7 +2459,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
24622459
}
24632460

24642461
free(oldlines);
2465-
free(newlines);
2462+
strbuf_release(&newlines);
24662463
free(preimage.line_allocated);
24672464
free(postimage.line_allocated);
24682465

cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,7 @@ extern unsigned parse_whitespace_rule(const char *);
10491049
extern unsigned ws_check(const char *line, int len, unsigned ws_rule);
10501050
extern void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
10511051
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 *);
10531053
extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
10541054

10551055
/* ls-files */

ws.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,8 @@ int ws_blank_line(const char *line, int len, unsigned ws_rule)
271271
return 1;
272272
}
273273

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)
276276
{
277277
/*
278278
* 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
286286
int last_tab_in_indent = -1;
287287
int last_space_in_indent = -1;
288288
int need_fix_leading_space = 0;
289-
char *buf;
290289

291290
/*
292291
* Strip trailing whitespace
@@ -326,7 +325,6 @@ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *erro
326325
break;
327326
}
328327

329-
buf = dst;
330328
if (need_fix_leading_space) {
331329
/* Process indent ourselves */
332330
int consecutive_spaces = 0;
@@ -348,28 +346,27 @@ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *erro
348346
char ch = src[i];
349347
if (ch != ' ') {
350348
consecutive_spaces = 0;
351-
*dst++ = ch;
349+
strbuf_addch(dst, ch);
352350
} else {
353351
consecutive_spaces++;
354352
if (consecutive_spaces == 8) {
355-
*dst++ = '\t';
353+
strbuf_addch(dst, '\t');
356354
consecutive_spaces = 0;
357355
}
358356
}
359357
}
360358
while (0 < consecutive_spaces--)
361-
*dst++ = ' ';
359+
strbuf_addch(dst, ' ');
362360
len -= last;
363361
src += last;
364362
fixed = 1;
365363
}
366364

367-
memcpy(dst, src, len);
365+
strbuf_add(dst, src, len);
368366
if (add_cr_to_tail)
369-
dst[len++] = '\r';
367+
strbuf_addch(dst, '\r');
370368
if (add_nl_to_tail)
371-
dst[len++] = '\n';
369+
strbuf_addch(dst, '\n');
372370
if (fixed && error_count)
373371
(*error_count)++;
374-
return dst + len - buf;
375372
}

0 commit comments

Comments
 (0)