Fix the jsonFormatString function.
authorscottmk <scottmk@9efc2488-bf62-4759-914b-345cdb29e865>
Wed, 21 Apr 2010 20:48:18 +0000 (20:48 +0000)
committerscottmk <scottmk@9efc2488-bf62-4759-914b-345cdb29e865>
Wed, 21 Apr 2010 20:48:18 +0000 (20:48 +0000)
Specifically: it was misbehaving when a string literal contained
a comma, square bracket, or curly brace.  Now it pays attention to
whether those characters are in within quotes or not, and treats
them accordingly.

It also applies more consistent indentation by consuming
extraneous white space that would otherwise lead to ragged margins.

M    src/libopensrf/osrf_json_tools.c

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

src/libopensrf/osrf_json_tools.c

index d8e0a8f..e444db9 100644 (file)
@@ -13,8 +13,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 */
 
-#include <opensrf/osrf_json.h>
-#include <opensrf/osrf_json_utils.h>
+#include <ctype.h>
+#include "opensrf/osrf_json.h"
+#include "opensrf/osrf_json_utils.h"
 
 static jsonObject* findMultiPath( const jsonObject* o,
                const char* root, const char* path );
@@ -45,42 +46,74 @@ static void append_indentation( growing_buffer* buf, int depth ) {
 
        If the input pointer is NULL, return an empty string.
 
+       WARNING: if the input JSON is not well-formed, the output JSON is likely
+       to be even worse-formed.
+
        The calling code is responsible for freeing the formatted copy.
 */
 char* jsonFormatString( const char* string ) {
-       if(!string) return strdup("");
+       if( !string ) return strdup( "" );
 
-       growing_buffer* buf = buffer_init(64);
+       growing_buffer* buf = buffer_init( 64 );
        int i;
        int depth = 0;
+       int in_quote = 0;   // boolean; true if in a string literal
+       int escaped = 0;    // boolean: true if previous character was a backslash
+       int beginning = 1;  // boolean: true if we're starting a new line
 
        char c;
-       for(i = 0; string[i]; i++) {
-               c = string[i];
+       for( i = 0; string[i]; i++ ) {
+               c = string[ i ];
 
                if( c == '{' || c == '[' ) {
 
                        OSRF_BUFFER_ADD_CHAR( buf, c );
-                       OSRF_BUFFER_ADD_CHAR( buf, '\n' );
-                       append_indentation( buf, ++depth );
+                       if( !in_quote ) {
+                               OSRF_BUFFER_ADD_CHAR( buf, '\n' );
+                               append_indentation( buf, ++depth );
+                               beginning = 1;
+                       }
 
                } else if( c == '}' || c == ']' ) {
 
-                       OSRF_BUFFER_ADD_CHAR( buf, '\n' );
-                       append_indentation( buf, --depth );
+                       if( !in_quote ) {
+                               OSRF_BUFFER_ADD_CHAR( buf, '\n' );
+                               append_indentation( buf, --depth );
+                               beginning = 1;
+                       }
                        OSRF_BUFFER_ADD_CHAR( buf, c );
 
                } else if( c == ',' ) {
 
                        OSRF_BUFFER_ADD_CHAR( buf, ',' );
-                       OSRF_BUFFER_ADD_CHAR( buf, '\n' );
-                       append_indentation( buf, depth );
+                       if( !in_quote ) {
+                               OSRF_BUFFER_ADD_CHAR( buf, '\n' );
+                               append_indentation( buf, depth );
+                               beginning = 1;
+                       }
 
-               } else
-                       OSRF_BUFFER_ADD_CHAR(buf, c);
+               } else {
+                       // Ignore white space at the beginning of a line
+                       if( beginning ) {
+                               if( !isspace( (unsigned char) c )) {
+                                       OSRF_BUFFER_ADD_CHAR( buf, c );
+                                       beginning = 0;
+                               }
+                       } else {
+                               OSRF_BUFFER_ADD_CHAR( buf, c );
+                       }
+               }
+
+               if( '\\' == c )
+                       escaped = !escaped;
+               else {
+                       if( '\"' == c && !escaped )
+                               in_quote = !in_quote;
+                       escaped = 0;
+               }
        }
 
-    return buffer_release(buf);
+    return buffer_release( buf );
 }