1 /*
2 Copyright 2020 Northern.tech AS
3
4 This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; version 3.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18
19 To the extent this program is licensed as part of the Enterprise
20 versions of CFEngine, the applicable Commercial Open Source License
21 (COSL) may apply to this file if you as a licensee so wish it. See
22 included file COSL.txt.
23 */
24
25 #include <platform.h>
26 #include <set.h>
27 #include <string.h> // strlen()
28
29 #include <alloc.h>
30 #include <string_lib.h>
31 #include <buffer.h>
32
TYPED_SET_DEFINE(String,char *,StringHash_untyped,StringEqual_untyped,free)33 TYPED_SET_DEFINE(String, char *,
34 StringHash_untyped, StringEqual_untyped, free)
35
36 Set *SetNew(MapHashFn element_hash_fn,
37 MapKeyEqualFn element_equal_fn,
38 MapDestroyDataFn element_destroy_fn)
39 {
40 return MapNew(element_hash_fn, element_equal_fn, element_destroy_fn, NULL);
41 }
42
SetDestroy(Set * set)43 void SetDestroy(Set *set)
44 {
45 MapDestroy(set);
46 }
47
SetAdd(Set * set,void * element)48 void SetAdd(Set *set, void *element)
49 {
50 assert(set != NULL);
51 MapInsert(set, element, element);
52 }
53
SetContains(const Set * set,const void * element)54 bool SetContains(const Set *set, const void *element)
55 {
56 assert(set != NULL);
57 return MapHasKey(set, element);
58 }
59
SetRemove(Set * set,const void * element)60 bool SetRemove(Set *set, const void *element)
61 {
62 assert(set != NULL);
63 return MapRemove(set, element);
64 }
65
SetClear(Set * set)66 void SetClear(Set *set)
67 {
68 assert(set != NULL);
69 MapClear(set);
70 }
71
SetSize(const Set * set)72 size_t SetSize(const Set *set)
73 {
74 assert(set != NULL);
75 return MapSize(set);
76 }
77
SetIsEqual(const Set * set1,const Set * set2)78 bool SetIsEqual(const Set *set1, const Set *set2)
79 {
80 assert(set1 != NULL);
81 assert(set2 != NULL);
82 return MapContainsSameKeys(set1, set2);
83 }
84
SetIteratorInit(Set * set)85 SetIterator SetIteratorInit(Set *set)
86 {
87 assert(set != NULL);
88 return MapIteratorInit(set);
89 }
90
SetIteratorNext(SetIterator * i)91 void *SetIteratorNext(SetIterator *i)
92 {
93 MapKeyValue *kv = MapIteratorNext(i);
94 return kv ? kv->key : NULL;
95 }
96
SetJoin(Set * set,Set * otherset,SetElementCopyFn copy_function)97 void SetJoin(Set *set, Set *otherset, SetElementCopyFn copy_function)
98 {
99 assert(set != NULL);
100 assert(otherset != NULL);
101 if (set == otherset)
102 return;
103
104 SetIterator si = SetIteratorInit(otherset);
105 void *ptr = NULL;
106
107 for (ptr = SetIteratorNext(&si); ptr != NULL; ptr = SetIteratorNext(&si))
108 {
109 if (copy_function != NULL)
110 {
111 ptr = copy_function(ptr);
112 }
113 SetAdd(set, ptr);
114 }
115 }
116
StringSetToBuffer(StringSet * set,const char delimiter)117 Buffer *StringSetToBuffer(StringSet *set, const char delimiter)
118 {
119 assert(set != NULL);
120
121 Buffer *buf = BufferNew();
122 StringSetIterator it = StringSetIteratorInit(set);
123 const char *element = NULL;
124 int pos = 0;
125 int size = StringSetSize(set);
126 char minibuf[2];
127
128 minibuf[0] = delimiter;
129 minibuf[1] = '\0';
130
131 while ((element = StringSetIteratorNext(&it)))
132 {
133 BufferAppend(buf, element, strlen(element));
134 if (pos < size-1)
135 {
136 BufferAppend(buf, minibuf, sizeof(char));
137 }
138
139 pos++;
140 }
141
142 return buf;
143 }
144
StringSetAddSplit(StringSet * set,const char * str,char delimiter)145 void StringSetAddSplit(StringSet *set, const char *str, char delimiter)
146 {
147 assert(set != NULL);
148 if (str) // TODO: remove this inconsistency, add assert(str)
149 {
150 const char *prev = str;
151 const char *cur = str;
152
153 while (*cur != '\0')
154 {
155 if (*cur == delimiter)
156 {
157 size_t len = cur - prev;
158 if (len > 0)
159 {
160 StringSetAdd(set, xstrndup(prev, len));
161 }
162 else
163 {
164 StringSetAdd(set, xstrdup(""));
165 }
166 prev = cur + 1;
167 }
168
169 cur++;
170 }
171
172 if (cur > prev)
173 {
174 StringSetAdd(set, xstrndup(prev, cur - prev));
175 }
176 }
177 }
178
StringSetFromString(const char * str,char delimiter)179 StringSet *StringSetFromString(const char *str, char delimiter)
180 {
181 StringSet *set = StringSetNew();
182
183 StringSetAddSplit(set, str, delimiter);
184
185 return set;
186 }
187
StringSetToJson(const StringSet * set)188 JsonElement *StringSetToJson(const StringSet *set)
189 {
190 assert(set != NULL);
191
192 JsonElement *arr = JsonArrayCreate(StringSetSize(set));
193 StringSetIterator it = StringSetIteratorInit((StringSet *)set);
194 const char *el = NULL;
195
196 while ((el = StringSetIteratorNext(&it)))
197 {
198 JsonArrayAppendString(arr, el);
199 }
200
201 return arr;
202 }
203