]> Git Repo - VerusCoin.git/blob - src/cJSON.c
Merge pull request #108 from jl777/dev
[VerusCoin.git] / src / cJSON.c
1
2 /*
3  Copyright (c) 2009 Dave Gamble
4  
5  Permission is hereby granted, free of charge, to any person obtaining a copy
6  of this software and associated documentation files (the "Software"), to deal
7  in the Software without restriction, including without limitation the rights
8  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  copies of the Software, and to permit persons to whom the Software is
10  furnished to do so, subject to the following conditions:
11  
12  The above copyright notice and this permission notice shall be included in
13  all copies or substantial portions of the Software.
14  
15  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21  THE SOFTWARE.
22  */
23
24 /* cJSON */
25 /* JSON parser in C. */
26 #include <math.h>
27
28 #include "cJSON.h"
29
30 #ifndef DBL_EPSILON
31 #define DBL_EPSILON 2.2204460492503131E-16
32 #endif
33
34 static const char *ep;
35
36 long stripquotes(char *str)
37 {
38     long len,offset;
39     if ( str == 0 )
40         return(0);
41     len = strlen(str);
42     if ( str[0] == '"' && str[len-1] == '"' )
43         str[len-1] = 0, offset = 1;
44     else offset = 0;
45     return(offset);
46 }
47
48 const char *cJSON_GetErrorPtr(void) {return ep;}
49
50 static int32_t cJSON_strcasecmp(const char *s1,const char *s2)
51 {
52         if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
53         for(; tolower((int32_t)(*s1)) == tolower((int32_t)(*s2)); ++s1, ++s2)   if(*s1 == 0)    return 0;
54         return tolower((int32_t)(*(const unsigned char *)s1)) - tolower((int32_t)(*(const unsigned char *)s2));
55 }
56
57 static void *(*cJSON_malloc)(size_t sz) = malloc;
58 static void (*cJSON_free)(void *ptr) = free;
59
60 static char* cJSON_strdup(const char* str)
61 {
62     size_t len;
63     char* copy;
64     
65     len = strlen(str) + 1;
66     if (!(copy = (char*)cJSON_malloc(len+1))) return 0;
67     memcpy(copy,str,len);
68     return copy;
69 }
70
71 void cJSON_InitHooks(cJSON_Hooks* hooks)
72 {
73     if (!hooks) { /* Reset hooks */
74         cJSON_malloc = malloc;
75         cJSON_free = free;
76         return;
77     }
78     
79         cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
80         cJSON_free       = (hooks->free_fn)?hooks->free_fn:free;
81 }
82
83 /* Internal constructor. */
84 static cJSON *cJSON_New_Item(void)
85 {
86         cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
87         if (node) memset(node,0,sizeof(cJSON));
88         return node;
89 }
90
91 /* Delete a cJSON structure. */
92 void cJSON_Delete(cJSON *c)
93 {
94         cJSON *next;
95         while (c)
96         {
97                 next=c->next;
98                 if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
99                 if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
100                 if (c->string) cJSON_free(c->string);
101                 cJSON_free(c);
102                 c=next;
103         }
104 }
105
106 /* Parse the input text to generate a number, and populate the result into item. */
107 static const char *parse_number(cJSON *item,const char *num)
108 {
109         double n=0,sign=1,scale=0;int32_t subscale=0,signsubscale=1;
110     
111         if (*num=='-') sign=-1,num++;   /* Has sign? */
112         if (*num=='0') num++;                   /* is zero */
113         if (*num>='1' && *num<='9')     do      n=(n*10.0)+(*num++ -'0');       while (*num>='0' && *num<='9'); /* Number? */
114         if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;            do      n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}      /* Fractional part? */
115         if (*num=='e' || *num=='E')             /* Exponent? */
116         {       num++;if (*num=='+') num++;     else if (*num=='-') signsubscale=-1,num++;              /* With sign? */
117                 while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');   /* Number? */
118         }
119     
120         n=sign*n*pow(10.0,(scale+subscale*signsubscale));       /* number = +/- number.fraction * 10^+/- exponent */
121         
122         item->valuedouble=n;
123         item->valueint=(int64_t)n;
124         item->type=cJSON_Number;
125         return num;
126 }
127
128 /* Render the number nicely from the given item into a string. */
129 static char *print_number(cJSON *item)
130 {
131         char *str;
132         double d = item->valuedouble;
133         if ( fabs(((double)item->valueint) - d) <= DBL_EPSILON && d >= (1. - DBL_EPSILON) && d < (1LL << 62) )//d <= INT_MAX && d >= INT_MIN )
134         {
135                 str = (char *)cJSON_malloc(24); /* 2^64+1 can be represented in 21 chars + sign. */
136                 if ( str != 0 )
137             sprintf(str,"%lld",(long long)item->valueint);
138         }
139         else
140         {
141                 str = (char *)cJSON_malloc(66); /* This is a nice tradeoff. */
142                 if ( str != 0 )
143                 {
144                         if ( fabs(floor(d) - d) <= DBL_EPSILON && fabs(d) < 1.0e60 )
145                 sprintf(str,"%.0f",d);
146                         //else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)                     sprintf(str,"%e",d);
147                         else
148                 sprintf(str,"%.8f",d);
149                 }
150         }
151         return str;
152 }
153
154 static unsigned parse_hex4(const char *str)
155 {
156         unsigned h=0;
157         if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
158         h=h<<4;str++;
159         if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
160         h=h<<4;str++;
161         if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
162         h=h<<4;str++;
163         if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
164         return h;
165 }
166
167 /* Parse the input text into an unescaped cstring, and populate item. */
168 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
169 static const char *parse_string(cJSON *item,const char *str)
170 {
171         const char *ptr=str+1;char *ptr2;char *out;int32_t len=0;unsigned uc,uc2;
172         if (*str!='\"') {ep=str;return 0;}      /* not a string! */
173         
174         while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++;  // Skip escaped quotes
175         
176         out=(char*)cJSON_malloc(len+2); /* This is how long we need for the string, roughly. */
177         if (!out) return 0;
178         
179         ptr=str+1;ptr2=out;
180         while (*ptr!='\"' && *ptr)
181         {
182                 if (*ptr!='\\')
183         {
184             if ( *ptr == '%' && is_hexstr((char *)&ptr[1],2) && isprint(_decode_hex((char *)&ptr[1])) != 0 )
185                 *ptr2++ = _decode_hex((char *)&ptr[1]), ptr += 3;
186             else *ptr2++ = *ptr++;
187         }
188                 else
189                 {
190                         ptr++;
191                         switch (*ptr)
192                         {
193                                 case 'b': *ptr2++='\b'; break;
194                                 case 'f': *ptr2++='\f'; break;
195                                 case 'n': *ptr2++='\n'; break;
196                                 case 'r': *ptr2++='\r'; break;
197                                 case 't': *ptr2++='\t'; break;
198                                 case 'u':        // transcode utf16 to utf8
199                                         uc=parse_hex4(ptr+1);ptr+=4;    // get the unicode char
200                     
201                                         if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)        break;  // check for invalid
202                     
203                                         if (uc>=0xD800 && uc<=0xDBFF)   // UTF16 surrogate pairs
204                                         {
205                                                 if (ptr[1]!='\\' || ptr[2]!='u')        break;  // missing second-half of surrogate.
206                                                 uc2=parse_hex4(ptr+3);ptr+=6;
207                                                 if (uc2<0xDC00 || uc2>0xDFFF)           break;  // invalid second-half of surrogate
208                                                 uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
209                                         }
210                     
211                                         len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
212                                         
213                                         switch (len) {
214                                                 case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
215                                                 case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
216                                                 case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
217                                                 case 1: *--ptr2 =(uc | firstByteMark[len]);
218                                         }
219                                         ptr2+=len;
220                                         break;
221                                 default:  *ptr2++=*ptr; break;
222                         }
223                         ptr++;
224                 }
225         }
226         *ptr2=0;
227         if (*ptr=='\"') ptr++;
228         item->valuestring=out;
229         item->type=cJSON_String;
230         return ptr;
231 }
232
233 /* Render the cstring provided to an escaped version that can be printed. */
234 static char *print_string_ptr(const char *str)
235 {
236         const char *ptr;char *ptr2,*out;int32_t len=0;unsigned char token;
237         
238         if (!str) return cJSON_strdup("");
239         ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
240         
241         out=(char*)cJSON_malloc(len+3+1);
242         if (!out) return 0;
243     
244         ptr2=out;ptr=str;
245         *ptr2++='\"';
246         while (*ptr)
247         {
248                 if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
249                 else
250                 {
251                         *ptr2++='\\';
252                         switch (token=*ptr++)
253                         {
254                                 case '\\':      *ptr2++='\\';   break;
255                                 case '\"':      *ptr2++='\"';   break;
256                                 case '\b':      *ptr2++='b';    break;
257                                 case '\f':      *ptr2++='f';    break;
258                                 case '\n':      *ptr2++='n';    break;
259                                 case '\r':      *ptr2++='r';    break;
260                                 case '\t':      *ptr2++='t';    break;
261                                 default: sprintf(ptr2,"u%04x",token);ptr2+=5;   break;  /* escape and print */
262                         }
263                 }
264         }
265         *ptr2++='\"';*ptr2++=0;
266         return out;
267 }
268 /* Invote print_string_ptr (which is useful) on an item. */
269 static char *print_string(cJSON *item)  {return print_string_ptr(item->valuestring);}
270
271 /* Predeclare these prototypes. */
272 static const char *parse_value(cJSON *item,const char *value);
273 static char *print_value(cJSON *item,int32_t depth,int32_t fmt);
274 static const char *parse_array(cJSON *item,const char *value);
275 static char *print_array(cJSON *item,int32_t depth,int32_t fmt);
276 static const char *parse_object(cJSON *item,const char *value);
277 static char *print_object(cJSON *item,int32_t depth,int32_t fmt);
278
279 /* Utility to jump whitespace and cr/lf */
280 static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
281
282 /* Parse an object - create a new root, and populate. */
283 cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int32_t require_null_terminated)
284 {
285         const char *end=0;
286         cJSON *c=cJSON_New_Item();
287         ep=0;
288         if (!c) return 0;       /* memory fail */
289     
290         end=parse_value(c,skip(value));
291         if (!end)       {cJSON_Delete(c);return 0;}     /* parse failure. ep is set. */
292     
293         /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
294         if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
295         if (return_parse_end) *return_parse_end=end;
296         return c;
297 }
298 /* Default options for cJSON_Parse */
299 cJSON *cJSON_Parse(const char *value)
300 {
301     return(cJSON_ParseWithOpts(value,0,0));
302 }
303
304 /* Render a cJSON item/entity/structure to text. */
305 char *cJSON_Print(cJSON *item)
306 {
307     return(print_value(item,0,1));
308 }
309 char *cJSON_PrintUnformatted(cJSON *item)       {return print_value(item,0,0);}
310
311 /* Parser core - when encountering text, process appropriately. */
312 static const char *parse_value(cJSON *item,const char *value)
313 {
314         if (!value)                                             return 0;       /* Fail on null. */
315         if (!strncmp(value,"null",4))   { item->type=cJSON_NULL;  return value+4; }
316         if (!strncmp(value,"false",5))  { item->type=cJSON_False; return value+5; }
317         if (!strncmp(value,"true",4))   { item->type=cJSON_True; item->valueint=1;      return value+4; }
318         if (*value=='\"')                               { return parse_string(item,value); }
319         if (*value=='-' || (*value>='0' && *value<='9'))        { return parse_number(item,value); }
320         if (*value=='[')                                { return parse_array(item,value); }
321         if (*value=='{')                                { return parse_object(item,value); }
322     
323         ep=value;return 0;      /* failure. */
324 }
325
326 /* Render a value to text. */
327 static char *print_value(cJSON *item,int32_t depth,int32_t fmt)
328 {
329         char *out=0;
330         if (!item) return 0;
331         switch ((item->type)&255)
332         {
333                 case cJSON_NULL:        out=cJSON_strdup("null");       break;
334                 case cJSON_False:       out=cJSON_strdup("false");break;
335                 case cJSON_True:        out=cJSON_strdup("true"); break;
336                 case cJSON_Number:      out=print_number(item);break;
337                 case cJSON_String:      out=print_string(item);break;
338                 case cJSON_Array:       out=print_array(item,depth,fmt);break;
339                 case cJSON_Object:      out=print_object(item,depth,fmt);break;
340         }
341         return out;
342 }
343
344 /* Build an array from input text. */
345 static const char *parse_array(cJSON *item,const char *value)
346 {
347         cJSON *child;
348         if (*value!='[')        {ep=value;return 0;}    /* not an array! */
349     
350         item->type=cJSON_Array;
351         value=skip(value+1);
352         if (*value==']') return value+1;        /* empty array. */
353     
354         item->child=child=cJSON_New_Item();
355         if (!item->child) return 0;              /* memory fail */
356         value=skip(parse_value(child,skip(value)));     /* skip any spacing, get the value. */
357         if (!value) return 0;
358     
359         while (*value==',')
360         {
361                 cJSON *new_item;
362                 if (!(new_item=cJSON_New_Item())) return 0;     /* memory fail */
363                 child->next=new_item;new_item->prev=child;child=new_item;
364                 value=skip(parse_value(child,skip(value+1)));
365                 if (!value) return 0;   /* memory fail */
366         }
367     
368         if (*value==']') return value+1;        /* end of array */
369         ep=value;return 0;      /* malformed. */
370 }
371
372 /* Render an array to text */
373 static char *print_array(cJSON *item,int32_t depth,int32_t fmt)
374 {
375         char **entries;
376         char *out=0,*ptr,*ret;int32_t len=5;
377         cJSON *child=item->child;
378         int32_t numentries=0,i=0,fail=0;
379         
380         /* How many entries in the array? */
381         while (child) numentries++,child=child->next;
382         /* Explicitly handle numentries==0 */
383         if (!numentries)
384         {
385                 out=(char*)cJSON_malloc(3+1);
386                 if (out) strcpy(out,"[]");
387                 return out;
388         }
389         /* Allocate an array to hold the values for each */
390         entries=(char**)cJSON_malloc((1+numentries)*sizeof(char*));
391         if (!entries) return 0;
392         memset(entries,0,numentries*sizeof(char*));
393         /* Retrieve all the results: */
394         child=item->child;
395         while (child && !fail)
396         {
397                 ret=print_value(child,depth+1,fmt);
398                 entries[i++]=ret;
399                 if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
400                 child=child->next;
401         }
402         
403         /* If we didn't fail, try to malloc the output string */
404         if (!fail) out=(char*)cJSON_malloc(len+1);
405         /* If that fails, we fail. */
406         if (!out) fail=1;
407     
408         /* Handle failure. */
409         if (fail)
410         {
411                 for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
412                 cJSON_free(entries);
413                 return 0;
414         }
415         
416         /* Compose the output array. */
417         *out='[';
418         ptr=out+1;*ptr=0;
419         for (i=0;i<numentries;i++)
420         {
421                 strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
422                 if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
423                 cJSON_free(entries[i]);
424         }
425         cJSON_free(entries);
426         *ptr++=']';*ptr++=0;
427         return out;
428 }
429
430 /* Build an object from the text. */
431 static const char *parse_object(cJSON *item,const char *value)
432 {
433         cJSON *child;
434         if (*value!='{')        {ep=value;return 0;}    /* not an object! */
435         
436         item->type=cJSON_Object;
437         value=skip(value+1);
438         if (*value=='}') return value+1;        /* empty array. */
439         
440         item->child=child=cJSON_New_Item();
441         if (!item->child) return 0;
442         value=skip(parse_string(child,skip(value)));
443         if (!value) return 0;
444         child->string=child->valuestring;child->valuestring=0;
445         if (*value!=':') {ep=value;return 0;}   /* fail! */
446         value=skip(parse_value(child,skip(value+1)));   /* skip any spacing, get the value. */
447         if (!value) return 0;
448         
449         while (*value==',')
450         {
451                 cJSON *new_item;
452                 if (!(new_item=cJSON_New_Item()))       return 0; /* memory fail */
453                 child->next=new_item;new_item->prev=child;child=new_item;
454                 value=skip(parse_string(child,skip(value+1)));
455                 if (!value) return 0;
456                 child->string=child->valuestring;child->valuestring=0;
457                 if (*value!=':') {ep=value;return 0;}   /* fail! */
458                 value=skip(parse_value(child,skip(value+1)));   /* skip any spacing, get the value. */
459                 if (!value) return 0;
460         }
461         
462         if (*value=='}') return value+1;        /* end of array */
463         ep=value;return 0;      /* malformed. */
464 }
465
466 /* Render an object to text. */
467 static char *print_object(cJSON *item,int32_t depth,int32_t fmt)
468 {
469         char **entries=0,**names=0;
470         char *out=0,*ptr,*ret,*str;int32_t len=7,i=0,j;
471         cJSON *child=item->child,*firstchild;
472         int32_t numentries=0,fail=0;
473         // Count the number of entries
474     firstchild = child;
475         while ( child )
476     {
477         numentries++;
478         child = child->next;
479         if ( child == firstchild )
480         {
481             printf("cJSON infinite loop detected\n");
482             break;
483         }
484     }
485         /* Explicitly handle empty object case */
486         if (!numentries)
487         {
488                 out=(char*)cJSON_malloc(fmt?depth+4+1:3+1);
489                 if (!out)       return 0;
490                 ptr=out;*ptr++='{';
491                 if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
492                 *ptr++='}';*ptr++=0;
493                 return out;
494         }
495         /* Allocate space for the names and the objects */
496         entries=(char**)cJSON_malloc(numentries*sizeof(char*));
497         if (!entries) return 0;
498         names=(char**)cJSON_malloc(numentries*sizeof(char*));
499         if (!names) {cJSON_free(entries);return 0;}
500         memset(entries,0,sizeof(char*)*numentries);
501         memset(names,0,sizeof(char*)*numentries);
502     
503         /* Collect all the results into our arrays: */
504         child=item->child;depth++;if (fmt) len+=depth;
505         while ( child )
506         {
507                 names[i]=str=print_string_ptr(child->string);
508                 entries[i++]=ret=print_value(child,depth,fmt);
509                 if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
510                 child=child->next;
511         if ( child == firstchild )
512             break;
513         }
514         
515         /* Try to allocate the output string */
516         if (!fail) out=(char*)cJSON_malloc(len+1);
517         if (!out) fail=1;
518     
519         /* Handle failure */
520         if (fail)
521         {
522                 for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
523                 cJSON_free(names);cJSON_free(entries);
524                 return 0;
525         }
526         
527         /* Compose the output: */
528         *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
529         for (i=0;i<numentries;i++)
530         {
531                 if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
532                 strcpy(ptr,names[i]);ptr+=strlen(names[i]);
533                 *ptr++=':';if (fmt) *ptr++='\t';
534                 strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
535                 if (i!=numentries-1) *ptr++=',';
536                 if (fmt) *ptr++='\n';*ptr=0;
537                 cJSON_free(names[i]);cJSON_free(entries[i]);
538         }
539         
540         cJSON_free(names);cJSON_free(entries);
541         if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
542         *ptr++='}';*ptr++=0;
543         return out;
544 }
545
546 /* Get Array size/item / object item. */
547 int32_t    cJSON_GetArraySize(cJSON *array)                                                     {cJSON *c; if ( array == 0 ) return(0); c=array->child;int32_t i=0;while(c)i++,c=c->next;return i;}
548 cJSON *cJSON_GetArrayItem(cJSON *array,int32_t item)                            {cJSON *c=array->child;  while (c && item>0) item--,c=c->next; return c;}
549 cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)    {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
550
551 /* Utility for array list handling. */
552 static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
553 /* Utility for handling references. */
554 static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
555
556 /* Add item to array/object. */
557 void   cJSON_AddItemToArray(cJSON *array, cJSON *item)                                          {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
558 void   cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item)      {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
559 void    cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)                                                {cJSON_AddItemToArray(array,create_reference(item));}
560 void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item)    {cJSON_AddItemToObject(object,string,create_reference(item));}
561
562 cJSON *cJSON_DetachItemFromArray(cJSON *array,int32_t which)                    {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
563         if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
564 void   cJSON_DeleteItemFromArray(cJSON *array,int32_t which)                    {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
565 cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int32_t i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
566 void   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
567
568 /* Replace array/object items with new ones. */
569 void   cJSON_ReplaceItemInArray(cJSON *array,int32_t which,cJSON *newitem)              {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
570         newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
571         if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
572 void   cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int32_t i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
573
574 /* Create basic types: */
575 cJSON *cJSON_CreateNull(void)                                   {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
576 cJSON *cJSON_CreateTrue(void)                                   {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
577 cJSON *cJSON_CreateFalse(void)                                  {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
578 cJSON *cJSON_CreateBool(int32_t b)                                      {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
579 cJSON *cJSON_CreateNumber(double num)                   {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int64_t)num;}return item;}
580 cJSON *cJSON_CreateString(const char *string)   {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
581 cJSON *cJSON_CreateArray(void)                                  {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
582 cJSON *cJSON_CreateObject(void)                                 {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
583
584 /* Create Arrays: */
585 cJSON *cJSON_CreateIntArray(int64_t *numbers,int32_t count)             {int32_t i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber((double)numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
586 cJSON *cJSON_CreateFloatArray(float *numbers,int32_t count)     {int32_t i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
587 cJSON *cJSON_CreateDoubleArray(double *numbers,int32_t count)   {int32_t i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
588 cJSON *cJSON_CreateStringArray(char **strings,int32_t count)    {int32_t i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
589
590 /* Duplication */
591 cJSON *cJSON_Duplicate(cJSON *item,int32_t recurse)
592 {
593         cJSON *newitem,*cptr,*nptr=0,*newchild;
594         /* Bail on bad ptr */
595         if (!item) return 0;
596         /* Create new item */
597         newitem=cJSON_New_Item();
598         if (!newitem) return 0;
599         /* Copy over all vars */
600         newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
601         if (item->valuestring)  {newitem->valuestring=cJSON_strdup(item->valuestring);  if (!newitem->valuestring)      {cJSON_Delete(newitem);return 0;}}
602         if (item->string)               {newitem->string=cJSON_strdup(item->string);                    if (!newitem->string)           {cJSON_Delete(newitem);return 0;}}
603         /* If non-recursive, then we're done! */
604         if (!recurse) return newitem;
605         /* Walk the ->next chain for the child. */
606         cptr=item->child;
607         while (cptr)
608         {
609                 newchild=cJSON_Duplicate(cptr,1);               /* Duplicate (with recurse) each item in the ->next chain */
610                 if (!newchild) {cJSON_Delete(newitem);return 0;}
611                 if (nptr)       {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;}        /* If newitem->child already set, then crosswire ->prev and ->next and move on */
612                 else            {newitem->child=newchild;nptr=newchild;}                                        /* Set newitem->child and move to it */
613                 cptr=cptr->next;
614         }
615         return newitem;
616 }
617
618 void cJSON_Minify(char *json)
619 {
620         char *into=json;
621         while (*json)
622         {
623                 if (*json==' ') json++;
624                 else if (*json=='\t') json++;   // Whitespace characters.
625                 else if (*json=='\r') json++;
626                 else if (*json=='\n') json++;
627                 else if (*json=='/' && json[1]=='/')  while (*json && *json!='\n') json++;      // double-slash comments, to end of line.
628                 else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;}   // multiline comments.
629                 else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive.
630                 else *into++=*json++;                   // All other characters.
631         }
632         *into=0;        // and null-terminate.
633 }
634
635 // the following written by jl777
636 /******************************************************************************
637  * Copyright Â© 2014-2017 The SuperNET Developers.                             *
638  *                                                                            *
639  * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at                  *
640  * the top-level directory of this distribution for the individual copyright  *
641  * holder information and the developer policies on copyright and licensing.  *
642  *                                                                            *
643  * Unless otherwise agreed in a custom licensing agreement, no part of the    *
644  * SuperNET software, including this file may be copied, modified, propagated *
645  * or distributed except according to the terms contained in the LICENSE file *
646  *                                                                            *
647  * Removal or modification of this copyright notice is prohibited.            *
648  *                                                                            *
649  ******************************************************************************/
650
651 void copy_cJSON(struct destbuf *dest,cJSON *obj)
652 {
653     char *str;
654     int i;
655     long offset;
656     dest->buf[0] = 0;
657     if ( obj != 0 )
658     {
659         str = cJSON_Print(obj);
660         if ( str != 0 )
661         {
662             offset = stripquotes(str);
663             //strcpy(dest,str+offset);
664             for (i=0; i<MAX_JSON_FIELD-1; i++)
665                 if ( (dest->buf[i]= str[offset+i]) == 0 )
666                     break;
667             dest->buf[i] = 0;
668             free(str);
669         }
670     }
671 }
672
673 void copy_cJSON2(char *dest,int32_t maxlen,cJSON *obj)
674 {
675     struct destbuf tmp;
676     maxlen--;
677     dest[0] = 0;
678     if ( maxlen > sizeof(tmp.buf) )
679         maxlen = sizeof(tmp.buf);
680     copy_cJSON(&tmp,obj);
681     if ( strlen(tmp.buf) < maxlen )
682         strcpy(dest,tmp.buf);
683     else dest[0] = 0;
684 }
685
686 int64_t _get_cJSON_int(cJSON *json)
687 {
688     struct destbuf tmp;
689     if ( json != 0 )
690     {
691         copy_cJSON(&tmp,json);
692         if ( tmp.buf[0] != 0 )
693             return(calc_nxt64bits(tmp.buf));
694     }
695     return(0);
696 }
697
698 int64_t get_cJSON_int(cJSON *json,char *field)
699 {
700     cJSON *numjson;
701     if ( json != 0 )
702     {
703         numjson = cJSON_GetObjectItem(json,field);
704         if ( numjson != 0 )
705             return(_get_cJSON_int(numjson));
706     }
707     return(0);
708 }
709
710 int64_t conv_floatstr(char *numstr)
711 {
712     double val,corr;
713     val = atof(numstr);
714     corr = (val < 0.) ? -0.50000000001 : 0.50000000001;
715     return((int64_t)(val * SATOSHIDEN + corr));
716 }
717
718 int64_t _conv_cJSON_float(cJSON *json)
719 {
720     int64_t conv_floatstr(char *);
721     struct destbuf tmp;
722     if ( json != 0 )
723     {
724         copy_cJSON(&tmp,json);
725         return(conv_floatstr(tmp.buf));
726     }
727     return(0);
728 }
729
730 int64_t conv_cJSON_float(cJSON *json,char *field)
731 {
732     if ( json != 0 )
733         return(_conv_cJSON_float(cJSON_GetObjectItem(json,field)));
734     return(0);
735 }
736
737 int32_t extract_cJSON_str(char *dest,int32_t max,cJSON *json,char *field)
738 {
739     int32_t safecopy(char *dest,char *src,long len);
740     char *str;
741     cJSON *obj;
742     int32_t len;
743     long offset;
744     dest[0] = 0;
745     obj = cJSON_GetObjectItem(json,field);
746     if ( obj != 0 )
747     {
748         str = cJSON_Print(obj);
749         offset = stripquotes(str);
750         len = safecopy(dest,str+offset,max);
751         free(str);
752         return(len);
753     }
754     return(0);
755 }
756
757 cJSON *gen_list_json(char **list)
758 {
759     cJSON *array,*item;
760     array = cJSON_CreateArray();
761     while ( list != 0 && *list != 0 && *list[0] != 0 )
762     {
763         item = cJSON_CreateString(*list++);
764         cJSON_AddItemToArray(array,item);
765     }
766     return(array);
767 }
768
769 uint64_t get_API_nxt64bits(cJSON *obj)
770 {
771     uint64_t nxt64bits = 0;
772     struct destbuf tmp;
773     if ( obj != 0 )
774     {
775         if ( is_cJSON_Number(obj) != 0 )
776             return((uint64_t)obj->valuedouble);
777         copy_cJSON(&tmp,obj);
778         nxt64bits = calc_nxt64bits(tmp.buf);
779     }
780     return(nxt64bits);
781 }
782 uint64_t j64bits(cJSON *json,char *field) { if ( field == 0 ) return(get_API_nxt64bits(json)); return(get_API_nxt64bits(cJSON_GetObjectItem(json,field))); }
783 uint64_t j64bitsi(cJSON *json,int32_t i) { return(get_API_nxt64bits(cJSON_GetArrayItem(json,i))); }
784
785 uint64_t get_satoshi_obj(cJSON *json,char *field)
786 {
787     int32_t i,n;
788     uint64_t prev,satoshis,mult = 1;
789     struct destbuf numstr,checkstr;
790     cJSON *numjson;
791     numjson = cJSON_GetObjectItem(json,field);
792     copy_cJSON(&numstr,numjson);
793     satoshis = prev = 0; mult = 1; n = (int32_t)strlen(numstr.buf);
794     for (i=n-1; i>=0; i--,mult*=10)
795     {
796         satoshis += (mult * (numstr.buf[i] - '0'));
797         if ( satoshis < prev )
798             printf("get_satoshi_obj numstr.(%s) i.%d prev.%llu vs satoshis.%llu\n",numstr.buf,i,(unsigned long long)prev,(unsigned long long)satoshis);
799         prev = satoshis;
800     }
801     sprintf(checkstr.buf,"%llu",(long long)satoshis);
802     if ( strcmp(checkstr.buf,numstr.buf) != 0 )
803     {
804         printf("SATOSHI GREMLIN?? numstr.(%s) -> %.8f -> (%s)\n",numstr.buf,dstr(satoshis),checkstr.buf);
805     }
806     return(satoshis);
807 }
808
809 void add_satoshis_json(cJSON *json,char *field,uint64_t satoshis)
810 {
811     cJSON *obj;
812     char numstr[64];
813     sprintf(numstr,"%lld",(long long)satoshis);
814     obj = cJSON_CreateString(numstr);
815     cJSON_AddItemToObject(json,field,obj);
816     if ( satoshis != get_satoshi_obj(json,field) )
817         printf("error adding satoshi obj %ld -> %ld\n",(unsigned long)satoshis,(unsigned long)get_satoshi_obj(json,field));
818 }
819
820 char *cJSON_str(cJSON *json)
821 {
822     if ( json != 0 && is_cJSON_String(json) != 0 )
823         return(json->valuestring);
824     return(0);
825 }
826
827 void jadd(cJSON *json,char *field,cJSON *item) { if ( json != 0 )cJSON_AddItemToObject(json,field,item); }
828 void jaddstr(cJSON *json,char *field,char *str) { if ( json != 0 && str != 0 ) cJSON_AddItemToObject(json,field,cJSON_CreateString(str)); }
829 void jaddnum(cJSON *json,char *field,double num) { if ( json != 0 )cJSON_AddItemToObject(json,field,cJSON_CreateNumber(num)); }
830 void jadd64bits(cJSON *json,char *field,uint64_t nxt64bits) { char numstr[64]; sprintf(numstr,"%llu",(long long)nxt64bits), jaddstr(json,field,numstr); }
831 void jaddi(cJSON *json,cJSON *item) { if ( json != 0 ) cJSON_AddItemToArray(json,item); }
832 void jaddistr(cJSON *json,char *str) { if ( json != 0 ) cJSON_AddItemToArray(json,cJSON_CreateString(str)); }
833 void jaddinum(cJSON *json,double num) { if ( json != 0 ) cJSON_AddItemToArray(json,cJSON_CreateNumber(num)); }
834 void jaddi64bits(cJSON *json,uint64_t nxt64bits) { char numstr[64]; sprintf(numstr,"%llu",(long long)nxt64bits), jaddistr(json,numstr); }
835 char *jstr(cJSON *json,char *field) { if ( json == 0 ) return(0); if ( field == 0 ) return(cJSON_str(json)); return(cJSON_str(cJSON_GetObjectItem(json,field))); }
836
837 char *jstri(cJSON *json,int32_t i) { return(cJSON_str(cJSON_GetArrayItem(json,i))); }
838 char *jprint(cJSON *json,int32_t freeflag)
839 {
840     char *str;
841     /*static portable_mutex_t mutex; static int32_t initflag;
842     if ( initflag == 0 )
843     {
844         portable_mutex_init(&mutex);
845         initflag = 1;
846     }*/
847     if ( json == 0 )
848         return(clonestr((char *)"{}"));
849     //portable_mutex_lock(&mutex);
850     //usleep(5000);
851     str = cJSON_Print(json), _stripwhite(str,' ');
852     if ( freeflag != 0 )
853         free_json(json);
854     //portable_mutex_unlock(&mutex);
855     return(str);
856 }
857
858 bits256 get_API_bits256(cJSON *obj)
859 {
860     bits256 hash; char *str;
861     memset(hash.bytes,0,sizeof(hash));
862     if ( obj != 0 )
863     {
864         if ( is_cJSON_String(obj) != 0 && (str= obj->valuestring) != 0 && strlen(str) == 64 )
865             decode_hex(hash.bytes,sizeof(hash),str);
866     }
867     return(hash);
868 }
869 bits256 jbits256(cJSON *json,char *field) { if ( field == 0 ) return(get_API_bits256(json)); return(get_API_bits256(cJSON_GetObjectItem(json,field))); }
870 bits256 jbits256i(cJSON *json,int32_t i) { return(get_API_bits256(cJSON_GetArrayItem(json,i))); }
871 void jaddbits256(cJSON *json,char *field,bits256 hash) { char str[65]; bits256_str(str,hash), jaddstr(json,field,str); }
872 void jaddibits256(cJSON *json,bits256 hash) { char str[65]; bits256_str(str,hash), jaddistr(json,str); }
873
874 char *get_cJSON_fieldname(cJSON *obj)
875 {
876     if ( obj != 0 )
877     {
878         if ( obj->child != 0 && obj->child->string != 0 )
879             return(obj->child->string);
880         else if ( obj->string != 0 )
881             return(obj->string);
882     }
883     return((char *)"<no cJSON string field>");
884 }
885
886 int32_t jnum(cJSON *obj,char *field)
887 {
888     char *str; int32_t polarity = 1;
889     if ( field != 0 )
890         obj = jobj(obj,field);
891     if ( obj != 0 )
892     {
893         if ( is_cJSON_Number(obj) != 0 )
894             return(obj->valuedouble);
895         else if ( is_cJSON_String(obj) != 0 && (str= jstr(obj,0)) != 0 )
896         {
897             if ( str[0] == '-' )
898                 polarity = -1, str++;
899             return(polarity * (int32_t)calc_nxt64bits(str));
900         }
901     }
902     return(0);
903 }
904
905 void ensure_jsonitem(cJSON *json,char *field,char *value)
906 {
907     cJSON *obj = cJSON_GetObjectItem(json,field);
908     if ( obj == 0 )
909         cJSON_AddItemToObject(json,field,cJSON_CreateString(value));
910     else cJSON_ReplaceItemInObject(json,field,cJSON_CreateString(value));
911 }
912
913 int32_t in_jsonarray(cJSON *array,char *value)
914 {
915     int32_t i,n;
916     struct destbuf remote;
917     if ( array != 0 && is_cJSON_Array(array) != 0 )
918     {
919         n = cJSON_GetArraySize(array);
920         for (i=0; i<n; i++)
921         {
922             if ( array == 0 || n == 0 )
923                 break;
924             copy_cJSON(&remote,cJSON_GetArrayItem(array,i));
925             if ( strcmp(remote.buf,value) == 0 )
926                 return(1);
927         }
928     }
929     return(0);
930 }
931
932 int32_t myatoi(char *str,int32_t range)
933 {
934     long x; char *ptr;
935     x = strtol(str,&ptr,10);
936     if ( range != 0 && x >= range )
937         x = (range - 1);
938     return((int32_t)x);
939 }
940
941 int32_t get_API_int(cJSON *obj,int32_t val)
942 {
943     struct destbuf buf;
944     if ( obj != 0 )
945     {
946         if ( is_cJSON_Number(obj) != 0 )
947             return((int32_t)obj->valuedouble);
948         copy_cJSON(&buf,obj);
949         val = myatoi(buf.buf,0);
950         if ( val < 0 )
951             val = 0;
952     }
953     return(val);
954 }
955 int32_t jint(cJSON *json,char *field) { if ( json == 0 ) return(0); if ( field == 0 ) return(get_API_int(json,0)); return(get_API_int(cJSON_GetObjectItem(json,field),0)); }
956 int32_t jinti(cJSON *json,int32_t i) { if ( json == 0 ) return(0); return(get_API_int(cJSON_GetArrayItem(json,i),0)); }
957
958 uint32_t get_API_uint(cJSON *obj,uint32_t val)
959 {
960     struct destbuf buf;
961     if ( obj != 0 )
962     {
963         if ( is_cJSON_Number(obj) != 0 )
964             return((uint32_t)obj->valuedouble);
965         copy_cJSON(&buf,obj);
966         val = myatoi(buf.buf,0);
967     }
968     return(val);
969 }
970 uint32_t juint(cJSON *json,char *field) { if ( json == 0 ) return(0); if ( field == 0 ) return(get_API_uint(json,0)); return(get_API_uint(cJSON_GetObjectItem(json,field),0)); }
971 uint32_t juinti(cJSON *json,int32_t i) { if ( json == 0 ) return(0); return(get_API_uint(cJSON_GetArrayItem(json,i),0)); }
972
973 double get_API_float(cJSON *obj)
974 {
975     double val = 0.;
976     struct destbuf buf;
977     if ( obj != 0 )
978     {
979         if ( is_cJSON_Number(obj) != 0 )
980             return(obj->valuedouble);
981         copy_cJSON(&buf,obj);
982         val = atof(buf.buf);
983     }
984     return(val);
985 }
986
987 double jdouble(cJSON *json,char *field)
988 {
989     if ( json != 0 )
990     {
991         if ( field == 0 )
992             return(get_API_float(json));
993         else return(get_API_float(cJSON_GetObjectItem(json,field)));
994     } else return(0.);
995 }
996
997 double jdoublei(cJSON *json,int32_t i)
998 {
999     if ( json != 0 )
1000         return(get_API_float(cJSON_GetArrayItem(json,i)));
1001     else return(0.);
1002 }
1003
1004 cJSON *jobj(cJSON *json,char *field) { if ( json != 0 ) return(cJSON_GetObjectItem(json,field)); return(0); }
1005
1006 void jdelete(cJSON *json,char *field)
1007 {
1008     if ( jobj(json,field) != 0 )
1009         cJSON_DeleteItemFromObject(json,field);
1010 }
1011
1012 cJSON *jduplicate(cJSON *json) { return(cJSON_Duplicate(json,1)); }
1013
1014 cJSON *jitem(cJSON *array,int32_t i) { if ( array != 0 && is_cJSON_Array(array) != 0 && cJSON_GetArraySize(array) > i ) return(cJSON_GetArrayItem(array,i)); return(0); }
1015 cJSON *jarray(int32_t *nump,cJSON *json,char *field)
1016 {
1017     cJSON *array;
1018     if ( json != 0 )
1019     {
1020         if ( field == 0 )
1021             array = json;
1022         else array = cJSON_GetObjectItem(json,field);
1023         if ( array != 0 && is_cJSON_Array(array) != 0 && (*nump= cJSON_GetArraySize(array)) > 0 )
1024             return(array);
1025     }
1026     *nump = 0;
1027     return(0);
1028 }
1029
1030 int32_t expand_nxt64bits(char *NXTaddr,uint64_t nxt64bits)
1031 {
1032     int32_t i,n;
1033     uint64_t modval;
1034     char rev[64];
1035     for (i=0; nxt64bits!=0; i++)
1036     {
1037         modval = nxt64bits % 10;
1038         rev[i] = (char)(modval + '0');
1039         nxt64bits /= 10;
1040     }
1041     n = i;
1042     for (i=0; i<n; i++)
1043         NXTaddr[i] = rev[n-1-i];
1044     NXTaddr[i] = 0;
1045     return(n);
1046 }
1047
1048 char *nxt64str(uint64_t nxt64bits)
1049 {
1050     static char NXTaddr[64];
1051     expand_nxt64bits(NXTaddr,nxt64bits);
1052     return(NXTaddr);
1053 }
1054
1055 char *nxt64str2(uint64_t nxt64bits)
1056 {
1057     static char NXTaddr[64];
1058     expand_nxt64bits(NXTaddr,nxt64bits);
1059     return(NXTaddr);
1060 }
1061
1062 int32_t cmp_nxt64bits(const char *str,uint64_t nxt64bits)
1063 {
1064     char expanded[64];
1065     if ( str == 0 )//|| str[0] == 0 || nxt64bits == 0 )
1066         return(-1);
1067     if ( nxt64bits == 0 && str[0] == 0 )
1068         return(0);
1069     expand_nxt64bits(expanded,nxt64bits);
1070     return(strcmp(str,expanded));
1071 }
1072
1073 uint64_t calc_nxt64bits(const char *NXTaddr)
1074 {
1075     int32_t c;
1076     int64_t n,i,polarity = 1;
1077     uint64_t lastval,mult,nxt64bits = 0;
1078     if ( NXTaddr == 0 )
1079     {
1080         printf("calling calc_nxt64bits with null ptr!\n");
1081         return(0);
1082     }
1083     n = strlen(NXTaddr);
1084     if ( n >= 22 )
1085     {
1086         printf("calc_nxt64bits: illegal NXTaddr.(%s) too long\n",NXTaddr);
1087         return(0);
1088     }
1089     else if ( strcmp(NXTaddr,"0") == 0 || strcmp(NXTaddr,"false") == 0 )
1090     {
1091         // printf("zero address?\n"); getchar();
1092         return(0);
1093     }
1094     if ( NXTaddr[0] == '-' )
1095         polarity = -1, NXTaddr++, n--;
1096     mult = 1;
1097     lastval = 0;
1098     for (i=n-1; i>=0; i--,mult*=10)
1099     {
1100         c = NXTaddr[i];
1101         if ( c < '0' || c > '9' )
1102         {
1103             printf("calc_nxt64bits: illegal char.(%c %d) in (%s).%d\n",c,c,NXTaddr,(int32_t)i);
1104 #ifdef __APPLE__
1105             //while ( 1 )
1106             {
1107                 //sleep(60);
1108                 printf("calc_nxt64bits: illegal char.(%c %d) in (%s).%d\n",c,c,NXTaddr,(int32_t)i);
1109             }
1110 #endif
1111             return(0);
1112         }
1113         nxt64bits += mult * (c - '0');
1114         if ( nxt64bits < lastval )
1115             printf("calc_nxt64bits: warning: 64bit overflow %llx < %llx\n",(long long)nxt64bits,(long long)lastval);
1116         lastval = nxt64bits;
1117     }
1118     while ( *NXTaddr == '0' && *NXTaddr != 0 )
1119         NXTaddr++;
1120     if ( cmp_nxt64bits(NXTaddr,nxt64bits) != 0 )
1121         printf("error calculating nxt64bits: %s -> %llx -> %s\n",NXTaddr,(long long)nxt64bits,nxt64str(nxt64bits));
1122     if ( polarity < 0 )
1123         return(-(int64_t)nxt64bits);
1124     return(nxt64bits);
1125 }
1126
1127 cJSON *addrs_jsonarray(uint64_t *addrs,int32_t num)
1128 {
1129     int32_t j; cJSON *array;
1130     array = cJSON_CreateArray();
1131     for (j=0; j<num; j++)
1132         jaddi64bits(array,addrs[j]);
1133     return(array);
1134 }
1135
1136 void free_json(cJSON *json) { if ( json != 0 ) cJSON_Delete(json); }
This page took 0.08894 seconds and 4 git commands to generate.