SystemCall run(block) can now exit the run if it returns false
[io/quag.git] / libs / basekit / source / UArray_string.c
blob41990934a215bf6b38645356abb62829b9c32ed8
1 /*
2 copyright: Steve Dekorte, 2006. All rights reserved.
3 license: See _BSDLicense.txt.
4 */
6 #include "UArray.h"
7 #include <string.h>
8 #include <stdarg.h>
9 #include <stdio.h>
10 #include <stddef.h>
12 void UArray_append_(UArray *self, const UArray *other)
14 UArray_at_putAll_(self, self->size, other);
17 void UArray_appendCString_(UArray *self, const char *s)
19 while (*s)
21 UArray_appendLong_(self, *s);
22 s ++;
26 void UArray_prepend_(UArray *self, const UArray *other)
28 UArray_at_putAll_(self, 0, other);
31 int UArray_equalsAnyCase_(const UArray *self, const UArray *other)
33 if (self->size == other->size)
35 return UArray_findAnyCase_(self, other) == 0;
38 return 0;
41 void UArray_replace_with_(UArray *self, const UArray *a1, const UArray *a2)
43 long i;
44 size_t start = 0;
45 UArray visible = UArray_stackRange(self, start, self->size);
47 while ((i = UArray_find_(&visible, a1)) != -1)
49 size_t index = start + i;
50 UArray_removeRange(self, index, a1->size);
51 UArray_at_putAll_(self, index, a2);
52 start = index + a2->size;
53 visible = UArray_stackRange(self, start, self->size - start);
55 UArray_changed(self);
58 BASEKIT_API void UArray_replaceCString_withCString_(UArray *self, const char *s1, const char *s2)
60 UArray a1 = UArray_stackAllocedWithCString_((char *)s1);
61 UArray a2 = UArray_stackAllocedWithCString_((char *)s2);
62 UArray_replace_with_(self, &a1, &a2);
65 void UArray_replaceAnyCase_with_(UArray *self, const UArray *a1, const UArray *a2)
67 long i;
68 size_t start = 0;
69 UArray visible = UArray_stackRange(self, start, self->size);
71 while ((i = UArray_findAnyCase_(&visible, a1)) != -1)
73 size_t index = start + i;
74 UArray_removeRange(self, index, a1->size);
75 UArray_at_putAll_(self, index, a2);
76 start = index + a2->size;
77 visible = UArray_stackRange(self, start, self->size - start);
80 UArray_changed(self);
83 BASEKIT_API void UArray_remove_(UArray *self, const UArray *a1)
85 UArray blank = UArray_stackAllocedEmptyUArray();
86 UArray_replace_with_(self, a1, &blank);
89 BASEKIT_API void UArray_removeAnyCase_(UArray *self, const UArray *a1)
91 UArray blank = UArray_stackAllocedEmptyUArray();
92 UArray_replaceAnyCase_with_(self, a1, &blank);
95 // clipping
97 BASEKIT_API int UArray_clipBefore_(UArray *self, const UArray *other)
99 long index = UArray_find_(self, other);
101 if (index > -1)
103 UArray_removeRange(self, 0, index);
104 return 1;
107 return 0;
110 BASEKIT_API int UArray_clipBeforeEndOf_(UArray *self, const UArray *other)
112 long index = UArray_find_(self, other);
114 if (index > -1)
116 UArray_removeRange(self, 0, index + other->size);
117 return 1;
120 return 0;
123 BASEKIT_API int UArray_clipAfter_(UArray *self, const UArray *other)
125 long index = UArray_find_(self, other);
127 if (index > -1)
129 UArray_removeRange(self, index + other->size, self->size);
130 return 1;
133 return 0;
136 BASEKIT_API int UArray_clipAfterStartOf_(UArray *self, const UArray *other)
138 long index = UArray_find_(self, other);
140 if (index > -1)
142 UArray_removeRange(self, index, self->size);
143 return 1;
146 return 0;
149 // strip
151 void UArray_lstrip_(UArray *self, const UArray *other)
153 size_t index = 0;
155 if (UArray_isFloatType(self))
157 UARRAY_FOREACH(self, i, v, index = i; if (!UArray_containsDouble_(other, v)) break; )
159 else
161 UARRAY_FOREACH(self, i, v, index = i; if (!UArray_containsLong_(other, v)) break; )
164 UArray_removeRange(self, 0, index);
167 void UArray_rstrip_(UArray *self, const UArray *other)
169 if (self->size)
171 size_t index = self->size - 1;
173 if (UArray_isFloatType(self))
175 UARRAY_RFOREACH(self, i, v, index = i; if (!UArray_containsDouble_(other, v)) break; )
177 else
179 UARRAY_RFOREACH(self, i, v, index = i; if (!UArray_containsLong_(other, v)) break; )
182 UArray_removeRange(self, index + 1, self->size);
186 BASEKIT_API void UArray_strip_(UArray *self, const UArray *other)
188 UArray_lstrip_(self, other);
189 UArray_rstrip_(self, other);
192 // swap
194 BASEKIT_API void UArray_swapIndex_withIndex_(UArray *self, size_t i, size_t j)
196 int itemSize = self->itemSize;
197 uint8_t *data = self->data;
198 void *ip = data + i * itemSize;
199 void *jp = data + j * itemSize;
200 UArrayValueUnion b;
202 memcpy(&b, ip, sizeof(UArray));
203 memcpy(ip, jp, sizeof(UArray));
204 memcpy(jp, &b, sizeof(UArray));
205 UArray_changed(self);
208 // reverse
210 BASEKIT_API void UArray_reverse(UArray *self)
212 long i = 0;
213 long j = self->size - 1;
214 UArrayValueUnion b;
215 int itemSize = self->itemSize;
216 uint8_t *data = self->data;
218 while (j > i)
220 void *ip = data + i * itemSize;
221 void *jp = data + j * itemSize;
223 memcpy(&b, ip, itemSize);
224 memcpy(ip, jp, itemSize);
225 memcpy(jp, &b, itemSize);
227 j --;
228 i ++;
231 UArray_changed(self);
235 #define UARRAY_MATCHPREFIXLENGTH_TYPES(OP2, TYPE1, self, TYPE2, other)\
237 long i, minSize = (self->size < other->size) ? self->size : other->size;\
238 for(i = 0; i < minSize; i ++)\
240 TYPE1 v1 = ((TYPE1 *)self->data)[i];\
241 TYPE2 v2 = ((TYPE2 *)other->data)[i];\
242 if (v1 != v2) break;\
244 return i;\
247 BASEKIT_API size_t UArray_matchingPrefixSizeWith_(const UArray *self, const UArray *other)
249 DUARRAY_OP(UARRAY_MATCHPREFIXLENGTH_TYPES, NULL, self, other);
253 // split
255 PtrUArray *UArray_split_(const UArray *self, const PtrUArray *delims)
257 PtrUArray *results = UArray_new();
258 size_t i, last = 0;
259 UArray_setItemType_(results, CTYPE_uintptr_t);
261 for (i = 0; i < self->size; i ++)
263 UArray slice = UArray_stackRange(self, i, self->size - i);
264 size_t j;
266 for (j = 0; j < delims->size; j ++)
268 UArray *delim = UArray_rawPointerAt_(delims, j);
270 if (UArray_beginsWith_(&slice, delim))
272 UArray_appendPointer_(results, UArray_range(self, last, i - last));
274 last = i + delim->size;
275 i = last - 1; // since for() will increment it
276 break;
281 if (last != self->size)
283 UArray_appendPointer_(results, UArray_range(self, last, self->size - last));
286 return results;
289 size_t UArray_splitCount_(const UArray *self, const PtrUArray *delims)
291 PtrUArray *r = UArray_split_(self, delims);
292 size_t count = UArray_size(r);
293 UArray_free(r);
294 return count;
297 // find
299 BASEKIT_API int UArray_beginsWith_(UArray *self, const UArray *other)
301 if (self->size >= other->size)
303 UArray tmp = UArray_stackRange(self, 0, other->size);
304 return UArray_find_(&tmp, other) != -1;
307 return 0;
310 BASEKIT_API int UArray_endsWith_(UArray *self, const UArray *other)
312 if (self->size >= other->size)
314 UArray tmp = UArray_stackRange(self, self->size - other->size, other->size);
315 return UArray_find_(&tmp, other) != -1;
318 return 0;
321 // escape and quote
323 void UArray_swapWith_(UArray *self, UArray *other)
325 UArray b;
326 memcpy(&b, other, sizeof(UArray));
327 memcpy(other, self, sizeof(UArray));
328 memcpy(self, &b, sizeof(UArray));
329 UArray_changed(self);
332 void UArray_escape(UArray *self)
334 UArray *out = UArray_new();
335 out->itemType = self->itemType;
337 UARRAY_FOREACH(self, i, v,
338 switch ((int)v)
340 case '"': UArray_appendCString_(out, "\\\""); break;
341 case '\a': UArray_appendCString_(out, "\\a"); break;
342 case '\b': UArray_appendCString_(out, "\\b"); break;
343 case '\f': UArray_appendCString_(out, "\\f"); break;
344 case '\n': UArray_appendCString_(out, "\\n"); break;
345 case '\r': UArray_appendCString_(out, "\\r"); break;
346 case '\t': UArray_appendCString_(out, "\\t"); break;
347 case '\v': UArray_appendCString_(out, "\\v"); break;
348 case '\\': UArray_appendCString_(out, "\\\\"); break;
349 default: UArray_appendLong_(out, v);
353 UArray_swapWith_(self, out);
354 UArray_free(out);
355 UArray_changed(self);
358 void UArray_unescape(UArray *self)
360 if (self->itemSize == 1)
362 int mbskip = 0; /* multi-byte character size */
363 size_t getIndex = 0;
364 size_t putIndex = 0;
365 char *s = (char *)self->data;
367 while (getIndex < self->size)
369 int c = s[getIndex];
370 int nextChar = s[getIndex + 1];
372 if (mbskip <= 0 && ismbchar(c))
374 mbskip = mbcharlen(c);
377 if (c != '\\' || mbskip > 0)
379 mbskip --;
381 if (getIndex != putIndex)
383 s[putIndex] = c;
386 putIndex ++;
388 else
390 char c = nextChar;
392 switch (c)
394 case 'a': c = '\a'; break;
395 case 'b': c = '\b'; break;
396 case 'f': c = '\f'; break;
397 case 'n': c = '\n'; break;
398 case 'r': c = '\r'; break;
399 case 't': c = '\t'; break;
400 case 'v': c = '\v'; break;
401 case '\0': c = '\\'; break;
402 default:
403 if (isdigit(c))
405 c -= 48;
409 s[putIndex] = c;
410 getIndex ++;
411 putIndex ++;
414 getIndex++;
417 UArray_setSize_(self, putIndex);
418 UArray_changed(self);
419 return;
421 printf("Error: UArray unescape unsupported on type size %i\n", self->itemSize);
424 void UArray_quote(UArray *self)
426 UArray q = UArray_stackAllocedWithCString_("\"");
427 UArray_prepend_(self, &q);
428 UArray_append_(self, &q);
429 UArray_changed(self);
432 void UArray_unquote(UArray *self)
434 UArray q = UArray_stackAllocedWithCString_("\"");
436 if(UArray_beginsWith_(self, &q) && UArray_endsWith_(self, &q))
438 UArray_removeFirst(self);
439 UArray_removeLast(self);
440 UArray_changed(self);
444 void UArray_translate(UArray *self, UArray *fromChars, UArray *toChars)
446 size_t max = 4096;
447 long fromMax = UArray_maxAsDouble(fromChars);
448 long toMax = UArray_maxAsDouble(toChars);
450 if (UArray_size(fromChars) != UArray_size(toChars))
452 printf("UArray_translate: translation strings must be of the same length");
453 return;
456 if ((0 < fromMax && fromMax < max) && (0 < toMax && toMax < 256))
458 size_t i;
459 uint8_t *map = io_calloc(1, fromMax);
460 memset(map, 0x0, fromMax);
462 for(i = 0; i < UArray_size(fromChars); i ++)
464 map[UArray_longAt_(fromChars, i)] = UArray_longAt_(toChars, i);
467 for(i = 0; i < UArray_size(self); i ++)
469 self->data[i] = map[self->data[i]];
472 io_free(map);
473 return;
477 UARRAY_FOREACH(self, i, currChar,
478 UARRAY_FOREACH(fromChars, j, fromChar,
479 if(currChar == fromChar)
481 UARRAY_RAWAT_PUT_(self, i, UARRAY_RAWAT_(toChars, j));
482 break;
488 UArray_error_(self, "UArray_translate unimplemented for this type");
491 size_t UArray_count_(const UArray *self, const UArray *other)
493 long i = 0;
494 size_t count = 0;
496 while ((i = UArray_find_from_(self, other, i)) != -1)
498 i += UArray_size(other);
499 count ++;
502 return count;