Patch from Scott McKellar to correct some problems with _jsonParserError(),
[OpenSRF.git] / src / libopensrf / osrf_json_parser.c
index e7b3f26..2d8bc8b 100644 (file)
@@ -22,7 +22,7 @@ GNU General Public License for more details.
 static void (*jsonClientErrorCallback) (const char*) = NULL;
 
 /* these are the handlers for our internal parser */
-static jsonParserHandler jsonInternalParserHandlerStruct = {
+static const jsonParserHandler jsonInternalParserHandler = {
        _jsonHandleStartObject,
        _jsonHandleObjectKey,
        _jsonHandleEndObject,
@@ -34,19 +34,34 @@ static jsonParserHandler jsonInternalParserHandlerStruct = {
        _jsonHandleNumber,
        _jsonHandleError
 };
-static jsonParserHandler* 
-       jsonInternalParserHandler = &jsonInternalParserHandlerStruct; 
 
+static jsonParserContext staticContext;
+static int staticContextInUse = 0;       // boolean
 
-jsonParserContext* jsonNewParser( jsonParserHandler* handler, void* userData) {
+static jsonInternalParser staticParser;
+static int staticParserInUse = 0;        // boolean
+
+jsonParserContext* jsonNewParser( const jsonParserHandler* handler, void* userData) {
        jsonParserContext* ctx;
-       OSRF_MALLOC(ctx, sizeof(jsonParserContext));
+
+       // Use the static instance of jsonParserContext,
+       // if it's available
+       
+       if( staticContextInUse )
+               OSRF_MALLOC(ctx, sizeof(jsonParserContext));
+       else {
+               ctx = &staticContext;
+               staticContextInUse = 1;
+       }
+
        ctx->stateStack                 = osrfNewList();
        ctx->buffer                                     = buffer_init(512);
        ctx->utfbuf                                     = buffer_init(5);
        ctx->handler                            = handler;
        ctx->state                                      = 0;
        ctx->index                                      = 0;
+       ctx->chunksize                          = 0;
+       ctx->flags                                      = 0;
        ctx->chunk                                      = NULL;
        ctx->userData                           = userData;
        return ctx;
@@ -57,7 +72,14 @@ void jsonParserFree( jsonParserContext* ctx ) {
        buffer_free(ctx->buffer);
        buffer_free(ctx->utfbuf);
        osrfListFree(ctx->stateStack);
-       free(ctx);
+
+       // if the jsonParserContext was allocated
+       // dynamically, then free it
+       
+       if( &staticContext == ctx )
+               staticContextInUse = 0;
+       else
+               free(ctx);
 }
 
 
@@ -69,14 +91,25 @@ void jsonSetGlobalErrorHandler(void (*errorHandler) (const char*)) {
 int _jsonParserError( jsonParserContext* ctx, char* err, ... ) {
        if( ctx->handler->handleError ) {
                VA_LIST_TO_STRING(err);
+
+               // Determine the beginning and ending points of a JSON
+               // fragment to display, from the vicinity of the error
+
                int pre = ctx->index - 15;
+               if( pre < 0 ) pre = 0;
                int post= ctx->index + 15;
-               while( pre < 0 ) pre++;
-               while( post >= ctx->chunksize ) post--;
-               int l = post - pre;
-               char buf[l];
-               snprintf(buf, sizeof(buf), ctx->chunk + pre);
-               ctx->handler->handleError( ctx->userData, 
+               if( post >= ctx->chunksize ) post = ctx->chunksize - 1;
+
+               // Copy the fragment into a buffer
+               
+               int len = post - pre + 1;  // length of fragment
+               char buf[len + 1];
+               memcpy( buf, ctx->chunk + pre, len );
+               buf[ len ] = '\0';
+
+               // Issue an error message
+
+               ctx->handler->handleError( ctx->userData,
                        "*JSON Parser Error\n - char  = %c\n "
                        "- index = %d\n - near  => %s\n - %s", 
                        ctx->chunk[ctx->index], ctx->index, buf, VA_BUF );
@@ -500,10 +533,22 @@ int jsonParseChunk( jsonParserContext* ctx, const char* data, int datalen, int f
 
 jsonInternalParser* _jsonNewInternalParser() {
        jsonInternalParser* p;
-       OSRF_MALLOC(p, sizeof(jsonInternalParser));
-       p->ctx = jsonNewParser( jsonInternalParserHandler, p );
+
+       // Use the static instance of jsonInternalParser,
+       // if it's available
+       
+       if( staticParserInUse )
+               OSRF_MALLOC(p, sizeof(jsonInternalParser));
+       else {
+               p = &staticParser;
+               staticParserInUse = 1;
+       }
+
+       p->ctx = jsonNewParser( &jsonInternalParserHandler, p );
        p->obj          = NULL;
+       p->current  = NULL;
        p->lastkey      = NULL;
+       p->handleError = NULL;
        return p;
 }
 
@@ -511,7 +556,14 @@ void _jsonInternalParserFree(jsonInternalParser* p) {
        if(!p) return;
        jsonParserFree(p->ctx);
        free(p->lastkey);
-       free(p);
+
+       // if the jsonInternalParser was allocated
+       // dynamically, then free it
+       
+       if( &staticParser == p )
+               staticParserInUse = 0;
+       else
+               free(p);
 }
 
 static jsonObject* _jsonParseStringImpl(const char* str, void (*errorHandler) (const char*) ) {