w_string_t *w_string_slice(w_string_t *str, uint32_t start, uint32_t len) { w_string_t *slice; if (start == 0 && len == str->len) { w_string_addref(str); return str; } if (start >= str->len || start + len > str->len) { errno = EINVAL; w_log(W_LOG_FATAL, "illegal string slice start=%" PRIu32 " len=%" PRIu32 " but str->len=%" PRIu32 "\n", start, len, str->len); return NULL; } slice = calloc(1, sizeof(*str)); slice->refcnt = 1; slice->len = len; slice->buf = str->buf + start; slice->slice = str; slice->hval = w_hash_bytes(slice->buf, slice->len, 0); w_string_addref(str); return slice; }
w_string_t *w_string_make_printf(const char *format, ...) { w_string_t *s; int len; char *buf; va_list args; va_start(args, format); // Get the length needed len = vsnprintf(NULL, 0, format, args); va_end(args); s = malloc(sizeof(*s) + len + 1); if (!s) { perror("no memory available"); abort(); } s->refcnt = 1; s->len = len; s->slice = NULL; buf = (char*)(s + 1); va_start(args, format); vsnprintf(buf, len + 1, format, args); va_end(args); s->buf = buf; s->hval = w_hash_bytes(buf, len, 0); return s; }
w_string_t *w_string_new(const char *str) { w_string_t *s; uint32_t len = u32_strlen(str); uint32_t hval; char *buf; hval = w_hash_bytes(str, len, 0); s = malloc(sizeof(*s) + len + 1); if (!s) { perror("no memory available"); abort(); } s->refcnt = 1; s->hval = hval; s->len = len; s->slice = NULL; buf = (char*)(s + 1); memcpy(buf, str, len); buf[len] = 0; s->buf = buf; return s; }
/* make a lowercased copy of string */ w_string_t *w_string_new_lower(const char *str) { w_string_t *s; uint32_t len = strlen(str); char *buf; uint32_t i; s = malloc(sizeof(*s) + len + 1); if (!s) { perror("no memory available"); abort(); } s->refcnt = 1; s->len = len; s->slice = NULL; buf = (char*)(s + 1); for (i = 0; i < len; i++) { buf[i] = tolower(str[i]); } buf[len] = 0; s->buf = buf; s->hval = w_hash_bytes(buf, len, 0); return s; }
w_string_t *w_string_path_cat_cstr(w_string_t *parent, const char *rhs) { w_string_t *s; int len; char *buf; uint32_t rhs_len = u32_strlen(rhs); if (rhs_len == 0) { w_string_addref(parent); return parent; } len = parent->len + rhs_len + 1; s = malloc(sizeof(*s) + len + 1); if (!s) { perror("no memory available"); abort(); } s->refcnt = 1; s->len = len; s->slice = NULL; buf = (char*)(s + 1); memcpy(buf, parent->buf, parent->len); buf[parent->len] = WATCHMAN_DIR_SEP; memcpy(buf + parent->len + 1, rhs, rhs_len); buf[parent->len + 1 + rhs_len] = '\0'; s->buf = buf; s->hval = w_hash_bytes(buf, len, 0); return s; }
w_string_t *w_string_path_cat(w_string_t *parent, w_string_t *rhs) { w_string_t *s; int len; char *buf; if (rhs->len == 0) { w_string_addref(parent); return parent; } len = parent->len + rhs->len + 1; s = malloc(sizeof(*s) + len + 1); if (!s) { perror("no memory available"); abort(); } s->refcnt = 1; s->len = len; s->slice = NULL; buf = (char*)(s + 1); memcpy(buf, parent->buf, parent->len); buf[parent->len] = '/'; memcpy(buf + parent->len + 1, rhs->buf, rhs->len); buf[parent->len + 1 + rhs->len] = '\0'; s->buf = buf; s->hval = w_hash_bytes(buf, len, 0); return s; }
// Normalize directory separators to match the platform. // Also trims any trailing directory separators w_string_t *w_string_normalize_separators(w_string_t *str, char target_sep) { w_string_t *s; char *buf; uint32_t i, len; len = str->len; if (len == 0) { w_string_addref(str); return str; } // This doesn't do any special UNC or path len escape prefix handling // on windows. We don't currently use it in a way that would require it. // Trim any trailing dir seps while (len > 0) { if (str->buf[len-1] == '/' || str->buf[len-1] == '\\') { --len; } else { break; } } s = malloc(sizeof(*s) + len + 1); if (!s) { perror("no memory available"); abort(); } s->refcnt = 1; s->len = len; s->slice = NULL; buf = (char*)(s + 1); for (i = 0; i < len; i++) { if (str->buf[i] == '/' || str->buf[i] == '\\') { buf[i] = target_sep; } else { buf[i] = str->buf[i]; } } buf[len] = 0; s->buf = buf; s->hval = w_hash_bytes(buf, len, 0); return s; }
// Given a string, return a shell-escaped copy w_string_t *w_string_shell_escape(const w_string_t *str) { // Worst case expansion for a char is 4x, plus quoting either end uint32_t len = 2 + (str->len * 4); w_string_t *s; char *buf; const char *src, *end; s = malloc(sizeof(*s) + len + 1); if (!s) { perror("no memory available"); abort(); } s->refcnt = 1; s->slice = NULL; buf = (char*)(s + 1); s->buf = buf; src = str->buf; end = src + str->len; *buf = '\''; buf++; while (src < end) { if (*src == '\'') { memcpy(buf, "'\\''", 4); buf += 4; } else { *buf = *src; buf++; } src++; } *buf = '\''; buf++; *buf = 0; s->len = (uint32_t)(buf - s->buf); s->hval = w_hash_bytes(s->buf, s->len, 0); return s; }
/* return a reference to a lowercased version of a string */ w_string_t *w_string_dup_lower(w_string_t *str) { bool is_lower = true; char *buf; uint32_t i; w_string_t *s; for (i = 0; i < str->len; i++) { if (tolower(str->buf[i]) != str->buf[i]) { is_lower = false; break; } } if (is_lower) { w_string_addref(str); return str; } /* need to make a lowercase version */ s = malloc(sizeof(*s) + str->len + 1); if (!s) { perror("no memory available"); abort(); } s->refcnt = 1; s->len = str->len; s->slice = NULL; buf = (char*)(s + 1); for (i = 0; i < str->len; i++) { buf[i] = tolower(str->buf[i]); } buf[str->len] = 0; s->buf = buf; s->hval = w_hash_bytes(buf, str->len, 0); return s; }
// Given a json array, concat the elements using a delimiter w_string_t *w_string_implode(json_t *arr, const char *delim) { uint32_t delim_len = u32_strlen(delim); uint32_t len = 0; uint32_t i; w_string_t *s; char *buf; if (json_array_size(arr) == 0) { return w_string_new(""); } if (json_array_size(arr) == 1) { return w_string_new(json_string_value(json_array_get(arr, 0))); } len = ((uint32_t)json_array_size(arr) - 1) * delim_len; for (i = 0; i < json_array_size(arr); i++) { const char *str; str = json_string_value(json_array_get(arr, i)); len += u32_strlen(str); } s = malloc(sizeof(*s) + len + 1); if (!s) { perror("no memory available"); abort(); } s->refcnt = 1; s->slice = NULL; buf = (char*)(s + 1); s->buf = buf; for (i = 0; i < json_array_size(arr); i++) { const char *str; uint32_t l; str = json_string_value(json_array_get(arr, i)); l = u32_strlen(str); memcpy(buf, str, l); // Final string doesn't want delimiter after it if (i == json_array_size(arr) - 1) { buf += l; break; } memcpy(buf + l, delim, delim_len); buf += l + delim_len; } *buf = '\0'; s->len = (uint32_t)(buf - s->buf); s->hval = w_hash_bytes(s->buf, s->len, 0); return s; }
uint32_t w_string_piece::hashValue() const { return w_hash_bytes(data(), size(), 0); }
uint32_t w_string_compute_hval(w_string_t *str) { str->_hval = w_hash_bytes(str->buf, str->len, 0); str->hval_computed = 1; return str->_hval; }