1 /* MIT License
2 *
3 * Copyright (c) 2018 John Schember
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * SPDX-License-Identifier: MIT
25 */
26
27 #if defined(__MVS__)
28 # include <strings.h>
29 #endif
30
31 #include "ares_setup.h"
32 #include "ares.h"
33 #include "ares_private.h"
34
ares__strsplit_free(char ** elms,size_t num_elm)35 void ares__strsplit_free(char **elms, size_t num_elm)
36 {
37 size_t i;
38
39 if (elms == NULL) {
40 return;
41 }
42
43 for (i = 0; i < num_elm; i++) {
44 ares_free(elms[i]);
45 }
46 ares_free(elms);
47 }
48
ares__strsplit_duplicate(char ** elms,size_t num_elm)49 char **ares__strsplit_duplicate(char **elms, size_t num_elm)
50 {
51 size_t i;
52 char **out;
53
54 if (elms == NULL || num_elm == 0) {
55 return NULL;
56 }
57
58 out = ares_malloc_zero(sizeof(*elms) * num_elm);
59 if (out == NULL) {
60 return NULL;
61 }
62
63 for (i = 0; i < num_elm; i++) {
64 out[i] = ares_strdup(elms[i]);
65 if (out[i] == NULL) {
66 ares__strsplit_free(out, num_elm);
67 return NULL;
68 }
69 }
70
71 return out;
72 }
73
ares__strsplit(const char * in,const char * delms,size_t * num_elm)74 char **ares__strsplit(const char *in, const char *delms, size_t *num_elm)
75 {
76 ares_status_t status;
77 ares__buf_t *buf = NULL;
78 ares__llist_t *llist = NULL;
79 ares__llist_node_t *node;
80 char **out = NULL;
81 size_t cnt = 0;
82 size_t idx = 0;
83
84 if (in == NULL || delms == NULL || num_elm == NULL) {
85 return NULL;
86 }
87
88 *num_elm = 0;
89
90 buf = ares__buf_create_const((const unsigned char *)in, ares_strlen(in));
91 if (buf == NULL) {
92 return NULL;
93 }
94
95 status = ares__buf_split(
96 buf, (const unsigned char *)delms, ares_strlen(delms),
97 ARES_BUF_SPLIT_NO_DUPLICATES | ARES_BUF_SPLIT_CASE_INSENSITIVE, &llist);
98 if (status != ARES_SUCCESS) {
99 goto done;
100 }
101
102 cnt = ares__llist_len(llist);
103 if (cnt == 0) {
104 status = ARES_EFORMERR;
105 goto done;
106 }
107
108
109 out = ares_malloc_zero(cnt * sizeof(*out));
110 if (out == NULL) {
111 status = ARES_ENOMEM;
112 goto done;
113 }
114
115 for (node = ares__llist_node_first(llist); node != NULL;
116 node = ares__llist_node_next(node)) {
117 ares__buf_t *val = ares__llist_node_val(node);
118 char *temp = NULL;
119
120 status = ares__buf_fetch_str_dup(val, ares__buf_len(val), &temp);
121 if (status != ARES_SUCCESS) {
122 goto done;
123 }
124
125 out[idx++] = temp;
126 }
127
128 *num_elm = cnt;
129 status = ARES_SUCCESS;
130
131 done:
132 ares__llist_destroy(llist);
133 ares__buf_destroy(buf);
134 if (status != ARES_SUCCESS) {
135 ares__strsplit_free(out, cnt);
136 out = NULL;
137 }
138
139 return out;
140 }
141