Separate integers and real numbers

This commit is contained in:
Petri Lehtinen 2009-06-23 00:14:28 +03:00
parent 39802813f4
commit b724c2b122
4 changed files with 120 additions and 35 deletions

View File

@ -106,12 +106,26 @@ static int do_dump(const json_t *json, uint32_t flags, int depth,
case JSON_FALSE:
return dump("false", 5, data);
case JSON_NUMBER:
case JSON_INTEGER:
{
char *buffer;
int size, ret;
size = asprintf(&buffer, "%.17f", json_number_value(json));
size = asprintf(&buffer, "%d", json_integer_value(json));
if(size == -1)
return -1;
ret = dump(buffer, size, data);
free(buffer);
return ret;
}
case JSON_REAL:
{
char *buffer;
int size, ret;
size = asprintf(&buffer, "%.17f", json_real_value(json));
if(size == -1)
return -1;

View File

@ -10,7 +10,8 @@ typedef enum {
JSON_OBJECT,
JSON_ARRAY,
JSON_STRING,
JSON_NUMBER,
JSON_INTEGER,
JSON_REAL,
JSON_TRUE,
JSON_FALSE,
JSON_NULL
@ -25,7 +26,9 @@ typedef struct {
#define json_is_object(json) (json && json_typeof(json) == JSON_OBJECT)
#define json_is_array(json) (json && json_typeof(json) == JSON_ARRAY)
#define json_is_string(json) (json && json_typeof(json) == JSON_STRING)
#define json_is_number(json) (json && json_typeof(json) == JSON_NUMBER)
#define json_is_integer(json) (json && json_typeof(json) == JSON_INTEGER)
#define json_is_real(json) (json && json_typeof(json) == JSON_REAL)
#define json_is_number(json) (json_is_integer(json) || json_is_real(json))
#define json_is_true(json) (json && json_typeof(json) == JSON_TRUE)
#define json_is_false(json) (json && json_typeof(json) == JSON_FALSE)
#define json_is_null(json) (json && json_typeof(json) == JSON_NULL)
@ -35,7 +38,8 @@ typedef struct {
json_t *json_object(void);
json_t *json_array(void);
json_t *json_string(const char *value);
json_t *json_number(double value);
json_t *json_integer(int value);
json_t *json_real(double value);
json_t *json_true(void);
json_t *json_false(void);
json_t *json_null(void);
@ -75,6 +79,8 @@ int json_array_set(json_t *array, unsigned int index, json_t *value);
int json_array_append(json_t *array, json_t *value);
const char *json_string_value(const json_t *json);
int json_integer_value(const json_t *json);
double json_real_value(const json_t *json);
double json_number_value(const json_t *json);

View File

@ -15,10 +15,11 @@
#define JSON_TOKEN_INVALID -1
#define JSON_TOKEN_EOF 0
#define JSON_TOKEN_STRING 256
#define JSON_TOKEN_NUMBER 257
#define JSON_TOKEN_TRUE 258
#define JSON_TOKEN_FALSE 259
#define JSON_TOKEN_NULL 260
#define JSON_TOKEN_INTEGER 257
#define JSON_TOKEN_REAL 258
#define JSON_TOKEN_TRUE 259
#define JSON_TOKEN_FALSE 260
#define JSON_TOKEN_NULL 261
typedef struct {
const char *input;
@ -27,7 +28,8 @@ typedef struct {
int line, column;
union {
char *string;
double number;
int integer;
double real;
} value;
} json_lex;
@ -176,7 +178,16 @@ static void json_scan_number(json_lex *lex)
p++;
}
if(*p == '.') {
if(*p != '.') {
lex->token = JSON_TOKEN_INTEGER;
lex->value.integer = strtol(lex->start, &end, 10);
assert(end == p);
lex->input = p;
return;
}
else /* *p == '.' */ {
p++;
if(!isdigit(*(p++)))
goto out;
@ -197,9 +208,9 @@ static void json_scan_number(json_lex *lex)
p++;
}
lex->token = JSON_TOKEN_NUMBER;
lex->token = JSON_TOKEN_REAL;
lex->value.number = strtod(lex->start, &end);
lex->value.real = strtod(lex->start, &end);
assert(end == p);
out:
@ -402,8 +413,13 @@ static json_t *json_parse(json_lex *lex, json_error_t *error)
break;
}
case JSON_TOKEN_NUMBER: {
json = json_number(lex->value.number);
case JSON_TOKEN_INTEGER: {
json = json_integer(lex->value.integer);
break;
}
case JSON_TOKEN_REAL: {
json = json_real(lex->value.real);
break;
}

View File

@ -29,12 +29,18 @@ typedef struct {
typedef struct {
json_t json;
double value;
} json_number_t;
} json_real_t;
typedef struct {
json_t json;
int value;
} json_integer_t;
#define json_to_object(json_) container_of(json_, json_object_t, json)
#define json_to_array(json_) container_of(json_, json_array_t, json)
#define json_to_string(json_) container_of(json_, json_string_t, json)
#define json_to_number(json_) container_of(json_, json_number_t, json)
#define json_to_real(json_) container_of(json_, json_real_t, json)
#define json_to_integer(json_) container_of(json_, json_integer_t, json)
static inline void json_init(json_t *json, json_type type)
{
@ -274,15 +280,58 @@ static void json_delete_string(json_string_t *string)
free(string);
}
json_t *json_number(double value)
{
json_number_t *number = malloc(sizeof(json_number_t));
if(!number)
return NULL;
json_init(&number->json, JSON_NUMBER);
number->value = value;
return &number->json;
/*** integer ***/
json_t *json_integer(int value)
{
json_integer_t *integer = malloc(sizeof(json_integer_t));
if(!integer)
return NULL;
json_init(&integer->json, JSON_INTEGER);
integer->value = value;
return &integer->json;
}
int json_integer_value(const json_t *json)
{
if(!json_is_integer(json))
return 0;
return json_to_integer(json)->value;
}
static void json_delete_integer(json_integer_t *integer)
{
free(integer);
}
/*** real ***/
json_t *json_real(double value)
{
json_real_t *real = malloc(sizeof(json_real_t));
if(!real)
return NULL;
json_init(&real->json, JSON_REAL);
real->value = value;
return &real->json;
}
double json_real_value(const json_t *json)
{
if(!json_is_real(json))
return 0;
return json_to_real(json)->value;
}
static void json_delete_real (json_real_t *real)
{
free(real);
}
@ -290,15 +339,12 @@ json_t *json_number(double value)
double json_number_value(const json_t *json)
{
if(!json_is_number(json))
if(json_is_integer(json))
return json_integer_value(json);
else if(json_is_real(json))
return json_real_value(json);
else
return 0.0;
return json_to_number(json)->value;
}
static void json_delete_number(json_number_t *number)
{
free(number);
}
@ -347,8 +393,11 @@ void json_delete(json_t *json)
else if(json_is_string(json))
json_delete_string(json_to_string(json));
else if(json_is_number(json))
json_delete_number(json_to_number(json));
else if(json_is_integer(json))
json_delete_integer(json_to_integer(json));
else if(json_is_real(json))
json_delete_real(json_to_real(json));
/* json_delete is not called for true, false or null */
}