smartlist_split.c 2.3 KB

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