Skip to content

Instantly share code, notes, and snippets.

@condy0919
Created January 23, 2014 16:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save condy0919/8581701 to your computer and use it in GitHub Desktop.
Save condy0919/8581701 to your computer and use it in GitHub Desktop.
stolen from cJSON...
#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);
}
#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
#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