/*
 * Copyright (c) 2010 Serge A. Zaitsev
 *
 * 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.
 *
 * Slightly modified by AK to not assume 0 terminated input.
 */

#include <stdlib.h>
#include "jsmn.h"
#define JSMN_STRICT

/*
 * Allocates a fresh unused token from the token pool.
 */
static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
				   jsmntok_t *tokens, size_t num_tokens)
{
	jsmntok_t *tok;

	if ((unsigned)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,
				      size_t len,
				      jsmntok_t *tokens, size_t num_tokens)
{
	jsmntok_t *token;
	int start;

	start = parser->pos;

	for (; parser->pos < len; 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;
		default:
			break;
		}
		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--; /* parent sees closing brackets */
	return JSMN_SUCCESS;
}

/*
 * Fills next token with JSON string.
 */
static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js,
				   size_t len,
				   jsmntok_t *tokens, size_t num_tokens)
{
	jsmntok_t *token;
	int start = parser->pos;

	/* Skip starting quote */
	parser->pos++;

	for (; parser->pos < len; 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, size_t len,
		     jsmntok_t *tokens, unsigned int num_tokens)
{
	jsmnerr_t r;
	int i;
	jsmntok_t *token;
#ifdef JSMN_STRICT
	/*
	 * Keeps track of whether a new object/list/primitive is expected. New items are only
	 * allowed after an opening brace, comma or colon. A closing brace after a comma is not
	 * valid JSON.
	 */
	int expecting_item = 1;
#endif

	for (; parser->pos < len; parser->pos++) {
		char c;
		jsmntype_t type;

		c = js[parser->pos];
		switch (c) {
		case '{':
		case '[':
#ifdef JSMN_STRICT
			if (!expecting_item)
				return JSMN_ERROR_INVAL;
#endif
			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 ']':
#ifdef JSMN_STRICT
			if (expecting_item)
				return JSMN_ERROR_INVAL;
#endif
			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 '\"':
#ifdef JSMN_STRICT
			if (!expecting_item)
				return JSMN_ERROR_INVAL;
			expecting_item = 0;
#endif
			r = jsmn_parse_string(parser, js, len, tokens,
					      num_tokens);
			if (r < 0)
				return r;
			if (parser->toksuper != -1)
				tokens[parser->toksuper].size++;
			break;
		case '\t':
		case '\r':
		case '\n':
		case ' ':
			break;
#ifdef JSMN_STRICT
		case ':':
		case ',':
			if (expecting_item)
				return JSMN_ERROR_INVAL;
			expecting_item = 1;
			break;
			/*
			 * 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
		case ':':
		case ',':
			break;
			/*
			 * In non-strict mode every unquoted value
			 * is a primitive.
			 */
			/*FALL THROUGH */
		default:
#endif

#ifdef JSMN_STRICT
			if (!expecting_item)
				return JSMN_ERROR_INVAL;
			expecting_item = 0;
#endif
			r = jsmn_parse_primitive(parser, js, len, 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;
	}

#ifdef JSMN_STRICT
	return expecting_item ? JSMN_ERROR_INVAL : JSMN_SUCCESS;
#else
	return JSMN_SUCCESS;
#endif
}

/*
 * 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;
}

const char *jsmn_strerror(jsmnerr_t err)
{
	switch (err) {
	case JSMN_ERROR_NOMEM:
		return "No enough tokens";
	case JSMN_ERROR_INVAL:
		return "Invalid character inside JSON string";
	case JSMN_ERROR_PART:
		return "The string is not a full JSON packet, more bytes expected";
	case JSMN_SUCCESS:
		return "Success";
	default:
		return "Unknown json error";
	}
}
