util_string.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #include "lib/string/util_string.h"
  6. #include "lib/string/compat_ctype.h"
  7. #include "lib/err/torerr.h"
  8. #include "lib/ctime/di_ops.h"
  9. #include <string.h>
  10. #include <stdlib.h>
  11. /** Remove from the string <b>s</b> every character which appears in
  12. * <b>strip</b>. */
  13. void
  14. tor_strstrip(char *s, const char *strip)
  15. {
  16. char *readp = s;
  17. while (*readp) {
  18. if (strchr(strip, *readp)) {
  19. ++readp;
  20. } else {
  21. *s++ = *readp++;
  22. }
  23. }
  24. *s = '\0';
  25. }
  26. /** Convert all alphabetic characters in the nul-terminated string <b>s</b> to
  27. * lowercase. */
  28. void
  29. tor_strlower(char *s)
  30. {
  31. while (*s) {
  32. *s = TOR_TOLOWER(*s);
  33. ++s;
  34. }
  35. }
  36. /** Convert all alphabetic characters in the nul-terminated string <b>s</b> to
  37. * lowercase. */
  38. void
  39. tor_strupper(char *s)
  40. {
  41. while (*s) {
  42. *s = TOR_TOUPPER(*s);
  43. ++s;
  44. }
  45. }
  46. /** Return 1 if every character in <b>s</b> is printable, else return 0.
  47. */
  48. int
  49. tor_strisprint(const char *s)
  50. {
  51. while (*s) {
  52. if (!TOR_ISPRINT(*s))
  53. return 0;
  54. s++;
  55. }
  56. return 1;
  57. }
  58. /** Return 1 if no character in <b>s</b> is uppercase, else return 0.
  59. */
  60. int
  61. tor_strisnonupper(const char *s)
  62. {
  63. while (*s) {
  64. if (TOR_ISUPPER(*s))
  65. return 0;
  66. s++;
  67. }
  68. return 1;
  69. }
  70. /** Return true iff every character in <b>s</b> is whitespace space; else
  71. * return false. */
  72. int
  73. tor_strisspace(const char *s)
  74. {
  75. while (*s) {
  76. if (!TOR_ISSPACE(*s))
  77. return 0;
  78. s++;
  79. }
  80. return 1;
  81. }
  82. /** As strcmp, except that either string may be NULL. The NULL string is
  83. * considered to be before any non-NULL string. */
  84. int
  85. strcmp_opt(const char *s1, const char *s2)
  86. {
  87. if (!s1) {
  88. if (!s2)
  89. return 0;
  90. else
  91. return -1;
  92. } else if (!s2) {
  93. return 1;
  94. } else {
  95. return strcmp(s1, s2);
  96. }
  97. }
  98. /** Compares the first strlen(s2) characters of s1 with s2. Returns as for
  99. * strcmp.
  100. */
  101. int
  102. strcmpstart(const char *s1, const char *s2)
  103. {
  104. size_t n = strlen(s2);
  105. return strncmp(s1, s2, n);
  106. }
  107. /** Compare the s1_len-byte string <b>s1</b> with <b>s2</b>,
  108. * without depending on a terminating nul in s1. Sorting order is first by
  109. * length, then lexically; return values are as for strcmp.
  110. */
  111. int
  112. strcmp_len(const char *s1, const char *s2, size_t s1_len)
  113. {
  114. size_t s2_len = strlen(s2);
  115. if (s1_len < s2_len)
  116. return -1;
  117. if (s1_len > s2_len)
  118. return 1;
  119. return fast_memcmp(s1, s2, s2_len);
  120. }
  121. /** Compares the first strlen(s2) characters of s1 with s2. Returns as for
  122. * strcasecmp.
  123. */
  124. int
  125. strcasecmpstart(const char *s1, const char *s2)
  126. {
  127. size_t n = strlen(s2);
  128. return strncasecmp(s1, s2, n);
  129. }
  130. /** Compares the last strlen(s2) characters of s1 with s2. Returns as for
  131. * strcmp.
  132. */
  133. int
  134. strcmpend(const char *s1, const char *s2)
  135. {
  136. size_t n1 = strlen(s1), n2 = strlen(s2);
  137. if (n2>n1)
  138. return strcmp(s1,s2);
  139. else
  140. return strncmp(s1+(n1-n2), s2, n2);
  141. }
  142. /** Compares the last strlen(s2) characters of s1 with s2. Returns as for
  143. * strcasecmp.
  144. */
  145. int
  146. strcasecmpend(const char *s1, const char *s2)
  147. {
  148. size_t n1 = strlen(s1), n2 = strlen(s2);
  149. if (n2>n1) /* then they can't be the same; figure out which is bigger */
  150. return strcasecmp(s1,s2);
  151. else
  152. return strncasecmp(s1+(n1-n2), s2, n2);
  153. }
  154. /** Return a pointer to the first char of s that is not whitespace and
  155. * not a comment, or to the terminating NUL if no such character exists.
  156. */
  157. const char *
  158. eat_whitespace(const char *s)
  159. {
  160. raw_assert(s);
  161. while (1) {
  162. switch (*s) {
  163. case '\0':
  164. default:
  165. return s;
  166. case ' ':
  167. case '\t':
  168. case '\n':
  169. case '\r':
  170. ++s;
  171. break;
  172. case '#':
  173. ++s;
  174. while (*s && *s != '\n')
  175. ++s;
  176. }
  177. }
  178. }
  179. /** Return a pointer to the first char of s that is not whitespace and
  180. * not a comment, or to the terminating NUL if no such character exists.
  181. */
  182. const char *
  183. eat_whitespace_eos(const char *s, const char *eos)
  184. {
  185. raw_assert(s);
  186. raw_assert(eos && s <= eos);
  187. while (s < eos) {
  188. switch (*s) {
  189. case '\0':
  190. default:
  191. return s;
  192. case ' ':
  193. case '\t':
  194. case '\n':
  195. case '\r':
  196. ++s;
  197. break;
  198. case '#':
  199. ++s;
  200. while (s < eos && *s && *s != '\n')
  201. ++s;
  202. }
  203. }
  204. return s;
  205. }
  206. /** Return a pointer to the first char of s that is not a space or a tab
  207. * or a \\r, or to the terminating NUL if no such character exists. */
  208. const char *
  209. eat_whitespace_no_nl(const char *s)
  210. {
  211. while (*s == ' ' || *s == '\t' || *s == '\r')
  212. ++s;
  213. return s;
  214. }
  215. /** As eat_whitespace_no_nl, but stop at <b>eos</b> whether we have
  216. * found a non-whitespace character or not. */
  217. const char *
  218. eat_whitespace_eos_no_nl(const char *s, const char *eos)
  219. {
  220. while (s < eos && (*s == ' ' || *s == '\t' || *s == '\r'))
  221. ++s;
  222. return s;
  223. }
  224. /** Return a pointer to the first char of s that is whitespace or <b>#</b>,
  225. * or to the terminating NUL if no such character exists.
  226. */
  227. const char *
  228. find_whitespace(const char *s)
  229. {
  230. /* tor_assert(s); */
  231. while (1) {
  232. switch (*s)
  233. {
  234. case '\0':
  235. case '#':
  236. case ' ':
  237. case '\r':
  238. case '\n':
  239. case '\t':
  240. return s;
  241. default:
  242. ++s;
  243. }
  244. }
  245. }
  246. /** As find_whitespace, but stop at <b>eos</b> whether we have found a
  247. * whitespace or not. */
  248. const char *
  249. find_whitespace_eos(const char *s, const char *eos)
  250. {
  251. /* tor_assert(s); */
  252. while (s < eos) {
  253. switch (*s)
  254. {
  255. case '\0':
  256. case '#':
  257. case ' ':
  258. case '\r':
  259. case '\n':
  260. case '\t':
  261. return s;
  262. default:
  263. ++s;
  264. }
  265. }
  266. return s;
  267. }
  268. /** Return the first occurrence of <b>needle</b> in <b>haystack</b> that
  269. * occurs at the start of a line (that is, at the beginning of <b>haystack</b>
  270. * or immediately after a newline). Return NULL if no such string is found.
  271. */
  272. const char *
  273. find_str_at_start_of_line(const char *haystack, const char *needle)
  274. {
  275. size_t needle_len = strlen(needle);
  276. do {
  277. if (!strncmp(haystack, needle, needle_len))
  278. return haystack;
  279. haystack = strchr(haystack, '\n');
  280. if (!haystack)
  281. return NULL;
  282. else
  283. ++haystack;
  284. } while (*haystack);
  285. return NULL;
  286. }
  287. /** Returns true if <b>string</b> could be a C identifier.
  288. A C identifier must begin with a letter or an underscore and the
  289. rest of its characters can be letters, numbers or underscores. No
  290. length limit is imposed. */
  291. int
  292. string_is_C_identifier(const char *string)
  293. {
  294. size_t iter;
  295. size_t length = strlen(string);
  296. if (!length)
  297. return 0;
  298. for (iter = 0; iter < length ; iter++) {
  299. if (iter == 0) {
  300. if (!(TOR_ISALPHA(string[iter]) ||
  301. string[iter] == '_'))
  302. return 0;
  303. } else {
  304. if (!(TOR_ISALPHA(string[iter]) ||
  305. TOR_ISDIGIT(string[iter]) ||
  306. string[iter] == '_'))
  307. return 0;
  308. }
  309. }
  310. return 1;
  311. }