int xdl_blankline(const char *line, long size, long flags) { long i; if (!(flags & XDF_WHITESPACE_FLAGS)) return (size <= 1); for (i = 0; i < size && XDL_ISSPACE(line[i]); i++) ; return (i == size); }
static int match_string_spaces(const char *line1, int len1, const char *line2, int len2, long flags) { if (flags & XDF_WHITESPACE_FLAGS) { for (; len1 > 0 && XDL_ISSPACE(line1[len1 - 1]); len1--); for (; len2 > 0 && XDL_ISSPACE(line2[len2 - 1]); len2--); } if (!(flags & (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE))) return (len1 == len2 && !memcmp(line1, line2, len1)); while (len1 > 0 && len2 > 0) { len1--; len2--; if (XDL_ISSPACE(line1[len1]) || XDL_ISSPACE(line2[len2])) { if ((flags & XDF_IGNORE_WHITESPACE_CHANGE) && (!XDL_ISSPACE(line1[len1]) || !XDL_ISSPACE(line2[len2]))) return 0; for (; len1 > 0 && XDL_ISSPACE(line1[len1]); len1--); for (; len2 > 0 && XDL_ISSPACE(line2[len2]); len2--); } if (line1[len1] != line2[len2]) return 0; } if (flags & XDF_IGNORE_WHITESPACE) { /* Consume remaining spaces */ for (; len1 > 0 && XDL_ISSPACE(line1[len1 - 1]); len1--); for (; len2 > 0 && XDL_ISSPACE(line2[len2 - 1]); len2--); } /* We matched full line1 and line2 */ if (!len1 && !len2) return 1; return 0; }
static unsigned long xdl_hash_record_with_whitespace(char const **data, char const *top, long flags) { unsigned long ha = 5381; char const *ptr = *data; for (; ptr < top && *ptr != '\n'; ptr++) { if (XDL_ISSPACE(*ptr)) { const char *ptr2 = ptr; int at_eol; while (ptr + 1 < top && XDL_ISSPACE(ptr[1]) && ptr[1] != '\n') ptr++; at_eol = (top <= ptr + 1 || ptr[1] == '\n'); if (flags & XDF_IGNORE_WHITESPACE) ; /* already handled */ else if (flags & XDF_IGNORE_WHITESPACE_CHANGE && !at_eol) { ha += (ha << 5); ha ^= (unsigned long) ' '; } else if (flags & XDF_IGNORE_WHITESPACE_AT_EOL && !at_eol) { while (ptr2 != ptr + 1) { ha += (ha << 5); ha ^= (unsigned long) *ptr2; ptr2++; } } continue; } ha += (ha << 5); ha ^= (unsigned long) *ptr; } *data = ptr < top ? ptr + 1: ptr; return ha; }
/* * Return the amount of indentation of the specified line, treating TAB as 8 * columns. Return -1 if line is empty or contains only whitespace. Clamp the * output value at MAX_INDENT. */ static int get_indent(xrecord_t *rec) { long i; int ret = 0; for (i = 0; i < rec->size; i++) { char c = rec->ptr[i]; if (!XDL_ISSPACE(c)) return ret; else if (c == ' ') ret += 1; else if (c == '\t') ret += 8 - ret % 8; /* ignore other whitespace characters */ if (ret >= MAX_INDENT) return MAX_INDENT; } /* The line contains only whitespace. */ return -1; }
int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags) { int i1, i2; if (s1 == s2 && !memcmp(l1, l2, s1)) return 1; if (!(flags & XDF_WHITESPACE_FLAGS)) return 0; i1 = 0; i2 = 0; /* * -w matches everything that matches with -b, and -b in turn * matches everything that matches with --ignore-space-at-eol. * * Each flavor of ignoring needs different logic to skip whitespaces * while we have both sides to compare. */ if (flags & XDF_IGNORE_WHITESPACE) { goto skip_ws; while (i1 < s1 && i2 < s2) { if (l1[i1++] != l2[i2++]) return 0; skip_ws: while (i1 < s1 && XDL_ISSPACE(l1[i1])) i1++; while (i2 < s2 && XDL_ISSPACE(l2[i2])) i2++; } } else if (flags & XDF_IGNORE_WHITESPACE_CHANGE) { while (i1 < s1 && i2 < s2) { if (XDL_ISSPACE(l1[i1]) && XDL_ISSPACE(l2[i2])) { /* Skip matching spaces and try again */ while (i1 < s1 && XDL_ISSPACE(l1[i1])) i1++; while (i2 < s2 && XDL_ISSPACE(l2[i2])) i2++; continue; } if (l1[i1++] != l2[i2++]) return 0; } } else if (flags & XDF_IGNORE_WHITESPACE_AT_EOL) { while (i1 < s1 && i2 < s2 && l1[i1++] == l2[i2++]) ; /* keep going */ } /* * After running out of one side, the remaining side must have * nothing but whitespace for the lines to match. Note that * ignore-whitespace-at-eol case may break out of the loop * while there still are characters remaining on both lines. */ if (i1 < s1) { while (i1 < s1 && XDL_ISSPACE(l1[i1])) i1++; if (s1 != i1) return 0; } if (i2 < s2) { while (i2 < s2 && XDL_ISSPACE(l2[i2])) i2++; return (s2 == i2); } return 1; }