mirror of
https://gitlab.com/bztsrc/bootboot.git
synced 2023-02-13 20:54:32 -05:00
109 lines
4.1 KiB
C
109 lines
4.1 KiB
C
/*
|
|
* mkbootimg/jsonc.c
|
|
*
|
|
* Copyright (C) 2018 bzt (bztsrc@gitlab)
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation
|
|
* files (the "Software"), to deal in the Software without
|
|
* restriction, including without limitation the rights to use, copy,
|
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
* of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* This file is part of the BOOTBOOT Protocol package.
|
|
* @brief Memory allocation-free, extremely fast JSON parser in pure ANSI C
|
|
*
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define JSON_MAXPATHLEVEL 32
|
|
|
|
/**
|
|
* jsonstr: zero terminated UTF-8 string
|
|
* key: path to a value, like "0.6.0.1" or "result.items.0.name"
|
|
* returns the value in a malloc'd string or NULL
|
|
*/
|
|
char *json_get(const char *jsonstr, char *key)
|
|
{
|
|
char *m=key, *ret=NULL;
|
|
unsigned char *c=(unsigned char*)jsonstr,*k[JSON_MAXPATHLEVEL+1];
|
|
unsigned char *v,*s=NULL,*e=NULL;
|
|
int l=0, j=1, i, n, x[JSON_MAXPATHLEVEL+1]={0};
|
|
if(!jsonstr || !jsonstr[0] || !key) return NULL;
|
|
while(1) {
|
|
/* skip white spaces */
|
|
while(*c && *c<=' ') c++;
|
|
if(j) { j=0; k[l]=v=c; }
|
|
switch(*c) {
|
|
/* string literals */
|
|
case '\"': c++; while(*c && *c!='\"'){if(*c=='\\'){c++;} c++;} break;
|
|
/* field names */
|
|
case ':': c++; while(*c && *c<=' ') { c++; } v=c--; break;
|
|
/* control blocks */
|
|
case 0: case ',': case '{': case '[': case '}': case ']':
|
|
if(*v!=','&&*v!='{'&&*v!='['&&*v!=']'&&*v!='}') {
|
|
/* skip index for topmost object */
|
|
n=k[0][0]=='{'?1:0;
|
|
/* match the path */
|
|
m=key;
|
|
for(i=n;i<=l && *m;i++) {
|
|
if(i!=n) { if(*m=='.') m++; else break; }
|
|
if(k[i][0]=='\"' && k[i]!=v && (*m<'0'||*m>'9')) {
|
|
s=e=k[i]+1;
|
|
while(*e&&*e!='\"') { if(*e=='\\') { e++; } e++; }
|
|
if(memcmp(m,s,e-s)) break;
|
|
m+=e-s;
|
|
} else {
|
|
if(atoi(m)!=x[i]) break;
|
|
while(*m && *m!='.') m++;
|
|
}
|
|
}
|
|
/* find start and end of the return value */
|
|
if(!*m) {
|
|
switch(*v) {
|
|
case '\"':
|
|
s=e=v+1;
|
|
while(*e&&*e!='\"') { if(*e=='\\') { e++; } e++; }
|
|
break;
|
|
case 'n': return NULL;
|
|
default:
|
|
s=e=v;
|
|
while(*e&&*e>' '&&*e!=','&&*e!=']'&&*e!='}') e++;
|
|
break;
|
|
}
|
|
/* we can't break the loop inside a switch in ANSI C */
|
|
goto end;
|
|
}
|
|
}
|
|
switch(*c) {
|
|
case 0: return NULL;
|
|
case '{': case '[': x[++l]=0; if(l>=(int)sizeof(x)-1) return NULL; break;
|
|
case '}': case ']': l--; break;
|
|
case ',': x[l]++; break;
|
|
}
|
|
j++;
|
|
break;
|
|
}
|
|
c++;
|
|
}
|
|
/* copy a zero terminated string of the value if any */
|
|
end:if(!*m && e>s) {
|
|
ret=malloc(e-s+1 < 256 ? 256 : e-s+1);
|
|
if(ret) { memset(ret,0,256); memcpy(ret,s,e-s); ret[e-s]=0; }
|
|
}
|
|
return ret;
|
|
}
|