jsonc.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * mkbootimg/jsonc.c
  3. *
  4. * Copyright (C) 2018 bzt (bztsrc@gitlab)
  5. *
  6. * Permission is hereby granted, free of charge, to any person
  7. * obtaining a copy of this software and associated documentation
  8. * files (the "Software"), to deal in the Software without
  9. * restriction, including without limitation the rights to use, copy,
  10. * modify, merge, publish, distribute, sublicense, and/or sell copies
  11. * of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  24. * DEALINGS IN THE SOFTWARE.
  25. *
  26. * This file is part of the BOOTBOOT Protocol package.
  27. * @brief Memory allocation-free, extremely fast JSON parser in pure ANSI C
  28. *
  29. */
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #define JSON_MAXPATHLEVEL 32
  33. /**
  34. * jsonstr: zero terminated UTF-8 string
  35. * key: path to a value, like "0.6.0.1" or "result.items.0.name"
  36. * returns the value in a malloc'd string or NULL
  37. */
  38. char *json_get(const char *jsonstr, char *key)
  39. {
  40. char *m=key, *ret=NULL;
  41. unsigned char *c=(unsigned char*)jsonstr,*k[JSON_MAXPATHLEVEL+1];
  42. unsigned char *v,*s=NULL,*e=NULL;
  43. int l=0, j=1, i, n, x[JSON_MAXPATHLEVEL+1]={0};
  44. if(!jsonstr || !jsonstr[0] || !key) return NULL;
  45. while(1) {
  46. /* skip white spaces */
  47. while(*c && *c<=' ') c++;
  48. if(j) { j=0; k[l]=v=c; }
  49. switch(*c) {
  50. /* string literals */
  51. case '\"': c++; while(*c && *c!='\"'){if(*c=='\\'){c++;} c++;} break;
  52. /* field names */
  53. case ':': c++; while(*c && *c<=' ') { c++; } v=c--; break;
  54. /* control blocks */
  55. case 0: case ',': case '{': case '[': case '}': case ']':
  56. if(*v!=','&&*v!='{'&&*v!='['&&*v!=']'&&*v!='}') {
  57. /* skip index for topmost object */
  58. n=k[0][0]=='{'?1:0;
  59. /* match the path */
  60. m=key;
  61. for(i=n;i<=l && *m;i++) {
  62. if(i!=n) { if(*m=='.') m++; else break; }
  63. if(k[i][0]=='\"' && k[i]!=v && (*m<'0'||*m>'9')) {
  64. s=e=k[i]+1;
  65. while(*e&&*e!='\"') { if(*e=='\\') { e++; } e++; }
  66. if(memcmp(m,s,e-s)) break;
  67. m+=e-s;
  68. } else {
  69. if(atoi(m)!=x[i]) break;
  70. while(*m && *m!='.') m++;
  71. }
  72. }
  73. /* find start and end of the return value */
  74. if(!*m) {
  75. switch(*v) {
  76. case '\"':
  77. s=e=v+1;
  78. while(*e&&*e!='\"') { if(*e=='\\') { e++; } e++; }
  79. break;
  80. case 'n': return NULL;
  81. default:
  82. s=e=v;
  83. while(*e&&*e>' '&&*e!=','&&*e!=']'&&*e!='}') e++;
  84. break;
  85. }
  86. /* we can't break the loop inside a switch in ANSI C */
  87. goto end;
  88. }
  89. }
  90. switch(*c) {
  91. case 0: return NULL;
  92. case '{': case '[': x[++l]=0; if(l>=(int)sizeof(x)-1) return NULL; break;
  93. case '}': case ']': l--; break;
  94. case ',': x[l]++; break;
  95. }
  96. j++;
  97. break;
  98. }
  99. c++;
  100. }
  101. /* copy a zero terminated string of the value if any */
  102. end:if(!*m && e>s) {
  103. ret=malloc(e-s+1 < 256 ? 256 : e-s+1);
  104. if(ret) { memset(ret,0,256); memcpy(ret,s,e-s); ret[e-s]=0; }
  105. }
  106. return ret;
  107. }