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>
This commit is contained in:
parent
52f3c81a9d
commit
fe3403c320
111
builtin-apply.c
111
builtin-apply.c
@ -1515,110 +1515,6 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int copy_wsfix(char *output, const char *patch, int plen,
|
|
||||||
unsigned ws_rule, int count_error)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* plen is number of bytes to be copied from patch, starting
|
|
||||||
* at patch. Typically patch[plen-1] is '\n', unless this is
|
|
||||||
* the incomplete last line.
|
|
||||||
*/
|
|
||||||
int i;
|
|
||||||
int add_nl_to_tail = 0;
|
|
||||||
int add_cr_to_tail = 0;
|
|
||||||
int fixed = 0;
|
|
||||||
int last_tab_in_indent = -1;
|
|
||||||
int last_space_in_indent = -1;
|
|
||||||
int need_fix_leading_space = 0;
|
|
||||||
char *buf;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Strip trailing whitespace
|
|
||||||
*/
|
|
||||||
if ((ws_rule & WS_TRAILING_SPACE) &&
|
|
||||||
(2 < plen && isspace(patch[plen-2]))) {
|
|
||||||
if (patch[plen - 1] == '\n') {
|
|
||||||
add_nl_to_tail = 1;
|
|
||||||
plen--;
|
|
||||||
if (1 < plen && patch[plen - 1] == '\r') {
|
|
||||||
add_cr_to_tail = !!(ws_rule & WS_CR_AT_EOL);
|
|
||||||
plen--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (0 < plen && isspace(patch[plen - 1])) {
|
|
||||||
while (0 < plen && isspace(patch[plen-1]))
|
|
||||||
plen--;
|
|
||||||
fixed = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check leading whitespaces (indent)
|
|
||||||
*/
|
|
||||||
for (i = 0; i < plen; i++) {
|
|
||||||
char ch = patch[i];
|
|
||||||
if (ch == '\t') {
|
|
||||||
last_tab_in_indent = i;
|
|
||||||
if ((ws_rule & WS_SPACE_BEFORE_TAB) &&
|
|
||||||
0 <= last_space_in_indent)
|
|
||||||
need_fix_leading_space = 1;
|
|
||||||
} else if (ch == ' ') {
|
|
||||||
last_space_in_indent = i;
|
|
||||||
if ((ws_rule & WS_INDENT_WITH_NON_TAB) &&
|
|
||||||
8 <= i - last_tab_in_indent)
|
|
||||||
need_fix_leading_space = 1;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = output;
|
|
||||||
if (need_fix_leading_space) {
|
|
||||||
/* Process indent ourselves */
|
|
||||||
int consecutive_spaces = 0;
|
|
||||||
int last = last_tab_in_indent + 1;
|
|
||||||
|
|
||||||
if (ws_rule & WS_INDENT_WITH_NON_TAB) {
|
|
||||||
/* have "last" point at one past the indent */
|
|
||||||
if (last_tab_in_indent < last_space_in_indent)
|
|
||||||
last = last_space_in_indent + 1;
|
|
||||||
else
|
|
||||||
last = last_tab_in_indent + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* between patch[0..last-1], strip the funny spaces,
|
|
||||||
* updating them to tab as needed.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < last; i++) {
|
|
||||||
char ch = patch[i];
|
|
||||||
if (ch != ' ') {
|
|
||||||
consecutive_spaces = 0;
|
|
||||||
*output++ = ch;
|
|
||||||
} else {
|
|
||||||
consecutive_spaces++;
|
|
||||||
if (consecutive_spaces == 8) {
|
|
||||||
*output++ = '\t';
|
|
||||||
consecutive_spaces = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (0 < consecutive_spaces--)
|
|
||||||
*output++ = ' ';
|
|
||||||
plen -= last;
|
|
||||||
patch += last;
|
|
||||||
fixed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(output, patch, plen);
|
|
||||||
if (add_cr_to_tail)
|
|
||||||
output[plen++] = '\r';
|
|
||||||
if (add_nl_to_tail)
|
|
||||||
output[plen++] = '\n';
|
|
||||||
if (fixed && count_error)
|
|
||||||
applied_after_fixing_ws++;
|
|
||||||
return output + plen - buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void update_pre_post_images(struct image *preimage,
|
static void update_pre_post_images(struct image *preimage,
|
||||||
struct image *postimage,
|
struct image *postimage,
|
||||||
char *buf,
|
char *buf,
|
||||||
@ -1740,14 +1636,14 @@ static int match_fragment(struct image *img,
|
|||||||
int match;
|
int match;
|
||||||
|
|
||||||
/* Try fixing the line in the preimage */
|
/* Try fixing the line in the preimage */
|
||||||
fixlen = copy_wsfix(buf, orig, oldlen, ws_rule, 0);
|
fixlen = ws_fix_copy(buf, orig, oldlen, ws_rule, NULL);
|
||||||
|
|
||||||
/* Try fixing the line in the target */
|
/* Try fixing the line in the target */
|
||||||
if (sizeof(tgtfixbuf) < tgtlen)
|
if (sizeof(tgtfixbuf) < tgtlen)
|
||||||
tgtfix = tgtfixbuf;
|
tgtfix = tgtfixbuf;
|
||||||
else
|
else
|
||||||
tgtfix = xmalloc(tgtlen);
|
tgtfix = xmalloc(tgtlen);
|
||||||
tgtfixlen = copy_wsfix(tgtfix, target, tgtlen, ws_rule, 0);
|
tgtfixlen = ws_fix_copy(tgtfix, target, tgtlen, ws_rule, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If they match, either the preimage was based on
|
* If they match, either the preimage was based on
|
||||||
@ -2006,8 +1902,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
|
|||||||
added = plen;
|
added = plen;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
added = copy_wsfix(new, patch + 1, plen,
|
added = ws_fix_copy(new, patch + 1, plen, ws_rule, &applied_after_fixing_ws);
|
||||||
ws_rule, 1);
|
|
||||||
}
|
}
|
||||||
add_line_info(&postimage, new, added,
|
add_line_info(&postimage, new, added,
|
||||||
(first == '+' ? 0 : LINE_COMMON));
|
(first == '+' ? 0 : LINE_COMMON));
|
||||||
|
1
cache.h
1
cache.h
@ -661,6 +661,7 @@ extern unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule,
|
|||||||
FILE *stream, const char *set,
|
FILE *stream, const char *set,
|
||||||
const char *reset, const char *ws);
|
const char *reset, const char *ws);
|
||||||
extern char *whitespace_error_string(unsigned ws);
|
extern char *whitespace_error_string(unsigned ws);
|
||||||
|
extern int ws_fix_copy(char *, const char *, int, unsigned, int *);
|
||||||
|
|
||||||
/* ls-files */
|
/* ls-files */
|
||||||
int pathspec_match(const char **spec, char *matched, const char *filename, int skiplen);
|
int pathspec_match(const char **spec, char *matched, const char *filename, int skiplen);
|
||||||
|
104
ws.c
104
ws.c
@ -212,3 +212,107 @@ unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule,
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy the line to the buffer while fixing whitespaces */
|
||||||
|
int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *error_count)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* len is number of bytes to be copied from src, starting
|
||||||
|
* at src. Typically src[len-1] is '\n', unless this is
|
||||||
|
* the incomplete last line.
|
||||||
|
*/
|
||||||
|
int i;
|
||||||
|
int add_nl_to_tail = 0;
|
||||||
|
int add_cr_to_tail = 0;
|
||||||
|
int fixed = 0;
|
||||||
|
int last_tab_in_indent = -1;
|
||||||
|
int last_space_in_indent = -1;
|
||||||
|
int need_fix_leading_space = 0;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Strip trailing whitespace
|
||||||
|
*/
|
||||||
|
if ((ws_rule & WS_TRAILING_SPACE) &&
|
||||||
|
(2 < len && isspace(src[len-2]))) {
|
||||||
|
if (src[len - 1] == '\n') {
|
||||||
|
add_nl_to_tail = 1;
|
||||||
|
len--;
|
||||||
|
if (1 < len && src[len - 1] == '\r') {
|
||||||
|
add_cr_to_tail = !!(ws_rule & WS_CR_AT_EOL);
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 < len && isspace(src[len - 1])) {
|
||||||
|
while (0 < len && isspace(src[len-1]))
|
||||||
|
len--;
|
||||||
|
fixed = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check leading whitespaces (indent)
|
||||||
|
*/
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
char ch = src[i];
|
||||||
|
if (ch == '\t') {
|
||||||
|
last_tab_in_indent = i;
|
||||||
|
if ((ws_rule & WS_SPACE_BEFORE_TAB) &&
|
||||||
|
0 <= last_space_in_indent)
|
||||||
|
need_fix_leading_space = 1;
|
||||||
|
} else if (ch == ' ') {
|
||||||
|
last_space_in_indent = i;
|
||||||
|
if ((ws_rule & WS_INDENT_WITH_NON_TAB) &&
|
||||||
|
8 <= i - last_tab_in_indent)
|
||||||
|
need_fix_leading_space = 1;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = dst;
|
||||||
|
if (need_fix_leading_space) {
|
||||||
|
/* Process indent ourselves */
|
||||||
|
int consecutive_spaces = 0;
|
||||||
|
int last = last_tab_in_indent + 1;
|
||||||
|
|
||||||
|
if (ws_rule & WS_INDENT_WITH_NON_TAB) {
|
||||||
|
/* have "last" point at one past the indent */
|
||||||
|
if (last_tab_in_indent < last_space_in_indent)
|
||||||
|
last = last_space_in_indent + 1;
|
||||||
|
else
|
||||||
|
last = last_tab_in_indent + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* between src[0..last-1], strip the funny spaces,
|
||||||
|
* updating them to tab as needed.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < last; i++) {
|
||||||
|
char ch = src[i];
|
||||||
|
if (ch != ' ') {
|
||||||
|
consecutive_spaces = 0;
|
||||||
|
*dst++ = ch;
|
||||||
|
} else {
|
||||||
|
consecutive_spaces++;
|
||||||
|
if (consecutive_spaces == 8) {
|
||||||
|
*dst++ = '\t';
|
||||||
|
consecutive_spaces = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (0 < consecutive_spaces--)
|
||||||
|
*dst++ = ' ';
|
||||||
|
len -= last;
|
||||||
|
src += last;
|
||||||
|
fixed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(dst, src, len);
|
||||||
|
if (add_cr_to_tail)
|
||||||
|
dst[len++] = '\r';
|
||||||
|
if (add_nl_to_tail)
|
||||||
|
dst[len++] = '\n';
|
||||||
|
if (fixed && error_count)
|
||||||
|
(*error_count)++;
|
||||||
|
return dst + len - buf;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user