Patch from Scott McKellar to correct some problems with _jsonParserError(),
[OpenSRF.git] / src / libopensrf / osrf_json_parser.c
index 14cb45c..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 );
@@ -332,7 +365,7 @@ int _jsonParserHandleNumber( jsonParserContext* ctx ) {
 
 
 
-int jsonParseChunk( jsonParserContext* ctx, char* data, int datalen, int flags ) {
+int jsonParseChunk( jsonParserContext* ctx, const char* data, int datalen, int flags ) {
 
        if( !( ctx && ctx->handler && data && datalen > 0 )) return -1;
        ctx->chunksize  = datalen;
@@ -500,10 +533,22 @@ int jsonParseChunk( jsonParserContext* ctx, char* data, int datalen, int flags )
 
 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,10 +556,17 @@ 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(char* str, void (*errorHandler) (const char*) ) {
+static jsonObject* _jsonParseStringImpl(const char* str, void (*errorHandler) (const char*) ) {
        jsonInternalParser* parser = _jsonNewInternalParser();
        parser->handleError = errorHandler;
        jsonParseChunk( parser->ctx, str, strlen(str),  JSON_PARSE_LAST_CHUNK );
@@ -530,7 +582,7 @@ jsonObject* jsonParseStringHandleError(
        return _jsonParseStringImpl(VA_BUF, errorHandler);
 }
 
-jsonObject* jsonParseString( char* str ) {
+jsonObject* jsonParseString( const char* str ) {
        if(!str) return NULL;
        jsonObject* obj =  _jsonParseStringImpl(str, NULL);
        jsonObject* obj2 = jsonObjectDecodeClass(obj);
@@ -538,12 +590,12 @@ jsonObject* jsonParseString( char* str ) {
        return obj2;
 }
 
-jsonObject* jsonParseStringRaw( char* str ) {
+jsonObject* jsonParseStringRaw( const char* str ) {
        if(!str) return NULL;
        return _jsonParseStringImpl(str, NULL);
 }
 
-jsonObject* jsonParseStringFmt( char* str, ... ) {
+jsonObject* jsonParseStringFmt( const char* str, ... ) {
        if(!str) return NULL;
        VA_LIST_TO_STRING(str);
        return _jsonParseStringImpl(VA_BUF, NULL);