struct lh_table* json_object_get_object(struct json_object *jso)
{
- if(!jso) return NULL;
- switch(jso->o_type) {
- case json_type_object:
- return jso->o.c_object;
- default:
- return NULL;
- }
+ if (!jso)
+ return NULL;
+ switch(jso->o_type)
+ {
+ case json_type_object:
+ return jso->o.c_object;
+ default:
+ return NULL;
+ }
+}
+
+void json_object_object_add_ex(struct json_object* jso,
+ const char *const key,
+ struct json_object *const val,
+ const unsigned opts)
+{
+ // We lookup the entry and replace the value, rather than just deleting
+ // and re-adding it, so the existing key remains valid.
+ json_object *existing_value = NULL;
+ struct lh_entry *existing_entry;
+ const unsigned long hash = lh_get_hash(jso->o.c_object, (void*)key);
+ existing_entry = (opts & JSON_C_OBJECT_ADD_KEY_IS_NEW) ? NULL :
+ lh_table_lookup_entry_w_hash(jso->o.c_object, (void*)key, hash);
+ if (!existing_entry)
+ {
+ void *const k = (opts & JSON_C_OBJECT_KEY_IS_CONSTANT) ?
+ (void*)key : strdup(key);
+ lh_table_insert_w_hash(jso->o.c_object, k, val, hash, opts);
+ return;
+ }
+ existing_value = (json_object *)existing_entry->v;
+ if (existing_value)
+ json_object_put(existing_value);
+ existing_entry->v = val;
}
- void json_object_object_add(struct json_object* jso, const char *key,
+ int json_object_object_add(struct json_object* jso, const char *key,
struct json_object *val)
{
// We lookup the entry and replace the value, rather than just deleting
// and re-adding it, so the existing key remains valid.
json_object *existing_value = NULL;
struct lh_entry *existing_entry;
- existing_entry = lh_table_lookup_entry(jso->o.c_object, (void*)key);
+ const unsigned long hash = lh_get_hash(jso->o.c_object, (void*)key);
+ existing_entry = lh_table_lookup_entry_w_hash(jso->o.c_object, (void*)key, hash);
if (!existing_entry)
{
- lh_table_insert_w_hash(jso->o.c_object, strdup(key), val, hash, 0);
- return;
- char * keydup = strdup( key );
- if ( keydup == NULL ) {
++ char *keydup = strdup(key);
++ if (keydup == NULL)
+ return -1;
- }
+
- return lh_table_insert(jso->o.c_object, keydup, val);
++ return lh_table_insert_w_hash(jso->o.c_object, keydup, val, hash, 0);
}
- existing_value = (void *)existing_entry->v;
+ existing_value = (json_object *)existing_entry->v;
if (existing_value)
json_object_put(existing_value);
existing_entry->v = val;
+
+ return 0;
}
+
+int json_object_object_length(struct json_object *jso)
+{
+ return lh_table_length(jso->o.c_object);
+}
+
struct json_object* json_object_object_get(struct json_object* jso, const char *key)
{
struct json_object *result = NULL;
* @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
+ *
+ * @return On success, <code>0</code> is returned.
+ * On error, a negative value is returned.
*/
- extern void json_object_object_add(struct json_object* obj, const char *key,
+ extern int json_object_object_add(struct json_object* obj, const char *key,
struct json_object *val);
+/** Add an object field to a json_object of type json_type_object
+ *
+ * The semantics are identical to json_object_object_add, except that an
+ * additional flag fields gives you more control over some detail aspects
+ * of processing. See the description of JSON_C_OBJECT_ADD_* flags for more
+ * details.
+ *
+ * @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
+ * arithmetic or (OPT1|OPT2)
+ */
+extern void json_object_object_add_ex(struct json_object* obj, const char *key,
+ struct json_object *val, const unsigned opts);
+
/** Get the json_object associate with a given object field
*
* *No* reference counts will be changed. There is no need to manually adjust
struct lh_table *t;
t = (struct lh_table*)calloc(1, sizeof(struct lh_table));
- if(!t) lh_abort("lh_table_new: calloc failed\n");
- if(!t) {
- goto nomem;
- }
++ if (!t)
++ return NULL;
+
t->count = 0;
t->size = size;
- t->name = name;
t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry));
- if(!t->table) lh_abort("lh_table_new: calloc failed\n");
- if(!t->table) {
- goto notablemem;
++ if (!t->table)
++ {
++ free(t);
++ return NULL;
+ }
t->free_fn = free_fn;
t->hash_fn = hash_fn;
t->equal_fn = equal_fn;
for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
return t;
-
-notablemem:
- free( t );
-nomem:
- return NULL;
}
-struct lh_table* lh_kchar_table_new(int size, const char *name,
+struct lh_table* lh_kchar_table_new(int size,
lh_entry_free_fn *free_fn)
{
- return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal);
+ return lh_table_new(size, free_fn, char_hash_fn, lh_char_equal);
}
-struct lh_table* lh_kptr_table_new(int size, const char *name,
+struct lh_table* lh_kptr_table_new(int size,
lh_entry_free_fn *free_fn)
{
- return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal);
+ return lh_table_new(size, free_fn, lh_ptr_hash, lh_ptr_equal);
}
- void lh_table_resize(struct lh_table *t, int new_size)
+ int lh_table_resize(struct lh_table *t, int new_size)
{
struct lh_table *new_t;
- struct lh_entry *ent;
- new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn);
- if ( new_t == NULL ) {
- goto nonewtable;
- }
-
- for ( struct lh_entry * ent = t->head; ent != NULL; ent = ent->next ) {
- int rc = lh_table_insert(new_t, ent->k, ent->v);
- if ( rc != 0 ) {
- goto noinsert;
+ new_t = lh_table_new(new_size, NULL, t->hash_fn, t->equal_fn);
- ent = t->head;
- while(ent) {
- lh_table_insert_w_hash(new_t, ent->k, ent->v,
- lh_get_hash(new_t, ent->k),
- (ent->k_is_constant) ? JSON_C_OBJECT_KEY_IS_CONSTANT : 0 );
- ent = ent->next;
++ if (new_t == NULL)
++ return -1;
++
++ for (struct lh_entry *ent = t->head; ent != NULL; ent = ent->next)
++ {
++ unsigned long h = lh_get_hash(new_t, ent->k);
++ unsigned int opts = 0;
++ if (ent->k_is_constant)
++ opts = JSON_C_OBJECT_KEY_IS_CONSTANT;
++ if (lh_table_insert_w_hash(new_t, ent->k, ent->v, h, opts) != 0)
++ {
++ lh_table_free(new_t);
++ return -1;
+ }
}
free(t->table);
t->table = new_t->table;
t->size = new_size;
t->head = new_t->head;
t->tail = new_t->tail;
- t->resizes++;
free(new_t);
-
-noinsert:
- free( new_t->table );
- free( new_t );
-nonewtable:
- return -1;
+
+ return 0;
}
void lh_table_free(struct lh_table *t)
}
-int lh_table_insert(struct lh_table *t, void *k, const void *v)
+int lh_table_insert_w_hash(struct lh_table *t, void *k, const void *v, const unsigned long h, const unsigned opts)
{
- unsigned long h, n;
+ unsigned long n;
- if(t->count >= t->size * LH_LOAD_FACTOR) lh_table_resize(t, t->size * 2);
- t->inserts++;
- if(t->count >= t->size * LH_LOAD_FACTOR) {
- int rc = lh_table_resize(t, t->size * 2);
- if ( rc != 0 ) {
++ if (t->count >= t->size * LH_LOAD_FACTOR)
++ if (lh_table_resize(t, t->size * 2) != 0)
+ return -1;
- }
- }
- h = t->hash_fn(k);
n = h % t->size;
while( 1 ) {
* @param equal_fn comparison function to compare keys. 2 standard ones defined:
* lh_ptr_hash and lh_char_hash for comparing pointer values
* and C strings respectively.
- * @return a pointer onto the linkhash table.
+ * @return On success, a pointer to the new linkhash table is returned.
+ * On error, a null pointer is returned.
*/
-extern struct lh_table* lh_table_new(int size, const char *name,
+extern struct lh_table* lh_table_new(int size,
lh_entry_free_fn *free_fn,
lh_hash_fn *hash_fn,
lh_equal_fn *equal_fn);
* @param size initial table size.
* @param name table name.
* @param free_fn callback function used to free memory for entries.
- * @return a pointer onto the linkhash table.
+ * @return On success, a pointer to the new linkhash table is returned.
+ * On error, a null pointer is returned.
*/
-extern struct lh_table* lh_kchar_table_new(int size, const char *name,
+extern struct lh_table* lh_kchar_table_new(int size,
lh_entry_free_fn *free_fn);
* @param size initial table size.
* @param name table name.
* @param free_fn callback function used to free memory for entries.
- * @return a pointer onto the linkhash table.
+ * @return On success, a pointer to the new linkhash table is returned.
+ * On error, a null pointer is returned.
*/
-extern struct lh_table* lh_kptr_table_new(int size, const char *name,
+extern struct lh_table* lh_kptr_table_new(int size,
lh_entry_free_fn *free_fn);
*/
extern int lh_table_delete(struct lh_table *t, const void *k);
+extern int lh_table_length(struct lh_table *t);
+
+ /**
+ * Prints a message to <code>stdout</code>,
+ * then exits the program with an exit code of <code>1</code>.
+ *
+ * @param msg Message format string, like for <code>printf</code>.
+ * @param ... Format args.
+ *
+ * @deprecated Since it is not a good idea to exit the entire program
+ * because of an internal library failure, json-c will no longer
+ * use this function internally.
+ * However, because its interface is public, it will remain part of
+ * the API on the off chance of legacy software using it externally.
+ */
void lh_abort(const char *msg, ...);
- void lh_table_resize(struct lh_table *t, int new_size);
+
+ /**
+ * Resizes the specified table.
+ *
+ * @param t Pointer to table to resize.
+ * @param new_size New table size. Must be positive.
+ *
+ * @return On success, <code>0</code> is returned.
+ * On error, a negative value is returned.
+ */
+ int lh_table_resize(struct lh_table *t, int new_size);
+
+/**
+ * Calculate the hash of a key for a given table.
+ * This is an exension to support functions that need to calculate
+ * the hash several times and allows them to do it just once and then pass
+ * in the hash to all utility functions. Depending on use case, this can be a
+ * very considerate performance improvement.
+ * @param t the table (used to obtain hash function)
+ * @param k a pointer to the key to lookup
+ * @return the key's hash
+ */
+static inline unsigned long lh_get_hash(const struct lh_table *t, const void *k)
+{
+ return t->hash_fn(k);
+}
+
#ifdef __cplusplus
}
#endif