Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ INSTALL_LIBRARY_PATH = $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH)

INSTALL ?= cp -a

CC = gcc -std=c89
CC = gcc -std=c11

# validate gcc version for use fstack-protector-strong
MIN_GCC_VERSION = "4.9"
Expand Down Expand Up @@ -66,7 +66,7 @@ UTILS_STATIC = $(UTILS_LIBNAME).$(STATIC)

SHARED_CMD = $(CC) -shared -o

.PHONY: all shared static tests clean install
.PHONY: all shared static tests mytests clean install

all: shared static tests

Expand All @@ -79,6 +79,9 @@ tests: $(CJSON_TEST)
test: tests
./$(CJSON_TEST)

mytests: cJSON.c mytest.c cJSON.h
gcc -std=c11 -ggdb3 $(R_CFLAGS) cJSON.c mytest.c -o $@ $(LDLIBS) -I.

.c.o:
$(CC) -c $(R_CFLAGS) $<

Expand Down
31 changes: 27 additions & 4 deletions cJSON.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
#include <limits.h>
#include <ctype.h>
#include <float.h>

#include <stdint.h>
#ifdef ENABLE_LOCALES
#include <locale.h>
#endif
Expand Down Expand Up @@ -102,6 +102,17 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item)
return item->valuestring;
}

CJSON_PUBLIC(size_t) cJSON_GetStringValueLength(cJSON *item)
{
if (!cJSON_IsString(item))
{
return 0;
}

return item->valuestring_len;
}


CJSON_PUBLIC(double) cJSON_GetNumberValue(cJSON *item)
{
if (!cJSON_IsNumber(item))
Expand Down Expand Up @@ -301,6 +312,7 @@ typedef struct
static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
{
double number = 0;
uint64_t number64;
unsigned char *after_end = NULL;
unsigned char number_c_string[64];
unsigned char decimal_point = get_decimal_point();
Expand Down Expand Up @@ -367,7 +379,12 @@ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_bu
{
item->valueint = (int)number;
}

number64 = strtoull((const char*)number_c_string, (char**)&after_end, 10);
if(number_c_string == after_end)
{
return false;
}
item->valueint64 = number64;
item->type = cJSON_Number;

input_buffer->offset += (size_t)(after_end - number_c_string);
Expand Down Expand Up @@ -769,7 +786,9 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
unsigned char *output_pointer = NULL;
unsigned char *output_pointer_before = NULL;
unsigned char *output = NULL;
size_t string_length = 0;

/* not a string */
if (buffer_at_offset(input_buffer)[0] != '\"')
Expand Down Expand Up @@ -808,8 +827,8 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
{
goto fail; /* allocation failure */
}
string_length = allocation_length - sizeof("") + skipped_bytes;
}

output_pointer = output;
/* loop through the string literal */
while (input_pointer < input_end)
Expand All @@ -826,7 +845,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
{
goto fail;
}

string_length++;
switch (input_pointer[1])
{
case 'b':
Expand All @@ -852,18 +871,21 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu

/* UTF-16 literal */
case 'u':
output_pointer_before = output_pointer;
sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
if (sequence_length == 0)
{
/* failed to convert UTF16-literal to UTF-8 */
goto fail;
}
string_length += (unsigned int)(output_pointer - output_pointer_before - 1);
break;

default:
goto fail;
}
input_pointer += sequence_length;
string_length -= sequence_length;
}
}

Expand All @@ -872,6 +894,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu

item->type = cJSON_String;
item->valuestring = (char*)output;
item->valuestring_len = string_length;

input_buffer->offset = (size_t) (input_end - input_buffer->content);
input_buffer->offset++;
Expand Down
7 changes: 5 additions & 2 deletions cJSON.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ
#define CJSON_VERSION_PATCH 13

#include <stddef.h>

#include <stdint.h>
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
Expand Down Expand Up @@ -117,9 +117,10 @@ typedef struct cJSON
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;

uint64_t valueint64;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change the cJSON struct and add new feature of C99 is a break change, it will cause incompatibility with C89. I think it should be implemented in v2.0

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crap... the int64 is a temp feature i added since i need int64 support and i think it's implemented badly as i need it now and didn't have time to architect it properly.
i'll open a new PR without it, maybe from a side branch.
I was sure the PR will not change after a commit to the tip of the master :-\

/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
size_t valuestring_len;
} cJSON;

typedef struct cJSON_Hooks
Expand Down Expand Up @@ -177,7 +178,9 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);

/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
CJSON_PUBLIC(size_t) cJSON_GetStringValueLength(cJSON *item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(cJSON *item);
CJSON_PUBLIC(long int) cJSON_Get64NumberValue(cJSON *item);

/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
Expand Down
2 changes: 1 addition & 1 deletion cJSON_Utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_
{
if (opcode == REMOVE)
{
static const cJSON invalid = { NULL, NULL, NULL, cJSON_Invalid, NULL, 0, 0, NULL};
static const cJSON invalid = { NULL, NULL, NULL, cJSON_Invalid, NULL, 0, 0, 0, NULL, 0};

overwrite_item(object, invalid);

Expand Down
35 changes: 35 additions & 0 deletions mytest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "cJSON.h"
#include <stdio.h>
#include <string.h>

char JSON_STR[] = "{ \"val\": \"\\u0000\\u0001\", \"vval\":true, \"test_plain\":\"\\r\\n\", \"plain_text\": \"i'm a text\", \"test_int64\": 18446744073709551610}";
int main(void) {
printf("%s\n", JSON_STR);
cJSON *json = cJSON_Parse(JSON_STR);
if(json == NULL) {
printf("could not parse\n");
return 1;
}
cJSON *json1 = cJSON_GetObjectItem(json, "val");
if(json1 == NULL) {
printf("could not get val\n");
}
printf("val is : *%s*\n", cJSON_GetStringValue(json1));
cJSON *json2 = cJSON_GetObjectItem(json, "test_plain");
if(json2 == NULL) {
printf("could not get val\n");
}
printf("val is : *%s*\n", cJSON_GetStringValue(json2));
cJSON *json3 = cJSON_GetObjectItem(json, "plain_text");
if(json3 == NULL) {
printf("could not get val\n");
}
cJSON *json4 = cJSON_GetObjectItem(json, "test_int64");
printf("got int 64 val: %016lx\n", json4->valueint64);
double asDouble = cJSON_GetNumberValue(json4);
int asInt = json4->valueint;
printf("got val: %e %lx %u\n",asDouble, *((uint64_t*)&asDouble), asInt);
printf("val is : *%s*\nlen is : %lu as opposed to: %lu\n", cJSON_GetStringValue(json3), json3->valuestring_len, strlen(json3->valuestring));
cJSON_Delete(json);
return 0;
}