<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jsmn/jsmn.h"
#include "../../citrine.h"

/**
 * [Json] new
 *
 * Creates a new instance of the Json object.
 * The Json object allows you to use the Json protocol to communicate with
 * other applications.
 */
ctr_object* ctr_json_new(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* jsonInstance = ctr_internal_create_object(CTR_OBJECT_TYPE_OTOBJECT);
	jsonInstance->link = myself;
	return jsonInstance;
}

/**
 * @internal
 */
ctr_object* ctr_jsmn_dump( char* data, jsmntok_t** tt ) {
	ctr_object* answer;
	ctr_argument* a;
	ctr_argument* b;
	char c;
	a = NULL;
	b = NULL;
	int i;
	jsmntok_t* t = *(tt);
	if (t->type == JSMN_STRING) {
		answer = ctr_build_string( (data + t->start), (t->end - t->start) );
		*(tt)+=1;
	}
	else if (t->type == JSMN_PRIMITIVE ) {
		c = *(data + t->start);
		if ( c == 't' ) {
			answer = ctr_build_bool( 1 );
		} else if ( c == 'f' ) {
			answer = ctr_build_bool( 0 );
		} else if ( c == 'n' ) {
			answer = ctr_build_nil();
		} else if ( c == '-' || ( c >= '0' && c <= '9' ) ) {
			answer = ctr_string_to_number( ctr_build_string( (char*) (data + t->start), (t->end - t->start) ), a );
		} else {
			answer = CtrStdNil;
		}
		*(tt)+=1;
	}
	else if (t->type == JSMN_ARRAY) {
		a = ctr_heap_allocate( sizeof(ctr_argument) );
		answer = ctr_array_new( CtrStdArray, NULL );
		*(tt)+=1;
		for(i = 0; i<t->size; i++ ) {
			ctr_object* element = ctr_jsmn_dump( data, tt );
			a->object = element;
			ctr_array_push( answer, a );
		}
		ctr_heap_free(a);
	}
	else if (t->type == JSMN_OBJECT ) {
		a = ctr_heap_allocate( sizeof(ctr_argument) );
		b = ctr_heap_allocate( sizeof(ctr_argument) );
		answer = ctr_map_new( CtrStdMap, NULL );
		*(tt)+=1;
		for (i = 0; i<(t->size); i+=1) {
			ctr_object* property = ctr_jsmn_dump( data, tt );
			ctr_object* value = ctr_jsmn_dump( data, tt );
			a->object = value;
			b->object = property;
			a->next = b;
			ctr_map_put( answer, a );
		}
		ctr_heap_free(a);
		ctr_heap_free(b);
	}
	else {
		answer = CtrStdNil;
		*(tt)+=1;
	}
	return answer;
}

/**
 * [Json] parse: [String].
 * 
 * Parses a string containing Json encoded data into native Citrine objects.
 * The Json structure must begin with an object (notation: {}). Therefore,
 * the answer to this message from the Json object will always be a Map.
 *
 * Usage:
 *
 * ☞ tasks := '{"todo":7,"finished":3}'.
 * ✎ write: tasks todo. #7
 *
 */
ctr_object* ctr_json_parse(ctr_object* myself, ctr_argument* argumentList) {
	char* jsonString = ctr_heap_allocate_cstring(
		ctr_internal_cast2string( argumentList->object )
	);
	ctr_size size;
	jsmn_parser jsmn;
	jsmn_parser jsmn2;
	ctr_object* answer;
	jsmntok_t* t;
	jsmntok_t* ot;
	int r;
	jsmn_init(&jsmn);
	size = (ctr_size) jsmn_parse(&jsmn, jsonString, strlen(jsonString), NULL, 0);
	t = (jsmntok_t*) ctr_heap_allocate( sizeof(jsmntok_t) * size );
	ot = t;
	jsmn_init(&jsmn2);
	r = jsmn_parse(&jsmn2, jsonString, strlen(jsonString), t, size);
	if (r < size || t[0].type != JSMN_OBJECT) {
		ctr_heap_free( t );
		ctr_heap_free( jsonString );
		return CtrStdNil;
	}
	answer = ctr_jsmn_dump(jsonString, &t);
	ctr_heap_free( ot );
	ctr_heap_free( jsonString );
	return answer;
}

/**
 * [Json] jsonify: [Map].
 *<commit_msg>Improve error handling.<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jsmn/jsmn.h"
#include "../../citrine.h"

/**
 * [Json] new
 *
 * Creates a new instance of the Json object.
 * The Json object allows you to use the Json protocol to communicate with
 * other applications.
 */
