DeepCover Embedded Security in IoT: Public-key Secured Data Paths

Dependencies:   MaximInterface

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers prettywriter.h Source File

prettywriter.h

00001 // Tencent is pleased to support the open source community by making RapidJSON available.
00002 // 
00003 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
00004 //
00005 // Licensed under the MIT License (the "License"); you may not use this file except
00006 // in compliance with the License. You may obtain a copy of the License at
00007 //
00008 // http://opensource.org/licenses/MIT
00009 //
00010 // Unless required by applicable law or agreed to in writing, software distributed 
00011 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
00012 // CONDITIONS OF ANY KIND, either express or implied. See the License for the 
00013 // specific language governing permissions and limitations under the License.
00014 
00015 #ifndef RAPIDJSON_PRETTYWRITER_H_
00016 #define RAPIDJSON_PRETTYWRITER_H_
00017 
00018 #include "writer.h"
00019 
00020 #ifdef __GNUC__
00021 RAPIDJSON_DIAG_PUSH
00022 RAPIDJSON_DIAG_OFF(effc++)
00023 #endif
00024 
00025 #if defined(__clang__)
00026 RAPIDJSON_DIAG_PUSH
00027 RAPIDJSON_DIAG_OFF(c++98-compat)
00028 #endif
00029 
00030 RAPIDJSON_NAMESPACE_BEGIN
00031 
00032 //! Combination of PrettyWriter format flags.
00033 /*! \see PrettyWriter::SetFormatOptions
00034  */
00035 enum PrettyFormatOptions {
00036     kFormatDefault = 0,         //!< Default pretty formatting.
00037     kFormatSingleLineArray = 1  //!< Format arrays on a single line.
00038 };
00039 
00040 //! Writer with indentation and spacing.
00041 /*!
00042     \tparam OutputStream Type of ouptut os.
00043     \tparam SourceEncoding Encoding of source string.
00044     \tparam TargetEncoding Encoding of output stream.
00045     \tparam StackAllocator Type of allocator for allocating memory of stack.
00046 */
00047 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
00048 class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
00049 public:
00050     typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
00051     typedef typename Base::Ch Ch;
00052 
00053     //! Constructor
00054     /*! \param os Output stream.
00055         \param allocator User supplied allocator. If it is null, it will create a private one.
00056         \param levelDepth Initial capacity of stack.
00057     */
00058     explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : 
00059         Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
00060 
00061 
00062     explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : 
00063         Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
00064 
00065 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
00066     PrettyWriter(PrettyWriter&& rhs) :
00067         Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
00068 #endif
00069 
00070     //! Set custom indentation.
00071     /*! \param indentChar       Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
00072         \param indentCharCount  Number of indent characters for each indentation level.
00073         \note The default indentation is 4 spaces.
00074     */
00075     PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
00076         RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
00077         indentChar_ = indentChar;
00078         indentCharCount_ = indentCharCount;
00079         return *this;
00080     }
00081 
00082     //! Set pretty writer formatting options.
00083     /*! \param options Formatting options.
00084     */
00085     PrettyWriter& SetFormatOptions(PrettyFormatOptions options) {
00086         formatOptions_ = options;
00087         return *this;
00088     }
00089 
00090     /*! @name Implementation of Handler
00091         \see Handler
00092     */
00093     //@{
00094 
00095     bool Null()                 { PrettyPrefix(kNullType);   return Base::WriteNull(); }
00096     bool Bool(bool b)           { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
00097     bool Int(int i)             { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
00098     bool Uint(unsigned u)       { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
00099     bool Int64(int64_t i64)     { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
00100     bool Uint64(uint64_t u64)   { PrettyPrefix(kNumberType); return Base::WriteUint64(u64);  }
00101     bool Double(double d)       { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
00102 
00103     bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
00104         RAPIDJSON_ASSERT(str != 0);
00105         (void)copy;
00106         PrettyPrefix(kNumberType);
00107         return Base::WriteString(str, length);
00108     }
00109 
00110     bool String(const Ch* str, SizeType length, bool copy = false) {
00111         RAPIDJSON_ASSERT(str != 0);
00112         (void)copy;
00113         PrettyPrefix(kStringType);
00114         return Base::WriteString(str, length);
00115     }
00116 
00117 #if RAPIDJSON_HAS_STDSTRING
00118     bool String(const std::basic_string<Ch>& str) {
00119         return String(str.data(), SizeType(str.size()));
00120     }
00121 #endif
00122 
00123     bool StartObject() {
00124         PrettyPrefix(kObjectType);
00125         new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
00126         return Base::WriteStartObject();
00127     }
00128 
00129     bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
00130 
00131 #if RAPIDJSON_HAS_STDSTRING
00132     bool Key(const std::basic_string<Ch>& str) {
00133         return Key(str.data(), SizeType(str.size()));
00134     }
00135 #endif
00136     
00137     bool EndObject(SizeType memberCount = 0) {
00138         (void)memberCount;
00139         RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
00140         RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
00141         bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
00142 
00143         if (!empty) {
00144             Base::os_->Put('\n');
00145             WriteIndent();
00146         }
00147         bool ret = Base::WriteEndObject();
00148         (void)ret;
00149         RAPIDJSON_ASSERT(ret == true);
00150         if (Base::level_stack_.Empty()) // end of json text
00151             Base::os_->Flush();
00152         return true;
00153     }
00154 
00155     bool StartArray() {
00156         PrettyPrefix(kArrayType);
00157         new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
00158         return Base::WriteStartArray();
00159     }
00160 
00161     bool EndArray(SizeType memberCount = 0) {
00162         (void)memberCount;
00163         RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
00164         RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
00165         bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
00166 
00167         if (!empty && !(formatOptions_ & kFormatSingleLineArray)) {
00168             Base::os_->Put('\n');
00169             WriteIndent();
00170         }
00171         bool ret = Base::WriteEndArray();
00172         (void)ret;
00173         RAPIDJSON_ASSERT(ret == true);
00174         if (Base::level_stack_.Empty()) // end of json text
00175             Base::os_->Flush();
00176         return true;
00177     }
00178 
00179     //@}
00180 
00181     /*! @name Convenience extensions */
00182     //@{
00183 
00184     //! Simpler but slower overload.
00185     bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
00186     bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
00187 
00188     //@}
00189 
00190     //! Write a raw JSON value.
00191     /*!
00192         For user to write a stringified JSON as a value.
00193 
00194         \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
00195         \param length Length of the json.
00196         \param type Type of the root of json.
00197         \note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
00198     */
00199     bool RawValue(const Ch* json, size_t length, Type type) {
00200         RAPIDJSON_ASSERT(json != 0);
00201         PrettyPrefix(type);
00202         return Base::WriteRawValue(json, length);
00203     }
00204 
00205 protected:
00206     void PrettyPrefix(Type type) {
00207         (void)type;
00208         if (Base::level_stack_.GetSize() != 0) { // this value is not at root
00209             typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
00210 
00211             if (level->inArray) {
00212                 if (level->valueCount > 0) {
00213                     Base::os_->Put(','); // add comma if it is not the first element in array
00214                     if (formatOptions_ & kFormatSingleLineArray)
00215                         Base::os_->Put(' ');
00216                 }
00217 
00218                 if (!(formatOptions_ & kFormatSingleLineArray)) {
00219                     Base::os_->Put('\n');
00220                     WriteIndent();
00221                 }
00222             }
00223             else {  // in object
00224                 if (level->valueCount > 0) {
00225                     if (level->valueCount % 2 == 0) {
00226                         Base::os_->Put(',');
00227                         Base::os_->Put('\n');
00228                     }
00229                     else {
00230                         Base::os_->Put(':');
00231                         Base::os_->Put(' ');
00232                     }
00233                 }
00234                 else
00235                     Base::os_->Put('\n');
00236 
00237                 if (level->valueCount % 2 == 0)
00238                     WriteIndent();
00239             }
00240             if (!level->inArray && level->valueCount % 2 == 0)
00241                 RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name
00242             level->valueCount++;
00243         }
00244         else {
00245             RAPIDJSON_ASSERT(!Base::hasRoot_);  // Should only has one and only one root.
00246             Base::hasRoot_ = true;
00247         }
00248     }
00249 
00250     void WriteIndent()  {
00251         size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
00252         PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
00253     }
00254 
00255     Ch indentChar_;
00256     unsigned indentCharCount_;
00257     PrettyFormatOptions formatOptions_;
00258 
00259 private:
00260     // Prohibit copy constructor & assignment operator.
00261     PrettyWriter(const PrettyWriter&);
00262     PrettyWriter& operator=(const PrettyWriter&);
00263 };
00264 
00265 RAPIDJSON_NAMESPACE_END
00266 
00267 #if defined(__clang__)
00268 RAPIDJSON_DIAG_POP
00269 #endif
00270 
00271 #ifdef __GNUC__
00272 RAPIDJSON_DIAG_POP
00273 #endif
00274 
00275 #endif // RAPIDJSON_RAPIDJSON_H_