Basic JSON serializer

pull/2/head
Harry Roberts 12 years ago
parent 457fa1100f
commit 23572fa680
  1. 1
      .gitignore
  2. 11
      Makefile
  3. 139
      parson.c
  4. 5
      parson.h
  5. 13
      tests.c

1
.gitignore vendored

@ -1 +1,2 @@
.DS_Store
test

@ -0,0 +1,11 @@
CFLAGS = -O0 -ggdb -Wall -Wextra -std=c89
all: test
.PHONY: test
test: tests.c parson.c
$(CC) $(CFLAGS) -o $@ tests.c parson.c
./$@
clean:
rm -f test *.o

@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#define ERROR 0
#define SUCCESS 1
@ -647,3 +648,141 @@ void json_value_free(JSON_Value *value) {
}
parson_free(value);
}
/* -------------------------------------------------------------------------- */
struct _serialize_str {
char *str;
size_t len;
};
/*
* Callback which appends data to the string
*/
void _serialize_str_cb( const char *str, size_t len, void *data ) {
struct _serialize_str *self = (struct _serialize_str*)data;
if( self->str == NULL ) {
self->str = parson_malloc(len + 1);
assert( self->str != NULL );
strncpy( self->str, str, len );
self->str[ len ] = 0;
self->len = len;
}
else {
self->str = parson_realloc( self->str, self->len + len + 1 );
assert( self->str != NULL );
strncpy( self->str + (self->len), str, len);
self->str[ self->len + len ] = 0;
self->len += len;
}
}
static void
json_serialize_string( const char *str, json_print_cb cb, void *arg ) {
cb("\"", 1, arg);
/* TODO: handle unicode encoding of string?
* XXX: need to be aware of unicode escape sequences so that we don't mess up
*/
cb(str, strlen(str), arg);
cb("\"", 1, arg);
}
static void
json_serialize_number( const JSON_Value *value, json_print_cb cb, void *arg ) {
char buf[64];
size_t len = sprintf(buf, "%.16g", json_value_get_number(value));
cb(buf, len, arg);
}
static void
json_serialize_object( const JSON_Value *value, json_print_cb cb, void *arg ) {
int first = 1;
size_t idx;
JSON_Object* obj = json_value_get_object(value);
const char *name = NULL;
JSON_Value *obj_value = json_object_get_value(obj, name);
cb("{", 1, arg);
for( idx = 0; idx < json_object_get_count(obj); idx++ ) {
name = json_object_get_name(obj, idx);
if( first ) {
first = 0;
}
else {
cb(",", 1, arg);
}
json_serialize_string( name, cb, arg );
cb(":", 1, arg);
json_serialize_cb(obj_value, cb, arg);
}
cb("}", 1, arg);
}
static void
json_serialize_array( const JSON_Value *value, json_print_cb cb, void *arg ) {
int first = 1;
size_t idx;
JSON_Array *array = json_value_get_array(value);
cb("[", 1, arg);
for( idx = 0; idx < json_array_get_count(array); idx++ ) {
if( first ) {
first = 0;
}
else {
cb(",", 1, arg);
}
json_serialize_cb( json_array_get_value(array, idx), cb, arg );
}
cb("]", 1, arg);
}
void
json_serialize_cb( const JSON_Value *value, json_print_cb cb, void *arg ) {
assert( json_value_get_type(value) != JSONError );
switch( json_value_get_type(value) ) {
case JSONNull:
cb( "null", 4, arg );
break;
case JSONString:
json_serialize_string( json_value_get_string(value), cb, arg );
break;
case JSONNumber:
json_serialize_number(value, cb, arg);
break;
case JSONObject:
json_serialize_object(value, cb, arg);
break;
case JSONArray:
json_serialize_array(value, cb, arg);
break;
case JSONBoolean:
if( json_value_get_boolean(value) ) {
cb("true", 4, arg);
}
else {
cb("false", 5, arg);
}
break;
default:
printf("Got unknown type!\n");
/* XXX: this shouldn't ever happen! */
break;
}
}
char *
json_serialize( const JSON_Value *value ) {
struct _serialize_str str;
str.str = NULL;
str.len = 0;
json_serialize_cb( value, &_serialize_str_cb, &str );
return str.str;
}

@ -93,6 +93,11 @@ double json_value_get_number (const JSON_Value *value);
int json_value_get_boolean(const JSON_Value *value);
void json_value_free (JSON_Value *value);
/* Functions for serializing JSON */
typedef void (*json_print_cb)(const char *str, size_t len, void *data);
void json_serialize_cb( const JSON_Value *value, json_print_cb cb, void *arg );
char *json_serialize( const JSON_Value *value );
#ifdef __cplusplus
}
#endif

@ -31,10 +31,12 @@
if(A){puts(" OK");tests_passed++;} \
else{puts(" FAIL");tests_failed++;}
#define STREQ(A, B) (A && B ? strcmp(A, B) == 0 : 0)
#define RESERIALIZE(A) (strcmp(json_serialize(json_parse_string(A)), A) == 0)
void test_suite_1(void);
void test_suite_2(void);
void test_suite_3(void);
void test_suite_4(void);
void print_commits_info(const char *username, const char *repo);
@ -47,6 +49,7 @@ int main(int argc, const char * argv[]) {
test_suite_1();
test_suite_2();
test_suite_3();
test_suite_4();
printf("Tests failed: %d\n", tests_failed);
printf("Tests passed: %d\n", tests_passed);
return 0;
@ -68,7 +71,7 @@ void test_suite_2(void) {
JSON_Value *root_value;
JSON_Object *object;
JSON_Array *array;
int i;
size_t i;
const char *filename = "tests/test_2.txt";
printf("Testing %s:\n", filename);
root_value = json_parse_file(filename);
@ -169,11 +172,17 @@ void test_suite_3(void) {
TEST(json_parse_string("[-07.0]") == NULL);
}
/* Test serialization */
void test_suite_4( void ) {
TEST(RESERIALIZE("[1]"));
TEST(RESERIALIZE("[\"hello\"]"));
}
void print_commits_info(const char *username, const char *repo) {
JSON_Value *root_value;
JSON_Array *commits;
JSON_Object *commit;
int i;
size_t i;
char curl_command[512];
char cleanup_command[256];

Loading…
Cancel
Save