From 66fc4bc123bf6fefd747c90b5aa329000f0ce5fa Mon Sep 17 00:00:00 2001 From: Charl Wentzel Date: Mon, 3 Apr 2017 21:48:29 +0200 Subject: [PATCH] Important Update: - Bug fix: incorrect memory allocation in SetValue() - Implement conversion of escaped chars during parsing - Implement escaping chars during printing --- DataTreeCore.cpp | 2 +- JSONparseCore.cpp | 108 ++++++++++++++++++++++++++++++++++++++++------ JSONparseCore.h | 1 + 3 files changed, 97 insertions(+), 14 deletions(-) diff --git a/DataTreeCore.cpp b/DataTreeCore.cpp index 171e8f9..c4662fd 100644 --- a/DataTreeCore.cpp +++ b/DataTreeCore.cpp @@ -325,7 +325,7 @@ bool CDataTree::SetValue( TDataMember * Member, EDataType Type, const char * Va } // Create copy of value - NewValue = (char *)malloc( sizeof(Len+1) ); + NewValue = (char *)malloc( Len+1 ); if (Value) { memcpy( NewValue, Value, Len ); } else { diff --git a/JSONparseCore.cpp b/JSONparseCore.cpp index e499124..bf60320 100644 --- a/JSONparseCore.cpp +++ b/JSONparseCore.cpp @@ -360,6 +360,8 @@ void CJSONparse::SkipWhiteSpace() bool CJSONparse::ParseString( char ** Value, int &Len ) { char * EndMark; + char * ValuePos = NULL; + char HexVal[5] = ""; // Check for opening quote if (*BufPos != '"') { @@ -402,7 +404,7 @@ bool CJSONparse::ParseString( char ** Value, int &Len ) } if (*(BufPos+1) == 'u') { for (EndMark = BufPos+2; EndMark < BufPos+6; EndMark++) { - if (!*BufPos && RefillBuffer) { + if (!*EndMark && RefillBuffer) { FillBuffer(); continue; } @@ -414,9 +416,11 @@ bool CJSONparse::ParseString( char ** Value, int &Len ) } } BufPos += 6; + Len -= 5; } else if (strchr( "bfnrt/\\\"", *(BufPos+1) )) { BufPos += 2; + Len -= 1; } else { Error = true; @@ -433,13 +437,48 @@ bool CJSONparse::ParseString( char ** Value, int &Len ) } } - // Get size of name - Len = BufPos-Mark-2; - // Create Return value pointer + Len += BufPos-Mark-2; *Value = (char*)malloc( Len+1 ); - memcpy( *Value, Mark+1, Len ); - (*Value)[Len] = 0; + ValuePos = *Value; + + // Convert value + BufPos = Mark+1; + while ((EndMark = strpbrk( BufPos, "\"\\" ))) + { + // Copy portion + memcpy( ValuePos, BufPos, (EndMark-BufPos) ); + ValuePos += (EndMark-BufPos); + BufPos = EndMark; + + if (*BufPos == '"') { + break; + } + else if (*BufPos== '\\') { + if (*(BufPos+1) == 'u') { + strncpy( HexVal, BufPos+2, 4 ); + *ValuePos = (char)strtol( HexVal, NULL, 16 ); + ValuePos++; + BufPos += 6; + } + else { + switch (*(BufPos+1)) { + case 'b': *ValuePos = '\b'; break; + case 'f': *ValuePos = '\f'; break; + case 'n': *ValuePos = '\n'; break; + case 'r': *ValuePos = '\r'; break; + case 't': *ValuePos = '\t'; break; + case '/': *ValuePos = '/'; break; + case '\\': *ValuePos = '\\'; break; + case '"': *ValuePos = '"'; break; + } + ValuePos++; + BufPos +=2; + } + } + } + *ValuePos = 0; + BufPos++; // Success return true; @@ -678,6 +717,52 @@ bool CJSONparse::ParsePrimitive( TDataMember * Member ) } //--------------------------------------------------------------------------- +bool CJSONparse::PrintString( char * String, int Len ) +{ + // Start quote + write( OutputHandle, "\"", 1 ); + + // Content + BufPos = String; + while (true) + { + // Scan for special chars + Mark = BufPos; + while ((*BufPos >= 32) && (*BufPos <= 126) && (*BufPos != '\\') && (*BufPos != '/') && (*BufPos != '"')) + BufPos++; + + // Print Portion + write( OutputHandle, Mark, (BufPos-Mark) ); + + // Handle special chars + if (!*BufPos) { + break; + } + else { + switch (*BufPos) { + case '\b': write( OutputHandle, "\\b", 2 ); break; + case '\f': write( OutputHandle, "\\f", 2 ); break; + case '\n': write( OutputHandle, "\\n", 2 ); break; + case '\r': write( OutputHandle, "\\r", 2 ); break; + case '\t': write( OutputHandle, "\\t", 2 ); break; + case '/': write( OutputHandle, "\\/", 2 ); break; + case '\\': write( OutputHandle, "\\\\", 2 ); break; + case '"': write( OutputHandle, "\\\"", 2 ); break; + default: + dprintf( OutputHandle, "\\u%04d", *BufPos ); + break; + } + BufPos++; + } + } + + // End Quote + write( OutputHandle, "\"", 1 ); + + return true; +} +//--------------------------------------------------------------------------- + bool CJSONparse::PrintObject( TDataMember * Object, const int Indent ) { TDataMember * Member; @@ -716,12 +801,11 @@ bool CJSONparse::PrintObject( TDataMember * Object, const int Indent ) } // Print key name - write( OutputHandle, "\"", 1 ); - write( OutputHandle, Member->Name, strlen(Member->Name) ); + PrintString( Member->Name, strlen(Member->Name) ); if (Indent) { - write( OutputHandle,"\" : ", 4 ); + write( OutputHandle," : ", 3 ); } else { - write( OutputHandle, "\":", 2 ); + write( OutputHandle, ":", 1 ); } // Print value @@ -739,9 +823,7 @@ bool CJSONparse::PrintObject( TDataMember * Object, const int Indent ) break; case jtString : - write( OutputHandle, "\"", 1 ); - write( OutputHandle, Member->Value, Member->Len ); - write( OutputHandle, "\"", 1 ); + PrintString( Member->Value, Member->Len ); break; case jtArray : diff --git a/JSONparseCore.h b/JSONparseCore.h index 0364d0e..2c272d8 100644 --- a/JSONparseCore.h +++ b/JSONparseCore.h @@ -54,6 +54,7 @@ private: bool ParseString( TDataMember * Member ); bool ParsePrimitive( TDataMember * Member ); + bool PrintString( char * String, int Len ); bool PrintObject( TDataMember * Object, const int Indent ); bool PrintArray( TDataMember * Object, const int Indent );