smartlist_split.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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/smartlist_core/smartlist_core.h"
  6. #include "lib/smartlist_core/smartlist_split.h"
  7. #include "lib/err/torerr.h"
  8. #include "lib/string/util_string.h"
  9. #include "lib/string/compat_ctype.h"
  10. #include "lib/malloc/util_malloc.h"
  11. #include <string.h>
  12. /**
  13. * Split a string <b>str</b> along all occurrences of <b>sep</b>,
  14. * appending the (newly allocated) split strings, in order, to
  15. * <b>sl</b>. Return the number of strings added to <b>sl</b>.
  16. *
  17. * If <b>flags</b>&amp;SPLIT_SKIP_SPACE is true, remove initial and
  18. * trailing space from each entry.
  19. * If <b>flags</b>&amp;SPLIT_IGNORE_BLANK is true, remove any entries
  20. * of length 0.
  21. * If <b>flags</b>&amp;SPLIT_STRIP_SPACE is true, strip spaces from each
  22. * split string.
  23. *
  24. * If <b>max</b>\>0, divide the string into no more than <b>max</b> pieces. If
  25. * <b>sep</b> is NULL, split on any sequence of horizontal space.
  26. */
  27. int
  28. smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
  29. int flags, int max)
  30. {
  31. const char *cp, *end, *next;
  32. int n = 0;
  33. raw_assert(sl);
  34. raw_assert(str);
  35. cp = str;
  36. while (1) {
  37. if (flags&SPLIT_SKIP_SPACE) {
  38. while (TOR_ISSPACE(*cp)) ++cp;
  39. }
  40. if (max>0 && n == max-1) {
  41. end = strchr(cp,'\0');
  42. } else if (sep) {
  43. end = strstr(cp,sep);
  44. if (!end)
  45. end = strchr(cp,'\0');
  46. } else {
  47. for (end = cp; *end && *end != '\t' && *end != ' '; ++end)
  48. ;
  49. }
  50. raw_assert(end);
  51. if (!*end) {
  52. next = NULL;
  53. } else if (sep) {
  54. next = end+strlen(sep);
  55. } else {
  56. next = end+1;
  57. while (*next == '\t' || *next == ' ')
  58. ++next;
  59. }
  60. if (flags&SPLIT_SKIP_SPACE) {
  61. while (end > cp && TOR_ISSPACE(*(end-1)))
  62. --end;
  63. }
  64. if (end != cp || !(flags&SPLIT_IGNORE_BLANK)) {
  65. char *string = tor_strndup(cp, end-cp);
  66. if (flags&SPLIT_STRIP_SPACE)
  67. tor_strstrip(string, " ");
  68. smartlist_add(sl, string);
  69. ++n;
  70. }
  71. if (!next)
  72. break;
  73. cp = next;
  74. }
  75. return n;
  76. }