1 #include <inttypes.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <stdint.h>
5 #include <string.h>
6 #include <memory.h>
7 #include "binn.h"
8 #include <ejdb2/iowow/iwutils.h>
9
10 #define INT64_FORMAT PRId64
11 #define UINT64_FORMAT PRIu64
12 #define INT64_HEX_FORMAT PRIx64
13
14 #define UNUSED(x) (void) (x)
15 #define round(dbl) dbl >= 0.0 ? (int) (dbl + 0.5) : ((dbl - (double) (int) dbl) <= -0.5 ? (int) dbl : (int) (dbl - 0.5))
16
17 #define CHUNK_SIZE 256 // 1024
18
19 #define BINN_STRUCT 1
20 #define BINN_BUFFER 2
21
22 void*(*malloc_fn)(size_t len) = malloc;
23 void* (*realloc_fn)(void *ptr, size_t len) = realloc;
24 void (*free_fn)(void *ptr) = free;
25
26 #if defined(__APPLE__) || defined(_WIN32)
27 #define __BIG_ENDIAN 0x1000
28 #define __LITTLE_ENDIAN 0x0001
29 #define __BYTE_ORDER __LITTLE_ENDIAN
30 #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
31 #include <sys/endian.h>
32 #define __BIG_ENDIAN BIG_ENDIAN
33 #define __LITTLE_ENDIAN LITTLE_ENDIAN
34 #define __BYTE_ORDER BYTE_ORDER
35 #elif defined(_AIX)
36 #include <sys/machine.h>
37 #define __BIG_ENDIAN BIG_ENDIAN
38 #define __LITTLE_ENDIAN LITTLE_ENDIAN
39 #define __BYTE_ORDER BYTE_ORDER
40 #else
41 #include <endian.h>
42 #endif
43
44 #ifndef __BYTE_ORDER
45 #error "__BYTE_ORDER not defined"
46 #endif
47 #ifndef __BIG_ENDIAN
48 #error "__BIG_ENDIAN not defined"
49 #endif
50 #ifndef __LITTLE_ENDIAN
51 #error "__LITTLE_ENDIAN not defined"
52 #endif
53 #if __BIG_ENDIAN == __LITTLE_ENDIAN
54 #error "__BIG_ENDIAN == __LITTLE_ENDIAN"
55 #endif
56
57 #if __BYTE_ORDER == __BIG_ENDIAN
58 #define tobe16(x) (x)
59 #define tobe32(x) (x)
60 #define tobe64(x) (x)
61 #else
62 #define tobe16(x) IW_SWAB16(x)
63 #define tobe32(x) IW_SWAB32(x)
64 #define tobe64(x) IW_SWAB64(x)
65 #endif
66
67 #define frombe16 tobe16
68 #define frombe32 tobe32
69 #define frombe64 tobe64
70
71 #ifndef WIN32
72 #define stricmp strcasecmp
73 #define strnicmp strncasecmp
74 #endif
75
binn_set_alloc_functions(void * (* new_malloc)(size_t),void * (* new_realloc)(void *,size_t),void (* new_free)(void *))76 void binn_set_alloc_functions(
77 void*(*new_malloc)(size_t), void*(*new_realloc)(void*, size_t),
78 void (*new_free)(void*)) {
79 malloc_fn = new_malloc;
80 realloc_fn = new_realloc;
81 free_fn = new_free;
82 }
83
binn_malloc(int size)84 ALWAYS_INLINE void *binn_malloc(int size) {
85 return malloc_fn(size);
86 }
87
binn_memdup(const void * src,int size)88 BINN_PRIVATE void *binn_memdup(const void *src, int size) {
89 void *dest;
90 if ((src == NULL) || (size <= 0)) {
91 return NULL;
92 }
93 dest = binn_malloc(size);
94 if (dest == NULL) {
95 return NULL;
96 }
97 memcpy(dest, src, size);
98 return dest;
99 }
100
strlen2(char * str)101 BINN_PRIVATE size_t strlen2(char *str) {
102 if (str == NULL) {
103 return 0;
104 }
105 return strlen(str);
106 }
107
binn_create_type(int storage_type,int data_type_index)108 int binn_create_type(int storage_type, int data_type_index) {
109 if (data_type_index < 0) {
110 return -1;
111 }
112 if ((storage_type < BINN_STORAGE_MIN) || (storage_type > BINN_STORAGE_MAX)) {
113 return -1;
114 }
115 if (data_type_index < 16) {
116 return storage_type | data_type_index;
117 } else if (data_type_index < 4096) {
118 storage_type |= BINN_STORAGE_HAS_MORE;
119 storage_type <<= 8;
120 data_type_index >>= 4;
121 return storage_type | data_type_index;
122 } else {
123 return -1;
124 }
125 }
126
binn_get_type_info(int long_type,int * pstorage_type,int * pextra_type)127 BOOL binn_get_type_info(int long_type, int *pstorage_type, int *pextra_type) {
128 int storage_type, extra_type;
129 BOOL retval = TRUE;
130
131 again:
132 if (long_type < 0) {
133 goto loc_invalid;
134 } else if (long_type <= 0xff) {
135 storage_type = long_type & BINN_STORAGE_MASK;
136 extra_type = long_type & BINN_TYPE_MASK;
137 } else if (long_type <= 0xffff) {
138 storage_type = long_type & BINN_STORAGE_MASK16;
139 storage_type >>= 8;
140 extra_type = long_type & BINN_TYPE_MASK16;
141 extra_type >>= 4;
142 } else if (long_type & BINN_STORAGE_VIRTUAL) {
143 //storage_type = BINN_STORAGE_VIRTUAL;
144 //extra_type = xxx;
145 long_type &= 0xffff;
146 goto again;
147 } else {
148 loc_invalid:
149 storage_type = -1;
150 extra_type = -1;
151 retval = FALSE;
152 }
153 if (pstorage_type) {
154 *pstorage_type = storage_type;
155 }
156 if (pextra_type) {
157 *pextra_type = extra_type;
158 }
159 return retval;
160 }
161
binn_create(binn * item,int type,int size,void * pointer)162 BOOL binn_create(binn *item, int type, int size, void *pointer) {
163 BOOL retval = FALSE;
164
165 switch (type) {
166 case BINN_LIST:
167 case BINN_MAP:
168 case BINN_OBJECT:
169 break;
170 default:
171 goto loc_exit;
172 }
173 if ((item == NULL) || (size < 0)) {
174 goto loc_exit;
175 }
176 if (size < MIN_BINN_SIZE) {
177 if (pointer) {
178 goto loc_exit;
179 } else {
180 size = 0;
181 }
182 }
183 memset(item, 0, sizeof(binn));
184
185 if (pointer) {
186 item->pre_allocated = TRUE;
187 item->pbuf = pointer;
188 item->alloc_size = size;
189 } else {
190 item->pre_allocated = FALSE;
191 if (size == 0) {
192 size = CHUNK_SIZE;
193 }
194 pointer = binn_malloc(size);
195 if (pointer == 0) {
196 return INVALID_BINN;
197 }
198 item->pbuf = pointer;
199 item->alloc_size = size;
200 }
201
202 item->header = BINN_MAGIC;
203 item->writable = TRUE;
204 item->used_size = MAX_BINN_HEADER; // save space for the header
205 item->type = type;
206 item->dirty = TRUE; // the header is not written to the buffer
207 retval = TRUE;
208
209 loc_exit:
210 return retval;
211 }
212
binn_new(int type,int size,void * pointer)213 binn *binn_new(int type, int size, void *pointer) {
214 binn *item;
215 item = (binn*) binn_malloc(sizeof(binn));
216 if (binn_create(item, type, size, pointer) == FALSE) {
217 free_fn(item);
218 return NULL;
219 }
220 item->allocated = TRUE;
221 return item;
222 }
223
binn_create_list(binn * list)224 BOOL binn_create_list(binn *list) {
225 return binn_create(list, BINN_LIST, 0, NULL);
226 }
227
binn_create_map(binn * map)228 BOOL binn_create_map(binn *map) {
229 return binn_create(map, BINN_MAP, 0, NULL);
230 }
231
binn_create_object(binn * object)232 BOOL binn_create_object(binn *object) {
233 return binn_create(object, BINN_OBJECT, 0, NULL);
234 }
235
binn_list()236 binn *binn_list() {
237 return binn_new(BINN_LIST, 0, 0);
238 }
239
binn_map()240 binn *binn_map() {
241 return binn_new(BINN_MAP, 0, 0);
242 }
243
binn_object()244 binn *binn_object() {
245 return binn_new(BINN_OBJECT, 0, 0);
246 }
247
binn_load(void * data,binn * value)248 BOOL binn_load(void *data, binn *value) {
249 if ((data == NULL) || (value == NULL)) {
250 return FALSE;
251 }
252 memset(value, 0, sizeof(binn));
253 value->header = BINN_MAGIC;
254 if (binn_is_valid(data, &value->type, &value->count, &value->size) == FALSE) {
255 return FALSE;
256 }
257 value->ptr = data;
258 return TRUE;
259 }
260
binn_open(void * data)261 binn *binn_open(void *data) {
262 binn *item;
263 item = (binn*) binn_malloc(sizeof(binn));
264 if (binn_load(data, item) == FALSE) {
265 free_fn(item);
266 return NULL;
267 }
268 item->allocated = TRUE;
269 return item;
270 }
271
binn_get_ptr_type(const void * ptr)272 BINN_PRIVATE int binn_get_ptr_type(const void *ptr) {
273 if (ptr == NULL) {
274 return 0;
275 }
276 switch (*(const unsigned int*) ptr) {
277 case BINN_MAGIC:
278 return BINN_STRUCT;
279 default:
280 return BINN_BUFFER;
281 }
282 }
283
binn_is_struct(void * ptr)284 BOOL binn_is_struct(void *ptr) {
285 if (ptr == NULL) {
286 return FALSE;
287 }
288 if ((*(unsigned int*) ptr) == BINN_MAGIC) {
289 return TRUE;
290 } else {
291 return FALSE;
292 }
293 }
294
CalcAllocation(int needed_size,int alloc_size)295 BINN_PRIVATE int CalcAllocation(int needed_size, int alloc_size) {
296 int calc_size;
297 calc_size = alloc_size;
298 while (calc_size < needed_size) {
299 calc_size <<= 1; // same as *= 2
300 //calc_size += CHUNK_SIZE; -- this is slower than the above line, because there are more reallocations
301 }
302 return calc_size;
303 }
304
CheckAllocation(binn * item,int add_size)305 BINN_PRIVATE BOOL CheckAllocation(binn *item, int add_size) {
306 int alloc_size;
307 void *ptr;
308 if (item->used_size + add_size > item->alloc_size) {
309 if (item->pre_allocated) {
310 return FALSE;
311 }
312 alloc_size = CalcAllocation(item->used_size + add_size, item->alloc_size);
313 ptr = realloc_fn(item->pbuf, alloc_size);
314 if (ptr == NULL) {
315 return FALSE;
316 }
317 item->pbuf = ptr;
318 item->alloc_size = alloc_size;
319 }
320 return TRUE;
321 }
322
323 #if __BYTE_ORDER == __BIG_ENDIAN
324
get_storage_size(int storage_type)325 BINN_PRIVATE int get_storage_size(int storage_type) {
326 switch (storage_type) {
327 case BINN_STORAGE_NOBYTES:
328 return 0;
329 case BINN_STORAGE_BYTE:
330 return 1;
331 case BINN_STORAGE_WORD:
332 return 2;
333 case BINN_STORAGE_DWORD:
334 return 4;
335 case BINN_STORAGE_QWORD:
336 return 8;
337 default:
338 return 0;
339 }
340 }
341
342 #endif
343
AdvanceDataPos(unsigned char * p,unsigned char * plimit)344 BINN_PRIVATE unsigned char *AdvanceDataPos(unsigned char *p, unsigned char *plimit) {
345 unsigned char byte;
346 int storage_type, dsize;
347 if (p > plimit) {
348 return 0;
349 }
350
351 byte = *p;
352 p++;
353 storage_type = byte & BINN_STORAGE_MASK;
354 if (byte & BINN_STORAGE_HAS_MORE) {
355 p++;
356 }
357
358 switch (storage_type) {
359 case BINN_STORAGE_NOBYTES:
360 break;
361 case BINN_STORAGE_BYTE:
362 p++;
363 break;
364 case BINN_STORAGE_WORD:
365 p += 2;
366 break;
367 case BINN_STORAGE_DWORD:
368 p += 4;
369 break;
370 case BINN_STORAGE_QWORD:
371 p += 8;
372 break;
373 case BINN_STORAGE_BLOB:
374 if (p + sizeof(int) - 1 > plimit) {
375 return 0;
376 }
377 memcpy(&dsize, p, 4);
378 dsize = frombe32(dsize);
379 p += 4 + dsize;
380 break;
381 case BINN_STORAGE_CONTAINER:
382 if (p > plimit) {
383 return 0;
384 }
385 dsize = *((unsigned char*) p);
386 if (dsize & 0x80) {
387 if (p + sizeof(int) - 1 > plimit) {
388 return 0;
389 }
390 memcpy(&dsize, p, 4);
391 dsize = frombe32(dsize);
392 dsize &= 0x7FFFFFFF;
393 }
394 dsize--; // remove the type byte already added before
395 p += dsize;
396 break;
397 case BINN_STORAGE_STRING:
398 if (p > plimit) {
399 return 0;
400 }
401 dsize = *((unsigned char*) p);
402 if (dsize & 0x80) {
403 if (p + sizeof(int) - 1 > plimit) {
404 return 0;
405 }
406 memcpy(&dsize, p, 4);
407 p += 4;
408 dsize = frombe32(dsize);
409 dsize &= 0x7FFFFFFF;
410 } else {
411 p++;
412 }
413 p += dsize;
414 p++; // null terminator.
415 break;
416 default:
417 return 0;
418 }
419 if (p > plimit) {
420 return 0;
421 }
422 return p;
423 }
424
SearchForID(unsigned char * p,int header_size,int size,int numitems,int id)425 BINN_PRIVATE unsigned char *SearchForID(unsigned char *p, int header_size, int size, int numitems, int id) {
426 unsigned char *plimit, *base;
427 int i, int32;
428
429 base = p;
430 plimit = p + size - 1;
431 p += header_size;
432
433 // search for the ID in all the arguments.
434 for (i = 0; i < numitems; i++) {
435 memcpy(&int32, p, 4);
436 p += 4;
437 int32 = frombe32(int32);
438 if (p > plimit) {
439 break;
440 }
441 // Compare if the IDs are equal.
442 if (int32 == id) {
443 return p;
444 }
445 // xxx
446 p = AdvanceDataPos(p, plimit);
447 if ((p == 0) || (p < base)) {
448 break;
449 }
450 }
451 return NULL;
452 }
453
SearchForKey(unsigned char * p,int header_size,int size,int numitems,const char * key,int keylen)454 BINN_PRIVATE unsigned char *SearchForKey(
455 unsigned char *p, int header_size, int size, int numitems, const char *key,
456 int keylen) {
457 unsigned char len, *plimit, *base;
458 int i;
459
460 base = p;
461 plimit = p + size - 1;
462 p += header_size;
463
464 // search for the key in all the arguments.
465 for (i = 0; i < numitems; i++) {
466 len = *((unsigned char*) p);
467 p++;
468 if (p > plimit) {
469 break;
470 }
471 // Compare if the strings are equal.
472 if (len > 0) {
473 if (strnicmp((char*) p, key, len) == 0) { // note that there is no null terminator here
474 if (keylen == len) {
475 p += len;
476 return p;
477 }
478 }
479 p += len;
480 if (p > plimit) {
481 break;
482 }
483 } else if (len == keylen) { // in the case of empty string: ""
484 return p;
485 }
486 // xxx
487 p = AdvanceDataPos(p, plimit);
488 if ((p == 0) || (p < base)) {
489 break;
490 }
491 }
492 return NULL;
493 }
494
495 BINN_PRIVATE BOOL AddValue(binn *item, int type, void *pvalue, int size);
496
binn_list_add_raw(binn * item,int type,void * pvalue,int size)497 BINN_PRIVATE BOOL binn_list_add_raw(binn *item, int type, void *pvalue, int size) {
498 if ((item == NULL) || (item->type != BINN_LIST) || (item->writable == FALSE)) {
499 return FALSE;
500 }
501 //if (CheckAllocation(item, 4) == FALSE) return FALSE; // 4 bytes used for data_store and data_format.
502 if (AddValue(item, type, pvalue, size) == FALSE) {
503 return FALSE;
504 }
505 item->count++;
506 return TRUE;
507 }
508
binn_object_set_raw(binn * item,const char * key,int keylen,int type,void * pvalue,int size)509 BINN_PRIVATE BOOL binn_object_set_raw(binn *item, const char *key, int keylen, int type, void *pvalue, int size) {
510 unsigned char *p, len;
511 int int32 = keylen;
512
513 if ( (key == NULL)
514 || (item == NULL)
515 || (item->type != BINN_OBJECT)
516 || (item->writable == FALSE)
517 || (keylen > 255)) {
518 return FALSE;
519 }
520
521 // is the key already in it?
522 p = SearchForKey(item->pbuf, MAX_BINN_HEADER, item->used_size, item->count, key, keylen);
523 if (p) {
524 return FALSE;
525 }
526
527 // start adding it
528 if (CheckAllocation(item, 1 + int32) == FALSE) {
529 return FALSE; // bytes used for the key size and the key itself.
530 }
531 p = ((unsigned char*) item->pbuf) + item->used_size;
532 len = int32;
533 *p = len;
534 p++;
535 memcpy(p, key, int32);
536 int32++; // now contains the strlen + 1 byte for the len
537 item->used_size += int32;
538
539 if (AddValue(item, type, pvalue, size) == FALSE) {
540 item->used_size -= int32;
541 return FALSE;
542 }
543 item->count++;
544 return TRUE;
545 }
546
binn_map_set_raw(binn * item,int id,int type,void * pvalue,int size)547 BINN_PRIVATE BOOL binn_map_set_raw(binn *item, int id, int type, void *pvalue, int size) {
548 unsigned char *p;
549 int int32;
550
551 if ((item == NULL) || (item->type != BINN_MAP) || (item->writable == FALSE)) {
552 return FALSE;
553 }
554 // is the ID already in it?
555 p = SearchForID(item->pbuf, MAX_BINN_HEADER, item->used_size, item->count, id);
556 if (p) {
557 return FALSE;
558 }
559 if (CheckAllocation(item, 4) == FALSE) {
560 return FALSE; // 4 bytes used for the id.
561 }
562 int32 = tobe32(id);
563 p = ((unsigned char*) item->pbuf) + item->used_size;
564
565 memcpy(p, &int32, 4);
566 item->used_size += 4;
567
568 if (AddValue(item, type, pvalue, size) == FALSE) {
569 item->used_size -= 4;
570 return FALSE;
571 }
572 item->count++;
573 return TRUE;
574 }
575
compress_int(int * pstorage_type,int * ptype,void * psource)576 BINN_PRIVATE void *compress_int(int *pstorage_type, int *ptype, void *psource) {
577 int storage_type, storage_type2, type, type2 = 0;
578 int64 vint = 0;
579 uint64 vuint;
580 char *pvalue;
581 #if __BYTE_ORDER == __BIG_ENDIAN
582 int size1, size2;
583 #endif
584
585 storage_type = *pstorage_type;
586 if (storage_type == BINN_STORAGE_BYTE) {
587 return psource;
588 }
589
590 type = *ptype;
591
592 switch (type) {
593 case BINN_INT64:
594 vint = *(int64*) psource;
595 goto loc_signed;
596 case BINN_INT32:
597 vint = *(int*) psource;
598 goto loc_signed;
599 case BINN_INT16:
600 vint = *(short*) psource;
601 goto loc_signed;
602 case BINN_UINT64:
603 vuint = *(uint64*) psource;
604 goto loc_positive;
605 case BINN_UINT32:
606 vuint = *(unsigned int*) psource;
607 goto loc_positive;
608 case BINN_UINT16:
609 vuint = *(unsigned short*) psource;
610 goto loc_positive;
611 }
612
613 loc_signed:
614 if (vint >= 0) {
615 vuint = vint;
616 goto loc_positive;
617 }
618 //loc_negative:
619 if (vint >= INT8_MIN) {
620 type2 = BINN_INT8;
621 } else if (vint >= INT16_MIN) {
622 type2 = BINN_INT16;
623 } else if (vint >= INT32_MIN) {
624 type2 = BINN_INT32;
625 }
626 goto loc_exit;
627
628 loc_positive:
629 if (vuint <= UINT8_MAX) {
630 type2 = BINN_UINT8;
631 } else if (vuint <= UINT16_MAX) {
632 type2 = BINN_UINT16;
633 } else if (vuint <= UINT32_MAX) {
634 type2 = BINN_UINT32;
635 }
636
637 loc_exit:
638 pvalue = (char*) psource;
639 if ((type2) && (type2 != type)) {
640 *ptype = type2;
641 storage_type2 = binn_get_write_storage(type2);
642 *pstorage_type = storage_type2;
643 #if __BYTE_ORDER == __BIG_ENDIAN
644 size1 = get_storage_size(storage_type);
645 size2 = get_storage_size(storage_type2);
646 pvalue += (size1 - size2);
647 #endif
648 }
649 return pvalue;
650 }
651
652 BINN_PRIVATE int type_family(int type);
653
AddValue(binn * item,int type,void * pvalue,int size)654 BINN_PRIVATE BOOL AddValue(binn *item, int type, void *pvalue, int size) {
655 int32_t argsz, storage_type, extra_type;
656 uint16_t su;
657 uint32_t lu;
658 uint64_t llu;
659
660 unsigned char *p, *ptr;
661
662 binn_get_type_info(type, &storage_type, &extra_type);
663
664 if (pvalue == NULL) {
665 switch (storage_type) {
666 case BINN_STORAGE_NOBYTES:
667 break;
668 case BINN_STORAGE_BLOB:
669 case BINN_STORAGE_STRING:
670 if (size == 0) {
671 break; // the 2 above are allowed to have 0 length
672 }
673 default:
674 return FALSE;
675 }
676 }
677
678 if (type_family(type) == BINN_FAMILY_INT) {
679 pvalue = compress_int(&storage_type, &type, pvalue);
680 }
681
682 switch (storage_type) {
683 case BINN_STORAGE_NOBYTES:
684 size = 0;
685 argsz = size;
686 break;
687 case BINN_STORAGE_BYTE:
688 size = 1;
689 argsz = size;
690 break;
691 case BINN_STORAGE_WORD:
692 size = 2;
693 argsz = size;
694 break;
695 case BINN_STORAGE_DWORD:
696 size = 4;
697 argsz = size;
698 break;
699 case BINN_STORAGE_QWORD:
700 size = 8;
701 argsz = size;
702 break;
703 case BINN_STORAGE_BLOB:
704 if (size < 0) {
705 return FALSE;
706 }
707 //if (size == 0) ...
708 argsz = size + 4;
709 break;
710 case BINN_STORAGE_STRING:
711 if (size < 0) {
712 return FALSE;
713 }
714 if (size == 0) {
715 size = strlen2((char*) pvalue);
716 }
717 argsz = size + 5; // at least this size
718 break;
719 case BINN_STORAGE_CONTAINER:
720 if (size <= 0) {
721 return FALSE;
722 }
723 argsz = size;
724 break;
725 default:
726 return FALSE;
727 }
728
729 argsz += 2; // at least 2 bytes used for data_type.
730 if (CheckAllocation(item, argsz) == FALSE) {
731 return FALSE;
732 }
733
734 // Gets the pointer to the next place in buffer
735 p = ((unsigned char*) item->pbuf) + item->used_size;
736
737 // If the data is not a container, store the data type
738 if (storage_type != BINN_STORAGE_CONTAINER) {
739 ptr = (unsigned char*) &type;
740 if (type > 255) {
741 type = tobe16(type); // correct the endianess, if needed
742 *p = *ptr;
743 p++;
744 item->used_size++;
745 ptr++;
746 }
747 *p = *ptr;
748 p++;
749 item->used_size++;
750 }
751
752 switch (storage_type) {
753 case BINN_STORAGE_NOBYTES:
754 // Nothing to do.
755 break;
756 case BINN_STORAGE_BYTE:
757 *((char*) p) = *((char*) pvalue);
758 item->used_size += 1;
759 break;
760 case BINN_STORAGE_WORD:
761 su = *((uint16_t*) pvalue);
762 su = tobe16(su);
763 memcpy(p, &su, 2);
764 item->used_size += 2;
765 break;
766 case BINN_STORAGE_DWORD:
767 lu = *((uint32_t*) pvalue);
768 lu = tobe32(lu);
769 memcpy(p, &lu, 4);
770 item->used_size += 4;
771 break;
772 case BINN_STORAGE_QWORD:
773 // is there an htond or htonq to be used with qwords? (64 bits)
774 llu = *((uint64_t*) pvalue);
775 llu = tobe64(llu);
776 memcpy(p, &llu, 8);
777 item->used_size += 8;
778 break;
779 case BINN_STORAGE_BLOB:
780 lu = tobe32(size);
781 memcpy(p, &lu, 4);
782 p += 4;
783 memcpy(p, pvalue, size);
784 item->used_size += 4 + size;
785 break;
786 case BINN_STORAGE_STRING:
787 if (size > 127) {
788 lu = size | 0x80000000;
789 lu = tobe32(lu);
790 memcpy(p, &lu, 4);
791 p += 4;
792 item->used_size += 4;
793 } else {
794 *((unsigned char*) p) = size;
795 p++;
796 item->used_size++;
797 }
798 memcpy(p, pvalue, size);
799 p += size;
800 *((char*) p) = (char) 0;
801 size++; // null terminator
802 item->used_size += size;
803 break;
804 case BINN_STORAGE_CONTAINER:
805 memcpy(p, pvalue, size);
806 item->used_size += size;
807 break;
808 }
809 item->dirty = TRUE;
810 return TRUE;
811 }
812
binn_save_header(binn * item)813 BOOL binn_save_header(binn *item) {
814 unsigned char byte, *p;
815 int int32, size;
816 if (item == NULL) {
817 return FALSE;
818 }
819
820 #ifndef BINN_DISABLE_SMALL_HEADER
821
822 p = ((unsigned char*) item->pbuf) + MAX_BINN_HEADER;
823 size = item->used_size - MAX_BINN_HEADER + 3; // at least 3 bytes for the header
824
825 // write the count
826 if (item->count > 127) {
827 p -= 4;
828 size += 3;
829 int32 = item->count | 0x80000000;
830 int32 = tobe32(int32);
831 memcpy(p, &int32, 4);
832 } else {
833 p--;
834 *p = (unsigned char) item->count;
835 }
836
837 // write the size
838 if (size > 127) {
839 p -= 4;
840 size += 3;
841 int32 = size | 0x80000000;
842 int32 = tobe32(int32);
843 memcpy(p, &int32, 4);
844 } else {
845 p--;
846 *p = (unsigned char) size;
847 }
848
849 // write the type.
850 p--;
851 *p = (unsigned char) item->type;
852
853 // set the values
854 item->ptr = p;
855 item->size = size;
856
857 UNUSED(byte);
858
859 #else
860
861 p = (unsigned char*) item->pbuf;
862
863 // write the type.
864 byte = item->type;
865 *p = byte;
866 p++;
867 // write the size
868 int32 = item->used_size | 0x80000000;
869 int32 = tobe32(int32);
870 memcpy(p, &int32, 4);
871 p += 4;
872 // write the count
873 int32 = item->count | 0x80000000;
874 int32 = tobe32(int32);
875 memcpy(p, &int32, 4);
876
877 item->ptr = item->pbuf;
878 item->size = item->used_size;
879
880 #endif
881
882 item->dirty = FALSE;
883 return TRUE;
884 }
885
binn_free(binn * item)886 void binn_free(binn *item) {
887 if (item == NULL) {
888 return;
889 }
890 if (item->userdata_freefn) {
891 item->userdata_freefn(item->user_data);
892 item->userdata_freefn = 0;
893 }
894 if ((item->writable) && (item->pre_allocated == FALSE)) {
895 free_fn(item->pbuf);
896 }
897 if (item->freefn) {
898 item->freefn(item->ptr);
899 }
900 if (item->allocated) {
901 free_fn(item);
902 } else {
903 memset(item, 0, sizeof(binn));
904 item->header = BINN_MAGIC;
905 }
906 }
907
908 // free the binn structure but keeps the binn buffer allocated, returning a pointer to it. use the free function to
909 // release the buffer later
binn_release(binn * item)910 void *binn_release(binn *item) {
911 void *data;
912 if (item == NULL) {
913 return NULL;
914 }
915 data = binn_ptr(item);
916 if (data > item->pbuf) {
917 memmove(item->pbuf, data, item->size);
918 data = item->pbuf;
919 }
920 if (item->allocated) {
921 free_fn(item);
922 } else {
923 memset(item, 0, sizeof(binn));
924 item->header = BINN_MAGIC;
925 }
926 return data;
927 }
928
IsValidBinnHeader(const void * pbuf,int * ptype,int * pcount,int * psize,int * pheadersize)929 BINN_PRIVATE BOOL IsValidBinnHeader(const void *pbuf, int *ptype, int *pcount, int *psize, int *pheadersize) {
930 const unsigned char *p, *plimit = 0;
931 unsigned char byte;
932 int int32, type, size, count;
933 if (pbuf == NULL) {
934 return FALSE;
935 }
936 p = (const unsigned char*) pbuf;
937 if (psize && (*psize > 0)) {
938 plimit = p + *psize - 1;
939 }
940 // get the type
941 byte = *p;
942 p++;
943 if ((byte & BINN_STORAGE_MASK) != BINN_STORAGE_CONTAINER) {
944 return FALSE;
945 }
946 if (byte & BINN_STORAGE_HAS_MORE) {
947 return FALSE;
948 }
949 type = byte;
950
951 switch (type) {
952 case BINN_LIST:
953 case BINN_MAP:
954 case BINN_OBJECT:
955 break;
956 default:
957 return FALSE;
958 }
959
960 // get the size
961 if (plimit && (p > plimit)) {
962 return FALSE;
963 }
964 int32 = *((const unsigned char*) p);
965 if (int32 & 0x80) {
966 if (plimit && (p + sizeof(int) - 1 > plimit)) {
967 return FALSE;
968 }
969 memcpy(&int32, p, 4);
970 p += 4;
971 int32 = frombe32(int32);
972 int32 &= 0x7FFFFFFF;
973 } else {
974 p++;
975 }
976 size = int32;
977
978 // get the count
979 if (plimit && (p > plimit)) {
980 return FALSE;
981 }
982 int32 = *((const unsigned char*) p);
983 if (int32 & 0x80) {
984 if (plimit && (p + sizeof(int) - 1 > plimit)) {
985 return FALSE;
986 }
987 memcpy(&int32, p, 4);
988 p += 4;
989 int32 = frombe32(int32);
990 int32 &= 0x7FFFFFFF;
991 } else {
992 p++;
993 }
994 count = int32;
995
996 if (size < MIN_BINN_SIZE) {
997 return FALSE;
998 }
999 // return the values
1000 if (ptype) {
1001 *ptype = type;
1002 }
1003 if (pcount) {
1004 *pcount = count;
1005 }
1006 if (psize && (*psize == 0)) {
1007 *psize = size;
1008 }
1009 if (pheadersize) {
1010 *pheadersize = (int) (p - (const unsigned char*) pbuf);
1011 }
1012 return TRUE;
1013 }
1014
binn_copy(void * old)1015 binn *binn_copy(void *old) {
1016 int type, count, size, header_size;
1017 unsigned char *old_ptr = binn_ptr(old);
1018 binn *item;
1019 size = 0;
1020 if (!IsValidBinnHeader(old_ptr, &type, &count, &size, &header_size)) {
1021 return NULL;
1022 }
1023 item = binn_new(type, size - header_size + MAX_BINN_HEADER, NULL);
1024 if (item) {
1025 unsigned char *dest;
1026 dest = ((unsigned char*) item->pbuf) + MAX_BINN_HEADER;
1027 memcpy(dest, old_ptr + header_size, size - header_size);
1028 item->used_size = MAX_BINN_HEADER + size - header_size;
1029 item->count = count;
1030 }
1031 return item;
1032 }
1033
binn_is_valid_header(const void * pbuf,int * ptype,int * pcount,int * psize,int * pheadersize)1034 BOOL binn_is_valid_header(const void *pbuf, int *ptype, int *pcount, int *psize, int *pheadersize) {
1035 return IsValidBinnHeader(pbuf, ptype, pcount, psize, pheadersize);
1036 }
1037
binn_buf_type(const void * pbuf)1038 int binn_buf_type(const void *pbuf) {
1039 int type;
1040 if (!IsValidBinnHeader(pbuf, &type, NULL, NULL, NULL)) {
1041 return INVALID_BINN;
1042 }
1043 return type;
1044 }
1045
binn_buf_count(const void * pbuf)1046 int binn_buf_count(const void *pbuf) {
1047 int nitems;
1048 if (!IsValidBinnHeader(pbuf, NULL, &nitems, NULL, NULL)) {
1049 return 0;
1050 }
1051 return nitems;
1052 }
1053
binn_buf_size(const void * pbuf)1054 int binn_buf_size(const void *pbuf) {
1055 int size = 0;
1056 if (!IsValidBinnHeader(pbuf, NULL, NULL, &size, NULL)) {
1057 return 0;
1058 }
1059 return size;
1060 }
1061
binn_ptr(void * ptr)1062 void *binn_ptr(void *ptr) {
1063 binn *item;
1064 switch (binn_get_ptr_type(ptr)) {
1065 case BINN_STRUCT:
1066 item = (binn*) ptr;
1067 if (item->writable && item->dirty) {
1068 binn_save_header(item);
1069 }
1070 return item->ptr;
1071 case BINN_BUFFER:
1072 return ptr;
1073 default:
1074 return NULL;
1075 }
1076 }
1077
binn_size(void * ptr)1078 int binn_size(void *ptr) {
1079 binn *item;
1080 switch (binn_get_ptr_type(ptr)) {
1081 case BINN_STRUCT:
1082 item = (binn*) ptr;
1083 if (item->writable && item->dirty) {
1084 binn_save_header(item);
1085 }
1086 return item->size;
1087 case BINN_BUFFER:
1088 return binn_buf_size(ptr);
1089 default:
1090 return 0;
1091 }
1092 }
1093
binn_type(void * ptr)1094 int binn_type(void *ptr) {
1095 binn *item;
1096 switch (binn_get_ptr_type(ptr)) {
1097 case BINN_STRUCT:
1098 item = (binn*) ptr;
1099 return item->type;
1100 case BINN_BUFFER:
1101 return binn_buf_type(ptr);
1102 default:
1103 return -1;
1104 }
1105 }
1106
binn_count(void * ptr)1107 int binn_count(void *ptr) {
1108 binn *item;
1109 switch (binn_get_ptr_type(ptr)) {
1110 case BINN_STRUCT:
1111 item = (binn*) ptr;
1112 return item->count;
1113 case BINN_BUFFER:
1114 return binn_buf_count(ptr);
1115 default:
1116 return -1;
1117 }
1118 }
1119
binn_is_valid_ex(void * ptr,int * ptype,int * pcount,int * psize)1120 BOOL binn_is_valid_ex(void *ptr, int *ptype, int *pcount, int *psize) {
1121 int i, type, count, size, header_size;
1122 unsigned char *p, *plimit, *base, len;
1123 void *pbuf;
1124
1125 pbuf = binn_ptr(ptr);
1126 if (pbuf == NULL) {
1127 return FALSE;
1128 }
1129
1130 // is there an informed size?
1131 if (psize && (*psize > 0)) {
1132 size = *psize;
1133 } else {
1134 size = 0;
1135 }
1136 if (!IsValidBinnHeader(pbuf, &type, &count, &size, &header_size)) {
1137 return FALSE;
1138 }
1139 // is there an informed size?
1140 if (psize && (*psize > 0)) {
1141 // is it the same as the one in the buffer?
1142 if (size != *psize) {
1143 return FALSE;
1144 }
1145 }
1146 // is there an informed count?
1147 if (pcount && (*pcount > 0)) {
1148 // is it the same as the one in the buffer?
1149 if (count != *pcount) {
1150 return FALSE;
1151 }
1152 }
1153 // is there an informed type?
1154 if (ptype && (*ptype != 0)) {
1155 // is it the same as the one in the buffer?
1156 if (type != *ptype) {
1157 return FALSE;
1158 }
1159 }
1160 // it could compare the content size with the size informed on the header
1161
1162 p = (unsigned char*) pbuf;
1163 base = p;
1164 plimit = p + size;
1165 p += header_size;
1166
1167 // process all the arguments.
1168 for (i = 0; i < count; i++) {
1169 switch (type) {
1170 case BINN_OBJECT:
1171 // gets the string size (argument name)
1172 len = *p;
1173 p++;
1174 //if (len == 0) goto Invalid;
1175 // increment the used space
1176 p += len;
1177 break;
1178 case BINN_MAP:
1179 // increment the used space
1180 p += 4;
1181 break;
1182 //case BINN_LIST:
1183 // break;
1184 }
1185 // xxx
1186 p = AdvanceDataPos(p, plimit);
1187 if ((p == 0) || (p < base)) {
1188 goto Invalid;
1189 }
1190 }
1191
1192 if (ptype && (*ptype == 0)) {
1193 *ptype = type;
1194 }
1195 if (pcount && (*pcount == 0)) {
1196 *pcount = count;
1197 }
1198 if (psize && (*psize == 0)) {
1199 *psize = size;
1200 }
1201 return TRUE;
1202
1203 Invalid:
1204 return FALSE;
1205 }
1206
binn_is_valid(void * ptr,int * ptype,int * pcount,int * psize)1207 BOOL binn_is_valid(void *ptr, int *ptype, int *pcount, int *psize) {
1208 if (ptype) {
1209 *ptype = 0;
1210 }
1211 if (pcount) {
1212 *pcount = 0;
1213 }
1214 if (psize) {
1215 *psize = 0;
1216 }
1217 return binn_is_valid_ex(ptr, ptype, pcount, psize);
1218 }
1219
1220 /*** INTERNAL FUNCTIONS ****************************************************/
1221
GetValue(unsigned char * p,binn * value)1222 BINN_PRIVATE BOOL GetValue(unsigned char *p, binn *value) {
1223 unsigned char byte;
1224 int data_type, storage_type; //, extra_type;
1225 int datasz;
1226 void *p2;
1227
1228 if (value == NULL) {
1229 return FALSE;
1230 }
1231 memset(value, 0, sizeof(binn));
1232 value->header = BINN_MAGIC;
1233
1234 // saves for use with BINN_STORAGE_CONTAINER
1235 p2 = p;
1236 // read the data type
1237 byte = *p;
1238 p++;
1239 storage_type = byte & BINN_STORAGE_MASK;
1240 if (byte & BINN_STORAGE_HAS_MORE) {
1241 data_type = byte << 8;
1242 byte = *p;
1243 p++;
1244 data_type |= byte;
1245 //extra_type = data_type & BINN_TYPE_MASK16;
1246 } else {
1247 data_type = byte;
1248 //extra_type = byte & BINN_TYPE_MASK;
1249 }
1250
1251 //value->storage_type = storage_type;
1252 value->type = data_type;
1253
1254 switch (storage_type) {
1255 case BINN_STORAGE_NOBYTES:
1256 break;
1257 case BINN_STORAGE_BYTE:
1258 value->vuint8 = *((unsigned char*) p);
1259 value->ptr = p; //value->ptr = &value->vuint8;
1260 break;
1261 case BINN_STORAGE_WORD:
1262 memcpy(&value->vint16, p, 2);
1263 value->vint16 = frombe16(value->vint16);
1264 value->ptr = &value->vint16;
1265 break;
1266 case BINN_STORAGE_DWORD:
1267 memcpy(&value->vint32, p, 4);
1268 value->vint32 = frombe32(value->vint32);
1269 value->ptr = &value->vint32;
1270 break;
1271 case BINN_STORAGE_QWORD:
1272 memcpy(&value->vint64, p, 8);
1273 value->vint64 = frombe64(value->vint64);
1274 value->ptr = &value->vint64;
1275 break;
1276 case BINN_STORAGE_BLOB:
1277 memcpy(&value->size, p, 4);
1278 p += 4;
1279 value->size = frombe32(value->size);
1280 value->ptr = p;
1281 break;
1282 case BINN_STORAGE_CONTAINER:
1283 value->ptr = p2; // <-- it returns the pointer to the container, not the data
1284 if (IsValidBinnHeader(p2, NULL, &value->count, &value->size, NULL) == FALSE) {
1285 return FALSE;
1286 }
1287 break;
1288 case BINN_STORAGE_STRING:
1289 datasz = *((unsigned char*) p);
1290 if (datasz & 0x80) {
1291 memcpy(&datasz, p, 4);
1292 p += 4;
1293 datasz = frombe32(datasz);
1294 datasz &= 0x7FFFFFFF;
1295 } else {
1296 p++;
1297 }
1298 value->size = datasz;
1299 value->ptr = p;
1300 break;
1301 default:
1302 return FALSE;
1303 }
1304
1305 // convert the returned value, if needed
1306 switch (value->type) {
1307 case BINN_TRUE:
1308 value->type = BINN_BOOL;
1309 value->vbool = TRUE;
1310 value->ptr = &value->vbool;
1311 break;
1312 case BINN_FALSE:
1313 value->type = BINN_BOOL;
1314 value->vbool = FALSE;
1315 value->ptr = &value->vbool;
1316 break;
1317 #ifdef BINN_EXTENDED
1318 case BINN_SINGLE_STR:
1319 value->type = BINN_SINGLE;
1320 value->vfloat = (float) atof((const char*) value->ptr); // converts from string to double, and then to float
1321 value->ptr = &value->vfloat;
1322 break;
1323 case BINN_DOUBLE_STR:
1324 value->type = BINN_DOUBLE;
1325 value->vdouble = atof((const char*) value->ptr); // converts from string to double
1326 value->ptr = &value->vdouble;
1327 break;
1328 #endif
1329 /*
1330 case BINN_DECIMAL:
1331 case BINN_CURRENCYSTR:
1332 case BINN_DATE:
1333 case BINN_DATETIME:
1334 case BINN_TIME:
1335 */
1336 }
1337 return TRUE;
1338 }
1339
1340 #if __BYTE_ORDER == __LITTLE_ENDIAN
1341
1342 // on little-endian devices we store the value so we can return a pointer to integers.
1343 // it's valid only for single-threaded apps. multi-threaded apps must use the _get_ functions instead.
1344
1345 binn local_value;
1346
store_value(binn * value)1347 BINN_PRIVATE void *store_value(binn *value) {
1348 memcpy(&local_value, value, sizeof(binn));
1349 switch (binn_get_read_storage(value->type)) {
1350 case BINN_STORAGE_NOBYTES:
1351 // return a valid pointer
1352 case BINN_STORAGE_WORD:
1353 case BINN_STORAGE_DWORD:
1354 case BINN_STORAGE_QWORD:
1355 return &local_value.vint32; // returns the pointer to the converted value, from big-endian to little-endian
1356 }
1357 return value->ptr; // returns from the on stack value to be thread-safe (for list, map, object, string and blob)
1358 }
1359
1360 #endif
1361
1362 /*** READ FUNCTIONS ********************************************************/
1363
binn_object_get_value(void * ptr,const char * key,binn * value)1364 BOOL binn_object_get_value(void *ptr, const char *key, binn *value) {
1365 int type, count, size = 0, header_size;
1366 unsigned char *p;
1367
1368 ptr = binn_ptr(ptr);
1369 if ((ptr == 0) || (key == 0) || (value == 0)) {
1370 return FALSE;
1371 }
1372
1373 // check the header
1374 if (IsValidBinnHeader(ptr, &type, &count, &size, &header_size) == FALSE) {
1375 return FALSE;
1376 }
1377
1378 if (type != BINN_OBJECT) {
1379 return FALSE;
1380 }
1381 if (count == 0) {
1382 return FALSE;
1383 }
1384
1385 p = (unsigned char*) ptr;
1386 p = SearchForKey(p, header_size, size, count, key, strlen(key));
1387 if (p == FALSE) {
1388 return FALSE;
1389 }
1390 return GetValue(p, value);
1391 }
1392
binn_map_get_value(void * ptr,int id,binn * value)1393 BOOL binn_map_get_value(void *ptr, int id, binn *value) {
1394 int type, count, size = 0, header_size;
1395 unsigned char *p;
1396
1397 ptr = binn_ptr(ptr);
1398 if ((ptr == 0) || (value == 0)) {
1399 return FALSE;
1400 }
1401
1402 // check the header
1403 if (IsValidBinnHeader(ptr, &type, &count, &size, &header_size) == FALSE) {
1404 return FALSE;
1405 }
1406
1407 if (type != BINN_MAP) {
1408 return FALSE;
1409 }
1410 if (count == 0) {
1411 return FALSE;
1412 }
1413
1414 p = (unsigned char*) ptr;
1415 p = SearchForID(p, header_size, size, count, id);
1416 if (p == FALSE) {
1417 return FALSE;
1418 }
1419 return GetValue(p, value);
1420 }
1421
binn_list_get_value(void * ptr,int pos,binn * value)1422 BOOL binn_list_get_value(void *ptr, int pos, binn *value) {
1423 int i, type, count, size = 0, header_size;
1424 unsigned char *p, *plimit, *base;
1425
1426 ptr = binn_ptr(ptr);
1427 if ((ptr == 0) || (value == 0)) {
1428 return FALSE;
1429 }
1430
1431 // check the header
1432 if (IsValidBinnHeader(ptr, &type, &count, &size, &header_size) == FALSE) {
1433 return FALSE;
1434 }
1435
1436 if (type != BINN_LIST) {
1437 return FALSE;
1438 }
1439 if (count == 0) {
1440 return FALSE;
1441 }
1442 if ((pos <= 0) | (pos > count)) {
1443 return FALSE;
1444 }
1445 pos--; // convert from base 1 to base 0
1446
1447 p = (unsigned char*) ptr;
1448 base = p;
1449 plimit = p + size;
1450 p += header_size;
1451
1452 for (i = 0; i < pos; i++) {
1453 p = AdvanceDataPos(p, plimit);
1454 if ((p == 0) || (p < base)) {
1455 return FALSE;
1456 }
1457 }
1458 return GetValue(p, value);
1459 }
1460
1461 /*** READ PAIR BY POSITION *************************************************/
1462
binn_read_pair(int expected_type,void * ptr,int pos,int * pid,char * pkey,binn * value)1463 BINN_PRIVATE BOOL binn_read_pair(int expected_type, void *ptr, int pos, int *pid, char *pkey, binn *value) {
1464 int type, count, size = 0, header_size;
1465 int i, int32, id = 0, counter = 0;
1466 unsigned char *p, *plimit, *base, *key = 0, len = 0;
1467
1468 ptr = binn_ptr(ptr);
1469
1470 // check the header
1471 if (IsValidBinnHeader(ptr, &type, &count, &size, &header_size) == FALSE) {
1472 return FALSE;
1473 }
1474
1475 if ((type != expected_type) || (count == 0) || (pos < 1) || (pos > count)) {
1476 return FALSE;
1477 }
1478
1479 p = (unsigned char*) ptr;
1480 base = p;
1481 plimit = p + size - 1;
1482 p += header_size;
1483
1484 for (i = 0; i < count; i++) {
1485 switch (type) {
1486 case BINN_MAP:
1487 memcpy(&int32, p, 4);
1488 p += 4;
1489 int32 = frombe32(int32);
1490 if (p > plimit) {
1491 return FALSE;
1492 }
1493 id = int32;
1494 break;
1495 case BINN_OBJECT:
1496 len = *p;
1497 p++;
1498 if (p > plimit) {
1499 return FALSE;
1500 }
1501 key = p;
1502 p += len;
1503 if (p > plimit) {
1504 return FALSE;
1505 }
1506 break;
1507 }
1508 counter++;
1509 if (counter == pos) {
1510 goto found;
1511 }
1512 //
1513 p = AdvanceDataPos(p, plimit);
1514 if ((p == 0) || (p < base)) {
1515 return FALSE;
1516 }
1517 }
1518 return FALSE;
1519
1520 found:
1521 switch (type) {
1522 case BINN_MAP:
1523 if (pid) {
1524 *pid = id;
1525 }
1526 break;
1527 case BINN_OBJECT:
1528 if (pkey) {
1529 memcpy(pkey, key, len);
1530 pkey[len] = 0;
1531 }
1532 break;
1533 }
1534 return GetValue(p, value);
1535 }
1536
binn_map_get_pair(void * ptr,int pos,int * pid,binn * value)1537 BOOL binn_map_get_pair(void *ptr, int pos, int *pid, binn *value) {
1538 return binn_read_pair(BINN_MAP, ptr, pos, pid, NULL, value);
1539 }
1540
binn_object_get_pair(void * ptr,int pos,char * pkey,binn * value)1541 BOOL binn_object_get_pair(void *ptr, int pos, char *pkey, binn *value) {
1542 return binn_read_pair(BINN_OBJECT, ptr, pos, NULL, pkey, value);
1543 }
1544
binn_map_pair(void * map,int pos,int * pid)1545 binn *binn_map_pair(void *map, int pos, int *pid) {
1546 binn *value;
1547 value = (binn*) binn_malloc(sizeof(binn));
1548 if (binn_read_pair(BINN_MAP, map, pos, pid, NULL, value) == FALSE) {
1549 free_fn(value);
1550 return NULL;
1551 }
1552 value->allocated = TRUE;
1553 return value;
1554 }
1555
binn_object_pair(void * obj,int pos,char * pkey)1556 binn *binn_object_pair(void *obj, int pos, char *pkey) {
1557 binn *value;
1558 value = (binn*) binn_malloc(sizeof(binn));
1559 if (binn_read_pair(BINN_OBJECT, obj, pos, NULL, pkey, value) == FALSE) {
1560 free_fn(value);
1561 return NULL;
1562 }
1563 value->allocated = TRUE;
1564 return value;
1565 }
1566
binn_map_read_pair(void * ptr,int pos,int * pid,int * ptype,int * psize)1567 void *binn_map_read_pair(void *ptr, int pos, int *pid, int *ptype, int *psize) {
1568 binn value;
1569
1570 if (binn_map_get_pair(ptr, pos, pid, &value) == FALSE) {
1571 return NULL;
1572 }
1573 if (ptype) {
1574 *ptype = value.type;
1575 }
1576 if (psize) {
1577 *psize = value.size;
1578 }
1579 #if __BYTE_ORDER == __LITTLE_ENDIAN
1580 return store_value(&value);
1581 #else
1582 return value.ptr;
1583 #endif
1584 }
1585
binn_object_read_pair(void * ptr,int pos,char * pkey,int * ptype,int * psize)1586 void *binn_object_read_pair(void *ptr, int pos, char *pkey, int *ptype, int *psize) {
1587 binn value;
1588
1589 if (binn_object_get_pair(ptr, pos, pkey, &value) == FALSE) {
1590 return NULL;
1591 }
1592 if (ptype) {
1593 *ptype = value.type;
1594 }
1595 if (psize) {
1596 *psize = value.size;
1597 }
1598 #if __BYTE_ORDER == __LITTLE_ENDIAN
1599 return store_value(&value);
1600 #else
1601 return value.ptr;
1602 #endif
1603 }
1604
1605 /*** SEQUENTIAL READ FUNCTIONS *********************************************/
1606
binn_iter_init(binn_iter * iter,void * ptr,int expected_type)1607 BOOL binn_iter_init(binn_iter *iter, void *ptr, int expected_type) {
1608 int type, count, size = 0, header_size;
1609
1610 ptr = binn_ptr(ptr);
1611 if ((ptr == 0) || (iter == 0)) {
1612 return FALSE;
1613 }
1614 memset(iter, 0, sizeof(binn_iter));
1615
1616 // check the header
1617 if (IsValidBinnHeader(ptr, &type, &count, &size, &header_size) == FALSE) {
1618 return FALSE;
1619 }
1620
1621 if (type != expected_type) {
1622 return FALSE;
1623 }
1624 //if (count == 0) return FALSE; -- should not be used
1625
1626 iter->plimit = (unsigned char*) ptr + size - 1;
1627 iter->pnext = (unsigned char*) ptr + header_size;
1628 iter->count = count;
1629 iter->current = 0;
1630 iter->type = type;
1631 return TRUE;
1632 }
1633
binn_list_next(binn_iter * iter,binn * value)1634 BOOL binn_list_next(binn_iter *iter, binn *value) {
1635 unsigned char *pnow;
1636
1637 if ( (iter == 0)
1638 || (iter->pnext == 0)
1639 || (iter->pnext > iter->plimit)
1640 || (iter->current > iter->count)
1641 || (iter->type != BINN_LIST)) {
1642 return FALSE;
1643 }
1644
1645 iter->current++;
1646 if (iter->current > iter->count) {
1647 return FALSE;
1648 }
1649
1650 pnow = iter->pnext;
1651 iter->pnext = AdvanceDataPos(pnow, iter->plimit);
1652 if ((iter->pnext != 0) && (iter->pnext < pnow)) {
1653 return FALSE;
1654 }
1655 return GetValue(pnow, value);
1656 }
1657
binn_read_next_pair(int expected_type,binn_iter * iter,int * pid,char * pkey,binn * value)1658 BINN_PRIVATE BOOL binn_read_next_pair(int expected_type, binn_iter *iter, int *pid, char *pkey, binn *value) {
1659 int int32, id;
1660 unsigned char *p, *key;
1661 unsigned short len;
1662
1663 if ( (iter == 0)
1664 || (iter->pnext == 0)
1665 || (iter->pnext > iter->plimit)
1666 || (iter->current > iter->count)
1667 || (iter->type != expected_type)) {
1668 return FALSE;
1669 }
1670
1671 iter->current++;
1672 if (iter->current > iter->count) {
1673 return FALSE;
1674 }
1675
1676 p = iter->pnext;
1677
1678 switch (expected_type) {
1679 case BINN_MAP:
1680 memcpy(&int32, p, 4);
1681 p += 4;
1682 int32 = frombe32(int32);
1683 if (p > iter->plimit) {
1684 return FALSE;
1685 }
1686 id = int32;
1687 if (pid) {
1688 *pid = id;
1689 }
1690 break;
1691 case BINN_OBJECT:
1692 len = *((unsigned char*) p);
1693 p++;
1694 key = p;
1695 p += len;
1696 if (p > iter->plimit) {
1697 return FALSE;
1698 }
1699 if (pkey) {
1700 memcpy(pkey, key, len);
1701 pkey[len] = 0;
1702 }
1703 break;
1704 }
1705 iter->pnext = AdvanceDataPos(p, iter->plimit);
1706 if ((iter->pnext != 0) && (iter->pnext < p)) {
1707 return FALSE;
1708 }
1709 return GetValue(p, value);
1710 }
1711
binn_read_next_pair2(int expected_type,binn_iter * iter,int * klidx,char ** pkey,binn * value)1712 BOOL binn_read_next_pair2(int expected_type, binn_iter *iter, int *klidx, char **pkey, binn *value) {
1713 int int32, id;
1714 unsigned char *p, *key;
1715 unsigned short len;
1716
1717 if ( (iter == 0)
1718 || (iter->pnext == 0)
1719 || (iter->pnext > iter->plimit)
1720 || (iter->current > iter->count)
1721 || (iter->type != expected_type)) {
1722 return FALSE;
1723 }
1724
1725 iter->current++;
1726 if (iter->current > iter->count) {
1727 return FALSE;
1728 }
1729 if (pkey) {
1730 *pkey = 0;
1731 }
1732 p = iter->pnext;
1733 switch (expected_type) {
1734 case BINN_MAP:
1735 memcpy(&int32, p, 4);
1736 p += 4;
1737 int32 = frombe32(int32);
1738 if (p > iter->plimit) {
1739 return FALSE;
1740 }
1741 id = int32;
1742 if (klidx) {
1743 *klidx = id;
1744 }
1745 break;
1746 case BINN_OBJECT:
1747 len = *p;
1748 p++;
1749 key = p;
1750 p += len;
1751 if (p > iter->plimit) {
1752 return FALSE;
1753 }
1754 if (klidx) {
1755 *klidx = len;
1756 }
1757 if (pkey) {
1758 *pkey = (char*) key;
1759 }
1760 break;
1761 }
1762 iter->pnext = AdvanceDataPos(p, iter->plimit);
1763 if ((iter->pnext != 0) && (iter->pnext < p)) {
1764 return FALSE;
1765 }
1766 return GetValue(p, value);
1767 }
1768
binn_map_next(binn_iter * iter,int * pid,binn * value)1769 BOOL binn_map_next(binn_iter *iter, int *pid, binn *value) {
1770 return binn_read_next_pair(BINN_MAP, iter, pid, NULL, value);
1771 }
1772
binn_object_next(binn_iter * iter,char * pkey,binn * value)1773 BOOL binn_object_next(binn_iter *iter, char *pkey, binn *value) {
1774 return binn_read_next_pair(BINN_OBJECT, iter, NULL, pkey, value);
1775 }
1776
binn_object_next2(binn_iter * iter,char ** pkey,int * klen,binn * value)1777 BOOL binn_object_next2(binn_iter *iter, char **pkey, int *klen, binn *value) {
1778 return binn_read_next_pair2(BINN_OBJECT, iter, klen, pkey, value);
1779 }
1780
binn_list_next_value(binn_iter * iter)1781 binn *binn_list_next_value(binn_iter *iter) {
1782 binn *value;
1783 value = (binn*) binn_malloc(sizeof(binn));
1784 if (binn_list_next(iter, value) == FALSE) {
1785 free_fn(value);
1786 return NULL;
1787 }
1788 value->allocated = TRUE;
1789 return value;
1790 }
1791
binn_map_next_value(binn_iter * iter,int * pid)1792 binn *binn_map_next_value(binn_iter *iter, int *pid) {
1793 binn *value;
1794 value = (binn*) binn_malloc(sizeof(binn));
1795 if (binn_map_next(iter, pid, value) == FALSE) {
1796 free_fn(value);
1797 return NULL;
1798 }
1799 value->allocated = TRUE;
1800 return value;
1801 }
1802
binn_object_next_value(binn_iter * iter,char * pkey)1803 binn *binn_object_next_value(binn_iter *iter, char *pkey) {
1804 binn *value;
1805 value = (binn*) binn_malloc(sizeof(binn));
1806 if (binn_object_next(iter, pkey, value) == FALSE) {
1807 free_fn(value);
1808 return NULL;
1809 }
1810 value->allocated = TRUE;
1811 return value;
1812 }
1813
binn_list_read_next(binn_iter * iter,int * ptype,int * psize)1814 void *binn_list_read_next(binn_iter *iter, int *ptype, int *psize) {
1815 binn value;
1816 if (binn_list_next(iter, &value) == FALSE) {
1817 return NULL;
1818 }
1819 if (ptype) {
1820 *ptype = value.type;
1821 }
1822 if (psize) {
1823 *psize = value.size;
1824 }
1825 #if __BYTE_ORDER == __LITTLE_ENDIAN
1826 return store_value(&value);
1827 #else
1828 return value.ptr;
1829 #endif
1830 }
1831
binn_map_read_next(binn_iter * iter,int * pid,int * ptype,int * psize)1832 void *binn_map_read_next(binn_iter *iter, int *pid, int *ptype, int *psize) {
1833 binn value;
1834 if (binn_map_next(iter, pid, &value) == FALSE) {
1835 return NULL;
1836 }
1837 if (ptype) {
1838 *ptype = value.type;
1839 }
1840 if (psize) {
1841 *psize = value.size;
1842 }
1843 #if __BYTE_ORDER == __LITTLE_ENDIAN
1844 return store_value(&value);
1845 #else
1846 return value.ptr;
1847 #endif
1848 }
1849
binn_object_read_next(binn_iter * iter,char * pkey,int * ptype,int * psize)1850 void *binn_object_read_next(binn_iter *iter, char *pkey, int *ptype, int *psize) {
1851 binn value;
1852
1853 if (binn_object_next(iter, pkey, &value) == FALSE) {
1854 return NULL;
1855 }
1856 if (ptype) {
1857 *ptype = value.type;
1858 }
1859 if (psize) {
1860 *psize = value.size;
1861 }
1862 #if __BYTE_ORDER == __LITTLE_ENDIAN
1863 return store_value(&value);
1864 #else
1865 return value.ptr;
1866 #endif
1867 }
1868
1869 /****** EXTENDED INTERFACE ***********************************************************/
1870 /****** none of the functions above call the functions below *************************/
1871
binn_get_write_storage(int type)1872 int binn_get_write_storage(int type) {
1873 int storage_type;
1874 switch (type) {
1875 case BINN_SINGLE_STR:
1876 case BINN_DOUBLE_STR:
1877 return BINN_STORAGE_STRING;
1878 case BINN_BOOL:
1879 return BINN_STORAGE_NOBYTES;
1880 default:
1881 binn_get_type_info(type, &storage_type, NULL);
1882 return storage_type;
1883 }
1884 }
1885
binn_get_read_storage(int type)1886 int binn_get_read_storage(int type) {
1887 int storage_type;
1888 switch (type) {
1889 #ifdef BINN_EXTENDED
1890 case BINN_SINGLE_STR:
1891 return BINN_STORAGE_DWORD;
1892 case BINN_DOUBLE_STR:
1893 return BINN_STORAGE_QWORD;
1894 #endif
1895 case BINN_BOOL:
1896 case BINN_TRUE:
1897 case BINN_FALSE:
1898 return BINN_STORAGE_DWORD;
1899 default:
1900 binn_get_type_info(type, &storage_type, NULL);
1901 return storage_type;
1902 }
1903 }
1904
GetWriteConvertedData(int * ptype,void ** ppvalue,const int * psize)1905 BINN_PRIVATE BOOL GetWriteConvertedData(int *ptype, void **ppvalue, const int *psize) {
1906 int type;
1907 float f1;
1908 double d1;
1909 char pstr[128];
1910
1911 UNUSED(pstr);
1912 UNUSED(d1);
1913 UNUSED(f1);
1914
1915 type = *ptype;
1916
1917 if (*ppvalue == NULL) {
1918 switch (type) {
1919 case BINN_NULL:
1920 case BINN_TRUE:
1921 case BINN_FALSE:
1922 break;
1923 case BINN_STRING:
1924 case BINN_BLOB:
1925 if (*psize == 0) {
1926 break;
1927 }
1928 default:
1929 return FALSE;
1930 }
1931 }
1932
1933 switch (type) {
1934 #ifdef BINN_EXTENDED
1935 case BINN_SINGLE:
1936 f1 = **(float**) ppvalue;
1937 d1 = f1; // convert from float (32bits) to double (64bits)
1938 type = BINN_SINGLE_STR;
1939 goto conv_double;
1940 case BINN_DOUBLE:
1941 d1 = **(double**) ppvalue;
1942 type = BINN_DOUBLE_STR;
1943 conv_double:
1944 // the '%.17e' is more precise than the '%g'
1945 snprintf(pstr, 127, "%.17e", d1);
1946 *ppvalue = pstr;
1947 *ptype = type;
1948 break;
1949 #endif
1950 case BINN_DECIMAL:
1951 case BINN_CURRENCYSTR:
1952 case BINN_DATE:
1953 case BINN_DATETIME:
1954 case BINN_TIME:
1955 return TRUE;
1956 break;
1957
1958 case BINN_BOOL:
1959 if (**((BOOL**) ppvalue) == FALSE) {
1960 type = BINN_FALSE;
1961 } else {
1962 type = BINN_TRUE;
1963 }
1964 *ptype = type;
1965 break;
1966 }
1967 return TRUE;
1968 }
1969
type_family(int type)1970 BINN_PRIVATE int type_family(int type) {
1971 switch (type) {
1972 case BINN_LIST:
1973 case BINN_MAP:
1974 case BINN_OBJECT:
1975 return BINN_FAMILY_BINN;
1976
1977 case BINN_INT8:
1978 case BINN_INT16:
1979 case BINN_INT32:
1980 case BINN_INT64:
1981 case BINN_UINT8:
1982 case BINN_UINT16:
1983 case BINN_UINT32:
1984 case BINN_UINT64:
1985 return BINN_FAMILY_INT;
1986
1987 case BINN_FLOAT32:
1988 case BINN_FLOAT64:
1989 //case BINN_SINGLE:
1990 case BINN_SINGLE_STR:
1991 //case BINN_DOUBLE:
1992 case BINN_DOUBLE_STR:
1993 return BINN_FAMILY_FLOAT;
1994
1995 case BINN_STRING:
1996 case BINN_HTML:
1997 case BINN_CSS:
1998 case BINN_XML:
1999 case BINN_JSON:
2000 case BINN_JAVASCRIPT:
2001 return BINN_FAMILY_STRING;
2002
2003 case BINN_BLOB:
2004 case BINN_JPEG:
2005 case BINN_GIF:
2006 case BINN_PNG:
2007 case BINN_BMP:
2008 return BINN_FAMILY_BLOB;
2009
2010 case BINN_DECIMAL:
2011 case BINN_CURRENCY:
2012 case BINN_DATE:
2013 case BINN_TIME:
2014 case BINN_DATETIME:
2015 return BINN_FAMILY_STRING;
2016
2017 case BINN_BOOL:
2018 return BINN_FAMILY_BOOL;
2019
2020 case BINN_NULL:
2021 return BINN_FAMILY_NULL;
2022
2023 default:
2024 // if it wasn't found
2025 return BINN_FAMILY_NONE;
2026 }
2027 }
2028
int_type(int type)2029 BINN_PRIVATE int int_type(int type) {
2030 switch (type) {
2031 case BINN_INT8:
2032 case BINN_INT16:
2033 case BINN_INT32:
2034 case BINN_INT64:
2035 return BINN_SIGNED_INT;
2036 case BINN_UINT8:
2037 case BINN_UINT16:
2038 case BINN_UINT32:
2039 case BINN_UINT64:
2040 return BINN_UNSIGNED_INT;
2041 default:
2042 return 0;
2043 }
2044 }
2045
copy_raw_value(const void * psource,void * pdest,int data_store)2046 BINN_PRIVATE BOOL copy_raw_value(const void *psource, void *pdest, int data_store) {
2047 switch (data_store) {
2048 case BINN_STORAGE_NOBYTES:
2049 break;
2050 case BINN_STORAGE_BYTE:
2051 *((char*) pdest) = *(const char*) psource;
2052 break;
2053 case BINN_STORAGE_WORD:
2054 *((short*) pdest) = *(const short*) psource;
2055 break;
2056 case BINN_STORAGE_DWORD:
2057 *((int*) pdest) = *(const int*) psource;
2058 break;
2059 case BINN_STORAGE_QWORD:
2060 *((uint64*) pdest) = *(const uint64*) psource;
2061 break;
2062 case BINN_STORAGE_BLOB:
2063 case BINN_STORAGE_STRING:
2064 case BINN_STORAGE_CONTAINER:
2065 *((const char**) pdest) = (const char*) psource;
2066 break;
2067 default:
2068 return FALSE;
2069 }
2070 return TRUE;
2071 }
2072
copy_int_value(void * psource,void * pdest,int source_type,int dest_type)2073 BINN_PRIVATE BOOL copy_int_value(void *psource, void *pdest, int source_type, int dest_type) {
2074 uint64 vuint64 = 0;
2075 int64 vf64 = 0;
2076 switch (source_type) {
2077 case BINN_INT8:
2078 vf64 = *(signed char*) psource;
2079 break;
2080 case BINN_INT16:
2081 vf64 = *(short*) psource;
2082 break;
2083 case BINN_INT32:
2084 vf64 = *(int*) psource;
2085 break;
2086 case BINN_INT64:
2087 vf64 = *(int64*) psource;
2088 break;
2089 case BINN_UINT8:
2090 vuint64 = *(unsigned char*) psource;
2091 break;
2092 case BINN_UINT16:
2093 vuint64 = *(unsigned short*) psource;
2094 break;
2095 case BINN_UINT32:
2096 vuint64 = *(unsigned int*) psource;
2097 break;
2098 case BINN_UINT64:
2099 vuint64 = *(uint64*) psource;
2100 break;
2101 default:
2102 return FALSE;
2103 }
2104 // copy from int64 to uint64, if possible
2105 if ((int_type(source_type) == BINN_UNSIGNED_INT) && (int_type(dest_type) == BINN_SIGNED_INT)) {
2106 if (vuint64 > INT64_MAX) {
2107 return FALSE;
2108 }
2109 vf64 = vuint64;
2110 } else if ((int_type(source_type) == BINN_SIGNED_INT) && (int_type(dest_type) == BINN_UNSIGNED_INT)) {
2111 if (vf64 < 0) {
2112 return FALSE;
2113 }
2114 vuint64 = (uint64) vf64;
2115 }
2116 switch (dest_type) {
2117 case BINN_INT8:
2118 if ((vf64 < INT8_MIN) || (vf64 > INT8_MAX)) {
2119 return FALSE;
2120 }
2121 *(signed char*) pdest = (signed char) vf64;
2122 break;
2123 case BINN_INT16:
2124 if ((vf64 < INT16_MIN) || (vf64 > INT16_MAX)) {
2125 return FALSE;
2126 }
2127 *(short*) pdest = (short) vf64;
2128 break;
2129 case BINN_INT32:
2130 if ((vf64 < INT32_MIN) || (vf64 > INT32_MAX)) {
2131 return FALSE;
2132 }
2133 *(int*) pdest = (int) vf64;
2134 break;
2135 case BINN_INT64:
2136 *(int64*) pdest = vf64;
2137 break;
2138 case BINN_UINT8:
2139 if (vuint64 > UINT8_MAX) {
2140 return FALSE;
2141 }
2142 *(unsigned char*) pdest = (unsigned char) vuint64;
2143 break;
2144 case BINN_UINT16:
2145 if (vuint64 > UINT16_MAX) {
2146 return FALSE;
2147 }
2148 *(unsigned short*) pdest = (unsigned short) vuint64;
2149 break;
2150 case BINN_UINT32:
2151 if (vuint64 > UINT32_MAX) {
2152 return FALSE;
2153 }
2154 *(unsigned int*) pdest = (unsigned int) vuint64;
2155 break;
2156 case BINN_UINT64:
2157 *(uint64*) pdest = vuint64;
2158 break;
2159 default:
2160 return FALSE;
2161 }
2162 return TRUE;
2163 }
2164
2165 #ifdef IW_TESTS
2166
copy_int_value_tests(void * psource,void * pdest,int source_type,int dest_type)2167 BOOL copy_int_value_tests(void *psource, void *pdest, int source_type, int dest_type) {
2168 return copy_int_value(psource, pdest, source_type, dest_type);
2169 }
2170
2171 #endif
2172
copy_float_value(void * psource,void * pdest,int source_type,int dest_type)2173 BINN_PRIVATE BOOL copy_float_value(void *psource, void *pdest, int source_type, int dest_type) {
2174 switch (source_type) {
2175 case BINN_FLOAT32:
2176 *(double*) pdest = *(float*) psource;
2177 break;
2178 case BINN_FLOAT64:
2179 *(float*) pdest = (float) *(double*) psource;
2180 break;
2181 default:
2182 return FALSE;
2183 }
2184 return TRUE;
2185 }
2186
zero_value(void * pvalue,int type)2187 BINN_PRIVATE void zero_value(void *pvalue, int type) {
2188 switch (binn_get_read_storage(type)) {
2189 case BINN_STORAGE_NOBYTES:
2190 break;
2191 case BINN_STORAGE_BYTE:
2192 memset(pvalue, 0, 1);
2193 break;
2194 case BINN_STORAGE_WORD:
2195 memset(pvalue, 0, 2);
2196 break;
2197 case BINN_STORAGE_DWORD:
2198 memset(pvalue, 0, 4);
2199 break;
2200 case BINN_STORAGE_QWORD:
2201 memset(pvalue, 0, 8);
2202 break;
2203 case BINN_STORAGE_BLOB:
2204 case BINN_STORAGE_STRING:
2205 case BINN_STORAGE_CONTAINER:
2206 *(char**) pvalue = NULL;
2207 break;
2208 }
2209 }
2210
copy_value(void * psource,void * pdest,int source_type,int dest_type,int data_store)2211 BINN_PRIVATE BOOL copy_value(void *psource, void *pdest, int source_type, int dest_type, int data_store) {
2212 if (type_family(source_type) != type_family(dest_type)) {
2213 return FALSE;
2214 }
2215 if ((type_family(source_type) == BINN_FAMILY_INT) && (source_type != dest_type)) {
2216 return copy_int_value(psource, pdest, source_type, dest_type);
2217 } else if ((type_family(source_type) == BINN_FAMILY_FLOAT) && (source_type != dest_type)) {
2218 return copy_float_value(psource, pdest, source_type, dest_type);
2219 } else {
2220 return copy_raw_value(psource, pdest, data_store);
2221 }
2222 }
2223
2224 /*** WRITE FUNCTIONS *****************************************************************/
2225
binn_list_add(binn * list,int type,void * pvalue,int size)2226 BOOL binn_list_add(binn *list, int type, void *pvalue, int size) {
2227 if (GetWriteConvertedData(&type, &pvalue, &size) == FALSE) {
2228 return FALSE;
2229 }
2230 return binn_list_add_raw(list, type, pvalue, size);
2231 }
2232
binn_map_set(binn * map,int id,int type,void * pvalue,int size)2233 BOOL binn_map_set(binn *map, int id, int type, void *pvalue, int size) {
2234 if (GetWriteConvertedData(&type, &pvalue, &size) == FALSE) {
2235 return FALSE;
2236 }
2237 return binn_map_set_raw(map, id, type, pvalue, size);
2238 }
2239
binn_object_set(binn * obj,const char * key,int type,void * pvalue,int size)2240 BOOL binn_object_set(binn *obj, const char *key, int type, void *pvalue, int size) {
2241 if (GetWriteConvertedData(&type, &pvalue, &size) == FALSE) {
2242 return FALSE;
2243 }
2244 return binn_object_set_raw(obj, key, strlen(key), type, pvalue, size);
2245 }
2246
binn_object_set2(binn * obj,const char * key,int keylen,int type,void * pvalue,int size)2247 BOOL binn_object_set2(binn *obj, const char *key, int keylen, int type, void *pvalue, int size) {
2248 if (GetWriteConvertedData(&type, &pvalue, &size) == FALSE) {
2249 return FALSE;
2250 }
2251 return binn_object_set_raw(obj, key, keylen, type, pvalue, size);
2252 }
2253
2254 // this function is used by the wrappers
binn_add_value(binn * item,int binn_type,int id,char * name,int type,void * pvalue,int size)2255 BOOL binn_add_value(binn *item, int binn_type, int id, char *name, int type, void *pvalue, int size) {
2256 switch (binn_type) {
2257 case BINN_LIST:
2258 return binn_list_add(item, type, pvalue, size);
2259 case BINN_MAP:
2260 return binn_map_set(item, id, type, pvalue, size);
2261 case BINN_OBJECT:
2262 return binn_object_set(item, name, type, pvalue, size);
2263 default:
2264 return FALSE;
2265 }
2266 }
2267
binn_list_add_new(binn * list,binn * value)2268 BOOL binn_list_add_new(binn *list, binn *value) {
2269 BOOL retval;
2270 retval = binn_list_add_value(list, value);
2271 binn_free(value);
2272 return retval;
2273 }
2274
binn_map_set_new(binn * map,int id,binn * value)2275 BOOL binn_map_set_new(binn *map, int id, binn *value) {
2276 BOOL retval;
2277 retval = binn_map_set_value(map, id, value);
2278 binn_free(value);
2279 return retval;
2280 }
2281
binn_object_set_new(binn * obj,const char * key,binn * value)2282 BOOL binn_object_set_new(binn *obj, const char *key, binn *value) {
2283 BOOL retval;
2284 retval = binn_object_set_value(obj, key, value);
2285 binn_free(value);
2286 return retval;
2287 }
2288
binn_object_set_new2(binn * obj,const char * key,int keylen,binn * value)2289 BOOL binn_object_set_new2(binn *obj, const char *key, int keylen, binn *value) {
2290 BOOL retval;
2291 retval = binn_object_set_value2(obj, key, keylen, value);
2292 binn_free(value);
2293 return retval;
2294 }
2295
2296 /*** READ FUNCTIONS ******************************************************************/
2297
binn_list_value(void * ptr,int pos)2298 binn *binn_list_value(void *ptr, int pos) {
2299 binn *value;
2300 value = (binn*) binn_malloc(sizeof(binn));
2301 if (binn_list_get_value(ptr, pos, value) == FALSE) {
2302 free_fn(value);
2303 return NULL;
2304 }
2305 value->allocated = TRUE;
2306 return value;
2307 }
2308
binn_map_value(void * ptr,int id)2309 binn *binn_map_value(void *ptr, int id) {
2310 binn *value;
2311 value = (binn*) binn_malloc(sizeof(binn));
2312 if (binn_map_get_value(ptr, id, value) == FALSE) {
2313 free_fn(value);
2314 return NULL;
2315 }
2316 value->allocated = TRUE;
2317 return value;
2318 }
2319
binn_object_value(void * ptr,const char * key)2320 binn *binn_object_value(void *ptr, const char *key) {
2321 binn *value;
2322 value = (binn*) binn_malloc(sizeof(binn));
2323 if (binn_object_get_value(ptr, key, value) == FALSE) {
2324 free_fn(value);
2325 return NULL;
2326 }
2327 value->allocated = TRUE;
2328 return value;
2329 }
2330
binn_list_read(void * list,int pos,int * ptype,int * psize)2331 void *binn_list_read(void *list, int pos, int *ptype, int *psize) {
2332 binn value;
2333 if (binn_list_get_value(list, pos, &value) == FALSE) {
2334 return NULL;
2335 }
2336 if (ptype) {
2337 *ptype = value.type;
2338 }
2339 if (psize) {
2340 *psize = value.size;
2341 }
2342 #if __BYTE_ORDER == __LITTLE_ENDIAN
2343 return store_value(&value);
2344 #else
2345 return value.ptr;
2346 #endif
2347 }
2348
binn_map_read(void * map,int id,int * ptype,int * psize)2349 void *binn_map_read(void *map, int id, int *ptype, int *psize) {
2350 binn value;
2351 if (binn_map_get_value(map, id, &value) == FALSE) {
2352 return NULL;
2353 }
2354 if (ptype) {
2355 *ptype = value.type;
2356 }
2357 if (psize) {
2358 *psize = value.size;
2359 }
2360 #if __BYTE_ORDER == __LITTLE_ENDIAN
2361 return store_value(&value);
2362 #else
2363 return value.ptr;
2364 #endif
2365 }
2366
binn_object_read(void * obj,const char * key,int * ptype,int * psize)2367 void *binn_object_read(void *obj, const char *key, int *ptype, int *psize) {
2368 binn value;
2369 if (binn_object_get_value(obj, key, &value) == FALSE) {
2370 return NULL;
2371 }
2372 if (ptype) {
2373 *ptype = value.type;
2374 }
2375 if (psize) {
2376 *psize = value.size;
2377 }
2378 #if __BYTE_ORDER == __LITTLE_ENDIAN
2379 return store_value(&value);
2380 #else
2381 return value.ptr;
2382 #endif
2383 }
2384
binn_list_get(void * ptr,int pos,int type,void * pvalue,int * psize)2385 BOOL binn_list_get(void *ptr, int pos, int type, void *pvalue, int *psize) {
2386 binn value;
2387 int storage_type;
2388 storage_type = binn_get_read_storage(type);
2389 if ((storage_type != BINN_STORAGE_NOBYTES) && (pvalue == NULL)) {
2390 return FALSE;
2391 }
2392 zero_value(pvalue, type);
2393 if (binn_list_get_value(ptr, pos, &value) == FALSE) {
2394 return FALSE;
2395 }
2396 if (copy_value(value.ptr, pvalue, value.type, type, storage_type) == FALSE) {
2397 return FALSE;
2398 }
2399 if (psize) {
2400 *psize = value.size;
2401 }
2402 return TRUE;
2403 }
2404
binn_map_get(void * ptr,int id,int type,void * pvalue,int * psize)2405 BOOL binn_map_get(void *ptr, int id, int type, void *pvalue, int *psize) {
2406 binn value;
2407 int storage_type;
2408 storage_type = binn_get_read_storage(type);
2409 if ((storage_type != BINN_STORAGE_NOBYTES) && (pvalue == NULL)) {
2410 return FALSE;
2411 }
2412 zero_value(pvalue, type);
2413 if (binn_map_get_value(ptr, id, &value) == FALSE) {
2414 return FALSE;
2415 }
2416 if (copy_value(value.ptr, pvalue, value.type, type, storage_type) == FALSE) {
2417 return FALSE;
2418 }
2419 if (psize) {
2420 *psize = value.size;
2421 }
2422 return TRUE;
2423 }
2424
binn_object_get(void * ptr,const char * key,int type,void * pvalue,int * psize)2425 BOOL binn_object_get(void *ptr, const char *key, int type, void *pvalue, int *psize) {
2426 binn value;
2427 int storage_type;
2428 storage_type = binn_get_read_storage(type);
2429 if ((storage_type != BINN_STORAGE_NOBYTES) && (pvalue == NULL)) {
2430 return FALSE;
2431 }
2432 zero_value(pvalue, type);
2433 if (binn_object_get_value(ptr, key, &value) == FALSE) {
2434 return FALSE;
2435 }
2436 if (copy_value(value.ptr, pvalue, value.type, type, storage_type) == FALSE) {
2437 return FALSE;
2438 }
2439 if (psize) {
2440 *psize = value.size;
2441 }
2442 return TRUE;
2443 }
2444
2445 // these functions below may not be implemented as inline functions, because
2446 // they use a lot of space, even for the variable. so they will be exported.
2447
2448 // but what about using as static?
2449 // is there any problem with wrappers? can these wrappers implement these functions using the header?
2450 // if as static, will they be present even on modules that don't use the functions?
2451
binn_list_int8(void * list,int pos)2452 signed char binn_list_int8(void *list, int pos) {
2453 signed char value;
2454 binn_list_get(list, pos, BINN_INT8, &value, NULL);
2455 return value;
2456 }
2457
binn_list_int16(void * list,int pos)2458 short binn_list_int16(void *list, int pos) {
2459 short value;
2460 binn_list_get(list, pos, BINN_INT16, &value, NULL);
2461 return value;
2462 }
2463
binn_list_int32(void * list,int pos)2464 int binn_list_int32(void *list, int pos) {
2465 int value;
2466 binn_list_get(list, pos, BINN_INT32, &value, NULL);
2467 return value;
2468 }
2469
binn_list_int64(void * list,int pos)2470 int64 binn_list_int64(void *list, int pos) {
2471 int64 value;
2472 binn_list_get(list, pos, BINN_INT64, &value, NULL);
2473 return value;
2474 }
2475
binn_list_uint8(void * list,int pos)2476 unsigned char binn_list_uint8(void *list, int pos) {
2477 unsigned char value;
2478 binn_list_get(list, pos, BINN_UINT8, &value, NULL);
2479 return value;
2480 }
2481
binn_list_uint16(void * list,int pos)2482 unsigned short binn_list_uint16(void *list, int pos) {
2483 unsigned short value;
2484 binn_list_get(list, pos, BINN_UINT16, &value, NULL);
2485 return value;
2486 }
2487
binn_list_uint32(void * list,int pos)2488 unsigned int binn_list_uint32(void *list, int pos) {
2489 unsigned int value;
2490 binn_list_get(list, pos, BINN_UINT32, &value, NULL);
2491 return value;
2492 }
2493
binn_list_uint64(void * list,int pos)2494 uint64 binn_list_uint64(void *list, int pos) {
2495 uint64 value;
2496 binn_list_get(list, pos, BINN_UINT64, &value, NULL);
2497 return value;
2498 }
2499
binn_list_float(void * list,int pos)2500 float binn_list_float(void *list, int pos) {
2501 float value;
2502 binn_list_get(list, pos, BINN_FLOAT32, &value, NULL);
2503 return value;
2504 }
2505
binn_list_double(void * list,int pos)2506 double binn_list_double(void *list, int pos) {
2507 double value;
2508 binn_list_get(list, pos, BINN_FLOAT64, &value, NULL);
2509 return value;
2510 }
2511
binn_list_bool(void * list,int pos)2512 BOOL binn_list_bool(void *list, int pos) {
2513 BOOL value;
2514 binn_list_get(list, pos, BINN_BOOL, &value, NULL);
2515 return value;
2516 }
2517
binn_list_null(void * list,int pos)2518 BOOL binn_list_null(void *list, int pos) {
2519 return binn_list_get(list, pos, BINN_NULL, NULL, NULL);
2520 }
2521
binn_list_str(void * list,int pos)2522 char *binn_list_str(void *list, int pos) {
2523 char *value;
2524 binn_list_get(list, pos, BINN_STRING, &value, NULL);
2525 return value;
2526 }
2527
binn_list_blob(void * list,int pos,int * psize)2528 void *binn_list_blob(void *list, int pos, int *psize) {
2529 void *value;
2530 binn_list_get(list, pos, BINN_BLOB, &value, psize);
2531 return value;
2532 }
2533
binn_list_list(void * list,int pos)2534 void *binn_list_list(void *list, int pos) {
2535 void *value;
2536 binn_list_get(list, pos, BINN_LIST, &value, NULL);
2537 return value;
2538 }
2539
binn_list_map(void * list,int pos)2540 void *binn_list_map(void *list, int pos) {
2541 void *value;
2542 binn_list_get(list, pos, BINN_MAP, &value, NULL);
2543 return value;
2544 }
2545
binn_list_object(void * list,int pos)2546 void *binn_list_object(void *list, int pos) {
2547 void *value;
2548 binn_list_get(list, pos, BINN_OBJECT, &value, NULL);
2549 return value;
2550 }
2551
binn_map_int8(void * map,int id)2552 signed char binn_map_int8(void *map, int id) {
2553 signed char value;
2554 binn_map_get(map, id, BINN_INT8, &value, NULL);
2555 return value;
2556 }
2557
binn_map_int16(void * map,int id)2558 short binn_map_int16(void *map, int id) {
2559 short value;
2560 binn_map_get(map, id, BINN_INT16, &value, NULL);
2561 return value;
2562 }
2563
binn_map_int32(void * map,int id)2564 int binn_map_int32(void *map, int id) {
2565 int value;
2566 binn_map_get(map, id, BINN_INT32, &value, NULL);
2567 return value;
2568 }
2569
binn_map_int64(void * map,int id)2570 int64 binn_map_int64(void *map, int id) {
2571 int64 value;
2572 binn_map_get(map, id, BINN_INT64, &value, NULL);
2573 return value;
2574 }
2575
binn_map_uint8(void * map,int id)2576 unsigned char binn_map_uint8(void *map, int id) {
2577 unsigned char value;
2578 binn_map_get(map, id, BINN_UINT8, &value, NULL);
2579 return value;
2580 }
2581
binn_map_uint16(void * map,int id)2582 unsigned short binn_map_uint16(void *map, int id) {
2583 unsigned short value;
2584 binn_map_get(map, id, BINN_UINT16, &value, NULL);
2585 return value;
2586 }
2587
binn_map_uint32(void * map,int id)2588 unsigned int binn_map_uint32(void *map, int id) {
2589 unsigned int value;
2590 binn_map_get(map, id, BINN_UINT32, &value, NULL);
2591 return value;
2592 }
2593
binn_map_uint64(void * map,int id)2594 uint64 binn_map_uint64(void *map, int id) {
2595 uint64 value;
2596 binn_map_get(map, id, BINN_UINT64, &value, NULL);
2597 return value;
2598 }
2599
binn_map_float(void * map,int id)2600 float binn_map_float(void *map, int id) {
2601 float value;
2602 binn_map_get(map, id, BINN_FLOAT32, &value, NULL);
2603 return value;
2604 }
2605
binn_map_double(void * map,int id)2606 double binn_map_double(void *map, int id) {
2607 double value;
2608 binn_map_get(map, id, BINN_FLOAT64, &value, NULL);
2609 return value;
2610 }
2611
binn_map_bool(void * map,int id)2612 BOOL binn_map_bool(void *map, int id) {
2613 BOOL value;
2614 binn_map_get(map, id, BINN_BOOL, &value, NULL);
2615 return value;
2616 }
2617
binn_map_null(void * map,int id)2618 BOOL binn_map_null(void *map, int id) {
2619 return binn_map_get(map, id, BINN_NULL, NULL, NULL);
2620 }
2621
binn_map_str(void * map,int id)2622 char *binn_map_str(void *map, int id) {
2623 char *value;
2624 binn_map_get(map, id, BINN_STRING, &value, NULL);
2625 return value;
2626 }
2627
binn_map_blob(void * map,int id,int * psize)2628 void *binn_map_blob(void *map, int id, int *psize) {
2629 void *value;
2630 binn_map_get(map, id, BINN_BLOB, &value, psize);
2631 return value;
2632 }
2633
binn_map_list(void * map,int id)2634 void *binn_map_list(void *map, int id) {
2635 void *value;
2636 binn_map_get(map, id, BINN_LIST, &value, NULL);
2637 return value;
2638 }
2639
binn_map_map(void * map,int id)2640 void *binn_map_map(void *map, int id) {
2641 void *value;
2642 binn_map_get(map, id, BINN_MAP, &value, NULL);
2643 return value;
2644 }
2645
binn_map_object(void * map,int id)2646 void *binn_map_object(void *map, int id) {
2647 void *value;
2648 binn_map_get(map, id, BINN_OBJECT, &value, NULL);
2649 return value;
2650 }
2651
binn_object_int8(void * obj,const char * key)2652 signed char binn_object_int8(void *obj, const char *key) {
2653 signed char value;
2654 binn_object_get(obj, key, BINN_INT8, &value, NULL);
2655 return value;
2656 }
2657
binn_object_int16(void * obj,const char * key)2658 short binn_object_int16(void *obj, const char *key) {
2659 short value;
2660 binn_object_get(obj, key, BINN_INT16, &value, NULL);
2661 return value;
2662 }
2663
binn_object_int32(void * obj,const char * key)2664 int binn_object_int32(void *obj, const char *key) {
2665 int value;
2666 binn_object_get(obj, key, BINN_INT32, &value, NULL);
2667 return value;
2668 }
2669
binn_object_int64(void * obj,const char * key)2670 int64 binn_object_int64(void *obj, const char *key) {
2671 int64 value;
2672 binn_object_get(obj, key, BINN_INT64, &value, NULL);
2673 return value;
2674 }
2675
binn_object_uint8(void * obj,const char * key)2676 unsigned char binn_object_uint8(void *obj, const char *key) {
2677 unsigned char value;
2678 binn_object_get(obj, key, BINN_UINT8, &value, NULL);
2679 return value;
2680 }
2681
binn_object_uint16(void * obj,const char * key)2682 unsigned short binn_object_uint16(void *obj, const char *key) {
2683 unsigned short value;
2684 binn_object_get(obj, key, BINN_UINT16, &value, NULL);
2685 return value;
2686 }
2687
binn_object_uint32(void * obj,const char * key)2688 unsigned int binn_object_uint32(void *obj, const char *key) {
2689 unsigned int value;
2690 binn_object_get(obj, key, BINN_UINT32, &value, NULL);
2691 return value;
2692 }
2693
binn_object_uint64(void * obj,const char * key)2694 uint64 binn_object_uint64(void *obj, const char *key) {
2695 uint64 value;
2696 binn_object_get(obj, key, BINN_UINT64, &value, NULL);
2697 return value;
2698 }
2699
binn_object_float(void * obj,const char * key)2700 float binn_object_float(void *obj, const char *key) {
2701 float value;
2702 binn_object_get(obj, key, BINN_FLOAT32, &value, NULL);
2703 return value;
2704 }
2705
binn_object_double(void * obj,const char * key)2706 double binn_object_double(void *obj, const char *key) {
2707 double value;
2708 binn_object_get(obj, key, BINN_FLOAT64, &value, NULL);
2709 return value;
2710 }
2711
binn_object_bool(void * obj,const char * key)2712 BOOL binn_object_bool(void *obj, const char *key) {
2713 BOOL value;
2714 binn_object_get(obj, key, BINN_BOOL, &value, NULL);
2715 return value;
2716 }
2717
binn_object_null(void * obj,const char * key)2718 BOOL binn_object_null(void *obj, const char *key) {
2719 return binn_object_get(obj, key, BINN_NULL, NULL, NULL);
2720 }
2721
binn_object_str(void * obj,const char * key)2722 char *binn_object_str(void *obj, const char *key) {
2723 char *value;
2724 binn_object_get(obj, key, BINN_STRING, &value, NULL);
2725 return value;
2726 }
2727
binn_object_blob(void * obj,const char * key,int * psize)2728 void *binn_object_blob(void *obj, const char *key, int *psize) {
2729 void *value;
2730 binn_object_get(obj, key, BINN_BLOB, &value, psize);
2731 return value;
2732 }
2733
binn_object_list(void * obj,const char * key)2734 void *binn_object_list(void *obj, const char *key) {
2735 void *value;
2736 binn_object_get(obj, key, BINN_LIST, &value, NULL);
2737 return value;
2738 }
2739
binn_object_map(void * obj,const char * key)2740 void *binn_object_map(void *obj, const char *key) {
2741 void *value;
2742 binn_object_get(obj, key, BINN_MAP, &value, NULL);
2743 return value;
2744 }
2745
binn_object_object(void * obj,const char * key)2746 void *binn_object_object(void *obj, const char *key) {
2747 void *value;
2748 binn_object_get(obj, key, BINN_OBJECT, &value, NULL);
2749 return value;
2750 }
2751
binn_alloc_item()2752 BINN_PRIVATE binn *binn_alloc_item() {
2753 binn *item;
2754 item = (binn*) binn_malloc(sizeof(binn));
2755 if (item) {
2756 memset(item, 0, sizeof(binn));
2757 item->header = BINN_MAGIC;
2758 item->allocated = TRUE;
2759 }
2760 return item;
2761 }
2762
binn_value(int type,void * pvalue,int size,binn_mem_free freefn)2763 binn *binn_value(int type, void *pvalue, int size, binn_mem_free freefn) {
2764 int storage_type;
2765 binn *item = binn_alloc_item();
2766 if (item) {
2767 item->type = type;
2768 binn_get_type_info(type, &storage_type, NULL);
2769 switch (storage_type) {
2770 case BINN_STORAGE_NOBYTES:
2771 break;
2772 case BINN_STORAGE_STRING:
2773 if (size == 0) {
2774 size = strlen((const char*) pvalue) + 1;
2775 }
2776 case BINN_STORAGE_BLOB:
2777 case BINN_STORAGE_CONTAINER:
2778 if (freefn == BINN_TRANSIENT) {
2779 item->ptr = binn_memdup(pvalue, size);
2780 if (item->ptr == NULL) {
2781 free_fn(item);
2782 return NULL;
2783 }
2784 item->freefn = free_fn;
2785 if (storage_type == BINN_STORAGE_STRING) {
2786 size--;
2787 }
2788 } else {
2789 item->ptr = pvalue;
2790 item->freefn = freefn;
2791 }
2792 item->size = size;
2793 break;
2794 default:
2795 item->ptr = &item->vint32;
2796 copy_raw_value(pvalue, item->ptr, storage_type);
2797 }
2798 }
2799 return item;
2800 }
2801
binn_set_string(binn * item,char * str,binn_mem_free pfree)2802 BOOL binn_set_string(binn *item, char *str, binn_mem_free pfree) {
2803 if ((item == NULL) || (str == NULL)) {
2804 return FALSE;
2805 }
2806 if (pfree == BINN_TRANSIENT) {
2807 item->ptr = binn_memdup(str, strlen(str) + 1);
2808 if (item->ptr == NULL) {
2809 return FALSE;
2810 }
2811 item->freefn = free_fn;
2812 } else {
2813 item->ptr = str;
2814 item->freefn = pfree;
2815 }
2816 item->type = BINN_STRING;
2817 return TRUE;
2818 }
2819
binn_set_blob(binn * item,void * ptr,int size,binn_mem_free pfree)2820 BOOL binn_set_blob(binn *item, void *ptr, int size, binn_mem_free pfree) {
2821 if ((item == NULL) || (ptr == NULL)) {
2822 return FALSE;
2823 }
2824 if (pfree == BINN_TRANSIENT) {
2825 item->ptr = binn_memdup(ptr, size);
2826 if (item->ptr == NULL) {
2827 return FALSE;
2828 }
2829 item->freefn = free_fn;
2830 } else {
2831 item->ptr = ptr;
2832 item->freefn = pfree;
2833 }
2834 item->type = BINN_BLOB;
2835 item->size = size;
2836 return TRUE;
2837 }
2838
2839 /*** READ CONVERTED VALUE ************************************************************/
2840
2841 #ifdef _MSC_VER
2842 #define atoi64 _atoi64
2843 #else
2844
atoi64(char * str)2845 int64 atoi64(char *str) {
2846 int64 retval;
2847 int is_negative = 0;
2848
2849 if (*str == '-') {
2850 is_negative = 1;
2851 str++;
2852 }
2853 retval = 0;
2854 for ( ; *str; str++) {
2855 retval = 10 * retval + (*str - '0');
2856 }
2857 if (is_negative) {
2858 retval *= -1;
2859 }
2860 return retval;
2861 }
2862
2863 #endif
2864
is_integer(char * p)2865 BINN_PRIVATE BOOL is_integer(char *p) {
2866 BOOL retval;
2867 if (p == NULL) {
2868 return FALSE;
2869 }
2870 if (*p == '-') {
2871 p++;
2872 }
2873 if (*p == 0) {
2874 return FALSE;
2875 }
2876 retval = TRUE;
2877 for ( ; *p; p++) {
2878 if ((*p < '0') || (*p > '9')) {
2879 retval = FALSE;
2880 }
2881 }
2882 return retval;
2883 }
2884
is_float(char * p)2885 BINN_PRIVATE BOOL is_float(char *p) {
2886 BOOL retval, number_found = FALSE;
2887 if (p == NULL) {
2888 return FALSE;
2889 }
2890 if (*p == '-') {
2891 p++;
2892 }
2893 if (*p == 0) {
2894 return FALSE;
2895 }
2896 retval = TRUE;
2897 for ( ; *p; p++) {
2898 if ((*p == '.') || (*p == ',')) {
2899 if (!number_found) {
2900 retval = FALSE;
2901 }
2902 } else if ((*p >= '0') && (*p <= '9')) {
2903 number_found = TRUE;
2904 } else {
2905 return FALSE;
2906 }
2907 }
2908 return retval;
2909 }
2910
is_bool_str(char * str,BOOL * pbool)2911 BINN_PRIVATE BOOL is_bool_str(char *str, BOOL *pbool) {
2912 int64 vint;
2913 double vdouble;
2914 if ((str == NULL) || (pbool == NULL)) {
2915 return FALSE;
2916 }
2917 if (stricmp(str, "true") == 0) {
2918 goto loc_true;
2919 }
2920 if (stricmp(str, "yes") == 0) {
2921 goto loc_true;
2922 }
2923 if (stricmp(str, "on") == 0) {
2924 goto loc_true;
2925 }
2926 //if (stricmp(str, "1") == 0) goto loc_true;
2927
2928 if (stricmp(str, "false") == 0) {
2929 goto loc_false;
2930 }
2931 if (stricmp(str, "no") == 0) {
2932 goto loc_false;
2933 }
2934 if (stricmp(str, "off") == 0) {
2935 goto loc_false;
2936 }
2937 //if (stricmp(str, "0") == 0) goto loc_false;
2938
2939 if (is_integer(str)) {
2940 vint = atoi64(str);
2941 *pbool = (vint != 0) ? TRUE : FALSE;
2942 return TRUE;
2943 } else if (is_float(str)) {
2944 vdouble = atof(str);
2945 *pbool = (vdouble != 0) ? TRUE : FALSE;
2946 return TRUE;
2947 }
2948
2949 return FALSE;
2950
2951 loc_true:
2952 *pbool = TRUE;
2953 return TRUE;
2954
2955 loc_false:
2956 *pbool = FALSE;
2957 return TRUE;
2958 }
2959
binn_get_int32(binn * value,int * pint)2960 BOOL binn_get_int32(binn *value, int *pint) {
2961 if ((value == NULL) || (pint == NULL)) {
2962 return FALSE;
2963 }
2964 if (type_family(value->type) == BINN_FAMILY_INT) {
2965 return copy_int_value(value->ptr, pint, value->type, BINN_INT32);
2966 }
2967 switch (value->type) {
2968 case BINN_FLOAT:
2969 *pint = round(value->vfloat);
2970 break;
2971 case BINN_DOUBLE:
2972 *pint = round(value->vdouble);
2973 break;
2974 case BINN_STRING:
2975 if (is_integer((char*) value->ptr)) {
2976 *pint = atoi((char*) value->ptr);
2977 } else if (is_float((char*) value->ptr)) {
2978 *pint = round(atof((char*) value->ptr));
2979 } else {
2980 return FALSE;
2981 }
2982 break;
2983 case BINN_BOOL:
2984 *pint = value->vbool;
2985 break;
2986 default:
2987 return FALSE;
2988 }
2989 return TRUE;
2990 }
2991
binn_get_int64(binn * value,int64 * pint)2992 BOOL binn_get_int64(binn *value, int64 *pint) {
2993 if ((value == NULL) || (pint == NULL)) {
2994 return FALSE;
2995 }
2996 if (type_family(value->type) == BINN_FAMILY_INT) {
2997 return copy_int_value(value->ptr, pint, value->type, BINN_INT64);
2998 }
2999 switch (value->type) {
3000 case BINN_FLOAT:
3001 *pint = round(value->vfloat);
3002 break;
3003 case BINN_DOUBLE:
3004 *pint = round(value->vdouble);
3005 break;
3006 case BINN_STRING:
3007 if (is_integer((char*) value->ptr)) {
3008 *pint = atoi64((char*) value->ptr);
3009 } else if (is_float((char*) value->ptr)) {
3010 *pint = round(atof((char*) value->ptr));
3011 } else {
3012 return FALSE;
3013 }
3014 break;
3015 case BINN_BOOL:
3016 *pint = value->vbool;
3017 break;
3018 default:
3019 return FALSE;
3020 }
3021 return TRUE;
3022 }
3023
binn_get_double(binn * value,double * pfloat)3024 BOOL binn_get_double(binn *value, double *pfloat) {
3025 int64 vint;
3026 if ((value == NULL) || (pfloat == NULL)) {
3027 return FALSE;
3028 }
3029 if (type_family(value->type) == BINN_FAMILY_INT) {
3030 if (copy_int_value(value->ptr, &vint, value->type, BINN_INT64) == FALSE) {
3031 return FALSE;
3032 }
3033 *pfloat = (double) vint;
3034 return TRUE;
3035 }
3036 switch (value->type) {
3037 case BINN_FLOAT:
3038 *pfloat = value->vfloat;
3039 break;
3040 case BINN_DOUBLE:
3041 *pfloat = value->vdouble;
3042 break;
3043 case BINN_STRING:
3044 if (is_integer((char*) value->ptr)) {
3045 *pfloat = (double) atoi64((char*) value->ptr);
3046 } else if (is_float((char*) value->ptr)) {
3047 *pfloat = atof((char*) value->ptr);
3048 } else {
3049 return FALSE;
3050 }
3051 break;
3052 case BINN_BOOL:
3053 *pfloat = value->vbool;
3054 break;
3055 default:
3056 return FALSE;
3057 }
3058 return TRUE;
3059 }
3060
binn_get_bool(binn * value,BOOL * pbool)3061 BOOL binn_get_bool(binn *value, BOOL *pbool) {
3062 int64 vint;
3063 if ((value == NULL) || (pbool == NULL)) {
3064 return FALSE;
3065 }
3066 if (type_family(value->type) == BINN_FAMILY_INT) {
3067 if (copy_int_value(value->ptr, &vint, value->type, BINN_INT64) == FALSE) {
3068 return FALSE;
3069 }
3070 *pbool = (vint != 0) ? TRUE : FALSE;
3071 return TRUE;
3072 }
3073 switch (value->type) {
3074 case BINN_BOOL:
3075 *pbool = value->vbool;
3076 break;
3077 case BINN_FLOAT:
3078 *pbool = (value->vfloat != 0) ? TRUE : FALSE;
3079 break;
3080 case BINN_DOUBLE:
3081 *pbool = (value->vdouble != 0) ? TRUE : FALSE;
3082 break;
3083 case BINN_STRING:
3084 return is_bool_str((char*) value->ptr, pbool);
3085 default:
3086 return FALSE;
3087 }
3088 return TRUE;
3089 }
3090
binn_get_str(binn * value)3091 char *binn_get_str(binn *value) {
3092 int64 vint;
3093 char buf[128];
3094 if (value == NULL) {
3095 return NULL;
3096 }
3097 if (type_family(value->type) == BINN_FAMILY_INT) {
3098 if (copy_int_value(value->ptr, &vint, value->type, BINN_INT64) == FALSE) {
3099 return NULL;
3100 }
3101 snprintf(buf, sizeof(buf), "%" INT64_FORMAT, vint); // -V576
3102 goto loc_convert_value;
3103 }
3104 switch (value->type) {
3105 case BINN_FLOAT:
3106 value->vdouble = value->vfloat;
3107 case BINN_DOUBLE:
3108 snprintf(buf, sizeof(buf), "%g", value->vdouble);
3109 goto loc_convert_value;
3110 case BINN_STRING:
3111 return (char*) value->ptr;
3112 case BINN_BOOL:
3113 if (value->vbool) {
3114 strcpy(buf, "true");
3115 } else {
3116 strcpy(buf, "false");
3117 }
3118 goto loc_convert_value;
3119 }
3120 return NULL;
3121
3122 loc_convert_value:
3123 value->ptr = strdup(buf);
3124 if (value->ptr == NULL) {
3125 return NULL;
3126 }
3127 value->freefn = free;
3128 value->type = BINN_STRING;
3129 return (char*) value->ptr;
3130 }
3131
3132 /*** GENERAL FUNCTIONS ***************************************************************/
3133
binn_is_container(binn * item)3134 BOOL binn_is_container(binn *item) {
3135 if (item == NULL) {
3136 return FALSE;
3137 }
3138 switch (item->type) {
3139 case BINN_LIST:
3140 case BINN_MAP:
3141 case BINN_OBJECT:
3142 return TRUE;
3143 default:
3144 return FALSE;
3145 }
3146 }
3147
binn_set_user_data(binn * item,void * user_data,binn_user_data_free freefn)3148 void binn_set_user_data(binn *item, void *user_data, binn_user_data_free freefn) {
3149 if (item->userdata_freefn) {
3150 item->userdata_freefn(item->user_data);
3151 }
3152 item->user_data = user_data;
3153 item->userdata_freefn = free_fn;
3154 }
3155