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