Changeset View
Changeset View
Standalone View
Standalone View
extern/rapidjson/include/rapidjson/prettywriter.h
- This file was added.
| // Copyright (C) 2011 Milo Yip | |||||
| // | |||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
| // of this software and associated documentation files (the "Software"), to deal | |||||
| // in the Software without restriction, including without limitation the rights | |||||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
| // copies of the Software, and to permit persons to whom the Software is | |||||
| // furnished to do so, subject to the following conditions: | |||||
| // | |||||
| // The above copyright notice and this permission notice shall be included in | |||||
| // all copies or substantial portions of the Software. | |||||
| // | |||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||||
| // THE SOFTWARE. | |||||
| #ifndef RAPIDJSON_PRETTYWRITER_H_ | |||||
| #define RAPIDJSON_PRETTYWRITER_H_ | |||||
| #include "writer.h" | |||||
| #ifdef __GNUC__ | |||||
| RAPIDJSON_DIAG_PUSH | |||||
| RAPIDJSON_DIAG_OFF(effc++) | |||||
| #endif | |||||
| namespace rapidjson { | |||||
| //! Writer with indentation and spacing. | |||||
| /*! | |||||
| \tparam OutputStream Type of ouptut os. | |||||
| \tparam SourceEncoding Encoding of source string. | |||||
| \tparam TargetEncoding Encoding of output stream. | |||||
| \tparam StackAllocator Type of allocator for allocating memory of stack. | |||||
| */ | |||||
| template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> | |||||
| class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> { | |||||
| public: | |||||
| typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base; | |||||
| typedef typename Base::Ch Ch; | |||||
| //! Constructor | |||||
| /*! \param os Output stream. | |||||
| \param allocator User supplied allocator. If it is null, it will create a private one. | |||||
| \param levelDepth Initial capacity of stack. | |||||
| */ | |||||
| PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : | |||||
| Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} | |||||
| //! Set custom indentation. | |||||
| /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). | |||||
| \param indentCharCount Number of indent characters for each indentation level. | |||||
| \note The default indentation is 4 spaces. | |||||
| */ | |||||
| PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { | |||||
| RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); | |||||
| indentChar_ = indentChar; | |||||
| indentCharCount_ = indentCharCount; | |||||
| return *this; | |||||
| } | |||||
| /*! @name Implementation of Handler | |||||
| \see Handler | |||||
| */ | |||||
| //@{ | |||||
| bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); } | |||||
| bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); } | |||||
| bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); } | |||||
| bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); } | |||||
| bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); } | |||||
| bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); } | |||||
| bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); } | |||||
| bool String(const Ch* str, SizeType length, bool copy = false) { | |||||
| (void)copy; | |||||
| PrettyPrefix(kStringType); | |||||
| return Base::WriteString(str, length); | |||||
| } | |||||
| bool StartObject() { | |||||
| PrettyPrefix(kObjectType); | |||||
| new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false); | |||||
| return Base::WriteStartObject(); | |||||
| } | |||||
| bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } | |||||
| bool EndObject(SizeType memberCount = 0) { | |||||
| (void)memberCount; | |||||
| RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); | |||||
| RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); | |||||
| bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; | |||||
| if (!empty) { | |||||
| Base::os_->Put('\n'); | |||||
| WriteIndent(); | |||||
| } | |||||
| if (!Base::WriteEndObject()) | |||||
| return false; | |||||
| if (Base::level_stack_.Empty()) // end of json text | |||||
| Base::os_->Flush(); | |||||
| return true; | |||||
| } | |||||
| bool StartArray() { | |||||
| PrettyPrefix(kArrayType); | |||||
| new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true); | |||||
| return Base::WriteStartArray(); | |||||
| } | |||||
| bool EndArray(SizeType memberCount = 0) { | |||||
| (void)memberCount; | |||||
| RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); | |||||
| RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray); | |||||
| bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; | |||||
| if (!empty) { | |||||
| Base::os_->Put('\n'); | |||||
| WriteIndent(); | |||||
| } | |||||
| if (!Base::WriteEndArray()) | |||||
| return false; | |||||
| if (Base::level_stack_.Empty()) // end of json text | |||||
| Base::os_->Flush(); | |||||
| return true; | |||||
| } | |||||
| //@} | |||||
| /*! @name Convenience extensions */ | |||||
| //@{ | |||||
| //! Simpler but slower overload. | |||||
| bool String(const Ch* str) { return String(str, internal::StrLen(str)); } | |||||
| bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } | |||||
| //@} | |||||
| protected: | |||||
| void PrettyPrefix(Type type) { | |||||
| (void)type; | |||||
| if (Base::level_stack_.GetSize() != 0) { // this value is not at root | |||||
| typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>(); | |||||
| if (level->inArray) { | |||||
| if (level->valueCount > 0) { | |||||
| Base::os_->Put(','); // add comma if it is not the first element in array | |||||
| Base::os_->Put('\n'); | |||||
| } | |||||
| else | |||||
| Base::os_->Put('\n'); | |||||
| WriteIndent(); | |||||
| } | |||||
| else { // in object | |||||
| if (level->valueCount > 0) { | |||||
| if (level->valueCount % 2 == 0) { | |||||
| Base::os_->Put(','); | |||||
| Base::os_->Put('\n'); | |||||
| } | |||||
| else { | |||||
| Base::os_->Put(':'); | |||||
| Base::os_->Put(' '); | |||||
| } | |||||
| } | |||||
| else | |||||
| Base::os_->Put('\n'); | |||||
| if (level->valueCount % 2 == 0) | |||||
| WriteIndent(); | |||||
| } | |||||
| if (!level->inArray && level->valueCount % 2 == 0) | |||||
| RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name | |||||
| level->valueCount++; | |||||
| } | |||||
| else { | |||||
| RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. | |||||
| Base::hasRoot_ = true; | |||||
| } | |||||
| } | |||||
| void WriteIndent() { | |||||
| size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; | |||||
| PutN(*Base::os_, indentChar_, count); | |||||
| } | |||||
| Ch indentChar_; | |||||
| unsigned indentCharCount_; | |||||
| private: | |||||
| // Prohibit copy constructor & assignment operator. | |||||
| PrettyWriter(const PrettyWriter&); | |||||
| PrettyWriter& operator=(const PrettyWriter&); | |||||
| }; | |||||
| } // namespace rapidjson | |||||
| #ifdef __GNUC__ | |||||
| RAPIDJSON_DIAG_POP | |||||
| #endif | |||||
| #endif // RAPIDJSON_RAPIDJSON_H_ | |||||