ctr_object* ctr_json_new(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* jsonInstance = ctr_internal_create_object(CTR_OBJECT_TYPE_OTOBJECT);
	jsonInstance->link = myself;
	return jsonInstance;
}

/**
 * @internal
 */
ctr_object* ctr_jsmn_dump( char* data, jsmntok_t** tt ) {
	ctr_object* answer;
	ctr_argument* a;
	ctr_argument* b;
	char c;
	a = NULL;
	b = NULL;
	int i;
	jsmntok_t* t = *(tt);
	if (t->type == JSMN_STRING) {
		answer = ctr_build_string( (data + t->start), (t->end - t->start) );
		*(tt)+=1;
	}
	else if (t->type == JSMN_PRIMITIVE ) {
		c = *(data + t->start);
		if ( c == 't' ) {
			answer = ctr_build_bool( 1 );
		} else if ( c == 'f' ) {
			answer = ctr_build_bool( 0 );
		} else if ( c == 'n' ) {
			answer = ctr_build_nil();
		} else if ( c == '-' || ( c >= '0' && c <= '9' ) ) {
			answer = ctr_string_to_number( ctr_build_string( (char*) (data + t->start), (t->end - t->start) ), a );
		} else {
			answer = CtrStdNil;
		}
		*(tt)+=1;
	}
	else if (t->type == JSMN_ARRAY) {
		a = ctr_heap_allocate( sizeof(ctr_argument) );
		answer = ctr_array_new( CtrStdArray, NULL );
		*(tt)+=1;
		for(i = 0; i<t->size; i++ ) {
			ctr_object* element = ctr_jsmn_dump( data, tt );
			a->object = element;
			ctr_array_push( answer, a );
		}
		ctr_heap_free(a);
	}
	else if (t->type == JSMN_OBJECT ) {
		a = ctr_heap_allocate( sizeof(ctr_argument) );
		b = ctr_heap_allocate( sizeof(ctr_argument) );
		answer = ctr_map_new( CtrStdMap, NULL );
		*(tt)+=1;
		for (i = 0; i<(t->size); i+=1) {
			ctr_object* property = ctr_jsmn_dump( data, tt );
			ctr_object* value = ctr_jsmn_dump( data, tt );
			a->object = value;
			b->object = property;
			a->next = b;
			ctr_map_put( answer, a );
		}
		ctr_heap_free(a);
		ctr_heap_free(b);
	}
	else {
		answer = CtrStdNil;
		*(tt)+=1;
	}
	return answer;
}

/**
 * [Json] parse: [String].
 * 
 * Parses a string containing Json encoded data into native Citrine objects.
 * The Json structure must begin with an object (notation: {}). Therefore,
 * the answer to this message from the Json object will always be a Map.
 *
 * Usage:
 *
 * ☞ tasks := '{"todo":7,"finished":3}'.
 * ✎ write: tasks todo. #7
 *
 */
ctr_object* ctr_json_parse(ctr_object* myself, ctr_argument* argumentList) {
	char* jsonString = ctr_heap_allocate_cstring(
		ctr_internal_cast2string( argumentList->object )
	);
	ctr_size size;
	jsmn_parser jsmn;
	jsmn_parser jsmn2;
	ctr_object* answer;
	jsmntok_t* t;
	jsmntok_t* ot;
	int r;
	int s;
	jsmn_init(&jsmn);
	s = jsmn_parse(&jsmn, jsonString, strlen(jsonString), NULL, 0);
	printf("size = %d \n", s);
	if ( s <= 0 ) {
		ctr_heap_free( jsonString );
		if ( s == JSMN_ERROR_INVAL ) {
			CtrStdFlow = ctr_build_string_from_cstring("Bad token, JSON string is corrupted.");
		}
		return CtrStdNil;
	}
	size = (ctr_size) s;
	t = (jsmntok_t*) ctr_heap_allocate( sizeof(jsmntok_t) * size );
	ot = t;
	jsmn_init(&jsmn2);
	r = jsmn_parse(&jsmn2, jsonString, strlen(jsonString), t, size);
	if (r < size || t[0].type != JSMN_OBJECT) {
		ctr_heap_free( t );
		ctr_heap_free( jsonString );
		return CtrStdNil;
	}
	answer = ctr_jsmn_dump(jsonString, &t);
	ctr_heap_free( ot );
	ctr_heap_free( jsonString );
	return answer;
}

/**
 * [Json] jsonify: [Map].
 *
{'fraction_non_alphanumeric': 0.16464217766720327, 'fraction_numerical': 0.0062929899019464365, 'mean_word_length': 3.7425399028452464, 'pattern_counts': {'":': 4, '<': 18, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7178426', 'n_tokens_mistral': 2983, 'n_tokens_neox': 2882, 'n_words': 661}