/* * Rips out leading blanks (-b). */ struct bwstring * ignore_leading_blanks(struct bwstring *str) { if (MB_CUR_MAX == 1) { unsigned char *dst, *end, *src; src = str->data.cstr; dst = src; end = src + str->len; while (src < end && isblank(*src)) ++src; if (src != dst) { size_t newlen; newlen = BWSLEN(str) - (src - dst); while (src < end) { *dst = *src; ++dst; ++src; } bws_setlen(str, newlen); } } else { wchar_t *dst, *end, *src; src = str->data.wstr; dst = src; end = src + str->len; while (src < end && iswblank(*src)) ++src; if (src != dst) { size_t newlen = BWSLEN(str) - (src - dst); while (src < end) { *dst = *src; ++dst; ++src; } bws_setlen(str, newlen); } } return (str); }
/* * Implements string sort. */ static int wstrcoll(struct key_value *kv1, struct key_value *kv2, size_t offset) { if (debug_sort) { if (offset) printf("; offset=%d\n", (int) offset); bwsprintf(stdout, kv1->k, "; k1=<", ">"); printf("(%zu)", BWSLEN(kv1->k)); bwsprintf(stdout, kv2->k, ", k2=<", ">"); printf("(%zu)", BWSLEN(kv2->k)); } return (bwscoll(kv1->k, kv2->k, offset)); }
/* * Skip fields according to specs */ static size_t skip_fields_to_start(const struct bwstring *s, size_t fields, bool *empty_field) { if (fields < 2) { if (BWSLEN(s) == 0) *empty_field = true; return (0); } else if (!(sort_opts_vals.tflag)) { size_t cpos = 0; bool pb = true; while (cpos < BWSLEN(s)) { bool isblank; isblank = iswblank(BWS_GET(s, cpos)); if (isblank && !pb) { --fields; if (fields <= 1) return (cpos); } pb = isblank; ++cpos; } if (fields > 1) *empty_field = true; return (cpos); } else { size_t cpos = 0; while (cpos < BWSLEN(s)) { if (BWS_GET(s,cpos) == (wchar_t)sort_opts_vals.field_sep) { --fields; if (fields <= 1) return (cpos + 1); } ++cpos; } if (fields > 1) *empty_field = true; return (cpos); } }
static inline int get_wc_index(struct sort_list_item *sli, size_t level) { const struct bwstring *bws; bws = sli->ka.key[0].k; if ((BWSLEN(bws) > level)) return (unsigned char) BWS_GET(bws,level); return (-1); }
/* * Skip columns according to specs */ static size_t skip_cols_to_start(const struct bwstring *s, size_t cols, size_t start, bool skip_blanks, bool *empty_key) { if (cols < 1) return (BWSLEN(s) + 1); if (skip_blanks) while (start < BWSLEN(s) && iswblank(BWS_GET(s,start))) ++start; while (start < BWSLEN(s) && cols > 1) { --cols; ++start; } if (start >= BWSLEN(s)) *empty_key = true; return (start); }
/* * Find end key position */ static size_t find_field_end(const struct bwstring *s, struct key_specs *ks) { size_t f2, next_field_start, pos_end; bool empty_field, empty_key; pos_end = 0; next_field_start = 0; empty_field = false; empty_key = false; f2 = ks->f2; if (f2 == 0) return (BWSLEN(s) + 1); else { if (ks->c2 == 0) { next_field_start = skip_fields_to_start(s, f2 + 1, &empty_field); if ((next_field_start > 0) && sort_opts_vals.tflag && (sort_opts_vals.field_sep == BWS_GET(s, next_field_start - 1))) --next_field_start; } else next_field_start = skip_fields_to_start(s, f2, &empty_field); } if (empty_field || (next_field_start >= BWSLEN(s))) return (BWSLEN(s) + 1); if (ks->c2) { pos_end = skip_cols_to_start(s, ks->c2, next_field_start, ks->pos2b, &empty_key); if (pos_end < BWSLEN(s)) ++pos_end; } else pos_end = next_field_start; return (pos_end); }
static inline int get_wc_index(struct sort_list_item *sli, size_t level) { const struct key_value *kv; const struct bwstring *bws; kv = get_key_from_keys_array(&sli->ka, 0); bws = kv->k; if ((BWSLEN(bws) > level)) return (unsigned char) BWS_GET(bws,level); return (-1); }
/* * Write binary string to the file. * The output is ended either with '\n' (nl == true) * or '\0' (nl == false). */ size_t bwsfwrite(struct bwstring *bws, FILE *f, bool zero_ended) { if (MB_CUR_MAX == 1) { size_t len = bws->len; if (!zero_ended) { bws->data.cstr[len] = '\n'; if (fwrite(bws->data.cstr, len + 1, 1, f) < 1) err(2, NULL); bws->data.cstr[len] = '\0'; } else if (fwrite(bws->data.cstr, len + 1, 1, f) < 1) err(2, NULL); return (len + 1); } else { wchar_t eols; size_t printed = 0; eols = zero_ended ? btowc('\0') : btowc('\n'); while (printed < BWSLEN(bws)) { const wchar_t *s = bws->data.wstr + printed; if (*s == L'\0') { int nums; nums = fwprintf(f, L"%lc", *s); if (nums != 1) err(2, NULL); ++printed; } else { int nums; nums = fwprintf(f, L"%ls", s); if (nums < 1) err(2, NULL); printed += nums; } } fwprintf(f, L"%lc", eols); return (printed + 1); } }
/* * Compare two version strings */ int vcmp(struct bwstring *s1, struct bwstring *s2) { bwstring_iterator si1, si2; wchar_t c1, c2; size_t len1, len2, slen1, slen2; int cmp_bytes, cmp_res; if (s1 == s2) return (0); cmp_bytes = bwscmp(s1, s2, 0); if (cmp_bytes == 0) return (0); len1 = slen1 = BWSLEN(s1); len2 = slen2 = BWSLEN(s2); if (slen1 < 1) return (-1); if (slen2 < 1) return (+1); si1 = bws_begin(s1); si2 = bws_begin(s2); c1 = bws_get_iter_value(si1); c2 = bws_get_iter_value(si2); if (c1 == L'.' && (slen1 == 1)) return (-1); if (c2 == L'.' && (slen2 == 1)) return (+1); if (slen1 == 2 && c1 == L'.' && bws_get_iter_value(bws_iterator_inc(si1, 1)) == L'.') return (-1); if (slen2 == 2 && c2 == L'.' && bws_get_iter_value(bws_iterator_inc(si2, 1)) == L'.') return (+1); if (c1 == L'.' && c2 != L'.') return (-1); if (c1 != L'.' && c2 == L'.') return (+1); if (c1 == L'.' && c2 == L'.') { si1 = bws_iterator_inc(si1, 1); si2 = bws_iterator_inc(si2, 1); } find_suffix(si1, bws_end(s1), &len1); find_suffix(si2, bws_end(s2), &len2); if ((len1 == len2) && (bws_iterator_cmp(si1, si2, len1) == 0)) return (cmp_bytes); cmp_res = cmpversions(si1, bws_iterator_inc(si1, len1), si2, bws_iterator_inc(si2, len2)); if (cmp_res == 0) cmp_res = cmp_bytes; return (cmp_res); }