root/tools/perf/pmu-events/jsmn.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. jsmn_alloc_token
  2. jsmn_fill_token
  3. jsmn_parse_primitive
  4. jsmn_parse_string
  5. jsmn_parse
  6. jsmn_init
  7. jsmn_strerror

   1 /*
   2  * Copyright (c) 2010 Serge A. Zaitsev
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a copy
   5  * of this software and associated documentation files (the "Software"), to deal
   6  * in the Software without restriction, including without limitation the rights
   7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   8  * copies of the Software, and to permit persons to whom the Software is
   9  * furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice shall be included in
  12  * all copies or substantial portions of the Software.
  13  *
  14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20  * THE SOFTWARE.
  21  *
  22  * Slightly modified by AK to not assume 0 terminated input.
  23  */
  24 
  25 #include <stdlib.h>
  26 #include "jsmn.h"
  27 
  28 /*
  29  * Allocates a fresh unused token from the token pool.
  30  */
  31 static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
  32                                    jsmntok_t *tokens, size_t num_tokens)
  33 {
  34         jsmntok_t *tok;
  35 
  36         if ((unsigned)parser->toknext >= num_tokens)
  37                 return NULL;
  38         tok = &tokens[parser->toknext++];
  39         tok->start = tok->end = -1;
  40         tok->size = 0;
  41         return tok;
  42 }
  43 
  44 /*
  45  * Fills token type and boundaries.
  46  */
  47 static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
  48                             int start, int end)
  49 {
  50         token->type = type;
  51         token->start = start;
  52         token->end = end;
  53         token->size = 0;
  54 }
  55 
  56 /*
  57  * Fills next available token with JSON primitive.
  58  */
  59 static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js,
  60                                       size_t len,
  61                                       jsmntok_t *tokens, size_t num_tokens)
  62 {
  63         jsmntok_t *token;
  64         int start;
  65 
  66         start = parser->pos;
  67 
  68         for (; parser->pos < len; parser->pos++) {
  69                 switch (js[parser->pos]) {
  70 #ifndef JSMN_STRICT
  71                 /*
  72                  * In strict mode primitive must be followed by ","
  73                  * or "}" or "]"
  74                  */
  75                 case ':':
  76 #endif
  77                 case '\t':
  78                 case '\r':
  79                 case '\n':
  80                 case ' ':
  81                 case ',':
  82                 case ']':
  83                 case '}':
  84                         goto found;
  85                 default:
  86                         break;
  87                 }
  88                 if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
  89                         parser->pos = start;
  90                         return JSMN_ERROR_INVAL;
  91                 }
  92         }
  93 #ifdef JSMN_STRICT
  94         /*
  95          * In strict mode primitive must be followed by a
  96          * comma/object/array.
  97          */
  98         parser->pos = start;
  99         return JSMN_ERROR_PART;
 100 #endif
 101 
 102 found:
 103         token = jsmn_alloc_token(parser, tokens, num_tokens);
 104         if (token == NULL) {
 105                 parser->pos = start;
 106                 return JSMN_ERROR_NOMEM;
 107         }
 108         jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
 109         parser->pos--; /* parent sees closing brackets */
 110         return JSMN_SUCCESS;
 111 }
 112 
 113 /*
 114  * Fills next token with JSON string.
 115  */
 116 static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js,
 117                                    size_t len,
 118                                    jsmntok_t *tokens, size_t num_tokens)
 119 {
 120         jsmntok_t *token;
 121         int start = parser->pos;
 122 
 123         /* Skip starting quote */
 124         parser->pos++;
 125 
 126         for (; parser->pos < len; parser->pos++) {
 127                 char c = js[parser->pos];
 128 
 129                 /* Quote: end of string */
 130                 if (c == '\"') {
 131                         token = jsmn_alloc_token(parser, tokens, num_tokens);
 132                         if (token == NULL) {
 133                                 parser->pos = start;
 134                                 return JSMN_ERROR_NOMEM;
 135                         }
 136                         jsmn_fill_token(token, JSMN_STRING, start+1,
 137                                         parser->pos);
 138                         return JSMN_SUCCESS;
 139                 }
 140 
 141                 /* Backslash: Quoted symbol expected */
 142                 if (c == '\\') {
 143                         parser->pos++;
 144                         switch (js[parser->pos]) {
 145                                 /* Allowed escaped symbols */
 146                         case '\"':
 147                         case '/':
 148                         case '\\':
 149                         case 'b':
 150                         case 'f':
 151                         case 'r':
 152                         case 'n':
 153                         case 't':
 154                                 break;
 155                                 /* Allows escaped symbol \uXXXX */
 156                         case 'u':
 157                                 /* TODO */
 158                                 break;
 159                                 /* Unexpected symbol */
 160                         default:
 161                                 parser->pos = start;
 162                                 return JSMN_ERROR_INVAL;
 163                         }
 164                 }
 165         }
 166         parser->pos = start;
 167         return JSMN_ERROR_PART;
 168 }
 169 
 170 /*
 171  * Parse JSON string and fill tokens.
 172  */
 173 jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
 174                      jsmntok_t *tokens, unsigned int num_tokens)
 175 {
 176         jsmnerr_t r;
 177         int i;
 178         jsmntok_t *token;
 179 
 180         for (; parser->pos < len; parser->pos++) {
 181                 char c;
 182                 jsmntype_t type;
 183 
 184                 c = js[parser->pos];
 185                 switch (c) {
 186                 case '{':
 187                 case '[':
 188                         token = jsmn_alloc_token(parser, tokens, num_tokens);
 189                         if (token == NULL)
 190                                 return JSMN_ERROR_NOMEM;
 191                         if (parser->toksuper != -1)
 192                                 tokens[parser->toksuper].size++;
 193                         token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
 194                         token->start = parser->pos;
 195                         parser->toksuper = parser->toknext - 1;
 196                         break;
 197                 case '}':
 198                 case ']':
 199                         type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
 200                         for (i = parser->toknext - 1; i >= 0; i--) {
 201                                 token = &tokens[i];
 202                                 if (token->start != -1 && token->end == -1) {
 203                                         if (token->type != type)
 204                                                 return JSMN_ERROR_INVAL;
 205                                         parser->toksuper = -1;
 206                                         token->end = parser->pos + 1;
 207                                         break;
 208                                 }
 209                         }
 210                         /* Error if unmatched closing bracket */
 211                         if (i == -1)
 212                                 return JSMN_ERROR_INVAL;
 213                         for (; i >= 0; i--) {
 214                                 token = &tokens[i];
 215                                 if (token->start != -1 && token->end == -1) {
 216                                         parser->toksuper = i;
 217                                         break;
 218                                 }
 219                         }
 220                         break;
 221                 case '\"':
 222                         r = jsmn_parse_string(parser, js, len, tokens,
 223                                               num_tokens);
 224                         if (r < 0)
 225                                 return r;
 226                         if (parser->toksuper != -1)
 227                                 tokens[parser->toksuper].size++;
 228                         break;
 229                 case '\t':
 230                 case '\r':
 231                 case '\n':
 232                 case ':':
 233                 case ',':
 234                 case ' ':
 235                         break;
 236 #ifdef JSMN_STRICT
 237                         /*
 238                          * In strict mode primitives are:
 239                          * numbers and booleans.
 240                          */
 241                 case '-':
 242                 case '0':
 243                 case '1':
 244                 case '2':
 245                 case '3':
 246                 case '4':
 247                 case '5':
 248                 case '6':
 249                 case '7':
 250                 case '8':
 251                 case '9':
 252                 case 't':
 253                 case 'f':
 254                 case 'n':
 255 #else
 256                         /*
 257                          * In non-strict mode every unquoted value
 258                          * is a primitive.
 259                          */
 260                         /*FALL THROUGH */
 261                 default:
 262 #endif
 263                         r = jsmn_parse_primitive(parser, js, len, tokens,
 264                                                  num_tokens);
 265                         if (r < 0)
 266                                 return r;
 267                         if (parser->toksuper != -1)
 268                                 tokens[parser->toksuper].size++;
 269                         break;
 270 
 271 #ifdef JSMN_STRICT
 272                         /* Unexpected char in strict mode */
 273                 default:
 274                         return JSMN_ERROR_INVAL;
 275 #endif
 276                 }
 277         }
 278 
 279         for (i = parser->toknext - 1; i >= 0; i--) {
 280                 /* Unmatched opened object or array */
 281                 if (tokens[i].start != -1 && tokens[i].end == -1)
 282                         return JSMN_ERROR_PART;
 283         }
 284 
 285         return JSMN_SUCCESS;
 286 }
 287 
 288 /*
 289  * Creates a new parser based over a given  buffer with an array of tokens
 290  * available.
 291  */
 292 void jsmn_init(jsmn_parser *parser)
 293 {
 294         parser->pos = 0;
 295         parser->toknext = 0;
 296         parser->toksuper = -1;
 297 }
 298 
 299 const char *jsmn_strerror(jsmnerr_t err)
 300 {
 301         switch (err) {
 302         case JSMN_ERROR_NOMEM:
 303                 return "No enough tokens";
 304         case JSMN_ERROR_INVAL:
 305                 return "Invalid character inside JSON string";
 306         case JSMN_ERROR_PART:
 307                 return "The string is not a full JSON packet, more bytes expected";
 308         case JSMN_SUCCESS:
 309                 return "Success";
 310         default:
 311                 return "Unknown json error";
 312         }
 313 }

/* [<][>][^][v][top][bottom][index][help] */