ws_fix_copy(): move the whitespace fixing function to ws.c
This is used by git-apply but we can use it elsewhere by slightly generalizing it. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Feb 23, 2008 at 16:59 UTC
fe3403c3205de44faa926a086b4b99f157fc63fe
3 files changed
+108
-108
builtin-apply.c
+3
-108
@@ -1515,110 +1515,6 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
1515
}
1516
}
1517
1518
-static int copy_wsfix(char *output, const char *patch, int plen,
1519
- unsigned ws_rule, int count_error)
1520
-{
1521
- /*
1522
- * plen is number of bytes to be copied from patch, starting
1523
- * at patch. Typically patch[plen-1] is '\n', unless this is
1524
- * the incomplete last line.
1525
- */
1526
- int i;
1527
- int add_nl_to_tail = 0;
1528
- int add_cr_to_tail = 0;
1529
- int fixed = 0;
1530
- int last_tab_in_indent = -1;
1531
- int last_space_in_indent = -1;
1532
- int need_fix_leading_space = 0;
1533
- char *buf;
1534
-
1535
- /*
1536
- * Strip trailing whitespace
1537
- */
1538
- if ((ws_rule & WS_TRAILING_SPACE) &&
1539
- (2 < plen && isspace(patch[plen-2]))) {
1540
- if (patch[plen - 1] == '\n') {
1541
- add_nl_to_tail = 1;
1542
- plen--;
1543
- if (1 < plen && patch[plen - 1] == '\r') {
1544
- add_cr_to_tail = !!(ws_rule & WS_CR_AT_EOL);
1545
- plen--;
1546
- }
1547
- }
1548
- if (0 < plen && isspace(patch[plen - 1])) {
1549
- while (0 < plen && isspace(patch[plen-1]))
1550
- plen--;
1551
- fixed = 1;
1552
- }
1553
- }
1554
-
1555
- /*
1556
- * Check leading whitespaces (indent)
1557
- */
1558
- for (i = 0; i < plen; i++) {
1559
- char ch = patch[i];
1560
- if (ch == '\t') {
1561
- last_tab_in_indent = i;
1562
- if ((ws_rule & WS_SPACE_BEFORE_TAB) &&
1563
- 0 <= last_space_in_indent)
1564
- need_fix_leading_space = 1;
1565
- } else if (ch == ' ') {
1566
- last_space_in_indent = i;
1567
- if ((ws_rule & WS_INDENT_WITH_NON_TAB) &&
1568
- 8 <= i - last_tab_in_indent)
1569
- need_fix_leading_space = 1;
1570
- } else
1571
- break;
1572
- }
1573
-
1574
- buf = output;
1575
- if (need_fix_leading_space) {
1576
- /* Process indent ourselves */
1577
- int consecutive_spaces = 0;
1578
- int last = last_tab_in_indent + 1;
1579
-
1580
- if (ws_rule & WS_INDENT_WITH_NON_TAB) {
1581
- /* have "last" point at one past the indent */
1582
- if (last_tab_in_indent < last_space_in_indent)
1583
- last = last_space_in_indent + 1;
1584
- else
1585
- last = last_tab_in_indent + 1;
1586
- }
1587
-
1588
- /*
1589
- * between patch[0..last-1], strip the funny spaces,
1590
- * updating them to tab as needed.
1591
- */
1592
- for (i = 0; i < last; i++) {
1593
- char ch = patch[i];
1594
- if (ch != ' ') {
1595
- consecutive_spaces = 0;
1596
- *output++ = ch;
1597
- } else {
1598
- consecutive_spaces++;
1599
- if (consecutive_spaces == 8) {
1600
- *output++ = '\t';
1601
- consecutive_spaces = 0;
1602
- }
1603
- }
1604
- }
1605
- while (0 < consecutive_spaces--)
1606
- *output++ = ' ';
1607
- plen -= last;
1608
- patch += last;
1609
- fixed = 1;
1610
- }
1611
-
1612
- memcpy(output, patch, plen);
1613
- if (add_cr_to_tail)
1614
- output[plen++] = '\r';
1615
- if (add_nl_to_tail)
1616
- output[plen++] = '\n';
1617
- if (fixed && count_error)
1618
- applied_after_fixing_ws++;
1619
- return output + plen - buf;
1620
-}
1621
-
1518
static void update_pre_post_images(struct image *preimage,
1519
struct image *postimage,
1520
char *buf,
@@ -1740,14 +1636,14 @@ static int match_fragment(struct image *img,
1636
int match;
1637
1638
/* Try fixing the line in the preimage */
1743
- fixlen = copy_wsfix(buf, orig, oldlen, ws_rule, 0);
1639
+ fixlen = ws_fix_copy(buf, orig, oldlen, ws_rule, NULL);
1640
1641
/* Try fixing the line in the target */
1642
if (sizeof(tgtfixbuf) < tgtlen)
1643
tgtfix = tgtfixbuf;
1644
else
1645
tgtfix = xmalloc(tgtlen);
1750
- tgtfixlen = copy_wsfix(tgtfix, target, tgtlen, ws_rule, 0);
1646
+ tgtfixlen = ws_fix_copy(tgtfix, target, tgtlen, ws_rule, NULL);
1647
1648
/*
1649
* If they match, either the preimage was based on
@@ -2006,8 +1902,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
1902
added = plen;
1903
}
1904
else {
2009
- added = copy_wsfix(new, patch + 1, plen,
2010
- ws_rule, 1);
1905
+ added = ws_fix_copy(new, patch + 1, plen, ws_rule, &applied_after_fixing_ws);
1906
}
1907
add_line_info(&postimage, new, added,
1908
(first == '+' ? 0 : LINE_COMMON));
cache.h
+1
@@ -661,6 +661,7 @@ extern unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule,
661
FILE *stream, const char *set,
662
const char *reset, const char *ws);
663
extern char *whitespace_error_string(unsigned ws);
664
+extern int ws_fix_copy(char *, const char *, int, unsigned, int *);
665
666
/* ls-files */
667
int pathspec_match(const char **spec, char *matched, const char *filename, int skiplen);
ws.c
+104
@@ -212,3 +212,107 @@ unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule,
212
}
213
return result;
214
}
215
+
216
+/* Copy the line to the buffer while fixing whitespaces */
217
+int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *error_count)
218
+{
219
+ /*
220
+ * len is number of bytes to be copied from src, starting
221
+ * at src. Typically src[len-1] is '\n', unless this is
222
+ * the incomplete last line.
223
+ */
224
+ int i;
225
+ int add_nl_to_tail = 0;
226
+ int add_cr_to_tail = 0;
227
+ int fixed = 0;
228
+ int last_tab_in_indent = -1;
229
+ int last_space_in_indent = -1;
230
+ int need_fix_leading_space = 0;
231
+ char *buf;
232
+
233
+ /*
234
+ * Strip trailing whitespace
235
+ */
236
+ if ((ws_rule & WS_TRAILING_SPACE) &&
237
+ (2 < len && isspace(src[len-2]))) {
238
+ if (src[len - 1] == '\n') {
239
+ add_nl_to_tail = 1;
240
+ len--;
241
+ if (1 < len && src[len - 1] == '\r') {
242
+ add_cr_to_tail = !!(ws_rule & WS_CR_AT_EOL);
243
+ len--;
244
+ }
245
+ }
246
+ if (0 < len && isspace(src[len - 1])) {
247
+ while (0 < len && isspace(src[len-1]))
248
+ len--;
249
+ fixed = 1;
250
+ }
251
+ }
252
+
253
+ /*
254
+ * Check leading whitespaces (indent)
255
+ */
256
+ for (i = 0; i < len; i++) {
257
+ char ch = src[i];
258
+ if (ch == '\t') {
259
+ last_tab_in_indent = i;
260
+ if ((ws_rule & WS_SPACE_BEFORE_TAB) &&
261
+ 0 <= last_space_in_indent)
262
+ need_fix_leading_space = 1;
263
+ } else if (ch == ' ') {
264
+ last_space_in_indent = i;
265
+ if ((ws_rule & WS_INDENT_WITH_NON_TAB) &&
266
+ 8 <= i - last_tab_in_indent)
267
+ need_fix_leading_space = 1;
268
+ } else
269
+ break;
270
+ }
271
+
272
+ buf = dst;
273
+ if (need_fix_leading_space) {
274
+ /* Process indent ourselves */
275
+ int consecutive_spaces = 0;
276
+ int last = last_tab_in_indent + 1;
277
+
278
+ if (ws_rule & WS_INDENT_WITH_NON_TAB) {
279
+ /* have "last" point at one past the indent */
280
+ if (last_tab_in_indent < last_space_in_indent)
281
+ last = last_space_in_indent + 1;
282
+ else
283
+ last = last_tab_in_indent + 1;
284
+ }
285
+
286
+ /*
287
+ * between src[0..last-1], strip the funny spaces,
288
+ * updating them to tab as needed.
289
+ */
290
+ for (i = 0; i < last; i++) {
291
+ char ch = src[i];
292
+ if (ch != ' ') {
293
+ consecutive_spaces = 0;
294
+ *dst++ = ch;
295
+ } else {
296
+ consecutive_spaces++;
297
+ if (consecutive_spaces == 8) {
298
+ *dst++ = '\t';
299
+ consecutive_spaces = 0;
300
+ }
301
+ }
302
+ }
303
+ while (0 < consecutive_spaces--)
304
+ *dst++ = ' ';
305
+ len -= last;
306
+ src += last;
307
+ fixed = 1;
308
+ }
309
+
310
+ memcpy(dst, src, len);
311
+ if (add_cr_to_tail)
312
+ dst[len++] = '\r';
313
+ if (add_nl_to_tail)
314
+ dst[len++] = '\n';
315
+ if (fixed && error_count)
316
+ (*error_count)++;
317
+ return dst + len - buf;
318
+}