From 0d93dfb7c60d2168aef38b32a33befe498763f62 Mon Sep 17 00:00:00 2001 From: Srecko Date: Thu, 16 May 2024 19:11:35 +0200 Subject: [PATCH] code-format (large diff because of code moved to a namespace) --- .../Utilities/interface/EvFDaqDirector.h | 2 +- EventFilter/Utilities/interface/features.h | 34 +- EventFilter/Utilities/interface/forwards.h | 58 +- .../Utilities/interface/json_batchallocator.h | 162 +- EventFilter/Utilities/interface/reader.h | 196 +- EventFilter/Utilities/interface/value.h | 1160 ++++----- EventFilter/Utilities/interface/writer.h | 198 +- EventFilter/Utilities/src/json_reader.cpp | 1234 +++++----- EventFilter/Utilities/src/json_value.cpp | 2108 ++++++++--------- EventFilter/Utilities/src/json_writer.cpp | 1096 ++++----- 10 files changed, 3124 insertions(+), 3124 deletions(-) diff --git a/EventFilter/Utilities/interface/EvFDaqDirector.h b/EventFilter/Utilities/interface/EvFDaqDirector.h index 921c612bfbd84..6b9a7ebc6616c 100644 --- a/EventFilter/Utilities/interface/EvFDaqDirector.h +++ b/EventFilter/Utilities/interface/EvFDaqDirector.h @@ -46,7 +46,7 @@ namespace jsoncollector { namespace Json { class Value; } -} +} // namespace jsoncollector namespace edm { class ConfigurationDescriptions; diff --git a/EventFilter/Utilities/interface/features.h b/EventFilter/Utilities/interface/features.h index 7f9739267996c..fb3dbab077c9e 100644 --- a/EventFilter/Utilities/interface/features.h +++ b/EventFilter/Utilities/interface/features.h @@ -4,40 +4,40 @@ #include "forwards.h" namespace jsoncollector { -namespace Json { + namespace Json { - /** \brief Configuration passed to reader and writer. + /** \brief Configuration passed to reader and writer. * This configuration object can be used to force the Reader or Writer * to behave in a standard conforming way. */ - class JSON_API Features { - public: - /** \brief A configuration that allows all features and assumes all strings are UTF-8. + class JSON_API Features { + public: + /** \brief A configuration that allows all features and assumes all strings are UTF-8. * - C & C++ comments are allowed * - Root object can be any JSON value * - Assumes Value strings are encoded in UTF-8 */ - static Features all(); + static Features all(); - /** \brief A configuration that is strictly compatible with the JSON specification. + /** \brief A configuration that is strictly compatible with the JSON specification. * - Comments are forbidden. * - Root object must be either an array or an object value. * - Assumes Value strings are encoded in UTF-8 */ - static Features strictMode(); + static Features strictMode(); - /** \brief Initialize the configuration like JsonConfig::allFeatures; + /** \brief Initialize the configuration like JsonConfig::allFeatures; */ - Features(); + Features(); - /// \c true if comments are allowed. Default: \c true. - bool allowComments_; + /// \c true if comments are allowed. Default: \c true. + bool allowComments_; - /// \c true if root must be either an array or an object value. Default: \c false. - bool strictRoot_; - }; + /// \c true if root must be either an array or an object value. Default: \c false. + bool strictRoot_; + }; -} // namespace Json -} // namespace jsoncollector + } // namespace Json +} // namespace jsoncollector #endif // CPPTL_JSON_FEATURES_H_INCLUDED diff --git a/EventFilter/Utilities/interface/forwards.h b/EventFilter/Utilities/interface/forwards.h index dde7efdf46913..cf83ceea6dfc6 100644 --- a/EventFilter/Utilities/interface/forwards.h +++ b/EventFilter/Utilities/interface/forwards.h @@ -4,37 +4,37 @@ #include "config.h" namespace jsoncollector { -namespace Json { - - // writer.h - class FastWriter; - class StyledWriter; - - // reader.h - class Reader; - - // features.h - class Features; - - // value.h - typedef int Int; - typedef unsigned int UInt; - class StaticString; - class Path; - class PathArgument; - class Value; - class ValueIteratorBase; - class ValueIterator; - class ValueConstIterator; + namespace Json { + + // writer.h + class FastWriter; + class StyledWriter; + + // reader.h + class Reader; + + // features.h + class Features; + + // value.h + typedef int Int; + typedef unsigned int UInt; + class StaticString; + class Path; + class PathArgument; + class Value; + class ValueIteratorBase; + class ValueIterator; + class ValueConstIterator; #ifdef JSON_VALUE_USE_INTERNAL_MAP - class ValueAllocator; - class ValueMapAllocator; - class ValueInternalLink; - class ValueInternalArray; - class ValueInternalMap; + class ValueAllocator; + class ValueMapAllocator; + class ValueInternalLink; + class ValueInternalArray; + class ValueInternalMap; #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP -} // namespace Json -} // namespace jsoncollector + } // namespace Json +} // namespace jsoncollector #endif // JSON_FORWARDS_H_INCLUDED diff --git a/EventFilter/Utilities/interface/json_batchallocator.h b/EventFilter/Utilities/interface/json_batchallocator.h index a66532b75675d..e1cf85bd22966 100644 --- a/EventFilter/Utilities/interface/json_batchallocator.h +++ b/EventFilter/Utilities/interface/json_batchallocator.h @@ -7,9 +7,9 @@ #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION namespace jsoncollector { -namespace Json { + namespace Json { - /* Fast memory allocator. + /* Fast memory allocator. * * This memory allocator allocates memory for a batch of object (specified by * the page size, the number of object in each page). @@ -21,93 +21,93 @@ namespace Json { * The in-place new operator must be used to construct the object using the pointer * returned by allocate. */ - template - class BatchAllocator { - public: - typedef AllocatedType Type; - - BatchAllocator(unsigned int objectsPerPage = 255) : freeHead_(0), objectsPerPage_(objectsPerPage) { - // printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() ); - assert(sizeof(AllocatedType) * objectPerAllocation >= - sizeof(AllocatedType *)); // We must be able to store a slist in the object free space. - assert(objectsPerPage >= 16); - batches_ = allocateBatch(0); // allocated a dummy page - currentBatch_ = batches_; - } - - ~BatchAllocator() { - for (BatchInfo *batch = batches_; batch;) { - BatchInfo *nextBatch = batch->next_; - free(batch); - batch = nextBatch; + template + class BatchAllocator { + public: + typedef AllocatedType Type; + + BatchAllocator(unsigned int objectsPerPage = 255) : freeHead_(0), objectsPerPage_(objectsPerPage) { + // printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() ); + assert(sizeof(AllocatedType) * objectPerAllocation >= + sizeof(AllocatedType *)); // We must be able to store a slist in the object free space. + assert(objectsPerPage >= 16); + batches_ = allocateBatch(0); // allocated a dummy page + currentBatch_ = batches_; } - } - - /// allocate space for an array of objectPerAllocation object. - /// @warning it is the responsability of the caller to call objects constructors. - AllocatedType *allocate() { - if (freeHead_) // returns node from free list. - { - AllocatedType *object = freeHead_; - freeHead_ = *(AllocatedType **)object; - return object; + + ~BatchAllocator() { + for (BatchInfo *batch = batches_; batch;) { + BatchInfo *nextBatch = batch->next_; + free(batch); + batch = nextBatch; + } } - if (currentBatch_->used_ == currentBatch_->end_) { - currentBatch_ = currentBatch_->next_; - while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_) - currentBatch_ = currentBatch_->next_; - if (!currentBatch_) // no free batch found, allocate a new one + /// allocate space for an array of objectPerAllocation object. + /// @warning it is the responsability of the caller to call objects constructors. + AllocatedType *allocate() { + if (freeHead_) // returns node from free list. { - currentBatch_ = allocateBatch(objectsPerPage_); - currentBatch_->next_ = batches_; // insert at the head of the list - batches_ = currentBatch_; + AllocatedType *object = freeHead_; + freeHead_ = *(AllocatedType **)object; + return object; + } + if (currentBatch_->used_ == currentBatch_->end_) { + currentBatch_ = currentBatch_->next_; + while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_) + currentBatch_ = currentBatch_->next_; + + if (!currentBatch_) // no free batch found, allocate a new one + { + currentBatch_ = allocateBatch(objectsPerPage_); + currentBatch_->next_ = batches_; // insert at the head of the list + batches_ = currentBatch_; + } } + AllocatedType *allocated = currentBatch_->used_; + currentBatch_->used_ += objectPerAllocation; + return allocated; } - AllocatedType *allocated = currentBatch_->used_; - currentBatch_->used_ += objectPerAllocation; - return allocated; - } - - /// Release the object. - /// @warning it is the responsability of the caller to actually destruct the object. - void release(AllocatedType *object) { - assert(object != 0); - *(AllocatedType **)object = freeHead_; - freeHead_ = object; - } - - // disabled copy constructor and assignement operator. - BatchAllocator(const BatchAllocator &) = delete; - void operator=(const BatchAllocator &) = delete; - - private: - struct BatchInfo { - BatchInfo *next_; - AllocatedType *used_; - AllocatedType *end_; - AllocatedType buffer_[objectPerAllocation]; + + /// Release the object. + /// @warning it is the responsability of the caller to actually destruct the object. + void release(AllocatedType *object) { + assert(object != 0); + *(AllocatedType **)object = freeHead_; + freeHead_ = object; + } + + // disabled copy constructor and assignement operator. + BatchAllocator(const BatchAllocator &) = delete; + void operator=(const BatchAllocator &) = delete; + + private: + struct BatchInfo { + BatchInfo *next_; + AllocatedType *used_; + AllocatedType *end_; + AllocatedType buffer_[objectPerAllocation]; + }; + + static BatchInfo *allocateBatch(unsigned int objectsPerPage) { + const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType) * objectPerAllocation + + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; + BatchInfo *batch = static_cast(malloc(mallocSize)); + batch->next_ = 0; + batch->used_ = batch->buffer_; + batch->end_ = batch->buffer_ + objectsPerPage; + return batch; + } + + BatchInfo *batches_; + BatchInfo *currentBatch_; + /// Head of a single linked list within the allocated space of freeed object + AllocatedType *freeHead_; + unsigned int objectsPerPage_; }; - static BatchInfo *allocateBatch(unsigned int objectsPerPage) { - const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType) * objectPerAllocation + - sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; - BatchInfo *batch = static_cast(malloc(mallocSize)); - batch->next_ = 0; - batch->used_ = batch->buffer_; - batch->end_ = batch->buffer_ + objectsPerPage; - return batch; - } - - BatchInfo *batches_; - BatchInfo *currentBatch_; - /// Head of a single linked list within the allocated space of freeed object - AllocatedType *freeHead_; - unsigned int objectsPerPage_; - }; - -} // namespace Json -} //namespace jsoncollector + } // namespace Json +} //namespace jsoncollector #endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION diff --git a/EventFilter/Utilities/interface/reader.h b/EventFilter/Utilities/interface/reader.h index bfc0c042930a9..904628eeebe73 100644 --- a/EventFilter/Utilities/interface/reader.h +++ b/EventFilter/Utilities/interface/reader.h @@ -9,27 +9,27 @@ #include namespace jsoncollector { -namespace Json { + namespace Json { - /** \brief Unserialize a JSON document into a Value. + /** \brief Unserialize a JSON document into a Value. * */ - class JSON_API Reader { - public: - typedef char Char; - typedef const Char *Location; + class JSON_API Reader { + public: + typedef char Char; + typedef const Char *Location; - /** \brief Constructs a Reader allowing all features + /** \brief Constructs a Reader allowing all features * for parsing. */ - Reader(); + Reader(); - /** \brief Constructs a Reader allowing the specified feature set + /** \brief Constructs a Reader allowing the specified feature set * for parsing. */ - Reader(const Features &features); + Reader(const Features &features); - /** \brief Read a Value from a JSON document. + /** \brief Read a Value from a JSON document. * \param document UTF-8 encoded string containing the document to read. * \param root [out] Contains the root value of the document if it was * successfully parsed. @@ -39,9 +39,9 @@ namespace Json { * is \c false. * \return \c true if the document was successfully parsed, \c false if an error occurred. */ - bool parse(const std::string &document, Value &root, bool collectComments = true); + bool parse(const std::string &document, Value &root, bool collectComments = true); - /** \brief Read a Value from a JSON document. + /** \brief Read a Value from a JSON document. * \param document UTF-8 encoded string containing the document to read. * \param root [out] Contains the root value of the document if it was * successfully parsed. @@ -51,97 +51,97 @@ namespace Json { * is \c false. * \return \c true if the document was successfully parsed, \c false if an error occurred. */ - bool parse(const char *beginDoc, const char *endDoc, Value &root, bool collectComments = true); + bool parse(const char *beginDoc, const char *endDoc, Value &root, bool collectComments = true); - /// \brief Parse from input stream. - /// \see Json::operator>>(std::istream&, Json::Value&). - bool parse(std::istream &is, Value &root, bool collectComments = true); + /// \brief Parse from input stream. + /// \see Json::operator>>(std::istream&, Json::Value&). + bool parse(std::istream &is, Value &root, bool collectComments = true); - /** \brief Returns a user friendly string that list errors in the parsed document. + /** \brief Returns a user friendly string that list errors in the parsed document. * \return Formatted error message with the list of errors with their location in * the parsed document. An empty string is returned if no error occurred * during parsing. */ - std::string getFormatedErrorMessages() const; - - private: - enum TokenType { - tokenEndOfStream = 0, - tokenObjectBegin, - tokenObjectEnd, - tokenArrayBegin, - tokenArrayEnd, - tokenString, - tokenNumber, - tokenTrue, - tokenFalse, - tokenNull, - tokenArraySeparator, - tokenMemberSeparator, - tokenComment, - tokenError - }; - - class Token { - public: - TokenType type_; - Location start_; + std::string getFormatedErrorMessages() const; + + private: + enum TokenType { + tokenEndOfStream = 0, + tokenObjectBegin, + tokenObjectEnd, + tokenArrayBegin, + tokenArrayEnd, + tokenString, + tokenNumber, + tokenTrue, + tokenFalse, + tokenNull, + tokenArraySeparator, + tokenMemberSeparator, + tokenComment, + tokenError + }; + + class Token { + public: + TokenType type_; + Location start_; + Location end_; + }; + + class ErrorInfo { + public: + Token token_; + std::string message_; + Location extra_; + }; + + typedef std::deque Errors; + + bool expectToken(TokenType type, Token &token, const char *message); + bool readToken(Token &token); + void skipSpaces(); + bool match(Location pattern, int patternLength); + bool readComment(); + bool readCStyleComment(); + bool readCppStyleComment(); + bool readString(); + void readNumber(); + bool readValue(); + bool readObject(Token &token); + bool readArray(Token &token); + bool decodeNumber(Token &token); + bool decodeString(Token &token); + bool decodeString(Token &token, std::string &decoded); + bool decodeDouble(Token &token); + bool decodeUnicodeCodePoint(Token &token, Location ¤t, Location end, unsigned int &unicode); + bool decodeUnicodeEscapeSequence(Token &token, Location ¤t, Location end, unsigned int &unicode); + bool addError(const std::string &message, Token &token, Location extra = nullptr); + bool recoverFromError(TokenType skipUntilToken); + bool addErrorAndRecover(const std::string &message, Token &token, TokenType skipUntilToken); + void skipUntilSpace(); + Value ¤tValue(); + Char getNextChar(); + void getLocationLineAndColumn(Location location, int &line, int &column) const; + std::string getLocationLineAndColumn(Location location) const; + void addComment(Location begin, Location end, CommentPlacement placement); + void skipCommentTokens(Token &token); + + typedef std::stack Nodes; + Nodes nodes_; + Errors errors_; + std::string document_; + Location begin_; Location end_; + Location current_; + Location lastValueEnd_; + Value *lastValue_; + std::string commentsBefore_; + Features features_; + bool collectComments_; }; - class ErrorInfo { - public: - Token token_; - std::string message_; - Location extra_; - }; - - typedef std::deque Errors; - - bool expectToken(TokenType type, Token &token, const char *message); - bool readToken(Token &token); - void skipSpaces(); - bool match(Location pattern, int patternLength); - bool readComment(); - bool readCStyleComment(); - bool readCppStyleComment(); - bool readString(); - void readNumber(); - bool readValue(); - bool readObject(Token &token); - bool readArray(Token &token); - bool decodeNumber(Token &token); - bool decodeString(Token &token); - bool decodeString(Token &token, std::string &decoded); - bool decodeDouble(Token &token); - bool decodeUnicodeCodePoint(Token &token, Location ¤t, Location end, unsigned int &unicode); - bool decodeUnicodeEscapeSequence(Token &token, Location ¤t, Location end, unsigned int &unicode); - bool addError(const std::string &message, Token &token, Location extra = nullptr); - bool recoverFromError(TokenType skipUntilToken); - bool addErrorAndRecover(const std::string &message, Token &token, TokenType skipUntilToken); - void skipUntilSpace(); - Value ¤tValue(); - Char getNextChar(); - void getLocationLineAndColumn(Location location, int &line, int &column) const; - std::string getLocationLineAndColumn(Location location) const; - void addComment(Location begin, Location end, CommentPlacement placement); - void skipCommentTokens(Token &token); - - typedef std::stack Nodes; - Nodes nodes_; - Errors errors_; - std::string document_; - Location begin_; - Location end_; - Location current_; - Location lastValueEnd_; - Value *lastValue_; - std::string commentsBefore_; - Features features_; - bool collectComments_; - }; - - /** \brief Read from 'sin' into 'root'. + /** \brief Read from 'sin' into 'root'. Always keep comments from the input JSON. @@ -165,8 +165,8 @@ namespace Json { \throw std::exception on parse error. \see Json::operator<<() */ - std::istream &operator>>(std::istream &, Value &); + std::istream &operator>>(std::istream &, Value &); -} // namespace Json -} // namespace jsoncollector + } // namespace Json +} // namespace jsoncollector #endif // CPPTL_JSON_READER_H_INCLUDED diff --git a/EventFilter/Utilities/interface/value.h b/EventFilter/Utilities/interface/value.h index 3c0c8a399d8e3..6cd97fec41b6c 100644 --- a/EventFilter/Utilities/interface/value.h +++ b/EventFilter/Utilities/interface/value.h @@ -18,34 +18,34 @@ */ namespace jsoncollector { -namespace Json { + namespace Json { - /** \brief Type of the value held by a Value object. + /** \brief Type of the value held by a Value object. */ - enum ValueType { - nullValue = 0, ///< 'null' value - intValue, ///< signed integer value - uintValue, ///< unsigned integer value - realValue, ///< double value - stringValue, ///< UTF-8 string value - booleanValue, ///< bool value - arrayValue, ///< array value (ordered list) - objectValue ///< object value (collection of name/value pairs). - }; - - enum CommentPlacement { - commentBefore = 0, ///< a comment placed on the line before a value - commentAfterOnSameLine, ///< a comment just after a value on the same line - commentAfter, ///< a comment on the line after a value (only make sense for root value) - numberOfCommentPlacement - }; - - //# ifdef JSON_USE_CPPTL - // typedef CppTL::AnyEnumerator EnumMemberNames; - // typedef CppTL::AnyEnumerator EnumValues; - //# endif - - /** \brief Lightweight wrapper to tag static string. + enum ValueType { + nullValue = 0, ///< 'null' value + intValue, ///< signed integer value + uintValue, ///< unsigned integer value + realValue, ///< double value + stringValue, ///< UTF-8 string value + booleanValue, ///< bool value + arrayValue, ///< array value (ordered list) + objectValue ///< object value (collection of name/value pairs). + }; + + enum CommentPlacement { + commentBefore = 0, ///< a comment placed on the line before a value + commentAfterOnSameLine, ///< a comment just after a value on the same line + commentAfter, ///< a comment on the line after a value (only make sense for root value) + numberOfCommentPlacement + }; + + //# ifdef JSON_USE_CPPTL + // typedef CppTL::AnyEnumerator EnumMemberNames; + // typedef CppTL::AnyEnumerator EnumValues; + //# endif + + /** \brief Lightweight wrapper to tag static string. * * Value constructor and objectValue member assignement takes advantage of the * StaticString and avoid the cost of string duplication when storing the @@ -59,19 +59,19 @@ namespace Json { * object[code] = 1234; * \endcode */ - class JSON_API StaticString { - public: - explicit StaticString(const char *czstring) : str_(czstring) {} + class JSON_API StaticString { + public: + explicit StaticString(const char *czstring) : str_(czstring) {} - operator const char *() const { return str_; } + operator const char *() const { return str_; } - const char *c_str() const { return str_; } + const char *c_str() const { return str_; } - private: - const char *str_; - }; + private: + const char *str_; + }; - /** \brief Represents a JSON value. + /** \brief Represents a JSON value. * * This class is a discriminated union wrapper that can represents a: * - signed integer [range: Value::minInt - Value::maxInt] @@ -98,59 +98,59 @@ namespace Json { * It is possible to iterate over the list of a #objectValue values using * the getMemberNames() method. */ - class JSON_API Value { - friend class ValueIteratorBase; + class JSON_API Value { + friend class ValueIteratorBase; #ifdef JSON_VALUE_USE_INTERNAL_MAP - friend class ValueInternalLink; - friend class ValueInternalMap; + friend class ValueInternalLink; + friend class ValueInternalMap; #endif - public: - typedef std::vector Members; - typedef ValueIterator iterator; - typedef ValueConstIterator const_iterator; - typedef Json::UInt UInt; - typedef Json::Int Int; - typedef UInt ArrayIndex; - - static const Value null; - static const Int minInt; - static const Int maxInt; - static const UInt maxUInt; - - private: -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION -#ifndef JSON_VALUE_USE_INTERNAL_MAP - class CZString { public: - enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy }; - CZString(int index); - CZString(const char *cstr, DuplicationPolicy allocate); - CZString(const CZString &other); - ~CZString(); - CZString &operator=(const CZString &other); - bool operator<(const CZString &other) const; - bool operator==(const CZString &other) const; - int index() const; - const char *c_str() const; - bool isStaticString() const; + typedef std::vector Members; + typedef ValueIterator iterator; + typedef ValueConstIterator const_iterator; + typedef Json::UInt UInt; + typedef Json::Int Int; + typedef UInt ArrayIndex; + + static const Value null; + static const Int minInt; + static const Int maxInt; + static const UInt maxUInt; private: - void swap(CZString &other); - const char *cstr_; - int index_; - }; +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION +#ifndef JSON_VALUE_USE_INTERNAL_MAP + class CZString { + public: + enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy }; + CZString(int index); + CZString(const char *cstr, DuplicationPolicy allocate); + CZString(const CZString &other); + ~CZString(); + CZString &operator=(const CZString &other); + bool operator<(const CZString &other) const; + bool operator==(const CZString &other) const; + int index() const; + const char *c_str() const; + bool isStaticString() const; + + private: + void swap(CZString &other); + const char *cstr_; + int index_; + }; - public: + public: #ifndef JSON_USE_CPPTL_SMALLMAP - typedef std::map ObjectValues; + typedef std::map ObjectValues; #else - typedef CppTL::SmallMap ObjectValues; + typedef CppTL::SmallMap ObjectValues; #endif // ifndef JSON_USE_CPPTL_SMALLMAP #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - public: - /** \brief Create a default Value of the given type. + public: + /** \brief Create a default Value of the given type. This is a very useful constructor. To create an empty array, pass arrayValue. @@ -165,13 +165,13 @@ namespace Json { Json::Value obj_value(Json::objectValue); // {} \endcode */ - Value(ValueType type = nullValue); - Value(Int value); - Value(UInt value); - Value(double value); - Value(const char *value); - Value(const char *beginValue, const char *endValue); - /** \brief Constructs a value from a static string. + Value(ValueType type = nullValue); + Value(Int value); + Value(UInt value); + Value(double value); + Value(const char *value); + Value(const char *beginValue, const char *endValue); + /** \brief Constructs a value from a static string. * Like other value string constructor but do not duplicate the string for * internal storage. The given string must remain alive after the call to this @@ -181,107 +181,107 @@ namespace Json { * Json::Value aValue( StaticString("some text") ); * \endcode */ - Value(const StaticString &value); - Value(const std::string &value); + Value(const StaticString &value); + Value(const std::string &value); #ifdef JSON_USE_CPPTL - Value(const CppTL::ConstString &value); + Value(const CppTL::ConstString &value); #endif - Value(bool value); - Value(const Value &other); - ~Value(); + Value(bool value); + Value(const Value &other); + ~Value(); - Value &operator=(const Value &other); - /// Swap values. - /// \note Currently, comments are intentionally not swapped, for - /// both logic and efficiency. - void swap(Value &other); + Value &operator=(const Value &other); + /// Swap values. + /// \note Currently, comments are intentionally not swapped, for + /// both logic and efficiency. + void swap(Value &other); - ValueType type() const; + ValueType type() const; - bool operator<(const Value &other) const; - bool operator<=(const Value &other) const; - bool operator>=(const Value &other) const; - bool operator>(const Value &other) const; + bool operator<(const Value &other) const; + bool operator<=(const Value &other) const; + bool operator>=(const Value &other) const; + bool operator>(const Value &other) const; - bool operator==(const Value &other) const; - bool operator!=(const Value &other) const; + bool operator==(const Value &other) const; + bool operator!=(const Value &other) const; - int compare(const Value &other); + int compare(const Value &other); - const char *asCString() const; - std::string asString() const; + const char *asCString() const; + std::string asString() const; #ifdef JSON_USE_CPPTL - CppTL::ConstString asConstString() const; + CppTL::ConstString asConstString() const; #endif - Int asInt() const; - UInt asUInt() const; - double asDouble() const; - bool asBool() const; - - bool isNull() const; - bool isBool() const; - bool isInt() const; - bool isUInt() const; - bool isIntegral() const; - bool isDouble() const; - bool isNumeric() const; - bool isString() const; - bool isArray() const; - bool isObject() const; - - bool isConvertibleTo(ValueType other) const; - - /// Number of values in array or object - UInt size() const; - - /// \brief Return true if empty array, empty object, or null; - /// otherwise, false. - bool empty() const; - - /// Return isNull() - bool operator!() const; - - /// Remove all object members and array elements. - /// \pre type() is arrayValue, objectValue, or nullValue - /// \post type() is unchanged - void clear(); - - /// Resize the array to size elements. - /// New elements are initialized to null. - /// May only be called on nullValue or arrayValue. - /// \pre type() is arrayValue or nullValue - /// \post type() is arrayValue - void resize(UInt size); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value &operator[](UInt index); - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value &operator[](UInt index) const; - /// If the array contains at least index+1 elements, returns the element value, - /// otherwise returns defaultValue. - Value get(UInt index, const Value &defaultValue) const; - /// Return true if index < size(). - bool isValidIndex(UInt index) const; - /// \brief Append value to array at the end. - /// - /// Equivalent to jsonvalue[jsonvalue.size()] = value; - Value &append(const Value &value); - - /// Access an object value by name, create a null member if it does not exist. - Value &operator[](const char *key); - /// Access an object value by name, returns null if there is no member with that name. - const Value &operator[](const char *key) const; - /// Access an object value by name, create a null member if it does not exist. - Value &operator[](const std::string &key); - /// Access an object value by name, returns null if there is no member with that name. - const Value &operator[](const std::string &key) const; - /** \brief Access an object value by name, create a null member if it does not exist. + Int asInt() const; + UInt asUInt() const; + double asDouble() const; + bool asBool() const; + + bool isNull() const; + bool isBool() const; + bool isInt() const; + bool isUInt() const; + bool isIntegral() const; + bool isDouble() const; + bool isNumeric() const; + bool isString() const; + bool isArray() const; + bool isObject() const; + + bool isConvertibleTo(ValueType other) const; + + /// Number of values in array or object + UInt size() const; + + /// \brief Return true if empty array, empty object, or null; + /// otherwise, false. + bool empty() const; + + /// Return isNull() + bool operator!() const; + + /// Remove all object members and array elements. + /// \pre type() is arrayValue, objectValue, or nullValue + /// \post type() is unchanged + void clear(); + + /// Resize the array to size elements. + /// New elements are initialized to null. + /// May only be called on nullValue or arrayValue. + /// \pre type() is arrayValue or nullValue + /// \post type() is arrayValue + void resize(UInt size); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value &operator[](UInt index); + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value &operator[](UInt index) const; + /// If the array contains at least index+1 elements, returns the element value, + /// otherwise returns defaultValue. + Value get(UInt index, const Value &defaultValue) const; + /// Return true if index < size(). + bool isValidIndex(UInt index) const; + /// \brief Append value to array at the end. + /// + /// Equivalent to jsonvalue[jsonvalue.size()] = value; + Value &append(const Value &value); + + /// Access an object value by name, create a null member if it does not exist. + Value &operator[](const char *key); + /// Access an object value by name, returns null if there is no member with that name. + const Value &operator[](const char *key) const; + /// Access an object value by name, create a null member if it does not exist. + Value &operator[](const std::string &key); + /// Access an object value by name, returns null if there is no member with that name. + const Value &operator[](const std::string &key) const; + /** \brief Access an object value by name, create a null member if it does not exist. * If the object as no entry for that name, then the member name used to store * the new entry is not duplicated. @@ -292,141 +292,141 @@ namespace Json { * object[code] = 1234; * \endcode */ - Value &operator[](const StaticString &key); + Value &operator[](const StaticString &key); #ifdef JSON_USE_CPPTL - /// Access an object value by name, create a null member if it does not exist. - Value &operator[](const CppTL::ConstString &key); - /// Access an object value by name, returns null if there is no member with that name. - const Value &operator[](const CppTL::ConstString &key) const; + /// Access an object value by name, create a null member if it does not exist. + Value &operator[](const CppTL::ConstString &key); + /// Access an object value by name, returns null if there is no member with that name. + const Value &operator[](const CppTL::ConstString &key) const; #endif - /// Return the member named key if it exist, defaultValue otherwise. - Value get(const char *key, const Value &defaultValue) const; - /// Return the member named key if it exist, defaultValue otherwise. - Value get(const std::string &key, const Value &defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + Value get(const char *key, const Value &defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + Value get(const std::string &key, const Value &defaultValue) const; #ifdef JSON_USE_CPPTL - /// Return the member named key if it exist, defaultValue otherwise. - Value get(const CppTL::ConstString &key, const Value &defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + Value get(const CppTL::ConstString &key, const Value &defaultValue) const; #endif - /// \brief Remove and return the named member. - /// - /// Do nothing if it did not exist. - /// \return the removed Value, or null. - /// \pre type() is objectValue or nullValue - /// \post type() is unchanged - Value removeMember(const char *key); - /// Same as removeMember(const char*) - Value removeMember(const std::string &key); - - /// Return true if the object has a member named key. - bool isMember(const char *key) const; - /// Return true if the object has a member named key. - bool isMember(const std::string &key) const; + /// \brief Remove and return the named member. + /// + /// Do nothing if it did not exist. + /// \return the removed Value, or null. + /// \pre type() is objectValue or nullValue + /// \post type() is unchanged + Value removeMember(const char *key); + /// Same as removeMember(const char*) + Value removeMember(const std::string &key); + + /// Return true if the object has a member named key. + bool isMember(const char *key) const; + /// Return true if the object has a member named key. + bool isMember(const std::string &key) const; #ifdef JSON_USE_CPPTL - /// Return true if the object has a member named key. - bool isMember(const CppTL::ConstString &key) const; + /// Return true if the object has a member named key. + bool isMember(const CppTL::ConstString &key) const; #endif - /// \brief Return a list of the member names. - /// - /// If null, return an empty list. - /// \pre type() is objectValue or nullValue - /// \post if type() was nullValue, it remains nullValue - Members getMemberNames() const; + /// \brief Return a list of the member names. + /// + /// If null, return an empty list. + /// \pre type() is objectValue or nullValue + /// \post if type() was nullValue, it remains nullValue + Members getMemberNames() const; - //# ifdef JSON_USE_CPPTL - // EnumMemberNames enumMemberNames() const; - // EnumValues enumValues() const; - //# endif + //# ifdef JSON_USE_CPPTL + // EnumMemberNames enumMemberNames() const; + // EnumValues enumValues() const; + //# endif - /// Comments must be //... or /* ... */ - void setComment(const char *comment, CommentPlacement placement); - /// Comments must be //... or /* ... */ - void setComment(const std::string &comment, CommentPlacement placement); - bool hasComment(CommentPlacement placement) const; - /// Include delimiters and embedded newlines. - std::string getComment(CommentPlacement placement) const; + /// Comments must be //... or /* ... */ + void setComment(const char *comment, CommentPlacement placement); + /// Comments must be //... or /* ... */ + void setComment(const std::string &comment, CommentPlacement placement); + bool hasComment(CommentPlacement placement) const; + /// Include delimiters and embedded newlines. + std::string getComment(CommentPlacement placement) const; - std::string toStyledString() const; + std::string toStyledString() const; - const_iterator begin() const; - const_iterator end() const; + const_iterator begin() const; + const_iterator end() const; - iterator begin(); - iterator end(); + iterator begin(); + iterator end(); - private: - Value &resolveReference(const char *key, bool isStatic); + private: + Value &resolveReference(const char *key, bool isStatic); #ifdef JSON_VALUE_USE_INTERNAL_MAP - inline bool isItemAvailable() const { return itemIsUsed_ == 0; } + inline bool isItemAvailable() const { return itemIsUsed_ == 0; } - inline void setItemUsed(bool isUsed = true) { itemIsUsed_ = isUsed ? 1 : 0; } + inline void setItemUsed(bool isUsed = true) { itemIsUsed_ = isUsed ? 1 : 0; } - inline bool isMemberNameStatic() const { return memberNameIsStatic_ == 0; } + inline bool isMemberNameStatic() const { return memberNameIsStatic_ == 0; } - inline void setMemberNameIsStatic(bool isStatic) { memberNameIsStatic_ = isStatic ? 1 : 0; } + inline void setMemberNameIsStatic(bool isStatic) { memberNameIsStatic_ = isStatic ? 1 : 0; } #endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP - private: - struct CommentInfo { - CommentInfo(); - ~CommentInfo(); + private: + struct CommentInfo { + CommentInfo(); + ~CommentInfo(); - void setComment(const char *text); + void setComment(const char *text); - char *comment_; - }; + char *comment_; + }; - //struct MemberNamesTransform - //{ - // typedef const char *result_type; - // const char *operator()( const CZString &name ) const - // { - // return name.c_str(); - // } - //}; - - union ValueHolder { - Int int_; - UInt uint_; - double real_; - bool bool_; - char *string_; + //struct MemberNamesTransform + //{ + // typedef const char *result_type; + // const char *operator()( const CZString &name ) const + // { + // return name.c_str(); + // } + //}; + + union ValueHolder { + Int int_; + UInt uint_; + double real_; + bool bool_; + char *string_; #ifdef JSON_VALUE_USE_INTERNAL_MAP - ValueInternalArray *array_; - ValueInternalMap *map_; + ValueInternalArray *array_; + ValueInternalMap *map_; #else - ObjectValues *map_; + ObjectValues *map_; #endif - } value_; - ValueType type_ : 8; - int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. + } value_; + ValueType type_ : 8; + int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. #ifdef JSON_VALUE_USE_INTERNAL_MAP - unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. - int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. + unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. + int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. #endif - CommentInfo *comments_; - }; + CommentInfo *comments_; + }; - /** \brief Experimental and untested: represents an element of the "path" to access a node. + /** \brief Experimental and untested: represents an element of the "path" to access a node. */ - class PathArgument { - public: - friend class Path; - - PathArgument(); - PathArgument(UInt index); - PathArgument(const char *key); - PathArgument(const std::string &key); - - private: - enum Kind { kindNone = 0, kindIndex, kindKey }; - std::string key_; - UInt index_; - Kind kind_; - }; - - /** \brief Experimental and untested: represents a "path" to access a node. + class PathArgument { + public: + friend class Path; + + PathArgument(); + PathArgument(UInt index); + PathArgument(const char *key); + PathArgument(const std::string &key); + + private: + enum Kind { kindNone = 0, kindIndex, kindKey }; + std::string key_; + UInt index_; + Kind kind_; + }; + + /** \brief Experimental and untested: represents a "path" to access a node. * * Syntax: * - "." => root node @@ -437,55 +437,55 @@ namespace Json { * - ".%" => member name is provided as parameter * - ".[%]" => index is provied as parameter */ - class Path { - public: - Path(const std::string &path, - const PathArgument &a1 = PathArgument(), - const PathArgument &a2 = PathArgument(), - const PathArgument &a3 = PathArgument(), - const PathArgument &a4 = PathArgument(), - const PathArgument &a5 = PathArgument()); - - const Value &resolve(const Value &root) const; - Value resolve(const Value &root, const Value &defaultValue) const; - /// Creates the "path" to access the specified node and returns a reference on the node. - Value &make(Value &root) const; - - private: - typedef std::vector InArgs; - typedef std::vector Args; - - void makePath(const std::string &path, const InArgs &in); - void addPathInArg(const std::string &path, - const InArgs &in, - InArgs::const_iterator &itInArg, - PathArgument::Kind kind); - void invalidPath(const std::string &path, int location); - - Args args_; - }; - - /** \brief Experimental do not use: Allocator to customize member name and string value memory management done by Value. + class Path { + public: + Path(const std::string &path, + const PathArgument &a1 = PathArgument(), + const PathArgument &a2 = PathArgument(), + const PathArgument &a3 = PathArgument(), + const PathArgument &a4 = PathArgument(), + const PathArgument &a5 = PathArgument()); + + const Value &resolve(const Value &root) const; + Value resolve(const Value &root, const Value &defaultValue) const; + /// Creates the "path" to access the specified node and returns a reference on the node. + Value &make(Value &root) const; + + private: + typedef std::vector InArgs; + typedef std::vector Args; + + void makePath(const std::string &path, const InArgs &in); + void addPathInArg(const std::string &path, + const InArgs &in, + InArgs::const_iterator &itInArg, + PathArgument::Kind kind); + void invalidPath(const std::string &path, int location); + + Args args_; + }; + + /** \brief Experimental do not use: Allocator to customize member name and string value memory management done by Value. * * - makeMemberName() and releaseMemberName() are called to respectively duplicate and * free an Json::objectValue member name. * - duplicateStringValue() and releaseStringValue() are called similarly to * duplicate and free a Json::stringValue value. */ - class ValueAllocator { - public: - enum { unknown = (unsigned)-1 }; + class ValueAllocator { + public: + enum { unknown = (unsigned)-1 }; - virtual ~ValueAllocator(); + virtual ~ValueAllocator(); - virtual char *makeMemberName(const char *memberName) const = 0; - virtual void releaseMemberName(char *memberName) const = 0; - virtual char *duplicateStringValue(const char *value, unsigned int length = unknown) const = 0; - virtual void releaseStringValue(char *value) const = 0; - }; + virtual char *makeMemberName(const char *memberName) const = 0; + virtual void releaseMemberName(char *memberName) const = 0; + virtual char *duplicateStringValue(const char *value, unsigned int length = unknown) const = 0; + virtual void releaseStringValue(char *value) const = 0; + }; #ifdef JSON_VALUE_USE_INTERNAL_MAP - /** \brief Allocator to customize Value internal map. + /** \brief Allocator to customize Value internal map. * Below is an example of a simple implementation (default implementation actually * use memory pool for speed). * \code @@ -529,37 +529,37 @@ namespace Json { }; * \endcode */ - class JSON_API ValueMapAllocator { - public: - virtual ~ValueMapAllocator(); - virtual ValueInternalMap *newMap() = 0; - virtual ValueInternalMap *newMapCopy(const ValueInternalMap &other) = 0; - virtual void destructMap(ValueInternalMap *map) = 0; - virtual ValueInternalLink *allocateMapBuckets(unsigned int size) = 0; - virtual void releaseMapBuckets(ValueInternalLink *links) = 0; - virtual ValueInternalLink *allocateMapLink() = 0; - virtual void releaseMapLink(ValueInternalLink *link) = 0; - }; - - /** \brief ValueInternalMap hash-map bucket chain link (for internal use only). + class JSON_API ValueMapAllocator { + public: + virtual ~ValueMapAllocator(); + virtual ValueInternalMap *newMap() = 0; + virtual ValueInternalMap *newMapCopy(const ValueInternalMap &other) = 0; + virtual void destructMap(ValueInternalMap *map) = 0; + virtual ValueInternalLink *allocateMapBuckets(unsigned int size) = 0; + virtual void releaseMapBuckets(ValueInternalLink *links) = 0; + virtual ValueInternalLink *allocateMapLink() = 0; + virtual void releaseMapLink(ValueInternalLink *link) = 0; + }; + + /** \brief ValueInternalMap hash-map bucket chain link (for internal use only). * \internal previous_ & next_ allows for bidirectional traversal. */ - class JSON_API ValueInternalLink { - public: - enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. - enum InternalFlags { flagAvailable = 0, flagUsed = 1 }; + class JSON_API ValueInternalLink { + public: + enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. + enum InternalFlags { flagAvailable = 0, flagUsed = 1 }; - ValueInternalLink(); + ValueInternalLink(); - ~ValueInternalLink(); + ~ValueInternalLink(); - Value items_[itemPerLink]; - char *keys_[itemPerLink]; - ValueInternalLink *previous_; - ValueInternalLink *next_; - }; + Value items_[itemPerLink]; + char *keys_[itemPerLink]; + ValueInternalLink *previous_; + ValueInternalLink *next_; + }; - /** \brief A linked page based hash-table implementation used internally by Value. + /** \brief A linked page based hash-table implementation used internally by Value. * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked * list in each bucket to handle collision. There is an addional twist in that * each node of the collision linked list is a page containing a fixed amount of @@ -571,79 +571,79 @@ namespace Json { * Only the last link of a bucket may contains 'available' item. The last link always * contains at least one element unless is it the bucket one very first link. */ - class JSON_API ValueInternalMap { - friend class ValueIteratorBase; - friend class Value; + class JSON_API ValueInternalMap { + friend class ValueIteratorBase; + friend class Value; - public: - typedef unsigned int HashKey; - typedef unsigned int BucketIndex; + public: + typedef unsigned int HashKey; + typedef unsigned int BucketIndex; #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - struct IteratorState { - IteratorState() : map_(0), link_(0), itemIndex_(0), bucketIndex_(0) {} - ValueInternalMap *map_; - ValueInternalLink *link_; - BucketIndex itemIndex_; - BucketIndex bucketIndex_; - }; + struct IteratorState { + IteratorState() : map_(0), link_(0), itemIndex_(0), bucketIndex_(0) {} + ValueInternalMap *map_; + ValueInternalLink *link_; + BucketIndex itemIndex_; + BucketIndex bucketIndex_; + }; #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - ValueInternalMap(); - ValueInternalMap(const ValueInternalMap &other); - ValueInternalMap &operator=(const ValueInternalMap &other); - ~ValueInternalMap(); + ValueInternalMap(); + ValueInternalMap(const ValueInternalMap &other); + ValueInternalMap &operator=(const ValueInternalMap &other); + ~ValueInternalMap(); - void swap(ValueInternalMap &other); + void swap(ValueInternalMap &other); - BucketIndex size() const; + BucketIndex size() const; - void clear(); + void clear(); - bool reserveDelta(BucketIndex growth); + bool reserveDelta(BucketIndex growth); - bool reserve(BucketIndex newItemCount); + bool reserve(BucketIndex newItemCount); - const Value *find(const char *key) const; + const Value *find(const char *key) const; - Value *find(const char *key); + Value *find(const char *key); - Value &resolveReference(const char *key, bool isStatic); + Value &resolveReference(const char *key, bool isStatic); - void remove(const char *key); + void remove(const char *key); - void doActualRemove(ValueInternalLink *link, BucketIndex index, BucketIndex bucketIndex); + void doActualRemove(ValueInternalLink *link, BucketIndex index, BucketIndex bucketIndex); - ValueInternalLink *&getLastLinkInBucket(BucketIndex bucketIndex); + ValueInternalLink *&getLastLinkInBucket(BucketIndex bucketIndex); - Value &setNewItem(const char *key, bool isStatic, ValueInternalLink *link, BucketIndex index); + Value &setNewItem(const char *key, bool isStatic, ValueInternalLink *link, BucketIndex index); - Value &unsafeAdd(const char *key, bool isStatic, HashKey hashedKey); + Value &unsafeAdd(const char *key, bool isStatic, HashKey hashedKey); - HashKey hash(const char *key) const; + HashKey hash(const char *key) const; - int compare(const ValueInternalMap &other) const; + int compare(const ValueInternalMap &other) const; - private: - void makeBeginIterator(IteratorState &it) const; - void makeEndIterator(IteratorState &it) const; - static bool equals(const IteratorState &x, const IteratorState &other); - static void increment(IteratorState &iterator); - static void incrementBucket(IteratorState &iterator); - static void decrement(IteratorState &iterator); - static const char *key(const IteratorState &iterator); - static const char *key(const IteratorState &iterator, bool &isStatic); - static Value &value(const IteratorState &iterator); - static int distance(const IteratorState &x, const IteratorState &y); + private: + void makeBeginIterator(IteratorState &it) const; + void makeEndIterator(IteratorState &it) const; + static bool equals(const IteratorState &x, const IteratorState &other); + static void increment(IteratorState &iterator); + static void incrementBucket(IteratorState &iterator); + static void decrement(IteratorState &iterator); + static const char *key(const IteratorState &iterator); + static const char *key(const IteratorState &iterator, bool &isStatic); + static Value &value(const IteratorState &iterator); + static int distance(const IteratorState &x, const IteratorState &y); - private: - ValueInternalLink *buckets_; - ValueInternalLink *tailLink_; - BucketIndex bucketsSize_; - BucketIndex itemCount_; - }; + private: + ValueInternalLink *buckets_; + ValueInternalLink *tailLink_; + BucketIndex bucketsSize_; + BucketIndex itemCount_; + }; - /** \brief A simplified deque implementation used internally by Value. + /** \brief A simplified deque implementation used internally by Value. * \internal * It is based on a list of fixed "page", each page contains a fixed number of items. * Instead of using a linked-list, a array of pointer is used for fast item look-up. @@ -654,62 +654,62 @@ namespace Json { * Insertion is amortized constant time (only the array containing the index of pointers * need to be reallocated when items are appended). */ - class JSON_API ValueInternalArray { - friend class Value; - friend class ValueIteratorBase; + class JSON_API ValueInternalArray { + friend class Value; + friend class ValueIteratorBase; - public: - enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo. - typedef Value::ArrayIndex ArrayIndex; - typedef unsigned int PageIndex; + public: + enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo. + typedef Value::ArrayIndex ArrayIndex; + typedef unsigned int PageIndex; #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - struct IteratorState // Must be a POD - { - IteratorState() : array_(0), currentPageIndex_(0), currentItemIndex_(0) {} - ValueInternalArray *array_; - Value **currentPageIndex_; - unsigned int currentItemIndex_; - }; + struct IteratorState // Must be a POD + { + IteratorState() : array_(0), currentPageIndex_(0), currentItemIndex_(0) {} + ValueInternalArray *array_; + Value **currentPageIndex_; + unsigned int currentItemIndex_; + }; #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - ValueInternalArray(); - ValueInternalArray(const ValueInternalArray &other); - ValueInternalArray &operator=(const ValueInternalArray &other); - ~ValueInternalArray(); - void swap(ValueInternalArray &other); - - void clear(); - void resize(ArrayIndex newSize); - - Value &resolveReference(ArrayIndex index); + ValueInternalArray(); + ValueInternalArray(const ValueInternalArray &other); + ValueInternalArray &operator=(const ValueInternalArray &other); + ~ValueInternalArray(); + void swap(ValueInternalArray &other); - Value *find(ArrayIndex index) const; + void clear(); + void resize(ArrayIndex newSize); - ArrayIndex size() const; + Value &resolveReference(ArrayIndex index); - int compare(const ValueInternalArray &other) const; + Value *find(ArrayIndex index) const; - private: - static bool equals(const IteratorState &x, const IteratorState &other); - static void increment(IteratorState &iterator); - static void decrement(IteratorState &iterator); - static Value &dereference(const IteratorState &iterator); - static Value &unsafeDereference(const IteratorState &iterator); - static int distance(const IteratorState &x, const IteratorState &y); - static ArrayIndex indexOf(const IteratorState &iterator); - void makeBeginIterator(IteratorState &it) const; - void makeEndIterator(IteratorState &it) const; - void makeIterator(IteratorState &it, ArrayIndex index) const; + ArrayIndex size() const; - void makeIndexValid(ArrayIndex index); + int compare(const ValueInternalArray &other) const; - Value **pages_; - ArrayIndex size_; - PageIndex pageCount_; - }; + private: + static bool equals(const IteratorState &x, const IteratorState &other); + static void increment(IteratorState &iterator); + static void decrement(IteratorState &iterator); + static Value &dereference(const IteratorState &iterator); + static Value &unsafeDereference(const IteratorState &iterator); + static int distance(const IteratorState &x, const IteratorState &y); + static ArrayIndex indexOf(const IteratorState &iterator); + void makeBeginIterator(IteratorState &it) const; + void makeEndIterator(IteratorState &it) const; + void makeIterator(IteratorState &it, ArrayIndex index) const; + + void makeIndexValid(ArrayIndex index); + + Value **pages_; + ArrayIndex size_; + PageIndex pageCount_; + }; - /** \brief Experimental: do not use. Allocator to customize Value internal array. + /** \brief Experimental: do not use. Allocator to customize Value internal array. * Below is an example of a simple implementation (actual implementation use * memory pool). \code @@ -768,13 +768,13 @@ class DefaultValueArrayAllocator : public ValueArrayAllocator }; \endcode */ - class JSON_API ValueArrayAllocator { - public: - virtual ~ValueArrayAllocator(); - virtual ValueInternalArray *newArray() = 0; - virtual ValueInternalArray *newArrayCopy(const ValueInternalArray &other) = 0; - virtual void destructArray(ValueInternalArray *array) = 0; - /** \brief Reallocate array page index. + class JSON_API ValueArrayAllocator { + public: + virtual ~ValueArrayAllocator(); + virtual ValueInternalArray *newArray() = 0; + virtual ValueInternalArray *newArrayCopy(const ValueInternalArray &other) = 0; + virtual void destructArray(ValueInternalArray *array) = 0; + /** \brief Reallocate array page index. * Reallocates an array of pointer on each page. * \param indexes [input] pointer on the current index. May be \c NULL. * [output] pointer on the new index of at least @@ -785,179 +785,179 @@ class DefaultValueArrayAllocator : public ValueArrayAllocator * \param minNewIndexCount Minimum number of page the new index must be able to * handle. */ - virtual void reallocateArrayPageIndex(Value **&indexes, - ValueInternalArray::PageIndex &indexCount, - ValueInternalArray::PageIndex minNewIndexCount) = 0; - virtual void releaseArrayPageIndex(Value **indexes, ValueInternalArray::PageIndex indexCount) = 0; - virtual Value *allocateArrayPage() = 0; - virtual void releaseArrayPage(Value *value) = 0; - }; + virtual void reallocateArrayPageIndex(Value **&indexes, + ValueInternalArray::PageIndex &indexCount, + ValueInternalArray::PageIndex minNewIndexCount) = 0; + virtual void releaseArrayPageIndex(Value **indexes, ValueInternalArray::PageIndex indexCount) = 0; + virtual Value *allocateArrayPage() = 0; + virtual void releaseArrayPage(Value *value) = 0; + }; #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - /** \brief base class for Value iterators. + /** \brief base class for Value iterators. * */ - class ValueIteratorBase { - public: - typedef unsigned int size_t; - typedef int difference_type; - typedef ValueIteratorBase SelfType; + class ValueIteratorBase { + public: + typedef unsigned int size_t; + typedef int difference_type; + typedef ValueIteratorBase SelfType; - ValueIteratorBase(); + ValueIteratorBase(); #ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueIteratorBase(const Value::ObjectValues::iterator ¤t); + explicit ValueIteratorBase(const Value::ObjectValues::iterator ¤t); #else - ValueIteratorBase(const ValueInternalArray::IteratorState &state); - ValueIteratorBase(const ValueInternalMap::IteratorState &state); + ValueIteratorBase(const ValueInternalArray::IteratorState &state); + ValueIteratorBase(const ValueInternalMap::IteratorState &state); #endif - bool operator==(const SelfType &other) const { return isEqual(other); } + bool operator==(const SelfType &other) const { return isEqual(other); } - bool operator!=(const SelfType &other) const { return !isEqual(other); } + bool operator!=(const SelfType &other) const { return !isEqual(other); } - difference_type operator-(const SelfType &other) const { return computeDistance(other); } + difference_type operator-(const SelfType &other) const { return computeDistance(other); } - /// Return either the index or the member name of the referenced value as a Value. - Value key() const; + /// Return either the index or the member name of the referenced value as a Value. + Value key() const; - /// Return the index of the referenced Value. -1 if it is not an arrayValue. - UInt index() const; + /// Return the index of the referenced Value. -1 if it is not an arrayValue. + UInt index() const; - /// Return the member name of the referenced Value. "" if it is not an objectValue. - const char *memberName() const; + /// Return the member name of the referenced Value. "" if it is not an objectValue. + const char *memberName() const; - protected: - Value &deref() const; + protected: + Value &deref() const; - void increment(); + void increment(); - void decrement(); + void decrement(); - difference_type computeDistance(const SelfType &other) const; + difference_type computeDistance(const SelfType &other) const; - bool isEqual(const SelfType &other) const; + bool isEqual(const SelfType &other) const; - void copy(const SelfType &other); + void copy(const SelfType &other); - private: + private: #ifndef JSON_VALUE_USE_INTERNAL_MAP - Value::ObjectValues::iterator current_; - // Indicates that iterator is for a null value. - bool isNull_; + Value::ObjectValues::iterator current_; + // Indicates that iterator is for a null value. + bool isNull_; #else - union { - ValueInternalArray::IteratorState array_; - ValueInternalMap::IteratorState map_; - } iterator_; - bool isArray_; + union { + ValueInternalArray::IteratorState array_; + ValueInternalMap::IteratorState map_; + } iterator_; + bool isArray_; #endif - }; + }; - /** \brief const iterator for object and array value. + /** \brief const iterator for object and array value. * */ - class ValueConstIterator : public ValueIteratorBase { - friend class Value; + class ValueConstIterator : public ValueIteratorBase { + friend class Value; - public: - typedef unsigned int size_t; - typedef int difference_type; - typedef const Value &reference; - typedef const Value *pointer; - typedef ValueConstIterator SelfType; + public: + typedef unsigned int size_t; + typedef int difference_type; + typedef const Value &reference; + typedef const Value *pointer; + typedef ValueConstIterator SelfType; - ValueConstIterator(); + ValueConstIterator(); - private: - /*! \internal Use by Value to create an iterator. + private: + /*! \internal Use by Value to create an iterator. */ #ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueConstIterator(const Value::ObjectValues::iterator ¤t); + explicit ValueConstIterator(const Value::ObjectValues::iterator ¤t); #else - ValueConstIterator(const ValueInternalArray::IteratorState &state); - ValueConstIterator(const ValueInternalMap::IteratorState &state); + ValueConstIterator(const ValueInternalArray::IteratorState &state); + ValueConstIterator(const ValueInternalMap::IteratorState &state); #endif - public: - SelfType &operator=(const ValueIteratorBase &other); - - SelfType operator++(int) { - SelfType temp(*this); - ++*this; - return temp; - } - - SelfType operator--(int) { - SelfType temp(*this); - --*this; - return temp; - } - - SelfType &operator--() { - decrement(); - return *this; - } - - SelfType &operator++() { - increment(); - return *this; - } - - reference operator*() const { return deref(); } - }; - - /** \brief Iterator for object and array value. + public: + SelfType &operator=(const ValueIteratorBase &other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType &operator--() { + decrement(); + return *this; + } + + SelfType &operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + }; + + /** \brief Iterator for object and array value. */ - class ValueIterator : public ValueIteratorBase { - friend class Value; - - public: - typedef unsigned int size_t; - typedef int difference_type; - typedef Value &reference; - typedef Value *pointer; - typedef ValueIterator SelfType; - - ValueIterator(); - ValueIterator(const ValueConstIterator &other); - ValueIterator(const ValueIterator &other); - - private: - /*! \internal Use by Value to create an iterator. + class ValueIterator : public ValueIteratorBase { + friend class Value; + + public: + typedef unsigned int size_t; + typedef int difference_type; + typedef Value &reference; + typedef Value *pointer; + typedef ValueIterator SelfType; + + ValueIterator(); + ValueIterator(const ValueConstIterator &other); + ValueIterator(const ValueIterator &other); + + private: + /*! \internal Use by Value to create an iterator. */ #ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueIterator(const Value::ObjectValues::iterator ¤t); + explicit ValueIterator(const Value::ObjectValues::iterator ¤t); #else - ValueIterator(const ValueInternalArray::IteratorState &state); - ValueIterator(const ValueInternalMap::IteratorState &state); + ValueIterator(const ValueInternalArray::IteratorState &state); + ValueIterator(const ValueInternalMap::IteratorState &state); #endif - public: - SelfType &operator=(const SelfType &other); - - SelfType operator++(int) { - SelfType temp(*this); - ++*this; - return temp; - } - - SelfType operator--(int) { - SelfType temp(*this); - --*this; - return temp; - } - - SelfType &operator--() { - decrement(); - return *this; - } - - SelfType &operator++() { - increment(); - return *this; - } - - reference operator*() const { return deref(); } - }; - -} // namespace Json -} // namespace jsoncollector + public: + SelfType &operator=(const SelfType &other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType &operator--() { + decrement(); + return *this; + } + + SelfType &operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + }; + + } // namespace Json +} // namespace jsoncollector #endif // CPPTL_JSON_H_INCLUDED diff --git a/EventFilter/Utilities/interface/writer.h b/EventFilter/Utilities/interface/writer.h index 9dbde0852ec63..14261dca7dd5a 100644 --- a/EventFilter/Utilities/interface/writer.h +++ b/EventFilter/Utilities/interface/writer.h @@ -7,43 +7,43 @@ #include namespace jsoncollector { -namespace Json { + namespace Json { - class Value; + class Value; - /** \brief Abstract class for writers. + /** \brief Abstract class for writers. */ - class JSON_API Writer { - public: - virtual ~Writer(); + class JSON_API Writer { + public: + virtual ~Writer(); - virtual std::string write(const Value &root) = 0; - }; + virtual std::string write(const Value &root) = 0; + }; - /** \brief Outputs a Value in JSON format without formatting (not human friendly). + /** \brief Outputs a Value in JSON format without formatting (not human friendly). * * The JSON document is written in a single line. It is not intended for 'human' consumption, * but may be usefull to support feature such as RPC where bandwith is limited. * \sa Reader, Value */ - class JSON_API FastWriter : public Writer { - public: - FastWriter(); - ~FastWriter() override {} + class JSON_API FastWriter : public Writer { + public: + FastWriter(); + ~FastWriter() override {} - void enableYAMLCompatibility(); + void enableYAMLCompatibility(); - public: // overridden from Writer - std::string write(const Value &root) override; + public: // overridden from Writer + std::string write(const Value &root) override; - private: - void writeValue(const Value &value); + private: + void writeValue(const Value &value); - std::string document_; - bool yamlCompatiblityEnabled_; - }; + std::string document_; + bool yamlCompatiblityEnabled_; + }; - /** \brief Writes a Value in JSON format in a human friendly way. + /** \brief Writes a Value in JSON format in a human friendly way. * * The rules for line break and indent are as follow: * - Object value: @@ -61,43 +61,43 @@ namespace Json { * * \sa Reader, Value, Value::setComment() */ - class JSON_API StyledWriter : public Writer { - public: - StyledWriter(); - ~StyledWriter() override {} + class JSON_API StyledWriter : public Writer { + public: + StyledWriter(); + ~StyledWriter() override {} - public: // overridden from Writer - /** \brief Serialize a Value in JSON format. + public: // overridden from Writer + /** \brief Serialize a Value in JSON format. * \param root Value to serialize. * \return String containing the JSON document that represents the root value. */ - std::string write(const Value &root) override; - - private: - void writeValue(const Value &value); - void writeArrayValue(const Value &value); - bool isMultineArray(const Value &value); - void pushValue(const std::string &value); - void writeIndent(); - void writeWithIndent(const std::string &value); - void indent(); - void unindent(); - void writeCommentBeforeValue(const Value &root); - void writeCommentAfterValueOnSameLine(const Value &root); - bool hasCommentForValue(const Value &value); - static std::string normalizeEOL(const std::string &text); - - typedef std::vector ChildValues; - - ChildValues childValues_; - std::string document_; - std::string indentString_; - int rightMargin_; - int indentSize_; - bool addChildValues_; - }; - - /** \brief Writes a Value in JSON format in a human friendly way, + std::string write(const Value &root) override; + + private: + void writeValue(const Value &value); + void writeArrayValue(const Value &value); + bool isMultineArray(const Value &value); + void pushValue(const std::string &value); + void writeIndent(); + void writeWithIndent(const std::string &value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value &root); + void writeCommentAfterValueOnSameLine(const Value &root); + bool hasCommentForValue(const Value &value); + static std::string normalizeEOL(const std::string &text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::string document_; + std::string indentString_; + int rightMargin_; + int indentSize_; + bool addChildValues_; + }; + + /** \brief Writes a Value in JSON format in a human friendly way, to a stream rather than to a string. * * The rules for line break and indent are as follow: @@ -117,54 +117,54 @@ namespace Json { * \param indentation Each level will be indented by this amount extra. * \sa Reader, Value, Value::setComment() */ - class JSON_API StyledStreamWriter { - public: - StyledStreamWriter(std::string indentation = "\t"); - ~StyledStreamWriter() {} + class JSON_API StyledStreamWriter { + public: + StyledStreamWriter(std::string indentation = "\t"); + ~StyledStreamWriter() {} - public: - /** \brief Serialize a Value in JSON format. + public: + /** \brief Serialize a Value in JSON format. * \param out Stream to write to. (Can be ostringstream, e.g.) * \param root Value to serialize. * \note There is no point in deriving from Writer, since write() should not return a value. */ - void write(std::ostream &out, const Value &root); - - private: - void writeValue(const Value &value); - void writeArrayValue(const Value &value); - bool isMultineArray(const Value &value); - void pushValue(const std::string &value); - void writeIndent(); - void writeWithIndent(const std::string &value); - void indent(); - void unindent(); - void writeCommentBeforeValue(const Value &root); - void writeCommentAfterValueOnSameLine(const Value &root); - bool hasCommentForValue(const Value &value); - static std::string normalizeEOL(const std::string &text); - - typedef std::vector ChildValues; - - ChildValues childValues_; - std::ostream *document_; - std::string indentString_; - int rightMargin_; - std::string indentation_; - bool addChildValues_; - }; - - std::string JSON_API valueToString(Int value); - std::string JSON_API valueToString(UInt value); - std::string JSON_API valueToString(double value); - std::string JSON_API valueToString(bool value); - std::string JSON_API valueToQuotedString(const char *value); - - /// \brief Output using the StyledStreamWriter. - /// \see Json::operator>>() - std::ostream &operator<<(std::ostream &, const Value &root); - -} // namespace Json -} // namespace jsoncollector + void write(std::ostream &out, const Value &root); + + private: + void writeValue(const Value &value); + void writeArrayValue(const Value &value); + bool isMultineArray(const Value &value); + void pushValue(const std::string &value); + void writeIndent(); + void writeWithIndent(const std::string &value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value &root); + void writeCommentAfterValueOnSameLine(const Value &root); + bool hasCommentForValue(const Value &value); + static std::string normalizeEOL(const std::string &text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::ostream *document_; + std::string indentString_; + int rightMargin_; + std::string indentation_; + bool addChildValues_; + }; + + std::string JSON_API valueToString(Int value); + std::string JSON_API valueToString(UInt value); + std::string JSON_API valueToString(double value); + std::string JSON_API valueToString(bool value); + std::string JSON_API valueToQuotedString(const char *value); + + /// \brief Output using the StyledStreamWriter. + /// \see Json::operator>>() + std::ostream &operator<<(std::ostream &, const Value &root); + + } // namespace Json +} // namespace jsoncollector #endif // JSON_WRITER_H_INCLUDED diff --git a/EventFilter/Utilities/src/json_reader.cpp b/EventFilter/Utilities/src/json_reader.cpp index 31c3748b64b44..2b24083e14992 100644 --- a/EventFilter/Utilities/src/json_reader.cpp +++ b/EventFilter/Utilities/src/json_reader.cpp @@ -12,670 +12,670 @@ #endif namespace jsoncollector { -namespace Json { + namespace Json { - // Implementation of class Features - // //////////////////////////////// + // Implementation of class Features + // //////////////////////////////// - Features::Features() : allowComments_(true), strictRoot_(false) {} + Features::Features() : allowComments_(true), strictRoot_(false) {} - Features Features::all() { return Features(); } + Features Features::all() { return Features(); } - Features Features::strictMode() { - Features features; - features.allowComments_ = false; - features.strictRoot_ = true; - return features; - } + Features Features::strictMode() { + Features features; + features.allowComments_ = false; + features.strictRoot_ = true; + return features; + } - // Implementation of class Reader - // //////////////////////////////// + // Implementation of class Reader + // //////////////////////////////// - static inline bool in(Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4) { - return c == c1 || c == c2 || c == c3 || c == c4; - } + static inline bool in(Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4) { + return c == c1 || c == c2 || c == c3 || c == c4; + } - static inline bool in( - Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5) { - return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; - } + static inline bool in( + Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5) { + return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; + } - static bool containsNewLine(Reader::Location begin, Reader::Location end) { - for (; begin < end; ++begin) - if (*begin == '\n' || *begin == '\r') - return true; - return false; - } - - static std::string codePointToUTF8(unsigned int cp) { - std::string result; - - // based on description from http://en.wikipedia.org/wiki/UTF-8 - - if (cp <= 0x7f) { - result.resize(1); - result[0] = static_cast(cp); - } else if (cp <= 0x7FF) { - result.resize(2); - result[1] = static_cast(0x80 | (0x3f & cp)); - result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); - } else if (cp <= 0xFFFF) { - result.resize(3); - result[2] = static_cast(0x80 | (0x3f & cp)); - result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); - result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); - } else if (cp <= 0x10FFFF) { - result.resize(4); - result[3] = static_cast(0x80 | (0x3f & cp)); - result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); - result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); - result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); - } - - return result; - } - - // Class Reader - // ////////////////////////////////////////////////////////////////// - - Reader::Reader() : features_(Features::all()) {} - - Reader::Reader(const Features &features) : features_(features) {} - - bool Reader::parse(const std::string &document, Value &root, bool collectComments) { - document_ = document; - const char *begin = document_.c_str(); - const char *end = begin + document_.length(); - return parse(begin, end, root, collectComments); - } - - bool Reader::parse(std::istream &sin, Value &root, bool collectComments) { - //std::istream_iterator begin(sin); - //std::istream_iterator end; - // Those would allow streamed input from a file, if parse() were a - // template function. - - // Since std::string is reference-counted, this at least does not - // create an extra copy. - std::string doc; - std::getline(sin, doc, (char)EOF); - return parse(doc, root, collectComments); - } - - bool Reader::parse(const char *beginDoc, const char *endDoc, Value &root, bool collectComments) { - if (!features_.allowComments_) { - collectComments = false; - } - - begin_ = beginDoc; - end_ = endDoc; - collectComments_ = collectComments; - current_ = begin_; - lastValueEnd_ = nullptr; - lastValue_ = nullptr; - commentsBefore_ = ""; - errors_.clear(); - while (!nodes_.empty()) - nodes_.pop(); - nodes_.push(&root); - - bool successful = readValue(); - Token token; - skipCommentTokens(token); - if (collectComments_ && !commentsBefore_.empty()) - root.setComment(commentsBefore_, commentAfter); - if (features_.strictRoot_) { - if (!root.isArray() && !root.isObject()) { - // Set error location to start of doc, ideally should be first token found in doc - token.type_ = tokenError; - token.start_ = beginDoc; - token.end_ = endDoc; - addError("A valid JSON document must be either an array or an object value.", token); - return false; + static bool containsNewLine(Reader::Location begin, Reader::Location end) { + for (; begin < end; ++begin) + if (*begin == '\n' || *begin == '\r') + return true; + return false; + } + + static std::string codePointToUTF8(unsigned int cp) { + std::string result; + + // based on description from http://en.wikipedia.org/wiki/UTF-8 + + if (cp <= 0x7f) { + result.resize(1); + result[0] = static_cast(cp); + } else if (cp <= 0x7FF) { + result.resize(2); + result[1] = static_cast(0x80 | (0x3f & cp)); + result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); + } else if (cp <= 0xFFFF) { + result.resize(3); + result[2] = static_cast(0x80 | (0x3f & cp)); + result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); + result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); + } else if (cp <= 0x10FFFF) { + result.resize(4); + result[3] = static_cast(0x80 | (0x3f & cp)); + result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); + result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); } + + return result; } - return successful; - } - bool Reader::readValue() { - Token token; - skipCommentTokens(token); - bool successful = true; + // Class Reader + // ////////////////////////////////////////////////////////////////// - if (collectComments_ && !commentsBefore_.empty()) { - currentValue().setComment(commentsBefore_, commentBefore); - commentsBefore_ = ""; + Reader::Reader() : features_(Features::all()) {} + + Reader::Reader(const Features &features) : features_(features) {} + + bool Reader::parse(const std::string &document, Value &root, bool collectComments) { + document_ = document; + const char *begin = document_.c_str(); + const char *end = begin + document_.length(); + return parse(begin, end, root, collectComments); } - switch (token.type_) { - case tokenObjectBegin: - successful = readObject(token); - break; - case tokenArrayBegin: - successful = readArray(token); - break; - case tokenNumber: - successful = decodeNumber(token); - break; - case tokenString: - successful = decodeString(token); - break; - case tokenTrue: - currentValue() = true; - break; - case tokenFalse: - currentValue() = false; - break; - case tokenNull: - currentValue() = Value(); - break; - default: - return addError("Syntax error: value, object or array expected.", token); - } - - if (collectComments_) { - lastValueEnd_ = current_; - lastValue_ = ¤tValue(); - } - - return successful; - } - - void Reader::skipCommentTokens(Token &token) { - if (features_.allowComments_) { - do { - readToken(token); - } while (token.type_ == tokenComment); - } else { - readToken(token); + bool Reader::parse(std::istream &sin, Value &root, bool collectComments) { + //std::istream_iterator begin(sin); + //std::istream_iterator end; + // Those would allow streamed input from a file, if parse() were a + // template function. + + // Since std::string is reference-counted, this at least does not + // create an extra copy. + std::string doc; + std::getline(sin, doc, (char)EOF); + return parse(doc, root, collectComments); } - } - - bool Reader::expectToken(TokenType type, Token &token, const char *message) { - readToken(token); - if (token.type_ != type) - return addError(message, token); - return true; - } - - bool Reader::readToken(Token &token) { - skipSpaces(); - token.start_ = current_; - Char c = getNextChar(); - bool ok = true; - switch (c) { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = readString(); - break; - case '/': - token.type_ = tokenComment; - ok = readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - token.type_ = tokenNumber; - readNumber(); - break; - case 't': - token.type_ = tokenTrue; - ok = match("rue", 3); - break; - case 'f': - token.type_ = tokenFalse; - ok = match("alse", 4); - break; - case 'n': - token.type_ = tokenNull; - ok = match("ull", 3); - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: - ok = false; - break; - } - if (!ok) - token.type_ = tokenError; - token.end_ = current_; - return true; - } - - void Reader::skipSpaces() { - while (current_ != end_) { - Char c = *current_; - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - ++current_; - else - break; + + bool Reader::parse(const char *beginDoc, const char *endDoc, Value &root, bool collectComments) { + if (!features_.allowComments_) { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = nullptr; + lastValue_ = nullptr; + commentsBefore_ = ""; + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + bool successful = readValue(); + Token token; + skipCommentTokens(token); + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { + if (!root.isArray() && !root.isObject()) { + // Set error location to start of doc, ideally should be first token found in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError("A valid JSON document must be either an array or an object value.", token); + return false; + } + } + return successful; } - } - bool Reader::match(Location pattern, int patternLength) { - if (end_ - current_ < patternLength) - return false; - int index = patternLength; - while (index--) - if (current_[index] != pattern[index]) - return false; - current_ += patternLength; - return true; - } - - bool Reader::readComment() { - Location commentBegin = current_ - 1; - Char c = getNextChar(); - bool successful = false; - if (c == '*') - successful = readCStyleComment(); - else if (c == '/') - successful = readCppStyleComment(); - if (!successful) - return false; + bool Reader::readValue() { + Token token; + skipCommentTokens(token); + bool successful = true; + + if (collectComments_ && !commentsBefore_.empty()) { + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_ = ""; + } + + switch (token.type_) { + case tokenObjectBegin: + successful = readObject(token); + break; + case tokenArrayBegin: + successful = readArray(token); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: + currentValue() = true; + break; + case tokenFalse: + currentValue() = false; + break; + case tokenNull: + currentValue() = Value(); + break; + default: + return addError("Syntax error: value, object or array expected.", token); + } - if (collectComments_) { - CommentPlacement placement = commentBefore; - if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { - if (c != '*' || !containsNewLine(commentBegin, current_)) - placement = commentAfterOnSameLine; + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); } - addComment(commentBegin, current_, placement); + return successful; } - return true; - } - void Reader::addComment(Location begin, Location end, CommentPlacement placement) { - assert(collectComments_); - if (placement == commentAfterOnSameLine) { - assert(lastValue_ != nullptr); - lastValue_->setComment(std::string(begin, end), placement); - } else { - if (!commentsBefore_.empty()) - commentsBefore_ += "\n"; - commentsBefore_ += std::string(begin, end); + void Reader::skipCommentTokens(Token &token) { + if (features_.allowComments_) { + do { + readToken(token); + } while (token.type_ == tokenComment); + } else { + readToken(token); + } } - } - bool Reader::readCStyleComment() { - while (current_ != end_) { + bool Reader::expectToken(TokenType type, Token &token, const char *message) { + readToken(token); + if (token.type_ != type) + return addError(message, token); + return true; + } + + bool Reader::readToken(Token &token) { + skipSpaces(); + token.start_ = current_; Char c = getNextChar(); - if (c == '*' && *current_ == '/') - break; + bool ok = true; + switch (c) { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + token.type_ = tokenNumber; + readNumber(); + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if (!ok) + token.type_ = tokenError; + token.end_ = current_; + return true; + } + + void Reader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + ++current_; + else + break; + } + } + + bool Reader::match(Location pattern, int patternLength) { + if (end_ - current_ < patternLength) + return false; + int index = patternLength; + while (index--) + if (current_[index] != pattern[index]) + return false; + current_ += patternLength; + return true; } - return getNextChar() == '/'; - } - bool Reader::readCppStyleComment() { - while (current_ != end_) { + bool Reader::readComment() { + Location commentBegin = current_ - 1; Char c = getNextChar(); - if (c == '\r' || c == '\n') - break; - } - return true; - } - - void Reader::readNumber() { - while (current_ != end_) { - if (!(*current_ >= '0' && *current_ <= '9') && !in(*current_, '.', 'e', 'E', '+', '-')) - break; - ++current_; - } - } - - bool Reader::readString() { - Char c = 0; - while (current_ != end_) { - c = getNextChar(); - if (c == '\\') - getNextChar(); - else if (c == '"') - break; - } - return c == '"'; - } - - bool Reader::readObject(Token &tokenStart) { - Token tokenName; - std::string name; - currentValue() = Value(objectValue); - while (readToken(tokenName)) { - bool initialTokenOk = true; - while (tokenName.type_ == tokenComment && initialTokenOk) - initialTokenOk = readToken(tokenName); - if (!initialTokenOk) - break; - if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object - return true; - if (tokenName.type_ != tokenString) - break; + bool successful = false; + if (c == '*') + successful = readCStyleComment(); + else if (c == '/') + successful = readCppStyleComment(); + if (!successful) + return false; - name = ""; - if (!decodeString(tokenName, name)) - return recoverFromError(tokenObjectEnd); + if (collectComments_) { + CommentPlacement placement = commentBefore; + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) + placement = commentAfterOnSameLine; + } - Token colon; - if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover("Missing ':' after object member name", colon, tokenObjectEnd); + addComment(commentBegin, current_, placement); } - Value &value = currentValue()[name]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenObjectEnd); - - Token comma; - if (!readToken(comma) || - (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && comma.type_ != tokenComment)) { - return addErrorAndRecover("Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + return true; + } + + void Reader::addComment(Location begin, Location end, CommentPlacement placement) { + assert(collectComments_); + if (placement == commentAfterOnSameLine) { + assert(lastValue_ != nullptr); + lastValue_->setComment(std::string(begin, end), placement); + } else { + if (!commentsBefore_.empty()) + commentsBefore_ += "\n"; + commentsBefore_ += std::string(begin, end); } - bool finalizeTokenOk = true; - while (comma.type_ == tokenComment && finalizeTokenOk) - finalizeTokenOk = readToken(comma); - if (comma.type_ == tokenObjectEnd) - return true; } - return addErrorAndRecover("Missing '}' or object member name", tokenName, tokenObjectEnd); - } - bool Reader::readArray(Token &tokenStart) { - currentValue() = Value(arrayValue); - skipSpaces(); - if (*current_ == ']') // empty array - { - Token endArray; - readToken(endArray); + bool Reader::readCStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') + break; + } + return getNextChar() == '/'; + } + + bool Reader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '\r' || c == '\n') + break; + } return true; } - int index = 0; - while (true) { - Value &value = currentValue()[index++]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenArrayEnd); - Token token; - // Accept Comment after last item in the array. - ok = readToken(token); - while (token.type_ == tokenComment && ok) { + void Reader::readNumber() { + while (current_ != end_) { + if (!(*current_ >= '0' && *current_ <= '9') && !in(*current_, '.', 'e', 'E', '+', '-')) + break; + ++current_; + } + } + + bool Reader::readString() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '"') + break; + } + return c == '"'; + } + + bool Reader::readObject(Token &tokenStart) { + Token tokenName; + std::string name; + currentValue() = Value(objectValue); + while (readToken(tokenName)) { + bool initialTokenOk = true; + while (tokenName.type_ == tokenComment && initialTokenOk) + initialTokenOk = readToken(tokenName); + if (!initialTokenOk) + break; + if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + return true; + if (tokenName.type_ != tokenString) + break; + + name = ""; + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + + Token colon; + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover("Missing ':' after object member name", colon, tokenObjectEnd); + } + Value &value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenObjectEnd); + + Token comma; + if (!readToken(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && comma.type_ != tokenComment)) { + return addErrorAndRecover("Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + } + bool finalizeTokenOk = true; + while (comma.type_ == tokenComment && finalizeTokenOk) + finalizeTokenOk = readToken(comma); + if (comma.type_ == tokenObjectEnd) + return true; + } + return addErrorAndRecover("Missing '}' or object member name", tokenName, tokenObjectEnd); + } + + bool Reader::readArray(Token &tokenStart) { + currentValue() = Value(arrayValue); + skipSpaces(); + if (*current_ == ']') // empty array + { + Token endArray; + readToken(endArray); + return true; + } + int index = 0; + while (true) { + Value &value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenArrayEnd); + + Token token; + // Accept Comment after last item in the array. ok = readToken(token); + while (token.type_ == tokenComment && ok) { + ok = readToken(token); + } + bool badTokenType = (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); + if (!ok || badTokenType) { + return addErrorAndRecover("Missing ',' or ']' in array declaration", token, tokenArrayEnd); + } + if (token.type_ == tokenArrayEnd) + break; } - bool badTokenType = (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); - if (!ok || badTokenType) { - return addErrorAndRecover("Missing ',' or ']' in array declaration", token, tokenArrayEnd); + return true; + } + + bool Reader::decodeNumber(Token &token) { + bool isDouble = false; + for (Location inspect = token.start_; inspect != token.end_; ++inspect) { + isDouble = isDouble || in(*inspect, '.', 'e', 'E', '+') || (*inspect == '-' && inspect != token.start_); } - if (token.type_ == tokenArrayEnd) - break; - } - return true; - } - - bool Reader::decodeNumber(Token &token) { - bool isDouble = false; - for (Location inspect = token.start_; inspect != token.end_; ++inspect) { - isDouble = isDouble || in(*inspect, '.', 'e', 'E', '+') || (*inspect == '-' && inspect != token.start_); - } - if (isDouble) - return decodeDouble(token); - Location current = token.start_; - bool isNegative = *current == '-'; - if (isNegative) - ++current; - Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt) : Value::maxUInt) / 10; - Value::UInt value = 0; - while (current < token.end_) { - Char c = *current++; - if (c < '0' || c > '9') - return addError("'" + std::string(token.start_, token.end_) + "' is not a number.", token); - if (value >= threshold) + if (isDouble) return decodeDouble(token); - value = value * 10 + Value::UInt(c - '0'); + Location current = token.start_; + bool isNegative = *current == '-'; + if (isNegative) + ++current; + Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt) : Value::maxUInt) / 10; + Value::UInt value = 0; + while (current < token.end_) { + Char c = *current++; + if (c < '0' || c > '9') + return addError("'" + std::string(token.start_, token.end_) + "' is not a number.", token); + if (value >= threshold) + return decodeDouble(token); + value = value * 10 + Value::UInt(c - '0'); + } + if (isNegative) + currentValue() = -Value::Int(value); + else if (value <= Value::UInt(Value::maxInt)) + currentValue() = Value::Int(value); + else + currentValue() = value; + return true; } - if (isNegative) - currentValue() = -Value::Int(value); - else if (value <= Value::UInt(Value::maxInt)) - currentValue() = Value::Int(value); - else + + bool Reader::decodeDouble(Token &token) { + double value = 0; + const int bufferSize = 32; + int count; + int length = int(token.end_ - token.start_); + if (length <= bufferSize) { + Char buffer[bufferSize]; + memcpy(buffer, token.start_, length); + buffer[length] = 0; + count = sscanf(buffer, "%lf", &value); + } else { + std::string buffer(token.start_, token.end_); + count = sscanf(buffer.c_str(), "%lf", &value); + } + + if (count != 1) + return addError("'" + std::string(token.start_, token.end_) + "' is not a number.", token); currentValue() = value; - return true; - } - - bool Reader::decodeDouble(Token &token) { - double value = 0; - const int bufferSize = 32; - int count; - int length = int(token.end_ - token.start_); - if (length <= bufferSize) { - Char buffer[bufferSize]; - memcpy(buffer, token.start_, length); - buffer[length] = 0; - count = sscanf(buffer, "%lf", &value); - } else { - std::string buffer(token.start_, token.end_); - count = sscanf(buffer.c_str(), "%lf", &value); - } - - if (count != 1) - return addError("'" + std::string(token.start_, token.end_) + "' is not a number.", token); - currentValue() = value; - return true; - } - - bool Reader::decodeString(Token &token) { - std::string decoded; - if (!decodeString(token, decoded)) - return false; - currentValue() = decoded; - return true; - } - - bool Reader::decodeString(Token &token, std::string &decoded) { - decoded.reserve(token.end_ - token.start_ - 2); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' - while (current != end) { - Char c = *current++; - if (c == '"') - break; - else if (c == '\\') { - if (current == end) - return addError("Empty escape sequence in string", token, current); - Char escape = *current++; - switch (escape) { - case '"': - decoded += '"'; - break; - case '/': - decoded += '/'; - break; - case '\\': - decoded += '\\'; - break; - case 'b': - decoded += '\b'; - break; - case 'f': - decoded += '\f'; - break; - case 'n': - decoded += '\n'; - break; - case 'r': - decoded += '\r'; - break; - case 't': - decoded += '\t'; - break; - case 'u': { - unsigned int unicode; - if (!decodeUnicodeCodePoint(token, current, end, unicode)) - return false; - decoded += codePointToUTF8(unicode); - } break; - default: - return addError("Bad escape sequence in string", token, current); + return true; + } + + bool Reader::decodeString(Token &token) { + std::string decoded; + if (!decodeString(token, decoded)) + return false; + currentValue() = decoded; + return true; + } + + bool Reader::decodeString(Token &token, std::string &decoded) { + decoded.reserve(token.end_ - token.start_ - 2); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + while (current != end) { + Char c = *current++; + if (c == '"') + break; + else if (c == '\\') { + if (current == end) + return addError("Empty escape sequence in string", token, current); + Char escape = *current++; + switch (escape) { + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); + } + } else { + decoded += c; } - } else { - decoded += c; } + return true; } - return true; - } - bool Reader::decodeUnicodeCodePoint(Token &token, Location ¤t, Location end, unsigned int &unicode) { - if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) - return false; - if (unicode >= 0xD800 && unicode <= 0xDBFF) { - // surrogate pairs - if (end - current < 6) - return addError("additional six characters expected to parse unicode surrogate pair.", token, current); - unsigned int surrogatePair; - if (*(current++) == '\\' && *(current++) == 'u') { - if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { - unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + bool Reader::decodeUnicodeCodePoint(Token &token, Location ¤t, Location end, unsigned int &unicode) { + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) { + // surrogate pairs + if (end - current < 6) + return addError("additional six characters expected to parse unicode surrogate pair.", token, current); + unsigned int surrogatePair; + if (*(current++) == '\\' && *(current++) == 'u') { + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } else + return false; } else - return false; - } else - return addError( - "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current); - } - return true; - } - - bool Reader::decodeUnicodeEscapeSequence(Token &token, Location ¤t, Location end, unsigned int &unicode) { - if (end - current < 4) - return addError("Bad unicode escape sequence in string: four digits expected.", token, current); - unicode = 0; - for (int index = 0; index < 4; ++index) { - Char c = *current++; - unicode *= 16; - if (c >= '0' && c <= '9') - unicode += c - '0'; - else if (c >= 'a' && c <= 'f') - unicode += c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - unicode += c - 'A' + 10; - else - return addError("Bad unicode escape sequence in string: hexadecimal digit expected.", token, current); - } - return true; - } - - bool Reader::addError(const std::string &message, Token &token, Location extra) { - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = extra; - errors_.push_back(info); - return false; - } - - bool Reader::recoverFromError(TokenType skipUntilToken) { - int errorCount = int(errors_.size()); - Token skip; - while (true) { - if (!readToken(skip)) - errors_.resize(errorCount); // discard errors caused by recovery - if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) - break; - } - errors_.resize(errorCount); - return false; - } - - bool Reader::addErrorAndRecover(const std::string &message, Token &token, TokenType skipUntilToken) { - addError(message, token); - return recoverFromError(skipUntilToken); - } - - Value &Reader::currentValue() { return *(nodes_.top()); } - - Reader::Char Reader::getNextChar() { - if (current_ == end_) - return 0; - return *current_++; - } - - void Reader::getLocationLineAndColumn(Location location, int &line, int &column) const { - Location current = begin_; - Location lastLineStart = current; - line = 0; - while (current < location && current != end_) { - Char c = *current++; - if (c == '\r') { - if (*current == '\n') - ++current; - lastLineStart = current; - ++line; - } else if (c == '\n') { - lastLineStart = current; - ++line; + return addError( + "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current); + } + return true; + } + + bool Reader::decodeUnicodeEscapeSequence(Token &token, Location ¤t, Location end, unsigned int &unicode) { + if (end - current < 4) + return addError("Bad unicode escape sequence in string: four digits expected.", token, current); + unicode = 0; + for (int index = 0; index < 4; ++index) { + Char c = *current++; + unicode *= 16; + if (c >= '0' && c <= '9') + unicode += c - '0'; + else if (c >= 'a' && c <= 'f') + unicode += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + unicode += c - 'A' + 10; + else + return addError("Bad unicode escape sequence in string: hexadecimal digit expected.", token, current); + } + return true; + } + + bool Reader::addError(const std::string &message, Token &token, Location extra) { + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back(info); + return false; + } + + bool Reader::recoverFromError(TokenType skipUntilToken) { + int errorCount = int(errors_.size()); + Token skip; + while (true) { + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery + if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) + break; + } + errors_.resize(errorCount); + return false; + } + + bool Reader::addErrorAndRecover(const std::string &message, Token &token, TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); + } + + Value &Reader::currentValue() { return *(nodes_.top()); } + + Reader::Char Reader::getNextChar() { + if (current_ == end_) + return 0; + return *current_++; + } + + void Reader::getLocationLineAndColumn(Location location, int &line, int &column) const { + Location current = begin_; + Location lastLineStart = current; + line = 0; + while (current < location && current != end_) { + Char c = *current++; + if (c == '\r') { + if (*current == '\n') + ++current; + lastLineStart = current; + ++line; + } else if (c == '\n') { + lastLineStart = current; + ++line; + } } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; } - // column & line start at 1 - column = int(location - lastLineStart) + 1; - ++line; - } - - std::string Reader::getLocationLineAndColumn(Location location) const { - int line, column; - getLocationLineAndColumn(location, line, column); - char buffer[18 + 16 + 16 + 1]; - sprintf(buffer, "Line %d, Column %d", line, column); - return buffer; - } - - std::string Reader::getFormatedErrorMessages() const { - std::string formattedMessage; - for (Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError) { - const ErrorInfo &error = *itError; - formattedMessage += "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; - formattedMessage += " " + error.message_ + "\n"; - if (error.extra_) - formattedMessage += "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; - } - return formattedMessage; - } - - std::istream &operator>>(std::istream &sin, Value &root) { - Json::Reader reader; - bool ok = reader.parse(sin, root, true); - //JSON_ASSERT( ok ); - if (!ok) - throw std::runtime_error(reader.getFormatedErrorMessages()); - return sin; - } - -} // namespace Json -} // namespace jsoncollector + + std::string Reader::getLocationLineAndColumn(Location location) const { + int line, column; + getLocationLineAndColumn(location, line, column); + char buffer[18 + 16 + 16 + 1]; + sprintf(buffer, "Line %d, Column %d", line, column); + return buffer; + } + + std::string Reader::getFormatedErrorMessages() const { + std::string formattedMessage; + for (Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError) { + const ErrorInfo &error = *itError; + formattedMessage += "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if (error.extra_) + formattedMessage += "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; + } + return formattedMessage; + } + + std::istream &operator>>(std::istream &sin, Value &root) { + Json::Reader reader; + bool ok = reader.parse(sin, root, true); + //JSON_ASSERT( ok ); + if (!ok) + throw std::runtime_error(reader.getFormatedErrorMessages()); + return sin; + } + + } // namespace Json +} // namespace jsoncollector diff --git a/EventFilter/Utilities/src/json_value.cpp b/EventFilter/Utilities/src/json_value.cpp index 4dca618e212fe..50ba082341a8d 100644 --- a/EventFilter/Utilities/src/json_value.cpp +++ b/EventFilter/Utilities/src/json_value.cpp @@ -20,117 +20,117 @@ throw std::runtime_error(message); namespace jsoncollector { -namespace Json { - - const Value Value::null; - const Int Value::minInt = Int(~(UInt(-1) / 2)); - const Int Value::maxInt = Int(UInt(-1) / 2); - const UInt Value::maxUInt = UInt(-1); - - // A "safe" implementation of strdup. Allow null pointer to be passed. - // Also avoid warning on msvc80. - // - //inline char *safeStringDup( const char *czstring ) - //{ - // if ( czstring ) - // { - // const size_t length = (unsigned int)( strlen(czstring) + 1 ); - // char *newString = static_cast( malloc( length ) ); - // memcpy( newString, czstring, length ); - // return newString; - // } - // return 0; - //} - // - //inline char *safeStringDup( const std::string &str ) - //{ - // if ( !str.empty() ) - // { - // const size_t length = str.length(); - // char *newString = static_cast( malloc( length + 1 ) ); - // memcpy( newString, str.c_str(), length ); - // newString[length] = 0; - // return newString; - // } - // return 0; - //} - - ValueAllocator::~ValueAllocator() {} - - class DefaultValueAllocator : public ValueAllocator { - public: - DefaultValueAllocator() {} - - ~DefaultValueAllocator() override {} - - char *makeMemberName(const char *memberName) const override { return duplicateStringValue(memberName); } - - void releaseMemberName(char *memberName) const override { releaseStringValue(memberName); } - - char *duplicateStringValue(const char *value, unsigned int length = unknown) const override { - // invesgate this old optimization - //if ( !value || value[0] == 0 ) - // return 0; - - if (length == unknown) - length = (unsigned int)strlen(value); - char *newString = static_cast(malloc(length + 1)); - memcpy(newString, value, length); - newString[length] = 0; - return newString; - } - - void releaseStringValue(char *value) const override { - if (value) - free(value); - } - }; + namespace Json { + + const Value Value::null; + const Int Value::minInt = Int(~(UInt(-1) / 2)); + const Int Value::maxInt = Int(UInt(-1) / 2); + const UInt Value::maxUInt = UInt(-1); + + // A "safe" implementation of strdup. Allow null pointer to be passed. + // Also avoid warning on msvc80. + // + //inline char *safeStringDup( const char *czstring ) + //{ + // if ( czstring ) + // { + // const size_t length = (unsigned int)( strlen(czstring) + 1 ); + // char *newString = static_cast( malloc( length ) ); + // memcpy( newString, czstring, length ); + // return newString; + // } + // return 0; + //} + // + //inline char *safeStringDup( const std::string &str ) + //{ + // if ( !str.empty() ) + // { + // const size_t length = str.length(); + // char *newString = static_cast( malloc( length + 1 ) ); + // memcpy( newString, str.c_str(), length ); + // newString[length] = 0; + // return newString; + // } + // return 0; + //} + + ValueAllocator::~ValueAllocator() {} + + class DefaultValueAllocator : public ValueAllocator { + public: + DefaultValueAllocator() {} + + ~DefaultValueAllocator() override {} + + char *makeMemberName(const char *memberName) const override { return duplicateStringValue(memberName); } + + void releaseMemberName(char *memberName) const override { releaseStringValue(memberName); } + + char *duplicateStringValue(const char *value, unsigned int length = unknown) const override { + // invesgate this old optimization + //if ( !value || value[0] == 0 ) + // return 0; + + if (length == unknown) + length = (unsigned int)strlen(value); + char *newString = static_cast(malloc(length + 1)); + memcpy(newString, value, length); + newString[length] = 0; + return newString; + } - static ValueAllocator const *valueAllocator() { - static const DefaultValueAllocator defaultAllocator; - static ValueAllocator const *valueAllocator = &defaultAllocator; - return valueAllocator; - } + void releaseStringValue(char *value) const override { + if (value) + free(value); + } + }; - static struct DummyValueAllocatorInitializer { - DummyValueAllocatorInitializer() { - valueAllocator(); // ensure valueAllocator() statics are initialized before main(). + static ValueAllocator const *valueAllocator() { + static const DefaultValueAllocator defaultAllocator; + static ValueAllocator const *valueAllocator = &defaultAllocator; + return valueAllocator; } - } dummyValueAllocatorInitializer; -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ValueInternals... -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// + static struct DummyValueAllocatorInitializer { + DummyValueAllocatorInitializer() { + valueAllocator(); // ensure valueAllocator() statics are initialized before main(). + } + } dummyValueAllocatorInitializer; + + // ////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////// + // ValueInternals... + // ////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////// #include "json_valueiterator.icc" - // ////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////// - // class Value::CommentInfo - // ////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////// - - Value::CommentInfo::CommentInfo() : comment_(nullptr) {} - - Value::CommentInfo::~CommentInfo() { - if (comment_) - valueAllocator()->releaseStringValue(comment_); - } - - void Value::CommentInfo::setComment(const char *text) { - if (comment_) - valueAllocator()->releaseStringValue(comment_); - JSON_ASSERT(text); - JSON_ASSERT_MESSAGE(text[0] == '\0' || text[0] == '/', "Comments must start with /"); - // It seems that /**/ style comments are acceptable as well. - comment_ = valueAllocator()->duplicateStringValue(text); - } + // ////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////// + // class Value::CommentInfo + // ////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////// + + Value::CommentInfo::CommentInfo() : comment_(nullptr) {} + + Value::CommentInfo::~CommentInfo() { + if (comment_) + valueAllocator()->releaseStringValue(comment_); + } + + void Value::CommentInfo::setComment(const char *text) { + if (comment_) + valueAllocator()->releaseStringValue(comment_); + JSON_ASSERT(text); + JSON_ASSERT_MESSAGE(text[0] == '\0' || text[0] == '/', "Comments must start with /"); + // It seems that /**/ style comments are acceptable as well. + comment_ = valueAllocator()->duplicateStringValue(text); + } // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// @@ -141,318 +141,318 @@ namespace Json { // ////////////////////////////////////////////////////////////////// #ifndef JSON_VALUE_USE_INTERNAL_MAP - // Notes: index_ indicates if the string was allocated when - // a string is stored. + // Notes: index_ indicates if the string was allocated when + // a string is stored. - Value::CZString::CZString(int index) : cstr_(nullptr), index_(index) {} + Value::CZString::CZString(int index) : cstr_(nullptr), index_(index) {} - Value::CZString::CZString(const char *cstr, DuplicationPolicy allocate) - : cstr_(allocate == duplicate ? valueAllocator()->makeMemberName(cstr) : cstr), index_(allocate) {} + Value::CZString::CZString(const char *cstr, DuplicationPolicy allocate) + : cstr_(allocate == duplicate ? valueAllocator()->makeMemberName(cstr) : cstr), index_(allocate) {} - Value::CZString::CZString(const CZString &other) - : cstr_(other.index_ != noDuplication && other.cstr_ != nullptr ? valueAllocator()->makeMemberName(other.cstr_) - : other.cstr_), - index_(other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate) : other.index_) {} + Value::CZString::CZString(const CZString &other) + : cstr_(other.index_ != noDuplication && other.cstr_ != nullptr ? valueAllocator()->makeMemberName(other.cstr_) + : other.cstr_), + index_(other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate) : other.index_) {} - Value::CZString::~CZString() { - if (cstr_ && index_ == duplicate) - valueAllocator()->releaseMemberName(const_cast(cstr_)); - } + Value::CZString::~CZString() { + if (cstr_ && index_ == duplicate) + valueAllocator()->releaseMemberName(const_cast(cstr_)); + } - void Value::CZString::swap(CZString &other) { - std::swap(cstr_, other.cstr_); - std::swap(index_, other.index_); - } + void Value::CZString::swap(CZString &other) { + std::swap(cstr_, other.cstr_); + std::swap(index_, other.index_); + } - Value::CZString &Value::CZString::operator=(const CZString &other) { - CZString temp(other); - swap(temp); - return *this; - } + Value::CZString &Value::CZString::operator=(const CZString &other) { + CZString temp(other); + swap(temp); + return *this; + } - bool Value::CZString::operator<(const CZString &other) const { - if (cstr_ and other.cstr_) - return strcmp(cstr_, other.cstr_) < 0; - return index_ < other.index_; - } + bool Value::CZString::operator<(const CZString &other) const { + if (cstr_ and other.cstr_) + return strcmp(cstr_, other.cstr_) < 0; + return index_ < other.index_; + } - bool Value::CZString::operator==(const CZString &other) const { - if (cstr_ and other.cstr_) - return strcmp(cstr_, other.cstr_) == 0; - return index_ == other.index_; - } + bool Value::CZString::operator==(const CZString &other) const { + if (cstr_ and other.cstr_) + return strcmp(cstr_, other.cstr_) == 0; + return index_ == other.index_; + } - int Value::CZString::index() const { return index_; } + int Value::CZString::index() const { return index_; } - const char *Value::CZString::c_str() const { return cstr_; } + const char *Value::CZString::c_str() const { return cstr_; } - bool Value::CZString::isStaticString() const { return index_ == noDuplication; } + bool Value::CZString::isStaticString() const { return index_ == noDuplication; } #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP - // ////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////// - // class Value::Value - // ////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////// - // ////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////// + // class Value::Value + // ////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////// + // ////////////////////////////////////////////////////////////////// - /*! \internal Default constructor initialization must be equivalent to: + /*! \internal Default constructor initialization must be equivalent to: * memset( this, 0, sizeof(Value) ) * This optimization is used in ValueInternalMap fast allocator. */ - Value::Value(ValueType type) - : type_(type), - allocated_(0), - comments_(nullptr) + Value::Value(ValueType type) + : type_(type), + allocated_(0), + comments_(nullptr) #ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) + , + itemIsUsed_(0) #endif - { - switch (type) { - case nullValue: - break; - case intValue: - case uintValue: - value_.int_ = 0; - break; - case realValue: - value_.real_ = 0.0; - break; - case stringValue: - value_.string_ = nullptr; - break; + { + switch (type) { + case nullValue: + break; + case intValue: + case uintValue: + value_.int_ = 0; + break; + case realValue: + value_.real_ = 0.0; + break; + case stringValue: + value_.string_ = nullptr; + break; #ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(); - break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(); + break; #else - case arrayValue: - value_.array_ = arrayAllocator()->newArray(); - break; - case objectValue: - value_.map_ = mapAllocator()->newMap(); - break; + case arrayValue: + value_.array_ = arrayAllocator()->newArray(); + break; + case objectValue: + value_.map_ = mapAllocator()->newMap(); + break; #endif - case booleanValue: - value_.bool_ = false; - break; - default: - JSON_ASSERT_UNREACHABLE; + case booleanValue: + value_.bool_ = false; + break; + default: + JSON_ASSERT_UNREACHABLE; + } } - } - Value::Value(Int value) - : type_(intValue), - comments_(nullptr) + Value::Value(Int value) + : type_(intValue), + comments_(nullptr) #ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) + , + itemIsUsed_(0) #endif - { - value_.int_ = value; - } + { + value_.int_ = value; + } - Value::Value(UInt value) - : type_(uintValue), - comments_(nullptr) + Value::Value(UInt value) + : type_(uintValue), + comments_(nullptr) #ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) + , + itemIsUsed_(0) #endif - { - value_.uint_ = value; - } + { + value_.uint_ = value; + } - Value::Value(double value) - : type_(realValue), - comments_(nullptr) + Value::Value(double value) + : type_(realValue), + comments_(nullptr) #ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) + , + itemIsUsed_(0) #endif - { - value_.real_ = value; - } - - Value::Value(const char *value) - : type_(stringValue), - allocated_(true), - comments_(nullptr) + { + value_.real_ = value; + } + + Value::Value(const char *value) + : type_(stringValue), + allocated_(true), + comments_(nullptr) #ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) + , + itemIsUsed_(0) #endif - { - value_.string_ = valueAllocator()->duplicateStringValue(value); - } - - Value::Value(const char *beginValue, const char *endValue) - : type_(stringValue), - allocated_(true), - comments_(nullptr) + { + value_.string_ = valueAllocator()->duplicateStringValue(value); + } + + Value::Value(const char *beginValue, const char *endValue) + : type_(stringValue), + allocated_(true), + comments_(nullptr) #ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) + , + itemIsUsed_(0) #endif - { - value_.string_ = valueAllocator()->duplicateStringValue(beginValue, UInt(endValue - beginValue)); - } - - Value::Value(const std::string &value) - : type_(stringValue), - allocated_(true), - comments_(nullptr) + { + value_.string_ = valueAllocator()->duplicateStringValue(beginValue, UInt(endValue - beginValue)); + } + + Value::Value(const std::string &value) + : type_(stringValue), + allocated_(true), + comments_(nullptr) #ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) + , + itemIsUsed_(0) #endif - { - value_.string_ = valueAllocator()->duplicateStringValue(value.c_str(), (unsigned int)value.length()); - } - - Value::Value(const StaticString &value) - : type_(stringValue), - allocated_(false), - comments_(nullptr) + { + value_.string_ = valueAllocator()->duplicateStringValue(value.c_str(), (unsigned int)value.length()); + } + + Value::Value(const StaticString &value) + : type_(stringValue), + allocated_(false), + comments_(nullptr) #ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) + , + itemIsUsed_(0) #endif - { - value_.string_ = const_cast(value.c_str()); - } + { + value_.string_ = const_cast(value.c_str()); + } #ifdef JSON_USE_CPPTL - Value::Value(const CppTL::ConstString &value) - : type_(stringValue), - allocated_(true), - comments_(0) + Value::Value(const CppTL::ConstString &value) + : type_(stringValue), + allocated_(true), + comments_(0) #ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) + , + itemIsUsed_(0) #endif - { - value_.string_ = valueAllocator()->duplicateStringValue(value, value.length()); - } + { + value_.string_ = valueAllocator()->duplicateStringValue(value, value.length()); + } #endif - Value::Value(bool value) - : type_(booleanValue), - comments_(nullptr) + Value::Value(bool value) + : type_(booleanValue), + comments_(nullptr) #ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) + , + itemIsUsed_(0) #endif - { - value_.bool_ = value; - } + { + value_.bool_ = value; + } - Value::Value(const Value &other) - : type_(other.type_), - comments_(nullptr) + Value::Value(const Value &other) + : type_(other.type_), + comments_(nullptr) #ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) + , + itemIsUsed_(0) #endif - { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - value_ = other.value_; - break; - case stringValue: - if (other.value_.string_) { - value_.string_ = valueAllocator()->duplicateStringValue(other.value_.string_); - allocated_ = true; - } else - value_.string_ = nullptr; - break; + { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if (other.value_.string_) { + value_.string_ = valueAllocator()->duplicateStringValue(other.value_.string_); + allocated_ = true; + } else + value_.string_ = nullptr; + break; #ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(*other.value_.map_); - break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(*other.value_.map_); + break; #else - case arrayValue: - value_.array_ = arrayAllocator()->newArrayCopy(*other.value_.array_); - break; - case objectValue: - value_.map_ = mapAllocator()->newMapCopy(*other.value_.map_); - break; + case arrayValue: + value_.array_ = arrayAllocator()->newArrayCopy(*other.value_.array_); + break; + case objectValue: + value_.map_ = mapAllocator()->newMapCopy(*other.value_.map_); + break; #endif - default: - JSON_ASSERT_UNREACHABLE; - } - if (other.comments_) { - comments_ = new CommentInfo[numberOfCommentPlacement]; - for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { - const CommentInfo &otherComment = other.comments_[comment]; - if (otherComment.comment_) - comments_[comment].setComment(otherComment.comment_); + default: + JSON_ASSERT_UNREACHABLE; + } + if (other.comments_) { + comments_ = new CommentInfo[numberOfCommentPlacement]; + for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { + const CommentInfo &otherComment = other.comments_[comment]; + if (otherComment.comment_) + comments_[comment].setComment(otherComment.comment_); + } } } - } - - Value::~Value() { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if (allocated_) - valueAllocator()->releaseStringValue(value_.string_); - break; + + Value::~Value() { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if (allocated_) + valueAllocator()->releaseStringValue(value_.string_); + break; #ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - delete value_.map_; - break; + case arrayValue: + case objectValue: + delete value_.map_; + break; #else - case arrayValue: - arrayAllocator()->destructArray(value_.array_); - break; - case objectValue: - mapAllocator()->destructMap(value_.map_); - break; + case arrayValue: + arrayAllocator()->destructArray(value_.array_); + break; + case objectValue: + mapAllocator()->destructMap(value_.map_); + break; #endif - default: - JSON_ASSERT_UNREACHABLE; + default: + JSON_ASSERT_UNREACHABLE; + } + + if (comments_) + delete[] comments_; } - if (comments_) - delete[] comments_; - } - - Value &Value::operator=(const Value &other) { - Value temp(other); - swap(temp); - return *this; - } - - void Value::swap(Value &other) { - ValueType temp = type_; - type_ = other.type_; - other.type_ = temp; - std::swap(value_, other.value_); - int temp2 = allocated_; - allocated_ = other.allocated_; - other.allocated_ = temp2; - } - - ValueType Value::type() const { return type_; } - - int Value::compare(const Value &other) { - /* + Value &Value::operator=(const Value &other) { + Value temp(other); + swap(temp); + return *this; + } + + void Value::swap(Value &other) { + ValueType temp = type_; + type_ = other.type_; + other.type_ = temp; + std::swap(value_, other.value_); + int temp2 = allocated_; + allocated_ = other.allocated_; + other.allocated_ = temp2; + } + + ValueType Value::type() const { return type_; } + + int Value::compare(const Value &other) { + /* int typeDelta = other.type_ - type_; switch ( type_ ) { @@ -476,818 +476,818 @@ namespace Json { JSON_ASSERT_UNREACHABLE; } */ - return 0; // unreachable - } - - bool Value::operator<(const Value &other) const { - int typeDelta = type_ - other.type_; - if (typeDelta) - return typeDelta < 0 ? true : false; - switch (type_) { - case nullValue: - return false; - case intValue: - return value_.int_ < other.value_.int_; - case uintValue: - return value_.uint_ < other.value_.uint_; - case realValue: - return value_.real_ < other.value_.real_; - case booleanValue: - return value_.bool_ < other.value_.bool_; - case stringValue: - return (value_.string_ == nullptr && other.value_.string_) || - (other.value_.string_ && value_.string_ && strcmp(value_.string_, other.value_.string_) < 0); + return 0; // unreachable + } + + bool Value::operator<(const Value &other) const { + int typeDelta = type_ - other.type_; + if (typeDelta) + return typeDelta < 0 ? true : false; + switch (type_) { + case nullValue: + return false; + case intValue: + return value_.int_ < other.value_.int_; + case uintValue: + return value_.uint_ < other.value_.uint_; + case realValue: + return value_.real_ < other.value_.real_; + case booleanValue: + return value_.bool_ < other.value_.bool_; + case stringValue: + return (value_.string_ == nullptr && other.value_.string_) || + (other.value_.string_ && value_.string_ && strcmp(value_.string_, other.value_.string_) < 0); #ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: { - int delta = int(value_.map_->size() - other.value_.map_->size()); - if (delta) - return delta < 0; - return (*value_.map_) < (*other.value_.map_); - } + case arrayValue: + case objectValue: { + int delta = int(value_.map_->size() - other.value_.map_->size()); + if (delta) + return delta < 0; + return (*value_.map_) < (*other.value_.map_); + } #else - case arrayValue: - return value_.array_->compare(*(other.value_.array_)) < 0; - case objectValue: - return value_.map_->compare(*(other.value_.map_)) < 0; + case arrayValue: + return value_.array_->compare(*(other.value_.array_)) < 0; + case objectValue: + return value_.map_->compare(*(other.value_.map_)) < 0; #endif - default: - JSON_ASSERT_UNREACHABLE; + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable } - return false; // unreachable - } - - bool Value::operator<=(const Value &other) const { return !(other > *this); } - - bool Value::operator>=(const Value &other) const { return !(*this < other); } - - bool Value::operator>(const Value &other) const { return other < *this; } - - bool Value::operator==(const Value &other) const { - //if ( type_ != other.type_ ) - // GCC 2.95.3 says: - // attempt to take address of bit-field structure member `Json::Value::type_' - // Beats me, but a temp solves the problem. - int temp = other.type_; - if (type_ != temp) - return false; - switch (type_) { - case nullValue: - return true; - case intValue: - return value_.int_ == other.value_.int_; - case uintValue: - return value_.uint_ == other.value_.uint_; - case realValue: - return value_.real_ == other.value_.real_; - case booleanValue: - return value_.bool_ == other.value_.bool_; - case stringValue: - return (value_.string_ == other.value_.string_) || - (other.value_.string_ && value_.string_ && strcmp(value_.string_, other.value_.string_) == 0); + + bool Value::operator<=(const Value &other) const { return !(other > *this); } + + bool Value::operator>=(const Value &other) const { return !(*this < other); } + + bool Value::operator>(const Value &other) const { return other < *this; } + + bool Value::operator==(const Value &other) const { + //if ( type_ != other.type_ ) + // GCC 2.95.3 says: + // attempt to take address of bit-field structure member `Json::Value::type_' + // Beats me, but a temp solves the problem. + int temp = other.type_; + if (type_ != temp) + return false; + switch (type_) { + case nullValue: + return true; + case intValue: + return value_.int_ == other.value_.int_; + case uintValue: + return value_.uint_ == other.value_.uint_; + case realValue: + return value_.real_ == other.value_.real_; + case booleanValue: + return value_.bool_ == other.value_.bool_; + case stringValue: + return (value_.string_ == other.value_.string_) || + (other.value_.string_ && value_.string_ && strcmp(value_.string_, other.value_.string_) == 0); #ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - return value_.map_->size() == other.value_.map_->size() && (*value_.map_) == (*other.value_.map_); + case arrayValue: + case objectValue: + return value_.map_->size() == other.value_.map_->size() && (*value_.map_) == (*other.value_.map_); #else - case arrayValue: - return value_.array_->compare(*(other.value_.array_)) == 0; - case objectValue: - return value_.map_->compare(*(other.value_.map_)) == 0; + case arrayValue: + return value_.array_->compare(*(other.value_.array_)) == 0; + case objectValue: + return value_.map_->compare(*(other.value_.map_)) == 0; #endif - default: - JSON_ASSERT_UNREACHABLE; + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable } - return false; // unreachable - } - - bool Value::operator!=(const Value &other) const { return !(*this == other); } - - const char *Value::asCString() const { - JSON_ASSERT(type_ == stringValue); - return value_.string_; - } - - std::string Value::asString() const { - switch (type_) { - case nullValue: - return ""; - case stringValue: - return value_.string_ ? value_.string_ : ""; - case booleanValue: - return value_.bool_ ? "true" : "false"; - case intValue: - case uintValue: - case realValue: - case arrayValue: - case objectValue: - JSON_ASSERT_MESSAGE(false, "Type is not convertible to string"); - default: - JSON_ASSERT_UNREACHABLE; + + bool Value::operator!=(const Value &other) const { return !(*this == other); } + + const char *Value::asCString() const { + JSON_ASSERT(type_ == stringValue); + return value_.string_; + } + + std::string Value::asString() const { + switch (type_) { + case nullValue: + return ""; + case stringValue: + return value_.string_ ? value_.string_ : ""; + case booleanValue: + return value_.bool_ ? "true" : "false"; + case intValue: + case uintValue: + case realValue: + case arrayValue: + case objectValue: + JSON_ASSERT_MESSAGE(false, "Type is not convertible to string"); + default: + JSON_ASSERT_UNREACHABLE; + } + return ""; // unreachable } - return ""; // unreachable - } #ifdef JSON_USE_CPPTL - CppTL::ConstString Value::asConstString() const { return CppTL::ConstString(asString().c_str()); } + CppTL::ConstString Value::asConstString() const { return CppTL::ConstString(asString().c_str()); } #endif - Value::Int Value::asInt() const { - switch (type_) { - case nullValue: - return 0; - case intValue: - return value_.int_; - case uintValue: - JSON_ASSERT_MESSAGE(value_.uint_ < (unsigned)maxInt, "integer out of signed integer range"); - return value_.uint_; - case realValue: - JSON_ASSERT_MESSAGE(value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range"); - return Int(value_.real_); - case booleanValue: - return value_.bool_ ? 1 : 0; - case stringValue: - case arrayValue: - case objectValue: - JSON_ASSERT_MESSAGE(false, "Type is not convertible to int"); - default: - JSON_ASSERT_UNREACHABLE; + Value::Int Value::asInt() const { + switch (type_) { + case nullValue: + return 0; + case intValue: + return value_.int_; + case uintValue: + JSON_ASSERT_MESSAGE(value_.uint_ < (unsigned)maxInt, "integer out of signed integer range"); + return value_.uint_; + case realValue: + JSON_ASSERT_MESSAGE(value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range"); + return Int(value_.real_); + case booleanValue: + return value_.bool_ ? 1 : 0; + case stringValue: + case arrayValue: + case objectValue: + JSON_ASSERT_MESSAGE(false, "Type is not convertible to int"); + default: + JSON_ASSERT_UNREACHABLE; + } + return 0; // unreachable; } - return 0; // unreachable; - } - - Value::UInt Value::asUInt() const { - switch (type_) { - case nullValue: - return 0; - case intValue: - JSON_ASSERT_MESSAGE(value_.int_ >= 0, "Negative integer can not be converted to unsigned integer"); - return value_.int_; - case uintValue: - return value_.uint_; - case realValue: - JSON_ASSERT_MESSAGE(value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range"); - return UInt(value_.real_); - case booleanValue: - return value_.bool_ ? 1 : 0; - case stringValue: - case arrayValue: - case objectValue: - JSON_ASSERT_MESSAGE(false, "Type is not convertible to uint"); - default: - JSON_ASSERT_UNREACHABLE; + + Value::UInt Value::asUInt() const { + switch (type_) { + case nullValue: + return 0; + case intValue: + JSON_ASSERT_MESSAGE(value_.int_ >= 0, "Negative integer can not be converted to unsigned integer"); + return value_.int_; + case uintValue: + return value_.uint_; + case realValue: + JSON_ASSERT_MESSAGE(value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range"); + return UInt(value_.real_); + case booleanValue: + return value_.bool_ ? 1 : 0; + case stringValue: + case arrayValue: + case objectValue: + JSON_ASSERT_MESSAGE(false, "Type is not convertible to uint"); + default: + JSON_ASSERT_UNREACHABLE; + } + return 0; // unreachable; } - return 0; // unreachable; - } - - double Value::asDouble() const { - switch (type_) { - case nullValue: - return 0.0; - case intValue: - return value_.int_; - case uintValue: - return value_.uint_; - case realValue: - return value_.real_; - case booleanValue: - return value_.bool_ ? 1.0 : 0.0; - case stringValue: - case arrayValue: - case objectValue: - JSON_ASSERT_MESSAGE(false, "Type is not convertible to double"); - default: - JSON_ASSERT_UNREACHABLE; + + double Value::asDouble() const { + switch (type_) { + case nullValue: + return 0.0; + case intValue: + return value_.int_; + case uintValue: + return value_.uint_; + case realValue: + return value_.real_; + case booleanValue: + return value_.bool_ ? 1.0 : 0.0; + case stringValue: + case arrayValue: + case objectValue: + JSON_ASSERT_MESSAGE(false, "Type is not convertible to double"); + default: + JSON_ASSERT_UNREACHABLE; + } + return 0; // unreachable; } - return 0; // unreachable; - } - bool Value::asBool() const { - switch (type_) { - case nullValue: - return false; - case intValue: - case uintValue: - return value_.int_ != 0; - case realValue: - return value_.real_ != 0.0; - case booleanValue: - return value_.bool_; - case stringValue: - return value_.string_ && value_.string_[0] != 0; - case arrayValue: - case objectValue: - return !value_.map_->empty(); - default: - JSON_ASSERT_UNREACHABLE; + bool Value::asBool() const { + switch (type_) { + case nullValue: + return false; + case intValue: + case uintValue: + return value_.int_ != 0; + case realValue: + return value_.real_ != 0.0; + case booleanValue: + return value_.bool_; + case stringValue: + return value_.string_ && value_.string_[0] != 0; + case arrayValue: + case objectValue: + return !value_.map_->empty(); + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable; } - return false; // unreachable; - } - - bool Value::isConvertibleTo(ValueType other) const { - switch (type_) { - case nullValue: - return true; - case intValue: - return (other == nullValue && value_.int_ == 0) || other == intValue || - (other == uintValue && value_.int_ >= 0) || other == realValue || other == stringValue || - other == booleanValue; - case uintValue: - return (other == nullValue && value_.uint_ == 0) || (other == intValue && value_.uint_ <= (unsigned)maxInt) || - other == uintValue || other == realValue || other == stringValue || other == booleanValue; - case realValue: - return (other == nullValue && value_.real_ == 0.0) || - (other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt) || - (other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt) || other == realValue || - other == stringValue || other == booleanValue; - case booleanValue: - return (other == nullValue && value_.bool_ == false) || other == intValue || other == uintValue || - other == realValue || other == stringValue || other == booleanValue; - case stringValue: - return other == stringValue || (other == nullValue && (!value_.string_ || value_.string_[0] == 0)); - case arrayValue: - return other == arrayValue || (other == nullValue && value_.map_->empty()); - case objectValue: - return other == objectValue || (other == nullValue && value_.map_->empty()); - default: - JSON_ASSERT_UNREACHABLE; + + bool Value::isConvertibleTo(ValueType other) const { + switch (type_) { + case nullValue: + return true; + case intValue: + return (other == nullValue && value_.int_ == 0) || other == intValue || + (other == uintValue && value_.int_ >= 0) || other == realValue || other == stringValue || + other == booleanValue; + case uintValue: + return (other == nullValue && value_.uint_ == 0) || (other == intValue && value_.uint_ <= (unsigned)maxInt) || + other == uintValue || other == realValue || other == stringValue || other == booleanValue; + case realValue: + return (other == nullValue && value_.real_ == 0.0) || + (other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt) || + (other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt) || other == realValue || + other == stringValue || other == booleanValue; + case booleanValue: + return (other == nullValue && value_.bool_ == false) || other == intValue || other == uintValue || + other == realValue || other == stringValue || other == booleanValue; + case stringValue: + return other == stringValue || (other == nullValue && (!value_.string_ || value_.string_[0] == 0)); + case arrayValue: + return other == arrayValue || (other == nullValue && value_.map_->empty()); + case objectValue: + return other == objectValue || (other == nullValue && value_.map_->empty()); + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable; } - return false; // unreachable; - } - - /// Number of values in array or object - Value::UInt Value::size() const { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - case stringValue: - return 0; + + /// Number of values in array or object + Value::UInt Value::size() const { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + case stringValue: + return 0; #ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: // size of the array is highest index + 1 - if (!value_.map_->empty()) { - ObjectValues::const_iterator itLast = value_.map_->end(); - --itLast; - return (*itLast).first.index() + 1; - } - return 0; - case objectValue: - return Int(value_.map_->size()); + case arrayValue: // size of the array is highest index + 1 + if (!value_.map_->empty()) { + ObjectValues::const_iterator itLast = value_.map_->end(); + --itLast; + return (*itLast).first.index() + 1; + } + return 0; + case objectValue: + return Int(value_.map_->size()); #else - case arrayValue: - return Int(value_.array_->size()); - case objectValue: - return Int(value_.map_->size()); + case arrayValue: + return Int(value_.array_->size()); + case objectValue: + return Int(value_.map_->size()); #endif - default: - JSON_ASSERT_UNREACHABLE; + default: + JSON_ASSERT_UNREACHABLE; + } + return 0; // unreachable; } - return 0; // unreachable; - } - bool Value::empty() const { - if (isNull() || isArray() || isObject()) - return size() == 0u; - else - return false; - } + bool Value::empty() const { + if (isNull() || isArray() || isObject()) + return size() == 0u; + else + return false; + } - bool Value::operator!() const { return isNull(); } + bool Value::operator!() const { return isNull(); } - void Value::clear() { - JSON_ASSERT(type_ == nullValue || type_ == arrayValue || type_ == objectValue); + void Value::clear() { + JSON_ASSERT(type_ == nullValue || type_ == arrayValue || type_ == objectValue); - switch (type_) { + switch (type_) { #ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_->clear(); - break; + case arrayValue: + case objectValue: + value_.map_->clear(); + break; #else - case arrayValue: - value_.array_->clear(); - break; - case objectValue: - value_.map_->clear(); - break; + case arrayValue: + value_.array_->clear(); + break; + case objectValue: + value_.map_->clear(); + break; #endif - default: - break; + default: + break; + } } - } - void Value::resize(UInt newSize) { - JSON_ASSERT(type_ == nullValue || type_ == arrayValue); - if (type_ == nullValue) - *this = Value(arrayValue); + void Value::resize(UInt newSize) { + JSON_ASSERT(type_ == nullValue || type_ == arrayValue); + if (type_ == nullValue) + *this = Value(arrayValue); #ifndef JSON_VALUE_USE_INTERNAL_MAP - UInt oldSize = size(); - if (newSize == 0) - clear(); - else if (newSize > oldSize) - (*this)[newSize - 1]; - else { - for (UInt index = newSize; index < oldSize; ++index) - value_.map_->erase(index); - assert(size() == newSize); - } + UInt oldSize = size(); + if (newSize == 0) + clear(); + else if (newSize > oldSize) + (*this)[newSize - 1]; + else { + for (UInt index = newSize; index < oldSize; ++index) + value_.map_->erase(index); + assert(size() == newSize); + } #else - value_.array_->resize(newSize); + value_.array_->resize(newSize); #endif - } + } - Value &Value::operator[](UInt index) { - JSON_ASSERT(type_ == nullValue || type_ == arrayValue); - if (type_ == nullValue) - *this = Value(arrayValue); + Value &Value::operator[](UInt index) { + JSON_ASSERT(type_ == nullValue || type_ == arrayValue); + if (type_ == nullValue) + *this = Value(arrayValue); #ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString key(index); - ObjectValues::iterator it = value_.map_->lower_bound(key); - if (it != value_.map_->end() && (*it).first == key) - return (*it).second; + CZString key(index); + ObjectValues::iterator it = value_.map_->lower_bound(key); + if (it != value_.map_->end() && (*it).first == key) + return (*it).second; - ObjectValues::value_type defaultValue(key, null); - it = value_.map_->insert(it, defaultValue); - return (*it).second; + ObjectValues::value_type defaultValue(key, null); + it = value_.map_->insert(it, defaultValue); + return (*it).second; #else - return value_.array_->resolveReference(index); + return value_.array_->resolveReference(index); #endif - } + } - const Value &Value::operator[](UInt index) const { - JSON_ASSERT(type_ == nullValue || type_ == arrayValue); - if (type_ == nullValue) - return null; + const Value &Value::operator[](UInt index) const { + JSON_ASSERT(type_ == nullValue || type_ == arrayValue); + if (type_ == nullValue) + return null; #ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString key(index); - ObjectValues::const_iterator it = value_.map_->find(key); - if (it == value_.map_->end()) - return null; - return (*it).second; + CZString key(index); + ObjectValues::const_iterator it = value_.map_->find(key); + if (it == value_.map_->end()) + return null; + return (*it).second; #else - Value *value = value_.array_->find(index); - return value ? *value : null; + Value *value = value_.array_->find(index); + return value ? *value : null; #endif - } + } - Value &Value::operator[](const char *key) { return resolveReference(key, false); } + Value &Value::operator[](const char *key) { return resolveReference(key, false); } - Value &Value::resolveReference(const char *key, bool isStatic) { - JSON_ASSERT(type_ == nullValue || type_ == objectValue); - if (type_ == nullValue) - *this = Value(objectValue); + Value &Value::resolveReference(const char *key, bool isStatic) { + JSON_ASSERT(type_ == nullValue || type_ == objectValue); + if (type_ == nullValue) + *this = Value(objectValue); #ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey(key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy); - ObjectValues::iterator it = value_.map_->lower_bound(actualKey); - if (it != value_.map_->end() && (*it).first == actualKey) - return (*it).second; - - ObjectValues::value_type defaultValue(actualKey, null); - it = value_.map_->insert(it, defaultValue); - Value &value = (*it).second; - return value; + CZString actualKey(key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy); + ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) + return (*it).second; + + ObjectValues::value_type defaultValue(actualKey, null); + it = value_.map_->insert(it, defaultValue); + Value &value = (*it).second; + return value; #else - return value_.map_->resolveReference(key, isStatic); + return value_.map_->resolveReference(key, isStatic); #endif - } + } - Value Value::get(UInt index, const Value &defaultValue) const { - const Value *value = &((*this)[index]); - return value == &null ? defaultValue : *value; - } + Value Value::get(UInt index, const Value &defaultValue) const { + const Value *value = &((*this)[index]); + return value == &null ? defaultValue : *value; + } - bool Value::isValidIndex(UInt index) const { return index < size(); } + bool Value::isValidIndex(UInt index) const { return index < size(); } - const Value &Value::operator[](const char *key) const { - JSON_ASSERT(type_ == nullValue || type_ == objectValue); - if (type_ == nullValue) - return null; + const Value &Value::operator[](const char *key) const { + JSON_ASSERT(type_ == nullValue || type_ == objectValue); + if (type_ == nullValue) + return null; #ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey(key, CZString::noDuplication); - ObjectValues::const_iterator it = value_.map_->find(actualKey); - if (it == value_.map_->end()) - return null; - return (*it).second; + CZString actualKey(key, CZString::noDuplication); + ObjectValues::const_iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return null; + return (*it).second; #else - const Value *value = value_.map_->find(key); - return value ? *value : null; + const Value *value = value_.map_->find(key); + return value ? *value : null; #endif - } + } - Value &Value::operator[](const std::string &key) { return (*this)[key.c_str()]; } + Value &Value::operator[](const std::string &key) { return (*this)[key.c_str()]; } - const Value &Value::operator[](const std::string &key) const { return (*this)[key.c_str()]; } + const Value &Value::operator[](const std::string &key) const { return (*this)[key.c_str()]; } - Value &Value::operator[](const StaticString &key) { return resolveReference(key, true); } + Value &Value::operator[](const StaticString &key) { return resolveReference(key, true); } #ifdef JSON_USE_CPPTL - Value &Value::operator[](const CppTL::ConstString &key) { return (*this)[key.c_str()]; } + Value &Value::operator[](const CppTL::ConstString &key) { return (*this)[key.c_str()]; } - const Value &Value::operator[](const CppTL::ConstString &key) const { return (*this)[key.c_str()]; } + const Value &Value::operator[](const CppTL::ConstString &key) const { return (*this)[key.c_str()]; } #endif - Value &Value::append(const Value &value) { return (*this)[size()] = value; } + Value &Value::append(const Value &value) { return (*this)[size()] = value; } - Value Value::get(const char *key, const Value &defaultValue) const { - const Value *value = &((*this)[key]); - return value == &null ? defaultValue : *value; - } + Value Value::get(const char *key, const Value &defaultValue) const { + const Value *value = &((*this)[key]); + return value == &null ? defaultValue : *value; + } - Value Value::get(const std::string &key, const Value &defaultValue) const { return get(key.c_str(), defaultValue); } + Value Value::get(const std::string &key, const Value &defaultValue) const { return get(key.c_str(), defaultValue); } - Value Value::removeMember(const char *key) { - JSON_ASSERT(type_ == nullValue || type_ == objectValue); - if (type_ == nullValue) - return null; + Value Value::removeMember(const char *key) { + JSON_ASSERT(type_ == nullValue || type_ == objectValue); + if (type_ == nullValue) + return null; #ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey(key, CZString::noDuplication); - ObjectValues::iterator it = value_.map_->find(actualKey); - if (it == value_.map_->end()) - return null; - Value old(it->second); - value_.map_->erase(it); - return old; -#else - Value *value = value_.map_->find(key); - if (value) { - Value old(*value); - value_.map_.remove(key); + CZString actualKey(key, CZString::noDuplication); + ObjectValues::iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return null; + Value old(it->second); + value_.map_->erase(it); return old; - } else { - return null; - } +#else + Value *value = value_.map_->find(key); + if (value) { + Value old(*value); + value_.map_.remove(key); + return old; + } else { + return null; + } #endif - } + } - Value Value::removeMember(const std::string &key) { return removeMember(key.c_str()); } + Value Value::removeMember(const std::string &key) { return removeMember(key.c_str()); } #ifdef JSON_USE_CPPTL - Value Value::get(const CppTL::ConstString &key, const Value &defaultValue) const { - return get(key.c_str(), defaultValue); - } + Value Value::get(const CppTL::ConstString &key, const Value &defaultValue) const { + return get(key.c_str(), defaultValue); + } #endif - bool Value::isMember(const char *key) const { - const Value *value = &((*this)[key]); - return value != &null; - } + bool Value::isMember(const char *key) const { + const Value *value = &((*this)[key]); + return value != &null; + } - bool Value::isMember(const std::string &key) const { return isMember(key.c_str()); } + bool Value::isMember(const std::string &key) const { return isMember(key.c_str()); } #ifdef JSON_USE_CPPTL - bool Value::isMember(const CppTL::ConstString &key) const { return isMember(key.c_str()); } + bool Value::isMember(const CppTL::ConstString &key) const { return isMember(key.c_str()); } #endif - Value::Members Value::getMemberNames() const { - JSON_ASSERT(type_ == nullValue || type_ == objectValue); - if (type_ == nullValue) - return Value::Members(); - Members members; - members.reserve(value_.map_->size()); + Value::Members Value::getMemberNames() const { + JSON_ASSERT(type_ == nullValue || type_ == objectValue); + if (type_ == nullValue) + return Value::Members(); + Members members; + members.reserve(value_.map_->size()); #ifndef JSON_VALUE_USE_INTERNAL_MAP - ObjectValues::const_iterator it = value_.map_->begin(); - ObjectValues::const_iterator itEnd = value_.map_->end(); - for (; it != itEnd; ++it) - members.push_back(std::string((*it).first.c_str())); + ObjectValues::const_iterator it = value_.map_->begin(); + ObjectValues::const_iterator itEnd = value_.map_->end(); + for (; it != itEnd; ++it) + members.push_back(std::string((*it).first.c_str())); #else - ValueInternalMap::IteratorState it; - ValueInternalMap::IteratorState itEnd; - value_.map_->makeBeginIterator(it); - value_.map_->makeEndIterator(itEnd); - for (; !ValueInternalMap::equals(it, itEnd); ValueInternalMap::increment(it)) - members.push_back(std::string(ValueInternalMap::key(it))); + ValueInternalMap::IteratorState it; + ValueInternalMap::IteratorState itEnd; + value_.map_->makeBeginIterator(it); + value_.map_->makeEndIterator(itEnd); + for (; !ValueInternalMap::equals(it, itEnd); ValueInternalMap::increment(it)) + members.push_back(std::string(ValueInternalMap::key(it))); #endif - return members; - } - // - //# ifdef JSON_USE_CPPTL - //EnumMemberNames - //Value::enumMemberNames() const - //{ - // if ( type_ == objectValue ) - // { - // return CppTL::Enum::any( CppTL::Enum::transform( - // CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), - // MemberNamesTransform() ) ); - // } - // return EnumMemberNames(); - //} - // - // - //EnumValues - //Value::enumValues() const - //{ - // if ( type_ == objectValue || type_ == arrayValue ) - // return CppTL::Enum::anyValues( *(value_.map_), - // CppTL::Type() ); - // return EnumValues(); - //} - // - //# endif - - bool Value::isNull() const { return type_ == nullValue; } - - bool Value::isBool() const { return type_ == booleanValue; } - - bool Value::isInt() const { return type_ == intValue; } - - bool Value::isUInt() const { return type_ == uintValue; } - - bool Value::isIntegral() const { return type_ == intValue || type_ == uintValue || type_ == booleanValue; } - - bool Value::isDouble() const { return type_ == realValue; } - - bool Value::isNumeric() const { return isIntegral() || isDouble(); } - - bool Value::isString() const { return type_ == stringValue; } - - bool Value::isArray() const { return type_ == nullValue || type_ == arrayValue; } - - bool Value::isObject() const { return type_ == nullValue || type_ == objectValue; } - - void Value::setComment(const char *comment, CommentPlacement placement) { - if (!comments_) - comments_ = new CommentInfo[numberOfCommentPlacement]; - comments_[placement].setComment(comment); - } - - void Value::setComment(const std::string &comment, CommentPlacement placement) { - setComment(comment.c_str(), placement); - } - - bool Value::hasComment(CommentPlacement placement) const { - return comments_ != nullptr && comments_[placement].comment_ != nullptr; - } - - std::string Value::getComment(CommentPlacement placement) const { - if (hasComment(placement)) - return comments_[placement].comment_; - return ""; - } - - std::string Value::toStyledString() const { - StyledWriter writer; - return writer.write(*this); - } - - Value::const_iterator Value::begin() const { - switch (type_) { + return members; + } + // + //# ifdef JSON_USE_CPPTL + //EnumMemberNames + //Value::enumMemberNames() const + //{ + // if ( type_ == objectValue ) + // { + // return CppTL::Enum::any( CppTL::Enum::transform( + // CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), + // MemberNamesTransform() ) ); + // } + // return EnumMemberNames(); + //} + // + // + //EnumValues + //Value::enumValues() const + //{ + // if ( type_ == objectValue || type_ == arrayValue ) + // return CppTL::Enum::anyValues( *(value_.map_), + // CppTL::Type() ); + // return EnumValues(); + //} + // + //# endif + + bool Value::isNull() const { return type_ == nullValue; } + + bool Value::isBool() const { return type_ == booleanValue; } + + bool Value::isInt() const { return type_ == intValue; } + + bool Value::isUInt() const { return type_ == uintValue; } + + bool Value::isIntegral() const { return type_ == intValue || type_ == uintValue || type_ == booleanValue; } + + bool Value::isDouble() const { return type_ == realValue; } + + bool Value::isNumeric() const { return isIntegral() || isDouble(); } + + bool Value::isString() const { return type_ == stringValue; } + + bool Value::isArray() const { return type_ == nullValue || type_ == arrayValue; } + + bool Value::isObject() const { return type_ == nullValue || type_ == objectValue; } + + void Value::setComment(const char *comment, CommentPlacement placement) { + if (!comments_) + comments_ = new CommentInfo[numberOfCommentPlacement]; + comments_[placement].setComment(comment); + } + + void Value::setComment(const std::string &comment, CommentPlacement placement) { + setComment(comment.c_str(), placement); + } + + bool Value::hasComment(CommentPlacement placement) const { + return comments_ != nullptr && comments_[placement].comment_ != nullptr; + } + + std::string Value::getComment(CommentPlacement placement) const { + if (hasComment(placement)) + return comments_[placement].comment_; + return ""; + } + + std::string Value::toStyledString() const { + StyledWriter writer; + return writer.write(*this); + } + + Value::const_iterator Value::begin() const { + switch (type_) { #ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if (value_.array_) { - ValueInternalArray::IteratorState it; - value_.array_->makeBeginIterator(it); - return const_iterator(it); - } - break; - case objectValue: - if (value_.map_) { - ValueInternalMap::IteratorState it; - value_.map_->makeBeginIterator(it); - return const_iterator(it); - } - break; + case arrayValue: + if (value_.array_) { + ValueInternalArray::IteratorState it; + value_.array_->makeBeginIterator(it); + return const_iterator(it); + } + break; + case objectValue: + if (value_.map_) { + ValueInternalMap::IteratorState it; + value_.map_->makeBeginIterator(it); + return const_iterator(it); + } + break; #else - case arrayValue: - case objectValue: - if (value_.map_) - return const_iterator(value_.map_->begin()); - break; + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->begin()); + break; #endif - default: - break; + default: + break; + } + return const_iterator(); } - return const_iterator(); - } - Value::const_iterator Value::end() const { - switch (type_) { + Value::const_iterator Value::end() const { + switch (type_) { #ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if (value_.array_) { - ValueInternalArray::IteratorState it; - value_.array_->makeEndIterator(it); - return const_iterator(it); - } - break; - case objectValue: - if (value_.map_) { - ValueInternalMap::IteratorState it; - value_.map_->makeEndIterator(it); - return const_iterator(it); - } - break; + case arrayValue: + if (value_.array_) { + ValueInternalArray::IteratorState it; + value_.array_->makeEndIterator(it); + return const_iterator(it); + } + break; + case objectValue: + if (value_.map_) { + ValueInternalMap::IteratorState it; + value_.map_->makeEndIterator(it); + return const_iterator(it); + } + break; #else - case arrayValue: - case objectValue: - if (value_.map_) - return const_iterator(value_.map_->end()); - break; + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->end()); + break; #endif - default: - break; + default: + break; + } + return const_iterator(); } - return const_iterator(); - } - Value::iterator Value::begin() { - switch (type_) { + Value::iterator Value::begin() { + switch (type_) { #ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if (value_.array_) { - ValueInternalArray::IteratorState it; - value_.array_->makeBeginIterator(it); - return iterator(it); - } - break; - case objectValue: - if (value_.map_) { - ValueInternalMap::IteratorState it; - value_.map_->makeBeginIterator(it); - return iterator(it); - } - break; + case arrayValue: + if (value_.array_) { + ValueInternalArray::IteratorState it; + value_.array_->makeBeginIterator(it); + return iterator(it); + } + break; + case objectValue: + if (value_.map_) { + ValueInternalMap::IteratorState it; + value_.map_->makeBeginIterator(it); + return iterator(it); + } + break; #else - case arrayValue: - case objectValue: - if (value_.map_) - return iterator(value_.map_->begin()); - break; + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->begin()); + break; #endif - default: - break; + default: + break; + } + return iterator(); } - return iterator(); - } - Value::iterator Value::end() { - switch (type_) { + Value::iterator Value::end() { + switch (type_) { #ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if (value_.array_) { - ValueInternalArray::IteratorState it; - value_.array_->makeEndIterator(it); - return iterator(it); - } - break; - case objectValue: - if (value_.map_) { - ValueInternalMap::IteratorState it; - value_.map_->makeEndIterator(it); - return iterator(it); - } - break; + case arrayValue: + if (value_.array_) { + ValueInternalArray::IteratorState it; + value_.array_->makeEndIterator(it); + return iterator(it); + } + break; + case objectValue: + if (value_.map_) { + ValueInternalMap::IteratorState it; + value_.map_->makeEndIterator(it); + return iterator(it); + } + break; #else - case arrayValue: - case objectValue: - if (value_.map_) - return iterator(value_.map_->end()); - break; + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->end()); + break; #endif - default: - break; + default: + break; + } + return iterator(); + } + + // class PathArgument + // ////////////////////////////////////////////////////////////////// + + PathArgument::PathArgument() : kind_(kindNone) {} + + PathArgument::PathArgument(Value::UInt index) : index_(index), kind_(kindIndex) {} + + PathArgument::PathArgument(const char *key) : key_(key), kind_(kindKey) {} + + PathArgument::PathArgument(const std::string &key) : key_(key), kind_(kindKey) {} + + // class Path + // ////////////////////////////////////////////////////////////////// + + Path::Path(const std::string &path, + const PathArgument &a1, + const PathArgument &a2, + const PathArgument &a3, + const PathArgument &a4, + const PathArgument &a5) { + InArgs in; + in.push_back(&a1); + in.push_back(&a2); + in.push_back(&a3); + in.push_back(&a4); + in.push_back(&a5); + makePath(path, in); } - return iterator(); - } - - // class PathArgument - // ////////////////////////////////////////////////////////////////// - - PathArgument::PathArgument() : kind_(kindNone) {} - - PathArgument::PathArgument(Value::UInt index) : index_(index), kind_(kindIndex) {} - - PathArgument::PathArgument(const char *key) : key_(key), kind_(kindKey) {} - - PathArgument::PathArgument(const std::string &key) : key_(key), kind_(kindKey) {} - - // class Path - // ////////////////////////////////////////////////////////////////// - - Path::Path(const std::string &path, - const PathArgument &a1, - const PathArgument &a2, - const PathArgument &a3, - const PathArgument &a4, - const PathArgument &a5) { - InArgs in; - in.push_back(&a1); - in.push_back(&a2); - in.push_back(&a3); - in.push_back(&a4); - in.push_back(&a5); - makePath(path, in); - } - - void Path::makePath(const std::string &path, const InArgs &in) { - const char *current = path.c_str(); - const char *end = current + path.length(); - InArgs::const_iterator itInArg = in.begin(); - while (current != end) { - if (*current == '[') { - ++current; - if (*current == '%') - addPathInArg(path, in, itInArg, PathArgument::kindIndex); - else { - Value::UInt index = 0; - for (; current != end && *current >= '0' && *current <= '9'; ++current) - index = index * 10 + Value::UInt(*current - '0'); - args_.push_back(index); + + void Path::makePath(const std::string &path, const InArgs &in) { + const char *current = path.c_str(); + const char *end = current + path.length(); + InArgs::const_iterator itInArg = in.begin(); + while (current != end) { + if (*current == '[') { + ++current; + if (*current == '%') + addPathInArg(path, in, itInArg, PathArgument::kindIndex); + else { + Value::UInt index = 0; + for (; current != end && *current >= '0' && *current <= '9'; ++current) + index = index * 10 + Value::UInt(*current - '0'); + args_.push_back(index); + } + if (current == end || *current++ != ']') + invalidPath(path, int(current - path.c_str())); + } else if (*current == '%') { + addPathInArg(path, in, itInArg, PathArgument::kindKey); + ++current; + } else if (*current == '.') { + ++current; + } else { + const char *beginName = current; + while (current != end && !strchr("[.", *current)) + ++current; + args_.push_back(std::string(beginName, current)); } - if (current == end || *current++ != ']') - invalidPath(path, int(current - path.c_str())); - } else if (*current == '%') { - addPathInArg(path, in, itInArg, PathArgument::kindKey); - ++current; - } else if (*current == '.') { - ++current; + } + } + + void Path::addPathInArg(const std::string &path, + const InArgs &in, + InArgs::const_iterator &itInArg, + PathArgument::Kind kind) { + if (itInArg == in.end()) { + // Error: missing argument %d + } else if ((*itInArg)->kind_ != kind) { + // Error: bad argument type } else { - const char *beginName = current; - while (current != end && !strchr("[.", *current)) - ++current; - args_.push_back(std::string(beginName, current)); + args_.push_back(**itInArg); } } - } - - void Path::addPathInArg(const std::string &path, - const InArgs &in, - InArgs::const_iterator &itInArg, - PathArgument::Kind kind) { - if (itInArg == in.end()) { - // Error: missing argument %d - } else if ((*itInArg)->kind_ != kind) { - // Error: bad argument type - } else { - args_.push_back(**itInArg); + + void Path::invalidPath(const std::string &path, int location) { + // Error: invalid path. } - } - - void Path::invalidPath(const std::string &path, int location) { - // Error: invalid path. - } - - const Value &Path::resolve(const Value &root) const { - const Value *node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument &arg = *it; - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray() || node->isValidIndex(arg.index_)) { - // Error: unable to resolve path (array value expected at position... - } - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) { - // Error: unable to resolve path (object value expected at position...) - } - node = &((*node)[arg.key_]); - if (node == &Value::null) { - // Error: unable to resolve path (object has no member named '' at position...) + + const Value &Path::resolve(const Value &root) const { + const Value *node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument &arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || node->isValidIndex(arg.index_)) { + // Error: unable to resolve path (array value expected at position... + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: unable to resolve path (object value expected at position...) + } + node = &((*node)[arg.key_]); + if (node == &Value::null) { + // Error: unable to resolve path (object has no member named '' at position...) + } } } + return *node; } - return *node; - } - - Value Path::resolve(const Value &root, const Value &defaultValue) const { - const Value *node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument &arg = *it; - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray() || node->isValidIndex(arg.index_)) - return defaultValue; - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) - return defaultValue; - node = &((*node)[arg.key_]); - if (node == &Value::null) - return defaultValue; + + Value Path::resolve(const Value &root, const Value &defaultValue) const { + const Value *node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument &arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || node->isValidIndex(arg.index_)) + return defaultValue; + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) + return defaultValue; + node = &((*node)[arg.key_]); + if (node == &Value::null) + return defaultValue; + } } + return *node; } - return *node; - } - - Value &Path::make(Value &root) const { - Value *node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument &arg = *it; - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray()) { - // Error: node is not an array at position ... - } - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) { - // Error: node is not an object at position... + + Value &Path::make(Value &root) const { + Value *node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument &arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray()) { + // Error: node is not an array at position ... + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: node is not an object at position... + } + node = &((*node)[arg.key_]); } - node = &((*node)[arg.key_]); } + return *node; } - return *node; - } -} // namespace Json -} //namespace jsoncollector + } // namespace Json +} //namespace jsoncollector diff --git a/EventFilter/Utilities/src/json_writer.cpp b/EventFilter/Utilities/src/json_writer.cpp index 139061e856304..92eb56f68a91a 100644 --- a/EventFilter/Utilities/src/json_writer.cpp +++ b/EventFilter/Utilities/src/json_writer.cpp @@ -12,263 +12,297 @@ #endif namespace jsoncollector { -namespace Json { - - static bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } - - static bool containsControlCharacter(const char *str) { - while (*str) { - if (isControlCharacter(*(str++))) - return true; - } - return false; - } - static void uintToString(unsigned int value, char *¤t) { - *--current = 0; - do { - *--current = (value % 10) + '0'; - value /= 10; - } while (value != 0); - } - - std::string valueToString(Int value) { - char buffer[32]; - char *current = buffer + sizeof(buffer); - bool isNegative = value < 0; - if (isNegative) - value = -value; - uintToString(UInt(value), current); - if (isNegative) - *--current = '-'; - assert(current >= buffer); - return current; - } - - std::string valueToString(UInt value) { - char buffer[32]; - char *current = buffer + sizeof(buffer); - uintToString(value, current); - assert(current >= buffer); - return current; - } - - std::string valueToString(double value) { - char buffer[32]; + namespace Json { + + static bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } + + static bool containsControlCharacter(const char *str) { + while (*str) { + if (isControlCharacter(*(str++))) + return true; + } + return false; + } + static void uintToString(unsigned int value, char *¤t) { + *--current = 0; + do { + *--current = (value % 10) + '0'; + value /= 10; + } while (value != 0); + } + + std::string valueToString(Int value) { + char buffer[32]; + char *current = buffer + sizeof(buffer); + bool isNegative = value < 0; + if (isNegative) + value = -value; + uintToString(UInt(value), current); + if (isNegative) + *--current = '-'; + assert(current >= buffer); + return current; + } + + std::string valueToString(UInt value) { + char buffer[32]; + char *current = buffer + sizeof(buffer); + uintToString(value, current); + assert(current >= buffer); + return current; + } + + std::string valueToString(double value) { + char buffer[32]; #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning. - sprintf_s(buffer, sizeof(buffer), "%#.16g", value); + sprintf_s(buffer, sizeof(buffer), "%#.16g", value); #else - sprintf(buffer, "%#.16g", value); + sprintf(buffer, "%#.16g", value); #endif - char *ch = buffer + strlen(buffer) - 1; - if (*ch != '0') - return buffer; // nothing to truncate, so save time - while (ch > buffer && *ch == '0') { - --ch; - } - char *last_nonzero = ch; - while (ch >= buffer) { - switch (*ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - --ch; - continue; - case '.': - // Truncate zeroes to save bytes in output, but keep one. - *(last_nonzero + 2) = '\0'; - return buffer; - default: - return buffer; + char *ch = buffer + strlen(buffer) - 1; + if (*ch != '0') + return buffer; // nothing to truncate, so save time + while (ch > buffer && *ch == '0') { + --ch; } + char *last_nonzero = ch; + while (ch >= buffer) { + switch (*ch) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + --ch; + continue; + case '.': + // Truncate zeroes to save bytes in output, but keep one. + *(last_nonzero + 2) = '\0'; + return buffer; + default: + return buffer; + } + } + return buffer; } - return buffer; - } - - std::string valueToString(bool value) { return value ? "true" : "false"; } - - std::string valueToQuotedString(const char *value) { - // Not sure how to handle unicode... - if (strpbrk(value, "\"\\\b\f\n\r\t") == nullptr && !containsControlCharacter(value)) - return std::string("\"") + value + "\""; - // We have to walk value and escape any special characters. - // Appending to std::string is not efficient, but this should be rare. - // (Note: forward slashes are *not* rare, but I am not escaping them.) - unsigned maxsize = strlen(value) * 2 + 3; // allescaped+quotes+NULL - std::string result; - result.reserve(maxsize); // to avoid lots of mallocs - result += "\""; - for (const char *c = value; *c != 0; ++c) { - switch (*c) { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; + + std::string valueToString(bool value) { return value ? "true" : "false"; } + + std::string valueToQuotedString(const char *value) { + // Not sure how to handle unicode... + if (strpbrk(value, "\"\\\b\f\n\r\t") == nullptr && !containsControlCharacter(value)) + return std::string("\"") + value + "\""; + // We have to walk value and escape any special characters. + // Appending to std::string is not efficient, but this should be rare. + // (Note: forward slashes are *not* rare, but I am not escaping them.) + unsigned maxsize = strlen(value) * 2 + 3; // allescaped+quotes+NULL + std::string result; + result.reserve(maxsize); // to avoid lots of mallocs + result += "\""; + for (const char *c = value; *c != 0; ++c) { + switch (*c) { + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + //case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something. + // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); + result += oss.str(); + } else { + result += *c; + } + break; + } + } + result += "\""; + return result; + } + + // Class Writer + // ////////////////////////////////////////////////////////////////// + Writer::~Writer() {} + + // Class FastWriter + // ////////////////////////////////////////////////////////////////// + + FastWriter::FastWriter() : yamlCompatiblityEnabled_(false) {} + + void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } + + std::string FastWriter::write(const Value &root) { + document_ = ""; + writeValue(root); + document_ += "\n"; + return document_; + } + + void FastWriter::writeValue(const Value &value) { + switch (value.type()) { + case nullValue: + document_ += "null"; break; - case '\b': - result += "\\b"; + case intValue: + document_ += valueToString(value.asInt()); break; - case '\f': - result += "\\f"; + case uintValue: + document_ += valueToString(value.asUInt()); break; - case '\n': - result += "\\n"; + case realValue: + document_ += valueToString(value.asDouble()); break; - case '\r': - result += "\\r"; + case stringValue: + document_ += valueToQuotedString(value.asCString()); break; - case '\t': - result += "\\t"; + case booleanValue: + document_ += valueToString(value.asBool()); break; - //case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something. - // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); - result += oss.str(); - } else { - result += *c; + case arrayValue: { + document_ += "["; + int size = value.size(); + for (int index = 0; index < size; ++index) { + if (index > 0) + document_ += ","; + writeValue(value[index]); + } + document_ += "]"; + } break; + case objectValue: { + Value::Members members(value.getMemberNames()); + document_ += "{"; + for (Value::Members::iterator it = members.begin(); it != members.end(); ++it) { + const std::string &name = *it; + if (it != members.begin()) + document_ += ","; + document_ += valueToQuotedString(name.c_str()); + document_ += yamlCompatiblityEnabled_ ? ": " : ":"; + writeValue(value[name]); } + document_ += "}"; + } break; + } + } + + // Class StyledWriter + // ////////////////////////////////////////////////////////////////// + + StyledWriter::StyledWriter() : rightMargin_(74), indentSize_(3) {} + + std::string StyledWriter::write(const Value &root) { + document_ = ""; + addChildValues_ = false; + indentString_ = ""; + writeCommentBeforeValue(root); + writeValue(root); + writeCommentAfterValueOnSameLine(root); + document_ += "\n"; + return document_; + } + + void StyledWriter::writeValue(const Value &value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asInt())); break; + case uintValue: + pushValue(valueToString(value.asUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: + pushValue(valueToQuotedString(value.asCString())); + break; + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + while (true) { + const std::string &name = *it; + const Value &childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + document_ += " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; } } - result += "\""; - return result; - } - - // Class Writer - // ////////////////////////////////////////////////////////////////// - Writer::~Writer() {} - - // Class FastWriter - // ////////////////////////////////////////////////////////////////// - - FastWriter::FastWriter() : yamlCompatiblityEnabled_(false) {} - - void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } - - std::string FastWriter::write(const Value &root) { - document_ = ""; - writeValue(root); - document_ += "\n"; - return document_; - } - - void FastWriter::writeValue(const Value &value) { - switch (value.type()) { - case nullValue: - document_ += "null"; - break; - case intValue: - document_ += valueToString(value.asInt()); - break; - case uintValue: - document_ += valueToString(value.asUInt()); - break; - case realValue: - document_ += valueToString(value.asDouble()); - break; - case stringValue: - document_ += valueToQuotedString(value.asCString()); - break; - case booleanValue: - document_ += valueToString(value.asBool()); - break; - case arrayValue: { - document_ += "["; - int size = value.size(); - for (int index = 0; index < size; ++index) { - if (index > 0) - document_ += ","; - writeValue(value[index]); - } - document_ += "]"; - } break; - case objectValue: { - Value::Members members(value.getMemberNames()); - document_ += "{"; - for (Value::Members::iterator it = members.begin(); it != members.end(); ++it) { - const std::string &name = *it; - if (it != members.begin()) - document_ += ","; - document_ += valueToQuotedString(name.c_str()); - document_ += yamlCompatiblityEnabled_ ? ": " : ":"; - writeValue(value[name]); - } - document_ += "}"; - } break; - } - } - - // Class StyledWriter - // ////////////////////////////////////////////////////////////////// - - StyledWriter::StyledWriter() : rightMargin_(74), indentSize_(3) {} - - std::string StyledWriter::write(const Value &root) { - document_ = ""; - addChildValues_ = false; - indentString_ = ""; - writeCommentBeforeValue(root); - writeValue(root); - writeCommentAfterValueOnSameLine(root); - document_ += "\n"; - return document_; - } - - void StyledWriter::writeValue(const Value &value) { - switch (value.type()) { - case nullValue: - pushValue("null"); - break; - case intValue: - pushValue(valueToString(value.asInt())); - break; - case uintValue: - pushValue(valueToString(value.asUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble())); - break; - case stringValue: - pushValue(valueToQuotedString(value.asCString())); - break; - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); + + void StyledWriter::writeArrayValue(const Value &value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); indent(); - Value::Members::iterator it = members.begin(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; while (true) { - const std::string &name = *it; - const Value &childValue = value[name]; + const Value &childValue = value[index]; writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); - document_ += " : "; - writeValue(childValue); - if (++it == members.end()) { + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + writeIndent(); + writeValue(childValue); + } + if (++index == size) { writeCommentAfterValueOnSameLine(childValue); break; } @@ -276,207 +310,207 @@ namespace Json { writeCommentAfterValueOnSameLine(childValue); } unindent(); - writeWithIndent("}"); - } - } break; - } - } - - void StyledWriter::writeArrayValue(const Value &value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isArrayMultiLine = isMultineArray(value); - if (isArrayMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - while (true) { - const Value &childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - writeIndent(); - writeValue(childValue); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + document_ += "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + document_ += ", "; + document_ += childValues_[index]; } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - document_ += ","; - writeCommentAfterValueOnSameLine(childValue); + document_ += " ]"; } - unindent(); - writeWithIndent("]"); - } else // output on a single line + } + } + + bool StyledWriter::isMultineArray(const Value &value) { + int size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (int index = 0; index < size && !isMultiLine; ++index) { + const Value &childValue = value[index]; + isMultiLine = isMultiLine || ((childValue.isArray() || childValue.isObject()) && !childValue.empty()); + } + if (!isMultiLine) // check if line length > max line length { - assert(childValues_.size() == size); - document_ += "[ "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - document_ += ", "; - document_ += childValues_[index]; + childValues_.reserve(size); + addChildValues_ = true; + int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (int index = 0; index < size && !isMultiLine; ++index) { + writeValue(value[index]); + lineLength += int(childValues_[index].length()); + isMultiLine = isMultiLine && hasCommentForValue(value[index]); } - document_ += " ]"; + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; } + return isMultiLine; } - } - - bool StyledWriter::isMultineArray(const Value &value) { - int size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (int index = 0; index < size && !isMultiLine; ++index) { - const Value &childValue = value[index]; - isMultiLine = isMultiLine || ((childValue.isArray() || childValue.isObject()) && !childValue.empty()); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (int index = 0; index < size && !isMultiLine; ++index) { - writeValue(value[index]); - lineLength += int(childValues_[index].length()); - isMultiLine = isMultiLine && hasCommentForValue(value[index]); + + void StyledWriter::pushValue(const std::string &value) { + if (addChildValues_) + childValues_.push_back(value); + else + document_ += value; + } + + void StyledWriter::writeIndent() { + if (!document_.empty()) { + char last = document_[document_.length() - 1]; + if (last == ' ') // already indented + return; + if (last != '\n') // Comments may add new-line + document_ += '\n'; } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; + document_ += indentString_; } - return isMultiLine; - } - void StyledWriter::pushValue(const std::string &value) { - if (addChildValues_) - childValues_.push_back(value); - else + void StyledWriter::writeWithIndent(const std::string &value) { + writeIndent(); document_ += value; - } + } + + void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); } + + void StyledWriter::unindent() { + assert(int(indentString_.size()) >= indentSize_); + indentString_.resize(indentString_.size() - indentSize_); + } - void StyledWriter::writeIndent() { - if (!document_.empty()) { - char last = document_[document_.length() - 1]; - if (last == ' ') // already indented + void StyledWriter::writeCommentBeforeValue(const Value &root) { + if (!root.hasComment(commentBefore)) return; - if (last != '\n') // Comments may add new-line - document_ += '\n'; + document_ += normalizeEOL(root.getComment(commentBefore)); + document_ += "\n"; } - document_ += indentString_; - } - void StyledWriter::writeWithIndent(const std::string &value) { - writeIndent(); - document_ += value; - } + void StyledWriter::writeCommentAfterValueOnSameLine(const Value &root) { + if (root.hasComment(commentAfterOnSameLine)) + document_ += " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); - void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); } + if (root.hasComment(commentAfter)) { + document_ += "\n"; + document_ += normalizeEOL(root.getComment(commentAfter)); + document_ += "\n"; + } + } - void StyledWriter::unindent() { - assert(int(indentString_.size()) >= indentSize_); - indentString_.resize(indentString_.size() - indentSize_); - } + bool StyledWriter::hasCommentForValue(const Value &value) { + return value.hasComment(commentBefore) || value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); + } - void StyledWriter::writeCommentBeforeValue(const Value &root) { - if (!root.hasComment(commentBefore)) - return; - document_ += normalizeEOL(root.getComment(commentBefore)); - document_ += "\n"; - } + std::string StyledWriter::normalizeEOL(const std::string &text) { + std::string normalized; + normalized.reserve(text.length()); + const char *begin = text.c_str(); + const char *end = begin + text.length(); + const char *current = begin; + while (current != end) { + char c = *current++; + if (c == '\r') // mac or dos EOL + { + if (*current == '\n') // convert dos EOL + ++current; + normalized += '\n'; + } else // handle unix EOL & other char + normalized += c; + } + return normalized; + } - void StyledWriter::writeCommentAfterValueOnSameLine(const Value &root) { - if (root.hasComment(commentAfterOnSameLine)) - document_ += " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); + // Class StyledStreamWriter + // ////////////////////////////////////////////////////////////////// - if (root.hasComment(commentAfter)) { - document_ += "\n"; - document_ += normalizeEOL(root.getComment(commentAfter)); - document_ += "\n"; + StyledStreamWriter::StyledStreamWriter(std::string indentation) + : document_(nullptr), rightMargin_(74), indentation_(indentation) {} + + void StyledStreamWriter::write(std::ostream &out, const Value &root) { + document_ = &out; + addChildValues_ = false; + indentString_ = ""; + writeCommentBeforeValue(root); + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *document_ << "\n"; + document_ = nullptr; // Forget the stream, for safety. } - } - - bool StyledWriter::hasCommentForValue(const Value &value) { - return value.hasComment(commentBefore) || value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); - } - - std::string StyledWriter::normalizeEOL(const std::string &text) { - std::string normalized; - normalized.reserve(text.length()); - const char *begin = text.c_str(); - const char *end = begin + text.length(); - const char *current = begin; - while (current != end) { - char c = *current++; - if (c == '\r') // mac or dos EOL - { - if (*current == '\n') // convert dos EOL - ++current; - normalized += '\n'; - } else // handle unix EOL & other char - normalized += c; - } - return normalized; - } - - // Class StyledStreamWriter - // ////////////////////////////////////////////////////////////////// - - StyledStreamWriter::StyledStreamWriter(std::string indentation) - : document_(nullptr), rightMargin_(74), indentation_(indentation) {} - - void StyledStreamWriter::write(std::ostream &out, const Value &root) { - document_ = &out; - addChildValues_ = false; - indentString_ = ""; - writeCommentBeforeValue(root); - writeValue(root); - writeCommentAfterValueOnSameLine(root); - *document_ << "\n"; - document_ = nullptr; // Forget the stream, for safety. - } - - void StyledStreamWriter::writeValue(const Value &value) { - switch (value.type()) { - case nullValue: - pushValue("null"); - break; - case intValue: - pushValue(valueToString(value.asInt())); - break; - case uintValue: - pushValue(valueToString(value.asUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble())); - break; - case stringValue: - pushValue(valueToQuotedString(value.asCString())); - break; - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); + + void StyledStreamWriter::writeValue(const Value &value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asInt())); + break; + case uintValue: + pushValue(valueToString(value.asUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: + pushValue(valueToQuotedString(value.asCString())); + break; + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + while (true) { + const std::string &name = *it; + const Value &childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + *document_ << " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } + } + + void StyledStreamWriter::writeArrayValue(const Value &value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); indent(); - Value::Members::iterator it = members.begin(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; while (true) { - const std::string &name = *it; - const Value &childValue = value[name]; + const Value &childValue = value[index]; writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); - *document_ << " : "; - writeValue(childValue); - if (++it == members.end()) { + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + writeIndent(); + writeValue(childValue); + } + if (++index == size) { writeCommentAfterValueOnSameLine(childValue); break; } @@ -484,88 +518,54 @@ namespace Json { writeCommentAfterValueOnSameLine(childValue); } unindent(); - writeWithIndent("}"); - } - } break; - } - } - - void StyledStreamWriter::writeArrayValue(const Value &value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isArrayMultiLine = isMultineArray(value); - if (isArrayMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - while (true) { - const Value &childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - writeIndent(); - writeValue(childValue); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + *document_ << "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + *document_ << ", "; + *document_ << childValues_[index]; } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - *document_ << "[ "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - *document_ << ", "; - *document_ << childValues_[index]; + *document_ << " ]"; } - *document_ << " ]"; } } - } - - bool StyledStreamWriter::isMultineArray(const Value &value) { - int size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (int index = 0; index < size && !isMultiLine; ++index) { - const Value &childValue = value[index]; - isMultiLine = isMultiLine || ((childValue.isArray() || childValue.isObject()) && !childValue.empty()); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + + bool StyledStreamWriter::isMultineArray(const Value &value) { + int size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); for (int index = 0; index < size && !isMultiLine; ++index) { - writeValue(value[index]); - lineLength += int(childValues_[index].length()); - isMultiLine = isMultiLine && hasCommentForValue(value[index]); + const Value &childValue = value[index]; + isMultiLine = isMultiLine || ((childValue.isArray() || childValue.isObject()) && !childValue.empty()); } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (int index = 0; index < size && !isMultiLine; ++index) { + writeValue(value[index]); + lineLength += int(childValues_[index].length()); + isMultiLine = isMultiLine && hasCommentForValue(value[index]); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; } - return isMultiLine; - } - void StyledStreamWriter::pushValue(const std::string &value) { - if (addChildValues_) - childValues_.push_back(value); - else - *document_ << value; - } + void StyledStreamWriter::pushValue(const std::string &value) { + if (addChildValues_) + childValues_.push_back(value); + else + *document_ << value; + } - void StyledStreamWriter::writeIndent() { - /* + void StyledStreamWriter::writeIndent() { + /* Some comments in this method would have been nice. ;-) if ( !document_.empty() ) @@ -577,68 +577,68 @@ namespace Json { *document_ << '\n'; } */ - *document_ << '\n' << indentString_; - } + *document_ << '\n' << indentString_; + } - void StyledStreamWriter::writeWithIndent(const std::string &value) { - writeIndent(); - *document_ << value; - } + void StyledStreamWriter::writeWithIndent(const std::string &value) { + writeIndent(); + *document_ << value; + } - void StyledStreamWriter::indent() { indentString_ += indentation_; } + void StyledStreamWriter::indent() { indentString_ += indentation_; } - void StyledStreamWriter::unindent() { - assert(indentString_.size() >= indentation_.size()); - indentString_.resize(indentString_.size() - indentation_.size()); - } + void StyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); + } - void StyledStreamWriter::writeCommentBeforeValue(const Value &root) { - if (!root.hasComment(commentBefore)) - return; - *document_ << normalizeEOL(root.getComment(commentBefore)); - *document_ << "\n"; - } + void StyledStreamWriter::writeCommentBeforeValue(const Value &root) { + if (!root.hasComment(commentBefore)) + return; + *document_ << normalizeEOL(root.getComment(commentBefore)); + *document_ << "\n"; + } - void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value &root) { - if (root.hasComment(commentAfterOnSameLine)) - *document_ << " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); + void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value &root) { + if (root.hasComment(commentAfterOnSameLine)) + *document_ << " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); - if (root.hasComment(commentAfter)) { - *document_ << "\n"; - *document_ << normalizeEOL(root.getComment(commentAfter)); - *document_ << "\n"; + if (root.hasComment(commentAfter)) { + *document_ << "\n"; + *document_ << normalizeEOL(root.getComment(commentAfter)); + *document_ << "\n"; + } } - } - - bool StyledStreamWriter::hasCommentForValue(const Value &value) { - return value.hasComment(commentBefore) || value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); - } - - std::string StyledStreamWriter::normalizeEOL(const std::string &text) { - std::string normalized; - normalized.reserve(text.length()); - const char *begin = text.c_str(); - const char *end = begin + text.length(); - const char *current = begin; - while (current != end) { - char c = *current++; - if (c == '\r') // mac or dos EOL - { - if (*current == '\n') // convert dos EOL - ++current; - normalized += '\n'; - } else // handle unix EOL & other char - normalized += c; - } - return normalized; - } - - std::ostream &operator<<(std::ostream &sout, const Value &root) { - Json::StyledStreamWriter writer; - writer.write(sout, root); - return sout; - } - -} // namespace Json -} // namespace jsoncollector + + bool StyledStreamWriter::hasCommentForValue(const Value &value) { + return value.hasComment(commentBefore) || value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); + } + + std::string StyledStreamWriter::normalizeEOL(const std::string &text) { + std::string normalized; + normalized.reserve(text.length()); + const char *begin = text.c_str(); + const char *end = begin + text.length(); + const char *current = begin; + while (current != end) { + char c = *current++; + if (c == '\r') // mac or dos EOL + { + if (*current == '\n') // convert dos EOL + ++current; + normalized += '\n'; + } else // handle unix EOL & other char + normalized += c; + } + return normalized; + } + + std::ostream &operator<<(std::ostream &sout, const Value &root) { + Json::StyledStreamWriter writer; + writer.write(sout, root); + return sout; + } + + } // namespace Json +} // namespace jsoncollector