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