su_string.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. /*
  2. * This file is part of the Sofia-SIP package
  3. *
  4. * Copyright (C) 2005 Nokia Corporation.
  5. *
  6. * Contact: Pekka Pessi <pekka.pessi@nokia.com>
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public License
  10. * as published by the Free Software Foundation; either version 2.1 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  21. * 02110-1301 USA
  22. *
  23. */
  24. /**@internal @file su_string.c
  25. * @brief Various string utility functions.
  26. *
  27. * @author Pekka Pessi <Pekka.Pessi@nokia.com>
  28. */
  29. #include "config.h"
  30. #include <sofia-sip/su_string.h>
  31. #include <ctype.h>
  32. #include <string.h>
  33. #include <stddef.h>
  34. #include <limits.h>
  35. /** ASCII-case-insensitive substring search.
  36. *
  37. * Search for substring ASCII-case-insensitively.
  38. *
  39. */
  40. char *
  41. su_strcasestr(const char *haystack,
  42. const char *needle)
  43. {
  44. unsigned char lcn, ucn;
  45. size_t i;
  46. if (haystack == NULL || needle == NULL)
  47. return NULL;
  48. lcn = ucn = needle[0];
  49. if ('A' <= lcn && lcn <= 'Z')
  50. lcn += 'a' - 'A';
  51. else if ('a' <= ucn && ucn <= 'z')
  52. ucn -= 'a' - 'A';
  53. if (lcn == 0)
  54. return (char *)haystack;
  55. while (haystack[0] != 0) {
  56. if (lcn == haystack[0] || ucn == haystack[0]) {
  57. for (i = 1; ; i++) {
  58. char n = needle[i], h = haystack[i];
  59. if (n == 0)
  60. return (char *)haystack;
  61. if (h == 0)
  62. return NULL;
  63. if (n == h)
  64. continue;
  65. if ((n ^ h) != ('A' ^ 'a'))
  66. break;
  67. if ('A' <= n && n <= 'Z')
  68. n += 'a' - 'A';
  69. else if ('A' <= h && h <= 'Z')
  70. h += 'a' - 'A';
  71. if (n != h)
  72. break;
  73. }
  74. }
  75. haystack++;
  76. }
  77. return NULL; /* Not found */
  78. }
  79. /** ASCII-case-insensitive comparison.
  80. *
  81. * Compare two strings colliding upper case and lower case ASCII chars.
  82. * Avoid using locale-dependent strcasecmp(). A NULL pointer compares as an
  83. * empty string.
  84. *
  85. * @retval An int less than zero if @a s1 is less than @a s2
  86. * @retval Zero if @a s1 matches @a s2
  87. * @retval An int greater than zero if @a s1 is greater than @a s2
  88. */
  89. int
  90. su_strcasecmp(char const *s1,
  91. char const *s2)
  92. {
  93. unsigned char const *A = (unsigned char const *)(s1 ? s1 : "");
  94. unsigned char const *B = (unsigned char const *)(s2 ? s2 : "");
  95. for (;;) {
  96. unsigned char a = *A++, b = *B++;
  97. int value = (int)a - (int)b;
  98. if (a == 0)
  99. return value;
  100. if (value == 0)
  101. continue;
  102. if ('A' <= a && a <= 'Z')
  103. a += 'a' - 'A';
  104. if ('A' <= b && b <= 'Z')
  105. b += 'a' - 'A';
  106. value = (int)a - (int)b;
  107. if (value)
  108. return value;
  109. }
  110. }
  111. /** ASCII-case-insensitive comparison.
  112. *
  113. * Compare first @a n bytes of two strings colliding upper case and lower
  114. * case ASCII chars. Avoid using locale-dependent strncasecmp(). A NULL
  115. * pointer compares as an empty string.
  116. *
  117. * @retval An int less than zero if first @a n bytes of @a s1 is less than @a s2
  118. * @retval Zero if first @a n bytes of @a s1 matches @a s2
  119. * @retval An int greater than zero if first @a n bytes of @a s1 is greater than @a s2
  120. */
  121. int
  122. su_strncasecmp(char const *s1,
  123. char const *s2,
  124. size_t n)
  125. {
  126. unsigned char const *A = (unsigned char const *)(s1 ? s1 : "");
  127. unsigned char const *B = (unsigned char const *)(s2 ? s2 : "");
  128. if (n == 0 || A == B || memcmp(A, B, n) == 0)
  129. return 0;
  130. for (;;) {
  131. unsigned char a, b;
  132. int value;
  133. if (n-- == 0)
  134. return 0;
  135. a = *A++, b = *B++;
  136. value = a - b;
  137. if (a == 0)
  138. return value;
  139. if (value == 0)
  140. continue;
  141. if ('A' <= a && a <= 'Z')
  142. a += 'a' - 'A';
  143. if ('A' <= b && b <= 'Z')
  144. b += 'a' - 'A';
  145. value = a - b;
  146. if (value)
  147. return value;
  148. }
  149. }
  150. /** Check if two strings match.
  151. *
  152. * Compare two strings. Accept NULL arguments: two NULL pointers match each
  153. * other, but otherwise NULL pointer does not match anything else, not even
  154. * empty string.
  155. *
  156. * @param s1
  157. *
  158. * @retval One if @a s1 matches @a s2
  159. * @retval Zero if @a s1 does not match @a s2
  160. */
  161. int
  162. su_strmatch(char const *s1, char const *s2)
  163. {
  164. if (s1 == s2)
  165. return 1;
  166. if (s1 == NULL || s2 == NULL)
  167. return 0;
  168. return strcmp(s1, s2) == 0;
  169. }
  170. /** ASCII-case-insensitive string match.
  171. *
  172. * Match two strings colliding upper case and lower case ASCII characters.
  173. * Avoid using locale-dependent strncasecmp(). Accept NULL arguments: two
  174. * NULL pointers match each other, but otherwise NULL pointer does not match
  175. * anything else, not even empty string.
  176. *
  177. * @retval One if first @a n bytes of @a s1 matches @a s2
  178. * @retval Zero if first @a n bytes of @a s1 do not match @a s2
  179. */
  180. int
  181. su_casematch(char const *s1, char const *s2)
  182. {
  183. if (s1 == s2)
  184. return 1;
  185. if (s1 == NULL || s2 == NULL)
  186. return 0;
  187. for (;;) {
  188. unsigned char a = *s1++, b = *s2++;
  189. if (b == 0)
  190. return a == b;
  191. if (a == b)
  192. continue;
  193. if ('A' <= a && a <= 'Z') {
  194. if (a + 'a' - 'A' != b)
  195. return 0;
  196. }
  197. else if ('A' <= b && b <= 'Z') {
  198. if (a != b + 'a' - 'A')
  199. return 0;
  200. }
  201. else
  202. return 0;
  203. }
  204. }
  205. /** String prefix match.
  206. *
  207. * Match first @a n bytes of two strings. If @a n is 0, match always, even
  208. * if arguments are NULL. Otherwise, accept NULL arguments: two NULL
  209. * pointers match each other. NULL pointer does not match
  210. * anything else, not even empty string.
  211. *
  212. * @retval One if first @a n bytes of @a s1 matches @a s2
  213. * @retval Zero if first @a n bytes of @a s1 do not match @a s2
  214. */
  215. int
  216. su_strnmatch(char const *s1,
  217. char const *s2,
  218. size_t n)
  219. {
  220. if (n == 0)
  221. return 1;
  222. if (s1 == s2)
  223. return 1;
  224. if (s1 == NULL || s2 == NULL)
  225. return 0;
  226. return strncmp(s1, s2, n) == 0;
  227. }
  228. /** ASCII-case-insensitive string match.
  229. *
  230. * Compare two strings colliding upper case and lower case ASCII characters.
  231. * Avoid using locale-dependent strncasecmp().
  232. *
  233. * @retval One if first @a n bytes of @a s1 matches @a s2
  234. * @retval Zero if first @a n bytes of @a s1 do not match @a s2
  235. */
  236. int
  237. su_casenmatch(char const *s1,
  238. char const *s2,
  239. size_t n)
  240. {
  241. if (n == 0)
  242. return 1;
  243. if (s1 == s2)
  244. return 1;
  245. if (s1 == NULL || s2 == NULL)
  246. return 0;
  247. if (strncmp(s1, s2, n) == 0)
  248. return 1;
  249. while (n-- > 0) {
  250. unsigned char a = *s1++, b = *s2++;
  251. if (a == 0 || b == 0)
  252. return a == b;
  253. if (a == b)
  254. continue;
  255. if ('A' <= a && a <= 'Z') {
  256. if (a + 'a' - 'A' != b)
  257. return 0;
  258. }
  259. else if ('A' <= b && b <= 'Z') {
  260. if (a != b + 'a' - 'A')
  261. return 0;
  262. }
  263. else
  264. return 0;
  265. }
  266. return 1;
  267. }
  268. /** Search a string for a set of characters.
  269. *
  270. * Calculate the length of the initial segment of first @a n bytes of @a s
  271. * which consists entirely of characters in @a accept.
  272. *
  273. * @param s string to search for characters
  274. * @param n limit of search length
  275. * @param accept set of characters to accept
  276. *
  277. * @return
  278. * Number of characters in the prefix of @a s which consists only of
  279. * characters from @a accept.
  280. */
  281. size_t
  282. su_strnspn(char const *s, size_t n, char const *accept)
  283. {
  284. size_t len;
  285. size_t asize;
  286. if (accept == NULL || s == NULL)
  287. return 0;
  288. asize = strlen(accept);
  289. if (asize == 0) {
  290. return 0;
  291. }
  292. else if (asize == 1) {
  293. char c, a = accept[0];
  294. for (len = 0; len < n && (c = s[len]) && c == a; len++)
  295. ;
  296. }
  297. else if (asize == 2) {
  298. char c, a1 = accept[0], a2 = accept[1];
  299. for (len = 0; len < n && (c = s[len]) && (c == a1 || c == a2); len++)
  300. ;
  301. }
  302. else {
  303. size_t i;
  304. char c, a1 = accept[0], a2 = accept[1];
  305. for (len = 0; len < n && (c = s[len]); len++) {
  306. if (c == a1 || c == a2)
  307. continue;
  308. for (i = 2; i < asize; i++) {
  309. if (c == accept[i])
  310. break;
  311. }
  312. if (i == asize)
  313. break;
  314. }
  315. }
  316. return len;
  317. }
  318. /** Search a string for a set of characters.
  319. *
  320. * Calculate the length of the initial segment of first @a n bytes of @a s
  321. * which does not constists of characters in @a reject.
  322. *
  323. * @param s string to search for characters
  324. * @param n limit of search length
  325. * @param reject set of characters to reject
  326. *
  327. * @return
  328. * Number of characters in the prefix of @a s which are not in @a reject.
  329. */
  330. size_t
  331. su_strncspn(char const *s, size_t n, char const *reject)
  332. {
  333. size_t len;
  334. size_t rsize;
  335. if (s == NULL)
  336. return 0;
  337. if (reject == NULL)
  338. rsize = 0;
  339. else
  340. rsize = strlen(reject);
  341. if (rsize == 0) {
  342. #if HAVE_STRNLEN
  343. len = strnlen(s, n);
  344. #else
  345. for (len = 0; len < n && s[len]; len++)
  346. ;
  347. #endif
  348. }
  349. else if (rsize == 1) {
  350. char c, rej = reject[0];
  351. for (len = 0; len < n && (c = s[len]) && c != rej; len++)
  352. ;
  353. }
  354. else if (rsize == 2) {
  355. char c, rej1 = reject[0], rej2 = reject[1];
  356. for (len = 0; len < n && (c = s[len]) && c != rej1 && c != rej2; len++)
  357. ;
  358. }
  359. else {
  360. size_t i;
  361. char c, rej1 = reject[0], rej2 = reject[1];
  362. for (len = 0; len < n && (c = s[len]) && c != rej1 && c != rej2; len++) {
  363. for (i = 2; i < rsize; i++)
  364. if (c == reject[i])
  365. return len;
  366. }
  367. }
  368. return len;
  369. }
  370. /**Scan memory for a set of bytes.
  371. *
  372. * Calculates the length of the memory area @a mem which consists entirely
  373. o * of bytes in @a accept.
  374. *
  375. * @param mem pointer to memory area
  376. * @param memlen size of @a mem in bytes
  377. * @param accept pointer to table containing bytes to accept
  378. * @param acceptlen size of @a accept table
  379. *
  380. * @return
  381. * The number of consequtive bytes in the memory area @a which consists
  382. * entirely of bytes in @a accept.
  383. */
  384. size_t su_memspn(const void *mem, size_t memlen,
  385. const void *accept, size_t acceptlen)
  386. {
  387. size_t i;
  388. unsigned char const *m = mem, *a = accept;
  389. char accepted[UCHAR_MAX + 1];
  390. if (mem == NULL || memlen == 0 || acceptlen == 0 || accept == NULL)
  391. return 0;
  392. memset(accepted, 0, sizeof accepted);
  393. for (i = 0; i < acceptlen; i++)
  394. accepted[a[i]] = 1;
  395. for (i = 0; i < memlen; i++)
  396. if (!accepted[m[i]])
  397. break;
  398. return i;
  399. }
  400. /**Search memory for bytes not in a given set.
  401. *
  402. * Calculates the length of the memory area @a mem which consists entirely
  403. * of bytes not in @a reject.
  404. *
  405. * @param mem pointer to memory area
  406. * @param memlen size of @a mem in bytes
  407. * @param reject pointer to table containing bytes to reject
  408. * @param rejectlen size of @a reject table
  409. *
  410. * @return
  411. * The number of consequtive bytes in the memory area @a which are not in @a
  412. * reject.
  413. * @par
  414. * If @a rejectlen is 0, or @a reject is NULL, it returns @a memlen, size of
  415. * the memory area.
  416. */
  417. size_t
  418. su_memcspn(const void *mem, size_t memlen,
  419. const void *reject, size_t rejectlen)
  420. {
  421. size_t i;
  422. unsigned char const *m = mem, *r = reject;
  423. char rejected[UCHAR_MAX + 1];
  424. if (mem == NULL || memlen == 0)
  425. return 0;
  426. if (rejectlen == 0 || reject == 0)
  427. return memlen;
  428. memset(rejected, 0, sizeof rejected);
  429. for (i = 0; i < rejectlen; i++)
  430. rejected[r[i]] = 1;
  431. for (i = 0; i < memlen; i++)
  432. if (rejected[m[i]])
  433. break;
  434. return i;
  435. }