Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:04

0001 // Tencent is pleased to support the open source community by making RapidJSON available.
0002 // 
0003 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
0004 //
0005 // Licensed under the MIT License (the "License"); you may not use this file except
0006 // in compliance with the License. You may obtain a copy of the License at
0007 //
0008 // http://opensource.org/licenses/MIT
0009 //
0010 // Unless required by applicable law or agreed to in writing, software distributed 
0011 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
0012 // CONDITIONS OF ANY KIND, either express or implied. See the License for the 
0013 // specific language governing permissions and limitations under the License.
0014 
0015 #ifndef RAPIDJSON_PRETTYWRITER_H_
0016 #define RAPIDJSON_PRETTYWRITER_H_
0017 
0018 #include "writer.h"
0019 
0020 #ifdef __GNUC__
0021 RAPIDJSON_DIAG_PUSH
0022 RAPIDJSON_DIAG_OFF(effc++)
0023 #endif
0024 
0025 #if defined(__clang__)
0026 RAPIDJSON_DIAG_PUSH
0027 RAPIDJSON_DIAG_OFF(c++98-compat)
0028 #endif
0029 
0030 RAPIDJSON_NAMESPACE_BEGIN
0031 
0032 //! Combination of PrettyWriter format flags.
0033 /*! \see PrettyWriter::SetFormatOptions
0034  */
0035 enum PrettyFormatOptions {
0036     kFormatDefault = 0,         //!< Default pretty formatting.
0037     kFormatSingleLineArray = 1  //!< Format arrays on a single line.
0038 };
0039 
0040 //! Writer with indentation and spacing.
0041 /*!
0042     \tparam OutputStream Type of output os.
0043     \tparam SourceEncoding Encoding of source string.
0044     \tparam TargetEncoding Encoding of output stream.
0045     \tparam StackAllocator Type of allocator for allocating memory of stack.
0046 */
0047 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
0048 class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
0049 public:
0050     typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base;
0051     typedef typename Base::Ch Ch;
0052 
0053     //! Constructor
0054     /*! \param os Output stream.
0055         \param allocator User supplied allocator. If it is null, it will create a private one.
0056         \param levelDepth Initial capacity of stack.
0057     */
0058     explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : 
0059         Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
0060 
0061 
0062     explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : 
0063         Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
0064 
0065 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
0066     PrettyWriter(PrettyWriter&& rhs) :
0067         Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
0068 #endif
0069 
0070     //! Set custom indentation.
0071     /*! \param indentChar       Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
0072         \param indentCharCount  Number of indent characters for each indentation level.
0073         \note The default indentation is 4 spaces.
0074     */
0075     PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
0076         RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
0077         indentChar_ = indentChar;
0078         indentCharCount_ = indentCharCount;
0079         return *this;
0080     }
0081 
0082     //! Set pretty writer formatting options.
0083     /*! \param options Formatting options.
0084     */
0085     PrettyWriter& SetFormatOptions(PrettyFormatOptions options) {
0086         formatOptions_ = options;
0087         return *this;
0088     }
0089 
0090     /*! @name Implementation of Handler
0091         \see Handler
0092     */
0093     //@{
0094 
0095     bool Null()                 { PrettyPrefix(kNullType);   return Base::EndValue(Base::WriteNull()); }
0096     bool Bool(bool b)           { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); }
0097     bool Int(int i)             { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); }
0098     bool Uint(unsigned u)       { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint(u)); }
0099     bool Int64(int64_t i64)     { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt64(i64)); }
0100     bool Uint64(uint64_t u64)   { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64));  }
0101     bool Double(double d)       { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); }
0102 
0103     bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
0104         RAPIDJSON_ASSERT(str != 0);
0105         (void)copy;
0106         PrettyPrefix(kNumberType);
0107         return Base::EndValue(Base::WriteString(str, length));
0108     }
0109 
0110     bool String(const Ch* str, SizeType length, bool copy = false) {
0111         RAPIDJSON_ASSERT(str != 0);
0112         (void)copy;
0113         PrettyPrefix(kStringType);
0114         return Base::EndValue(Base::WriteString(str, length));
0115     }
0116 
0117 #if RAPIDJSON_HAS_STDSTRING
0118     bool String(const std::basic_string<Ch>& str) {
0119         return String(str.data(), SizeType(str.size()));
0120     }
0121 #endif
0122 
0123     bool StartObject() {
0124         PrettyPrefix(kObjectType);
0125         new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
0126         return Base::WriteStartObject();
0127     }
0128 
0129     bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
0130 
0131 #if RAPIDJSON_HAS_STDSTRING
0132     bool Key(const std::basic_string<Ch>& str) {
0133         return Key(str.data(), SizeType(str.size()));
0134     }
0135 #endif
0136     
0137     bool EndObject(SizeType memberCount = 0) {
0138         (void)memberCount;
0139         RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object
0140         RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); // currently inside an Array, not Object
0141         RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top<typename Base::Level>()->valueCount % 2); // Object has a Key without a Value
0142        
0143         bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
0144 
0145         if (!empty) {
0146             Base::os_->Put('\n');
0147             WriteIndent();
0148         }
0149         bool ret = Base::EndValue(Base::WriteEndObject());
0150         (void)ret;
0151         RAPIDJSON_ASSERT(ret == true);
0152         if (Base::level_stack_.Empty()) // end of json text
0153             Base::Flush();
0154         return true;
0155     }
0156 
0157     bool StartArray() {
0158         PrettyPrefix(kArrayType);
0159         new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
0160         return Base::WriteStartArray();
0161     }
0162 
0163     bool EndArray(SizeType memberCount = 0) {
0164         (void)memberCount;
0165         RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
0166         RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
0167         bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
0168 
0169         if (!empty && !(formatOptions_ & kFormatSingleLineArray)) {
0170             Base::os_->Put('\n');
0171             WriteIndent();
0172         }
0173         bool ret = Base::EndValue(Base::WriteEndArray());
0174         (void)ret;
0175         RAPIDJSON_ASSERT(ret == true);
0176         if (Base::level_stack_.Empty()) // end of json text
0177             Base::Flush();
0178         return true;
0179     }
0180 
0181     //@}
0182 
0183     /*! @name Convenience extensions */
0184     //@{
0185 
0186     //! Simpler but slower overload.
0187     bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
0188     bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
0189 
0190     //@}
0191 
0192     //! Write a raw JSON value.
0193     /*!
0194         For user to write a stringified JSON as a value.
0195 
0196         \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
0197         \param length Length of the json.
0198         \param type Type of the root of json.
0199         \note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
0200     */
0201     bool RawValue(const Ch* json, size_t length, Type type) {
0202         RAPIDJSON_ASSERT(json != 0);
0203         PrettyPrefix(type);
0204         return Base::EndValue(Base::WriteRawValue(json, length));
0205     }
0206 
0207 protected:
0208     void PrettyPrefix(Type type) {
0209         (void)type;
0210         if (Base::level_stack_.GetSize() != 0) { // this value is not at root
0211             typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
0212 
0213             if (level->inArray) {
0214                 if (level->valueCount > 0) {
0215                     Base::os_->Put(','); // add comma if it is not the first element in array
0216                     if (formatOptions_ & kFormatSingleLineArray)
0217                         Base::os_->Put(' ');
0218                 }
0219 
0220                 if (!(formatOptions_ & kFormatSingleLineArray)) {
0221                     Base::os_->Put('\n');
0222                     WriteIndent();
0223                 }
0224             }
0225             else {  // in object
0226                 if (level->valueCount > 0) {
0227                     if (level->valueCount % 2 == 0) {
0228                         Base::os_->Put(',');
0229                         Base::os_->Put('\n');
0230                     }
0231                     else {
0232                         Base::os_->Put(':');
0233                         Base::os_->Put(' ');
0234                     }
0235                 }
0236                 else
0237                     Base::os_->Put('\n');
0238 
0239                 if (level->valueCount % 2 == 0)
0240                     WriteIndent();
0241             }
0242             if (!level->inArray && level->valueCount % 2 == 0)
0243                 RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name
0244             level->valueCount++;
0245         }
0246         else {
0247             RAPIDJSON_ASSERT(!Base::hasRoot_);  // Should only has one and only one root.
0248             Base::hasRoot_ = true;
0249         }
0250     }
0251 
0252     void WriteIndent()  {
0253         size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
0254         PutN(*Base::os_, static_cast<typename OutputStream::Ch>(indentChar_), count);
0255     }
0256 
0257     Ch indentChar_;
0258     unsigned indentCharCount_;
0259     PrettyFormatOptions formatOptions_;
0260 
0261 private:
0262     // Prohibit copy constructor & assignment operator.
0263     PrettyWriter(const PrettyWriter&);
0264     PrettyWriter& operator=(const PrettyWriter&);
0265 };
0266 
0267 RAPIDJSON_NAMESPACE_END
0268 
0269 #if defined(__clang__)
0270 RAPIDJSON_DIAG_POP
0271 #endif
0272 
0273 #ifdef __GNUC__
0274 RAPIDJSON_DIAG_POP
0275 #endif
0276 
0277 #endif // RAPIDJSON_RAPIDJSON_H_