Source

jsmn / jsmn.c

Full commit
Serge A. Zaitsev 90642b1 



Serge A. Zaitsev 20591f1 


Serge A. Zaitsev dfb2c0c 

Serge A. Zaitsev b4737a8 


Serge A. Zaitsev 8c403c4 
Serge A. Zaitsev b4737a8 



Serge A. Zaitsev 8c403c4 

Serge A. Zaitsev 20591f1 




Serge A. Zaitsev 8c403c4 


Serge A. Zaitsev 0af8582 
Serge A. Zaitsev 8c403c4 

Serge A. Zaitsev 20591f1 


Serge A. Zaitsev 700bc7a 
Serge A. Zaitsev dfb2c0c 
Serge A. Zaitsev c8ff928 
Serge A. Zaitsev 8c403c4 


Serge A. Zaitsev 0fd4fd3 


Serge A. Zaitsev 2eca5cf 



Serge A. Zaitsev 0fd4fd3 
Serge A. Zaitsev ea3f778 
Serge A. Zaitsev 0fd4fd3 

Serge A. Zaitsev 8c403c4 
Serge A. Zaitsev 0fd4fd3 


Serge A. Zaitsev 2eca5cf 

Serge A. Zaitsev 8c403c4 
Serge A. Zaitsev 0fd4fd3 
Serge A. Zaitsev ea3f778 



Serge A. Zaitsev b364e33 

Serge A. Zaitsev ea3f778 
Serge A. Zaitsev b364e33 
Serge A. Zaitsev ea3f778 


Serge A. Zaitsev 0fd4fd3 

Serge A. Zaitsev 20591f1 


Serge A. Zaitsev 700bc7a 
Serge A. Zaitsev dfb2c0c 
Serge A. Zaitsev c8ff928 
Serge A. Zaitsev 0fd4fd3 
Serge A. Zaitsev 8c403c4 

Serge A. Zaitsev 0fd4fd3 

Serge A. Zaitsev cbefe8c 
Serge A. Zaitsev 0fd4fd3 

Serge A. Zaitsev 90642b1 
Serge A. Zaitsev cbefe8c 
Serge A. Zaitsev 0fd4fd3 
Serge A. Zaitsev dfb2c0c 
Serge A. Zaitsev b364e33 

Serge Zaitsev 555ce4f 
Serge A. Zaitsev b364e33 
Serge A. Zaitsev dd7f825 
Serge A. Zaitsev 0fd4fd3 
Serge A. Zaitsev cbefe8c 
Serge A. Zaitsev 90642b1 
Serge A. Zaitsev cbefe8c 
Serge A. Zaitsev 0fd4fd3 


Serge A. Zaitsev cbefe8c 









Serge A. Zaitsev 8c403c4 
Serge A. Zaitsev 0fd4fd3 
Serge A. Zaitsev cbefe8c 


Serge A. Zaitsev 8c403c4 
Serge A. Zaitsev 0fd4fd3 
Serge A. Zaitsev cbefe8c 
Serge A. Zaitsev 90642b1 
Serge A. Zaitsev 20591f1 


Serge A. Zaitsev c3427ad 

Serge A. Zaitsev 700bc7a 
Serge A. Zaitsev dea589a 
Serge A. Zaitsev c8ff928 
Serge A. Zaitsev 0fd4fd3 


Serge A. Zaitsev ea3f778 

Serge A. Zaitsev 0fd4fd3 


Serge A. Zaitsev dfb2c0c 
Serge Zaitsev 555ce4f 

Serge A. Zaitsev 0af8582 

Serge A. Zaitsev c8ff928 
Serge A. Zaitsev 8c403c4 
Serge A. Zaitsev 0af8582 
Serge A. Zaitsev 0fd4fd3 

Serge A. Zaitsev c8ff928 
Serge A. Zaitsev a2e4297 
Serge A. Zaitsev dfb2c0c 
Serge A. Zaitsev 8c403c4 



Serge A. Zaitsev 0af8582 
Serge A. Zaitsev 8c403c4 



Serge A. Zaitsev 1caee52 

Serge A. Zaitsev dea589a 
Serge A. Zaitsev dfb2c0c 
Serge A. Zaitsev dea589a 
Serge A. Zaitsev 0af8582 
Serge A. Zaitsev dea589a 


Serge A. Zaitsev 0fd4fd3 

Serge A. Zaitsev dfb2c0c 
Serge A. Zaitsev 8c403c4 
Serge A. Zaitsev 0af8582 

Serge A. Zaitsev 0fd4fd3 


Serge A. Zaitsev 2eca5cf 










Serge A. Zaitsev 0af8582 

Serge A. Zaitsev 2eca5cf 



Serge A. Zaitsev 0fd4fd3 

Serge A. Zaitsev 2eca5cf 

Serge A. Zaitsev cbefe8c 

Serge A. Zaitsev e71893a 







Serge A. Zaitsev 0fd4fd3 
Serge A. Zaitsev cbefe8c 
Serge A. Zaitsev 90642b1 
Serge A. Zaitsev c3427ad 





Serge A. Zaitsev a2e4297 
Serge A. Zaitsev 0af8582 
Serge A. Zaitsev c3427ad 
#include <stdlib.h>

#include "jsmn.h"

/**
 * Allocates a fresh unused token from the token pull.
 */
static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, 
		jsmntok_t *tokens, size_t num_tokens) {
	jsmntok_t *tok;
	if (parser->toknext >= num_tokens) {
		return NULL;
	}
	tok = &tokens[parser->toknext++];
	tok->start = tok->end = -1;
	tok->size = 0;
	return tok;
}

