Merge branch 'tor-gitlab/mr/568'
[tor.git] / src / lib / smartlist_core / smartlist_split.c
blobe275e870511cec1dbc9d8f835662d2ac83fc4eca
1 /* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 /**
7 * \file smartlist_split.c
8 * \brief Split a string into a smartlist_t of substrings.
9 **/
11 #include "lib/smartlist_core/smartlist_core.h"
12 #include "lib/smartlist_core/smartlist_split.h"
14 #include "lib/err/torerr.h"
15 #include "lib/string/util_string.h"
16 #include "lib/string/compat_ctype.h"
17 #include "lib/malloc/malloc.h"
19 #include <string.h>
21 /**
22 * Split a string <b>str</b> along all occurrences of <b>sep</b>,
23 * appending the (newly allocated) split strings, in order, to
24 * <b>sl</b>. Return the number of strings added to <b>sl</b>.
26 * If <b>flags</b>&amp;SPLIT_SKIP_SPACE is true, remove initial and
27 * trailing space from each entry.
28 * If <b>flags</b>&amp;SPLIT_IGNORE_BLANK is true, remove any entries
29 * of length 0.
30 * If <b>flags</b>&amp;SPLIT_STRIP_SPACE is true, strip spaces from each
31 * split string.
33 * If <b>max</b>\>0, divide the string into no more than <b>max</b> pieces. If
34 * <b>sep</b> is NULL, split on any sequence of horizontal space.
36 int
37 smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
38 int flags, int max)
40 const char *cp, *end, *next;
41 int n = 0;
43 raw_assert(sl);
44 raw_assert(str);
46 cp = str;
47 while (1) {
48 if (flags&SPLIT_SKIP_SPACE) {
49 while (TOR_ISSPACE(*cp)) ++cp;
52 if (max>0 && n == max-1) {
53 end = strchr(cp,'\0');
54 } else if (sep) {
55 end = strstr(cp,sep);
56 if (!end)
57 end = strchr(cp,'\0');
58 } else {
59 for (end = cp; *end && *end != '\t' && *end != ' '; ++end)
63 raw_assert(end);
65 if (!*end) {
66 next = NULL;
67 } else if (sep) {
68 next = end+strlen(sep);
69 } else {
70 next = end+1;
71 while (*next == '\t' || *next == ' ')
72 ++next;
75 if (flags&SPLIT_SKIP_SPACE) {
76 while (end > cp && TOR_ISSPACE(*(end-1)))
77 --end;
79 if (end != cp || !(flags&SPLIT_IGNORE_BLANK)) {
80 char *string = tor_strndup(cp, end-cp);
81 if (flags&SPLIT_STRIP_SPACE)
82 tor_strstrip(string, " ");
83 smartlist_add(sl, string);
84 ++n;
86 if (!next)
87 break;
88 cp = next;
91 return n;