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