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