Patches from Scott McKellar covering:
authormiker <miker@9efc2488-bf62-4759-914b-345cdb29e865>
Fri, 19 Oct 2007 23:43:59 +0000 (23:43 +0000)
committermiker <miker@9efc2488-bf62-4759-914b-345cdb29e865>
Fri, 19 Oct 2007 23:43:59 +0000 (23:43 +0000)
1. Eliminating a const-removing cast from jsonObjectToJSON().  This
cast is no longer necessary now that a recent patch has changed the
signature of jsonObjectEncodeClass().

2. Moving the JSON_INIT_CLEAR macro out of the header file and into
the implementation file.  No other file invokes this macro -- nor
could it, since the macro refers to two static functions within
osrf_json_object.c.  Strictly speaking another file could provide
other functions with the same signatures, but I doubt that any such
usage was ever intended.

3. Adds some sanity checking to prevent undefined behavior when
a floating point payload is not representable as an int.

4. Streamlines the serialization of hashes and arrays by
eliminating a layer of allocation and deallocation.

git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@1111 9efc2488-bf62-4759-914b-345cdb29e865

include/opensrf/osrf_json_utils.h
src/libopensrf/osrf_json_object.c

index db3c1aa..7b73474 100644 (file)
@@ -34,31 +34,7 @@ GNU General Public License for more details.
 
 #define JSON_NUMBER_CHARS "0123456789.+-e"
 
-
-/* cleans up an object if it is morphing another object, also
- * verifies that the appropriate storage container exists where appropriate */
-#define JSON_INIT_CLEAR(_obj_, newtype)                \
-       if( _obj_->type == JSON_HASH && newtype != JSON_HASH ) {                        \
-               osrfHashFree(_obj_->value.h);                   \
-               _obj_->value.h = NULL;                                  \
-       } else if( _obj_->type == JSON_ARRAY && newtype != JSON_ARRAY ) {       \
-               osrfListFree(_obj_->value.l);                   \
-               _obj_->value.l = NULL;                                  \
-       } else if( _obj_->type == JSON_STRING && newtype != JSON_STRING ) { \
-               free(_obj_->value.s);                                           \
-               _obj_->value.s = NULL;                                  \
-       } \
-       _obj_->type = newtype;\
-       if( newtype == JSON_HASH && _obj_->value.h == NULL ) {  \
-               _obj_->value.h = osrfNewHash();         \
-               _obj_->value.h->freeItem = _jsonFreeHashItem; \
-       } else if( newtype == JSON_ARRAY && _obj_->value.l == NULL ) {  \
-               _obj_->value.l = osrfNewList();         \
-               _obj_->value.l->freeItem = _jsonFreeListItem;\
-       }                                                                                               \
-
-
-/** 
+/**
  * These are the callbacks through which the top level parser 
  * builds objects via the push parser
  */
index 878e3ee..64c8efd 100644 (file)
@@ -13,9 +13,34 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 */
 
+#include <limits.h>
 #include <opensrf/osrf_json.h>
 #include <opensrf/osrf_json_utils.h>
 
+/* cleans up an object if it is morphing another object, also
+ * verifies that the appropriate storage container exists where appropriate */
+#define JSON_INIT_CLEAR(_obj_, newtype)                \
+       if( _obj_->type == JSON_HASH && newtype != JSON_HASH ) {                        \
+               osrfHashFree(_obj_->value.h);                   \
+               _obj_->value.h = NULL;                                  \
+} else if( _obj_->type == JSON_ARRAY && newtype != JSON_ARRAY ) {      \
+               osrfListFree(_obj_->value.l);                   \
+               _obj_->value.l = NULL;                                  \
+} else if( _obj_->type == JSON_STRING && newtype != JSON_STRING ) { \
+               free(_obj_->value.s);                                           \
+               _obj_->value.s = NULL;                                  \
+} \
+       _obj_->type = newtype;\
+       if( newtype == JSON_HASH && _obj_->value.h == NULL ) {  \
+               _obj_->value.h = osrfNewHash();         \
+               _obj_->value.h->freeItem = _jsonFreeHashItem; \
+} else if( newtype == JSON_ARRAY && _obj_->value.l == NULL ) { \
+               _obj_->value.l = osrfNewList();         \
+               _obj_->value.l->freeItem = _jsonFreeListItem;\
+}
+
+static void add_json_to_buffer( const jsonObject* obj, growing_buffer * buf );
+
 jsonObject* jsonNewObject(const char* data) {
 
        jsonObject* o;
@@ -138,7 +163,7 @@ const jsonObject* jsonObjectGetKeyConst( const jsonObject* obj, const char* key
 }
 
 char* jsonObjectToJSON( const jsonObject* obj ) {
-       jsonObject* obj2 = jsonObjectEncodeClass( (jsonObject*) obj);
+       jsonObject* obj2 = jsonObjectEncodeClass( obj );
        char* json = jsonObjectToJSONRaw(obj2);
        jsonObjectFree(obj2);
        return json;
@@ -147,8 +172,11 @@ char* jsonObjectToJSON( const jsonObject* obj ) {
 char* jsonObjectToJSONRaw( const jsonObject* obj ) {
        if(!obj) return NULL;
        growing_buffer* buf = buffer_init(32);
-       int i;
-    char* json;
+       add_json_to_buffer( obj, buf );
+       return buffer_release( buf );
+}
+
+static void add_json_to_buffer( const jsonObject* obj, growing_buffer * buf ) {
 
        switch(obj->type) {
 
@@ -159,8 +187,8 @@ char* jsonObjectToJSONRaw( const jsonObject* obj ) {
 
                case JSON_NUMBER: {
                        double x = obj->value.n;
-                       if( x == (int) x ) {
-                               INT_TO_STRING((int)x);  
+                       if( x <= INT_MAX && x >= INT_MIN && x == (int) x ) {
+                               INT_TO_STRING((int)x);
                                OSRF_BUFFER_ADD(buf, INTSTR);
 
                        } else {
@@ -188,13 +216,12 @@ char* jsonObjectToJSONRaw( const jsonObject* obj ) {
                case JSON_ARRAY: {
                        OSRF_BUFFER_ADD_CHAR(buf, '[');
                        if( obj->value.l ) {
+                               int i;
                                for( i = 0; i != obj->value.l->size; i++ ) {
-                                       json = jsonObjectToJSONRaw(OSRF_LIST_GET_INDEX(obj->value.l, i));
                                        if(i > 0) OSRF_BUFFER_ADD(buf, ",");
-                                       OSRF_BUFFER_ADD(buf, json);
-                                       free(json);
+                                       add_json_to_buffer( OSRF_LIST_GET_INDEX(obj->value.l, i), buf );
                                }
-                       } 
+                       }
                        OSRF_BUFFER_ADD_CHAR(buf, ']');
                        break;
                }
@@ -209,9 +236,7 @@ char* jsonObjectToJSONRaw( const jsonObject* obj ) {
                        while( (item = osrfHashIteratorNext(itr)) ) {
                                if(i++ > 0) OSRF_BUFFER_ADD(buf, ",");
                                buffer_fadd(buf, "\"%s\":", itr->current);
-                               char* json = jsonObjectToJSONRaw(item);
-                               OSRF_BUFFER_ADD(buf, json);
-                               free(json);
+                               add_json_to_buffer( item, buf );
                        }
 
                        osrfHashIteratorFree(itr);
@@ -219,8 +244,6 @@ char* jsonObjectToJSONRaw( const jsonObject* obj ) {
                        break;
                }
        }
-
-    return buffer_release(buf);
 }