/**
 * Fills token type and boundaries.
 */
static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, 
                            int start, int end) {
	token->type = type;
	token->start = start;
	token->end = end;
	token->size = 0;
}

/**
 * Fills next available token with JSON primitive.
 */
static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js,
		jsmntok_t *tokens, size_t num_tokens) {
	jsmntok_t *token;
	int start;

	start = parser->pos;

	for (; js[parser->pos] != '\0'; parser->pos++) {
		switch (js[parser->pos]) {
#ifndef JSMN_STRICT
			/* In strict mode primitive must be followed by "," or "}" or "]" */
			case '\t' : case '\r' : case '\n' : case ' ' : case ':': 
#endif
			case ','  : case ']'  : case '}' :
				goto found;
		}
		if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
			parser->pos = start;
			return JSMN_ERROR_INVAL;
		}
	}
#ifdef JSMN_STRICT
	/* In strict mode primitive must be followed by a comma/object/array */
	parser->pos = start;
	return JSMN_ERROR_PART;
#endif

found:
	token = jsmn_alloc_token(parser, tokens, num_tokens);
	if (token == NULL) {
		parser->pos = start;
		return JSMN_ERROR_NOMEM;
	}
	jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
	parser->pos--;
	return JSMN_SUCCESS;
}

/**
 * Filsl next token with JSON string.
 */
static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js,
		jsmntok_t *tokens, size_t num_tokens) {
	jsmntok_t *token;

	int start = parser->pos;

	parser->pos++;

	/* Skip starting quote */
	for (; js[parser->pos] != '\0'; parser->pos++) {
		char c = js[parser->pos];

		/* Quote: end of string */
		if (c == '\"') {
			token = jsmn_alloc_token(parser, tokens, num_tokens);
			if (token == NULL) {
				parser->pos = start;
				return JSMN_ERROR_NOMEM;
			}
			jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
			return JSMN_SUCCESS;
		}

		/* Backslash: Quoted symbol expected */
		if (c == '\\') {
			parser->pos++;
			switch (js[parser->pos]) {
				/* Allowed escaped symbols */
				case '\"': case '/' : case '\\' : case 'b' :
				case 'f' : case 'r' : case 'n'  : case 't' :
					break;
				/* Allows escaped symbol \uXXXX */
				case 'u':
					/* TODO */
					break;
				/* Unexpected symbol */
				default:
					parser->pos = start;
					return JSMN_ERROR_INVAL;
			}
		}
	}
	parser->pos = start;
	return JSMN_ERROR_PART;
}

/**
 * Parse JSON string and fill tokens.
 */
jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, jsmntok_t *tokens, 
		unsigned int num_tokens) {
	jsmnerr_t r;
	int i;
	jsmntok_t *token;

	for (; js[parser->pos] != '\0'; parser->pos++) {
		char c;
		jsmntype_t type;

		c = js[parser->pos];
		switch (c) {
			case '{': case '[':
				token = jsmn_alloc_token(parser, tokens, num_tokens);
				if (token == NULL)
					return JSMN_ERROR_NOMEM;
				if (parser->toksuper != -1)
					tokens[parser->toksuper].size++;
				token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
				token->start = parser->pos;
				parser->toksuper = parser->toknext - 1;
				break;
			case '}': case ']':
				type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
				for (i = parser->toknext - 1; i >= 0; i--) {
					token = &tokens[i];
					if (token->start != -1 && token->end == -1) {
						if (token->type != type) {
							return JSMN_ERROR_INVAL;
						}
						parser->toksuper = -1;
						token->end = parser->pos + 1;
						break;
					}
				}
				/* Error if unmatched closing bracket */
				if (i == -1) return JSMN_ERROR_INVAL;
				for (; i >= 0; i--) {
					token = &tokens[i];
					if (token->start != -1 && token->end == -1) {
						parser->toksuper = i;
						break;
					}
				}
				break;
			case '\"':
				r = jsmn_parse_string(parser, js, tokens, num_tokens);
				if (r < 0) return r;
				if (parser->toksuper != -1)
					tokens[parser->toksuper].size++;
				break;
			case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ': 
				break;
#ifdef JSMN_STRICT
			/* In strict mode primitives are: numbers and booleans */
			case '-': case '0': case '1' : case '2': case '3' : case '4':
			case '5': case '6': case '7' : case '8': case '9':
			case 't': case 'f': case 'n' :
#else
			/* In non-strict mode every unquoted value is a primitive */
			default:
#endif
				r = jsmn_parse_primitive(parser, js, tokens, num_tokens);
				if (r < 0) return r;
				if (parser->toksuper != -1)
					tokens[parser->toksuper].size++;
				break;

#ifdef JSMN_STRICT
			/* Unexpected char in strict mode */
			default:
				return JSMN_ERROR_INVAL;
#endif

		}
	}

	for (i = parser->toknext - 1; i >= 0; i--) {
		/* Unmatched opened object or array */
		if (tokens[i].start != -1 && tokens[i].end == -1) {
			return JSMN_ERROR_PART;
		}
	}

	return JSMN_SUCCESS;
}

/**
 * Creates a new parser based over a given  buffer with an array of tokens 
 * available.
 */
void jsmn_init(jsmn_parser *parser) {
	parser->pos = 0;
	parser->toknext = 0;
	parser->toksuper = -1;
}