Browse Source

Additional changes to json to contain null characters

pull/715/head
HexTheDragon 4 years ago
parent
commit
3c0a85c9e8
10 changed files with 106 additions and 29 deletions
  1. +5
    -1
      json-c.sym
  2. +56
    -13
      json_object.c
  3. +21
    -7
      json_object.h
  4. +2
    -2
      json_object_iterator.c
  5. +2
    -1
      json_object_iterator.h
  6. +1
    -1
      json_types.h
  7. +2
    -2
      json_visit.c
  8. +2
    -1
      json_visit.h
  9. +6
    -1
      linkhash.c
  10. +9
    -0
      linkhash.h

+ 5
- 1
json-c.sym View File

@@ -3,7 +3,7 @@
* Symbol versioning for libjson-c.
* All exported symbols must be listed here.
*
* See
* See
* https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf
*/

@@ -166,8 +166,12 @@ JSONC_0.15 {

JSONC_0.16 {
global:
lh_string_data;
lh_string_size;
lh_string_print;
json_object_object_add_len;
json_object_object_add_ex_len;
json_object_object_del_len;
json_object_object_get_len;
json_object_object_get_ex_len;
} JSONC_0.15;

+ 56
- 13
json_object.c View File

@@ -116,6 +116,14 @@ static inline const struct json_object_string *JC_STRING_C(const struct json_obj
static inline struct json_object *json_object_new(enum json_type o_type, size_t alloc_size,
json_object_to_json_string_fn *to_json_string);

static int json_object_object_add_internal(struct json_object *jso, const struct lh_string *key,
struct json_object *const val, const unsigned opts);
static int json_object_object_del_internal(struct json_object *jso_base,
const struct lh_string *key);
static json_bool json_object_object_get_internal(const struct json_object *jso,
const struct lh_string *key,
struct json_object **value);

static void json_object_object_delete(struct json_object *jso_base);
static void json_object_string_delete(struct json_object *jso);
static void json_object_array_delete(struct json_object *jso);
@@ -506,7 +514,7 @@ static int json_object_object_to_json_string(struct json_object *jso, struct pri
printbuf_strappend(pb, " ");
indent(pb, level + 1, flags);
printbuf_strappend(pb, "\"");
json_escape_str(pb, iter.key, strlen(iter.key), flags);
json_escape_str(pb, lh_string_data(iter.key), lh_string_size(iter.key), flags);
if (flags & JSON_C_TO_STRING_SPACED)
printbuf_strappend(pb, "\": ");
else
@@ -576,12 +584,21 @@ int json_object_object_add_ex(struct json_object *jso, const char *const key,

int json_object_object_add_ex_len(struct json_object *jso, const char *const key, const int len,
struct json_object *const val, const unsigned opts)
{
// Created on the stack rather than calling `lh_string_new_ptr`
// or `lh_string_new_imm` since this saves copying `key` if it turns
// out the value already exists in the hash table
const struct lh_string hashable = {.length = len, .str = {.pdata = key}};
return json_object_object_add_internal(jso, &hashable, val, opts);
}

int json_object_object_add_internal(struct json_object *jso, const struct lh_string *key,
struct json_object *const val, const unsigned opts)
{
struct json_object *existing_value;
struct lh_entry *existing_entry;
unsigned long hash;
/** Required due to the `lh_get_hash` function wanting a `const struct lh_string *` */
const struct lh_string hashable = {.length = len, .str = {.pdata = key}};

assert(json_object_get_type(jso) == json_type_object);

@@ -594,7 +611,7 @@ int json_object_object_add_ex_len(struct json_object *jso, const char *const key

// We lookup the entry and replace the value, rather than just deleting
// and re-adding it, so the existing key remains valid.
hash = lh_get_hash(JC_OBJECT(jso)->c_object, (const void *)&hashable);
hash = lh_get_hash(JC_OBJECT(jso)->c_object, key);
existing_entry =
(opts & JSON_C_OBJECT_ADD_KEY_IS_NEW)
? NULL
@@ -602,9 +619,15 @@ int json_object_object_add_ex_len(struct json_object *jso, const char *const key

if (existing_entry == NULL)
{
const struct lh_string *k = (opts & JSON_C_OBJECT_KEY_IS_CONSTANT)
? lh_string_new_ptr(len, key)
: lh_string_new_imm(len, key);
// need to copy `key` because the caller might have created it
// on the stack, which would be more efficient than copying
// `lh_string_data` into `key->string.idata` if it had happened
// that `existing_entry` wasn't NULL.
const struct lh_string *k =
(opts & JSON_C_OBJECT_KEY_IS_CONSTANT)
? lh_string_new_ptr(lh_string_size(key), lh_string_data(key))
: lh_string_new_imm(lh_string_size(key), lh_string_data(key));
// TODO some optimization where (opts & JSON_C_OBJECT_ADD_KEY_IS_NEW)
if (k == NULL)
{
return -1;
@@ -681,8 +704,10 @@ json_bool json_object_object_get_ex_len(const struct json_object *jso, const cha
switch (jso->o_type)
{
case json_type_object:
return lh_table_lookup_ex(JC_OBJECT_C(jso)->c_object, (const void *)key,
(void **)value);
{
const struct lh_string hashable = {.length = len, .str = {.pdata = key}};
return json_object_object_get_internal(jso, &hashable, value);
}
default:
if (value != NULL)
*value = NULL;
@@ -690,10 +715,28 @@ json_bool json_object_object_get_ex_len(const struct json_object *jso, const cha
}
}

json_bool json_object_object_get_internal(const struct json_object *jso,
const struct lh_string *key, struct json_object **value)
{
assert(json_object_get_type(jso) == json_type_object);
return lh_table_lookup_ex(JC_OBJECT_C(jso)->c_object, key, (void **)value);
}

void json_object_object_del(struct json_object *jso, const char *key)
{
json_object_object_del_len(jso, key, strlen(key));
}

void json_object_object_del_len(struct json_object *jso, const char *key, const int len)
{
const struct lh_string hashable = {.length = len, .str = {.pdata = key}};
json_object_object_del_internal(jso, &hashable);
}

int json_object_object_del_internal(struct json_object *jso, const struct lh_string *key)
{
assert(json_object_get_type(jso) == json_type_object);
lh_table_delete(JC_OBJECT(jso)->c_object, key);
return lh_table_delete(JC_OBJECT(jso)->c_object, key);
}

/* json_object_boolean */
@@ -1680,7 +1723,7 @@ static int json_object_copy_serializer_data(struct json_object *src, struct json
*
* This always returns -1 or 1. It will never return 2 since it does not copy the serializer.
*/
int json_c_shallow_copy_default(json_object *src, json_object *parent, const char *key,
int json_c_shallow_copy_default(json_object *src, json_object *parent, const struct lh_string *key,
size_t index, json_object **dst)
{
switch (src->o_type)
@@ -1728,8 +1771,8 @@ int json_c_shallow_copy_default(json_object *src, json_object *parent, const cha
* Note: caller is responsible for freeing *dst if this fails and returns -1.
*/
static int json_object_deep_copy_recursive(struct json_object *src, struct json_object *parent,
const char *key_in_parent, size_t index_in_parent,
struct json_object **dst,
const struct lh_string *key_in_parent,
size_t index_in_parent, struct json_object **dst,
json_c_shallow_copy_fn *shallow_copy)
{
struct json_object_iter iter;
@@ -1761,7 +1804,7 @@ static int json_object_deep_copy_recursive(struct json_object *src, struct json_
return -1;
}

if (json_object_object_add(*dst, iter.key, jso) < 0)
if (json_object_object_add_internal(*dst, iter.key, jso, 0) < 0)
{
json_object_put(jso);
return -1;


+ 21
- 7
json_object.h View File

@@ -547,6 +547,19 @@ JSON_EXPORT json_bool json_object_object_get_ex_len(const struct json_object *ob
*/
JSON_EXPORT void json_object_object_del(struct json_object *obj, const char *key);

/** Delete the given json_object field
*
* The reference count will be decremented for the deleted object. If there
* are no more owners of the value represented by this key, then the value is
* freed. Otherwise, the reference to the value will remain in memory.
*
* @param obj the json_object instance
* @param key the object field name,
* which is not terminated by a NULL ( @c '\0' ) character
* @param len the length of @p key
*/
void json_object_object_del_len(struct json_object *jso, const char *key, const int len);

/**
* Iterate through all keys and values of an object.
*
@@ -560,17 +573,18 @@ JSON_EXPORT void json_object_object_del(struct json_object *obj, const char *key
* @param val the local name for the json_object* object variable defined in
* the body
*/
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && \
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)

#define json_object_object_foreach(obj, key, val) \
char *key = NULL; \
struct lh_string *key = NULL; \
struct json_object *val __attribute__((__unused__)) = NULL; \
for (struct lh_entry *entry##key = json_object_get_object(obj)->head, \
*entry_next##key = NULL; \
({ \
if (entry##key) \
{ \
key = (char *)lh_entry_k(entry##key); \
key = (struct lh_string *)lh_entry_k(entry##key); \
val = (struct json_object *)lh_entry_v(entry##key); \
entry_next##key = entry##key->next; \
}; \
@@ -600,7 +614,7 @@ JSON_EXPORT void json_object_object_del(struct json_object *obj, const char *key
*/
#define json_object_object_foreachC(obj, iter) \
for (iter.entry = json_object_get_object(obj)->head; \
(iter.entry ? (iter.key = (char *)lh_entry_k(iter.entry), \
(iter.entry ? (iter.key = (struct lh_string *)lh_entry_k(iter.entry), \
iter.val = (struct json_object *)lh_entry_v(iter.entry), iter.entry) \
: 0); \
iter.entry = iter.entry->next)
@@ -746,7 +760,7 @@ JSON_EXPORT struct json_object *json_object_new_boolean(json_bool b);
* The type is coerced to a json_bool if the passed object is not a json_bool.
* integer and double objects will return 0 if there value is zero
* or 1 otherwise. If the passed object is a string it will return
* 1 if it has a non zero length.
* 1 if it has a non zero length.
* If any other object type is passed 0 will be returned, even non-empty
* json_type_array and json_type_object objects.
*
@@ -1114,8 +1128,8 @@ JSON_EXPORT int json_object_equal(struct json_object *obj1, struct json_object *
*
* @return On success 1 or 2, -1 on errors
*/
typedef int(json_c_shallow_copy_fn)(json_object *src, json_object *parent, const char *key,
size_t index, json_object **dst);
typedef int(json_c_shallow_copy_fn)(json_object *src, json_object *parent,
const struct lh_string *key, size_t index, json_object **dst);

/**
* The default shallow copy implementation for use with json_object_deep_copy().


+ 2
- 2
json_object_iterator.c View File

@@ -104,12 +104,12 @@ void json_object_iter_next(struct json_object_iterator *iter)
/**
* ****************************************************************************
*/
const char *json_object_iter_peek_name(const struct json_object_iterator *iter)
const struct lh_string *json_object_iter_peek_name(const struct json_object_iterator *iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);

return (const char *)(((const struct lh_entry *)iter->opaque_)->k);
return (const struct lh_string *)(((const struct lh_entry *)iter->opaque_)->k);
}

/**


+ 2
- 1
json_object_iterator.h View File

@@ -168,7 +168,8 @@ JSON_EXPORT void json_object_iter_next(struct json_object_iterator *iter);
* deleted or modified, and MUST NOT be modified or
* freed by the user.
*/
JSON_EXPORT const char *json_object_iter_peek_name(const struct json_object_iterator *iter);
JSON_EXPORT const struct lh_string *
json_object_iter_peek_name(const struct json_object_iterator *iter);

/** Returns a pointer to the json-c instance representing the
* value of the referenced name/value pair, without altering


+ 1
- 1
json_types.h View File

@@ -33,7 +33,7 @@ struct printbuf;
*/
struct json_object_iter
{
char *key;
struct lh_string *key;
struct json_object *val;
struct lh_entry *entry;
};


+ 2
- 2
json_visit.c View File

@@ -13,7 +13,7 @@
#include "json_visit.h"
#include "linkhash.h"

static int _json_c_visit(json_object *jso, json_object *parent_jso, const char *jso_key,
static int _json_c_visit(json_object *jso, json_object *parent_jso, const struct lh_string *jso_key,
size_t *jso_index, json_c_visit_userfunc *userfunc, void *userarg);

int json_c_visit(json_object *jso, int future_flags, json_c_visit_userfunc *userfunc, void *userarg)
@@ -28,7 +28,7 @@ int json_c_visit(json_object *jso, int future_flags, json_c_visit_userfunc *user
default: return JSON_C_VISIT_RETURN_ERROR;
}
}
static int _json_c_visit(json_object *jso, json_object *parent_jso, const char *jso_key,
static int _json_c_visit(json_object *jso, json_object *parent_jso, const struct lh_string *jso_key,
size_t *jso_index, json_c_visit_userfunc *userfunc, void *userarg)
{
int userret = userfunc(jso, 0, parent_jso, jso_key, jso_index, userarg);


+ 2
- 1
json_visit.h View File

@@ -13,7 +13,8 @@ extern "C" {
#endif

typedef int(json_c_visit_userfunc)(json_object *jso, int flags, json_object *parent_jso,
const char *jso_key, size_t *jso_index, void *userarg);
const struct lh_string *jso_key, size_t *jso_index,
void *userarg);

/**
* Visit each object in the JSON hierarchy starting at jso.


+ 6
- 1
linkhash.c View File

@@ -506,6 +506,11 @@ size_t lh_string_size(const struct lh_string *str)
return (str->length > 0) ? (size_t)str->length : (size_t)(-(str->length));
}

size_t lh_string_print(const struct lh_string *key, FILE *stream)
{
return fwrite(lh_string_data(key), lh_string_size(key), 1, stream);
}

const struct lh_string *lh_string_new_ptr(const size_t length, const char *data)
{
struct lh_string *result = malloc(sizeof(struct lh_string));
@@ -535,7 +540,7 @@ const struct lh_string *lh_string_new_imm(const size_t length, const char *data)
result->length = -length;
char *unconst = _LH_UNCONST(result->str.idata);
memcpy(unconst, data, length);
unconst = '\0';
unconst[length] = '\0';
return result;
}



+ 9
- 0
linkhash.h View File

@@ -20,6 +20,7 @@
#define _json_c_linkhash_h_

#include "json_object.h"
#include <stdio.h>

#ifdef __cplusplus
extern "C" {
@@ -206,6 +207,14 @@ extern const char *lh_string_data(const struct lh_string *str);
*/
extern size_t lh_string_size(const struct lh_string *str);

/**
* @brief Print a `struct lh_string` to a given stream
*
* @param str value to print
* @param stream Stream to write data to
*/
extern size_t lh_string_print(const struct lh_string *str, FILE *stream);

/**
* @brief Creates a new `struct lh_string` using the `pdata` field.
*


Loading…
Cancel
Save