Permalink
Browse files

Upgrade wxJSON to 1.2.1

Fixes issue when some files in recent list have non-ascii characters in their names
  • Loading branch information...
1 parent 5d8cb37 commit 2607987729dffcc1c988ebafcc94818c07f4bc7f @tea tea committed Dec 17, 2010
Showing with 5,347 additions and 3,635 deletions.
  1. +6 −4 src/eSettings.cpp
  2. +88 −12 src/json_defs.h
  3. +1,467 −1,284 src/jsonreader.cpp
  4. +78 −85 src/jsonreader.h
  5. +2,332 −1,387 src/jsonval.cpp
  6. +315 −213 src/jsonval.h
  7. +1,000 −587 src/jsonwriter.cpp
  8. +61 −63 src/jsonwriter.h
View
10 src/eSettings.cpp
@@ -65,10 +65,12 @@ void eSettings::Load(const wxString& appDataPath) {
if (m_jsonRoot.HasMember(wxT("env"))) {
const wxJSONValue envNode = m_jsonRoot.ItemAt(wxT("env"));
- const wxArrayString keys = envNode.GetMemberNames();
- for( size_t i = 0; i < keys.Count(); i++){
- const wxString& key = keys[i];
- env[key] = envNode.ItemAt(key).AsString();
+ if (envNode.IsObject()) {
+ const wxArrayString keys = envNode.GetMemberNames();
+ for( size_t i = 0; i < keys.Count(); i++){
+ const wxString& key = keys[i];
+ env[key] = envNode.ItemAt(key).AsString();
+ }
}
}
View
100 src/json_defs.h
@@ -16,8 +16,8 @@
// The following symbols should be updated for each new component release
// since some kind of tests, like those of AM_WXCODE_CHECKFOR_COMPONENT_VERSION()
// for "configure" scripts under unix, use them.
-#define wxJSON_MAJOR 0
-#define wxJSON_MINOR 5
+#define wxJSON_MAJOR 1
+#define wxJSON_MINOR 2
#define wxJSON_RELEASE 1
// For non-Unix systems (i.e. when building without a configure script),
@@ -56,30 +56,27 @@
// the __PRETTY_FUNCTION__ macro expands to the full class's
// member name in the GNU GCC.
-// For other compilers you have to set the correct macro
-//#if !defined( __GNUC__ )
-// #define __PRETTY_FUNCTION__ __WXFUNCTION__
-//#endif
+// For other compilers we use the standard __wxFUNCTION__ macro
+#if !defined( __GNUC__ )
+ #define __PRETTY_FUNCTION__ __WXFUNCTION__
+#endif
-#define __PRETTY_FUNCTION__ __WXFUNCTION__
// define wxJSON_USE_UNICODE if wxWidgets was built with
// unicode support
#if defined( wxJSON_USE_UNICODE )
#undef wxJSON_USE_UNICODE
#endif
-
// do not modify the following lines
#if wxUSE_UNICODE == 1
#define wxJSON_USE_UNICODE
#endif
// the following macro, if defined, cause the wxJSONValue to store
// pointers to C-strings as pointers to statically allocated
-// C-strings
-// by default this macro is not defined
-// #define WXJSON_USE_CSTRING
+// C-strings. By default this macro is not defined
+// #define wxJSON_USE_CSTRING
// the following macro, if defined, cause the wxJSONvalue and its
@@ -125,7 +122,86 @@
#endif
#if !defined( LLONG_MIN )
- #define LLONG_MIN -9223372036854775808
+ #define LLONG_MIN -9223372036854775808
+#endif
+
+
+
+// the same applies for all other integer constants
+#if !defined( INT_MIN )
+ #define INT_MIN -32768
+#endif
+#if !defined( INT_MAX )
+ #define INT_MAX 32767
+#endif
+#if !defined( UINT_MAX )
+ #define UINT_MAX 65535
+#endif
+#if !defined( LONG_MIN )
+ #define LONG_MIN -2147483648
#endif
+#if !defined( LONG_MAX )
+ #define LONG_MAX 2147483647
+#endif
+#if !defined( ULONG_MAX )
+ #define ULONG_MAX 4294967295
+#endif
+#if !defined( SHORT_MAX )
+ #define SHORT_MAX 32767
+#endif
+#if !defined( SHORT_MIN )
+ #define SHORT_MIN -32768
+#endif
+#if !defined( USHORT_MAX )
+ #define USHORT_MAX 65535
+#endif
+
+
+
+//
+// define the wxJSON_ASSERT() macro to expand to wxASSERT()
+// unless the wxJSON_NOABORT_ASSERT is defined
+// #define wxJSON_NOABORT_ASSERT
+#if defined( wxJSON_NOABORT_ASSERT )
+ #define wxJSON_ASSERT( cond )
+#else
+ #define wxJSON_ASSERT( cond ) wxASSERT( cond );
+#endif
+
+
+//
+// the following macros are used by the wxJSONWriter::WriteStringValues()
+// when the wxJSONWRITER_SPLIT_STRING flag is set
+#define wxJSONWRITER_LAST_COL 50
+#define wxJSONWRITER_SPLIT_COL 75
+#define wxJSONWRITER_MIN_LENGTH 15
+#define wxJSONWRITER_TAB_LENGTH 4
+
+
+//
+// some compilers (i.e. MSVC++) defines their own 'snprintf' function
+// so if it is not defined, define it in the following lines
+// please note that we cannot use the wxWidget's counterpart 'wxSnprintf'
+// because the latter uses 'wxChar' but wxJSON only use 'char'
+#if !defined(snprintf) && defined(_MSC_VER)
+#define snprintf _snprintf
+#endif
+
+
+//
+// check if wxWidgets is compiled using --enable-stl in which case
+// we have to use different aproaches when declaring the array and
+// key/value containers (see the docs: wxJSON internals: array and hash_map
+#undef wxJSON_USE_STL
+#if defined( wxUSE_STL ) && wxUSE_STL == 1
+#define wxJSON_USE_STL
+#endif
+
+//
+// defines the MIN and MAX macro for numeric arguments
+// note that the safest way to define such functions is using templates
+#define MIN(a,b) a < b ? a : b
+#define MAX(a,b) a > b ? a : b
+
#endif // _WX_JSON_DEFS_H_
View
2,751 src/jsonreader.cpp
1,467 additions, 1,284 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
163 src/jsonreader.h
@@ -17,7 +17,7 @@
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
-
+
#ifdef __BORLANDC__
#pragma hdrstop
#endif
@@ -36,120 +36,113 @@
// The flags of the parser
enum {
- wxJSONREADER_STRICT = 0,
- wxJSONREADER_ALLOW_COMMENTS = 1,
- wxJSONREADER_STORE_COMMENTS = 2,
- wxJSONREADER_CASE = 4,
- wxJSONREADER_MISSING = 8,
- wxJSONREADER_MULTISTRING = 16,
- wxJSONREADER_COMMENTS_AFTER = 32,
- wxJSONREADER_TOLERANT = wxJSONREADER_ALLOW_COMMENTS | wxJSONREADER_CASE |
+ wxJSONREADER_STRICT = 0,
+ wxJSONREADER_ALLOW_COMMENTS = 1,
+ wxJSONREADER_STORE_COMMENTS = 2,
+ wxJSONREADER_CASE = 4,
+ wxJSONREADER_MISSING = 8,
+ wxJSONREADER_MULTISTRING = 16,
+ wxJSONREADER_COMMENTS_AFTER = 32,
+ wxJSONREADER_NOUTF8_STREAM = 64,
+ wxJSONREADER_MEMORYBUFF = 128,
+
+ wxJSONREADER_TOLERANT = wxJSONREADER_ALLOW_COMMENTS | wxJSONREADER_CASE |
wxJSONREADER_MISSING | wxJSONREADER_MULTISTRING,
- wxJSONREADER_COMMENTS_BEFORE = wxJSONREADER_ALLOW_COMMENTS | wxJSONREADER_STORE_COMMENTS
+ wxJSONREADER_COMMENTS_BEFORE = wxJSONREADER_ALLOW_COMMENTS | wxJSONREADER_STORE_COMMENTS
};
class WXDLLIMPEXP_JSON wxJSONReader
{
public:
- wxJSONReader( int flags = wxJSONREADER_TOLERANT, int maxErrors = 30 );
- virtual ~wxJSONReader();
+ wxJSONReader( int flags = wxJSONREADER_TOLERANT, int maxErrors = 30 );
+ virtual ~wxJSONReader();
- int Parse( const wxString& doc, wxJSONValue* val );
- int Parse( wxInputStream& doc, wxJSONValue* val );
+ int Parse( const wxString& doc, wxJSONValue* val );
+ int Parse( wxInputStream& doc, wxJSONValue* val );
- int GetErrorCount() const;
- int GetWarningCount() const;
+ int GetDepth() const;
+ int GetErrorCount() const;
+ int GetWarningCount() const;
+ const wxArrayString& GetErrors() const;
+ const wxArrayString& GetWarnings() const;
- static int UTF8NumBytes( char ch );
+ static int UTF8NumBytes( char ch );
#if defined( wxJSON_64BIT_INT )
- static bool Strtoll( const wxString& str, wxInt64* i64 );
- static bool Strtoull( const wxString& str, wxUint64* ui64 );
+ static bool Strtoll( const wxString& str, wxInt64* i64 );
+ static bool Strtoull( const wxString& str, wxUint64* ui64 );
+ static bool DoStrto_ll( const wxString& str, wxUint64* ui64, wxChar* sign );
#endif
- const wxArrayString& GetErrors() const;
- const wxArrayString& GetWarnings() const;
-
protected:
- int Parse( wxJSONValue* val );
- int DoRead( wxJSONValue& val );
- void AddError( const wxString& descr );
- void AddError( const wxString& fmt, const wxString& str );
- void AddError( const wxString& fmt, wxChar ch );
- void AddWarning( int type, const wxString& descr );
- int GetStart();
- int ReadChar();
- int GetChar();
- int PeekChar();
- void StoreValue( int ch, const wxString& key, wxJSONValue& value, wxJSONValue& parent );
- int SkipWhiteSpace();
- int SkipComment();
- void StoreComment( const wxJSONValue* parent );
- int ReadString( wxJSONValue& val );
- int ReadToken( int ch, wxString& s );
- int ReadValue( int ch, wxJSONValue& val );
- int ReadUnicode( long int& hex );
- int AppendUnicodeSequence( wxString& s, int hex );
- int NumBytes();
-
- static bool DoStrto_ll( const wxString& str, wxUint64* ui64, wxChar* sign );
-
- // constructor's parameters
+ int DoRead( wxInputStream& doc, wxJSONValue& val );
+ void AddError( const wxString& descr );
+ void AddError( const wxString& fmt, const wxString& str );
+ void AddError( const wxString& fmt, wxChar ch );
+ void AddWarning( int type, const wxString& descr );
+ int GetStart( wxInputStream& is );
+ int ReadChar( wxInputStream& is );
+ int PeekChar( wxInputStream& is );
+ void StoreValue( int ch, const wxString& key, wxJSONValue& value, wxJSONValue& parent );
+ int SkipWhiteSpace( wxInputStream& is );
+ int SkipComment( wxInputStream& is );
+ void StoreComment( const wxJSONValue* parent );
+ int ReadString( wxInputStream& is, wxJSONValue& val );
+ int ReadToken( wxInputStream& is, int ch, wxString& s );
+ int ReadValue( wxInputStream& is, int ch, wxJSONValue& val );
+ int ReadUES( wxInputStream& is, char* uesBuffer );
+ int AppendUES( wxMemoryBuffer& utf8Buff, const char* uesBuffer );
+ int NumBytes( char ch );
+ int ConvertCharByChar( wxString& s, const wxMemoryBuffer& utf8Buffer );
+ int ReadMemoryBuff( wxInputStream& is, wxJSONValue& val );
- //! Flag that control the parser behaviour,
- int m_flags;
+ //! Flag that control the parser behaviour,
+ int m_flags;
- //! aximum number of errors stored in the error's array
- int m_maxErrors;
+ //! Maximum number of errors stored in the error's array
+ int m_maxErrors;
- // data for the Parse() function
+ //! The current line number (start at 1).
+ int m_lineNo;
- //! The current line number (start at 1).
- int m_lineNo;
+ //! The current column number (start at 1).
+ int m_colNo;
- //! The current column number (start at 1).
- int m_colNo;
+ //! The current level of object/array annidation (start at ZERO).
+ int m_level;
- //! The current level of object/array annidation (start at ZERO).
- int m_level;
+ //! The depth level of the read JSON text
+ int m_depth;
- //! The pointer to the value object that is being read.
- wxJSONValue* m_current;
+ //! The pointer to the value object that is being read.
+ wxJSONValue* m_current;
- //! The pointer to the value object that was last stored.
- wxJSONValue* m_lastStored;
+ //! The pointer to the value object that was last stored.
+ wxJSONValue* m_lastStored;
- //! The pointer to the value object that will be read.
- wxJSONValue* m_next;
+ //! The pointer to the value object that will be read.
+ wxJSONValue* m_next;
- //! The comment string read by SkipComment().
- wxString m_comment;
+ //! The comment string read by SkipComment().
+ wxString m_comment;
- //! The starting line of the comment string.
- int m_commentLine;
+ //! The starting line of the comment string.
+ int m_commentLine;
- //! The array of error messages.
- wxArrayString m_errors;
+ //! The array of error messages.
+ wxArrayString m_errors;
- //! The array of warning messages.
- wxArrayString m_warnings;
+ //! The array of warning messages.
+ wxArrayString m_warnings;
- //! The current character position for string input
- int m_charPos;
+ //! The character read by the PeekChar() function (-1 none)
+ int m_peekChar;
- //! The input type (0=string, 1=stream)
- int m_inType;
-
- //! The pointer to the input object (a string or a stream)
- void* m_inObject;
-
- //! The character read by the PeekChar() function (-1 none)
- int m_peekChar;
-
- //! The conversion object (can only be NULL or the pointer to a UTF-8 converter)
- wxMBConv* m_conv;
+ //! ANSI: do not convert UTF-8 strings
+ bool m_noUtf8;
};
-#endif // not defined _WX_JSONREADER_H
+
+#endif // not defined _WX_JSONREADER_H
View
3,719 src/jsonval.cpp
2,332 additions, 1,387 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
528 src/jsonval.h
@@ -17,7 +17,7 @@
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
-
+
#ifdef __BORLANDC__
#pragma hdrstop
#endif
@@ -37,13 +37,22 @@
// forward declarations
class WXDLLIMPEXP_JSON wxJSONReader;
class WXDLLIMPEXP_JSON wxJSONRefData;
-class WXDLLIMPEXP_JSON wxJSONInternalMap;
-class WXDLLIMPEXP_JSON wxJSONInternalArray;
+
+#if defined( wxJSON_USE_STL )
+ // if compiling on MinGW we use the STL-style declaration of wxWidget's
+ // container classes
+ class WXDLLIMPEXP_JSON wxJSONValue;
+ WX_DECLARE_OBJARRAY( wxJSONValue, wxJSONInternalArray );
+ WX_DECLARE_STRING_HASH_MAP( wxJSONValue, wxJSONInternalMap );
+#else
+ class WXDLLIMPEXP_JSON wxJSONInternalMap;
+ class WXDLLIMPEXP_JSON wxJSONInternalArray;
+#endif
//! The type of the value held by the wxJSONRefData class
enum wxJSONType {
- wxJSONTYPE_EMPTY = 0, /*!< empty type is for uninitialized objects */
+ wxJSONTYPE_INVALID = 0, /*!< the object is not uninitialized */
wxJSONTYPE_NULL, /*!< the object contains a NULL value */
wxJSONTYPE_INT, /*!< the object contains an integer */
wxJSONTYPE_UINT, /*!< the object contains an unsigned integer */
@@ -53,10 +62,13 @@ enum wxJSONType {
wxJSONTYPE_BOOL, /*!< the object contains a boolean */
wxJSONTYPE_ARRAY, /*!< the object contains an array of values */
wxJSONTYPE_OBJECT, /*!< the object contains a map of keys/values */
- wxJSONTYPE_INT32, /*!< the object contains a 32-bit integer */
+ wxJSONTYPE_LONG, /*!< the object contains a 32-bit integer */
wxJSONTYPE_INT64, /*!< the object contains a 64-bit integer */
- wxJSONTYPE_UINT32, /*!< the object contains an unsigned 32-bit integer */
- wxJSONTYPE_UINT64 /*!< the object contains an unsigned 64-bit integer */
+ wxJSONTYPE_ULONG, /*!< the object contains an unsigned 32-bit integer */
+ wxJSONTYPE_UINT64, /*!< the object contains an unsigned 64-bit integer */
+ wxJSONTYPE_SHORT, /*!< the object contains a 16-bit integer */
+ wxJSONTYPE_USHORT, /*!< the object contains a 16-bit unsigned integer */
+ wxJSONTYPE_MEMORYBUFF /*!< the object contains a binary memory buffer */
};
// the comment position: every value only has one comment position
@@ -70,270 +82,360 @@ enum {
/***********************************************************************
- class wxJSONValue
+ class wxJSONValue
***********************************************************************/
// class WXDLLIMPEXP_JSON wxJSONValue : public wxObject
class WXDLLIMPEXP_JSON wxJSONValue
{
- friend class wxJSONReader;
+ friend class wxJSONReader;
public:
- // ctors and dtor
- wxJSONValue();
- wxJSONValue( wxJSONType type );
- wxJSONValue( int i );
- wxJSONValue( unsigned int i );
+ // ctors and dtor
+ wxJSONValue();
+ wxJSONValue( wxJSONType type );
+ wxJSONValue( int i );
+ wxJSONValue( unsigned int i );
+ wxJSONValue( short i );
+ wxJSONValue( unsigned short i );
+ wxJSONValue( long int i );
+ wxJSONValue( unsigned long int i );
#if defined( wxJSON_64BIT_INT)
- wxJSONValue( wxInt64 i );
- wxJSONValue( wxUint64 ui );
+ wxJSONValue( wxInt64 i );
+ wxJSONValue( wxUint64 ui );
#endif
- wxJSONValue( bool b );
- wxJSONValue( double d );
- wxJSONValue( const wxChar* str ); // assume static ASCIIZ strings
- wxJSONValue( const wxString& str );
- wxJSONValue( const wxJSONValue& other );
- virtual ~wxJSONValue();
-
- // get the value type
- wxJSONType GetType() const;
- bool IsEmpty() const;
- bool IsNull() const;
- bool IsInt() const;
- bool IsUInt() const;
+ wxJSONValue( bool b );
+ wxJSONValue( double d );
+ wxJSONValue( const wxChar* str ); // assume static ASCIIZ strings
+ wxJSONValue( const wxString& str );
+ wxJSONValue( const wxMemoryBuffer& buff );
+ wxJSONValue( const void* buff, size_t len );
+ wxJSONValue( const wxJSONValue& other );
+ virtual ~wxJSONValue();
+
+ // functions for retrieving the value type
+ wxJSONType GetType() const;
+ bool IsValid() const;
+ bool IsNull() const;
+ bool IsInt() const;
+ bool IsUInt() const;
+ bool IsShort() const;
+ bool IsUShort() const;
+ bool IsLong() const;
+ bool IsULong() const;
#if defined( wxJSON_64BIT_INT)
- bool IsInt32() const;
- bool IsInt64() const;
- bool IsUInt32() const;
- bool IsUInt64() const;
+ bool IsInt32() const;
+ bool IsInt64() const;
+ bool IsUInt32() const;
+ bool IsUInt64() const;
#endif
- bool IsBool() const;
- bool IsDouble() const;
- bool IsString() const;
- bool IsCString() const;
- bool IsArray() const;
- bool IsObject() const;
-
- // get the value as ...
- int AsInt() const;
- unsigned int AsUInt() const;
+ bool IsBool() const;
+ bool IsDouble() const;
+ bool IsString() const;
+ bool IsCString() const;
+ bool IsArray() const;
+ bool IsObject() const;
+ bool IsMemoryBuff() const;
+
+ // function for retireving the value as ...
+ int AsInt() const;
+ unsigned int AsUInt() const;
+ short AsShort() const;
+ unsigned short AsUShort() const;
+ long int AsLong() const;
+ unsigned long AsULong() const;
+ bool AsInt( int& i ) const;
+ bool AsUInt( unsigned int& ui ) const;
+ bool AsShort( short int& s ) const;
+ bool AsUShort( unsigned short& us ) const;
+ bool AsLong( long int& l ) const;
+ bool AsULong( unsigned long& ul ) const;
#if defined( wxJSON_64BIT_INT)
- int AsInt32() const;
- unsigned int AsUInt32() const;
- wxInt64 AsInt64() const;
- wxUint64 AsUInt64() const;
+ wxInt32 AsInt32() const;
+ wxUint32 AsUInt32() const;
+ wxInt64 AsInt64() const;
+ wxUint64 AsUInt64() const;
+ bool AsInt32( wxInt32& i32 ) const;
+ bool AsUInt32( wxUint32& ui32 ) const;
+ bool AsInt64( wxInt64& i64 ) const;
+ bool AsUInt64( wxUint64& ui64 ) const;
#endif
- bool AsBool() const;
- double AsDouble() const;
- wxString AsString() const;
- const wxChar* AsCString() const;
- const wxJSONInternalMap* AsMap() const;
- const wxJSONInternalArray* AsArray() const;
-
- // get members names, size and other info
- bool HasMember( unsigned index ) const;
- bool HasMember( const wxString& key ) const;
- int Size() const;
- wxArrayString GetMemberNames() const;
-
- // appending items, resizing and deleting items
- wxJSONValue& Insert( unsigned index, const wxJSONValue& value );
- wxJSONValue& Append( const wxJSONValue& value );
- wxJSONValue& Append( bool b );
- wxJSONValue& Append( int i );
- wxJSONValue& Append( unsigned int ui );
+ bool AsBool() const;
+ double AsDouble() const;
+ wxString AsString() const;
+ const wxChar* AsCString() const;
+ bool AsBool( bool& b ) const;
+ bool AsDouble( double& d ) const;
+ bool AsString( wxString& str ) const;
+ bool AsCString( wxChar* ch ) const;
+ wxMemoryBuffer AsMemoryBuff() const;
+ bool AsMemoryBuff( wxMemoryBuffer& buff ) const;
+
+ const wxJSONInternalMap* AsMap() const;
+ const wxJSONInternalArray* AsArray() const;
+
+ // get members names, size and other info
+ bool HasMember( unsigned index ) const;
+ bool HasMember( const wxString& key ) const;
+ int Size() const;
+ wxArrayString GetMemberNames() const;
+
+ // appending items, resizing and deleting items
+ wxJSONValue& Insert( unsigned index, const wxJSONValue& value );
+ wxJSONValue& Append( const wxJSONValue& value );
+ wxJSONValue& Append( bool b );
+ wxJSONValue& Append( int i );
+ wxJSONValue& Append( unsigned int ui );
+ wxJSONValue& Append( short int i );
+ wxJSONValue& Append( unsigned short int ui );
+ wxJSONValue& Append( long int l );
+ wxJSONValue& Append( unsigned long int ul );
#if defined( wxJSON_64BIT_INT )
- wxJSONValue& Append( wxInt64 i );
- wxJSONValue& Append( wxUint64 ui );
+ wxJSONValue& Append( wxInt64 i );
+ wxJSONValue& Append( wxUint64 ui );
#endif
- wxJSONValue& Append( double d );
- wxJSONValue& Append( const wxChar* str );
- wxJSONValue& Append( const wxString& str );
- bool Remove( int index );
- bool Remove( const wxString& key );
- void RemoveAll();
- void Clear();
- bool Cat( const wxChar* str );
- bool Cat( const wxString& str );
-
- // retrieve an item
- wxJSONValue& Item( unsigned index );
- wxJSONValue& Item( const wxString& key );
- wxJSONValue ItemAt( unsigned index ) const;
- wxJSONValue ItemAt( const wxString& key ) const;
-
- wxJSONValue& operator [] ( unsigned index );
- wxJSONValue& operator [] ( const wxString& key );
-
- wxJSONValue& operator = ( int i );
- wxJSONValue& operator = ( unsigned int ui );
+ wxJSONValue& Append( double d );
+ wxJSONValue& Append( const wxChar* str );
+ wxJSONValue& Append( const wxString& str );
+ wxJSONValue& Append( const wxMemoryBuffer& buff );
+ wxJSONValue& Append( const void* buff, size_t len );
+ bool Remove( int index );
+ bool Remove( const wxString& key );
+ void RemoveAll();
+ void Clear();
+ bool Cat( const wxChar* str );
+ bool Cat( const wxString& str );
+ bool Cat( const wxMemoryBuffer& buff );
+
+ // retrieve an item
+ wxJSONValue& Item( unsigned index );
+ wxJSONValue& Item( const wxString& key );
+ wxJSONValue ItemAt( unsigned index ) const;
+ wxJSONValue ItemAt( const wxString& key ) const;
+
+ wxJSONValue& operator [] ( unsigned index );
+ wxJSONValue& operator [] ( const wxString& key );
+
+ wxJSONValue& operator = ( int i );
+ wxJSONValue& operator = ( unsigned int ui );
+ wxJSONValue& operator = ( short int i );
+ wxJSONValue& operator = ( unsigned short int ui );
+ wxJSONValue& operator = ( long int l );
+ wxJSONValue& operator = ( unsigned long int ul );
#if defined( wxJSON_64BIT_INT )
- wxJSONValue& operator = ( wxInt64 i );
- wxJSONValue& operator = ( wxUint64 ui );
+ wxJSONValue& operator = ( wxInt64 i );
+ wxJSONValue& operator = ( wxUint64 ui );
#endif
- wxJSONValue& operator = ( bool b );
- wxJSONValue& operator = ( double d );
- wxJSONValue& operator = ( const wxChar* str );
- wxJSONValue& operator = ( const wxString& str );
- wxJSONValue& operator = ( const wxJSONValue& value );
-
- // get the value of a default value
- wxJSONValue Get( const wxString& key, const wxJSONValue& defaultValue ) const;
-
- // comparison function
- bool IsSameAs( const wxJSONValue& other ) const;
-
- // comment-related functions
- int AddComment( const wxString& str, int position = wxJSONVALUE_COMMENT_DEFAULT );
- int AddComment( const wxArrayString& comments, int position = wxJSONVALUE_COMMENT_DEFAULT );
- wxString GetComment( int idx = -1 ) const;
- int GetCommentPos() const;
- int GetCommentCount() const;
- void ClearComments();
- const wxArrayString& GetCommentArray() const;
-
- // debugging functions
- wxString GetInfo() const;
- wxString Dump( bool deep = false, int mode = 0 ) const;
-
- wxJSONRefData* GetRefData() const;
- wxJSONRefData* SetType( wxJSONType type );
-
- int GetLineNo() const;
- void SetLineNo( int num );
-
- static wxString TypeToString( wxJSONType type );
+ wxJSONValue& operator = ( bool b );
+ wxJSONValue& operator = ( double d );
+ wxJSONValue& operator = ( const wxChar* str );
+ wxJSONValue& operator = ( const wxString& str );
+ wxJSONValue& operator = ( const wxMemoryBuffer& buff );
+ // wxJSONValue& operator = ( const void* buff, size_t len ); cannot be declared
+ wxJSONValue& operator = ( const wxJSONValue& value );
+
+ // get the value or a default value
+ wxJSONValue Get( const wxString& key, const wxJSONValue& defaultValue ) const;
+
+ // comparison function
+ bool IsSameAs( const wxJSONValue& other ) const;
+
+ // comment-related functions
+ int AddComment( const wxString& str, int position = wxJSONVALUE_COMMENT_DEFAULT );
+ int AddComment( const wxArrayString& comments, int position = wxJSONVALUE_COMMENT_DEFAULT );
+ wxString GetComment( int idx = -1 ) const;
+ int GetCommentPos() const;
+ int GetCommentCount() const;
+ void ClearComments();
+ const wxArrayString& GetCommentArray() const;
+
+ // debugging functions
+ wxString GetInfo() const;
+ wxString Dump( bool deep = false, int mode = 0 ) const;
+
+ //misc functions
+ wxJSONRefData* GetRefData() const;
+ wxJSONRefData* SetType( wxJSONType type );
+ int GetLineNo() const;
+ void SetLineNo( int num );
+
+ // public static functions: mainly used for debugging
+ static wxString TypeToString( wxJSONType type );
+ static wxString MemoryBuffToString( const wxMemoryBuffer& buff, size_t len = -1 );
+ static wxString MemoryBuffToString( const void* buff, size_t len, size_t actualLen = -1 );
+ static int CompareMemoryBuff( const wxMemoryBuffer& buff1, const wxMemoryBuffer& buff2 );
+ static int CompareMemoryBuff( const wxMemoryBuffer& buff1, const void* buff2 );
+ static wxMemoryBuffer ArrayToMemoryBuff( const wxJSONValue& value );
protected:
- wxJSONValue* Find( unsigned index ) const;
- wxJSONValue* Find( const wxString& key ) const;
- // void DeleteObj();
- void DeepCopy( const wxJSONValue& other );
+ wxJSONValue* Find( unsigned index ) const;
+ wxJSONValue* Find( const wxString& key ) const;
+ void DeepCopy( const wxJSONValue& other );
- wxJSONRefData* Init( wxJSONType type );
- wxJSONRefData* COW();
+ wxJSONRefData* Init( wxJSONType type );
+ wxJSONRefData* COW();
-#if defined( wxJSON_64BIT_INT )
- bool AsInt32( wxInt32* i) const;
- bool AsUInt32( wxUint32* i ) const;
-#endif
+ // overidden from wxObject
+ virtual wxJSONRefData* CloneRefData(const wxJSONRefData *data) const;
+ virtual wxJSONRefData* CreateRefData() const;
- // overidden from wxObject
- virtual wxJSONRefData* CloneRefData(const wxJSONRefData *data) const;
- virtual wxJSONRefData* CreateRefData() const;
+ void SetRefData(wxJSONRefData* data);
+ void Ref(const wxJSONValue& clone);
+ void UnRef();
+ void UnShare();
+ void AllocExclusive();
- void SetRefData(wxJSONRefData* data);
- void Ref(const wxJSONValue& clone);
- void UnRef();
- void UnShare();
- void AllocExclusive();
+ //! the referenced data
+ wxJSONRefData* m_refData;
- //! the referenced data
- wxJSONRefData* m_refData;
- // used for debugging purposes: only in debug builds.
+ // used for debugging purposes: only in debug builds.
#if defined( WXJSON_USE_VALUE_COUNTER )
- int m_progr;
- static int sm_progr;
+ int m_progr;
+ static int sm_progr;
#endif
};
+#if !defined( wxJSON_USE_STL )
+ // if using wxWidget's implementation of container classes we declare
+ // the OBJARRAY are HASH_MAP _after_ the wxJSONValue is fully known
+ WX_DECLARE_OBJARRAY( wxJSONValue, wxJSONInternalArray );
+ WX_DECLARE_STRING_HASH_MAP( wxJSONValue, wxJSONInternalMap );
+#endif
+
+
/***********************************************************************
- class wxJSONRefData
+ class wxJSONRefData
***********************************************************************/
-WX_DECLARE_OBJARRAY( wxJSONValue, wxJSONInternalArray );
-WX_DECLARE_STRING_HASH_MAP( wxJSONValue, wxJSONInternalMap );
+
//! The actual value held by the wxJSONValue class (internal use)
/*!
- Note that this structure is not a \b union as in the previous versions.
- This allow to store instances of the string, ObjArray and HashMap objects
- (no more pointers to them)
+ Note that this structure is a \b union as in versions prior to 0.4.x
+ The union just stores primitive types and not complex types which are
+ stored in separate data members of the wxJSONRefData structure.
+
+ This organization give us more flexibility when retrieving compatible
+ types such as ints unsigned ints, long and so on.
+ To know more about the internal structure of the wxJSONValue class
+ see \ref pg_json_internals.
*/
-struct wxJSONValueHolder {
+union wxJSONValueHolder {
+ int m_valInt;
+ unsigned int m_valUInt;
+ short int m_valShort;
+ unsigned short m_valUShort;
+ long int m_valLong;
+ unsigned long m_valULong;
+ double m_valDouble;
+ const wxChar* m_valCString;
+ bool m_valBool;
#if defined( wxJSON_64BIT_INT )
- wxInt64 m_valInt;
- wxUint64 m_valUInt;
+ wxInt64 m_valInt64;
+ wxUint64 m_valUInt64;
+#endif
+ };
+
+//
+// access to the (unsigned) integer value is done through
+// the VAL_INT macro which expands to the 'long' integer
+// data member of the 'long long' integer if 64-bits integer
+// support is enabled
+#if defined( wxJSON_64BIT_INT )
+ #define VAL_INT m_valInt64
+ #define VAL_UINT m_valUInt64
#else
- int m_valInt;
- unsigned m_valUInt;
+ #define VAL_INT m_valLong
+ #define VAL_UINT m_valULong
#endif
- double m_valDouble;
- const wxChar* m_valCString;
- bool m_valBool;
- wxString m_valString;
- wxJSONInternalArray m_valArray;
- wxJSONInternalMap m_valMap;
- };
+
// class WXDLLIMPEXP_JSON wxJSONRefData : public wxObjectRefData
class WXDLLIMPEXP_JSON wxJSONRefData
{
- // friend class wxJSONReader;
- friend class wxJSONValue;
+ // friend class wxJSONReader;
+ friend class wxJSONValue;
+ friend class wxJSONWriter;
public:
- wxJSONRefData();
- virtual ~wxJSONRefData();
+ wxJSONRefData();
+ virtual ~wxJSONRefData();
- int GetRefCount() const;
+ int GetRefCount() const;
- // there is no need to define copy ctor
- // wxJSONRefData( const wxJSONRefData& other );
+ // there is no need to define copy ctor
-protected:
- //! the references count
- int m_refCount;
-
- //! The actual type of the value held by this object.
- wxJSONType m_type;
-
- //! The JSON value held by this object.
- /*!
- This data member contains the JSON data types defined by the
- JSON syntax with the exception of wxJSONTYPE_EMPTY which is an
- internal type used by the parser class.
- */
- wxJSONValueHolder m_value;
-
- //! The position of the comment line(s), if any.
- /*!
- The data member contains one of the following constants:
- \li \c wxJSONVALUE_COMMENT_BEFORE
- \li \c wxJSONVALUE_COMMENT_AFTER
- \li \c wxJSONVALUE_COMMENT_INLINE
- */
- int m_commentPos;
-
- //! The array of comment lines; may be empty.
- wxArrayString m_comments;
-
- //! The line number when this value was read
- /*!
- This data member is used by the wxJSONReader class and it is
- used to store the line number of the JSON text document where
- the value appeared. This value is compared to the line number
- of a comment line in order to obtain the value which a
- comment refersto.
- */
- int m_lineNo;
-
-
- // used for debugging purposes: only in debug builds.
- #if defined( WXJSON_USE_VALUE_COUNTER )
+ //! the references count
+ int m_refCount;
+
+ //! The actual type of the value held by this object.
+ wxJSONType m_type;
+
+ //! The JSON value held by this object.
+ /*!
+ This data member contains the JSON data types defined by the
+ JSON syntax with the exception of the complex objects.
+ This data member is an union of the primitive types
+ so that it is simplier to cast them in other compatible types.
+ */
+ wxJSONValueHolder m_value;
+
+ //! The JSON string value.
+ wxString m_valString;
+
+ //! The JSON array value.
+ wxJSONInternalArray m_valArray;
+
+ //! The JSON object value.
+ wxJSONInternalMap m_valMap;
+
+ //! The position of the comment line(s), if any.
+ /*!
+ The data member contains one of the following constants:
+ \li \c wxJSONVALUE_COMMENT_BEFORE
+ \li \c wxJSONVALUE_COMMENT_AFTER
+ \li \c wxJSONVALUE_COMMENT_INLINE
+ */
+ int m_commentPos;
+
+ //! The array of comment lines; may be empty.
+ wxArrayString m_comments;
+
+ //! The line number when this value was read
+ /*!
+ This data member is used by the wxJSONReader class and it is
+ used to store the line number of the JSON text document where
+ the value appeared. This value is compared to the line number
+ of a comment line in order to obtain the value which a
+ comment refersto.
+ */
+ int m_lineNo;
+
+ //! The pointer to the memory buffer object
+ /*!
+ Note that despite using reference counting, the \b wxMemoryBuffer is not a
+ \e copy-on-write structure so the wxJSON library uses some tricks in order to
+ avoid the side effects of copying / assigning wxMemoryBuffer objects
+ */
+ wxMemoryBuffer* m_memBuff;
+
+ // used for debugging purposes: only in debug builds.
+#if defined( WXJSON_USE_VALUE_COUNTER )
int m_progr;
static int sm_progr;
- #endif
+#endif
};
-#endif // not defined _WX_JSONVAL_H
+
+
+#endif // not defined _WX_JSONVAL_H
View
1,587 src/jsonwriter.cpp
@@ -16,6 +16,7 @@
#include "jsonwriter.h"
#include <wx/sstream.h>
+#include <wx/mstream.h>
#include <wx/debug.h>
#include <wx/log.h>
@@ -25,46 +26,98 @@ static const wxChar* writerTraceMask = _T("traceWriter");
\brief The JSON document writer
This class is a JSON document writer and it is used to write a
- wxJSONValue object to an output stream or to a string object
- of type wxString.
- The ctor accepts some parameters which can be used to
+ wxJSONValue object to an output stream or to a string object.
+ The ctor accepts some parameters which can be used to
change the style of the output.
- The default output is in human-readable format.
+ The default output is in human-readable format that uses a three-space
+ indentation for object / array sub-items and separates every
+ value with a linefeed character.
- Here is an example on how to use this class:
+
+ \par Examples
+
+ Using the default writer constructor
\code
// construct the JSON value object and add values to it
wxJSONValue root;
root["key1"] = "some value";
...
- // now we want a string that contains the text data
- // we use the default settings to obtain human-readable text
- wxJSONWriter jsw;
+ // construct the string that will contain the JSON text
wxString str;
- jsw.Write( root, str );
+
+ // construct a JSON writer: use the default writer's settings
+ wxJSONWriter writer;
+
+ // call the writer's Write() memberfunction
+ writer.Write( root, str );
+ \endcode
+
+
+ To write a JSON value object using a four-spaces indentation and forcing all
+ comment strings to apear before the value they refer to, use the following code:
+ \code
+ wxJSONWriter writer( wxJSONWRITER_STYLED | // want a styled output
+ wxJSONWRITER_WRITE_COMMENTS | // want comments in the document
+ wxJSONWRITER_COMMENTS_BEFORE, // force comments before value
+ 0, // initial indentation
+ 4); // indentation step
+ writer.Write( value, document );
\endcode
- \par output objects
+ The following code construct a JSON writer that produces the most compact
+ text output but it is hard to read by humans:
+
+ \code
+ wxJSONWriter writer( wxJSONWRITER_NONE );
+ writer.Write( value, document );
+ \endcode
+
+
+ \par The two types of output objects
You can write JSON text to two different kind of objects:
\li a string object (\b wxString)
\li a stream object (\b wxOutputStream)
- When writing to a string object, the output is platform dependent.
+ When writing to a string object, the output is platform- and mode-dependent.
In ANSI builds, the JSON text output in the string object will
contain one-byte characters: the actual characters represented is
locale dependent.
In Unicode builds, the JSON text output in the string contains
wide characters which encoding format is platform dependent: UCS-2 in
Windows, UCS-4 in GNU/Linux.
+ Starting from wxWidgets version 2.9 the internal encoding for Unicode
+ builds in linux/unix systems is UTF-8.
When writing to a stream object, the JSON text output is always
encoded in UTF-8 in both ANSI and Unicode builds.
+ In ANSI builds the user may want to suppress UTF-8 encoding so
+ that the JSON text can be stored in ANSI format.
+ Note that this is not valid JSON text unless all characters written
+ to the JSON text document are in the US-ASCII character ser (0x00..0x7F).
+ To know more read \ref wxjson_tutorial_unicode_ansi
+
+ \par Efficiency
+
+ In versions up to 1.0 the JSON writer wrote every character to the
+ output object (the string or the stream).
+ This is very inefficient becuase the writer converted each char to
+ UTF-8 when writing to streams but we have to note that only string values
+ have to be actually converted.
+ Special JSON characters, numbers and literals do not need the conversion
+ because they lay in the US-ASCII plane (0x00-0x7F)
+ and no conversion is needed as the UTF-8 encoding is the same as US-ASCII.
For more info about the unicode topic see \ref wxjson_tutorial_unicode.
+
+ \par The problem of writing doubles
+
+ You can customize the ouput of doubles by specifing the format string
+ that has to be used by the JSON writer class. To know more about this issue
+ read \ref wxjson_tutorial_write_doubles
*/
//! Ctor.
@@ -73,58 +126,91 @@ static const wxChar* writerTraceMask = _T("traceWriter");
Note that if \c styled is FALSE the indentation is totally suppressed
and the values of the other two parameters are simply ignored.
- \param style this can be a combination of the following constant OR'ed togheter:
- \li wxJSONWRITER_NONE: no indentation is performed (hard to read by humans)
- and no comment lines are written.
- \li wxJSONWRITER_STYLED: output is human-readable (indented)
- \li wxJSONWRITER_WRITE_COMMENTS: only meaningfull if the style is \b styled
- this flag force the writer to write C/C++ comment strings: the comments
- will be written in their original position
- \li wxJSONWRITER_COMMENTS_BEFORE: only meaingfull if the style also includes
- wxJSONWRITER_WRITE_COMMENTS, this flag force the writer to write C/C++ comments
- always before the value they refer to
- \li wxJSONWRITER_COMMENTS_AFTER: only meaingfull if the style also includes
- wxJSONWRITER_WRITE_COMMENTS, this flag force the writer to write C/C++ comments
- always after the value they refer to
- \li wxJSONWRITER_SPLIT_STRINGS: only meaningfull if the style is \b styled
- this flag force the writer to split strings into two or more lines if they
- contain a new-line character. See \ref json_multiline_string for more info.
-
- \param indent the initial indentation in number of spaces
- \param step the indentation increment for new objects/arrays (default=3)
-
- Note that the wxJSONWRITER_STYLED flag controls all the other parameters. If the
- style is wxJSONWRITER_NONE, all other parameters and flags are ignored.
-
- \b Example
-
- To write a JSON value object using a four-spaces indentation and forcing all
- comment strings to apear before the value they refer to, use the following code:
- \code
- wxJSONWriter writer( wxJSONWRITER_STYLED | // want a styled output
- wxJSONWRITER_WRITE_COMMENTS | // want comments in the document
- wxJSONWRITER_COMMENTS_BEFORE, // force comments before value
- 0, // initial indentation
- 4); // indentation step
- writer.Write( value, document );
- \endcode
-
- The following code construct a JSON writer that produces hard-to-read
- output: indentation is suppressed and no comment lines are written
- \code
- wxJSONWriter writer( wxJSONWRITER_NONE );
- writer.Write( value, document );
- \endcode
+ \param indent the initial indentation in number of spaces. Default is ZERO.
+ If you specify the wxJSONWRITER_TAB_INDENT flag for the \e style,
+ this value referes to the number of TABs in the initial indentation
+
+ \param step the indentation increment for new objects/arrays in number of spaces
+ (default is 3).
+ This value is ignored if you specify the wxJSONWRITER_TAB_INDENT flag for
+ the \e style: the indentation increment is only one TAB character.
+
+ \param style this is a combination of the following constants OR'ed togheter:
+ \li wxJSONWRITER_NONE: no indentation is performed and no LF character is
+ written between values.
+ This style produces strict JSON text but it is hard to read by humans
+ \li wxJSONWRITER_STYLED: output is human-readable: values are separated by
+ LF characters and sub-items are indented.
+ This style produces strict JSON text that is easy to read by humans.
+ \li wxJSONWRITER_WRITE_COMMENTS: this flag force the writer to write C/C++
+ comment strings, if any. The comments will be written in their original position.
+ C/C++ comments may not be recognized by other JSON implementations because
+ they are not strict JSON text.
+ \li wxJSONWRITER_COMMENTS_BEFORE: this flag force the writer to write C/C++ comments
+ always before the value they refer to.
+ In order for this style to take effect, you also have to specify the
+ wxJSONWRITER_WRITE_COMMENTS flag.
+ \li wxJSONWRITER_COMMENTS_AFTER: this flag force the writer to write C/C++ comments
+ always after the value they refer to.
+ In order for this style to take effect, you also have to specify the
+ wxJSONWRITER_WRITE_COMMENTS flag.
+ \li wxJSONWRITER_SPLIT_STRINGS: this flag cause the writer to split strings
+ in more than one line if they are too long.
+ \li wxJSONWRITER_NO_LINEFEEDS: this flag cause the JSON writer to not add
+ newlines between values. It is ignored if wxJSONWRITER_STYLED is not set.
+ This style produces strict JSON text.
+ \li wxJSONWRITER_ESCAPE_SOLIDUS: the solidus character (/) should only be
+ escaped if the JSON text is meant for embedding in HTML.
+ Unlike in older 0.x versions, it is disabled by default and this flag cause
+ the solidus char to be escaped.
+ This style produces strict JSON text.
+ \li wxJSONWRITER_MULTILINE_STRING:this is a multiline-string mode where newlines
+ and tabs are not escaped. This is not strict JSON, but it helps immensely when
+ manually editing json files with multiline strings
+ \li wxJSONWRITER_RECOGNIZE_UNSIGNED: this flag cause the JSON writer to prepend
+ a plus sign (+) to unsigned integer values. This is used by the wxJSON reader to
+ force the integer to be stored in an \b unsigned \b int. Note that this
+ feature may be incompatible with other JSON implementations.
+ \li wxJSONWRITER_TAB_INDENT: this flag cause the indentation of sub-objects / arrays
+ to be done using a TAB character instead of SPACES.
+ In order for this style to take effect, you also have to specify the
+ wxJSONWRITER_STYLED flag.
+ This style produces strict JSON text.
+ \li wxJSONWRITER_NO_INDENTATION: this flag cause the JSON writer to not add
+ indentation. It is ignored if wxJSONWRITER_STYLED is not set.
+ This style produces strict JSON text.
+ \li wxJSONWRITER_NOUTF8_STREAM: suppress UTF-8 conversion when writing string
+ values to the stream thus producing ANSI text output; only meaningfull in
+ ANSI builds, this flag is simply ignored in Unicode builds.
+ \li wxJSONWRITER_MEMORYBUFF:
+
+
+ Note that for the style wxJSONWRITER_NONE the JSON text output is a bit
+ different from that of old 0.x versions although it is syntactically equal.
+ If you rely on the old JSON output formatting read the following page
+ \ref wxjson_tutorial_style_none.
+ To know more about the writer's styles see \ref wxjson_tutorial_style
*/
wxJSONWriter::wxJSONWriter( int style, int indent, int step )
{
- m_indent = indent;
- m_step = step;
- m_style = style;
- if ( m_style == wxJSONWRITER_NONE ) {
- m_indent = 0;
- m_step = 0;
- }
+ m_indent = indent;
+ m_step = step;
+ m_style = style;
+ m_noUtf8 = false;
+ if ( m_style == wxJSONWRITER_NONE ) {
+ m_indent = 0;
+ m_step = 0;
+ }
+ // set the default format string for doubles as
+ // 10 significant digits and suppress trailing ZEROes
+ SetDoubleFmtString( "%.10g") ;
+
+#if !defined( wxJSON_USE_UNICODE )
+ // in ANSI builds we can suppress UTF-8 conversion for both the writer and the reader
+ if ( m_style == wxJSONWRITER_NOUTF8_STREAM ) {
+ m_noUtf8 = true;
+ }
+#endif
}
//! Dtor - does nothing
@@ -141,20 +227,12 @@ wxJSONWriter::~wxJSONWriter()
\li a stream object ( \b wxOutputStream)
The two types of output object are very different because the
- text outputted in encoded in different formats depending on the
+ text outputted is encoded in different formats depending on the
build mode.
-
- For \b Unicode builds, the JSON text output is platform dependent
- because \b wxString objects store wide characters which are
- represented in different formats: UCS-2 on Windows and UCS-4
- on Linux.
-
- For \b ANSI mode the JSON text output written to a string object
- is encoded in a locale dependent format: wide characters are not
- supported and the string object always contains one-byte characters.
-
- When the output object is a stream, the JSON text output is always
- encoded in UTF-8 format in both Unicode and ANSI builds.
+ When writing to a string object, the JSON text output is encoded
+ differently depending on the build mode and the platform.
+ Writing to a stream always produce UTF-8 encoded text.
+ To know more about this topic read \ref wxjson_tutorial_unicode.
Also note that the Write() function does not return a status code.
If you are writing to a string, you do not have to warry about this
@@ -184,292 +262,326 @@ wxJSONWriter::~wxJSONWriter()
void
wxJSONWriter::Write( const wxJSONValue& value, wxString& str )
{
- m_level = 0;
+#if !defined( wxJSON_USE_UNICODE )
+ // in ANSI builds output to a string never use UTF-8 conversion
+ bool noUtf8_bak = m_noUtf8; // save the current setting
+ m_noUtf8 = true;
+#endif
+
+ wxMemoryOutputStream os;
+ Write( value, os );
- // when writing to string objects, we cannot use different charsets
- // as the one used in the wxString object which is either ANSI or
- // Unicode depending the wxWidget's build mode.
- m_conv = 0;
+ // get the address of the buffer
+ wxFileOffset len = os.GetLength();
+ wxStreamBuffer* osBuff = os.GetOutputStreamBuffer();
+ void* buffStart = osBuff->GetBufferStart();
- m_outType = 0; // string
- m_outObject = &str;
- DoWrite( value, 0, false );
+ if ( m_noUtf8 ) {
+ str = wxString::From8BitData( (const char*) buffStart, len );
+ }
+ else {
+ str = wxString::FromUTF8( (const char*) buffStart, len );
+ }
+#if !defined( wxJSON_USE_UNICODE )
+ m_noUtf8 = noUtf8_bak; // restore the old setting
+#endif
}
//! \overload Write( const wxJSONValue&, wxString& )
void
wxJSONWriter::Write( const wxJSONValue& value, wxOutputStream& os )
{
- m_level = 0;
- // we use the UTF-8 encoding. It is only meaningfull in Unicode builds
- wxMBConvUTF8 conv;
- m_conv = &conv;
+ m_level = 0;
+ DoWrite( os, value, 0, false );
+}
- m_outType = 1; // stream
- m_outObject = &os;
+//! Set the format string for double values.
+/*!
+ This function sets the format string used for printing double values.
+ Double values are outputted to JSON text using the \b snprintf function
+ with a default format string of:
+ \code
+ %.10g
+ \endcode
+ which prints doubles with a precision of 10 decimal digits and suppressing
+ trailing ZEROes.
- DoWrite( value, 0, false );
+ Note that the parameter is a pointer to \b char and not to \b wxChar. This
+ is because the JSON writer always procudes UTF-8 encoded text and decimal
+ digits in UTF-8 are made of only one UTF-8 code-unit (1 byte).
+*/
+void
+wxJSONWriter::SetDoubleFmtString( const char* fmt )
+{
+ m_fmt = (char*) fmt;
}
+
//! Perform the real write operation.
/*!
- This is a recursive function. If the value is not a hashmap or
- an array, the function calls the other \b WriteXxxxx functions
- which actually write the text output.
- For maps and arrays, the function calls itself for all items
- in the array / hashmap after incrementing the \c m_level data member.
+ This is a recursive function that gets the type of the \c value object and
+ calls several protected functions depending on the type:
+
+ \li \c WriteNullvalue for type NULL
+ \li \c WriteStringValue() for STRING and CSTRING types
+ \li \c WriteIntValue for INT types
+ \li \c WriteUIntValue for UINT types
+ \li \c WriteBoolValue for BOOL types
+ \li \c WriteDoubleValue for DOUBLE types
+ \li \c WriteMemoryBuff for MEMORYBUFF types
+
+ If the value is an array or key/value map (types ARRAY and OBJECT), the function
+ iterates through all JSON value object in the array/map and calls itself for every
+ item in the container.
*/
int
-wxJSONWriter::DoWrite( const wxJSONValue& value, const wxString* key,
- bool comma )
+wxJSONWriter::DoWrite( wxOutputStream& os, const wxJSONValue& value, const wxString* key, bool comma )
{
- // note that this function is recursive
-
- // some variables that cannot be allocated in the switch statement
- const wxJSONInternalMap* map = 0;
- int size;
-
- // determine the comment position; it is one of:
- //
- // wxJSONVALUE_COMMENT_BEFORE
- // wxJSONVALUE_COMMENT_AFTER
- // wxJSONVALUE_COMMENT_INLINE
- //
- // or -1 if comments have not to be written
- int commentPos = -1;
- if ( value.GetCommentCount() > 0 && (m_style & wxJSONWRITER_WRITE_COMMENTS)) {
- commentPos = value.GetCommentPos();
- if ( ( m_style & wxJSONWRITER_COMMENTS_BEFORE) != 0 ) {
- commentPos = wxJSONVALUE_COMMENT_BEFORE;
- }
- else if ( (m_style & wxJSONWRITER_COMMENTS_AFTER) != 0 ) {
- commentPos = wxJSONVALUE_COMMENT_AFTER;
- }
- }
-
- int lastChar = 0; // check if WriteComment() writes the last LF char
-
- // first write the comment if it is BEFORE
- if ( commentPos == wxJSONVALUE_COMMENT_BEFORE ) {
- lastChar = WriteComment( value, true );
- }
- if ( lastChar < 0 ) {
- return lastChar;
- }
+ // note that this function is recursive
+
+ // some variables that cannot be allocated in the switch statement
+ const wxJSONInternalMap* map = 0;
+ int size;
+ m_colNo = 1; m_lineNo = 1;
+ // determine the comment position; it is one of:
+ //
+ // wxJSONVALUE_COMMENT_BEFORE
+ // wxJSONVALUE_COMMENT_AFTER
+ // wxJSONVALUE_COMMENT_INLINE
+ //
+ // or -1 if comments have not to be written
+ int commentPos = -1;
+ if ( value.GetCommentCount() > 0 && (m_style & wxJSONWRITER_WRITE_COMMENTS)) {
+ commentPos = value.GetCommentPos();
+ if ( ( m_style & wxJSONWRITER_COMMENTS_BEFORE) != 0 ) {
+ commentPos = wxJSONVALUE_COMMENT_BEFORE;
+ }
+ else if ( (m_style & wxJSONWRITER_COMMENTS_AFTER) != 0 ) {
+ commentPos = wxJSONVALUE_COMMENT_AFTER;
+ }
+ }
- lastChar = WriteIndent();
- if ( lastChar < 0 ) {
- return lastChar;
- }
+ int lastChar = 0; // check if WriteComment() writes the last LF char
- // now write the key if it is not NULL
- if ( key ) {
- lastChar = WriteKey( *key );
- }
- if ( lastChar < 0 ) {
- return lastChar;
- }
+ // first write the comment if it is BEFORE
+ if ( commentPos == wxJSONVALUE_COMMENT_BEFORE ) {
+ lastChar = WriteComment( os, value, true );
+ if ( lastChar < 0 ) {
+ return lastChar;
+ }
+ else if ( lastChar != '\n' ) {
+ WriteSeparator( os );
+ }
+ }
- // now write the value
- int t = value.GetType();
- switch ( t ) {
- case wxJSONTYPE_EMPTY :
- wxFAIL_MSG( _T("wxJSONWriter::WriteEmpty() cannot be called (not a valid JSON type)"));
- break;
+ lastChar = WriteIndent( os );
+ if ( lastChar < 0 ) {
+ return lastChar;
+ }
- case wxJSONTYPE_NULL :
- // lastChar = WriteNull();
- // break;
+ // now write the key if it is not NULL
+ if ( key ) {
+ lastChar = WriteKey( os, *key );
+ }
+ if ( lastChar < 0 ) {
+ return lastChar;
+ }
+
+ // now write the value
+ wxJSONInternalMap::const_iterator it; // declare the map object
+ long int count = 0;
+
+ wxJSONType t = value.GetType();
+ switch ( t ) {
+ case wxJSONTYPE_INVALID :
+ WriteInvalid( os );
+ wxFAIL_MSG( _T("wxJSONWriter::WriteEmpty() cannot be called (not a valid JSON text"));
+ break;
case wxJSONTYPE_INT :
- case wxJSONTYPE_INT64 :
- // lastChar = WriteInt( value.AsInt());
- // break;
+ case wxJSONTYPE_SHORT :
+ case wxJSONTYPE_LONG :
+ case wxJSONTYPE_INT64 :
+ lastChar = WriteIntValue( os, value );
+ break;
case wxJSONTYPE_UINT :
- case wxJSONTYPE_UINT64 :
- // lastChar = WriteUInt( value.AsUInt());
- // break;
+ case wxJSONTYPE_USHORT :
+ case wxJSONTYPE_ULONG :
+ case wxJSONTYPE_UINT64 :
+ lastChar = WriteUIntValue( os, value );
+ break;
+ case wxJSONTYPE_NULL :
+ lastChar = WriteNullValue( os );
+ break;
case wxJSONTYPE_BOOL :
- // lastChar = WriteBool( value.AsBool());
- // break;
+ lastChar = WriteBoolValue( os, value );
+ break;
case wxJSONTYPE_DOUBLE :
- // lastChar = WriteDouble( value.AsDouble());
- // break;
- lastChar = WritePrimitiveValue( value );
- break;
+ lastChar = WriteDoubleValue( os, value );
+ break;
case wxJSONTYPE_STRING :
- lastChar = WriteStringValue( value.AsString());
- break;
-
case wxJSONTYPE_CSTRING :
- // we use the 'WriteString()' function
- lastChar = WriteStringValue( value.AsString());
- break;
+ lastChar = WriteStringValue( os, value.AsString());
+ break;
+
+ case wxJSONTYPE_MEMORYBUFF :
+ lastChar = WriteMemoryBuff( os, value.AsMemoryBuff());
+ break;
case wxJSONTYPE_ARRAY :
- {
- ++m_level;
- lastChar = WriteChar( '[' );
- // the inline comment for objects and arrays are printed in the open char
- if ( commentPos == wxJSONVALUE_COMMENT_INLINE ) {
- commentPos = -1; // we have already written the comment
- lastChar = WriteChar( ' ' );
- if ( lastChar < 0 ) {
- return lastChar;
- }
- lastChar = WriteComment( value, false );
- if ( lastChar < 0 ) {
- return lastChar;
- }
- if ( lastChar != '\n' ) {
- WriteChar( '\n' );
- lastChar = '\n';
- }
- }
- else {
- lastChar = WriteChar( '\n' );
- if ( lastChar < 0 ) {
- return lastChar;
- }
- }
-
- size = value.Size();
- for ( int i = 0; i < size; i++ ) {
- bool comma = false;
- if ( i < size - 1 ) {
- comma = true;
- }
- wxJSONValue v = value.ItemAt( i );
- lastChar = DoWrite( v, 0, comma );
- if ( lastChar == -1 ) {
- return lastChar;
- }
- }
- --m_level;
- lastChar = WriteIndent();
- if ( lastChar < 0 ) {
- return lastChar;
- }
- lastChar = WriteChar( ']' );
- }
- break;
+ ++m_level;
+ os.PutC( '[' );
+ // the inline comment for objects and arrays are printed in the open char
+ if ( commentPos == wxJSONVALUE_COMMENT_INLINE ) {
+ commentPos = -1; // we have already written the comment
+ lastChar = WriteComment( os, value, false );
+ if ( lastChar < 0 ) {
+ return lastChar;
+ }
+ if ( lastChar != '\n' ) {
+ lastChar = WriteSeparator( os );
+ }
+ }
+ else { // comment is not to be printed inline, so write a LF
+ lastChar = WriteSeparator( os );
+ if ( lastChar < 0 ) {
+ return lastChar;
+ }
+ }
- case wxJSONTYPE_OBJECT :
- ++m_level;
+ // now iterate through all sub-items and call DoWrite() recursively
+ size = value.Size();
+ for ( int i = 0; i < size; i++ ) {
+ bool comma = false;
+ if ( i < size - 1 ) {
+ comma = true;
+ }
+ wxJSONValue v = value.ItemAt( i );
+ lastChar = DoWrite( os, v, 0, comma );
+ if ( lastChar < 0 ) {
+ return lastChar;
+ }
- lastChar = WriteChar( '{' );
- if ( lastChar < 0 ) {
- return lastChar;
- }
- // the inline comment for objects and arrays are printed in the open char
- if ( commentPos == wxJSONVALUE_COMMENT_INLINE ) {
- lastChar = WriteChar( ' ' );
- commentPos = -1; // we have already written the comment
- lastChar = WriteComment( value, false );
+ }
+ --m_level;
+ lastChar = WriteIndent( os );
if ( lastChar < 0 ) {
- return lastChar;
+ return lastChar;
}
- if ( lastChar != '\n' ) {
- WriteChar( '\n' );
+ os.PutC( ']' );
+ break;
+
+ case wxJSONTYPE_OBJECT :
+ ++m_level;
+
+ os.PutC( '{' );
+ // the inline comment for objects and arrays are printed in the open char
+ if ( commentPos == wxJSONVALUE_COMMENT_INLINE ) {
+ commentPos = -1; // we have already written the comment
+ lastChar = WriteComment( os, value, false );
+ if ( lastChar < 0 ) {
+ return lastChar;
+ }
+ if ( lastChar != '\n' ) {
+ WriteSeparator( os );
+ }
}
- }
- else {
- lastChar = WriteChar( '\n' );
- }
-
- map = value.AsMap();
- size = value.Size();
- wxJSONInternalMap::const_iterator it;
- int i = 0;
- for ( it = map->begin(); it != map->end(); ++it ) {
- // get the key and the value
- wxString key = it->first;
- const wxJSONValue& v = it->second;
-
- bool comma = false;
- if ( i < size - 1 ) {
- comma = true;
+ else {
+ lastChar = WriteSeparator( os );
}
- lastChar = DoWrite( v, &key, comma );
- if ( lastChar == -1 ) {
- return lastChar;
+
+ map = value.AsMap();
+ size = value.Size();
+ count = 0;
+ for ( it = map->begin(); it != map->end(); ++it ) {
+ // get the key and the value
+ wxString key = it->first;
+ const wxJSONValue& v = it->second;
+ bool comma = false;
+ if ( count < size - 1 ) {
+ comma = true;
+ }
+ lastChar = DoWrite( os, v, &key, comma );
+ if ( lastChar < 0 ) {
+ return lastChar;
+ }
+ count++;
}
- i++;
- }
- --m_level;
- lastChar = WriteIndent();
- if ( lastChar < 0 ) {
- return lastChar;
- }
- lastChar = WriteChar( '}' );
- break;
- }
-
- // when the value is written, check if we need a comma character
- // and if a comment inline / after must be written
- if ( comma ) {
- lastChar = WriteChar( ',' );
- if ( lastChar < 0 ) {
- return lastChar;
+ --m_level;
+ lastChar = WriteIndent( os );
+ if ( lastChar < 0 ) {
+ return lastChar;
+ }
+ os.PutC( '}' );
+ break;
+
+ default :
+ // a not yet defined wxJSONType: we FAIL
+ wxFAIL_MSG( _T("wxJSONWriter::DoWrite() undefined wxJSONType type"));
+ break;
}
- }
- if ( commentPos == wxJSONVALUE_COMMENT_INLINE ) {
- lastChar = WriteChar( ' ' );
- lastChar = WriteComment( value, false );
- if ( lastChar < 0 ) {
- return lastChar;
+
+ // writes the comma character before the inline comment
+ if ( comma ) {
+ os.PutC( ',' );
}
- }
- else if ( commentPos == wxJSONVALUE_COMMENT_AFTER ) {
- WriteChar( '\n' );
- lastChar = WriteComment( value, true );
- if ( lastChar < 0 ) {
- return lastChar;
+
+ if ( commentPos == wxJSONVALUE_COMMENT_INLINE ) {
+ lastChar = WriteComment( os, value, false );
+ if ( lastChar < 0 ) {
+ return lastChar;
+ }
}
- }
- if ( lastChar != '\n' ) {
- lastChar = WriteChar( '\n' );
- }
- return lastChar;
+ else if ( commentPos == wxJSONVALUE_COMMENT_AFTER ) {
+ WriteSeparator( os );
+ lastChar = WriteComment( os, value, true );
+ if ( lastChar < 0 ) {
+ return lastChar;
+ }
+ }
+ if ( lastChar != '\n' ) {
+ lastChar = WriteSeparator( os );
+ }
+ return lastChar;
}
//! Write the comment strings, if any.
int
-wxJSONWriter::WriteComment( const wxJSONValue& value, bool indent )
+wxJSONWriter::WriteComment( wxOutputStream& os, const wxJSONValue& value, bool indent )
{
- // the function returns the last character written which should be
- // a LF char or -1 in case of errors
- // if nothing is written, returns ZERO
- int lastChar = 0;
-
- // only write comments if the style is STYLED and the WRITE_COMMENTS flag
- // is set.
- if ( (m_style & wxJSONWRITER_STYLED ) == 0 ) {
- return lastChar;
- }
- if ( (m_style & wxJSONWRITER_WRITE_COMMENTS ) == 0 ) {
- return lastChar;
- }
+ // the function returns the last character written which should be
+ // a LF char or -1 in case of errors
+ // if nothing is written, returns ZERO
+ int lastChar = 0;
- const wxArrayString cmt = value.GetCommentArray();
- int cmtSize = cmt.GetCount();
- for ( int i = 0; i < cmtSize; i++ ) {
- if ( indent ) {
- lastChar = WriteIndent();
+ // only write comments if the style include the WRITE_COMMENTS flag
+ if ( (m_style & wxJSONWRITER_WRITE_COMMENTS ) == 0 ) {
+ return lastChar;
}
- WriteString( cmt[i]);
- lastChar = cmt[i].Last();
- if ( lastChar != '\n' ) {
- lastChar = WriteChar( '\n' );
+
+ const wxArrayString cmt = value.GetCommentArray();
+ int cmtSize = cmt.GetCount();
+ for ( int i = 0; i < cmtSize; i++ ) {
+ if ( indent ) {
+ WriteIndent( os );
+ }
+ else {
+ os.PutC( '\t' );
+ }
+ WriteString( os, cmt[i]);
+ lastChar = cmt[i].Last();
+ if ( lastChar != '\n' ) {
+ os.PutC( '\n' );
+ lastChar = '\n';
+ }
}
- }
- return lastChar;
+ return lastChar;
}
//! Writes the indentation to the JSON text.
@@ -479,42 +591,60 @@ wxJSONWriter::WriteComment( const wxJSONValue& value, bool indent )
writes the specified number of spaces.
If no parameter is given, the function computes the number of spaces
using the following formula:
- \code
- numSpaces = m_indent + ( m_step * m_level )
- \endcode
+ If the wxJSONWRITER_TAB_INDENT flag is used in the writer's cnstructor,
+ the function calls WriteTabIndent().
+
+ The function also checks that wxJSONWRITER_STYLED is set and the
+ wxJSONWRITER_NO_INDENTATION is not set.
*/
int
-wxJSONWriter::WriteIndent()
+wxJSONWriter::WriteIndent( wxOutputStream& os )
{
- int lastChar = 0;
- int numSpaces = m_indent + ( m_step * m_level );
- if ( m_style & wxJSONWRITER_STYLED ) {
- for ( int i = 0; i < numSpaces; i++ ) {
- lastChar = WriteChar( ' ' );
- if ( lastChar == -1 ) {
- break;
- }
- }
- }
- return lastChar;
+ int lastChar = WriteIndent( os, m_level );
+ return lastChar;
}
-//! \overload WriteIndentation()
+//! Write the specified number of indentation (spaces or tabs)
+/*!
+ The function is called by WriteIndent() and other writer's functions.
+ It writes the indentation as specified in the \c num parameter which is
+ the actual \b level of annidation.
+ The function checks if wxJSONWRITER_STYLED is set: if not, no indentation
+ is performed.
+ Also, the function checks if wxJSONWRITER_TAB_INDENT is set: if it is,
+ indentation is done by writing \b num TAB characters otherwise,
+ it is performed by writing a number of spaces computed as:
+ \code
+ numSpaces = m_indent + ( m_step * num )
+ \endcode
+
+*/
int
-wxJSONWriter::WriteIndent( int num )
+wxJSONWriter::WriteIndent( wxOutputStream& os, int num )
{
- int lastChar = 0;
- if ( m_style & wxJSONWRITER_STYLED ) {
- for ( int i = 0; i < num; i++ ) {
- lastChar = WriteChar( ' ' );
- if ( lastChar == -1 ) {
- break;
- }
+ int lastChar = 0;
+ if ( !(m_style & wxJSONWRITER_STYLED) || (m_style & wxJSONWRITER_NO_INDENTATION)) {
+ return lastChar;
+ }
+
+ int numChars = m_indent + ( m_step * num );
+ char c = ' ';
+ if ( m_style & wxJSONWRITER_TAB_INDENT ) {
+ c = '\t';
+ numChars = num;
+ }
+
+ for ( int i = 0; i < numChars; i++ ) {
+ os.PutC( c );
+ if ( os.GetLastError() != wxSTREAM_NO_ERROR ) {
+ return -1;
+ }
+
}
- }
- return lastChar;
+ return c;
}
+
//! Write the provided string to the output object.
/*!
The function writes the string \c str to the output object that
@@ -527,304 +657,425 @@ wxJSONWriter::WriteIndent( int num )
in the provided string the function calls WriteChar() which does
the actual character output.
- The function returns the last character written or -1 in case of errors.
+ The function returns ZERO on success or -1 in case of errors.
*/
int
-wxJSONWriter::WriteStringValue( const wxString& str )
+wxJSONWriter::WriteStringValue( wxOutputStream& os, const wxString& str )
{
- // the characters that have to be escaped
- static const wxChar escapedChars[] = {
- _T( '/' ), // solidus
- _T( '\"' ), // quotes
- _T( '\\' ), // reverse solidus
- _T( '\b' ), // backspace
- _T( '\f' ), // formfeed
- _T( '\r' ), // carriage-return
- _T( '\t' ), // horizontal tab
- _T( '\n' ), // newline (has to be last)
- };
- // 8 elements
-
- const wxString replaceChars[] = {
- _T("\\/"),
- _T("\\\""),
- _T("\\\\"),
- _T("\\b"),
- _T("\\f"),
- _T("\\r"),
- _T("\\t"),
- _T("\\n")
- };
-
- // flag that controls the output and indentation of multiline strings
- // it would be nice if the lines after the first one start at the same
- // column as, for example:
- //
- // "key" : "this is first line\n"
- // "this is line #2\n"
- // "this is line #3"
- //
- // but there is not a data member that stores the actual column number
- // so by now, the indentation is calculated by adding 2 levels to the
- // current level number so the output of the above example will be
- // (consider a indent step of 3 (the default):
- //
- // "key" : "this is first line\n"
- // "this is line #2\n"
- // "this is line #3"
- //
- int multiLineIndent = -1;
- if ( ( m_style & wxJSONWRITER_SPLIT_STRING) && ( m_style & wxJSONWRITER_STYLED) ) {
- multiLineIndent = ( m_level + 2 ) * m_step;
- }
-
- // solidus only has to be escaped when embedding in html
- const int escapedStart = (m_style & wxJSONWRITER_ESCAPE_SOLIDUS) ? 0 : 1;
-
- // multiline string flag allows literal newlines and tabs in strings
- const int escapedEnd = (m_style & wxJSONWRITER_MULTILINE_STRING) ? 6 : 8;
-
- int lastChar = WriteChar( '\"' ); // open quotes
- if ( lastChar < 0 ) {
- return lastChar;
- }
-
- // every character is written using the WriteChar() function
- size_t len = str.length();
- for ( size_t i = 0; i < len; i++ ) {
- wxChar ch = str.at(i ); bool replaced = false;
- for ( int l = escapedStart; l < escapedEnd; l++ ) {
- if ( ch == escapedChars[l] ) {
- lastChar = WriteString( replaceChars[l] );
- if ( lastChar < 0 ) {
- return lastChar;
- }
- replaced = true;
- break;
- }
+ // JSON values of type STRING are written by converting the whole string
+ // to UTF-8 and then copying the UTF-8 buffer to the 'os' stream
+ // one byte at a time and processing them
+ os.PutC( '\"' ); // open quotes
+
+ // the buffer that has to be written is either UTF-8 or ANSI c_str() depending
+ // on the 'm_noUtf8' flag
+ char* writeBuff = 0;
+ wxCharBuffer utf8CB = str.ToUTF8(); // the UTF-8 buffer
+#if !defined( wxJSON_USE_UNICODE )
+ wxCharBuffer ansiCB( str.c_str()); // the ANSI buffer
+ if ( m_noUtf8 ) {
+ writeBuff = ansiCB.data();
}
- if ( !replaced ) {
- lastChar = WriteChar( ch );
- if ( lastChar < 0 ) {
- return lastChar;
- }
+ else {
+ writeBuff = utf8CB.data();
}
- // check if the char is LF and if the style is SPLIT_STRING
- if ( ch == '\n' && multiLineIndent > 0 ) {
- lastChar = WriteString( _T("\"\n" )); // close quotes
- if ( lastChar < 0 ) {
- return lastChar;
- }
- lastChar = WriteIndent( multiLineIndent );
- if ( lastChar < 0 ) {
- return lastChar;
- }
- lastChar = WriteChar( '\"' ); // reopen quotes
- if ( lastChar < 0 ) {
- return lastChar;
- }
+#else
+ writeBuff = utf8CB.data();
+#endif
+
+ // NOTE: in ANSI builds UTF-8 conversion may fail (see samples/test5.cpp,
+ // test 7.3) although I do not know why
+ if ( writeBuff == 0 ) {
+ const char* err = "<wxJSONWriter::WriteStringValue(): error converting the string to a UTF8 buffer>";
+ os.Write( err, strlen( err ));
+ return 0;
}
- }
- lastChar = WriteChar( '\"' ); // close quotes
- return lastChar;
-}
+ size_t len = strlen( writeBuff );
+ int lastChar = 0;
+
+ // store the column at which the string starts
+ // splitting strings only happen if the string starts within
+ // column wxJSONWRITER_LAST_COL (default 50)
+ // see 'include/wx/json_defs.h' for the defines
+ int tempCol = m_colNo;
+
+ // now write the UTF8 buffer processing the bytes
+ size_t i;
+ for ( i = 0; i < len; i++ ) {
+ bool shouldEscape = false;
+ unsigned char ch = *writeBuff;
+ ++writeBuff; // point to the next byte
+
+ // the escaped character
+ char escCh = 0;
+
+ // for every character we have to check if it is a character that
+ // needs to be escaped: note that characters that should be escaped
+ // may be not if some writer's flags are specified
+ switch ( ch ) {
+ case '\"' : // quotes
+ shouldEscape = true;
+ escCh = '\"';
+ break;
+ case '\\' : // reverse solidus
+ shouldEscape = true;
+ escCh = '\\';
+ break;
+ case '/' : // solidus
+ shouldEscape = true;
+ escCh = '/';
+ break;
+ case '\b' : // backspace
+ shouldEscape = true;
+ escCh = 'b';
+ break;
+ case '\f' : // formfeed
+ shouldEscape = true;
+ escCh = 'f';
+ break;
+ case '\n' : // newline
+ shouldEscape = true;
+ escCh = 'n';
+ break;
+ case '\r' : // carriage-return
+ shouldEscape = true;
+ escCh = 'r';
+ break;
+ case '\t' : // horizontal tab
+ shouldEscape = true;
+ escCh = 't';
+ break;
+ default :
+ shouldEscape = false;
+ break;
+ } // end switch
+
+
+ // if the character is a control character that is not identified by a
+ // lowercase letter, we should escape it
+ if ( !shouldEscape && ch < 32 ) {
+ char b[8];
+ snprintf( b, 8, "\\u%04X", (int) ch );
+ os.Write( b, 6 );
+ if ( os.GetLastError() != wxSTREAM_NO_ERROR ) {
+ return -1;
+ }
+ }
-//! Write a character to the output object
-/*!
- This function does the real output of the JSON text to the output
- object which can be a wxString object or a wxOutputStream object.
- The function outputs only one character.
- What is actually written to the output JSON text depends on:
+ // the char is not a control character
+ else {
+ // some characters that should be escaped are not escaped
+ // if the writer was constructed with some flags
+ if ( shouldEscape && !( m_style & wxJSONWRITER_ESCAPE_SOLIDUS) ) {
+ if ( ch == '/' ) {
+ shouldEscape = false;
+ }
+ }
+ if ( shouldEscape && (m_style & wxJSONWRITER_MULTILINE_STRING)) {
+ if ( ch == '\n' || ch == '\t' ) {
+ shouldEscape = false;
+ }
+ }
+
+
+ // now write the character prepended by ESC if it should be escaped
+ if ( shouldEscape ) {
+ os.PutC( '\\' );
+ os.PutC( escCh );
+ if ( os.GetLastError() != wxSTREAM_NO_ERROR ) {
+ return -1;
+ }
+ }
+ else {
+ // a normal char or a UTF-8 units: write the character
+ os.PutC( ch );
+ if ( os.GetLastError() != wxSTREAM_NO_ERROR ) {
+ return -1;
+ }
+ }
+ }
- \li if the output is a string object, the function just appends
- to the string object pointed to by \c m_outObject the
- character that has to be written
+ // check if SPLIT_STRING flag is set and if the string has to
+ // be splitted
+ if ( (m_style & wxJSONWRITER_STYLED) && (m_style & wxJSONWRITER_SPLIT_STRING)) {
+ // split the string if the character written is LF
+ if ( ch == '\n' ) {
+ // close quotes and CR
+ os.Write( "\"\n", 2 );
+ lastChar = WriteIndent( os, m_level + 2 ); // write indentation
+ os.PutC( '\"' ); // reopen quotes
+ if ( lastChar < 0 ) {
+ return lastChar;
+ }
+ }
+ // split the string only if there is at least wxJSONWRITER_MIN_LENGTH
+ // character to write and the character written is a punctuation or space
+ // BUG: the following does not work because the columns are not counted
+ else if ( (m_colNo >= wxJSONWRITER_SPLIT_COL)
+ && (tempCol <= wxJSONWRITER_LAST_COL )) {
+ if ( IsSpace( ch ) || IsPunctuation( ch )) {
+ if ( len - i > wxJSONWRITER_MIN_LENGTH ) {
+ // close quotes and CR
+ os.Write( "\"\n", 2 );
+ lastChar = WriteIndent( os, m_level + 2 ); // write indentation
+ os.PutC( '\"' ); // reopen quotes
+ if ( lastChar < 0 ) {
+ return lastChar;
+ }
+ }
+ }
+ }
+ }
+ } // end for
+ os.PutC( '\"' ); // close quotes
+ return 0;
+}
- \li if the output is a stream object than we have to distinguish
- if the library has built in ANSI or Unicode mode:
- \li in ANSI builds, the character is converted to a wide
- character and then to UTF-8 encoding format
- \li in Unicode builds, the wide character is converted to
- UTF-8 format
- The function returns the written character ('ch' itself) or -1 in case
- of errors.
+//! Write a generic string
+/*!
+ The function writes the wxString object \c str to the output object.
+ The string is written as is; you cannot use it to write JSON strings
+ to the output text.
+ The function converts the string \c str to UTF-8 and writes the buffer..
*/
int
-wxJSONWriter::WriteChar( wxChar ch )
+wxJSONWriter::WriteString( wxOutputStream& os, const wxString& str )
{
- // we have to set the result 'r' equal to the returned char
- // but ANSI and Unicode are different - see the Test60() function
- // in 'samples/test13.cpp' source file.
-#if defined( wxJSON_USE_UNICODE )
- int r = ch;
-#else
- int r = (unsigned char) ch;
-#endif
- if ( m_outType == 0 ) { // output is a string object?
- //wxString* out = wxDynamicCast( m_outObject, wxString );
- //wxASSERT( out != 0 );
- wxString* out = (wxString*) m_outObject;
- out->append( ch );
- }
- else { // output is a stream
- //wxOutputStream* out = wxDynamicCast( m_outObject, wxOutputStream );
- //wxASSERT( out != 0 );
- wxOutputStream* out = (wxOutputStream*) m_outObject;
- wchar_t wchar[2]; size_t len;
-
+ wxLogTrace( writerTraceMask, _T("(%s) string to write=%s"),
+ __PRETTY_FUNCTION__, str.c_str() );
+ int lastChar = 0;
+ char* writeBuff = 0;
+
+ // the buffer that has to be written is either UTF-8 or ANSI c_str() depending
+ // on the 'm_noUtf8' flag
+ wxCharBuffer utf8CB = str.ToUTF8(); // the UTF-8 buffer
#if !defined( wxJSON_USE_UNICODE )
- // in ANSI builds we have to first convert the locale dependent
- // character to a wide char
- char c = (char) ch;
- len = wxConvLibc.ToWChar( wchar, 2, &c, 1 );
+ wxCharBuffer ansiCB( str.c_str()); // the ANSI buffer
+
+ if ( m_noUtf8 ) {
+ writeBuff = ansiCB.data();
+ }
+ else {
+ writeBuff = utf8CB.data();
+ }
#else
- wchar[0] = ch;
+ writeBuff = utf8CB.data();
#endif
- // writing to a stream is always done in UTF-8 format
- // the m_conv data member must contain a pointer to an instance
- // of a wxMBConvUTF8 class which is, by default, wxConvLocal
-
- char buffer[10];
- wxASSERT( m_conv != 0 );
- len = m_conv->FromWChar( buffer, 10, &(wchar[0]), 1 );
- wxASSERT( len != wxCONV_FAILED );
-
- // conversion is OK, write the buffer
- // it seems that the conversion function adds a trailing NULL byte
- // to the output buffer so we have to decrement the converted lenght by 1
- // see the Test37() function in 'samples/test9.cpp' for details
-
- ::wxLogTrace( writerTraceMask, _T("(%s) length=%d"), __PRETTY_FUNCTION__, (int) len );
- if ( len <= 1 ) {
- ::wxLogTrace( writerTraceMask,
- _T("(%s) length less than or equal to 1"), __PRETTY_FUNCTION__ );
+ // NOTE: in ANSI builds UTF-8 conversion may fail (see samples/test5.cpp,
+ // test 7.3) although I do not know why
+ if ( writeBuff == 0 ) {
+ const char* err = "<wxJSONWriter::WriteComment(): error converting the string to UTF-8>";
+ os.Write( err, strlen( err ));
+ return 0;
}
+ size_t len = strlen( writeBuff );
- wxASSERT( len > 1 );
- out->Write( buffer, len - 1 );
- wxStreamError err = out->GetLastError();
- switch ( err ) {
- case wxSTREAM_NO_ERROR :
- break;
- case wxSTREAM_EOF :
- r = -1;
- break;
- case wxSTREAM_WRITE_ERROR :
- case wxSTREAM_READ_ERROR :
- r = -1;
- break;
- default : // should never happen
- break;
+ os.Write( writeBuff, len );
+ if ( os.GetLastError() != wxSTREAM_NO_ERROR ) {
+ return -1;
}
- }
- return r;
-}
-//! Write a generic string
-/*!
- The function writes the wxString object \c str to the output object.
- The string is written as is; you cannot use it to write JSON strings
- to the output text.
- The function is used by many other functions for example by WriteInt()
- which converts the integer in a string and then writes it to the
- output JSON text.
- The function just calls WriteChar() for every character in the string.
-*/
-int
-wxJSONWriter::WriteString( const wxString& str )
-{
- int lastChar = 0;
- size_t len = str.length();
- for ( size_t i = 0; i < len; i++ ) {
- lastChar = WriteChar( str[i] );
- if ( lastChar < 0 ) {
- break;
- }
- }
- return lastChar;
+ wxLogTrace( writerTraceMask, _T("(%s) result=%d"),
+ __PRETTY_FUNCTION__, lastChar );
+ return lastChar;
}
-//! Writes a value of primitive type.
+//! Write the NULL JSON value to the output stream.
/*!
- This function is called for every value object of primite types
- except string values and it relaces all \c WriteXxxxx() functions.
- In order to write primitive types, this functions calls the
- wxJSONValue::AsString() function to get a string representation
- of the value.
+ The function writes the \b null literal string to the output stream.
*/
int
-wxJSONWriter::WritePrimitiveValue( const wxJSONValue& value )
+wxJSONWriter::WriteNullValue( wxOutputStream& os )
{
- int r;
- wxString s = value.AsString();
- wxASSERT( !s.empty());
- r = WriteString( s );
- return r;
+ os.Write( "null", 4 );
+ if ( os.GetLastError() != wxSTREAM_NO_ERROR ) {
+ return -1;
+ }
+ return 0;
}
-
-//! Write the provided integer to the output stream.
+//! Writes a value of type INT.
+/*!
+ This function is called for every value objects of INT type.
+ This function uses the \n snprintf function to get the US-ASCII
+ representation of the integer and simply copy it to the output stream.
+ Returns -1 on stream errors or ZERO if no errors.
+*/
int
-wxJSONWriter::WriteInt( int i )
+wxJSONWriter::WriteIntValue( wxOutputStream& os, const wxJSONValue& value )
{
- wxString s;
- s = wxString::Format( _T( "%d"), i);
- return WriteString( s );
+ int r = 0;
+ char buffer[32]; // need to store 64-bits integers (max 20 digits)
+ size_t len;
+
+ wxJSONRefData* data = value.GetRefData();
+ wxASSERT( data );
+
+#if defined( wxJSON_64BIT_INT )
+ #if wxCHECK_VERSION(2, 9, 0 ) || !defined( wxJSON_USE_UNICODE )
+ // this is fine for wxW 2.9 and for wxW 2.8 ANSI
+ snprintf( buffer, 32, "%" wxLongLongFmtSpec "d",
+ data->m_value.m_valInt64 );
+ #else
+ // this is for wxW 2.8 Unicode: in order to use the cross-platform
+ // format specifier, we use the wxString's sprintf() function and then
+ // convert to UTF-8 before writing to the stream
+ wxString s;
+ s.Printf( _T("%") wxLongLongFmtSpec _T("d"),
+ data->m_value.m_valInt64 );
+ wxCharBuffer cb = s.ToUTF8();
+ const char* cbData = cb.data();
+ len = strlen( cbData );
+ wxASSERT( len < 32 );
+ memcpy( buffer, cbData, len );
+ buffer[len] = 0;
+ #endif
+#else
+ snprintf( buffer, 32, "%ld", data->m_value.m_valLong );
+#endif
+ len = strlen( buffer );
+ os.Write( buffer, len );
+ if