]> granicus.if.org Git - json-c/commitdiff
Merge commit '2be921d88376e78f84d79aafa6db2714da804e59'
authorEric Haszlakiewicz <erh+git@nimenees.com>
Wed, 9 Dec 2015 02:51:06 +0000 (20:51 -0600)
committerEric Haszlakiewicz <erh+git@nimenees.com>
Wed, 9 Dec 2015 02:51:06 +0000 (20:51 -0600)
1  2 
json_object.c
json_object.h
linkhash.c
linkhash.h

diff --cc json_object.c
index 5a758d6502fd1ff3edc183fc507670663b6e0dd5,39c93279ece3dfb447aaf6d76f9b5e8687b9fc0a..0175522a3ff4eab65379e469df86acf205d08e44
@@@ -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 695101984c82d2bb685de1a8a53a8f28616bf737,b7d37feed50ca8dc00a7ae999f902b671becf28b..5164e141688670d41020cc5e378058d357e3d4cf
@@@ -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, <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
diff --cc linkhash.c
index e19297ee712c995c5838c751d573c57d45aa6204,b77cd5f1c7739abb8c0e0e77cf197a4023ee8ff0..c89e35b33dd48a21ca4b6e9ccf89bbf2cebbd569
@@@ -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);
 -
 -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 ) {
diff --cc linkhash.h
index c037fefb36e115e0af347a1e6a18c21f67a1e600,c834a3bc4ea336a59c99ed1c6ca1259a8b5dee41..ead4818405e551247ed4a593a2605e8b9000c10f
@@@ -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);
   * @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);
  
  
@@@ -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 <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