Browse Source

Rename lh_string to json_key and move to json_object.h

pull/715/head
HexTheDragon 4 years ago
parent
commit
2c9019f7ff
21 changed files with 284 additions and 231 deletions
  1. +5
    -3
      json-c.sym
  2. +66
    -29
      json_object.c
  3. +123
    -15
      json_object.h
  4. +2
    -2
      json_object_iterator.c
  5. +1
    -1
      json_object_iterator.h
  6. +42
    -16
      json_object_private.h
  7. +2
    -3
      json_tokener.c
  8. +1
    -2
      json_tokener.h
  9. +3
    -1
      json_types.h
  10. +2
    -2
      json_visit.c
  11. +1
    -1
      json_visit.h
  12. +4
    -52
      linkhash.c
  13. +0
    -72
      linkhash.h
  14. +1
    -1
      tests/test1.c
  15. +11
    -11
      tests/testReplaceExisting.c
  16. +3
    -3
      tests/test_deep_copy.c
  17. +2
    -2
      tests/test_null_keys_add.c
  18. +1
    -1
      tests/test_null_keys_del.expected
  19. +1
    -1
      tests/test_object_iterator.c
  20. +1
    -1
      tests/test_parse.c
  21. +12
    -12
      tests/test_visit.c

+ 5
- 3
json-c.sym View File

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

JSONC_0.16 {
global:
lh_string_data;
lh_string_size;
lh_string_print;
json_key_data;
json_key_size;
json_object_object_add_len;
json_object_object_add_ex_len;
json_object_object_add_key;
json_object_object_del_len;
json_object_object_del_key;
json_object_object_get_len;
json_object_object_get_ex_len;
json_object_object_get_key;
} JSONC_0.15;

+ 66
- 29
json_object.c View File

