• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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