1 /*
2 	copyright: Steve Dekorte, 2006. All rights reserved.
3 	license: See _BSDLicense.txt.
4 */
5 
6 #include "UArray.h"
7 #include "cencode.h"
8 #include "cdecode.h"
9 #include <string.h>
10 #include <stdarg.h>
11 #include <stdio.h>
12 #include <stddef.h>
13 #include <ctype.h>
14 
UArray_append_(UArray * self,const UArray * other)15 void UArray_append_(UArray *self, const UArray *other)
16 {
17 	if(UArray_itemSize(self) < UArray_itemSize(other))
18 	{
19 		UArray_convertToItemType_(self, (int)UArray_itemType(other));
20 	}
21 
22 	UArray_at_putAll_(self, self->size, other);
23 }
24 
UArray_appendCString_(UArray * self,const char * s)25 void UArray_appendCString_(UArray *self, const char *s)
26 {
27 	/* TODO: pass in the length of the string since it's usually known. */
28 	UArray_appendBytes_size_(self, (const uint8_t *) s, strlen(s));
29 }
30 
UArray_prepend_(UArray * self,const UArray * other)31 void UArray_prepend_(UArray *self, const UArray *other)
32 {
33 	UArray_at_putAll_(self, 0, other);
34 }
35 
UArray_equalsAnyCase_(const UArray * self,const UArray * other)36 int UArray_equalsAnyCase_(const UArray *self, const UArray *other)
37 {
38 	if (self->size == other->size)
39 	{
40 		return UArray_findAnyCase_(self, other) == 0;
41 	}
42 
43 	return 0;
44 }
45 
UArray_replace_with_(UArray * self,const UArray * a1,const UArray * a2)46 void UArray_replace_with_(UArray *self, const UArray *a1, const UArray *a2)
47 {
48 	long i;
49 	size_t start = 0;
50 	UArray visible = UArray_stackRange(self, start, self->size);
51 
52 	if (UArray_size(a1) == 0) return;
53 
54 	while ((i = UArray_find_(&visible, a1)) != -1)
55 	{
56 		size_t index = start + i;
57 		UArray_removeRange(self, index, a1->size);
58 		UArray_at_putAll_(self, index, a2);
59 		start = index + a2->size;
60 		visible = UArray_stackRange(self, start, self->size - start);
61 	}
62 	UArray_changed(self);
63 }
64 
UArray_replaceCString_withCString_(UArray * self,const char * s1,const char * s2)65 BASEKIT_API void UArray_replaceCString_withCString_(UArray *self, const char *s1, const char *s2)
66 {
67 	UArray a1 = UArray_stackAllocedWithCString_((char *)s1);
68 	UArray a2 = UArray_stackAllocedWithCString_((char *)s2);
69 	UArray_replace_with_(self, &a1, &a2);
70 }
71 
UArray_replaceAnyCase_with_(UArray * self,const UArray * a1,const UArray * a2)72 void UArray_replaceAnyCase_with_(UArray *self, const UArray *a1, const UArray *a2)
73 {
74 	long i;
75 	size_t start = 0;
76 	UArray visible = UArray_stackRange(self, start, self->size);
77 
78 	while ((i = UArray_findAnyCase_(&visible, a1)) != -1)
79 	{
80 		size_t index = start + i;
81 		UArray_removeRange(self, index, a1->size);
82 		UArray_at_putAll_(self, index, a2);
83 		start = index + a2->size;
84 		visible = UArray_stackRange(self, start, self->size - start);
85 	}
86 
87 	UArray_changed(self);
88 }
89 
UArray_remove_(UArray * self,const UArray * a1)90 BASEKIT_API void UArray_remove_(UArray *self, const UArray *a1)
91 {
92 	UArray blank = UArray_stackAllocedEmptyUArray();
93 	UArray_replace_with_(self, a1, &blank);
94 }
95 
UArray_removeAnyCase_(UArray * self,const UArray * a1)96 BASEKIT_API void UArray_removeAnyCase_(UArray *self, const UArray *a1)
97 {
98 	UArray blank = UArray_stackAllocedEmptyUArray();
99 	UArray_replaceAnyCase_with_(self, a1, &blank);
100 }
101 
102 // clipping
103 
UArray_clipBefore_(UArray * self,const UArray * other)104 BASEKIT_API int UArray_clipBefore_(UArray *self, const UArray *other)
105 {
106 	long index = UArray_find_(self, other);
107 
108 	if (index > -1)
109 	{
110 		UArray_removeRange(self, 0, index);
111 		return 1;
112 	}
113 
114 	return 0;
115 }
116 
UArray_clipBeforeEndOf_(UArray * self,const UArray * other)117 BASEKIT_API int UArray_clipBeforeEndOf_(UArray *self, const UArray *other)
118 {
119 	long index = UArray_find_(self, other);
120 	/*
121 	printf("UArray_find_('%s', '%s')\n", UArray_bytes(self), UArray_bytes(other));
122 	printf("find index = %i\n", index);
123 	printf("prefix sizeInBytes = %i\n", UArray_sizeInBytes(other));
124 	printf("prefix size = %i\n", UArray_size(other));
125 	*/
126 	if (index > -1 && other->size)
127 	{
128 		//printf("UArray_removeRange(0, %i)\n", index + other->size - 1);
129 		UArray_removeRange(self, 0, index + other->size);
130 		//printf("result = '%s'\n", UArray_bytes(self));
131 		return 1;
132 	}
133 
134 	return 0;
135 }
136 
UArray_clipAfter_(UArray * self,const UArray * other)137 BASEKIT_API int UArray_clipAfter_(UArray *self, const UArray *other)
138 {
139 	long index = UArray_find_(self, other);
140 
141 	if (index > -1)
142 	{
143 		UArray_removeRange(self, index + other->size, self->size);
144 		return 1;
145 	}
146 
147 	return 0;
148 }
149 
UArray_clipAfterStartOf_(UArray * self,const UArray * other)150 BASEKIT_API int UArray_clipAfterStartOf_(UArray *self, const UArray *other)
151 {
152 	long index = UArray_find_(self, other);
153 
154 	if (index > -1)
155 	{
156 		UArray_removeRange(self, index, self->size);
157 		return 1;
158 	}
159 
160 	return 0;
161 }
162 
163 // strip
164 
UArray_lstrip_(UArray * self,const UArray * other)165 void UArray_lstrip_(UArray *self, const UArray *other)
166 {
167 	size_t amount = 0;
168 
169 	if (UArray_isFloatType(self))
170 	{
171 		UARRAY_FOREACH(self, i, v,
172 			amount = i+1;
173 			if (!UArray_containsDouble_(other, v))
174 			{
175 				amount --;
176 				break;
177 			}
178 		)
179 	}
180 	else
181 	{
182 		UARRAY_FOREACH(self, i, v,
183 			amount = i+1;
184 			if (!UArray_containsLong_(other, v))
185 			{
186 				amount --;
187 				break;
188 			}
189 		)
190 	}
191 
192 	UArray_removeRange(self, 0, amount);
193 }
194 
UArray_rstrip_(UArray * self,const UArray * other)195 void UArray_rstrip_(UArray *self, const UArray *other)
196 {
197 	size_t index = 0; // initial value is only needed when FOREACHes don't work
198 
199 	if (UArray_isFloatType(self))
200 	{
201 		UARRAY_RFOREACH(self, i, v,
202 			index = i;
203 			if (!UArray_containsDouble_(other, v)) { index++; break; }
204 		)
205 	}
206 	else
207 	{
208 		UARRAY_RFOREACH(self, i, v,
209 			index = i;
210 			if (!UArray_containsLong_(other, v)) { index++; break; }
211 		)
212 	}
213 
214 	UArray_removeRange(self, index, self->size);
215 }
216 
UArray_strip_(UArray * self,const UArray * other)217 BASEKIT_API void UArray_strip_(UArray *self, const UArray *other)
218 {
219 	UArray_lstrip_(self, other);
220 	UArray_rstrip_(self, other);
221 }
222 
223 // swap
224 
UArray_swapIndex_withIndex_(UArray * self,size_t i,size_t j)225 BASEKIT_API void UArray_swapIndex_withIndex_(UArray *self, size_t i, size_t j)
226 {
227 	size_t itemSize = self->itemSize;
228 	uint8_t *data = self->data;
229 	void *ip = data + i * itemSize;
230 	void *jp = data + j * itemSize;
231 	UArrayValueUnion b;
232 
233 	memcpy(&b, ip, sizeof(UArray));
234 	memcpy(ip, jp, sizeof(UArray));
235 	memcpy(jp, &b, sizeof(UArray));
236 	UArray_changed(self);
237 }
238 
239 // reverse
240 
UArray_reverse(UArray * self)241 BASEKIT_API void UArray_reverse(UArray *self)
242 {
243 	long i = 0;
244 	long j = self->size - 1;
245 	UArrayValueUnion b;
246 	size_t itemSize = self->itemSize;
247 	uint8_t *data = self->data;
248 
249 	while (j > i)
250 	{
251 		void *ip = data + i * itemSize;
252 		void *jp = data + j * itemSize;
253 
254 		memcpy(&b, ip, itemSize);
255 		memcpy(ip, jp, itemSize);
256 		memcpy(jp, &b, itemSize);
257 
258 		j --;
259 		i ++;
260 	}
261 
262 	UArray_changed(self);
263 }
264 
265 /*
266 #define UARRAY_MATCHPREFIXLENGTH_TYPES(OP2, TYPE1, self, TYPE2, other)\
267 {\
268 	long i, minSize = (self->size < other->size) ? self->size : other->size;\
269 	for(i = 0; i < minSize; i ++)\
270 	{\
271 		TYPE1 v1 = ((TYPE1 *)self->data)[i];\
272 		TYPE2 v2 = ((TYPE2 *)other->data)[i];\
273 		if (v1 != v2) break;\
274 	}\
275 	return i;\
276 }
277 
278 BASEKIT_API size_t UArray_matchingPrefixSizeWith_(const UArray *self, const UArray *other)
279 {
280 	DUARRAY_OP(UARRAY_MATCHPREFIXLENGTH_TYPES, NULL, self, other);
281 }
282 */
283 
284 // split
285 
UArray_split_(const UArray * self,const PtrUArray * delims)286 PtrUArray *UArray_split_(const UArray *self, const PtrUArray *delims)
287 {
288 	PtrUArray *results = UArray_new();
289 	size_t i, last = 0;
290 	UArray_setItemType_(results, CTYPE_uintptr_t);
291 
292 	for (i = 0; i < self->size; i ++)
293 	{
294 		UArray slice = UArray_stackRange(self, i, self->size - i);
295 		size_t j;
296 
297 		for (j = 0; j < delims->size; j ++)
298 		{
299 			UArray *delim = UArray_rawPointerAt_(delims, j);
300 
301 			if (UArray_beginsWith_(&slice, delim))
302 			{
303 				UArray_appendPointer_(results, UArray_range(self, last, i - last));
304 
305 				last = i + delim->size;
306 				i = last - 1; // since for() will increment it
307 				break;
308 			}
309 		}
310 	}
311 
312 	if (last != self->size)
313 	{
314 		UArray_appendPointer_(results, UArray_range(self, last, self->size - last));
315 	}
316 
317 	return results;
318 }
319 
UArray_splitCount_(const UArray * self,const PtrUArray * delims)320 size_t UArray_splitCount_(const UArray *self, const PtrUArray *delims)
321 {
322 	PtrUArray *r = UArray_split_(self, delims);
323 	size_t count = UArray_size(r);
324 	UArray_free(r);
325 	return count;
326 }
327 
328 // find
329 
UArray_beginsWith_(UArray * self,const UArray * other)330 BASEKIT_API int UArray_beginsWith_(UArray *self, const UArray *other)
331 {
332 	size_t msize = self->size;
333 	size_t osize = other->size;
334 
335 	if (msize >= osize)
336 	{
337 		/* A common case seems to be comparing against a single byte, which
338 		 * happens all of the place internally (not sure why yet, but it would
339 		 * be good to investigate this)*/
340 		if (osize == 1)
341 		{
342 			return (*(self->data) == *(other->data));
343 		}
344 		else if (memcmp(self->data, other->data, osize) == 0)
345 		{
346 			return 1;
347 		}
348 		return 0;
349 	}
350 	return  0;
351 }
352 
UArray_endsWith_(UArray * self,const UArray * other)353 BASEKIT_API int UArray_endsWith_(UArray *self, const UArray *other)
354 {
355 	if (self->size >= other->size)
356 	{
357 		UArray tmp = UArray_stackRange(self, self->size - other->size, other->size);
358 		return UArray_find_(&tmp, other) != -1;
359 	}
360 
361 	return 0;
362 }
363 
364 // escape and quote
365 
UArray_swapWith_(UArray * self,UArray * other)366 void UArray_swapWith_(UArray *self, UArray *other)
367 {
368 	UArray b;
369 	memcpy(&b, other, sizeof(UArray));
370 	memcpy(other, self, sizeof(UArray));
371 	memcpy(self, &b, sizeof(UArray));
372 	UArray_changed(self);
373 }
374 
UArray_escape(UArray * self)375 void UArray_escape(UArray *self)
376 {
377 	UArray *out = UArray_new();
378 	out->itemType = self->itemType;
379 	out->itemSize = self->itemSize;
380 
381 	UARRAY_FOREACH(self, i, v,
382 		switch ((int)v)
383 		{
384 			case '"':  UArray_appendCString_(out, "\\\""); break;
385 			case '\a': UArray_appendCString_(out, "\\a"); break;
386 			case '\b': UArray_appendCString_(out, "\\b"); break;
387 			case '\f': UArray_appendCString_(out, "\\f"); break;
388 			case '\n': UArray_appendCString_(out, "\\n"); break;
389 			case '\r': UArray_appendCString_(out, "\\r"); break;
390 			case '\t': UArray_appendCString_(out, "\\t"); break;
391 			case '\v': UArray_appendCString_(out, "\\v"); break;
392 			case '\0': UArray_appendCString_(out, "\\0"); break;
393 			case '\\': UArray_appendCString_(out, "\\\\"); break;
394 			default:   UArray_appendLong_(out, v);
395 		}
396 	);
397 
398 	UArray_swapWith_(self, out);
399 	UArray_free(out);
400 	UArray_changed(self);
401 }
402 
UArray_unescape(UArray * self)403 void UArray_unescape(UArray *self)
404 {
405 	size_t getIndex = 0;
406 	size_t putIndex = 0;
407 
408 	while (getIndex < self->size)
409 	{
410 		long c = UArray_longAt_(self, getIndex);
411 		long nextChar = UArray_longAt_(self, getIndex + 1);
412 
413 		if (c != '\\')
414 		{
415 			if (getIndex != putIndex)
416 			{
417 				UArray_at_putLong_(self, putIndex, c);
418 			}
419 
420 			putIndex ++;
421 		}
422 		else
423 		{
424 			c = nextChar;
425 
426 			switch (c)
427 			{
428 				case  'a': c = '\a'; break;
429 				case  'b': c = '\b'; break;
430 				case  'f': c = '\f'; break;
431 				case  'n': c = '\n'; break;
432 				case  'r': c = '\r'; break;
433 				case  't': c = '\t'; break;
434 				case  'v': c = '\v'; break;
435 				case '\0': c = '\\'; break;
436 				default:
437 					if (isdigit((int)c))
438 					{
439 						c -= 48;
440 					}
441 			}
442 
443 			UArray_at_putLong_(self, putIndex, c);
444 			getIndex ++;
445 			putIndex ++;
446 		}
447 
448 		getIndex ++;
449 	}
450 
451 	UArray_setSize_(self, putIndex);
452 	UArray_changed(self);
453 }
454 
UArray_quote(UArray * self)455 void UArray_quote(UArray *self)
456 {
457 	UArray q = UArray_stackAllocedWithCString_("\"");
458 	UArray_prepend_(self, &q);
459 	UArray_append_(self, &q);
460 	UArray_changed(self);
461 }
462 
UArray_unquote(UArray * self)463 void UArray_unquote(UArray *self)
464 {
465 	UArray q = UArray_stackAllocedWithCString_("\"");
466 
467 	if(UArray_beginsWith_(self, &q) && UArray_endsWith_(self, &q))
468 	{
469 		UArray_removeFirst(self);
470 		UArray_removeLast(self);
471 		UArray_changed(self);
472 	}
473 }
474 
UArray_translate(UArray * self,UArray * fromChars,UArray * toChars)475 void UArray_translate(UArray *self, UArray *fromChars, UArray *toChars)
476 {
477 	double max = 4096;
478 	double fromMax = UArray_maxAsDouble(fromChars);
479 	double toMax   = UArray_maxAsDouble(toChars);
480 
481 	if (UArray_size(fromChars) != UArray_size(toChars))
482 	{
483 		printf("UArray_translate: translation strings must be of the same length");
484 		return;
485 	}
486 
487 	if ((0 < fromMax && fromMax < max) && (0 < toMax && toMax < 256))
488 	{
489 		size_t i;
490 		uint8_t *map = io_calloc(1, fromMax);
491 		memset(map, 0x0, fromMax);
492 
493 		for(i = 0; i < UArray_size(fromChars); i ++)
494 		{
495 			map[UArray_longAt_(fromChars, i)] = UArray_longAt_(toChars, i);
496 		}
497 
498 		for(i = 0; i < UArray_size(self); i ++)
499 		{
500 			self->data[i] = map[self->data[i]];
501 		}
502 
503 		io_free(map);
504 		return;
505 	}
506 
507 	/*
508 	 UARRAY_FOREACH(self, i, currChar,
509 				 UARRAY_FOREACH(fromChars, j, fromChar,
510 							 if(currChar == fromChar)
511 							 {
512 								 UARRAY_RAWAT_PUT_(self, i, UARRAY_RAWAT_(toChars, j));
513 								 break;
514 							 }
515 							 );
516 				 );
517 	 */
518 
519 	UArray_error_(self, "UArray_translate unimplemented for this type");
520 }
521 
UArray_count_(const UArray * self,const UArray * other)522 size_t UArray_count_(const UArray *self, const UArray *other)
523 {
524 	long i = 0;
525 	size_t count = 0;
526 
527 	while ((i = UArray_find_from_(self, other, i)) != -1)
528 	{
529 		i += UArray_size(other);
530 		count ++;
531 	}
532 
533 	return count;
534 }
535 
UArray_asBase64(const UArray * self,int charsPerLine)536 UArray *UArray_asBase64(const UArray *self, int charsPerLine)
537 {
538 	base64_encodestate state;
539 	size_t unencodedBytesSize;
540 	uint8_t *encodedBytes;
541 	size_t encodedBytesSize;
542 	UArray *encoded;
543 
544 	base64_init_encodestate(&state);
545 	state.chars_per_line = charsPerLine;
546 
547 	unencodedBytesSize = UArray_sizeInBytes(self);
548 	encodedBytes = io_calloc(2 * unencodedBytesSize, 1);
549 
550 	encoded = UArray_new();
551 	UArray_setItemType_(encoded, CTYPE_uint8_t);
552 
553 	encodedBytesSize = base64_encode_block((char *)UArray_bytes(self), (int)unencodedBytesSize, (char *)encodedBytes, &state);
554 	UArray_appendBytes_size_(encoded, encodedBytes, encodedBytesSize);
555 
556 	encodedBytesSize = base64_encode_blockend((char *)encodedBytes, &state);
557 	UArray_appendBytes_size_(encoded, encodedBytes, encodedBytesSize);
558 
559 	io_free(encodedBytes);
560 
561 	return encoded;
562 }
563 
UArray_fromBase64(const UArray * self)564 UArray *UArray_fromBase64(const UArray *self)
565 {
566 	base64_decodestate state;
567 	size_t undecodedBytesSize;
568 	uint8_t *decodedBytes;
569 	size_t decodedBytesSize;
570 	UArray *decoded;
571 
572 	base64_init_decodestate(&state);
573 	undecodedBytesSize = UArray_sizeInBytes(self);
574 	decodedBytes = io_calloc(2 * undecodedBytesSize, 1);
575 
576 	decoded = UArray_new();
577 	UArray_setItemType_(decoded, CTYPE_uint8_t);
578 
579 	decodedBytesSize = base64_decode_block((char *)UArray_bytes(self), (int)undecodedBytesSize, (char *)decodedBytes, &state);
580 	UArray_appendBytes_size_(decoded, decodedBytes, decodedBytesSize);
581 
582 	io_free(decodedBytes);
583 
584 	return decoded;
585 }
586 
587