From: Eric Haszlakiewicz Date: Wed, 9 Dec 2015 02:51:06 +0000 (-0600) Subject: Merge commit '2be921d88376e78f84d79aafa6db2714da804e59' X-Git-Tag: json-c-0.13-20171207~176 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=980cdd61beaceaecf30d4e57eccdd561185fe42f;p=thirdparty%2Fjson-c.git Merge commit '2be921d88376e78f84d79aafa6db2714da804e59' --- 980cdd61beaceaecf30d4e57eccdd561185fe42f diff --cc json_object.c index 5a758d65,39c93279..0175522a --- a/json_object.c +++ b/json_object.c @@@ -408,68 -362,40 +408,73 @@@ struct json_object* json_object_new_obj 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; diff --cc json_object.h index 69510198,b7d37fee..5164e141 --- a/json_object.h +++ b/json_object.h @@@ -314,26 -230,13 +314,29 @@@ extern int json_object_object_length(st * @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, 0 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 diff --cc linkhash.c index e19297ee,b77cd5f1..c89e35b3 --- a/linkhash.c +++ b/linkhash.c @@@ -474,49 -63,71 +474,64 @@@ struct lh_table* lh_table_new(int size 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); + + return 0; - -noinsert: - free( new_t->table ); - free( new_t ); -nonewtable: - return -1; } void lh_table_free(struct lh_table *t) @@@ -532,12 -143,19 +547,14 @@@ } -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 ) { diff --cc linkhash.h index c037fefb,c834a3bc..ead48184 --- a/linkhash.h +++ b/linkhash.h @@@ -159,9 -182,10 +159,10 @@@ for(entry = table->head; entry && ((tm * @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); @@@ -172,9 -196,10 +173,10 @@@ * @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); @@@ -184,9 -209,10 +186,10 @@@ * @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); @@@ -285,27 -286,32 +291,50 @@@ extern int lh_table_delete_entry(struc */ 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 stdout, + * then exits the program with an exit code of 1. + * + * @param msg Message format string, like for printf. + * @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, 0 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