123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- /* Copyright (c) 2003-2004, Roger Dingledine
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
- /* See LICENSE for licensing information */
- #include "lib/string/util_string.h"
- #include "lib/string/compat_ctype.h"
- #include "lib/err/torerr.h"
- #include "lib/ctime/di_ops.h"
- #include <string.h>
- #include <stdlib.h>
- /** 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';
- }
- /** 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);
- }
- /** 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)
- {
- raw_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)
- {
- raw_assert(s);
- raw_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;
- }
|