1 /*
2 copyright: Steve Dekorte, 2006. All rights reserved.
3 license: See _BSDLicense.txt.
4 */
5 
6 #include "Base.h"
7 
8 #define UArray_C
9 #include "UArray.h"
10 #undef UArray_C
11 
12 #include <string.h>
13 #include <ctype.h>
14 #include <stdlib.h>
15 #include <limits.h>
16 
CTYPE_size(CTYPE type)17 size_t CTYPE_size(CTYPE type)
18 {
19 	switch (type)
20 	{
21 		case CTYPE_uint8_t:   return sizeof(uint8_t);
22 		case CTYPE_uint16_t:  return sizeof(uint16_t);
23 		case CTYPE_uint32_t:  return sizeof(uint32_t);
24 		case CTYPE_uint64_t:  return sizeof(uint64_t);
25 
26 		case CTYPE_int8_t:    return sizeof(int8_t);
27 		case CTYPE_int16_t:   return sizeof(int16_t);
28 		case CTYPE_int32_t:   return sizeof(int32_t);
29 		case CTYPE_int64_t:   return sizeof(int64_t);
30 
31 		case CTYPE_float32_t: return sizeof(float32_t);
32 		case CTYPE_float64_t: return sizeof(float64_t);
33 
34 		case CTYPE_uintptr_t: return sizeof(uintptr_t);
35 	}
36 	return 0;
37 }
38 
CTYPE_name(CTYPE type)39 const char *CTYPE_name(CTYPE type)
40 {
41 	switch (type)
42 	{
43 		case CTYPE_uint8_t:   return "uint8";
44 		case CTYPE_uint16_t:  return "uint16";
45 		case CTYPE_uint32_t:  return "uint32";
46 		case CTYPE_uint64_t:  return "uint64";
47 
48 		case CTYPE_int8_t:    return "int8";
49 		case CTYPE_int16_t:   return "int16";
50 		case CTYPE_int32_t:   return "int32";
51 		case CTYPE_int64_t:   return "int64";
52 
53 		case CTYPE_float32_t: return "float32";
54 		case CTYPE_float64_t: return "float64";
55 
56 		case CTYPE_uintptr_t: return "intptr";
57 	}
58 	return "unknown";
59 }
60 
CTYPE_forName(const char * name)61 int CTYPE_forName(const char *name)
62 {
63 	if(!strcmp(name, "uint8"))   return CTYPE_uint8_t;
64 	if(!strcmp(name, "uint16"))  return CTYPE_uint16_t;
65 	if(!strcmp(name, "uint32"))  return CTYPE_uint32_t;
66 	if(!strcmp(name, "uint64"))  return CTYPE_uint64_t;
67 	if(!strcmp(name, "int8"))    return CTYPE_int8_t;
68 	if(!strcmp(name, "int16"))   return CTYPE_int16_t;
69 	if(!strcmp(name, "int32"))   return CTYPE_int32_t;
70 	if(!strcmp(name, "int64"))   return CTYPE_int64_t;
71 	if(!strcmp(name, "float32")) return CTYPE_float32_t;
72 	if(!strcmp(name, "float64")) return CTYPE_float64_t;
73 	return -1;
74 }
75 
CTYPE_fixedWidthTextEncodingForType(CTYPE type)76 int CTYPE_fixedWidthTextEncodingForType(CTYPE type)
77 {
78 	if(type == CTYPE_int8_t)    return CENCODING_ASCII;
79 	if(type == CTYPE_uint16_t)	return CENCODING_UCS2;
80 	if(type == CTYPE_uint32_t)	return CENCODING_UCS4;
81 	return -1;
82 }
83 
CENCODING_forName(const char * name)84 int CENCODING_forName(const char *name)
85 {
86 	if(!strcmp(name, "ascii"))  return CENCODING_ASCII;
87 	if(!strcmp(name, "utf8"))   return CENCODING_UTF8;
88 	if(!strcmp(name, "ucs2"))	return CENCODING_UCS2;
89 	if(!strcmp(name, "ucs4"))	return CENCODING_UCS4;
90 	if(!strcmp(name, "number")) return CENCODING_NUMBER;
91 	return -1;
92 }
93 
CENCODING_isText(CENCODING encoding)94 int CENCODING_isText(CENCODING encoding)
95 {
96 	return encoding != CENCODING_NUMBER;
97 }
98 
CENCODING_name(CENCODING encoding)99 const char *CENCODING_name(CENCODING encoding)
100 {
101 	switch (encoding)
102 	{
103 		case CENCODING_ASCII:  return "ascii";
104 		case CENCODING_UTF8:   return "utf8";
105 		case CENCODING_UCS2:   return "ucs2";
106 		case CENCODING_UCS4:   return "ucs4";
107 		case CENCODING_NUMBER: return "number";
108 	}
109 	return "unknown";
110 }
111 
112 // error
113 
UArray_unsupported_with_(const UArray * self,const char * methodName,const UArray * other)114 void UArray_unsupported_with_(const UArray *self, const char *methodName, const UArray *other)
115 {
116 	//UArray_error_(self, "Error: '%s' not supported between '%s' and '%s'\n");
117 	printf("Error: '%s' not supported between '%s' and '%s'\n",
118 		   methodName, CTYPE_name(self->itemType), CTYPE_name(other->itemType));
119 	exit(-1);
120 }
121 
UArray_error_(const UArray * self,char * e)122 void UArray_error_(const UArray *self, char *e)
123 {
124 	printf("%s\n", e);
125 	exit(-1);
126 }
127 
128 // new
129 
UArray_itemType(const UArray * self)130 CTYPE UArray_itemType(const UArray *self)
131 {
132 	return self->itemType;
133 }
134 
UArray_itemSize(const UArray * self)135 size_t UArray_itemSize(const UArray *self)
136 {
137 	return self->itemSize;
138 }
139 
140 //inline
UArray_sizeRequiredToContain_(const UArray * self,const UArray * other)141 size_t UArray_sizeRequiredToContain_(const UArray *self, const UArray *other)
142 {
143 	return (UArray_sizeInBytes(other)  + self->itemSize - 1) / self->itemSize;
144 }
145 
UArray_rawSetItemType_(UArray * self,CTYPE type)146 void UArray_rawSetItemType_(UArray *self, CTYPE type)
147 {
148 	int itemSize = (int)CTYPE_size(type);
149 	self->itemType = type;
150 	self->itemSize = itemSize;
151 }
152 
UArray_setItemType_(UArray * self,CTYPE type)153 void UArray_setItemType_(UArray *self, CTYPE type)
154 {
155 	int itemSize = (int)CTYPE_size(type);
156 	div_t q = div((int)UArray_sizeInBytes(self), (int)itemSize);
157 
158 	if (q.rem != 0)
159 	{
160 		q.quot += 1;
161 		UArray_setSize_(self, (q.quot * itemSize) / self->itemSize);
162 	}
163 
164 	self->itemType = type;
165 
166 	self->itemSize = itemSize;
167 	self->size = q.quot;
168 
169 	// ensure encoding is sane for type
170 
171 	if (UArray_isFloatType(self))
172 	{
173 		self->encoding = CENCODING_NUMBER;
174 	}
175 	else if (self->encoding == CENCODING_ASCII)
176 	{
177 		switch(self->itemSize)
178 		{
179 			case 2: self->encoding = CENCODING_UCS2; break;
180 			case 4: self->encoding = CENCODING_UCS4; break;
181 			case 8: self->encoding = CENCODING_NUMBER; break;
182 		}
183 	}
184 }
185 
UArray_encoding(const UArray * self)186 CENCODING UArray_encoding(const UArray *self)
187 {
188 	return self->encoding;
189 }
190 
UArray_setEncoding_(UArray * self,CENCODING encoding)191 void UArray_setEncoding_(UArray *self, CENCODING encoding)
192 {
193 	// ensure that size matches new encoding
194 
195 	switch(encoding)
196 	{
197 		case CENCODING_ASCII:
198 		case CENCODING_UTF8:
199 			UArray_setItemType_(self, CTYPE_uint8_t);
200 			break;
201 		case CENCODING_UCS2:
202 			UArray_setItemType_(self, CTYPE_uint16_t);
203 			break;
204 		case CENCODING_UCS4:
205 			UArray_setItemType_(self, CTYPE_uint32_t);
206 			break;
207 		case CENCODING_NUMBER:
208 			// Don't change itemType when setting raw encoding. Raw encoding
209 			// used for vectors and numbers and the item type may have been set
210 			// before this call.
211 			break;
212 	}
213 
214 	self->encoding = encoding;
215 }
216 
UArray_convertToEncoding_(UArray * self,CENCODING encoding)217 void UArray_convertToEncoding_(UArray *self, CENCODING encoding)
218 {
219 	switch(encoding)
220 	{
221 		case CENCODING_ASCII:
222 		case CENCODING_UTF8:
223 			UArray_convertToUTF8(self);
224 			break;
225 		case CENCODING_UCS2:
226 			UArray_convertToUCS2(self);
227 			break;
228 		case CENCODING_UCS4:
229 			UArray_convertToUCS4(self);
230 			break;
231 		case CENCODING_NUMBER:
232 			UArray_setItemType_(self, CTYPE_uint8_t);
233 			break;
234 	}
235 
236 	self->encoding = encoding;
237 	UArray_changed(self);
238 }
239 
UArray_newWithData_type_encoding_size_copy_(void * bytes,CTYPE type,CENCODING encoding,size_t size,int copy)240 UArray *UArray_newWithData_type_encoding_size_copy_(void *bytes, CTYPE type, CENCODING encoding, size_t size, int copy)
241 {
242 	UArray *self = (UArray *)io_calloc(1, sizeof(UArray));
243 	UArray_setData_type_size_copy_(self, bytes, type, size, copy);
244 	self->encoding = encoding;
245 	return self;
246 }
247 
UArray_newWithData_type_size_copy_(void * bytes,CTYPE type,size_t size,int copy)248 UArray *UArray_newWithData_type_size_copy_(void *bytes, CTYPE type, size_t size, int copy)
249 {
250 	UArray *self = (UArray *)io_calloc(1, sizeof(UArray));
251 	UArray_setData_type_size_copy_(self, bytes, type, size, copy);
252 	self->encoding = CENCODING_ASCII;
253 	return self;
254 }
255 
UArray_new(void)256 UArray *UArray_new(void)
257 {
258 	return UArray_newWithData_type_size_copy_("", CTYPE_uint8_t, 0, 1);
259 }
260 
UArray_clone(const UArray * self)261 UArray *UArray_clone(const UArray *self)
262 {
263 	UArray *out = UArray_new();
264 	UArray_copy_(out, self);
265 	return out;
266 }
267 
UArray_show(const UArray * self)268 void UArray_show(const UArray *self)
269 {
270 	printf("UArray_%p %s\t", (void *)self, CTYPE_name(self->itemType));
271 	printf("size: %i ", (int)self->size);
272 	printf("itemSize: %i ", (int)self->itemSize);
273 	printf("data: ");
274 	UArray_print(self);
275 	printf("\n");
276 }
277 
UArray_print(const UArray * self)278 void UArray_print(const UArray *self)
279 {
280 	if(self->encoding == CENCODING_ASCII || self->encoding == CENCODING_UTF8)
281 	{
282 		fwrite(self->data, self->itemSize, self->size, stdout);
283 	}
284 	else if(self->encoding != CENCODING_NUMBER)
285 	{
286 		UARRAY_FOREACH(self, i, v, printf("%c", (int)v); );
287 	}
288 	else if(UArray_isFloatType(self))
289 	{
290 		printf("[");
291 		UARRAY_FOREACH(self, i, v,
292 					printf("%f", (float)v);
293 					if(i != self->size - 1) printf(", ");
294 					);
295 		printf("]");
296 	}
297 	else
298 	{
299 		printf("[");
300 		UARRAY_FOREACH(self, i, v,
301 					printf("%i", (int)v);
302 					if(i != self->size - 1) printf(", ");
303 					);
304 		printf("]");
305 	}
306 }
307 
UArray_stackAllocedWithData_type_size_(void * data,CTYPE type,size_t size)308 UArray UArray_stackAllocedWithData_type_size_(void *data, CTYPE type, size_t size)
309 {
310 	UArray self;
311 	memset(&self, 0, sizeof(UArray));
312 
313 #ifdef UARRAY_DEBUG
314 	self.stackAllocated = 1;
315 #endif
316 
317 	self.itemType = type;
318 	self.itemSize = (int)CTYPE_size(type);
319 	self.size = size;
320 	self.data = data;
321 	return self;
322 }
323 
UArray_stackAllocedEmptyUArray(void)324 BASEKIT_API UArray UArray_stackAllocedEmptyUArray(void)
325 {
326 	UArray self;
327 	memset(&self, 0, sizeof(UArray));
328 
329 #ifdef UARRAY_DEBUG
330 	self.stackAllocated = 1;
331 #endif
332 
333 	self.itemType = CTYPE_int32_t;
334 	self.itemSize = 4;
335 	self.size = 0;
336 	self.data = 0x0;
337 	return self;
338 }
339 
UArray_newWithCString_copy_(char * s,int copy)340 UArray *UArray_newWithCString_copy_(char *s, int copy)
341 {
342 	return UArray_newWithData_type_size_copy_(s, CTYPE_uint8_t, strlen(s), copy);
343 }
344 
UArray_newWithCString_(const char * s)345 UArray *UArray_newWithCString_(const char *s)
346 {
347 	return UArray_newWithData_type_size_copy_((uint8_t *)s, CTYPE_uint8_t, strlen(s), 1);
348 }
349 
UArray_empty(UArray * self)350 void UArray_empty(UArray *self)
351 {
352 	UArray_setSize_(self, 0);
353 }
354 
UArray_setCString_(UArray * self,const char * s)355 void UArray_setCString_(UArray *self, const char *s)
356 {
357 	UArray_empty(self);
358 	UArray_setItemType_(self, CTYPE_uint8_t);
359 	UArray_appendCString_(self, s);
360 }
361 
362 #ifdef UARRAY_DEBUG
UArray_checkIfOkToRelloc(UArray * self)363 void UArray_checkIfOkToRelloc(UArray *self)
364 {
365 	if(self->stackAllocated)
366 	{
367 		printf("UArray debug error: attempt to io_realloc UArray data that this UArray does not own");
368 		exit(-1);
369 	}
370 }
371 #endif
372 
UArray_setData_type_size_copy_(UArray * self,void * data,CTYPE type,size_t size,int copy)373 void UArray_setData_type_size_copy_(UArray *self, void *data, CTYPE type, size_t size, int copy)
374 {
375 	size_t sizeInBytes;
376 
377 	UArray_rawSetItemType_(self, type);
378 	self->size = size;
379 
380 	sizeInBytes = self->size * self->itemSize;
381 
382 #ifdef UARRAY_DEBUG
383 	UArray_checkIfOkToRelloc(self);
384 #endif
385 
386 	if (copy)
387 	{
388 		self->data = io_realloc(self->data, sizeInBytes + 1);
389 		memmove(self->data, data, sizeInBytes);
390 		self->data[sizeInBytes] = 0x0;
391 	}
392 	else
393 	{
394 		if(self->data) free(self->data);
395 		self->data = data;
396 	}
397 
398 }
399 
UArray_stackAllocedWithCString_(char * s)400 UArray UArray_stackAllocedWithCString_(char *s)
401 {
402 	return UArray_stackAllocedWithData_type_size_(s, CTYPE_uint8_t, strlen(s));
403 }
404 
UArray_data(const UArray * self)405 const void *UArray_data(const UArray *self)
406 {
407 	return self->data;
408 }
409 
UArray_bytes(const UArray * self)410 const uint8_t *UArray_bytes(const UArray *self)
411 {
412 	return self->data;
413 }
414 
UArray_mutableBytes(UArray * self)415 uint8_t *UArray_mutableBytes(UArray *self)
416 {
417 	UArray_changed(self);
418 	return self->data;
419 }
420 
UArray_asCString(const UArray * self)421 const char *UArray_asCString(const UArray *self)
422 {
423 	return (const char *)(self->data);
424 }
425 
UArray_stackFree(UArray * self)426 void UArray_stackFree(UArray *self)
427 {
428 	if(self->data) io_free(self->data);
429 }
430 
UArray_free(UArray * self)431 void UArray_free(UArray *self)
432 {
433 	if(self->data) io_free(self->data);
434 	io_free(self);
435 }
436 
437 // size
438 
UArray_setSize_(UArray * self,size_t size)439 void UArray_setSize_(UArray *self, size_t size)
440 {
441 	if (size != self->size)
442 	{
443 		size_t oldSizeInBytes = UArray_sizeInBytes(self);
444 		size_t newSizeInBytes = self->itemSize * size;
445 
446 #ifdef UARRAY_DEBUG
447 			UArray_checkIfOkToRelloc(self);
448 #endif
449 		self->data = io_realloc(self->data, newSizeInBytes + 1);
450 
451 
452 		self->data[newSizeInBytes] = 0x0;
453 		self->size = size;
454 
455 		if (newSizeInBytes > oldSizeInBytes)
456 		{
457 			memset(self->data + oldSizeInBytes, 0, newSizeInBytes - oldSizeInBytes);
458 		}
459 
460 		UArray_changed(self);
461 	}
462 }
463 
UArray_size(const UArray * self)464 size_t UArray_size(const UArray *self)
465 {
466 	return self->size;
467 }
468 
UArray_sizeInBytes(const UArray * self)469 size_t UArray_sizeInBytes(const UArray *self)
470 {
471 	return self->size * self->itemSize;
472 }
473 
UArray_sizeTo_(UArray * self,size_t size)474 void UArray_sizeTo_(UArray *self, size_t size)
475 {
476 	UArray_setSize_(self, size);
477 }
478 
479 // copy
480 
UArray_copy_(UArray * self,const UArray * other)481 void UArray_copy_(UArray *self, const UArray *other)
482 {
483 	UArray_setItemType_(self, UArray_itemType(other));
484 	UArray_setEncoding_(self, UArray_encoding(other));
485 	UArray_setSize_(self, UArray_size(other));
486 	UArray_copyItems_(self, other);
487 }
488 
UArray_copyItems_(UArray * self,const UArray * other)489 void UArray_copyItems_(UArray *self, const UArray *other)
490 {
491 	if(self->size != other->size)
492 	{
493 		printf("UArray_copyItems_ error - arrays not of same size\n");
494 		exit(-1);
495 	}
496 
497 	if(self->itemType == other->itemType)
498 	{
499 		UArray_copyData_(self, other);
500 	}
501 	else
502 	{
503 		DUARRAY_OP(UARRAY_BASICOP_TYPES, =, self, other);
504 	}
505 
506 	UArray_changed(self);
507 }
508 
UArray_copyData_(UArray * self,const UArray * other)509 void UArray_copyData_(UArray *self, const UArray *other)
510 {
511 	UArray_setSize_(self, UArray_sizeRequiredToContain_(self, other));
512 	memmove(self->data, other->data, UArray_sizeInBytes(other));
513 }
514 
UArray_convertToItemType_(UArray * self,CTYPE newItemType)515 void UArray_convertToItemType_(UArray *self, CTYPE newItemType)
516 {
517 	if (self->itemType != newItemType)
518 	{
519 		UArray *tmp = UArray_new();
520 		CENCODING encoding = UArray_encoding(self);
521 		UArray_setItemType_(tmp, newItemType);
522 
523 		if(CENCODING_isText(self->encoding))
524 		{
525 			encoding = CTYPE_fixedWidthTextEncodingForType(newItemType);
526 		}
527 
528 		UArray_setEncoding_(tmp, encoding);
529 		UArray_setSize_(tmp, self->size);
530 		UArray_copyItems_(tmp, self);
531 		UArray_copy_(self, tmp);
532 		UArray_free(tmp);
533 		UArray_changed(self);
534 	}
535 }
536 
537 // slice
538 
UArray_stackRange(const UArray * self,size_t start,size_t size)539 UArray UArray_stackRange(const UArray *self, size_t start, size_t size)
540 {
541 	UArray s;
542 
543 	memcpy(&s, self, sizeof(UArray));
544 	UArray_changed(&s);
545 
546 #ifdef UARRAY_DEBUG
547 	s.stackAllocated = 1;
548 #endif
549 
550 	if(start < self->size || start == 0)
551 	{
552 		s.data = self->data + self->itemSize * start;
553 	}
554 	else
555 	{
556 		s.data = 0x0;
557 	}
558 
559 	if(start + size <= self->size)
560 	{
561 		s.size = size;
562 	}
563 	else
564 	{
565 		s.size = 0;
566 	}
567 
568 	return s;
569 }
570 
UArray_range(const UArray * self,size_t start,size_t size)571 UArray *UArray_range(const UArray *self, size_t start, size_t size)
572 {
573 	UArray out = UArray_stackRange(self, start, size);
574 	return UArray_clone(&out);
575 }
576 
UArray_stackSlice(const UArray * self,long start,long end)577 UArray UArray_stackSlice(const UArray *self, long start, long end)
578 {
579 	start = UArray_wrapPos_(self, start);
580 	end   = UArray_wrapPos_(self, end);
581 	if (end < start) end = start;
582 	return UArray_stackRange(self, start, end - start);
583 }
584 
UArray_slice(const UArray * self,long start,long end)585 BASEKIT_API UArray *UArray_slice(const UArray *self, long start, long end)
586 {
587 	UArray out = UArray_stackSlice(self, start, end);
588 	return UArray_clone(&out);
589 }
590 
591 // at, without bounds check
592 
UArray_rawPointerAt_(const UArray * self,size_t i)593 void *UArray_rawPointerAt_(const UArray *self, size_t i)
594 {
595 	if (self->itemType == CTYPE_uintptr_t)
596 	{
597 		return ((void **)self->data)[i];
598 	}
599 
600 	UArray_error_(self, "UArray_rawPointerAt_ not supported on this type");
601 	return NULL;
602 }
603 
UArray_rawLongAt_(const UArray * self,size_t i)604 long UArray_rawLongAt_(const UArray *self, size_t i)
605 {
606 	UARRAY_RAWAT_(self, i);
607 	UArray_error_(self, "UArray_rawLongAt_ not supported on this type");
608 	return 0;
609 }
610 
UArray_rawDoubleAt_(const UArray * self,size_t i)611 double UArray_rawDoubleAt_(const UArray *self, size_t i)
612 {
613 	UARRAY_RAWAT_(self, i);
614 	UArray_error_(self, "UArray_doubleAt_ not supported on this type");
615 	return 0;
616 }
617 
618 // at, with bounds check
619 
UArray_pointerAt_(const UArray * self,size_t i)620 void *UArray_pointerAt_(const UArray *self, size_t i)
621 {
622 	if (i >= self->size) { return NULL; }
623 	return UArray_rawPointerAt_(self, i);
624 }
625 
UArray_longAt_(const UArray * self,size_t i)626 long UArray_longAt_(const UArray *self, size_t i)
627 {
628 	if (i >= self->size) { return 0; }
629 	return UArray_rawLongAt_(self, i);
630 }
631 
UArray_doubleAt_(const UArray * self,size_t i)632 double UArray_doubleAt_(const UArray *self, size_t i)
633 {
634 	if (i >= self->size) { return 0.0; }
635 	return UArray_rawDoubleAt_(self, i);
636 }
637 
638 // at, extras
639 
UArray_firstLong(const UArray * self)640 long UArray_firstLong(const UArray *self)
641 {
642 	return UArray_rawLongAt_(self, 0);
643 }
644 
UArray_lastLong(const UArray * self)645 long UArray_lastLong(const UArray *self)
646 {
647 	if (!self->size)
648 	{
649 		return 0;
650 	}
651 
652 	return UArray_rawLongAt_(self, self->size - 1);
653 }
654 
655 // remove
656 
UArray_removeRange(UArray * self,size_t start,size_t removeSize)657 void UArray_removeRange(UArray *self, size_t start, size_t removeSize)
658 {
659 	if (start < self->size)
660 	{
661 		if (start + removeSize > self->size)
662 		{
663 			removeSize = self->size - start;
664 		}
665 		else if (start + removeSize < self->size)
666 		{
667 			// need to copy end
668 			size_t remainder = start + removeSize;
669 			size_t remainderSize = self->size - remainder;
670 			memmove(UARRAY_BYTESAT_(self, start), UARRAY_BYTESAT_(self, remainder), self -> itemSize * remainderSize);
671 		}
672 
673 		UArray_setSize_(self, self->size - removeSize);
674 	}
675 	UArray_changed(self);
676 }
677 
UArray_leave_thenRemove_(UArray * self,size_t itemsToLeave,size_t itemsToRemove)678 void UArray_leave_thenRemove_(UArray *self, size_t itemsToLeave, size_t itemsToRemove)
679 {
680 	if (itemsToLeave <= 0)
681 	{
682 		UArray_clear(self);
683 		UArray_setSize_(self, 0);
684 		return;
685 	}
686 
687 	if (itemsToRemove <= 0)
688 	{
689 		return;
690 	}
691 
692 	{
693 		size_t tailChunkSizeInBytes;
694 
695 		size_t period = itemsToLeave + itemsToRemove;
696 		size_t tailItemCount = UArray_size(self) % period;
697 		size_t itemSize = self->itemSize;
698 		size_t chunkSizeInBytes = itemSize * itemsToLeave;
699 
700 		if (tailItemCount == 0)
701 		{
702 			tailChunkSizeInBytes = 0;
703 		}
704 		else if (tailItemCount <= itemsToLeave)
705 		{
706 			tailChunkSizeInBytes = tailItemCount * itemSize;
707 		}
708 		else
709 		{
710 			tailChunkSizeInBytes = chunkSizeInBytes;
711 		}
712 
713 		{
714 			size_t chunkCount = UArray_size(self) / period;
715 			size_t newItemCount = chunkCount * itemsToLeave + tailChunkSizeInBytes / itemSize;
716 			uint8_t *newData = malloc(newItemCount * itemSize);
717 
718 			{
719 				size_t chunkPos;
720 
721 				for (chunkPos = 0; chunkPos < chunkCount; chunkPos++)
722 				{
723 					memmove(newData + chunkPos * chunkSizeInBytes, UARRAY_BYTESAT_(self, chunkPos * period), chunkSizeInBytes);
724 				}
725 
726 				if (tailChunkSizeInBytes)
727 				{
728 					memmove(newData + chunkPos * chunkSizeInBytes, UARRAY_BYTESAT_(self, chunkPos * period), tailChunkSizeInBytes);
729 				}
730 
731 				UArray_setData_type_size_copy_(self, newData, UArray_itemType(self), newItemCount, 0);
732 				UArray_changed(self);
733 			}
734 		}
735 	}
736 }
737 
UArray_removeFirst(UArray * self)738 BASEKIT_API void UArray_removeFirst(UArray *self)
739 {
740 	UArray_removeRange(self, 0, 1);
741 }
742 
UArray_removeLast(UArray * self)743 BASEKIT_API void UArray_removeLast(UArray *self)
744 {
745 	if (self->size > 0)
746 	{
747 		UArray_setSize_(self, self->size - 1);
748 	}
749 }
750 
751 // insert
752 
753 #define UARRAY_RAWAT_PUT_(self, pos, v) \
754 switch (self->itemType)\
755 {\
756 	case CTYPE_uint8_t:   ((uint8_t   *)self->data)[pos] = v; return;\
757 	case CTYPE_uint16_t:  ((uint16_t  *)self->data)[pos] = v; return;\
758 	case CTYPE_uint32_t:  ((uint32_t  *)self->data)[pos] = v; return;\
759 	case CTYPE_uint64_t:  ((uint64_t  *)self->data)[pos] = v; return;\
760 	case CTYPE_int8_t:    ((int8_t    *)self->data)[pos] = v; return;\
761 	case CTYPE_int16_t:   ((int16_t   *)self->data)[pos] = v; return;\
762 	case CTYPE_int32_t:   ((int32_t   *)self->data)[pos] = v; return;\
763 	case CTYPE_int64_t:   ((int64_t   *)self->data)[pos] = v; return;\
764 	case CTYPE_float32_t: ((float32_t *)self->data)[pos] = v; return;\
765 	case CTYPE_float64_t: ((float64_t *)self->data)[pos] = v; return;\
766 	case CTYPE_uintptr_t: ((uintptr_t *)self->data)[pos] = v; return;\
767 }
768 
UArray_at_putLong_(UArray * self,size_t pos,long v)769 void UArray_at_putLong_(UArray *self, size_t pos, long v)
770 {
771 	if (pos >= self->size)
772 	{
773 		UArray_setSize_(self, pos + 1);
774 	}
775 
776 	//if(UArray_longAt_(self, pos) != v)
777 	{
778 		UARRAY_RAWAT_PUT_(self, pos, (uint32_t)v);
779 		UArray_changed(self);
780 	}
781 }
782 
UArray_at_putDouble_(UArray * self,size_t pos,double v)783 void UArray_at_putDouble_(UArray *self, size_t pos, double v)
784 {
785 	if(pos >= self->size) UArray_setSize_(self, pos + 1);
786 
787 	//if(UArray_doubleAt_(self, pos) != v)
788 	{
789 		UARRAY_RAWAT_PUT_(self, pos, v);
790 		UArray_changed(self);
791 	}
792 }
793 
UArray_at_putPointer_(UArray * self,size_t pos,void * v)794 void UArray_at_putPointer_(UArray *self, size_t pos, void *v)
795 {
796 	if (pos >= self->size) UArray_setSize_(self, pos + 1);
797 
798 	switch (self->itemType)
799 	{
800 		case CTYPE_uintptr_t:
801 			if(((void **)self->data)[pos] != v)
802 			{
803 				((void **)self->data)[pos] = v;
804 				UArray_changed(self);
805 			}
806 			return;
807 		default:
808 			UArray_error_(self, "UArray_at_putPointer_ not supported with this type");
809 	}
810 
811 	//UArray_error_(self, "UArray_at_putPointer_ not supported with this type");
812 }
813 
UArray_appendLong_(UArray * self,long v)814 void UArray_appendLong_(UArray *self, long v)
815 {
816 	UArray_at_putLong_(self, self->size, v);
817 }
818 
UArray_appendDouble_(UArray * self,double v)819 void UArray_appendDouble_(UArray *self, double v)
820 {
821 	UArray_at_putDouble_(self, self->size, v);
822 }
823 
UArray_appendPointer_(UArray * self,void * v)824 void UArray_appendPointer_(UArray *self, void *v)
825 {
826 	UArray_at_putPointer_(self, self->size, v);
827 }
828 
UArray_appendBytes_size_(UArray * self,const uint8_t * bytes,size_t size)829 void UArray_appendBytes_size_(UArray *self, const uint8_t *bytes, size_t size)
830 {
831 	UArray a = UArray_stackAllocedWithData_type_size_((uint8_t *)bytes, CTYPE_uint8_t, size);
832 	UArray_append_(self, &a);
833 }
834 
835 /*
836 void UArray_appendByte_(UArray *self, uint8_t byte)
837 {
838 	UArray a = UArray_stackAllocedWithData_type_size_(&byte, CTYPE_uint8_t, 1);
839 	UArray_append_(self, &a);
840 }
841 */
842 
UArray_insert_every_(UArray * self,UArray * other,size_t itemCount)843 void UArray_insert_every_(UArray *self, UArray *other, size_t itemCount)
844 {
845 	UArray *out = UArray_new();
846 	UArray *convertedOther = other;
847 
848 	if (itemCount == 0)
849 	{
850 		UArray_error_(self, "UArray_insert_every_: itemCount must be > 0");
851 		return;
852 	}
853 
854 	if(UArray_itemType(self) != UArray_itemType(other))
855 	{
856 		UArray *convertedOther = UArray_clone(other);
857 		UArray_convertToItemType_(convertedOther, UArray_itemType(self));
858 	}
859 
860 	{
861 		size_t selfSizeInBytes  = UArray_sizeInBytes(self);
862 		size_t otherSize = UArray_size(convertedOther);
863 		size_t chunkSize  = itemCount * UArray_itemSize(self);
864 		size_t i;
865 
866 		for(i = 0; i < selfSizeInBytes; i += chunkSize)
867 		{
868 			if (i + chunkSize > selfSizeInBytes)
869 			{
870 				UArray_appendBytes_size_(out, self->data + i, selfSizeInBytes - i);
871 			}
872 			else
873 			{
874 				UArray_appendBytes_size_(out, self->data + i, chunkSize);
875 				UArray_appendBytes_size_(out, convertedOther->data, otherSize);
876 			}
877 		}
878 	}
879 
880 	if(UArray_itemType(self) != UArray_itemType(other))
881 	{
882 		UArray_free(convertedOther);
883 	}
884 
885 	UArray_copy_(self, out);
886 	UArray_free(out);
887 }
888 
UArray_at_putAll_(UArray * self,size_t pos,const UArray * other)889 void UArray_at_putAll_(UArray *self, size_t pos, const UArray *other)
890 {
891 	if (other->size == 0) return;
892 
893 	if (pos > self->size)
894 	{
895 		UArray_setSize_(self, pos);
896 	}
897 
898 	{
899 		size_t chunkSize = self->size - pos;
900 		size_t originalSelfSize = self->size;
901 
902 		UArray_setSize_(self, self->size + other->size);
903 
904 		{
905 			UArray oldChunk = UArray_stackRange(self, pos, chunkSize);
906 			UArray newChunk = UArray_stackRange(self, pos + other->size, chunkSize);
907 			UArray insertChunk = UArray_stackRange(self, pos, other->size);
908 
909 			if (
910 				//(&newChunk)->data == 0x0 ||
911 				(&insertChunk)->data == 0x0)
912 			{
913 				printf("oldChunk.data     %p size %i\n", (void *)(&oldChunk)->data, (int)oldChunk.size);
914 				printf("newChunk.data     %p size %i\n", (void *)(&newChunk)->data, (int)newChunk.size);
915 				printf("insertChunk.data  %p size %i\n", (void *)(&insertChunk)->data, (int)insertChunk.size);
916 				printf("originalSelfSize = %i\n", (int)originalSelfSize);
917 				printf("self->size  = %i\n", (int)self->size);
918 				printf("other->size = %i\n", (int)other->size);
919 				printf("pos = %i\n", (int)pos);
920 				//exit(-1);
921 
922 				oldChunk = UArray_stackRange(self, pos, chunkSize);
923 				newChunk = UArray_stackRange(self, pos + other->size, chunkSize);
924 				insertChunk = UArray_stackRange(self, pos, other->size);
925 				return;
926 			}
927 
928 			if (newChunk.size) //UArray_copy_(&newChunk, &oldChunk); // copy chunk to end
929 			UArray_copyItems_(&newChunk, &oldChunk);
930 			//UArray_copy_(&insertChunk, other); // insert other
931 			UArray_copyItems_(&insertChunk, other);
932 		}
933 
934 		UArray_changed(self);
935 	}
936 }
937 
938 // compare
939 
940 #define UARRAY_COMPARE_TYPES(OP2, TYPE1, self, TYPE2, other)\
941 {\
942 	size_t i, minSize = self->size < other->size ? self->size : other->size;\
943 	for(i = 0; i < minSize; i ++)\
944 	{\
945 		TYPE1 v1 = ((TYPE1 *)self->data)[i];\
946 		TYPE2 v2 = ((TYPE2 *)other->data)[i];\
947 		if (v1 > v2) return 1;\
948 		if (v1 < v2) return -1;\
949 	}\
950 	if(self->size != other->size)\
951 	{\
952 		return self->size < other->size ? -1 : 1;\
953 	}\
954 	return 0;\
955 }
956 
957 #define UARRAY_EQ_TYPES(OP2, TYPE1, self, TYPE2, other)\
958 {\
959 	size_t i, minSize = self->size < other->size ? self->size : other->size;\
960 	for(i = 0; i < minSize; i ++)\
961 	{\
962 		TYPE1 v1 = ((TYPE1 *)self->data)[i];\
963 		TYPE2 v2 = ((TYPE2 *)other->data)[i];\
964 		if (v1 != v2) return 0;\
965 	}\
966 	return 1;\
967 }
968 
969 #define UARRAY_GT_TYPES(OP2, TYPE1, self, TYPE2, other)\
970 {\
971 	size_t i, minSize = self->size < other->size ? self->size : other->size;\
972 	for(i = 0; i < minSize; i ++)\
973 	{\
974 		TYPE1 v1 = ((TYPE1 *)self->data)[i];\
975 		TYPE2 v2 = ((TYPE2 *)other->data)[i];\
976 		if (v1 < v2) return 0;\
977 	}\
978 	return 1;\
979 }
980 
981 #define UARRAY_LT_TYPES(OP2, TYPE1, self, TYPE2, other)\
982 {\
983 	size_t i, minSize = self->size < other->size ? self->size : other->size;\
984 	for(i = 0; i < minSize; i ++)\
985 	{\
986 		TYPE1 v1 = ((TYPE1 *)self->data)[i];\
987 		TYPE2 v2 = ((TYPE2 *)other->data)[i];\
988 		if (v1 > v2) return 0;\
989 	}\
990 	return 1;\
991 }
992 
UArray_compare_(const UArray * self,const UArray * other)993 int UArray_compare_(const UArray *self, const UArray *other)
994 {
995 	if(self->itemType == CTYPE_uint32_t && other->itemType == CTYPE_uint8_t)
996 	{
997 		size_t i, minSize = self->size < other->size ? self->size : other->size;
998 		for(i = 0; i < minSize; i ++)
999 		{
1000 			uint32_t v1 = ((uint32_t *)self->data)[i];
1001 			uint8_t v2 = ((uint8_t *)other->data)[i];
1002 			if (v1 > v2) return 1;
1003 			if (v1 < v2) return -1;
1004 		}
1005 		if(self->size != other->size)
1006 		{
1007 			return self->size < other->size ? -1 : 1;
1008 		}
1009 	}
1010 	else
1011 	{
1012 		DUARRAY_OP(UARRAY_COMPARE_TYPES, NULL, self, other);
1013 	}
1014 
1015 	return 0;
1016 }
1017 
UArray_equals_(const UArray * self,const UArray * other)1018 int UArray_equals_(const UArray *self, const UArray *other)
1019 {
1020 	if (self->size != other->size) return 0;
1021 	DUARRAY_OP(UARRAY_EQ_TYPES, NULL, self, other);
1022 	return 0;
1023 }
1024 
UArray_greaterThan_(const UArray * self,const UArray * other)1025 int UArray_greaterThan_(const UArray *self, const UArray *other)
1026 {
1027 	if(self->encoding == CENCODING_NUMBER)
1028 	{ DUARRAY_OP(UARRAY_GT_TYPES, NULL, self, other); }
1029 
1030 	return UArray_compare_(self, other) > 0;
1031 }
1032 
UArray_lessThan_(const UArray * self,const UArray * other)1033 int UArray_lessThan_(const UArray *self, const UArray *other)
1034 {
1035 	if(self->encoding == CENCODING_NUMBER)
1036 	{ DUARRAY_OP(UARRAY_LT_TYPES, NULL, self, other); }
1037 
1038 	return UArray_compare_(self, other) < 0;
1039 }
1040 
UArray_greaterThanOrEqualTo_(const UArray * self,const UArray * other)1041 int UArray_greaterThanOrEqualTo_(const UArray *self, const UArray *other)
1042 {
1043 	if(self->encoding == CENCODING_NUMBER)
1044 	{
1045 		if (UArray_greaterThan_(self, other) | UArray_equals_(self, other))
1046 		{ return 1; } else { return 0; }
1047 	}
1048 
1049 	return UArray_compare_(self, other) >= 0;
1050 }
1051 
UArray_lessThanOrEqualTo_(const UArray * self,const UArray * other)1052 int UArray_lessThanOrEqualTo_(const UArray *self, const UArray *other)
1053 {
1054 	if(self->encoding == CENCODING_NUMBER)
1055 	{
1056 		if (UArray_lessThan_(self, other) | UArray_equals_(self, other))
1057 		{ return 1; } else { return 0; }
1058 	}
1059 
1060 	return UArray_compare_(self, other) <= 0;
1061 }
1062 
UArray_isZero(const UArray * self)1063 int UArray_isZero(const UArray *self)
1064 {
1065 	UARRAY_FOREACH(self, i, v, if (v) return 0;)
1066 	return 1;
1067 }
1068 
1069 // find
1070 
1071 // printf("i %i %c j %i %c\n", i, v1, j, v2);\
1072 // printf("j%i == %i\n", i, other->size);\
1073 
1074 #define UARRAY_FIND_TYPES(OP2, TYPE1, self, TYPE2, other)\
1075 {\
1076 	size_t i;\
1077 			if((self->size < other->size) || (self->size == 0)) return -1;\
1078 			for(i = 0; i < self->size - other->size + 1; i ++)\
1079 			{\
1080 				size_t j;\
1081 					int match = 1;\
1082 					for(j = 0; j < other->size; j ++)\
1083 					{\
1084 						TYPE1 v1 = ((TYPE1 *)self->data)[i + j];\
1085 							TYPE2 v2 = ((TYPE2 *)other->data)[j];\
1086 								if (v1 != v2) { match = 0; break; }\
1087 					}\
1088 					if (match) return i;\
1089 			}\
1090 			return -1;\
1091 }
1092 
UArray_find_(const UArray * self,const UArray * other)1093 long UArray_find_(const UArray *self, const UArray *other)
1094 {
1095 	DUARRAY_OP(UARRAY_FIND_TYPES, NULL, self, other);
1096 	return -1;
1097 }
1098 
UArray_contains_(const UArray * self,const UArray * other)1099 int UArray_contains_(const UArray *self, const UArray *other)
1100 {
1101 	return UArray_find_(self, other) != -1;
1102 }
1103 
UArray_find_from_(const UArray * self,const UArray * other,size_t from)1104 long UArray_find_from_(const UArray *self, const UArray *other, size_t from)
1105 {
1106 	UArray s;
1107 	long i;
1108 	if (self->size < from) return -1;
1109 	s = UArray_stackRange(self, from, self->size - from);
1110 	i = UArray_find_(&s, other);
1111 	return i == -1 ? -1 : from + i;
1112 }
1113 
1114 #define UARRAY_FINDANYCASE_TYPES(OP2, TYPE1, self, TYPE2, other)\
1115 {\
1116 	size_t i;\
1117 		if(self->size < other->size) return -1;\
1118 			for(i = 0; i < self->size - other->size + 1; i ++)\
1119 			{\
1120 				size_t j;\
1121 				int match = 1;\
1122 					for(j = 0; j < other->size; j ++)\
1123 					{\
1124 						TYPE1 v1 = ((TYPE1 *)self->data)[i + j];\
1125 						TYPE2 v2 = ((TYPE2 *)other->data)[j];\
1126 						if (tolower((int)v1) != tolower((int)v2)) { match = 0; break; }\
1127 					}\
1128 					if(match) { return i; }\
1129 			}\
1130 			return -1;\
1131 }
1132 
UArray_findAnyCase_(const UArray * self,const UArray * other)1133 long UArray_findAnyCase_(const UArray *self, const UArray *other)
1134 {
1135 	DUARRAY_OP(UARRAY_FINDANYCASE_TYPES, NULL, self, other);
1136 	return -1;
1137 }
1138 
UArray_containsAnyCase_(const UArray * self,const UArray * other)1139 int UArray_containsAnyCase_(const UArray *self, const UArray *other)
1140 {
1141 	long i = UArray_findAnyCase_(self, other);
1142 	return i != -1;
1143 }
1144 
UArray_findLongValue_(const UArray * self,long value)1145 long UArray_findLongValue_(const UArray *self, long value)
1146 {
1147 	UARRAY_FOREACH(self, i, v, if(v == value) return i);
1148 	return -1;
1149 }
1150 
UArray_containsLong_(const UArray * self,long value)1151 int UArray_containsLong_(const UArray *self, long value)
1152 {
1153 	return UArray_findLongValue_(self, value) != -1;
1154 }
1155 
UArray_findDoubleValue_(const UArray * self,double value)1156 long UArray_findDoubleValue_(const UArray *self, double value)
1157 {
1158 	UARRAY_FOREACH(self, i, v, if(v == value) return i);
1159 	return -1;
1160 }
1161 
UArray_containsDouble_(const UArray * self,double value)1162 int UArray_containsDouble_(const UArray *self, double value)
1163 {
1164 	return UArray_findDoubleValue_(self, value) != -1;
1165 }
1166 
1167 #define UARRAY_RFIND_TYPES(OP2, TYPE1, self, TYPE2, other)\
1168 {\
1169 	long i, j;\
1170 		if(self->size < other->size) return -1;\
1171 			for(i = self->size - other->size + 1; i > -1; i --)\
1172 			{\
1173 				int match = 1;\
1174 				for(j = 0; j < other->size; j ++)\
1175 				{\
1176 					TYPE1 v1 = ((TYPE1 *)self->data)[i+j];\
1177 						TYPE2 v2 = ((TYPE2 *)other->data)[j];\
1178 							if (v1 != v2) { match = 0; break; }\
1179 				}\
1180 				if(match) { return i;}\
1181 			}\
1182 			return -1;\
1183 }
1184 
UArray_rFind_(const UArray * self,const UArray * other)1185 long UArray_rFind_(const UArray *self, const UArray *other)
1186 {
1187 	DUARRAY_OP(UARRAY_RFIND_TYPES, NULL, self, other);
1188 	return -1;
1189 }
1190 
UArray_rFind_from_(const UArray * self,const UArray * other,size_t from)1191 BASEKIT_API long UArray_rFind_from_(const UArray *self, const UArray *other, size_t from)
1192 {
1193 	UArray s = UArray_stackRange(self, 0, from);
1194 	long i = UArray_rFind_(&s, other);
1195 	return i;
1196 }
1197 
1198 #define UARRAY_RFINDANYCASE_TYPES(OP2, TYPE1, self, TYPE2, other)\
1199 {\
1200 	size_t i, j;\
1201 		if(self->size < other->size) return -1;\
1202 			for(i = self->size - other->size + 1; i > -1; i --)\
1203 			{\
1204 				int match = 1;\
1205 				for(j = 0; j < other->size; j ++)\
1206 				{\
1207 					int v1 = (int)((TYPE1 *)self->data)[i+j];\
1208 						int v2 = (int)((TYPE2 *)other->data)[j];\
1209 							if (tolower(v1) != tolower(v2)) { match = 0; break; }\
1210 				}\
1211 				if(match) return i;\
1212 			}\
1213 			return -1;\
1214 }
1215 
UArray_rFindAnyCase_(const UArray * self,const UArray * other)1216 long UArray_rFindAnyCase_(const UArray *self, const UArray *other)
1217 {
1218 	DUARRAY_OP(UARRAY_RFINDANYCASE_TYPES, NULL, self, other);
1219 	return -1;
1220 }
1221 
1222 #define UARRAY_RFINDANYVALUE_TYPES(OP2, TYPE1, self, TYPE2, other)\
1223 {\
1224 	long i, j;\
1225 		if(self->size < other->size) return -1;\
1226 			for(i = self->size - 1; i > -1; i --)\
1227 			{\
1228 				TYPE1 v1 = ((TYPE1 *)self->data)[i];\
1229 				for(j = 0; j < other->size; j ++)\
1230 				{\
1231 					TYPE2 v2 = ((TYPE2 *)other->data)[j];\
1232 					if (v1 == v2) { return i; }\
1233 				}\
1234 			}\
1235 			return -1;\
1236 }
1237 
UArray_rFindAnyValue_(const UArray * self,const UArray * other)1238 long UArray_rFindAnyValue_(const UArray *self, const UArray *other)
1239 {
1240 	DUARRAY_OP(UARRAY_RFINDANYVALUE_TYPES, NULL, self, other);
1241 	return -1;
1242 }
1243 
1244 // types
1245 
UArray_isFloatType(const UArray * self)1246 int UArray_isFloatType(const UArray *self)
1247 {
1248 	return self->itemType == CTYPE_float32_t || self->itemType == CTYPE_float64_t;
1249 }
1250 
UArray_isSignedType(const UArray * self)1251 int UArray_isSignedType(const UArray *self)
1252 {
1253 	switch (self->itemType)
1254 	{
1255 		case CTYPE_uint8_t:   return 0;
1256 		case CTYPE_uint16_t:  return 0;
1257 		case CTYPE_uint32_t:  return 0;
1258 		case CTYPE_uint64_t:  return 0;
1259 		case CTYPE_int8_t:    return 1;
1260 		case CTYPE_int16_t:   return 1;
1261 		case CTYPE_int32_t:   return 1;
1262 		case CTYPE_int64_t:   return 1;
1263 		case CTYPE_float32_t: return 1;
1264 		case CTYPE_float64_t: return 1;
1265 		case CTYPE_uintptr_t: return 0;
1266 	}
1267 	return 0;
1268 }
1269 
UArray_wrapPos_(const UArray * self,long pos)1270 size_t UArray_wrapPos_(const UArray *self, long pos)
1271 {
1272 	long size = self->size;
1273 
1274 	if (pos > size - 1)
1275 	{
1276 		return size;
1277 	}
1278 
1279 	if (pos < 0)
1280 	{
1281 		pos = size + pos;
1282 
1283 		if (pos < 0)
1284 		{
1285 			pos = 0;
1286 		}
1287 	}
1288 
1289 	return pos;
1290 }
1291 
cmp_uint8_t(const uint8_t * a,const uint8_t * b)1292 int cmp_uint8_t (const uint8_t  *a, const uint8_t *b)     { return *a == *b ? 0 : (*a < *b ? -1 : 1); }
cmp_uint16_t(const uint16_t * a,const uint16_t * b)1293 int cmp_uint16_t(const uint16_t *a, const uint16_t *b)    { return *a == *b ? 0 : (*a < *b ? -1 : 1); }
cmp_uint32_t(const uint32_t * a,const uint32_t * b)1294 int cmp_uint32_t(const uint32_t *a, const uint32_t *b)    { return *a == *b ? 0 : (*a < *b ? -1 : 1); }
cmp_uint64_t(const uint64_t * a,const uint64_t * b)1295 int cmp_uint64_t(const uint64_t *a, const uint64_t *b)    { return *a == *b ? 0 : (*a < *b ? -1 : 1); }
1296 
cmp_int8_t(const int8_t * a,const int8_t * b)1297 int cmp_int8_t (const int8_t  *a, const int8_t  *b)       { return *a == *b ? 0 : (*a < *b ? -1 : 1); }
cmp_int16_t(const int16_t * a,const int16_t * b)1298 int cmp_int16_t(const int16_t *a, const int16_t *b)       { return *a == *b ? 0 : (*a < *b ? -1 : 1); }
cmp_int32_t(const int32_t * a,const int32_t * b)1299 int cmp_int32_t(const int32_t *a, const int32_t *b)       { return *a == *b ? 0 : (*a < *b ? -1 : 1); }
cmp_int64_t(const int64_t * a,const int64_t * b)1300 int cmp_int64_t(const int64_t *a, const int64_t *b)       { return *a == *b ? 0 : (*a < *b ? -1 : 1); }
1301 
cmp_float32_t(const float32_t * a,const float32_t * b)1302 int cmp_float32_t(const float32_t *a, const float32_t *b) { return *a == *b ? 0 : (*a < *b ? -1 : 1); }
cmp_float64_t(const float64_t * a,const float64_t * b)1303 int cmp_float64_t(const float64_t *a, const float64_t *b) { return *a == *b ? 0 : (*a < *b ? -1 : 1); }
cmp_uintptr_t(const uintptr_t * a,const uintptr_t * b)1304 int cmp_uintptr_t(const uintptr_t *a, const uintptr_t *b) { return *a == *b ? 0 : (*a < *b ? -1 : 1); }
1305 
UArray_sort(UArray * self)1306 void UArray_sort(UArray *self)
1307 {
1308 	void *base = self->data;
1309 	size_t size = self->size;
1310 
1311 	UArray_changed(self);
1312 
1313 	switch(self->itemType)
1314 	{
1315 		case CTYPE_uint8_t:   qsort(base, size,  sizeof(uint8_t),  (UArraySortCallback *)cmp_uint8_t);   return;
1316 		case CTYPE_uint16_t:  qsort(base, size, sizeof(uint16_t),  (UArraySortCallback *)cmp_uint16_t);  return;
1317 		case CTYPE_uint32_t:  qsort(base, size, sizeof(uint32_t),  (UArraySortCallback *)cmp_uint32_t);  return;
1318 		case CTYPE_uint64_t:  qsort(base, size, sizeof(uint64_t),  (UArraySortCallback *)cmp_uint64_t);  return;
1319 
1320 		case CTYPE_int8_t:    qsort(base, size,  sizeof(int8_t),   (UArraySortCallback *)cmp_int8_t);    return;
1321 		case CTYPE_int16_t:   qsort(base, size, sizeof(int16_t),   (UArraySortCallback *)cmp_int16_t);   return;
1322 		case CTYPE_int32_t:   qsort(base, size, sizeof(int32_t),   (UArraySortCallback *)cmp_int32_t);   return;
1323 		case CTYPE_int64_t:   qsort(base, size, sizeof(int64_t),   (UArraySortCallback *)cmp_int64_t);   return;
1324 
1325 		case CTYPE_float32_t: qsort(base, size, sizeof(float32_t), (UArraySortCallback *)cmp_float32_t); return;
1326 		case CTYPE_float64_t: qsort(base, size, sizeof(float64_t), (UArraySortCallback *)cmp_float64_t); return;
1327 		case CTYPE_uintptr_t: qsort(base, size, sizeof(uintptr_t), (UArraySortCallback *)cmp_uintptr_t); return;
1328 	}
1329 }
1330 
UArray_sortBy_(UArray * self,UArraySortCallback * cmp)1331 void UArray_sortBy_(UArray *self, UArraySortCallback *cmp)
1332 {
1333 	void *base = self->data;
1334 	size_t size = self->size;
1335 
1336 	UArray_changed(self);
1337 
1338 	switch(self->itemType)
1339 	{
1340 		case CTYPE_uint8_t:   qsort(base, size,  sizeof(uint8_t),  cmp); return;
1341 		case CTYPE_uint16_t:  qsort(base, size, sizeof(uint16_t),  cmp); return;
1342 		case CTYPE_uint32_t:  qsort(base, size, sizeof(uint32_t),  cmp); return;
1343 		case CTYPE_uint64_t:  qsort(base, size, sizeof(uint64_t),  cmp); return;
1344 
1345 		case CTYPE_int8_t:    qsort(base, size,  sizeof(int8_t),   cmp); return;
1346 		case CTYPE_int16_t:   qsort(base, size, sizeof(int16_t),   cmp); return;
1347 		case CTYPE_int32_t:   qsort(base, size, sizeof(int32_t),   cmp); return;
1348 		case CTYPE_int64_t:   qsort(base, size, sizeof(int64_t),   cmp); return;
1349 
1350 		case CTYPE_float32_t: qsort(base, size, sizeof(float32_t), cmp); return;
1351 		case CTYPE_float64_t: qsort(base, size, sizeof(float64_t), cmp); return;
1352 		case CTYPE_uintptr_t: qsort(base, size, sizeof(uintptr_t), cmp); return;
1353 	}
1354 }
1355 
1356 
1357