예제 #1
0
inline
json_error_t* allocate_object_by_type(
		json_t **objectPtr,
		jsmntok_t *token,
		jsmntok_t tokens[TOKENS_COUNT], size_t tokensCount, size_t *tokenIndex,
		char* js) {

	json_error_t* parseError = NULL;
	json_t* jsonObject = NULL;

	json_type type = decode_jsmn_type(token->type);



	switch (type) {
	case JSON_STRING:
		jsonObject = json_alloc(JSON_STRING, token->size);
		if(jsonObject == NULL) {
			parseError = parsingError(
				JSON_MEMORY_ALLOC_FAILED,
				"Error: Unable to allocate string object.",
				token,
				js
			);
		}
		break;



	case JSON_PRIMITIVE:
	{
		char *firstCharacter = js + token->start;
		switch(*firstCharacter) {
		case '-': {};
		case '0': {};
		case '1': {};
		case '2': {};
		case '3': {};
		case '4': {};
		case '5': {};
		case '6': {};
		case '7': {};
		case '8': {};
		case '9': {};
			jsonObject = json_alloc(JSON_NUMBER, token->size);
			break;
		case 't':
			jsonObject = json_alloc(JSON_TRUE, token->size);
			break;
		case 'f':
			jsonObject = json_alloc(JSON_FALSE, token->size);
			break;
		case 'n' :
			jsonObject = json_alloc(JSON_NULL, token->size);
			break;
		default:
			parseError = parsingError(
				JSON_INVALID_OBJECT_TYPE,
				"Error: Unable to allocate primitive object by first character. Wrong character at -->",
				token,
				js
			);
			break;
		}
	} break;


	case JSON_OBJECT:
	case JSON_ARRAY:
		parseError = createJsonObject(&jsonObject, js, tokens, tokensCount, tokenIndex);
		break;
	default:
		parseError = parsingError(
			JSON_INVALID_OBJECT_TYPE,
			"Error: Unable to allocate object by type. Wrong type.",
			token,
			js
		);
		break;
	}

	if(parseError == NULL) {

		add_value_from_token(jsonObject, js, token);
//		/* assign returned object */
//		if(objectPtr != NULL) {
//			json_free(objectPtr);
//		}
//		objectPtr = (json_t*) json_malloc(sizeof(json_t));
//		memcpy(objectPtr, jsonObject, sizeof(json_t));
//
//		json_free(jsonObject);

		*objectPtr = jsonObject;


	}


	return parseError;
}
예제 #2
0
json_value *json_parse(char *source, char **error_pos, int *error_line, block_allocator *allocator)
{
	json_value *root = 0;
	json_value *top = 0;

	char *name = 0;
	char *it = source;

	int escaped_newlines = 0;

	while (*it)
	{
		switch (*it)
		{
		case '{':
		case '[':
			{
				// create new value
				json_value *object = json_alloc(allocator);

				// name
				object->name = name;
				name = 0;

				// type
				object->type = (*it == '{') ? JSON_OBJECT : JSON_ARRAY;

				// skip open character
				++it;

				// set top and root
				if (top)
				{
					json_append(top, object);
				}
				else if (!root)
				{
					root = object;
				}
				else
				{
					ERROR(it, "Second root. Only one root allowed");
				}
				top = object;
			}
			break;

		case '}':
		case ']':
			{
				if (!top || top->type != ((*it == '}') ? JSON_OBJECT : JSON_ARRAY))
				{
					ERROR(it, "Mismatch closing brace/bracket");
				}

				// skip close character
				++it;

				// set top
				top = top->parent;
			}
			break;

		case ':':
			if (!top || top->type != JSON_OBJECT)
			{
				ERROR(it, "Unexpected character");
			}
			++it;
			break;

		case ',':
			CHECK_TOP();
			++it;
			break;

		case '"':
			{
				CHECK_TOP();

				// skip '"' character
				++it;

				char *first = it;
				char *last = it;
				while (*it)
				{
					if ((unsigned char)*it < '\x20')
					{
						ERROR(first, "Control characters not allowed in strings");
					}
					else if (*it == '\\')
					{
						switch (it[1])
						{
						case '"':
							*last = '"';
							break;
						case '\\':
							*last = '\\';
							break;
						case '/':
							*last = '/';
							break;
						case 'b':
							*last = '\b';
							break;
						case 'f':
							*last = '\f';
							break;
						case 'n':
							*last = '\n';
							++escaped_newlines;
							break;
						case 'r':
							*last = '\r';
							break;
						case 't':
							*last = '\t';
							break;
						case 'u':
							{
								unsigned int codepoint;
								if (hatoui(it + 2, it + 6, &codepoint) != it + 6)
								{
									ERROR(it, "Bad unicode codepoint");
								}

								if (codepoint <= 0x7F)
								{
									*last = (char)codepoint;
								}
								else if (codepoint <= 0x7FF)
								{
									*last++ = (char)(0xC0 | (codepoint >> 6));
									*last = (char)(0x80 | (codepoint & 0x3F));
								}
								else if (codepoint <= 0xFFFF)
								{
									*last++ = (char)(0xE0 | (codepoint >> 12));
									*last++ = (char)(0x80 | ((codepoint >> 6) & 0x3F));
									*last = (char)(0x80 | (codepoint & 0x3F));
								}
							}
							it += 4;
							break;
						default:
							ERROR(first, "Unrecognized escape sequence");
						}

						++last;
						it += 2;
					}
					else if (*it == '"')
					{
						*last = 0;
						++it;
						break;
					}
					else
					{
						*last++ = *it++;
					}
				}
예제 #3
0
json_error_t* createJsonObject(
		json_t **json_root,
		char *js,
		jsmntok_t tokens[TOKENS_COUNT],
		size_t tokensCount,
		size_t *tokenIndex
) {

	typedef enum { START, KEY, PRINT, VALUE, ARRAY, STOP } parse_state;
	parse_state state = START;

	json_error_t* error = NULL;
	//static char msgBuffer[MSG_BUFFER_SIZE];

	//size_t tokenIndex = 0;

//	strbuffer_t *tokenStr = NULL;

	size_t object_tokens = 0;

	json_t *root = NULL;
	json_t *key = NULL;
	json_t *value = NULL;

	for (; *tokenIndex < tokensCount; *tokenIndex += 1 ) {
		jsmntok_t *token = &tokens[*tokenIndex];

//		size_t heapSize = xPortGetFreeHeapSize();
//		sprintf(msgBuffer, "HEAP SIZE: %d\n", heapSize);
//		log_d(msgBuffer);

		if(token->start > strlen(js)
					|| token->end > strlen(js)
					|| token->end > strlen(js)
					|| (token->end - token->start) > strlen(js)
		) {
			continue;
		}


//		tokenStr = json_token_tostr(js, token);

		switch (state) {

		case START:
			if (token->type != JSMN_OBJECT && token->type != JSMN_ARRAY) {
				return parsingError(
					JSON_INVALID_OBJECT_TYPE,
					"Error:  Root object is not object or array.",
					token,
					js
				);
			}

			switch(token->type) {

			case JSMN_OBJECT:

				root = json_alloc(JSON_OBJECT, token->size);
				if(root == NULL) {
					freeResources(root, key, value);
					return parsingError(
						JSON_MEMORY_ALLOC_FAILED,
						"Error:  Unable to allocate root object.",
						token,
						js
					);
				}

				state = KEY;
				break;

			case JSMN_ARRAY:
				state = ARRAY;
				root = json_alloc(JSON_ARRAY, token->size);
				if(root == NULL) {
					freeResources(root, key, value);
					return parsingError(
						JSON_MEMORY_ALLOC_FAILED,
						"Error:  Unable to allocate root array.",
						token,
						js
					);
				}
				break;

			default:
				freeResources(root, key, value);
				return parsingError(
					JSON_INVALID_OBJECT_TYPE,
					"Error:  Root object is not object or array.",
					token,
					js
				);
			}


			object_tokens = token->size;


			if (object_tokens == 0) {
				*json_root = root;
				return NULL; /* exit with no errors */
			}


//			if (object_tokens % 2 != 0)
//				log_die("Invalid response: object must have even number of children. %d\n", tokenIndex);

			break;

		case KEY:

			if (token->type != JSMN_STRING) {
				freeResources(root, key, value);
				return parsingError(
					JSON_INVALID_OBJECT_TYPE,
					"Error:  Object key is not string.",
					token,
					js
				);
			}

			key = json_alloc(JSON_KEY, token->size);
			if(key == NULL) {
				freeResources(root, key, value);
				return parsingError(
					JSON_MEMORY_ALLOC_FAILED,
					"Error: Unable to allocate memory for json key object.",
					token,
					js
				);
			}

			add_value_from_token(key, js, token);

			if(key->value == NULL) {
				freeResources(root, key, value);
				return parsingError(
					JSON_MEMORY_ALLOC_FAILED,
					"Error: Unable to allocate memory for json key string.",
					token,
					js
				);
			}


			error = json_append_child(root, key);

			if( error != NULL) {
				freeResources(root, key, value);
				return error;
			}

			object_tokens--;
			state = VALUE;

			break;

		case VALUE:
//			if (token->type != JSMN_STRING && token->type != JSMN_PRIMITIVE)
//				printf("failed: not string and not primitive skip %d\n", tokenIndex);



			error = allocate_object_by_type(
					&value,
					token, tokens, tokensCount,
					tokenIndex, js);
			if(error != NULL) {
				freeResources(root, key, value);
				return error;
			}

			error = json_append_child(key, value);
			if(error != NULL) {
				freeResources(root, key, value);
				return error;
			}

			object_tokens--;
			state = KEY;

			if (object_tokens == 0) {
				*json_root = root;
				return NULL; /* exit with no errors */
			}

			break;

		case ARRAY:
			if(root->type != JSON_ARRAY) {
				freeResources(root, key, value);
				return parsingError(
					JSON_INVALID_OBJECT_TYPE,
					"Error: In state ARRAY. Parent element is not array",
					token,
					js
				);
			}

			error = allocate_object_by_type(
					&value,
					token, tokens, tokensCount,
					tokenIndex, js);
			if(error != NULL) {
				freeResources(root, key, value);
				return error;
			}

			error = json_append_child(root, value);
			if(error != NULL) {
				freeResources(root, key, value);
				return error;
			}

			object_tokens--;
			state = ARRAY;

			if (object_tokens == 0) {
				*json_root = root;
				return NULL; /* exit with no errors */
			}

			break;

		case STOP:
			// Just consume the tokens
			return NULL; /* exit with no errors */
			break;

		default:
			return parsingError(
				JSON_INLLEGAL_STATE_EXCEPTION,
				"Error: Invalid parsing state. Program should not get here!",
				NULL,
				NULL
			);
		}

	}

	return parsingError(
		JSON_INLLEGAL_STATE_EXCEPTION,
		"Error: Program should not get here!",
		NULL,
		NULL
	);


	//json_object_free(root);

//	for (tokenIndex = 0, tokensLeft = 1; tokensLeft > 0;
//			tokenIndex++, tokensLeft--) {
//
//		jsmntok_t *t = &tokens[tokenIndex];
//
//		// Should never reach uninitialized tokens
//		log_assert(t->start != -1 && t->end != -1);
//
//		if (t->type == JSMN_ARRAY || t->type == JSMN_OBJECT)
//			tokensLeft += t->size;
//
//		switch (state) {
//		case START:
//			if (t->type != JSMN_OBJECT)
//				printf("failed NOt object: %d\n", tokenIndex);
//
//			state = KEY;
//			object_tokens = t->size;
//
//			if (object_tokens == 0)
//				state = STOP;
//
//			if (object_tokens % 2 != 0)
//				printf("failed: %d\n", tokenIndex);
//
//			break;
//
//		case KEY:
//			object_tokens--;
//
//			if (t->type != JSMN_STRING)
//				printf("failed: Key is not string %d\n", tokenIndex);
//
//			state = SKIP;
//
//			for (i = 0; i < sizeof(KEYS) / sizeof(char *); i++) {
//				if (json_token_streq(js, t, KEYS[i])) {
//					printf("%s: ", KEYS[i]);
//					state = PRINT;
//					break;
//				}
//			}
//
//			break;
//
//		case SKIP:
//			if (t->type != JSMN_STRING && t->type != JSMN_PRIMITIVE)
//				printf("failed: not string and not primitive skip %d\n", tokenIndex);
//
//			object_tokens--;
//			state = KEY;
//
//			if (object_tokens == 0)
//				state = STOP;
//
//			break;
//
//		case PRINT:
//			if (t->type != JSMN_STRING && t->type != JSMN_PRIMITIVE)
//				printf("failed not string and not primitive print: %d\n", tokenIndex);
//
//			char *str = json_token_tostr(js, t);
//			puts(str);
//
//			object_tokens--;
//			state = KEY;
//
//			if (object_tokens == 0)
//				state = STOP;
//
//			break;
//
//		case STOP:
//			// Just consume the tokens
//			break;
//
//		default:
//			log_die("Invalid state %u", state);
//		}
//	}
}