mirror of
https://github.com/kgabis/parson.git
synced 2025-07-15 16:32:08 +00:00
Basic JSON serializer
This commit is contained in:
parent
457fa1100f
commit
23572fa680
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
|
test
|
||||||
|
11
Makefile
Normal file
11
Makefile
Normal file
@ -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
|
139
parson.c
139
parson.c
@ -27,6 +27,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#define ERROR 0
|
#define ERROR 0
|
||||||
#define SUCCESS 1
|
#define SUCCESS 1
|
||||||
@ -647,3 +648,141 @@ void json_value_free(JSON_Value *value) {
|
|||||||
}
|
}
|
||||||
parson_free(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;
|
||||||
|
}
|
||||||
|
5
parson.h
5
parson.h
@ -93,6 +93,11 @@ double json_value_get_number (const JSON_Value *value);
|
|||||||
int json_value_get_boolean(const JSON_Value *value);
|
int json_value_get_boolean(const JSON_Value *value);
|
||||||
void json_value_free (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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
13
tests.c
13
tests.c
@ -31,10 +31,12 @@
|
|||||||
if(A){puts(" OK");tests_passed++;} \
|
if(A){puts(" OK");tests_passed++;} \
|
||||||
else{puts(" FAIL");tests_failed++;}
|
else{puts(" FAIL");tests_failed++;}
|
||||||
#define STREQ(A, B) (A && B ? strcmp(A, B) == 0 : 0)
|
#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_1(void);
|
||||||
void test_suite_2(void);
|
void test_suite_2(void);
|
||||||
void test_suite_3(void);
|
void test_suite_3(void);
|
||||||
|
void test_suite_4(void);
|
||||||
|
|
||||||
void print_commits_info(const char *username, const char *repo);
|
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_1();
|
||||||
test_suite_2();
|
test_suite_2();
|
||||||
test_suite_3();
|
test_suite_3();
|
||||||
|
test_suite_4();
|
||||||
printf("Tests failed: %d\n", tests_failed);
|
printf("Tests failed: %d\n", tests_failed);
|
||||||
printf("Tests passed: %d\n", tests_passed);
|
printf("Tests passed: %d\n", tests_passed);
|
||||||
return 0;
|
return 0;
|
||||||
@ -68,7 +71,7 @@ void test_suite_2(void) {
|
|||||||
JSON_Value *root_value;
|
JSON_Value *root_value;
|
||||||
JSON_Object *object;
|
JSON_Object *object;
|
||||||
JSON_Array *array;
|
JSON_Array *array;
|
||||||
int i;
|
size_t i;
|
||||||
const char *filename = "tests/test_2.txt";
|
const char *filename = "tests/test_2.txt";
|
||||||
printf("Testing %s:\n", filename);
|
printf("Testing %s:\n", filename);
|
||||||
root_value = json_parse_file(filename);
|
root_value = json_parse_file(filename);
|
||||||
@ -169,11 +172,17 @@ void test_suite_3(void) {
|
|||||||
TEST(json_parse_string("[-07.0]") == NULL);
|
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) {
|
void print_commits_info(const char *username, const char *repo) {
|
||||||
JSON_Value *root_value;
|
JSON_Value *root_value;
|
||||||
JSON_Array *commits;
|
JSON_Array *commits;
|
||||||
JSON_Object *commit;
|
JSON_Object *commit;
|
||||||
int i;
|
size_t i;
|
||||||
|
|
||||||
char curl_command[512];
|
char curl_command[512];
|
||||||
char cleanup_command[256];
|
char cleanup_command[256];
|
||||||
|
Loading…
Reference in New Issue
Block a user