su_strlst.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. /*
  2. * This file is part of the Sofia-SIP package
  3. *
  4. * Copyright (C) 2006 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. /**@defgroup su_strlst String Lists
  25. *
  26. * Lists of strings.
  27. *
  28. * String lists using #su_home_t.
  29. *
  30. */
  31. /**@ingroup su_strlst
  32. * @CFILE su_strlst.c
  33. * @brief String lists.
  34. *
  35. * The string lists can be used to concatenate a large number of strings, or
  36. * split a string to smaller pieces (e.g., lines).
  37. *
  38. * Example of concatenating a number of strings to @a s:
  39. * @code
  40. * su_strlst_t *l = su_strlist_create(home);
  41. * su_strlst_append(l, "=============");
  42. * su_slprintf(l, "a is: %d", a)
  43. * su_slprintf(l, "b is: %d", b)
  44. * su_slprintf(l, "c is: %d", c)
  45. * su_strlst_append(l, "------------");
  46. * su_slprintf(l, "total: %d", a + b + c));
  47. * su_strlst_append(l, "=============");
  48. * s = su_strlst_join(l, "\n");
  49. * @endcode
  50. *
  51. * Another example, splitting a string into lines and counting the number of
  52. * non-empty ones:
  53. * @code
  54. * usize_t i, n;
  55. * su_strlst_t *l;
  56. *
  57. * l = su_strlst_split(NULL, buf, "\n");
  58. *
  59. * nonempty = 0;
  60. *
  61. * for (i = 0; i < su_strlst_len(l); i++) {
  62. * n = strcspn(su_strlst_item(l, i), " \t");
  63. * if (su_strlst_item(l, i)[n])
  64. * nonempty++;
  65. * }
  66. *
  67. * su_strlst_destroy(l);
  68. * @endcode
  69. *
  70. * @author Pekka Pessi <Pekka.Pessi@nokia.com>
  71. *
  72. * @date Created: Fri May 3 09:22:59 2002 ppessi
  73. */
  74. #include "config.h"
  75. #include "sofia-sip/su_config.h"
  76. #include "sofia-sip/su_strlst.h"
  77. #include <stdio.h>
  78. #include <stdlib.h>
  79. #include <stddef.h>
  80. #include <memory.h>
  81. #include <limits.h>
  82. #include <string.h>
  83. #include <assert.h>
  84. #if defined(va_copy)
  85. /* Xyzzy */
  86. #elif defined(__va_copy)
  87. #define va_copy(dst, src) __va_copy((dst), (src))
  88. #else
  89. #define va_copy(dst, src) (memcpy(&(dst), &(src), sizeof (va_list)))
  90. #endif
  91. enum { N = 8 };
  92. struct su_strlst_s
  93. {
  94. su_home_t sl_home[1];
  95. size_t sl_size;
  96. size_t sl_len;
  97. size_t sl_total;
  98. char const **sl_list;
  99. };
  100. /** Create a list with initial values */
  101. static
  102. su_strlst_t *su_strlst_vcreate_with_by(su_home_t *home,
  103. char const *value,
  104. va_list va,
  105. int deeply)
  106. {
  107. su_strlst_t *self;
  108. size_t i, n, m;
  109. size_t total, size;
  110. m = 0, total = 0;
  111. /* Count arguments and their length */
  112. if (value) {
  113. char const *s;
  114. va_list va0;
  115. va_copy(va0, va);
  116. for (s = value; s; m++, s = va_arg(va0, char *))
  117. total += strlen(s);
  118. va_end(va0);
  119. }
  120. for (n = N; m > n; n *= 2)
  121. ;
  122. size = sizeof(*self) + n * sizeof(*self->sl_list);
  123. if (deeply)
  124. size += total + m;
  125. self = su_home_clone(home, size);
  126. if (self) {
  127. self->sl_size = n;
  128. self->sl_list = (char const **)(self + 1);
  129. self->sl_len = m;
  130. self->sl_total = total;
  131. if (deeply) {
  132. char *s = (char *)(self->sl_list + self->sl_size);
  133. char *end = s + total + m;
  134. for (i = 0; i < m; i++) {
  135. assert(s);
  136. self->sl_list[i] = s;
  137. s = memccpy(s, value, '\0', end - s);
  138. value = va_arg(va, char const *);
  139. }
  140. }
  141. else {
  142. for (i = 0; i < m; i++) {
  143. self->sl_list[i] = value;
  144. value = va_arg(va, char const *);
  145. }
  146. }
  147. }
  148. return self;
  149. }
  150. /** Create an empty string list.
  151. *
  152. * The list is initially empty. The memory home for the list is cloned from
  153. * @a home.
  154. *
  155. */
  156. su_strlst_t *su_strlst_create(su_home_t *home)
  157. {
  158. su_strlst_t *self;
  159. self = su_home_clone(home, sizeof(*self) + N * sizeof(*self->sl_list));
  160. if (self) {
  161. self->sl_size = N;
  162. self->sl_list = (char const **)(self + 1);
  163. }
  164. return self;
  165. }
  166. /** Create a string list with initial values.
  167. *
  168. * The list is initialized with strings in argument. The argument list is
  169. * terminated with NULL. The memory home for the list is cloned from @a
  170. * home.
  171. */
  172. su_strlst_t *su_strlst_create_with(su_home_t *home, char const *value, ...)
  173. {
  174. va_list va;
  175. su_strlst_t *l;
  176. va_start(va, value);
  177. l = su_strlst_vcreate_with_by(home, value, va, 0);
  178. va_end(va);
  179. return l;
  180. }
  181. /** Create a string list with initial values.
  182. *
  183. * The string list is initialized with strings from @a va_list @a va. The
  184. * argument list is terminated with NULL. The memory home for the list is
  185. * cloned from @a home.
  186. */
  187. su_strlst_t *su_strlst_vcreate_with(su_home_t *home,
  188. char const *value,
  189. va_list va)
  190. {
  191. return su_strlst_vcreate_with_by(home, value, va, 0);
  192. }
  193. /** Create a string list with duplicatedd initial values.
  194. *
  195. * The list is initialized with copies of strings in argument list. The
  196. * argument list is terminated with NULL. The memory home for the list is
  197. * cloned from @a home.
  198. */
  199. su_strlst_t *su_strlst_create_with_dup(su_home_t *home, char const *value, ...)
  200. {
  201. va_list va;
  202. su_strlst_t *l;
  203. va_start(va, value);
  204. l = su_strlst_vcreate_with_by(home, value, va, 1);
  205. va_end(va);
  206. return l;
  207. }
  208. /** Create a string list with duplicates of initial values.
  209. *
  210. * The string list is initialized with copies of strings from @a va_list @a
  211. * va. The argument list is terminated with NULL. The memory home for the
  212. * list is cloned from @a home.
  213. */
  214. su_strlst_t *su_strlst_vcreate_with_dup(su_home_t *home,
  215. char const *value,
  216. va_list va)
  217. {
  218. return su_strlst_vcreate_with_by(home, value, va, 1);
  219. }
  220. /** Copy a string list */
  221. static
  222. su_strlst_t *su_strlst_copy_by(su_home_t *home,
  223. su_strlst_t const *orig,
  224. int deeply)
  225. {
  226. su_strlst_t *self;
  227. size_t N, i, size, deepsize = 0;
  228. if (orig == NULL)
  229. return NULL;
  230. N = orig->sl_size;
  231. if (deeply)
  232. deepsize = orig->sl_len + orig->sl_total;
  233. size = sizeof(*self) + N * sizeof(self->sl_list[0]) + deepsize;
  234. self = su_home_clone(home, size);
  235. if (self) {
  236. self->sl_size = N;
  237. self->sl_list = (char const **)(self + 1);
  238. self->sl_len = N = orig->sl_len;
  239. self->sl_total = orig->sl_total;
  240. if (deeply) {
  241. char *s = (char *)(self->sl_list + self->sl_size);
  242. char *end = s + deepsize;
  243. for (i = 0; i < N; i++) {
  244. self->sl_list[i] = s;
  245. s = memccpy(s, orig->sl_list[i], '\0', end - s);
  246. assert(s);
  247. }
  248. }
  249. else {
  250. for (i = 0; i < N; i++) {
  251. self->sl_list[i] = orig->sl_list[i];
  252. }
  253. }
  254. }
  255. return self;
  256. }
  257. /** Shallow copy a string list. */
  258. su_strlst_t *su_strlst_copy(su_home_t *home, su_strlst_t const *orig)
  259. {
  260. return su_strlst_copy_by(home, orig, 0);
  261. }
  262. /** Deep copy a string list. */
  263. su_strlst_t *su_strlst_dup(su_home_t *home, su_strlst_t const *orig)
  264. {
  265. return su_strlst_copy_by(home, orig, 1);
  266. }
  267. /** Destroy a string list.
  268. *
  269. * The function su_strlst_destroy() destroys a list of strings and frees all
  270. * duplicated strings belonging to it.
  271. */
  272. void su_strlst_destroy(su_strlst_t *self)
  273. {
  274. su_home_zap(self->sl_home);
  275. }
  276. /** Increase the list size for next item, if necessary. */
  277. static int su_strlst_increase(su_strlst_t *self)
  278. {
  279. if (self->sl_size <= self->sl_len + 1) {
  280. size_t size = 2 * self->sl_size * sizeof(self->sl_list[0]);
  281. char const **list;
  282. if (self->sl_list != (char const **)(self + 1)) {
  283. list = su_realloc(self->sl_home, (void *)self->sl_list, size);
  284. } else {
  285. list = su_alloc(self->sl_home, size);
  286. if (list)
  287. memcpy(list, self->sl_list, self->sl_len * sizeof(*self->sl_list));
  288. }
  289. if (!list)
  290. return 0;
  291. self->sl_list = list;
  292. self->sl_size = 2 * self->sl_size;
  293. }
  294. return 1;
  295. }
  296. /**Duplicate and append a string to list.
  297. *
  298. * @param self pointer to a string list object
  299. * @param str string to be duplicated and appended
  300. *
  301. * @return
  302. * Pointer to duplicated string, if successful, or NULL upon an error.
  303. */
  304. char *su_strlst_dup_append(su_strlst_t *self, char const *str)
  305. {
  306. size_t len;
  307. if (str == NULL)
  308. str = "";
  309. len = strlen(str);
  310. if (self && su_strlst_increase(self)) {
  311. char *retval = su_alloc(self->sl_home, len + 1);
  312. if (retval) {
  313. memcpy(retval, str, len);
  314. retval[len] = 0;
  315. self->sl_list[self->sl_len++] = retval;
  316. self->sl_total += len;
  317. }
  318. return retval;
  319. }
  320. return NULL;
  321. }
  322. /**Append a string to list.
  323. *
  324. * The string is not copied, and it @b must not be modified while string
  325. * list exists.
  326. *
  327. * @param self pointer to a string list object
  328. * @param str string to be appended
  329. *
  330. * @return
  331. * Pointer to string, if successful, or NULL upon an error.
  332. */
  333. char const *su_strlst_append(su_strlst_t *self, char const *str)
  334. {
  335. if (str == NULL)
  336. str = "";
  337. if (self && su_strlst_increase(self)) {
  338. self->sl_list[self->sl_len++] = str;
  339. self->sl_total += strlen(str);
  340. return str;
  341. }
  342. return NULL;
  343. }
  344. /**Append a formatted string to the list.
  345. *
  346. * Format a string according to a @a fmt like printf(). The resulting string
  347. * is copied to a memory area freshly allocated from a the memory home of
  348. * the list and appended to the string list.
  349. *
  350. * @param self pointer to a string list object
  351. * @param fmt format string
  352. * @param ... argument list (must match with the @a fmt format string)
  353. *
  354. * @return A pointer to a fresh copy of formatting result, or NULL upon an
  355. * error.
  356. */
  357. char const *su_slprintf(su_strlst_t *self, char const *fmt, ...)
  358. {
  359. char const *str;
  360. va_list ap;
  361. va_start(ap, fmt);
  362. str = su_slvprintf(self, fmt, ap);
  363. va_end(ap);
  364. return str;
  365. }
  366. /**Append a formatted string to the list.
  367. *
  368. * Format a string according to a @a fmt like vprintf(). The resulting
  369. * string is copied to a memory area freshly allocated from a the memory
  370. * home of the list and appended to the string list.
  371. *
  372. * @param self pointer to a string list object
  373. * @param fmt format string
  374. * @param ap stdarg argument list (must match with the @a fmt format string)
  375. *
  376. * @return A pointer to a fresh copy of formatting result, or NULL upon an
  377. * error.
  378. */
  379. char const *su_slvprintf(su_strlst_t *self, char const *fmt, va_list ap)
  380. {
  381. char *str = NULL;
  382. if (self && su_strlst_increase(self)) {
  383. str = su_vsprintf(self->sl_home, fmt, ap);
  384. if (str) {
  385. self->sl_list[self->sl_len++] = str;
  386. self->sl_total += strlen(str);
  387. }
  388. }
  389. return str;
  390. }
  391. /**Returns a numbered item from the list of strings. The numbering starts from
  392. * 0.
  393. *
  394. * @param self pointer to a string list object
  395. * @param i string index
  396. *
  397. * @return
  398. * Pointer to string, if item exists, or NULL if index is out of bounds or
  399. * list does not exist.
  400. */
  401. char const *su_strlst_item(su_strlst_t const *self, usize_t i)
  402. {
  403. if (self && i < self->sl_len)
  404. return self->sl_list[i];
  405. else
  406. return NULL;
  407. }
  408. /**Sets a item to the list of strings.
  409. *
  410. * Note that the item numbering starts from 0.
  411. *
  412. * @param self pointer to a string list object
  413. * @param i string index
  414. * @param s string to be set as item @a i
  415. *
  416. * @return
  417. * Pointer to string, if item exists, or NULL if index is out of bounds or
  418. * list does not exist.
  419. */
  420. char const *su_strlst_set_item(su_strlst_t *self, usize_t i, char const *s)
  421. {
  422. char const *old = NULL;
  423. if (self == NULL)
  424. return NULL;
  425. else if (i == self->sl_len)
  426. return (void)su_strlst_append(self, s), NULL;
  427. else if (i > self->sl_len)
  428. return NULL;
  429. if (s == NULL)
  430. s = "";
  431. old = self->sl_list[i];
  432. self->sl_list[i] = s;
  433. return old;
  434. }
  435. /**Removes a numbered item from the list of strings. The numbering starts from
  436. * 0. The caller is responsible of reclaiming memory used by the removed string.
  437. *
  438. * @param self pointer to a string list object
  439. * @param i string index
  440. *
  441. * @return
  442. * Pointer to string, if item exists, or NULL if index is out of bounds or
  443. * list does not exist.
  444. */
  445. SU_DLL char const *su_strlst_remove(su_strlst_t *self, usize_t i)
  446. {
  447. if (self && i < self->sl_len) {
  448. char const *s = self->sl_list[i];
  449. memmove(&self->sl_list[i], &self->sl_list[i + 1],
  450. &self->sl_list[self->sl_len] - &self->sl_list[i]);
  451. self->sl_len--;
  452. return s;
  453. }
  454. else
  455. return NULL;
  456. }
  457. /** Concatenate list of strings to one string.
  458. *
  459. * The function su_strlst_join() concatenates the list of strings. Between
  460. * each string in list it uses @a sep. The separator is not inserted after
  461. * the last string in list, but one can always append an empty string to the
  462. * list.
  463. *
  464. * The string is allocated from the memory @a home. If @a home is NULL, the
  465. * string is allocated using malloc().
  466. *
  467. * @param self pointer to a string list object
  468. * @param home home pointer
  469. * @param sep separator (may be NULL)
  470. *
  471. * @return
  472. *
  473. * The function su_strlst_join() returns a concatenation of the strings in
  474. * list, or NULL upon an error.
  475. */
  476. char *su_strlst_join(su_strlst_t *self, su_home_t *home, char const *sep)
  477. {
  478. if (!sep)
  479. sep = "";
  480. if (self && self->sl_len > 0) {
  481. size_t seplen = strlen(sep);
  482. size_t total = self->sl_total + seplen * (self->sl_len - 1);
  483. char *retval;
  484. retval = su_alloc(home, total + 1);
  485. if (retval) {
  486. char *s = retval;
  487. size_t i = 0, len;
  488. for (;;) {
  489. len = strlen(self->sl_list[i]);
  490. memcpy(s, self->sl_list[i], len), s += len;
  491. if (++i >= self->sl_len)
  492. break;
  493. memcpy(s, sep, seplen), s += seplen;
  494. }
  495. *s = '\0';
  496. assert(s == retval + total);
  497. }
  498. return retval;
  499. }
  500. return su_strdup(home, "");
  501. }
  502. su_inline
  503. su_strlst_t *
  504. su_strlst_split0(su_strlst_t *l, char *str, char const *sep)
  505. {
  506. size_t n = sep ? strlen(sep) : 0;
  507. char *s;
  508. if (n > 0) {
  509. while ((s = strstr(str, sep))) {
  510. *s = '\0';
  511. if (!su_strlst_append(l, str))
  512. return NULL;
  513. str = s + n;
  514. }
  515. }
  516. if (!su_strlst_append(l, str))
  517. return NULL;
  518. return l;
  519. }
  520. /**Split a string.
  521. *
  522. * Splits a string to substrings. It returns a string list object. The
  523. * string to be split is not copied but instead modified in place. Use
  524. * su_strlst_dup_split() if you do not want to modify @a str.
  525. *
  526. * @param home home pointer
  527. * @param str string to be split
  528. * @param sep separator between substrings
  529. *
  530. * @return
  531. * Pointer to list of strings, if successful, or NULL upon an error.
  532. */
  533. su_strlst_t *
  534. su_strlst_split(su_home_t *home, char *str, char const *sep)
  535. {
  536. if (str) {
  537. su_strlst_t *l = su_strlst_create(home);
  538. if (!su_strlst_split0(l, str, sep))
  539. su_strlst_destroy(l), l = NULL;
  540. return l;
  541. }
  542. return NULL;
  543. }
  544. /**Duplicate and split a string.
  545. *
  546. * Duplicates a string and splits the result to substrings. It returns a
  547. * string list object. The string to be splitted is not modified.
  548. *
  549. * @param home home pointer
  550. * @param cstr string to be split
  551. * @param sep separator between substrings
  552. *
  553. * @return
  554. * Pointer to list of strings, if successful, or NULL upon an error.
  555. */
  556. su_strlst_t *su_strlst_dup_split(su_home_t *home,
  557. char const *cstr,
  558. char const *sep)
  559. {
  560. if (cstr) {
  561. su_strlst_t *l = su_strlst_create(home);
  562. if (l) {
  563. char *s = su_strdup(su_strlst_home(l), cstr);
  564. if (s && !su_strlst_split0(l, s, sep))
  565. su_strlst_destroy(l), l = NULL;
  566. }
  567. return l;
  568. }
  569. return NULL;
  570. }
  571. /** Get number of items in list.
  572. *
  573. * The function su_strlst_len() returns the number of items in the
  574. * string list.
  575. *
  576. */
  577. usize_t su_strlst_len(su_strlst_t const *l)
  578. {
  579. return l ? l->sl_len : 0;
  580. }
  581. /**Get a string array from list.
  582. *
  583. * The function su_strlst_get_array() returns an array of strings. The
  584. * length of the array is always one longer than the length of the string
  585. * list, and the last string in the returned array is always NULL.
  586. *
  587. * @param self pointer to a string list object
  588. *
  589. * @return
  590. * Pointer to array of strings, or NULL if error occurred.
  591. */
  592. char const **su_strlst_get_array(su_strlst_t *self)
  593. {
  594. if (self) {
  595. char const **retval;
  596. size_t size = sizeof(retval[0]) * (self->sl_len + 1);
  597. retval = su_alloc(self->sl_home, size);
  598. if (retval) {
  599. memcpy(retval, self->sl_list, sizeof(retval[0]) * self->sl_len);
  600. retval[self->sl_len] = NULL;
  601. return retval;
  602. }
  603. }
  604. return NULL;
  605. }
  606. /**Free a string array.
  607. *
  608. * The function su_strlst_free_array() discards a string array allocated
  609. * with su_strlst_get_array().
  610. *
  611. * @param self pointer to a string list object
  612. * @param array string array to be freed
  613. *
  614. */
  615. void su_strlst_free_array(su_strlst_t *self, char const **array)
  616. {
  617. if (array)
  618. su_free(self->sl_home, (void *)array);
  619. }