@@ -116,12 +116,6 @@ 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_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);
@@ -512,7 +506,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, lh_string_data(iter.key), lh_string_size(iter.key), flags);
json_escape_str(pb, json_key_data(iter.key), json_key_size(iter.key), flags);
if (flags & JSON_C_TO_STRING_SPACED)
printbuf_strappend(pb, "\": ");
else
@@ -583,20 +577,20 @@ 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
// Created on the stack rather than calling `json_key_new_ptr`
// or `json_key_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);
const struct json_key hashable = {.length = len, .str = {.pdata = key}};
return json_object_object_add_key(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)
int json_object_object_add_key(struct json_object *jso, const struct json_key *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 *` */
/** Required due to the `lh_get_hash` function wanting a `const struct json_key *` */

assert(json_object_get_type(jso) == json_type_object);

@@ -619,12 +613,12 @@ int json_object_object_add_internal(struct json_object *jso, const struct lh_str
{
// 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
// `json_key_data` into `key->string.idata` if it had happened
// that `existing_entry` wasn't NULL.
const struct lh_string *k =
const struct json_key *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));
? json_key_new_ptr(json_key_size(key), json_key_data(key))
: json_key_new_imm(json_key_size(key), json_key_data(key));
// TODO some optimization where (opts & JSON_C_OBJECT_ADD_KEY_IS_NEW)
if (k == NULL)
{
@@ -632,7 +626,7 @@ int json_object_object_add_internal(struct json_object *jso, const struct lh_str
}
return lh_table_insert_w_hash(JC_OBJECT(jso)->c_object, k, val, hash,
opts & ~JSON_C_OBJECT_KEY_IS_CONSTANT);
// `struct lh_string` always needs to be freed,
// `struct json_key` always needs to be freed,
// so JSON_C_OBJECT_KEY_IS_CONSTANT cannot be set
}
else
@@ -703,8 +697,8 @@ json_bool json_object_object_get_ex_len(const struct json_object *jso, const cha
{
case json_type_object:
{
const struct lh_string hashable = {.length = len, .str = {.pdata = key}};
return json_object_object_get_internal(jso, &hashable, value);
const struct json_key hashable = {.length = len, .str = {.pdata = key}};
return json_object_object_get_key(jso, &hashable, value);
}
default:
if (value != NULL)
@@ -713,8 +707,8 @@ 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)
json_bool json_object_object_get_key(const struct json_object *jso, const struct json_key *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);
@@ -727,11 +721,11 @@ void json_object_object_del(struct json_object *jso, const char *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);
const struct json_key hashable = {.length = len, .str = {.pdata = key}};
json_object_object_del_key(jso, &hashable);
}

int json_object_object_del_internal(struct json_object *jso, const struct lh_string *key)
int json_object_object_del_key(struct json_object *jso, const struct json_key *key)
{
assert(json_object_get_type(jso) == json_type_object);
return lh_table_delete(JC_OBJECT(jso)->c_object, key);
@@ -1721,7 +1715,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 struct lh_string *key,
int json_c_shallow_copy_default(json_object *src, json_object *parent, const struct json_key *key,
size_t index, json_object **dst)
{
switch (src->o_type)
@@ -1769,7 +1763,7 @@ int json_c_shallow_copy_default(json_object *src, json_object *parent, const str
* 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 struct lh_string *key_in_parent,
const struct json_key *key_in_parent,
size_t index_in_parent, struct json_object **dst,
json_c_shallow_copy_fn *shallow_copy)
{
@@ -1802,7 +1796,7 @@ static int json_object_deep_copy_recursive(struct json_object *src, struct json_
return -1;
}

if (json_object_object_add_internal(*dst, iter.key, jso, 0) < 0)
if (json_object_object_add_key(*dst, iter.key, jso, 0) < 0)
{
json_object_put(jso);
return -1;
@@ -1876,3 +1870,46 @@ static void json_abort(const char *message)
fprintf(stderr, "json-c aborts with error: %s\n", message);
abort();
}

size_t json_key_size(const struct json_key *str)
{
return (str->length > 0) ? (size_t)str->length : (size_t)(-(str->length));
}

const char *json_key_data(const struct json_key *str)
{
return (str->length > 0) ? str->str.pdata : str->str.idata;
}

struct json_key *json_key_new_ptr(const size_t length, const char *data)
{
struct json_key *result = malloc(sizeof(struct json_key));
if (result == NULL)
{
return NULL;
}
result->length = length;
result->str.pdata = data;
return result;
}

struct json_key *json_key_new_imm(const size_t length, const char *data)
{
struct json_key *result;
if (length >
SSIZE_T_MAX - (sizeof(struct json_key) - sizeof(((struct json_key *)NULL)->str)) - 1)
{
return NULL;
}
result =
malloc(sizeof(struct json_key) - sizeof(((struct json_key *)NULL)->str) + length + 1);
if (result == NULL)
{
return NULL;
}
result->length = -length;
char *unconst = _LH_UNCONST(result->str.idata);
memcpy(unconst, data, length);
unconst[length] = '\0';
return result;
}

+ 123
- 15
json_object.h View File

@@ -456,8 +456,27 @@ JSON_EXPORT int json_object_object_add_ex_len(struct json_object *obj, const cha
const int len, struct json_object *const val,
const unsigned opts);

/** Get the json_object associate with a given object field.
* Deprecated/discouraged: used json_object_object_get_ex instead.
/**
* @brief Add an object field to a json_object of type json_type_object
*
* The semantics are identical to `json_object_object_add_ex`, except that @p key
* contains both the data and the length.
*
* @param obj the json_object instance
* @param key the object field name (a private copy will be duplicated)
* @param val a json_object or NULL member to associate with the given field
* @param opts process-modifying options. To specify multiple options, use
* (OPT1|OPT2)
* @return On success, @c 0 is returned.
* On error, a negative value is returned.
*/
JSON_EXPORT int json_object_object_add_key(struct json_object *obj, const struct json_key *key,
struct json_object *const val, const unsigned opts);

/**
* @brief Get the json_object associate with a given object field.
*
* @deprecated Deprecated/discouraged: used json_object_object_get_ex instead.
*
* This functions exactly like calling
* @code json_object_object_get_len(obj, key, strlen(key)) @endcode
@@ -469,8 +488,10 @@ JSON_EXPORT int json_object_object_add_ex_len(struct json_object *obj, const cha
*/
JSON_EXPORT struct json_object *json_object_object_get(const struct json_object *obj,
const char *key);
/** Get the json_object associate with a given object field.
* Deprecated/discouraged: used json_object_object_get_ex_len instead.
/**
* @brief Get the json_object associate with a given object field.
*
* @deprecated Deprecated/discouraged: used json_object_object_get_ex_len instead.
*
* This returns NULL if the field is found but its value is null, or if
* the field is not found, or if obj is not a json_type_object. If you
@@ -496,7 +517,8 @@ JSON_EXPORT struct json_object *json_object_object_get(const struct json_object
JSON_EXPORT struct json_object *json_object_object_get_len(const struct json_object *obj,
const char *key, const int len);

/** Get the json_object associated with a given object field.
/**
* @brief Get the json_object associated with a given object field.
*
* This functions exactly like calling
* @code json_object_object_get_ex_len(obj, key, strlen(key), value) @endcode
@@ -513,7 +535,8 @@ JSON_EXPORT struct json_object *json_object_object_get_len(const struct json_obj
JSON_EXPORT json_bool json_object_object_get_ex(const struct json_object *obj, const char *key,
struct json_object **value);

/** Get the json_object associated with a given object field.
/**
* @brief Get the json_object associated with a given object field.
*
* This returns true if the key is found, false in all other cases (including
* if obj isn't a json_type_object).
@@ -536,7 +559,29 @@ JSON_EXPORT json_bool json_object_object_get_ex(const struct json_object *obj, c
JSON_EXPORT json_bool json_object_object_get_ex_len(const struct json_object *obj, const char *key,
const int len, struct json_object **value);

/** Delete the given json_object field
/**
* @brief Get the json_object associated with a given object field.
*
* *No* reference counts will be changed. There is no need to manually adjust
* reference counts through the json_object_put/json_object_get methods unless
* you need to have the child (value) reference maintain a different lifetime
* than the owning parent (obj). Ownership of value is retained by obj.
*
* @param obj the json_object instance
* @param key the object field name
* @param value a pointer where to store a reference to the json_object
* associated with the given field name.
* \n
* It is safe to pass a NULL value.
* @returns true if the key is found, false in all other cases (including
* if obj isn't a json_type_object)
*/
JSON_EXPORT json_bool json_object_object_get_key(const struct json_object *jso,
const struct json_key *key,
struct json_object **value);

/**
* @brief 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
@@ -547,7 +592,8 @@ 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
/**
* @brief 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
@@ -558,10 +604,24 @@ JSON_EXPORT void json_object_object_del(struct json_object *obj, const char *key
* 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);
JSON_EXPORT 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.
* @brief 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
*/
JSON_EXPORT int json_object_object_del_key(struct json_object *jso_base,
const struct json_key *key);

/**
* @brief Iterate through all keys and values of an object.
*
* Adding keys to the object while iterating is NOT allowed.
*
@@ -577,14 +637,14 @@ void json_object_object_del_len(struct json_object *jso, const char *key, const
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)

#define json_object_object_foreach(obj, key, val) \
struct lh_string *key = NULL; \
struct json_key *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 = (struct lh_string *)lh_entry_k(entry##key); \
key = (struct json_key *)lh_entry_k(entry##key); \
val = (struct json_object *)lh_entry_v(entry##key); \
entry_next##key = entry##key->next; \
}; \
@@ -608,13 +668,14 @@ void json_object_object_del_len(struct json_object *jso, const char *key, const

#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) && (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) */

/** Iterate through all keys and values of an object (ANSI C Safe)
/**
* @brief Iterate through all keys and values of an object (ANSI C Safe)
* @param obj the json_object instance
* @param iter the object iterator, use type json_object_iter
*/
#define json_object_object_foreachC(obj, iter) \
for (iter.entry = json_object_get_object(obj)->head; \
(iter.entry ? (iter.key = (struct lh_string *)lh_entry_k(iter.entry), \
(iter.entry ? (iter.key = (struct json_key *)lh_entry_k(iter.entry), \
iter.val = (struct json_object *)lh_entry_v(iter.entry), iter.entry) \
: 0); \
iter.entry = iter.entry->next)
@@ -1129,7 +1190,7 @@ 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 struct lh_string *key, size_t index, json_object **dst);
const struct json_key *key, size_t index, json_object **dst);

/**
* The default shallow copy implementation for use with json_object_deep_copy().
@@ -1166,6 +1227,53 @@ JSON_EXPORT json_c_shallow_copy_fn json_c_shallow_copy_default;

JSON_EXPORT int json_object_deep_copy(struct json_object *src, struct json_object **dst,
json_c_shallow_copy_fn *shallow_copy);

/* Json Object Keys */

/**
* @brief Get the length of the data stored in a `struct json_key *`
*
* @param str value to retrieve the length of
*/
JSON_EXPORT size_t json_key_size(const struct json_key *str);

/**
* @brief Get the data from a `struct json_key *`
*
* @param str value to retrieve the data from
*/
JSON_EXPORT const char *json_key_data(const struct json_key *str);

/**
* @brief Creates a new `struct json_key` that uses the `pdata` field.
*
* This avoids unneeded copying, for cases wher ethe key is in an area of
* memory that will not be modified or freed until after this object is freed.
*
* @param length The length of the data located at @p data
* @param data The data to include
* @return On success, a pointer to the new key is returned.
* On error, a null pointer is returned.
*/
JSON_EXPORT struct json_key *json_key_new_ptr(const size_t length, const char *data);

/**
* @brief Creates a new `struct json_key` that uses the `idata` field.
*
* @param length The length of the data to copy into the returned value
* @param data The data to include and copy into the returned value
* @return On success, a pointer to the new key is returned.
* On error, a null pointer is returned.
*/
JSON_EXPORT struct json_key *json_key_new_imm(const size_t length, const char *data);

/**
* @brief Frees the memory associated with a `struct json_key`
*
* @param key The data to free
*/
JSON_EXPORT void json_key_del(const struct json_key *key);

#ifdef __cplusplus
}
#endif


+ 2
- 2
json_object_iterator.c View File

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

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

/**


+ 1
- 1
json_object_iterator.h View File

@@ -168,7 +168,7 @@ 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 struct lh_string *
JSON_EXPORT const struct json_key *
json_object_iter_peek_name(const struct json_object_iterator *iter);

/** Returns a pointer to the json-c instance representing the


+ 42
- 16
json_object_private.h View File

@@ -98,27 +98,53 @@ struct json_object_string

void _json_c_set_last_err(const char *err_fmt, ...);

/**
* @brief Add an object field to a json_object of type json_type_object
*
* The semantics are identical to json_object_object_add_ex, except that @p key
* contains both the data and the length.
*
* @param obj the json_object instance
* @param key the object field name (a private copy will be duplicated)
* @param val a json_object or NULL member to associate with the given field
* @param opts process-modifying options. To specify multiple options, use
* (OPT1|OPT2)
* @return On success, @c 0 is returned.
* On error, a negative value is returned.
*/
int json_object_object_add_internal(struct json_object *obj, const struct lh_string *key,
struct json_object *const val, const unsigned opts);
/**
* The characters that can make up hexadecimal numbers
*/
extern const char *json_hex_chars;

/**
* @brief A buffer of characters that may contain null charaters in the middle
*
* A buffer of data that can hold a normal null-terminated string
* (in which case `length` should just be equal to `strlen`)
* or a string with embedded null characters (in which case `length` reflects
* all the characters that make up the "string").
* Either way, this struct can be treated as if it contains null characters,
* since the `length` member should always be equal to the proper size of the
* buffer and the terminating null character wouldn't be included
* (it wouldn't be counted by strlen).
*/
struct json_key
{
/**
* @brief Stores the length of the buffer
*
* If the length is positive, then `pdata` should be used.
* Otherwise, idata should be used.
*/
ssize_t length;
union
{
/**
* @brief A pointer to data that is stored elsewhere
*
* If the data stored there will not change for the lifetime of
* the key, use `pdata` rather than `idata`.
*/
const char *pdata;
/**
* @brief Data stored inline
*
* If the data stored may be overwritten, such as if it is
* copied from the stack, this struct should be allocated with
* enough space to store the whole string (of length `len`)
* and one additional null character.
*/
const char idata[0];
} str;
};

#ifdef __cplusplus
}
#endif


+ 2
- 3
json_tokener.c View File

@@ -1106,8 +1106,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
printbuf_memappend_fast(tok->pb, case_start,
str - case_start);
obj_field_name =
lh_string_new_imm(tok->pb->bpos, tok->pb->buf);
// lh_string_print(obj_field_name, stdout);
json_key_new_imm(tok->pb->bpos, tok->pb->buf);
saved_state = json_tokener_state_object_field_end;
state = json_tokener_state_eatws;
break;
@@ -1155,7 +1154,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
goto redo_char;

case json_tokener_state_object_value_add:
json_object_object_add_internal(current, obj_field_name, obj, 0);
json_object_object_add_key(current, obj_field_name, obj, 0);
free(obj_field_name);
obj_field_name = NULL;
saved_state = json_tokener_state_object_sep;


+ 1
- 2
json_tokener.h View File

@@ -17,7 +17,6 @@
#define _json_tokener_h_

#include "json_object.h"
#include "linkhash.h"
#include <stddef.h>

#ifdef __cplusplus
@@ -86,7 +85,7 @@ struct json_tokener_srec
enum json_tokener_state state, saved_state;
struct json_object *obj;
struct json_object *current;
struct lh_string *obj_field_name;
struct json_key *obj_field_name;
};

#define JSON_TOKENER_DEFAULT_DEPTH 32


+ 3
- 1
json_types.h View File

@@ -33,7 +33,7 @@ struct printbuf;
*/
struct json_object_iter
{
struct lh_string *key;
struct json_key *key;
struct json_object *val;
struct lh_entry *entry;
};
@@ -71,6 +71,8 @@ typedef enum json_type
json_type_string
} json_type;

typedef struct json_key json_key;

#ifdef __cplusplus
}
#endif


+ 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 struct lh_string *jso_key,
static int _json_c_visit(json_object *jso, json_object *parent_jso, const struct json_key *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 struct lh_string *jso_key,
static int _json_c_visit(json_object *jso, json_object *parent_jso, const struct json_key *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);


+ 1
- 1
json_visit.h View File

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

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

/**


+ 4
- 52
linkhash.c View File

@@ -486,62 +486,14 @@ static unsigned long lh_char_hash(const void *k)
random_seed = seed; /* potentially racy */
#endif
}
return hashlittle(lh_string_data((const struct lh_string *)k),
lh_string_size((const struct lh_string *)k), random_seed);
return hashlittle(json_key_data((const struct json_key *)k),
json_key_size((const struct json_key *)k), random_seed);
}

int lh_char_equal(const void *k1, const void *k2)
{
return lh_string_size(k1) == lh_string_size(k2) &&
memcmp(lh_string_data(k1), lh_string_data(k2), lh_string_size(k1)) == 0;
}

const char *lh_string_data(const struct lh_string *str)
{
return (str->length > 0) ? str->str.pdata : str->str.idata;
}

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);
}

struct lh_string *lh_string_new_ptr(const size_t length, const char *data)
{
struct lh_string *result = malloc(sizeof(struct lh_string));
if (result == NULL)
{
return NULL;
}
result->length = length;
result->str.pdata = data;
return result;
}

struct lh_string *lh_string_new_imm(const size_t length, const char *data)
{
struct lh_string *result;
if (length >
SSIZE_T_MAX - (sizeof(struct lh_string) - sizeof(((struct lh_string *)NULL)->str)) - 1)
{
return NULL;
}
result =
malloc(sizeof(struct lh_string) - sizeof(((struct lh_string *)NULL)->str) + length + 1);
if (result == NULL)
{
return NULL;
}
result->length = -length;
char *unconst = _LH_UNCONST(result->str.idata);
memcpy(unconst, data, length);
unconst[length] = '\0';
return result;
return json_key_size(k1) == json_key_size(k2) &&
memcmp(json_key_data(k1), json_key_data(k2), json_key_size(k1)) == 0;
}

struct lh_table *lh_table_new(int size, lh_entry_free_fn *free_fn, lh_hash_fn *hash_fn,


+ 0
- 72
linkhash.h View File

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

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

#ifdef __cplusplus
extern "C" {
@@ -80,34 +79,6 @@ typedef unsigned long(lh_hash_fn)(const void *k);
*/
typedef int(lh_equal_fn)(const void *k1, const void *k2);

/**
* @brief A buffer of characters that may contain null charaters in the middle
*
* A buffer of data that can hold a normal null-terminated string
* (in which case `length` should just be equal to `strlen`)
* or a string with embedded null characters (in which case `length` reflects
* all the characters that make up the "string").
* Either way, this struct can be treated as if it contains null characters,
* since the `length` member should always be equal to the proper size of the
* buffer and the terminating null character wouldn't be included
* (it wouldn't be counted by strlen).
*/
struct lh_string
{
/**
* @brief Stores the length of the buffer
*
* If the length is positive, then `pdata` should be used.
* Otherwise, idata should be used.
*/
ssize_t length;
union
{
const char *pdata;
const char idata[0];
} str;
};

/**
* An entry in the hash table
*/
@@ -193,49 +164,6 @@ typedef struct lh_table lh_table;
#define lh_foreach_safe(table, entry, tmp) \
for (entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)

/**
* @brief Get the data from a `struct lh_string *`
*
* @param str value to retrieve the data from
*/
extern const char *lh_string_data(const struct lh_string *str);

/**
* @brief Get the length of the data stored in a `struct lh_string *`
*
* @param str value to retrieve the length of
*/
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.
*
* This avoids unneeded copying, for cases wher ethe key is in an area of
* memory that will not be modified or freed until after this object is freed.
*
* @param length The length of the data located at @p data
* @param data The data to include
* @return `NULL` on error
*/
extern struct lh_string *lh_string_new_ptr(const size_t length, const char *data);

/**
* @brief Creates a new `struct lh_string` using the `idata` field.
*
* @param length The length of the data to copy into the returned value
* @param data The data to include and copy into the returned value
* @return `NULL` on error
*/
extern struct lh_string *lh_string_new_imm(const size_t length, const char *data);

/**
* Create a new linkhash table.
*


+ 1
- 1
tests/test1.c View File

@@ -307,7 +307,7 @@ int main(int argc, char **argv)
json_object_object_foreach(my_object, key, val)
{
putchar('\t');
lh_string_print(key, stdout);
fwrite(json_key_data(key), json_key_size(key), 1, stdout);
printf(": %s\n", json_object_to_json_string(val));
}
printf("my_object.to_string()=%s\n", json_object_to_json_string(my_object));


+ 11
- 11
tests/testReplaceExisting.c View File

@@ -24,11 +24,11 @@ int main(int argc, char **argv)
int orig_count = 0;
json_object_object_foreach(my_object, key0, val0)
{
printf("Key at index %d is [%s] %d", orig_count, lh_string_data(key0),
printf("Key at index %d is [%s] %d", orig_count, json_key_data(key0),
(val0 == NULL));
if (strcmp(lh_string_data(key0), "deleteme") == 0)
if (strcmp(json_key_data(key0), "deleteme") == 0)
{
json_object_object_del(my_object, lh_string_data(key0));
json_object_object_del(my_object, json_key_data(key0));
printf(" (deleted)\n");
}
else
@@ -38,18 +38,18 @@ int main(int argc, char **argv)

printf("==== replace-value first loop starting ====\n");

const struct lh_string *original_key = NULL;
const struct json_key *original_key = NULL;
orig_count = 0;
json_object_object_foreach(my_object, key, val)
{
printf("Key at index %d is [%s] %d\n", orig_count, lh_string_data(key),
printf("Key at index %d is [%s] %d\n", orig_count, json_key_data(key),
(val == NULL));
orig_count++;
if (strcmp(lh_string_data(key), "foo2") != 0)
if (strcmp(json_key_data(key), "foo2") != 0)
continue;
printf("replacing value for key [%s]\n", lh_string_data(key));
printf("replacing value for key [%s]\n", json_key_data(key));
original_key = key;
json_object_object_add(my_object, lh_string_data(key0),
json_object_object_add(my_object, json_key_data(key0),
json_object_new_string("zzz"));
}

@@ -59,12 +59,12 @@ int main(int argc, char **argv)
int retval = 0;
json_object_object_foreach(my_object, key2, val2)
{
printf("Key at index %d is [%s] %d\n", new_count, lh_string_data(key2),
printf("Key at index %d is [%s] %d\n", new_count, json_key_data(key2),
(val2 == NULL));
new_count++;
if (strcmp(lh_string_data(key2), "foo2") != 0)
if (strcmp(json_key_data(key2), "foo2") != 0)
continue;
printf("pointer for key [%s] does %smatch\n", lh_string_data(key2),
printf("pointer for key [%s] does %smatch\n", json_key_data(key2),
(key2 == original_key) ? "" : "NOT ");
if (key2 != original_key)
retval = 1;


+ 3
- 3
tests/test_deep_copy.c View File

@@ -93,14 +93,14 @@ int my_custom_serializer(struct json_object *jso, struct printbuf *pb, int level
}

json_c_shallow_copy_fn my_shallow_copy;
int my_shallow_copy(json_object *src, json_object *parent, const struct lh_string *key,
size_t index, json_object **dst)
int my_shallow_copy(json_object *src, json_object *parent, const struct json_key *key, size_t index,
json_object **dst)
{
int rc;
rc = json_c_shallow_copy_default(src, parent, key, index, dst);
if (rc < 0)
return rc;
if (key != NULL && strcmp(lh_string_data(key), "with_serializer") == 0)
if (key != NULL && strcmp(json_key_data(key), "with_serializer") == 0)
{
printf("CALLED: my_shallow_copy on with_serializer object\n");
void *userdata = json_object_get_userdata(src);


+ 2
- 2
tests/test_null_keys_add.c View File

@@ -114,8 +114,8 @@ int main(void)
json_object_object_foreach(parsed, key, val)
{
putchar('\"');
fwrite(lh_string_data(key), lh_string_size(key), 1, stdout);
printf("\" (%zd)\n", lh_string_size(key));
fwrite(json_key_data(key), json_key_size(key), 1, stdout);
printf("\" (%zd)\n", json_key_size(key));
}
return 1;
}


+ 1
- 1
tests/test_null_keys_del.expected View File

@@ -1,5 +1,5 @@
Parsed input: { "biff\u0000": null, "\u0000zxcvbnm": 178 }
Result is `json_type_object`
Expected keys ("biff\0" and "\0zxcvbnm") present with expected values
Expected keys ("biff\u0000" and "\u0000zxcvbnm") present with expected values
Key deleted properly
PASS

+ 1
- 1
tests/test_object_iterator.c View File

@@ -31,7 +31,7 @@ int main(int atgc, char **argv)

while (!json_object_iter_equal(&it, &itEnd))
{
printf("%s\n", lh_string_data(json_object_iter_peek_name(&it)));
printf("%s\n", json_key_data(json_object_iter_peek_name(&it)));
printf("%s\n", json_object_to_json_string(json_object_iter_peek_value(&it)));
json_object_iter_next(&it);
}


+ 1
- 1
tests/test_parse.c View File

@@ -215,7 +215,7 @@ static void do_clear_serializer(json_object *jso)
}

static int clear_serializer(json_object *jso, int flags, json_object *parent_jso,
const struct lh_string *jso_key, size_t *jso_index, void *userarg)
const struct json_key *jso_key, size_t *jso_index, void *userarg)
{
if (jso)
json_object_set_serializer(jso, NULL, NULL, NULL);


+ 12
- 12
tests/test_visit.c View File

@@ -69,16 +69,16 @@ int main(void)
}

static int emit_object(json_object *jso, int flags, json_object *parent_jso,
const struct lh_string *jso_key, size_t *jso_index, void *userarg)
const struct json_key *jso_key, size_t *jso_index, void *userarg)
{
printf("flags: 0x%x, key: %s, index: %ld, value: %s\n", flags,
(jso_key ? lh_string_data(jso_key) : "(null)"), (jso_index ? (long)*jso_index : -1L),
(jso_key ? json_key_data(jso_key) : "(null)"), (jso_index ? (long)*jso_index : -1L),
json_object_to_json_string(jso));
return JSON_C_VISIT_RETURN_CONTINUE;
}

static int skip_arrays(json_object *jso, int flags, json_object *parent_jso,
const struct lh_string *jso_key, size_t *jso_index, void *userarg)
const struct json_key *jso_key, size_t *jso_index, void *userarg)
{
(void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg);
if (json_object_get_type(jso) == json_type_array)
@@ -87,15 +87,15 @@ static int skip_arrays(json_object *jso, int flags, json_object *parent_jso,
}

static int pop_and_stop(json_object *jso, int flags, json_object *parent_jso,
const struct lh_string *jso_key, size_t *jso_index, void *userarg)
const struct json_key *jso_key, size_t *jso_index, void *userarg)
{
(void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg);
if (jso_key != NULL && strcmp(lh_string_data(jso_key), "subobj1") == 0)
if (jso_key != NULL && strcmp(json_key_data(jso_key), "subobj1") == 0)
{
printf("POP after handling subobj1\n");
return JSON_C_VISIT_RETURN_POP;
}
if (jso_key != NULL && strcmp(lh_string_data(jso_key), "obj3") == 0)
if (jso_key != NULL && strcmp(json_key_data(jso_key), "obj3") == 0)
{
printf("STOP after handling obj3\n");
return JSON_C_VISIT_RETURN_STOP;
@@ -104,10 +104,10 @@ static int pop_and_stop(json_object *jso, int flags, json_object *parent_jso,
}

static int err_on_subobj2(json_object *jso, int flags, json_object *parent_jso,
const struct lh_string *jso_key, size_t *jso_index, void *userarg)
const struct json_key *jso_key, size_t *jso_index, void *userarg)
{
(void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg);
if (jso_key != NULL && strcmp(lh_string_data(jso_key), "subobj2") == 0)
if (jso_key != NULL && strcmp(json_key_data(jso_key), "subobj2") == 0)
{
printf("ERROR after handling subobj1\n");
return JSON_C_VISIT_RETURN_ERROR;
@@ -116,7 +116,7 @@ static int err_on_subobj2(json_object *jso, int flags, json_object *parent_jso,
}

static int pop_array(json_object *jso, int flags, json_object *parent_jso,
const struct lh_string *jso_key, size_t *jso_index, void *userarg)
const struct json_key *jso_key, size_t *jso_index, void *userarg)
{
(void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg);
if (jso_index != NULL && (*jso_index == 0))
@@ -128,7 +128,7 @@ static int pop_array(json_object *jso, int flags, json_object *parent_jso,
}

static int stop_array(json_object *jso, int flags, json_object *parent_jso,
const struct lh_string *jso_key, size_t *jso_index, void *userarg)
const struct json_key *jso_key, size_t *jso_index, void *userarg)
{
(void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg);
if (jso_index != NULL && (*jso_index == 0))
@@ -140,10 +140,10 @@ static int stop_array(json_object *jso, int flags, json_object *parent_jso,
}

static int err_return(json_object *jso, int flags, json_object *parent_jso,
const struct lh_string *jso_key, size_t *jso_index, void *userarg)
const struct json_key *jso_key, size_t *jso_index, void *userarg)
{
printf("flags: 0x%x, key: %s, index: %ld, value: %s\n", flags,
(jso_key ? lh_string_data(jso_key) : "(null)"), (jso_index ? (long)*jso_index : -1L),
(jso_key ? json_key_data(jso_key) : "(null)"), (jso_index ? (long)*jso_index : -1L),
json_object_to_json_string(jso));
return 100;
}

Loading…
Cancel
Save