jsmn / jsmn.c

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 0c208cc 


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 7825e7d 
Serge A. Zaitsev 2eca5cf 
Serge A. Zaitsev 7825e7d 
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 0c208cc 


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 0c208cc 


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 0c208cc 
Serge A. Zaitsev 0af8582 
Serge A. Zaitsev 0c208cc 



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

Serge A. Zaitsev c8ff928 
Serge A. Zaitsev 0c208cc 
















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 0c208cc 
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;
#ifdef JSMN_PARENT_LINKS
	tok->parent = -1;
#endif
	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 ':':
#endif
			case '\t' : case '\r' : case '\n' : case ' ' :
			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);
#ifdef JSMN_PARENT_LINKS
	token->parent = parser->toksuper;
#endif
	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);
#ifdef JSMN_PARENT_LINKS
			token->parent = parser->toksuper;
#endif
			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++;
#ifdef JSMN_PARENT_LINKS
					token->parent = parser->toksuper;
#endif
				}
				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);
#ifdef JSMN_PARENT_LINKS
				if (parser->toknext < 1) {
					return JSMN_ERROR_INVAL;
				}
				token = &tokens[parser->toknext - 1];
				for (;;) {
					if (token->start != -1 && token->end == -1) {
						token->end = parser->pos + 1;
						parser->toksuper = token->parent;
						break;
					}
					if (token->parent == -1) {
						break;
					}
					token = &tokens[token->parent];
				}
#else
				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;
					}
				}
#endif
				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;
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.