diff options
Diffstat (limited to 'src/common/util.c')
-rw-r--r-- | src/common/util.c | 629 |
1 files changed, 0 insertions, 629 deletions
diff --git a/src/common/util.c b/src/common/util.c index 358a68fd75..597ff2c420 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -385,22 +385,6 @@ n_bits_set_u8(uint8_t v) * String manipulation * ===== */ -/** Remove from the string <b>s</b> every character which appears in - * <b>strip</b>. */ -void -tor_strstrip(char *s, const char *strip) -{ - char *readp = s; - while (*readp) { - if (strchr(strip, *readp)) { - ++readp; - } else { - *s++ = *readp++; - } - } - *s = '\0'; -} - /** Return a pointer to a NUL-terminated hexadecimal string encoding * the first <b>fromlen</b> bytes of <b>from</b>. (fromlen must be \<= 32.) The * result does not need to be deallocated, but repeated calls to @@ -416,145 +400,6 @@ hex_str(const char *from, size_t fromlen) return buf; } -/** Convert all alphabetic characters in the nul-terminated string <b>s</b> to - * lowercase. */ -void -tor_strlower(char *s) -{ - while (*s) { - *s = TOR_TOLOWER(*s); - ++s; - } -} - -/** Convert all alphabetic characters in the nul-terminated string <b>s</b> to - * lowercase. */ -void -tor_strupper(char *s) -{ - while (*s) { - *s = TOR_TOUPPER(*s); - ++s; - } -} - -/** Return 1 if every character in <b>s</b> is printable, else return 0. - */ -int -tor_strisprint(const char *s) -{ - while (*s) { - if (!TOR_ISPRINT(*s)) - return 0; - s++; - } - return 1; -} - -/** Return 1 if no character in <b>s</b> is uppercase, else return 0. - */ -int -tor_strisnonupper(const char *s) -{ - while (*s) { - if (TOR_ISUPPER(*s)) - return 0; - s++; - } - return 1; -} - -/** Return true iff every character in <b>s</b> is whitespace space; else - * return false. */ -int -tor_strisspace(const char *s) -{ - while (*s) { - if (!TOR_ISSPACE(*s)) - return 0; - s++; - } - return 1; -} - -/** As strcmp, except that either string may be NULL. The NULL string is - * considered to be before any non-NULL string. */ -int -strcmp_opt(const char *s1, const char *s2) -{ - if (!s1) { - if (!s2) - return 0; - else - return -1; - } else if (!s2) { - return 1; - } else { - return strcmp(s1, s2); - } -} - -/** Compares the first strlen(s2) characters of s1 with s2. Returns as for - * strcmp. - */ -int -strcmpstart(const char *s1, const char *s2) -{ - size_t n = strlen(s2); - return strncmp(s1, s2, n); -} - -/** Compare the s1_len-byte string <b>s1</b> with <b>s2</b>, - * without depending on a terminating nul in s1. Sorting order is first by - * length, then lexically; return values are as for strcmp. - */ -int -strcmp_len(const char *s1, const char *s2, size_t s1_len) -{ - size_t s2_len = strlen(s2); - if (s1_len < s2_len) - return -1; - if (s1_len > s2_len) - return 1; - return fast_memcmp(s1, s2, s2_len); -} - -/** Compares the first strlen(s2) characters of s1 with s2. Returns as for - * strcasecmp. - */ -int -strcasecmpstart(const char *s1, const char *s2) -{ - size_t n = strlen(s2); - return strncasecmp(s1, s2, n); -} - -/** Compares the last strlen(s2) characters of s1 with s2. Returns as for - * strcmp. - */ -int -strcmpend(const char *s1, const char *s2) -{ - size_t n1 = strlen(s1), n2 = strlen(s2); - if (n2>n1) - return strcmp(s1,s2); - else - return strncmp(s1+(n1-n2), s2, n2); -} - -/** Compares the last strlen(s2) characters of s1 with s2. Returns as for - * strcasecmp. - */ -int -strcasecmpend(const char *s1, const char *s2) -{ - size_t n1 = strlen(s1), n2 = strlen(s2); - if (n2>n1) /* then they can't be the same; figure out which is bigger */ - return strcasecmp(s1,s2); - else - return strncasecmp(s1+(n1-n2), s2, n2); -} - /** Compare the value of the string <b>prefix</b> with the start of the * <b>memlen</b>-byte memory chunk at <b>mem</b>. Return as for strcmp. * @@ -571,179 +416,6 @@ fast_memcmpstart(const void *mem, size_t memlen, return fast_memcmp(mem, prefix, plen); } -/** Return a pointer to the first char of s that is not whitespace and - * not a comment, or to the terminating NUL if no such character exists. - */ -const char * -eat_whitespace(const char *s) -{ - tor_assert(s); - - while (1) { - switch (*s) { - case '\0': - default: - return s; - case ' ': - case '\t': - case '\n': - case '\r': - ++s; - break; - case '#': - ++s; - while (*s && *s != '\n') - ++s; - } - } -} - -/** Return a pointer to the first char of s that is not whitespace and - * not a comment, or to the terminating NUL if no such character exists. - */ -const char * -eat_whitespace_eos(const char *s, const char *eos) -{ - tor_assert(s); - tor_assert(eos && s <= eos); - - while (s < eos) { - switch (*s) { - case '\0': - default: - return s; - case ' ': - case '\t': - case '\n': - case '\r': - ++s; - break; - case '#': - ++s; - while (s < eos && *s && *s != '\n') - ++s; - } - } - return s; -} - -/** Return a pointer to the first char of s that is not a space or a tab - * or a \\r, or to the terminating NUL if no such character exists. */ -const char * -eat_whitespace_no_nl(const char *s) -{ - while (*s == ' ' || *s == '\t' || *s == '\r') - ++s; - return s; -} - -/** As eat_whitespace_no_nl, but stop at <b>eos</b> whether we have - * found a non-whitespace character or not. */ -const char * -eat_whitespace_eos_no_nl(const char *s, const char *eos) -{ - while (s < eos && (*s == ' ' || *s == '\t' || *s == '\r')) - ++s; - return s; -} - -/** Return a pointer to the first char of s that is whitespace or <b>#</b>, - * or to the terminating NUL if no such character exists. - */ -const char * -find_whitespace(const char *s) -{ - /* tor_assert(s); */ - while (1) { - switch (*s) - { - case '\0': - case '#': - case ' ': - case '\r': - case '\n': - case '\t': - return s; - default: - ++s; - } - } -} - -/** As find_whitespace, but stop at <b>eos</b> whether we have found a - * whitespace or not. */ -const char * -find_whitespace_eos(const char *s, const char *eos) -{ - /* tor_assert(s); */ - while (s < eos) { - switch (*s) - { - case '\0': - case '#': - case ' ': - case '\r': - case '\n': - case '\t': - return s; - default: - ++s; - } - } - return s; -} - -/** Return the first occurrence of <b>needle</b> in <b>haystack</b> that - * occurs at the start of a line (that is, at the beginning of <b>haystack</b> - * or immediately after a newline). Return NULL if no such string is found. - */ -const char * -find_str_at_start_of_line(const char *haystack, const char *needle) -{ - size_t needle_len = strlen(needle); - - do { - if (!strncmp(haystack, needle, needle_len)) - return haystack; - - haystack = strchr(haystack, '\n'); - if (!haystack) - return NULL; - else - ++haystack; - } while (*haystack); - - return NULL; -} - -/** Returns true if <b>string</b> could be a C identifier. - A C identifier must begin with a letter or an underscore and the - rest of its characters can be letters, numbers or underscores. No - length limit is imposed. */ -int -string_is_C_identifier(const char *string) -{ - size_t iter; - size_t length = strlen(string); - if (!length) - return 0; - - for (iter = 0; iter < length ; iter++) { - if (iter == 0) { - if (!(TOR_ISALPHA(string[iter]) || - string[iter] == '_')) - return 0; - } else { - if (!(TOR_ISALPHA(string[iter]) || - TOR_ISDIGIT(string[iter]) || - string[iter] == '_')) - return 0; - } - } - - return 1; -} - /** Return true iff the 'len' bytes at 'mem' are all zero. */ int tor_mem_is_zero(const char *mem, size_t len) @@ -2923,307 +2595,6 @@ expand_filename(const char *filename) #endif /* defined(_WIN32) */ } -#define MAX_SCANF_WIDTH 9999 - -/** Helper: given an ASCII-encoded decimal digit, return its numeric value. - * NOTE: requires that its input be in-bounds. */ -static int -digit_to_num(char d) -{ - int num = ((int)d) - (int)'0'; - tor_assert(num <= 9 && num >= 0); - return num; -} - -/** Helper: Read an unsigned int from *<b>bufp</b> of up to <b>width</b> - * characters. (Handle arbitrary width if <b>width</b> is less than 0.) On - * success, store the result in <b>out</b>, advance bufp to the next - * character, and return 0. On failure, return -1. */ -static int -scan_unsigned(const char **bufp, unsigned long *out, int width, unsigned base) -{ - unsigned long result = 0; - int scanned_so_far = 0; - const int hex = base==16; - tor_assert(base == 10 || base == 16); - if (!bufp || !*bufp || !out) - return -1; - if (width<0) - width=MAX_SCANF_WIDTH; - - while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp)) - && scanned_so_far < width) { - unsigned digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++); - // Check for overflow beforehand, without actually causing any overflow - // This preserves functionality on compilers that don't wrap overflow - // (i.e. that trap or optimise away overflow) - // result * base + digit > ULONG_MAX - // result * base > ULONG_MAX - digit - if (result > (ULONG_MAX - digit)/base) - return -1; /* Processing this digit would overflow */ - result = result * base + digit; - ++scanned_so_far; - } - - if (!scanned_so_far) /* No actual digits scanned */ - return -1; - - *out = result; - return 0; -} - -/** Helper: Read an signed int from *<b>bufp</b> of up to <b>width</b> - * characters. (Handle arbitrary width if <b>width</b> is less than 0.) On - * success, store the result in <b>out</b>, advance bufp to the next - * character, and return 0. On failure, return -1. */ -static int -scan_signed(const char **bufp, long *out, int width) -{ - int neg = 0; - unsigned long result = 0; - - if (!bufp || !*bufp || !out) - return -1; - if (width<0) - width=MAX_SCANF_WIDTH; - - if (**bufp == '-') { - neg = 1; - ++*bufp; - --width; - } - - if (scan_unsigned(bufp, &result, width, 10) < 0) - return -1; - - if (neg && result > 0) { - if (result > ((unsigned long)LONG_MAX) + 1) - return -1; /* Underflow */ - else if (result == ((unsigned long)LONG_MAX) + 1) - *out = LONG_MIN; - else { - /* We once had a far more clever no-overflow conversion here, but - * some versions of GCC apparently ran it into the ground. Now - * we just check for LONG_MIN explicitly. - */ - *out = -(long)result; - } - } else { - if (result > LONG_MAX) - return -1; /* Overflow */ - *out = (long)result; - } - - return 0; -} - -/** Helper: Read a decimal-formatted double from *<b>bufp</b> of up to - * <b>width</b> characters. (Handle arbitrary width if <b>width</b> is less - * than 0.) On success, store the result in <b>out</b>, advance bufp to the - * next character, and return 0. On failure, return -1. */ -static int -scan_double(const char **bufp, double *out, int width) -{ - int neg = 0; - double result = 0; - int scanned_so_far = 0; - - if (!bufp || !*bufp || !out) - return -1; - if (width<0) - width=MAX_SCANF_WIDTH; - - if (**bufp == '-') { - neg = 1; - ++*bufp; - } - - while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) { - const int digit = digit_to_num(*(*bufp)++); - result = result * 10 + digit; - ++scanned_so_far; - } - if (**bufp == '.') { - double fracval = 0, denominator = 1; - ++*bufp; - ++scanned_so_far; - while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) { - const int digit = digit_to_num(*(*bufp)++); - fracval = fracval * 10 + digit; - denominator *= 10; - ++scanned_so_far; - } - result += fracval / denominator; - } - - if (!scanned_so_far) /* No actual digits scanned */ - return -1; - - *out = neg ? -result : result; - return 0; -} - -/** Helper: copy up to <b>width</b> non-space characters from <b>bufp</b> to - * <b>out</b>. Make sure <b>out</b> is nul-terminated. Advance <b>bufp</b> - * to the next non-space character or the EOS. */ -static int -scan_string(const char **bufp, char *out, int width) -{ - int scanned_so_far = 0; - if (!bufp || !out || width < 0) - return -1; - while (**bufp && ! TOR_ISSPACE(**bufp) && scanned_so_far < width) { - *out++ = *(*bufp)++; - ++scanned_so_far; - } - *out = '\0'; - return 0; -} - -/** Locale-independent, minimal, no-surprises scanf variant, accepting only a - * restricted pattern format. For more info on what it supports, see - * tor_sscanf() documentation. */ -int -tor_vsscanf(const char *buf, const char *pattern, va_list ap) -{ - int n_matched = 0; - - while (*pattern) { - if (*pattern != '%') { - if (*buf == *pattern) { - ++buf; - ++pattern; - continue; - } else { - return n_matched; - } - } else { - int width = -1; - int longmod = 0; - ++pattern; - if (TOR_ISDIGIT(*pattern)) { - width = digit_to_num(*pattern++); - while (TOR_ISDIGIT(*pattern)) { - width *= 10; - width += digit_to_num(*pattern++); - if (width > MAX_SCANF_WIDTH) - return -1; - } - if (!width) /* No zero-width things. */ - return -1; - } - if (*pattern == 'l') { - longmod = 1; - ++pattern; - } - if (*pattern == 'u' || *pattern == 'x') { - unsigned long u; - const int base = (*pattern == 'u') ? 10 : 16; - if (!*buf) - return n_matched; - if (scan_unsigned(&buf, &u, width, base)<0) - return n_matched; - if (longmod) { - unsigned long *out = va_arg(ap, unsigned long *); - *out = u; - } else { - unsigned *out = va_arg(ap, unsigned *); - if (u > UINT_MAX) - return n_matched; - *out = (unsigned) u; - } - ++pattern; - ++n_matched; - } else if (*pattern == 'f') { - double *d = va_arg(ap, double *); - if (!longmod) - return -1; /* float not supported */ - if (!*buf) - return n_matched; - if (scan_double(&buf, d, width)<0) - return n_matched; - ++pattern; - ++n_matched; - } else if (*pattern == 'd') { - long lng=0; - if (scan_signed(&buf, &lng, width)<0) - return n_matched; - if (longmod) { - long *out = va_arg(ap, long *); - *out = lng; - } else { - int *out = va_arg(ap, int *); -#if LONG_MAX > INT_MAX - if (lng < INT_MIN || lng > INT_MAX) - return n_matched; -#endif - *out = (int)lng; - } - ++pattern; - ++n_matched; - } else if (*pattern == 's') { - char *s = va_arg(ap, char *); - if (longmod) - return -1; - if (width < 0) - return -1; - if (scan_string(&buf, s, width)<0) - return n_matched; - ++pattern; - ++n_matched; - } else if (*pattern == 'c') { - char *ch = va_arg(ap, char *); - if (longmod) - return -1; - if (width != -1) - return -1; - if (!*buf) - return n_matched; - *ch = *buf++; - ++pattern; - ++n_matched; - } else if (*pattern == '%') { - if (*buf != '%') - return n_matched; - if (longmod) - return -1; - ++buf; - ++pattern; - } else { - return -1; /* Unrecognized pattern component. */ - } - } - } - - return n_matched; -} - -/** Minimal sscanf replacement: parse <b>buf</b> according to <b>pattern</b> - * and store the results in the corresponding argument fields. Differs from - * sscanf in that: - * <ul><li>It only handles %u, %lu, %x, %lx, %[NUM]s, %d, %ld, %lf, and %c. - * <li>It only handles decimal inputs for %lf. (12.3, not 1.23e1) - * <li>It does not handle arbitrarily long widths. - * <li>Numbers do not consume any space characters. - * <li>It is locale-independent. - * <li>%u and %x do not consume any space. - * <li>It returns -1 on malformed patterns.</ul> - * - * (As with other locale-independent functions, we need this to parse data that - * is in ASCII without worrying that the C library's locale-handling will make - * miscellaneous characters look like numbers, spaces, and so on.) - */ -int -tor_sscanf(const char *buf, const char *pattern, ...) -{ - int r; - va_list ap; - va_start(ap, pattern); - r = tor_vsscanf(buf, pattern, ap); - va_end(ap); - return r; -} - /** Append the string produced by tor_asprintf(<b>pattern</b>, <b>...</b>) * to <b>sl</b>. */ void |