Yodiwo / YodiwoPlegma

yodiwo_helpers.c

Committer:
mitsarionas
Date:
2015-09-15
Revision:
4:073e23f6718c
Parent:
3:96b08b5f998f
Child:
6:4596aaa1a824

File content as of revision 4:073e23f6718c:



#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "jsmn.h"
#include "yodiwo_api.h"
#include "yodiwo_helpers.h"


/* ======================================================================================================================= */
/* FromJson Functions                                                                                                      */
/* ======================================================================================================================= */

Yodiwo_Plegma_Json_e HelperJsonParseExec(char*json, int jsonSize, ParseTable table[], size_t tableSize)
{
	int i, tokIndex;
	int tokSize;
	jsmntok_t t[64]; /* We expect no more than 128 tokens */
	jsmn_parser p;
	jsmn_init(&p);
	if ((tokSize = jsmn_parse(&p, json, jsonSize, t, sizeof(t) / sizeof(t[0]))) < 0) return Yodiwo_JsonFailedToParse;
	if (tokSize < 1 || t[0].type != JSMN_OBJECT) return Yodiwo_JsonFailedObjectExpected;

	/* Loop over all keys of the root object */
	for (tokIndex = 1; tokIndex < tokSize; tokIndex++) {
		jsmntok_t *tok = &t[tokIndex];
//		printf("Type: %d \n", t[tokIndex + 1].type);

		// Scan the match table
		for (i = 0; i < tableSize; i++) {
			// Try to find a match
			int l = (tok->end - tok->start);
			if ((tok->type == JSMN_PRIMITIVE || tok->type == JSMN_STRING) &&
				(l == table[i].filedNameLength) &&
				(memcmp(&json[tok->start], table[i].fieldName, l) == 0))
			{
				if (table[i].parseFunc != NULL)
				{
					tokIndex += table[i].parseFunc(&t[tokIndex + 1], json, table[i].value);
				}
				else if (table[i].parseFuncSubStruct != NULL)
				{
					// We wait for object
					if (!((t[tokIndex + 1].type == JSMN_OBJECT) || (t[tokIndex + 1].type == JSMN_ARRAY)))
						break;

					table[i].parseFuncSubStruct(&json[t[tokIndex + 1].start], t[tokIndex + 1].end - t[tokIndex + 1].start, table[i].value);

					// Skip sub objects
					int blockEnd = t[tokIndex + 1].end;
					int j;
					for (j = tokIndex + 1; j < tokSize && t[j].end <= blockEnd; j++)
						tokIndex++;
				}
				break;
			}
		}
	}
	return Yodiwo_JsonSuccessParse;
}
// -----------------------------------------------------------------------------------------------------------------------
static void *os_zmalloc(size_t size)
{
	void *p = malloc(size);
	if (p != NULL)
		memset(p, 0, size);
	return p;
}
// -----------------------------------------------------------------------------------------------------------------------
int Parse_String(jsmntok_t* t, char* json, void** result)
{
	int s = t->end - t->start;
	int escaped = count_escaped(&json[t->start], s);
	*result = os_zmalloc(sizeof(char)*(s - escaped + 1));
	if (*result != NULL)
		memcpy_unescaped(*result, &json[t->start], s);
	return 1;
}
// -----------------------------------------------------------------------------------------------------------------------
int Parse_Double(jsmntok_t* t, char* json, void** result)
{
	int s = t->end - t->start;
	char d[100]; memset(d, 0, s);
	memcpy(d, &json[t->start], s);
	*result = atof(d);
	return 1;
}
// -----------------------------------------------------------------------------------------------------------------------
int Parse_Float(jsmntok_t* t, char* json, void** result)
{
	int s = t->end - t->start;
	char d[100]; memset(d, 0, s);
	memcpy(d, &json[t->start], s);
	*result = atof(d);
	return 1;
}
// -----------------------------------------------------------------------------------------------------------------------
int Parse_Int(jsmntok_t* t, char* json, void** result)
{
	int s = t->end - t->start;
	char d[100]; memset(d, 0, s);
	memcpy(d, &json[t->start], s);
	*result = atoi(d);
	return 1;
}
// -----------------------------------------------------------------------------------------------------------------------
int Parse_Bool(jsmntok_t* t, char* json, void** result)
{
	int s = t->end - t->start;
	char d[100]; memset(d, 0, s);
	memcpy(d, &json[t->start], s);
	if (t->type == JSMN_STRING)
	{
		if (memcmp(d, "true", 4) == 0 ||
			memcmp(d, "True", 4) == 0 ||
			memcmp(d, "TRUE", 4) == 0)
			*result = true;
		else
			*result = false;
	}
	else
	{
		*result = atoi(d) > 0;
	}
	return 1;
}
// -----------------------------------------------------------------------------------------------------------------------
// Parse array and find sub structs
// NOTE: this replace the T with the sub elements !!!!
int Helper_Json_ParseArray(jsmntok_t t[], int tokSize)
{
	int i, n = 0, j;
	for (i = 1; i < tokSize; i++)
	{
		// We wait for object
		if (t[i].type != JSMN_OBJECT)
			break;

		// store the element
		t[n] = t[i];
		n++;

		// Skip sub objects
		int blockEnd = t[i].end;
		for (j = i + 1; j < tokSize && t[j].end <= blockEnd; j++)
			i++;
	}
	return n;
}
// -----------------------------------------------------------------------------------------------------------------------
int Helper_Json_ParseArrayType(jsmntok_t t[], int tokSize, jsmntype_t type)
{
	int i, n = 0, j;
	for (i = 1; i < tokSize; i++)
	{
		// We wait for object
		if (t[i].type != type)
			break;

		// store the element
		t[n] = t[i];
		n++;

		// Skip sub objects
		int blockEnd = t[i].end;
		for (j = i + 1; j < tokSize && t[j].end <= blockEnd; j++)
			i++;
	}
	return n;
}
// -----------------------------------------------------------------------------------------------------------------------
// Primitive helperf ToJsonFunction
int Array_string_ToJson(char* jsonStart, size_t jsonSize, Array_string *array)
{
	int i = 0, len; char *json = jsonStart, *jsonEnd = json + jsonSize;
	*json = '['; json++;
	if (array != NULL) {
		for (i = 0; i < array->num && json < jsonEnd; i++) {
			if ((len = snprintf(json, jsonEnd - json - 2, "\"%s\"", array->elems[i])) < 0)
				return -1;
			else json += len;
			*json = ','; json++;
		}
		if (i > 0) json--; // remove last ,
	}
	*json = ']'; json++;
	*json = '\0'; json++;
	return json - jsonStart;
}
// -----------------------------------------------------------------------------------------------------------------------
Yodiwo_Plegma_Json_e Array_string_FromJson(char* json, size_t jsonSize, Array_string *array)
{
	int i = 0, r;
	Yodiwo_Plegma_Json_e  res = Yodiwo_JsonSuccessParse;
	jsmntok_t t[64]; /* We expect no more than 64 tokens */
	jsmn_parser p;
	jsmn_init(&p);
	if ((r = jsmn_parse(&p, json, jsonSize, t, sizeof(t) / sizeof(t[0]))) < 0) return Yodiwo_JsonFailedToParse;
	if (r < 1 || t[0].type != JSMN_ARRAY) return Yodiwo_JsonFailedObjectExpected;

	array->num = Helper_Json_ParseArrayType(t, r, JSMN_STRING);
	array->elems = (char**)os_zmalloc(array->num*sizeof(char*));
	for (i = 0; i < array->num; i++) {
		int size = t[i].end - t[i].start;
		array->elems[i] = (char*)os_zmalloc((size + 1)*sizeof(char)); // add and a zero lead
		if (array->elems[i] == NULL)
			break;

		// copy the string
		memcpy(array->elems[i], &json[t[i].start], size);
	}
	if (i == array->num)
		return Yodiwo_JsonSuccessParse;
	return res;
}
// -----------------------------------------------------------------------------------------------------------------------