From a73f83183c82d29b69c821c0ef0214aef22271bc Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sat, 5 Jul 2014 16:21:47 +0200 Subject: [PATCH 01/13] ignore generated Doxygen documentation --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2dbbadb..d53ea43 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,6 @@ /build/*.exe /build/gmake /build/vs*/ +/doc/html /thirdparty/lib /intermediate From 252e282dc69153a662c4ef54016de69c45f37ceb Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sat, 5 Jul 2014 17:16:50 +0200 Subject: [PATCH 02/13] Doxyfile: prepare for Markdown rendering --- build/Doxyfile | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/build/Doxyfile b/build/Doxyfile index 6e60e58..a54bd8e 100644 --- a/build/Doxyfile +++ b/build/Doxyfile @@ -52,7 +52,7 @@ PROJECT_LOGO = # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. -OUTPUT_DIRECTORY = ../doc +OUTPUT_DIRECTORY = ./doc # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output @@ -514,7 +514,7 @@ GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. -ENABLED_SECTIONS = +ENABLED_SECTIONS = $(RAPIDJSON_SECTIONS) # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in @@ -548,7 +548,7 @@ SHOW_FILES = YES # Namespaces page. This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. -SHOW_NAMESPACES = YES +SHOW_NAMESPACES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from @@ -638,7 +638,9 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../include/ +INPUT = ./include/ \ + ./readme.md \ + ./doc/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -660,34 +662,12 @@ FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ - *.c++ \ - *.d \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ - *.h++ \ - *.idl \ - *.odl \ - *.cs \ - *.php \ - *.php3 \ *.inc \ - *.m \ - *.mm \ - *.dox \ - *.py \ - *.f90 \ - *.f \ - *.for \ - *.vhd \ - *.vhdl + *.md # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. @@ -748,7 +728,7 @@ EXAMPLE_RECURSIVE = NO # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = +IMAGE_PATH = ./doc # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -1479,13 +1459,13 @@ ENABLE_PREPROCESSING = YES # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. -MACRO_EXPANSION = NO +MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. -EXPAND_ONLY_PREDEF = NO +EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. From 5174fe4f652f4d31961d309ff864ebbdb4abd5b3 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sat, 5 Jul 2014 17:09:35 +0200 Subject: [PATCH 03/13] rapidjson.h: add some file-level doxygen documentation Although not yet complete, the rapidjson.h header contains most of the customisation macro definitions. These should be documented via Doxygen as well. This requires adding file-level documentation. Some parts are excluded via `@cond` to avoid cluttering the documentation with internals too much. Secondly, a brief description is added to the 'rapidjson' namespace to include the namespace-level elements (enums, typedefs, functions) to the generated documentation. --- include/rapidjson/rapidjson.h | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index a6d5c06..c73efa5 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -4,6 +4,12 @@ // Copyright (c) 2011 Milo Yip (miloyip@gmail.com) // Version 0.1 +/*!\file rapidjson.h + \brief common definitions and configuration + + \todo Complete Doxygen documentation for configure macros. + */ + #include // malloc(), realloc(), free() #include // memcpy() @@ -14,6 +20,7 @@ // (U)INT64_C constant macros. // If user have their own definition, can define RAPIDJSON_NO_INT64DEFINE to disable this. #ifndef RAPIDJSON_NO_INT64DEFINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN #ifndef __STDC_CONSTANT_MACROS # define __STDC_CONSTANT_MACROS 1 // required by C++ standard #endif @@ -25,6 +32,7 @@ #include #include #endif +//!@endcond #endif // RAPIDJSON_NO_INT64TYPEDEF /////////////////////////////////////////////////////////////////////////////// @@ -46,7 +54,7 @@ //! Endianness of the machine. /*! GCC provided macro for detecting endianness of the target machine. But other compilers may not have this. User can define RAPIDJSON_ENDIAN to either - RAPIDJSON_LITTLEENDIAN or RAPIDJSON_BIGENDIAN. + \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN. */ #ifndef RAPIDJSON_ENDIAN #ifdef __BYTE_ORDER__ @@ -115,7 +123,9 @@ typedef unsigned SizeType; // Adopt from boost #ifndef RAPIDJSON_STATIC_ASSERT +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN namespace rapidjson { + template struct STATIC_ASSERTION_FAILURE; template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; template struct StaticAssertTest {}; @@ -130,7 +140,13 @@ template struct StaticAssertTest {}; #else #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE #endif +//!@endcond +/*! \def RAPIDJSON_STATIC_ASSERT + \brief (internal) macro to check for conditions at compile-time + \param x compile-time condition + \hideinitializer + */ #define RAPIDJSON_STATIC_ASSERT(x) typedef ::rapidjson::StaticAssertTest<\ sizeof(::rapidjson::STATIC_ASSERTION_FAILURE)>\ RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE @@ -139,9 +155,11 @@ template struct StaticAssertTest {}; /////////////////////////////////////////////////////////////////////////////// // Helpers +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN #define RAPIDJSON_MULTILINEMACRO_BEGIN do { #define RAPIDJSON_MULTILINEMACRO_END \ } while((void)0, 0) +//!@endcond /////////////////////////////////////////////////////////////////////////////// // Allocators and Encodings @@ -149,6 +167,7 @@ template struct StaticAssertTest {}; #include "allocators.h" #include "encodings.h" +//! main RapidJSON namespace namespace rapidjson { /////////////////////////////////////////////////////////////////////////////// From c63c40fa857fa6422db1d450890c67832cefbed2 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sat, 5 Jul 2014 17:03:54 +0200 Subject: [PATCH 04/13] GenericMemberIterator::Type -> GenericMemberIterator::Iterator Rename nested typedef to avoid confusion with JSON Type enum. --- include/rapidjson/document.h | 40 ++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index bc2d836..faf3909 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -73,7 +73,7 @@ class GenericMemberIterator public: //! Iterator type itself - typedef GenericMemberIterator Type; + typedef GenericMemberIterator Iterator; //! Constant iterator type typedef GenericMemberIterator ConstType; //! Non-constant iterator type @@ -112,29 +112,29 @@ public: //! @name stepping //@{ - Type& operator++(){ ++ptr_; return *this; } - Type& operator--(){ --ptr_; return *this; } - Type operator++(int){ Type old(*this); ++ptr_; return old; } - Type operator--(int){ Type old(*this); --ptr_; return old; } + Iterator& operator++(){ ++ptr_; return *this; } + Iterator& operator--(){ --ptr_; return *this; } + Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } + Iterator operator--(int){ Iterator old(*this); --ptr_; return old; } //@} //! @name increment/decrement //@{ - Type operator+(DifferenceType n) const { return Type(ptr_+n); } - Type operator-(DifferenceType n) const { return Type(ptr_-n); } + Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); } + Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); } - Type& operator+=(DifferenceType n) { ptr_+=n; return *this; } - Type& operator-=(DifferenceType n) { ptr_-=n; return *this; } + Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; } + Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; } //@} //! @name relations //@{ - bool operator==(Type that) const { return ptr_ == that.ptr_; } - bool operator!=(Type that) const { return ptr_ != that.ptr_; } - bool operator<=(Type that) const { return ptr_ <= that.ptr_; } - bool operator>=(Type that) const { return ptr_ >= that.ptr_; } - bool operator< (Type that) const { return ptr_ < that.ptr_; } - bool operator> (Type that) const { return ptr_ > that.ptr_; } + bool operator==(Iterator that) const { return ptr_ == that.ptr_; } + bool operator!=(Iterator that) const { return ptr_ != that.ptr_; } + bool operator<=(Iterator that) const { return ptr_ <= that.ptr_; } + bool operator>=(Iterator that) const { return ptr_ >= that.ptr_; } + bool operator< (Iterator that) const { return ptr_ < that.ptr_; } + bool operator> (Iterator that) const { return ptr_ > that.ptr_; } //@} //! @name dereference @@ -145,7 +145,7 @@ public: //@} //! Distance - DifferenceType operator-(Type that) const { return ptr_-that.ptr_; } + DifferenceType operator-(Iterator that) const { return ptr_-that.ptr_; } private: //! Internal constructor from plain pointer @@ -165,13 +165,13 @@ struct GenericMemberIterator; template struct GenericMemberIterator { //! use plain pointer as iterator type - typedef GenericMember* Type; + typedef GenericMember* Iterator; }; //! const GenericMemberIterator template struct GenericMemberIterator { //! use plain const pointer as iterator type - typedef const GenericMember* Type; + typedef const GenericMember* Iterator; }; #endif // RAPIDJSON_NOMEMBERITERATORCLASS @@ -198,8 +198,8 @@ public: typedef Encoding EncodingType; //!< Encoding type from template parameter. typedef Allocator AllocatorType; //!< Allocator type from template parameter. typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. - typedef typename GenericMemberIterator::Type MemberIterator; //!< Member iterator for iterating in object. - typedef typename GenericMemberIterator::Type ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef typename GenericMemberIterator::Iterator MemberIterator; //!< Member iterator for iterating in object. + typedef typename GenericMemberIterator::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. From 6ed0ac174f9750c6829b770f60520f639a3b629e Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sat, 5 Jul 2014 17:04:59 +0200 Subject: [PATCH 05/13] GenericDocument: improve Doxygen documentation --- include/rapidjson/document.h | 66 +++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index faf3909..3fd98b8 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -937,7 +937,7 @@ private: }; #pragma pack (pop) -//! Value with UTF8 encoding. +//! GenericValue with UTF8 encoding typedef GenericValue > Value; /////////////////////////////////////////////////////////////////////////////// @@ -948,6 +948,7 @@ typedef GenericValue > Value; \note implements Handler concept \tparam Encoding encoding for both parsing and string storage. \tparam Allocator allocator for allocating memory for the DOM, and the stack during parsing. + \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructors. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue. */ template > class GenericDocument : public GenericValue { @@ -962,8 +963,13 @@ public: */ GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseErrorCode_(kParseErrorNone), errorOffset_(0) {} - //! Parse JSON text from an input stream. - /*! \tparam parseFlags Combination of ParseFlag. + //!@name Parse from stream + //!@{ + + //! Parse JSON text from an input stream (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam SourceEncoding Encoding of input stream + \tparam InputStream Type of input stream, implementing Stream concept \param is Input stream to be parsed. \return The document itself for fluent API. */ @@ -985,18 +991,34 @@ public: return *this; } + //! Parse JSON text from an input stream + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ template GenericDocument& ParseStream(InputStream& is) { return ParseStream(is); } + //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ template GenericDocument& ParseStream(InputStream& is) { return ParseStream(is); } + //!@} - //! Parse JSON text from a mutable string. - /*! \tparam parseFlags Combination of ParseFlag. + //!@name Parse in-place from mutable string + //!@{ + + //! Parse JSON text from a mutable string (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam SourceEncoding Transcoding from input Encoding \param str Mutable zero-terminated string to be parsed. \return The document itself for fluent API. */ @@ -1006,17 +1028,31 @@ public: return ParseStream(s); } + //! Parse JSON text from a mutable string + /*! \tparam parseFlags Combination of \ref ParseFlag. + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ template GenericDocument& ParseInsitu(Ch* str) { return ParseInsitu(str); } + //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) + /*! \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ GenericDocument& ParseInsitu(Ch* str) { return ParseInsitu(str); } + //!@} - //! Parse JSON text from a read-only string. - /*! \tparam parseFlags Combination of ParseFlag (must not contain kParseInsituFlag). + //!@name Parse from read-only string + //!@{ + + //! Parse JSON text from a read-only string (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \tparam SourceEncoding Transcoding from input Encoding \param str Read-only zero-terminated string to be parsed. */ template @@ -1026,14 +1062,25 @@ public: return ParseStream(s); } + //! Parse JSON text from a read-only string + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \param str Read-only zero-terminated string to be parsed. + */ template GenericDocument& Parse(const Ch* str) { return Parse(str); } + //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) + /*! \param str Read-only zero-terminated string to be parsed. + */ GenericDocument& Parse(const Ch* str) { return Parse(str); } + //!@} + + //!@name Handling parse errors + //!@{ //! Whether a parse error was occured in the last parsing. bool HasParseError() const { return parseErrorCode_ != kParseErrorNone; } @@ -1044,6 +1091,8 @@ public: //! Get the offset in character of the parsing error. size_t GetErrorOffset() const { return errorOffset_; } + //!@} + //! Get the allocator of this document. Allocator& GetAllocator() { return stack_.GetAllocator(); } @@ -1086,7 +1135,7 @@ private: } private: - // Prohibit assignment + //! Prohibit assignment GenericDocument& operator=(const GenericDocument&); void ClearStack() { @@ -1103,6 +1152,7 @@ private: size_t errorOffset_; }; +//! GenericDocument with UTF8 encoding typedef GenericDocument > Document; // defined here due to the dependency on GenericDocument From 7972f22fcb2b10f23ff95c45269dd812a294a082 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sat, 5 Jul 2014 17:05:48 +0200 Subject: [PATCH 06/13] Doxygen: document some UTF-8 typedefs --- include/rapidjson/rapidjson.h | 2 ++ include/rapidjson/stringbuffer.h | 1 + 2 files changed, 3 insertions(+) diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index c73efa5..bd500bc 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -265,6 +265,7 @@ struct StreamTraits > { enum { copyOptimization = 1 }; }; +//! String stream with UTF8 encoding. typedef GenericStringStream > StringStream; /////////////////////////////////////////////////////////////////////////////// @@ -301,6 +302,7 @@ struct StreamTraits > { enum { copyOptimization = 1 }; }; +//! Insitu string stream with UTF8 encoding. typedef GenericInsituStringStream > InsituStringStream; /////////////////////////////////////////////////////////////////////////////// diff --git a/include/rapidjson/stringbuffer.h b/include/rapidjson/stringbuffer.h index fd7aab8..162e5f1 100644 --- a/include/rapidjson/stringbuffer.h +++ b/include/rapidjson/stringbuffer.h @@ -37,6 +37,7 @@ struct GenericStringBuffer { mutable internal::Stack stack_; }; +//! String buffer with UTF8 encoding typedef GenericStringBuffer > StringBuffer; //! Implement specialized version of PutN() with memset() for better performance. From ec8f26e6e5256e6c8c10289e244e40586b1d48fc Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sat, 5 Jul 2014 17:06:44 +0200 Subject: [PATCH 07/13] (Pretty)Writer: improve doxygen documentation --- include/rapidjson/prettywriter.h | 23 +++++++++------ include/rapidjson/writer.h | 48 +++++++++++++++++++++----------- 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/include/rapidjson/prettywriter.h b/include/rapidjson/prettywriter.h index cbbcdab..5d04433 100644 --- a/include/rapidjson/prettywriter.h +++ b/include/rapidjson/prettywriter.h @@ -24,9 +24,9 @@ public: typedef typename Base::Ch Ch; //! Constructor - /*! \param os Output os. + /*! \param os Output stream. \param allocator User supplied allocator. If it is null, it will create a private one. - \param levelDepth Initial capacity of + \param levelDepth Initial capacity of stack. */ PrettyWriter(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} @@ -46,7 +46,9 @@ public: return *this; } - //@name Implementation of Handler. + /*! @name Implementation of Handler + \see Handler + */ //@{ PrettyWriter& Null() { PrettyPrefix(kNullType); Base::WriteNull(); return *this; } @@ -56,11 +58,6 @@ public: PrettyWriter& Int64(int64_t i64) { PrettyPrefix(kNumberType); Base::WriteInt64(i64); return *this; } PrettyWriter& Uint64(uint64_t u64) { PrettyPrefix(kNumberType); Base::WriteUint64(u64); return *this; } PrettyWriter& Double(double d) { PrettyPrefix(kNumberType); Base::WriteDouble(d); return *this; } - //! Overridden for fluent API, see \ref Writer::Double() - PrettyWriter& Double(double d, int precision) { - int oldPrecision = Base::GetDoublePrecision(); - return SetDoublePrecision(precision).Double(d).SetDoublePrecision(oldPrecision); - } PrettyWriter& String(const Ch* str, SizeType length, bool copy = false) { (void)copy; @@ -117,9 +114,19 @@ public: //@} + /*! @name Convenience extensions */ + //@{ + //! Simpler but slower overload. PrettyWriter& String(const Ch* str) { return String(str, internal::StrLen(str)); } + //! Overridden for fluent API, see \ref Writer::Double() + PrettyWriter& Double(double d, int precision) { + int oldPrecision = Base::GetDoublePrecision(); + return SetDoublePrecision(precision).Double(d).SetDoublePrecision(oldPrecision); + } + + //@} protected: void PrettyPrefix(Type type) { (void)type; diff --git a/include/rapidjson/writer.h b/include/rapidjson/writer.h index 95c550c..979b781 100644 --- a/include/rapidjson/writer.h +++ b/include/rapidjson/writer.h @@ -25,8 +25,9 @@ namespace rapidjson { for example Reader::Parse() and Document::Accept(). \tparam OutputStream Type of output stream. - \tparam SourceEncoding Encoding of both source strings. - \tparam TargetEncoding Encoding of and output stream. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam Allocator Type of allocator for allocating memory of stack. \note implements Handler concept */ template, typename TargetEncoding = UTF8<>, typename Allocator = MemoryPoolAllocator<> > @@ -34,6 +35,11 @@ class Writer { public: typedef typename SourceEncoding::Ch Ch; + //! Constructor + /*! \param os Output stream. + \param allocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ Writer(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : os_(os), level_stack_(allocator, levelDepth * sizeof(Level)), doublePrecision_(kDefaultDoublePrecision) {} @@ -53,8 +59,11 @@ public: //! \see SetDoublePrecision() int GetDoublePrecision() const { return doublePrecision_; } - //@name Implementation of Handler + /*!@name Implementation of Handler + \see Handler + */ //@{ + Writer& Null() { Prefix(kNullType); WriteNull(); return *this; } Writer& Bool(bool b) { Prefix(b ? kTrueType : kFalseType); WriteBool(b); return *this; } Writer& Int(int i) { Prefix(kNumberType); WriteInt(i); return *this; } @@ -75,20 +84,6 @@ public: */ Writer& Double(double d) { Prefix(kNumberType); WriteDouble(d); return *this; } - //! Writes the given \c double value to the stream (explicit precision) - /*! - The currently set double precision is ignored in favor of the explicitly - given precision for this value. - \see Double(), SetDoublePrecision(), GetDoublePrecision() - \param d The value to be written - \param precision The number of significant digits for this value - \return The Writer itself for fluent API. - */ - Writer& Double(double d, int precision) { - int oldPrecision = GetDoublePrecision(); - return SetDoublePrecision(precision).Double(d).SetDoublePrecision(oldPrecision); - } - Writer& String(const Ch* str, SizeType length, bool copy = false) { (void)copy; Prefix(kStringType); @@ -133,9 +128,28 @@ public: } //@} + /*! @name Convenience extensions */ + //@{ + + //! Writes the given \c double value to the stream (explicit precision) + /*! + The currently set double precision is ignored in favor of the explicitly + given precision for this value. + \see Double(), SetDoublePrecision(), GetDoublePrecision() + \param d The value to be written + \param precision The number of significant digits for this value + \return The Writer itself for fluent API. + */ + Writer& Double(double d, int precision) { + int oldPrecision = GetDoublePrecision(); + return SetDoublePrecision(precision).Double(d).SetDoublePrecision(oldPrecision); + } + //! Simpler but slower overload. Writer& String(const Ch* str) { return String(str, internal::StrLen(str)); } + //@} + protected: //! Information for each nested level struct Level { From 53b27ac8baab4dbd441409bd6794a6ea34378d96 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sat, 5 Jul 2014 17:07:13 +0200 Subject: [PATCH 08/13] GenericReader: improve doxygen documentation --- include/rapidjson/reader.h | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index dac1537..59d03b6 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -43,6 +43,8 @@ namespace rapidjson { // ParseFlag //! Combination of parseFlags +/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream + */ enum ParseFlag { kParseDefaultFlags = 0, //!< Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer. kParseInsituFlag = 1, //!< In-situ(destructive) parsing. @@ -257,7 +259,7 @@ template<> inline void SkipWhitespace(StringStream& is) { /////////////////////////////////////////////////////////////////////////////// // GenericReader -//! SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator. +//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator. /*! GenericReader parses JSON text from a stream, and send events synchronously to an object implementing Handler concept. @@ -276,7 +278,7 @@ template<> inline void SkipWhitespace(StringStream& is) { template > class GenericReader { public: - typedef typename SourceEncoding::Ch Ch; + typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type //! Constructor. /*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) @@ -285,12 +287,12 @@ public: GenericReader(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseErrorCode_(kParseErrorNone), errorOffset_(0) {} //! Parse JSON text. - /*! \tparam parseFlags Combination of ParseFlag. - \tparam InputStream Type of input stream. - \tparam Handler Type of handler which must implement Handler concept. - \param is Input stream to be parsed. - \param handler The handler to receive events. - \return Whether the parsing is successful. + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. */ template bool Parse(InputStream& is, Handler& handler) { @@ -321,6 +323,13 @@ public: return !HasParseError(); } + //! Parse JSON text (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ template bool Parse(InputStream& is, Handler& handler) { return Parse(is, handler); From b30c3c0538bee19fa6364caf8352399179ce99a6 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sat, 5 Jul 2014 17:10:43 +0200 Subject: [PATCH 09/13] readme.md: prepare Markdown for GitHub and Doxygen rendering --- readme.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/readme.md b/readme.md index 6c1fa80..98a51eb 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# RapidJSON +# RapidJSON {#mainpage} Copyright (c) 2011-2014 Milo Yip (miloyip@gmail.com) @@ -37,7 +37,7 @@ Users can build and run the unit tests on their platform/compiler. ## Installation -RapidJSON is a header-only C++ library. Just copy the `rapidjson/include/rapidjson` folder to system or project's include path. +RapidJSON is a header-only C++ library. Just copy the `include/rapidjson` folder to system or project's include path. To build the tests and examples: @@ -45,15 +45,21 @@ To build the tests and examples: 2. Copy premake4 executable to RapidJSON/build (or system path) 3. Run `rapidjson/build/premake.bat` on Windows, `RapidJSON/build/premake.sh` on Linux or other platforms 4. On Windows, build the solution at `rapidjson/build/vs2008/` or `/vs2010/` -5. On other platforms, run GNU make at `rapidjson/build/gmake/` (e.g., `make -f test.make config=release32`, `make -f example.make config=debug32`) +5. On other platforms, run GNU make at `rapidjson/build/gmake/` (e.g., `make -f test.make config=release32`; `make -f example.make config=debug32`) 6. On success, the executable are generated at `rapidjson/bin` +To build the [Doxygen](http://doxygen.org) documentation: + +1. Obtain and install [Doxygen](http://doxygen.org/download.html). +2. In the top-level directory, run `doxygen build/Doxyfile`. +3. Browse the generated documentation in `doc/html`. + ## Usage at a glance This simple example parses a JSON string into a document (DOM), make a simple modification of the DOM, and finally stringify the DOM to a JSON string. [simpledom.cpp](example/simpledom/simpledom.cpp) -```cpp +~~~~~~~~~~cpp #include "rapidjson/document.h" #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h" @@ -80,12 +86,12 @@ int main() { std::cout << buffer.GetString() << std::endl; return 0; } -``` +~~~~~~~~~~ Note that this example did not handle potential errors. The following diagram shows the process. -![simpledom](doc/diagram/simpledom.png?raw=true) +![simpledom](doc/diagram/simpledom.png) More [examples](example/) are available. From 2a57d97f632865b3973f9ac07e49e74be3f4b95f Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sat, 5 Jul 2014 17:11:15 +0200 Subject: [PATCH 10/13] features.md: prepare Markdown for GitHub and Doxygen rendering --- doc/features.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/features.md b/doc/features.md index f5d9355..3cc6309 100644 --- a/doc/features.md +++ b/doc/features.md @@ -39,10 +39,10 @@ ## API styles * SAX (Simple API for XML) style API - * Similar to [SAX](http://en.wikipedia.org/wiki/Simple_API_for_XML), RapidJSON provides a event sequential access parser API (`GenericReader`). It also provides a generator API (`GenericWriter`) which consumes the same set of events. + * Similar to [SAX](http://en.wikipedia.org/wiki/Simple_API_for_XML), RapidJSON provides a event sequential access parser API (`rapidjson::GenericReader`). It also provides a generator API (`rapidjson::Writer`) which consumes the same set of events. * DOM (Document Object Model) style API - * Similar to [DOM](http://en.wikipedia.org/wiki/Document_Object_Model) for HTML/XML, RapidJSON can parse JSON into a DOM representation (`GenericDocument`), for easy manipulation, and finally stringify back to JSON if needed. - * The DOM style API (`GenericDocument`) is actually implemented with SAX style API (`GenericReader`). SAX is faster but sometimes DOM is easier. Users can pick their choices according to scenarios. + * Similar to [DOM](http://en.wikipedia.org/wiki/Document_Object_Model) for HTML/XML, RapidJSON can parse JSON into a DOM representation (`rapidjson::GenericDocument`), for easy manipulation, and finally stringify back to JSON if needed. + * The DOM style API (`rapidjson::GenericDocument`) is actually implemented with SAX style API (`rapidjson::GenericReader`). SAX is faster but sometimes DOM is easier. Users can pick their choices according to scenarios. ## DOM (Document) @@ -59,13 +59,13 @@ ## SAX (Writer) -* Support PrettyWriter for adding newlines and indentations. +* Support `rapidjson::PrettyWriter` for adding newlines and indentations. * Support custom precision for floating point values. ## Stream -* Support `GenericStringBuffer` for storing the output JSON as string. -* Support `FileReadStream`/`FileWriteStream` for input/output `FILE` object. +* Support `rapidjson::GenericStringBuffer` for storing the output JSON as string. +* Support `rapidjson::FileReadStream`/`rapidjson::FileWriteStream` for input/output `FILE` object. * Support custom streams. ## Memory From ba05cc137750f138cb40ffd7479c2f9cc98a5fdd Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sat, 5 Jul 2014 17:14:32 +0200 Subject: [PATCH 11/13] tutorial.md: prepare Markdown for GitHub and Doxygen rendering --- doc/tutorial.md | 136 ++++++++++++++++++++++++------------------------ 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index eb6a150..804cc6a 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -13,7 +13,7 @@ Each JSON value is stored in a type called `Value`. A `Document`, representing t In this section, we will use excerpt of [`example/tutorial/tutorial.cpp`](../example/tutorial/tutorial.cpp). Assumes we have a JSON text stored in a C string (`const char* json`): -```js +~~~~~~~~~~js { "hello": "world", "t": true , @@ -23,10 +23,10 @@ Assumes we have a JSON text stored in a C string (`const char* json`): "pi": 3.1416, "a": [1, 2, 3, 4] } -``` +~~~~~~~~~~ Parse it into a `Document` -```cpp +~~~~~~~~~~cpp #include "rapidjson/document.h" using namespace rapidjson; @@ -34,50 +34,50 @@ using namespace rapidjson; // ... Document document; document.Parse(json); -``` +~~~~~~~~~~ The JSON text is now parsed into `document` as a *DOM tree*: -![tutorial](diagram/tutorial.png?raw=true) +![tutorial](diagram/tutorial.png) The root of a conforming JSON should be either an object or an array. In this case, the root is an object. -```cpp +~~~~~~~~~~cpp assert(document.IsObject()); -``` +~~~~~~~~~~ Query whether a `"hello"` member exists in the root object. Since a `Value` can contain different types of value, we may need to verify its type and use suitable API to obtain the value. In this example, `"hello"` member associates with a JSON string. -```cpp +~~~~~~~~~~cpp assert(document.HasMember("hello")); assert(document["hello"].IsString()); printf("hello = %s\n", document["hello"].GetString()); -``` +~~~~~~~~~~ -``` +~~~~~~~~~~ world -``` +~~~~~~~~~~ JSON true/false values are represented as `bool`. -```cpp +~~~~~~~~~~cpp assert(document["t"].IsBool()); printf("t = %s\n", document["t"].GetBool() ? "true" : "false"); -``` +~~~~~~~~~~ -``` +~~~~~~~~~~ true -``` +~~~~~~~~~~ JSON null can be queryed by `IsNull()`. -```cpp +~~~~~~~~~~cpp printf("n = %s\n", document["n"].IsNull() ? "null" : "?"); -``` +~~~~~~~~~~ -``` +~~~~~~~~~~ null -``` +~~~~~~~~~~ JSON number type represents all numeric values. However, C++ needs more specific type for manipulation. -```cpp +~~~~~~~~~~cpp assert(document["i"].IsNumber()); // In this case, IsUint()/IsInt64()/IsUInt64() also return true. @@ -88,28 +88,28 @@ printf("i = %d\n", document["i"].GetInt()); assert(document["pi"].IsNumber()); assert(document["pi"].IsDouble()); printf("pi = %g\n", document["pi"].GetDouble()); -``` +~~~~~~~~~~ -``` +~~~~~~~~~~ i = 123 pi = 3.1416 -``` +~~~~~~~~~~ JSON array contains a number of elements. -```cpp +~~~~~~~~~~cpp // Using a reference for consecutive access is handy and faster. const Value& a = document["a"]; assert(a.IsArray()); for (SizeType i = 0; i < a.Size(); i++) // Uses SizeType instead of size_t printf("a[%d] = %d\n", i, a[i].GetInt()); -``` +~~~~~~~~~~ -``` +~~~~~~~~~~ a[0] = 1 a[1] = 2 a[2] = 3 a[3] = 4 -``` +~~~~~~~~~~ Note that, RapidJSON does not automatically convert values between JSON types. If a value is a string, it is invalid to call `GetInt()`, for example. In debug mode it will fail an assertion. In release mode, the behavior is undefined. @@ -124,10 +124,10 @@ You may access the elements in array by integer literal, for example, `a[1]`, `a * `a[0u]` Array is similar to `std::vector`, instead of using indices, you may also use iterator to access all the elements. -```cpp +~~~~~~~~~~cpp for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) printf("%d ", itr->GetInt()); -``` +~~~~~~~~~~ And other familiar query functions: * `SizeType Capacity() const` @@ -137,7 +137,7 @@ And other familiar query functions: Similar to array, we can iterate object members by iterator: -```cpp +~~~~~~~~~~cpp static const char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" }; @@ -147,9 +147,9 @@ for (Value::ConstMemberIterator itr = document.MemberBegin(); printf("Type of member %s is %s\n", itr->name.GetString(), kTypeNames[itr->value.GetType()]); } -``` +~~~~~~~~~~ -``` +~~~~~~~~~~ Type of member hello is String Type of member t is True Type of member f is False @@ -157,17 +157,17 @@ Type of member n is Null Type of member i is Number Type of member pi is Number Type of member a is Array -``` +~~~~~~~~~~ Note that, when `operator[](const char*)` cannot find the member, it will fail an assertion. If we are unsure whether a member exists, we need to call `HasMember()` before calling `operator[](const char*)`. However, this incurs two lookup. A better way is to call `FindMember()`, which can check the existence of member and obtain its value at once: -```cpp +~~~~~~~~~~cpp Value::ConstMemberIterator itr = document.FindMember("hello"); if (itr != document.MemberEnd()) printf("%s %s\n", itr->value.GetString()); -``` +~~~~~~~~~~ ### Querying Number @@ -210,18 +210,18 @@ To conform RFC 4627, RapidJSON supports string containing `U+0000`. If you need For example, after parsing a the following JSON string to `Document d`. -```js +~~~~~~~~~~js { "s" : "a\u0000b" } -``` +~~~~~~~~~~ The correct length of the value `"a\u0000b"` is 3. But `strlen()` returns 1. `GetStringLength()` can also improve performance, as user may often need to call `strlen()` for allocating buffer. Besides, `std::string` also support a constructor: -```cpp +~~~~~~~~~~cpp string( const char* s, size_type count); -``` +~~~~~~~~~~ which accepts the length of string as parameter. This constructor supports storing null character within the string, and should also provide better performance. @@ -232,43 +232,43 @@ There are several ways to create values. After a DOM tree is created and/or modi ### Changing Value Type When creating a Value or Document by default constructor, its type is Null. To change its type, call `SetXXX()` or assignment operator, for example: -```cpp +~~~~~~~~~~cpp Document d; // Null d.SetObject(); Value v; // Null v.SetInt(10); v = 10; // Shortcut, same as above -``` +~~~~~~~~~~ ### Overloaded Constructors There are also overloaded constructors for several types: -```cpp +~~~~~~~~~~cpp Value b(true); // calls Value(bool) Value i(-123); // calls Value(int) Value u(123u); // calls Value(unsigned) Value d(1.5); // calls Value(double) -``` +~~~~~~~~~~ To create empty object or array, you may use `SetObject()`/`SetArray()` after default constructor, or using the `Value(Type)` in one shot: -```cpp +~~~~~~~~~~cpp Value o(kObjectType); Value a(kArrayType); -``` +~~~~~~~~~~ ### Move Semantics A very special decision during design of RapidJSON is that, assignment of value does not copy the source value to destination value. Instead, the value from source is moved to the destination. For example, -```cpp +~~~~~~~~~~cpp Value a(123); Value b(456); b = a; // a becomes a Null value, b becomes number 123. -``` +~~~~~~~~~~ -![move1](diagram/move1.png?raw=true) +![move1](diagram/move1.png) Why? What is the advantage of this semantics? @@ -276,7 +276,7 @@ The simple answer is performance. For fixed size JSON types (Number, True, False For example, if normal *copy* semantics was used: -```cpp +~~~~~~~~~~cpp Value o(kObjectType); { Value contacts(kArrayType); @@ -285,9 +285,9 @@ Value o(kObjectType); o.AddMember("contacts", contacts); // deep clone contacts (may be with lots of allocations) // destruct contacts. } -``` +~~~~~~~~~~ -![move2](diagram/move2.png?raw=true) +![move2](diagram/move2.png) The object `o` needs to allocate a buffer of same size as contacts, makes a deep clone of it, and then finally contacts is destructed. This will incur a lot of unnecessary allocations/deallocations and memory copying. @@ -297,7 +297,7 @@ To make RapidJSON simple and fast, we chose to use *move* semantics for assignme So, with move semantics, the above example becomes: -```cpp +~~~~~~~~~~cpp Value o(kObjectType); { Value contacts(kArrayType); @@ -305,9 +305,9 @@ Value o(kObjectType); o.AddMember("contacts", contacts); // just memcpy() of contacts itself to the value of new member (16 bytes) // contacts became Null here. Its destruction is trivial. } -``` +~~~~~~~~~~ -![move3](diagram/move3.png?raw=true) +![move3](diagram/move3.png) This is called move assignment operator in C++11. As RapidJSON supports C++03, it adopts move semantics using assignment operator, and all other modifying function like `AddMember()`, `PushBack()`. @@ -323,7 +323,7 @@ To make memory allocation customizable, RapidJSON requires user to pass an insta Therefore, when we assign a copy-string, we call this overloaded `SetString()` with allocator: -```cpp +~~~~~~~~~~cpp Document document; Value author; char buffer[10]; @@ -331,7 +331,7 @@ int len = sprintf(buffer, "%s %s", "Milo", "Yip"); // dynamically created string author.SetString(buffer, len, document.GetAllocator()); memset(buffer, 0, sizeof(buffer)); // author.GetString() still contains "Milo Yip" after buffer is destroyed -``` +~~~~~~~~~~ In this example, we get the allocator from a `Document` instance. This is a common idiom when using RapidJSON. But you may use other instances of allocator. @@ -339,12 +339,12 @@ Besides, the above `SetString()` requires length. This can handle null character Finally, for literal string or string with safe life-cycle can use const-string version of `SetString()`, which lacks allocator parameter: -```cpp +~~~~~~~~~~cpp Value s; s.SetString("rapidjson", 9); // faster, can contain null character s.SetString("rapidjson"); // slower, assumes null-terminated s = "rapidjson"; // shortcut, same as above -``` +~~~~~~~~~~ ### Modify Array Value with array type provides similar APIs as `std::vector`. @@ -359,7 +359,7 @@ Note that, `Reserve(...)` and `PushBack(...)` may allocate memory, therefore req Here is an example of `PushBack()`: -```cpp +~~~~~~~~~~cpp Value a(kArrayType); Document::AllocatorType& allocator = document.GetAllocator(); @@ -368,7 +368,7 @@ for (int i = 5; i <= 10; i++) // Fluent interface a.PushBack("Lua", allocator).PushBack("Mio", allocator); -``` +~~~~~~~~~~ Differs from STL, `PushBack()`/`PopBack()` returns the array reference itself. This is called fluent interface. @@ -382,16 +382,16 @@ Object is a collection of key-value pairs. Each key must be a string value. The Here is an example. -```cpp -Value contact(kObejct); +~~~~~~~~~~cpp +Value contact(kObject); contact.AddMember("name", "Milo", document.GetAllocator()); contact.AddMember("married", true, document.GetAllocator()); -``` +~~~~~~~~~~ ### Deep Copy Value If we really need to copy a DOM tree, we can use two APIs for deep copy: constructor with allocator, and `CopyFrom()`. -```cpp +~~~~~~~~~~cpp Document d; Document::AllocatorType& a = d.GetAllocator(); Value v1("foo"); @@ -406,19 +406,19 @@ v2.CopyFrom(d, a); // copy whole document to v2 assert(d.IsArray() && d.Size() == 2); // d untouched v1.SetObject().AddMember( "array", v2, a ); d.PushBack(v1,a); -``` +~~~~~~~~~~ ### Swap Values `Swap()` is also provided. -```cpp +~~~~~~~~~~cpp Value a(123); Value b("Hello"); a.Swap(b); assert(a.IsString()); assert(b.IsInt()); -``` +~~~~~~~~~~ Swapping two DOM trees is fast (constant time), despite the complexity of the tress. @@ -433,4 +433,4 @@ This tutorial shows the basics of DOM tree query and manipulation. There are sev 5. [Performance](performance.md) shows some in-house and third-party benchmarks. 6. [Internals](internals.md) describes some internal designs and techniques of RapidJSON. -You may also refer to the FAQ, API documentation, examples and unit tests. +You may also refer to the [FAQ](faq.md), API documentation, examples and unit tests. From b197be2f303123afc2482434b22df7041d275885 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 6 Jul 2014 15:14:32 +0200 Subject: [PATCH 12/13] stream.md: prepare Markdown for GitHub and Doxygen rendering --- doc/stream.md | 68 ++++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/doc/stream.md b/doc/stream.md index ebc34d5..84d58bc 100644 --- a/doc/stream.md +++ b/doc/stream.md @@ -1,6 +1,6 @@ # RapidJSON Stream -In RapidJSON, `Stream` is a concept for reading/writing JSON. Here we first show how to use streams provided. And then see how to create a custom streams. +In RapidJSON, `rapidjson::Stream` is a concept for reading/writing JSON. Here we first show how to use streams provided. And then see how to create a custom streams. ## Memory Streams @@ -10,7 +10,7 @@ Memory streams store JSON in memory. `StringStream` is the most basic input stream. It represents a complete, read-only JSON stored in memory. It is defined in `rapidjson/rapidjson.h`. -```cpp +~~~~~~~~~~cpp #include "rapidjson/document.h" // will include "rapidjson/rapidjson.h" using namespace rapidjson; @@ -21,16 +21,16 @@ StringStream s(json); Document d; d.ParseStream(s); -``` +~~~~~~~~~~ Since this is very common usage, `Document::Parse(const char*)` is provided to do exactly the same as above: -```cpp +~~~~~~~~~~cpp // ... const char json[] = "[1, 2, 3, 4]"; Document d; d.Parse(json); -``` +~~~~~~~~~~ Note that, `StringStream` is a typedef of `GenericStringStream >`, user may use another encodings to represent the character set of the stream. @@ -38,7 +38,7 @@ Note that, `StringStream` is a typedef of `GenericStringStream >`, user m `StringBuffer` is a simple output stream. It allocates a memory buffer for writing the whole JSON. Use `GetString()` to obtain the buffer. -```cpp +~~~~~~~~~~cpp #include "rapidjson/stringbuffer.h" StringBuffer buffer; @@ -46,14 +46,14 @@ Writer writer(buffer); d.Accept(writer); const char* output = buffer.GetString(); -``` +~~~~~~~~~~ When the buffer is full, it will increases the capacity automatically. The default capacity is 256 characters (256 bytes for UTF8, 512 bytes for UTF16, etc.). User can provide an allocator and a initial capacity. -```cpp +~~~~~~~~~~cpp StringBuffer buffer1(0, 1024); // Use its allocator, initial size = 1024 StringBuffer buffer2(allocator, 1024); -``` +~~~~~~~~~~ By default, `StringBuffer` will instantiate an internal allocator. @@ -69,10 +69,12 @@ However, if the JSON is big, or memory is limited, you can use `FileReadStream`. `FileReadStream` reads the file via a `FILE` pointer. And user need to provide a buffer. -```cpp +~~~~~~~~~~cpp #include "rapidjson/filereadstream.h" #include +using namespace rapidjson; + FILE* fp = fopen("big.json", "rb"); // non-Windows use "r" char readBuffer[65536]; @@ -82,7 +84,7 @@ Document d; d.ParseStream(is); fclose(fp); -``` +~~~~~~~~~~ Different from string streams, `FileReadStream` is byte stream. It does not handle encodings. If the file is not UTF-8, the byte stream can be wrapped in a `EncodedInputStream`. It will be discussed very soon. @@ -92,10 +94,12 @@ Apart from reading file, user can also use `FileReadStream` to read `stdin`. `FileWriteStream` is buffered output stream. Its usage is very similar to `FileReadStream`. -```cpp +~~~~~~~~~~cpp #include "rapidjson/filewritestream.h" #include +using namespace rapidjson; + Document d; d.Parse(json); // ... @@ -109,7 +113,7 @@ Writer writer(os); d.Accept(writer); fclose(fp); -``` +~~~~~~~~~~ It can also directs the output to `stdout`. @@ -129,7 +133,7 @@ Note that, these encoded streams can be applied to streams other than file. For `EncodedInputStream` has two template parameters. The first one is a `Encoding` class, such as `UTF8`, `UTF16LE`, defined in `rapidjson/encodings.h`. The second one is the class of stream to be wrapped. -```cpp +~~~~~~~~~~cpp #include "rapidjson/document.h" #include "rapidjson/filereadstream.h" // FileReadStream #include "rapidjson/encodedstream.h" // EncodedInputStream @@ -148,13 +152,13 @@ Document d; // Document is GenericDocument > d.ParseStream<0, UTF16LE<> >(eis); // Parses UTF-16LE file into UTF-8 in memory fclose(fp); -``` +~~~~~~~~~~ ### EncodedOutputStream `EncodedOutputStream` is similar but it has a `bool putBOM` parameter in the constructor, controlling whether to write BOM into output byte stream. -```cpp +~~~~~~~~~~cpp #include "rapidjson/filewritestream.h" // FileWriteStream #include "rapidjson/encodedstream.h" // EncodedOutputStream #include @@ -174,7 +178,7 @@ Writer, UTF8<>> writer(eos); d.Accept(writer); // This generates UTF32-LE file from UTF-8 in memory fclose(fp); -``` +~~~~~~~~~~ ### AutoUTFInputStream @@ -182,7 +186,7 @@ Sometimes an application may want to handle all supported JSON encoding. `AutoUT Since the characters (code units) may be 8-bit, 16-bit or 32-bit. `AutoUTFInputStream` requires a character type which can hold at least 32-bit. We may use `unsigned`, as in the template parameter: -```cpp +~~~~~~~~~~cpp #include "rapidjson/document.h" #include "rapidjson/filereadstream.h" // FileReadStream #include "rapidjson/encodedstream.h" // AutoUTFInputStream @@ -201,7 +205,7 @@ Document d; // Document is GenericDocument > d.ParseStream<0, AutoUTF >(eis); // This parses any UTF file into UTF-8 in memory fclose(fp); -``` +~~~~~~~~~~ When specifying the encoding of stream, uses `AutoUTF` as in `ParseStream()` above. @@ -211,7 +215,9 @@ You can obtain the type of UTF via `UTFType GetType()`. And check whether a BOM Similarly, to choose encoding for output during runtime, we can use `AutoUTFOutputStream`. This class is not automatic *per se*. You need to specify the UTF type and whether to write BOM in runtime. -```cpp +~~~~~~~~~~cpp +using namespace rapidjson; + void WriteJSONFile(FILE* fp, UTFType type, bool putBOM, const Document& d) { char writeBuffer[256]; FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer)); @@ -222,7 +228,7 @@ void WriteJSONFile(FILE* fp, UTFType type, bool putBOM, const Document& d) { Writer, AutoUTF<> > writer; d.Accept(writer); } -``` +~~~~~~~~~~ `AutoUTFInputStream` and `AutoUTFOutputStream` is more convenient than `EncodedInputStream` and `EncodedOutputStream`. They just incur a little bit runtime overheads. @@ -232,7 +238,7 @@ In addition to memory/file streams, user can create their own stream classes whi RapidJSON combines different types using templates. A class containing all required interface can be a stream. The Stream interface is defined in comments of `rapidjson/rapidjson.h`: -```cpp +~~~~~~~~~~cpp concept Stream { typename Ch; //!< Character type of the stream. @@ -261,7 +267,7 @@ concept Stream { //! \return Number of characters written. size_t PutEnd(Ch* begin); } -``` +~~~~~~~~~~ For input stream, they must implement `Peek()`, `Take()` and `Tell()`. For output stream, they must implement `Put()` and `Flush()`. @@ -271,7 +277,7 @@ There are two special interface, `PutBegin()` and `PutEnd()`, which are only for The following example is a wrapper of `std::istream`, which only implements 3 functions. -```cpp +~~~~~~~~~~cpp class IStreamWrapper { public: typedef char Ch; @@ -302,18 +308,18 @@ private: std::istream& is_; }; -``` +~~~~~~~~~~ User can use it to wrap instances of `std::stringstream`, `std::ifstream`. -```cpp +~~~~~~~~~~cpp const char* json = "[1,2,3,4]"; std::stringstream ss(json); IStreamWrapper is(ss); Document d; d.Parse(is); -``` +~~~~~~~~~~ Note that, this implementation may not be as efficient as RapidJSON's memory or file streams, due to internal overheads of the standard library. @@ -321,7 +327,7 @@ Note that, this implementation may not be as efficient as RapidJSON's memory or The following example is a wrapper of `std::istream`, which only implements 2 functions. -```cpp +~~~~~~~~~~cpp class OStreamWrapper { public: typedef char Ch; @@ -344,11 +350,11 @@ private: std::ostream& os_; }; -``` +~~~~~~~~~~ User can use it to wrap instances of `std::stringstream`, `std::ofstream`. -```cpp +~~~~~~~~~~cpp Document d; // ... @@ -357,7 +363,7 @@ OSStreamWrapper os(ss); Writer writer(os); d.Accept(writer); -``` +~~~~~~~~~~ Note that, this implementation may not be as efficient as RapidJSON's memory or file streams, due to internal overheads of the standard library. From a213d2d881962bbb2a3b271b58584c2ef3d3c6f0 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 6 Jul 2014 16:39:23 +0200 Subject: [PATCH 13/13] Doxygen: fixup main page To avoid the {#mainpage} tag to be rendered on GitHub, explicitly add a `\mainpage` section to `rapidjson.h`, referring to `readme.md`. --- include/rapidjson/rapidjson.h | 4 ++++ readme.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index bd500bc..b6cb2f4 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -10,6 +10,10 @@ \todo Complete Doxygen documentation for configure macros. */ +/*! \mainpage + Documentation can be found in \ref readme.md README. +*/ + #include // malloc(), realloc(), free() #include // memcpy() diff --git a/readme.md b/readme.md index 98a51eb..1741d91 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# RapidJSON {#mainpage} +# RapidJSON Copyright (c) 2011-2014 Milo Yip (miloyip@gmail.com)