1 /*
2 *
3 * Copyright (C) 2012-2018 by C.H. Huang
4 * plushuang.tw@gmail.com
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 * ---
21 *
22 * In addition, as a special exception, the copyright holders give
23 * permission to link the code of portions of this program with the
24 * OpenSSL library under certain conditions as described in each
25 * individual source file, and distribute linked combinations
26 * including the two.
27 * You must obey the GNU Lesser General Public License in all respects
28 * for all of the code used other than OpenSSL. If you modify
29 * file(s) with this exception, you may extend this exception to your
30 * version of the file(s), but you are not obligated to do so. If you
31 * do not wish to do so, delete this exception statement from your
32 * version. If you delete this exception statement from all source
33 * files in the program, then also delete it here.
34 *
35 */
36
37 #include <stddef.h> // NULL
38 #include <string.h>
39 #include <UgString.h>
40 #include <UgArray.h>
41 #include <UgEntry.h>
42
43 #if defined(_MSC_VER)
44 #define strtoll _strtoi64
45 #endif
46
47 // ----------------------------------------------------------------------------
48 // UgArray: for UG_ENTRY_ARRAY
49
ug_array_init(void * arr,int element_size,int allocated_len)50 void ug_array_init(void* arr, int element_size, int allocated_len)
51 {
52 UgArrayChar* array = arr;
53
54 if (allocated_len)
55 array->at = ug_malloc(element_size * allocated_len);
56 else
57 array->at = NULL;
58 array->length = 0;
59 array->allocated = allocated_len;
60 array->element_size = element_size;
61 }
62
ug_array_clear(void * arr)63 void ug_array_clear(void* arr)
64 {
65 UgArrayChar* array = arr;
66
67 ug_free(array->at);
68 array->at = NULL;
69 array->length = 0;
70 array->allocated = 0;
71 }
72
ug_array_alloc(void * arr,int nElements)73 void* ug_array_alloc(void* arr, int nElements)
74 {
75 UgArrayChar* array = arr;
76 int len;
77
78 len = array->length + nElements;
79 if (array->allocated < len) {
80 array->allocated = len * 2;
81 // if (array->allocated < 16)
82 // array->allocated = 16;
83 array->at = ug_realloc(array->at, array->allocated * array->element_size);
84 }
85 arr = array->at + array->length * array->element_size;
86 array->length += nElements;
87 return arr;
88 }
89
ug_array_foreach(void * array,UgForeachFunc func,void * data)90 void ug_array_foreach(void* array, UgForeachFunc func, void* data)
91 {
92 char* cur;
93 char* end;
94
95 cur = ((UgArrayChar*)array)->at;
96 end = cur + ((UgArrayChar*)array)->element_size * ((UgArrayChar*)array)->length;
97
98 for (; cur < end; cur+= ((UgArrayChar*)array)->element_size)
99 func(cur, data);
100 }
101
ug_array_foreach_ptr(void * array,UgForeachFunc func,void * data)102 void ug_array_foreach_ptr(void* array, UgForeachFunc func, void* data)
103 {
104 char* cur = ((UgArrayChar*)array)->at;
105 char* end = cur + ((UgArrayChar*)array)->element_size * ((UgArrayChar*)array)->length;
106
107 for (; cur < end; cur+= ((UgArrayChar*)array)->element_size)
108 func(*(void**)cur, data);
109 }
110
ug_array_find_sorted(void * array,const void * key,UgCompareFunc compare,int * inserted_index)111 void* ug_array_find_sorted(void* array, const void* key,
112 UgCompareFunc compare, int* inserted_index)
113 {
114 int low;
115 int cur;
116 int high;
117 int diff;
118 void* cur_key;
119
120 low = 0;
121 cur = 0;
122 high = ((UgArrayChar*)array)->length;
123 while (low < high) {
124 // cur = low + ((high - low) / 2);
125 cur = low + ((high - low) >> 1);
126 cur_key = ((UgArrayChar*)array)->at + cur *
127 ((UgArrayChar*)array)->element_size;
128
129 diff = compare(cur_key, key);
130 if (diff == 0) {
131 if (inserted_index)
132 inserted_index[0] = cur;
133 return ((UgArrayChar*)array)->at + cur *
134 ((UgArrayChar*)array)->element_size;
135 }
136 else if (diff > 0)
137 high = cur;
138 else if (diff < 0)
139 low = cur + 1;
140 }
141
142 if (inserted_index) {
143 if (cur < low)
144 cur++;
145 inserted_index[0] = cur;
146 }
147 return NULL;
148 }
149
150 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
151 // C99 or C++ inline functions in UgArray.h
152 #else
ug_array_insert(void * array,int index,int length)153 void* ug_array_insert(void* array, int index, int length)
154 {
155 char* addr;
156 ug_array_alloc(array, length);
157 memmove(ug_array_addr(array, index + length),
158 addr = ug_array_addr(array, index),
159 ug_array_count(array, ug_array_length(array) - index - 1));
160 return (void*)addr;
161 }
162
ug_array_erase(void * array,int index,int length)163 void ug_array_erase(void* array, int index, int length)
164 {
165 memmove(ug_array_addr(array, index),
166 ug_array_addr(array, index + length),
167 ug_array_count(array, ug_array_length(array) - index - 1));
168 ((UgArrayChar*)array)->length -= length;
169 }
170
ug_array_sort(void * array,UgCompareFunc compare)171 void ug_array_sort(void* array, UgCompareFunc compare)
172 {
173 qsort( ((UgArrayChar*)array)->at, ((UgArrayChar*)array)->length,
174 ((UgArrayChar*)array)->element_size, compare);
175 }
176 #endif // __STDC_VERSION__
177
ug_array_compare_int(const void * s1,const void * s2)178 int ug_array_compare_int(const void *s1, const void *s2)
179 {
180 return *(int*)s1 - *(int*)s2;
181 }
182
ug_array_compare_string(const void * s1,const void * s2)183 int ug_array_compare_string(const void *s1, const void *s2)
184 {
185 return strcmp(*(char**)s1, *(char**)s2);
186 }
187
ug_array_compare_pointer(const void * s1,const void * s2)188 int ug_array_compare_pointer(const void *s1, const void *s2)
189 {
190 return *(char**)s1 - *(char**)s2;
191 }
192
193 // ----------------------------------------------------------------------------
194 // UgJsonParseFunc for JSON array elements
195
ug_json_parse_array_bool(UgJson * json,const char * name,const char * value,void * array,void * none)196 UgJsonError ug_json_parse_array_bool(UgJson* json,
197 const char* name, const char* value,
198 void* array, void* none)
199 {
200 int boolValue;
201
202 if (json->type != UG_JSON_TRUE && json->type != UG_JSON_FALSE) {
203 // if (json->type >= UG_JSON_OBJECT)
204 // ug_json_push(json, ug_json_parse_unknown, NULL, NULL);
205 return UG_JSON_ERROR_TYPE_NOT_MATCH;
206 }
207
208 if (json->type == UG_JSON_TRUE)
209 boolValue = TRUE;
210 else
211 boolValue = FALSE;
212
213 ((UgArrayInt*)array)->element_size = sizeof(int);
214 *((int*) ug_array_alloc(array, 1)) = boolValue;
215 return UG_JSON_ERROR_NONE;
216 }
217
ug_json_parse_array_int(UgJson * json,const char * name,const char * value,void * array,void * none)218 UgJsonError ug_json_parse_array_int(UgJson* json,
219 const char* name, const char* value,
220 void* array, void* none)
221 {
222 if (json->type != UG_JSON_NUMBER) {
223 // if (json->type >= UG_JSON_OBJECT)
224 // ug_json_push(json, ug_json_parse_unknown, NULL, NULL);
225 return UG_JSON_ERROR_TYPE_NOT_MATCH;
226 }
227
228 ((UgArrayInt*)array)->element_size = sizeof(int);
229 *((int*) ug_array_alloc(array, 1)) = strtol(value, NULL, 10);
230 return UG_JSON_ERROR_NONE;
231 }
232
ug_json_parse_array_uint(UgJson * json,const char * name,const char * value,void * array,void * none)233 UgJsonError ug_json_parse_array_uint(UgJson* json,
234 const char* name, const char* value,
235 void* array, void* none)
236 {
237 if (json->type != UG_JSON_NUMBER) {
238 // if (json->type >= UG_JSON_OBJECT)
239 // ug_json_push(json, ug_json_parse_unknown, NULL, NULL);
240 return UG_JSON_ERROR_TYPE_NOT_MATCH;
241 }
242
243 ((UgArrayInt*)array)->element_size = sizeof(unsigned int);
244 *((unsigned int*) ug_array_alloc(array, 1)) = strtoul(value, NULL, 10);
245 return UG_JSON_ERROR_NONE;
246 }
247
ug_json_parse_array_int64(UgJson * json,const char * name,const char * value,void * array,void * none)248 UgJsonError ug_json_parse_array_int64(UgJson* json,
249 const char* name, const char* value,
250 void* array, void* none)
251 {
252 if (json->type != UG_JSON_NUMBER) {
253 // if (json->type >= UG_JSON_OBJECT)
254 // ug_json_push(json, ug_json_parse_unknown, NULL, NULL);
255 return UG_JSON_ERROR_TYPE_NOT_MATCH;
256 }
257
258 ((UgArrayInt*)array)->element_size = sizeof(int64_t);
259 *((int64_t*) ug_array_alloc(array, 1)) = strtoll(value, NULL, 10);
260 return UG_JSON_ERROR_NONE;
261 }
262
ug_json_parse_array_double(UgJson * json,const char * name,const char * value,void * array,void * none)263 UgJsonError ug_json_parse_array_double(UgJson* json,
264 const char* name, const char* value,
265 void* array, void* none)
266 {
267 if (json->type != UG_JSON_NUMBER) {
268 // if (json->type >= UG_JSON_OBJECT)
269 // ug_json_push(json, ug_json_parse_unknown, NULL, NULL);
270 return UG_JSON_ERROR_TYPE_NOT_MATCH;
271 }
272
273 ((UgArrayInt*)array)->element_size = sizeof(double);
274 *((double*) ug_array_alloc(array, 1)) = strtod(value, NULL);
275 return UG_JSON_ERROR_NONE;
276 }
277
ug_json_parse_array_string(UgJson * json,const char * name,const char * value,void * array,void * none)278 UgJsonError ug_json_parse_array_string(UgJson* json,
279 const char* name, const char* value,
280 void* array, void* none)
281 {
282 char* string;
283
284 if (json->type == UG_JSON_STRING)
285 string = ug_strdup(value);
286 else if (json->type == UG_JSON_NULL)
287 string = NULL;
288 else {
289 // if (json->type >= UG_JSON_OBJECT)
290 // ug_json_push(json, ug_json_parse_unknown, NULL, NULL);
291 return UG_JSON_ERROR_TYPE_NOT_MATCH;
292 }
293
294 ((UgArrayInt*)array)->element_size = sizeof(char*);
295 *((char**) ug_array_alloc(array, 1)) = string;
296 return UG_JSON_ERROR_NONE;
297 }
298
299 // ----------------------------------------------------------------------------
300 // write JSON array elements
301
ug_json_write_array_bool(UgJson * json,UgArrayInt * array)302 void ug_json_write_array_bool(UgJson* json, UgArrayInt* array)
303 {
304 // UgArrayInt* array = src;
305 int index;
306
307 for (index = 0; index < array->length; index++)
308 ug_json_write_bool(json, array->at[index]);
309 }
310
ug_json_write_array_int(UgJson * json,UgArrayInt * array)311 void ug_json_write_array_int(UgJson* json, UgArrayInt* array)
312 {
313 // UgArrayInt* array = src;
314 int index;
315
316 for (index = 0; index < array->length; index++)
317 ug_json_write_int(json, array->at[index]);
318 }
319
ug_json_write_array_uint(UgJson * json,UgArrayUint * array)320 void ug_json_write_array_uint(UgJson* json, UgArrayUint* array)
321 {
322 int index;
323
324 for (index = 0; index < array->length; index++)
325 ug_json_write_uint(json, array->at[index]);
326 }
327
ug_json_write_array_int64(UgJson * json,UgArrayInt64 * array)328 void ug_json_write_array_int64(UgJson* json, UgArrayInt64* array)
329 {
330 int index;
331
332 for (index = 0; index < array->length; index++)
333 ug_json_write_int64(json, array->at[index]);
334 }
335
ug_json_write_array_double(UgJson * json,UgArrayDouble * array)336 void ug_json_write_array_double(UgJson* json, UgArrayDouble* array)
337 {
338 int index;
339
340 for (index = 0; index < array->length; index++)
341 ug_json_write_double(json, array->at[index]);
342 }
343
ug_json_write_array_string(UgJson * json,UgArrayStr * array)344 void ug_json_write_array_string(UgJson* json, UgArrayStr* array)
345 {
346 int index;
347 char* string;
348
349 for (index = 0; index < array->length; index++) {
350 string = array->at[index];
351 if (string == NULL)
352 ug_json_write_null(json);
353 else
354 ug_json_write_string(json, string);
355 }
356 }
357
358