Created
January 23, 2014 16:28
-
-
Save condy0919/8581701 to your computer and use it in GitHub Desktop.
stolen from cJSON...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "json.h" | |
static void print_ch(char ch, int n) | |
{ | |
while (n-- > 0) | |
putchar(ch); | |
} | |
static const char* whitespace(const char* src) | |
{ | |
while (isblank(*src) || !isprint(*src)) | |
++src; | |
return src; | |
} | |
json_t* json_new_item() | |
{ | |
json_t* ret = malloc(sizeof(json_t)); | |
if (!ret) | |
return 0; | |
memset(ret, 0, sizeof(json_t)); | |
return ret; | |
} | |
json_t* json_new_null() | |
{ | |
json_t* ret = json_new_item(); | |
if (!ret) | |
return 0; | |
ret->type = JSON_NULL; | |
return ret; | |
} | |
json_t* json_new_true() | |
{ | |
json_t* ret = json_new_item(); | |
if (!ret) | |
return 0; | |
ret->type = JSON_TRUE; | |
ret->value_int = 1; | |
return ret; | |
} | |
json_t* json_new_false() | |
{ | |
json_t* ret = json_new_item(); | |
if (!ret) | |
return 0; | |
ret->type = JSON_FALSE; | |
ret->value_int = 0; | |
return ret; | |
} | |
json_t* json_new_int(const int val) | |
{ | |
json_t* ret = json_new_item(); | |
if (!ret) | |
return 0; | |
ret->type = JSON_NUMBER; | |
ret->number_type = JSON_INT; | |
ret->value_int = val; | |
return ret; | |
} | |
json_t* json_new_double(const double val) | |
{ | |
json_t* ret = json_new_item(); | |
if (!ret) | |
return 0; | |
ret->type = JSON_NUMBER; | |
ret->number_type = JSON_DOUBLE; | |
ret->value_double = val; | |
return ret; | |
} | |
json_t* json_new_string(const char* src) | |
{ | |
json_t* ret = json_new_item(); | |
if (!ret) | |
return 0; | |
ret->type = JSON_STRING; | |
ret->value_string = strdup(src); | |
return ret; | |
} | |
json_t* json_new_bool(const int flag) | |
{ | |
json_t* ret = json_new_item(); | |
if (!ret) | |
return 0; | |
ret->type = JSON_BOOL; | |
ret->value_int = flag; | |
return ret; | |
} | |
json_t* json_new_array() | |
{ | |
json_t* ret = json_new_item(); | |
if (!ret) | |
return 0; | |
ret->type = JSON_ARRAY; | |
return ret; | |
} | |
json_t* json_new_object() | |
{ | |
json_t* ret = json_new_item(); | |
if (!ret) | |
return 0; | |
ret->type = JSON_OBJECT; | |
return ret; | |
} | |
const char* json_parse_number(json_t* item, const char* src) | |
{ | |
double val; | |
const char* p = src; | |
if (!src) | |
return 0; | |
item->type = JSON_NUMBER; | |
sscanf(src, "%lf", &val); | |
if (fabs(val - (int)val) <= DBL_EPSILON) { | |
item->number_type = JSON_INT; | |
item->value_int = val; | |
} else { | |
item->number_type = JSON_DOUBLE; | |
item->value_double = val; | |
} | |
if (*p == '-' || *p == '+') | |
++p; | |
if (*p == '0') | |
++p; | |
else if (isdigit(*p)) { | |
++p; | |
while (isdigit(*p)) | |
++p; | |
} | |
if (*p == '.') { | |
++p; | |
while (isdigit(*p)) | |
++p; | |
} | |
if (*p == 'E' || *p == 'e') | |
++p; | |
if (*p == '+' || *p == '-') | |
++p; | |
while (isdigit(*p)) | |
++p; | |
return p; | |
} | |
const char* json_parse_string(json_t* item, const char* src) | |
{ | |
const char *lp, *rp; | |
if (!src) | |
return 0; | |
item->type = JSON_STRING; | |
lp = src; | |
if (*lp != '\"') | |
return 0; | |
for (rp = lp + 1; *rp; ++rp) | |
if (*rp == '\"' && *(rp - 1) != '\\') | |
break; | |
if (rp == lp + 1) | |
item->value_string = 0; | |
else | |
item->value_string = strndup(lp + 1, rp - lp - 1); | |
return rp + 1; | |
} | |
const char* json_parse_array(json_t* item, const char* src) | |
{ | |
json_t *sub_item, *t; | |
const char* p; | |
if (!src) | |
return 0; | |
item->type = JSON_ARRAY; | |
item->value = sub_item = json_new_item(); | |
p = json_parse_value(sub_item, whitespace(src + 1)); | |
p = whitespace(p); | |
while (*p == ',') { | |
t = json_new_item(); | |
p = whitespace(json_parse_value(t, whitespace(p + 1))); | |
sub_item->next = t; | |
t->prev = sub_item; | |
sub_item = t; | |
} | |
return p + 1; | |
} | |
const char* json_parse_object(json_t* item, const char* src) | |
{ | |
const char* p; | |
json_t *sub_item, *t; | |
if (!src) | |
return 0; | |
item->type = JSON_OBJECT; | |
item->value = sub_item = json_new_item(); | |
p = json_parse_string(sub_item, whitespace(src + 1)); | |
sub_item->key = sub_item->value_string; | |
sub_item->value_string = 0; | |
p = whitespace(p); | |
if (*p != ':') | |
return 0; | |
p = json_parse_value(sub_item, whitespace(p + 1)); | |
p = whitespace(p); | |
while (*p == ',') { | |
t = json_new_item(); | |
p = whitespace(json_parse_string(t, whitespace(p + 1))); | |
t->key = t->value_string; | |
t->value_string = 0; | |
if (*p != ':') | |
return 0; | |
p = whitespace(json_parse_value(t, whitespace(p + 1))); | |
sub_item->next = t; | |
t->prev = sub_item; | |
sub_item = t; | |
} | |
return p + 1; | |
} | |
const char* json_parse_value(json_t* item, const char* src) | |
{ | |
if (!src) | |
return 0; | |
if (*src == '\"') { | |
return json_parse_string(item, src); | |
} else if (*src == '{') { | |
return json_parse_object(item, src); | |
} else if (*src == '[') { | |
return json_parse_array(item, src); | |
} else if (isdigit(*src) || *src == '-' || *src == '+') { | |
return json_parse_number(item, src); | |
} else if (strncmp(src, "true", 4) == 0) { | |
item->type = JSON_TRUE; | |
return src + 4; | |
} else if (strncmp(src, "false", 5) == 0) { | |
item->type = JSON_FALSE; | |
return src + 5; | |
} else if (strncmp(src, "null", 4) == 0) { | |
item->type = JSON_NULL; | |
return src + 4; | |
} | |
return 0; | |
} | |
json_t* json_parse(const char* src) | |
{ | |
const char* p; | |
json_t* ret = json_new_item(); | |
p = json_parse_value(ret, src); | |
return ret; | |
} | |
void json_free(json_t* item) | |
{ | |
json_t *p, *temp; | |
if (!item) | |
return; | |
if (item->type == JSON_ARRAY) { | |
p = item->value; | |
while (p) { | |
temp = p->next; | |
json_free(p); | |
p = temp; | |
} | |
} else if (item->type == JSON_OBJECT) { | |
p = item->value; | |
while (p) { | |
temp = p->next; | |
free(p->key); | |
json_free(p); | |
p = temp; | |
} | |
} else if (item->type == JSON_STRING) { | |
free(item->value_string); | |
} | |
free(item); | |
} | |
void json_print_number(json_t* item) | |
{ | |
if (item->number_type == JSON_INT) | |
printf("%d", item->value_int); | |
else | |
printf("%lf", item->value_double); | |
} | |
void json_print_string(json_t* item) | |
{ | |
putchar('\"'); | |
printf("%s", item->value_string); | |
putchar('\"'); | |
} | |
void json_print_object(json_t* item, int depth) | |
{ | |
json_t* p; | |
char* temp; | |
printf("{\n"); | |
print_ch(' ', 4 * (depth + 1)); | |
p = item->value; | |
temp = p->value_string; | |
p->value_string = p->key; | |
json_print_string(p); | |
p->value_string = temp; | |
putchar(':'); | |
json_print_value(p, depth + 1); | |
for (p = p->next; p; p = p->next) { | |
printf(",\n"); | |
print_ch(' ', 4 * (depth + 1)); | |
temp = p->value_string; | |
p->value_string = p->key; | |
json_print_string(p); | |
p->value_string = temp; | |
putchar(':'); | |
json_print_value(p, depth + 1); | |
} | |
printf("\n"); | |
print_ch(' ', 4 * depth); | |
printf("}"); | |
} | |
void json_print_array(json_t* item, int depth) | |
{ | |
json_t* p; | |
printf("[\n"); | |
print_ch(' ', 4 * (depth + 1)); | |
p = item->value; | |
json_print_value(p, depth + 1); | |
for (p = p->next; p; p = p->next) { | |
printf(",\n"); | |
print_ch(' ', 4 * (depth + 1)); | |
json_print_value(p, depth + 1); | |
} | |
printf("\n"); | |
print_ch(' ', 4 * depth); | |
printf("]"); | |
} | |
void json_print_value(json_t* item, int depth) | |
{ | |
if (item->type == JSON_NUMBER) | |
json_print_number(item); | |
else if (item->type == JSON_STRING) | |
json_print_string(item); | |
else if (item->type == JSON_OBJECT) | |
json_print_object(item, depth); | |
else if (item->type == JSON_ARRAY) | |
json_print_array(item, depth); | |
else if (item->type == JSON_TRUE) | |
printf("true"); | |
else if (item->type == JSON_FALSE) | |
printf("false"); | |
else if (item->type == JSON_BOOL) | |
printf("%s", item->value_int ? "true" : "false"); | |
} | |
void json_print(json_t* item) | |
{ | |
if (!item) | |
return; | |
json_print_value(item, 0); | |
putchar('\n'); | |
} | |
size_t json_get_array_size(json_t* array) | |
{ | |
size_t size = 0; | |
json_t* p; | |
for (p = array->value; p; p = p->next, ++size) | |
; | |
return size; | |
} | |
json_t* json_get_array_item(json_t* array, int idx) | |
{ | |
json_t* p; | |
for (p = array->value; idx > 0 && p; p = p->next, --idx) | |
; | |
return (idx > 0) ? 0 : p; | |
} | |
json_t* json_get_object_item(json_t* object, const char* key) | |
{ | |
json_t* p; | |
for (p = object->value; p; p = p->next) | |
if (strcmp(p->key, key) == 0) | |
break; | |
return p; | |
} | |
json_t* json_new_int_array(int a[], int n) | |
{ | |
int i; | |
json_t* ret = json_new_array(); | |
json_t** p; | |
if (!ret) | |
return 0; | |
for (p = &ret->value, i = 0; i < n; ++i, p = &(*p)->next) { | |
*p = json_new_int(a[i]); | |
if (!*p) | |
return 0; | |
} | |
return ret; | |
} | |
json_t* json_new_double_array(double a[], int n) | |
{ | |
int i; | |
json_t* ret = json_new_array(); | |
json_t** p; | |
if (!ret) | |
return 0; | |
for (p = &ret->value, i = 0; i < n; ++i, p = &(*p)->next) { | |
*p = json_new_double(a[i]); | |
if (!*p) | |
return 0; | |
} | |
return ret; | |
} | |
json_t* json_new_string_array(const char* a[], int n) | |
{ | |
int i; | |
json_t* ret = json_new_array(); | |
json_t** p; | |
if (!ret) | |
return 0; | |
for (p = &ret->value, i = 0; i < n; ++i, p = &(*p)->next) { | |
*p = json_new_string(a[i]); | |
if (!*p) | |
return 0; | |
} | |
return ret; | |
} | |
void json_add_item_to_array(json_t* array, json_t* item) | |
{ | |
json_t* p = array->value; | |
if (!p) { | |
array->value = item; | |
return; | |
} | |
while (p->next) | |
p = p->next; | |
p->next = item; | |
} | |
void json_add_item_to_object(json_t* object, | |
const char* key, json_t* value) | |
{ | |
json_t* p = object->value; | |
if (!p) { | |
object->value = value; | |
object->value->key = strdup(key); | |
return; | |
} | |
while (p->next) | |
p = p->next; | |
p->next = value; | |
p->next->key = strdup(key); | |
} | |
json_t* json_detach_item_from_array(json_t* array, int idx) | |
{ | |
void _remove(json_t* prev, json_t* next) { | |
if (prev) | |
prev->next = next; | |
if (next) | |
next->prev = prev; | |
} | |
json_t *p, *ret; | |
if (!array) | |
return 0; | |
if (idx < 0 || idx >= json_get_array_size(array)) | |
return 0; | |
for (p = array->value; idx > 0; --idx, p = p->next) | |
; | |
_remove(p->prev, p->next); | |
if (p == array->value) | |
array->value = p->next; | |
return p; | |
} | |
void json_delete_item_from_array(json_t* array, int idx) | |
{ | |
json_t* ret = json_detach_item_from_array(array, idx); | |
if (ret) | |
json_free(ret); | |
} | |
json_t* json_detach_item_from_object(json_t* object, | |
const char* key) | |
{ | |
void _remove(json_t* prev, json_t* next) { | |
if (prev) | |
prev->next = next; | |
if (next) | |
next->prev = prev; | |
} | |
json_t* p; | |
if (!object) | |
return 0; | |
for (p = object->value; p; p = p->next) | |
if (strcmp(key, p->key) == 0) | |
break; | |
if (!p) | |
return 0; | |
_remove(p->prev, p->next); | |
if (p == object->value) | |
object->value = p->next; | |
return p; | |
} | |
void json_delete_item_from_object(json_t* object, | |
const char* key) | |
{ | |
json_t* ret = json_detach_item_from_object(object, key); | |
if (ret) | |
json_free(ret); | |
} | |
void json_replace_item_in_array(json_t* array, int idx, | |
json_t* value) | |
{ | |
void diff_copy(json_t* _new, json_t* _old) { | |
// only remain old's `prev', `next' pointers | |
// and key | |
char* t = _old->key; | |
json_t *p = _old->prev, *n = _old->next; | |
memcpy(_old, _new, sizeof(json_t)); | |
_old->key = t; | |
_old->prev = p, _old->next = n; | |
} | |
json_t* p; | |
if (!array || idx < 0 || idx >= json_get_array_size(array)) | |
return; | |
for (p = array->value; idx > 0; --idx, p = p->next) | |
; | |
json_free(p->value); | |
diff_copy(value, p); | |
} | |
void json_replace_item_in_object(json_t* object, | |
const char* key, json_t* value) | |
{ | |
void diff_copy(json_t* _new, json_t* _old) { | |
// only remain old's `prev', `next' pointers | |
// and key | |
char* t = _old->key; | |
json_t *p = _old->prev, *n = _old->next; | |
memcpy(_old, _new, sizeof(json_t)); | |
_old->key = t; | |
_old->prev = p, _old->next = n; | |
} | |
json_t* p; | |
if (!object) | |
return; | |
for (p = object->value; p; p = p->next) | |
if (strcmp(key, p->key) == 0) | |
break; | |
if (!p) | |
return; | |
json_free(p->value); | |
diff_copy(value, p); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef JSON_H | |
#define JSON_H | |
#include <string.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <ctype.h> | |
#include <float.h> | |
#include <math.h> | |
typedef enum type_t { | |
JSON_OBJECT, JSON_ARRAY, JSON_NUMBER, JSON_STRING, JSON_BOOL, | |
JSON_TRUE, JSON_FALSE, JSON_NULL, | |
JSON_INT, JSON_DOUBLE // only used NUMBER | |
} type_t; | |
typedef struct json_t { | |
type_t type; | |
struct json_t *prev, *next;// for object and array | |
char* value_string; | |
type_t number_type; | |
int value_int; | |
double value_double; | |
char* key;// when TYPE == OBJECT | |
struct json_t* value;// when TYPE == OBJECT or ARRAY | |
} json_t; | |
// create an empty item | |
json_t* json_new_item(); | |
// some specified constructors | |
json_t* json_new_null(); | |
json_t* json_new_true(); | |
json_t* json_new_false(); | |
json_t* json_new_int(const int val); | |
json_t* json_new_double(const double val); | |
json_t* json_new_string(const char* src); | |
json_t* json_new_bool(const int flag); | |
json_t* json_new_array(); | |
json_t* json_new_object(); | |
// parse from a string | |
const char* json_parse_number(json_t* item, const char* src); | |
const char* json_parse_string(json_t* item, const char* src); | |
const char* json_parse_object(json_t* item, const char* src); | |
const char* json_parse_array(json_t* item, const char* src); | |
const char* json_parse_value(json_t* item, const char* src); | |
// wrapper for parsing | |
json_t* json_parse(const char* src); | |
// print json_t | |
void json_print_number(json_t* item); | |
void json_print_string(json_t* item); | |
void json_print_object(json_t* item, int depth); | |
void json_print_array(json_t* item, int depth); | |
void json_print_value(json_t* item, int depth); | |
// wrapper for printing | |
void json_print(json_t* item); | |
void json_free(json_t* item); | |
size_t json_get_array_size(json_t* array); | |
json_t* json_get_array_item(json_t* array, int idx); | |
json_t* json_get_object_item(json_t* object, const char* key); | |
// specified array operations | |
json_t* json_new_int_array(int a[], int n); | |
json_t* json_new_double_array(double a[], int n); | |
json_t* json_new_string_array(const char* a[], int n); | |
// add, remove and replace operations | |
void json_add_item_to_array(json_t* array, json_t* item); | |
void json_add_item_to_object(json_t* object, | |
const char* key, json_t* value); | |
json_t* json_detach_item_from_array(json_t* array, int idx); | |
void json_delete_item_from_array(json_t* array, int idx); | |
json_t* json_detach_item_from_object(json_t* object, | |
const char* key); | |
void json_delete_item_from_object(json_t* object, | |
const char* key); | |
void json_replace_item_in_array(json_t* array, int idx, | |
json_t* value); | |
void json_replace_item_in_object(json_t* object, | |
const char* key, json_t* value); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "json.h" | |
int a[] = {1,2,3,4,5}; | |
int main() | |
{ | |
json_t* p; | |
const char* src = "{ \"weatherinfo\" : { \"cityid\" : 1111 , \"weather\" : \"sunny\" }, \"cc\":{\"aa\":123},\"a\":12 }"; | |
const char* s2 = "{\"key1\":\"value1\"}"; | |
p = json_parse(src); | |
json_print(p); | |
json_t* replace = json_new_object(); | |
json_t* val1 = json_new_int(1111); | |
json_add_item_to_object(replace, "int1111", val1); | |
json_t* val2 = json_new_double(2222.2222); | |
json_add_item_to_object(replace, "dbl2222", val2); | |
json_print(replace); | |
json_replace_item_in_object(p, "a", replace); | |
json_print(p); | |
json_free(p); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment