diff options
Diffstat (limited to 'src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/writer.h')
-rw-r--r-- | src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/writer.h | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/writer.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/writer.h new file mode 100644 index 000000000..874faa881 --- /dev/null +++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/writer.h @@ -0,0 +1,395 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_WRITER_H_ +#define RAPIDJSON_WRITER_H_ + +#include "rapidjson.h" +#include "internal/stack.h" +#include "internal/strfunc.h" +#include "internal/dtoa.h" +#include "internal/itoa.h" +#include "stringbuffer.h" +#include <new> // placement new + +#if RAPIDJSON_HAS_STDSTRING +#include <string> +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! JSON writer +/*! Writer implements the concept Handler. + It generates JSON text by events to an output os. + + User may programmatically calls the functions of a writer to generate JSON text. + + On the other side, a writer can also be passed to objects that generates events, + + for example Reader::Parse() and Document::Accept(). + + \tparam OutputStream Type of output stream. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. + \note implements Handler concept +*/ +template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> +class Writer { +public: + typedef typename SourceEncoding::Ch Ch; + + //! Constructor + /*! \param os Output stream. + \param stackAllocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit + Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {} + + explicit + Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {} + + //! Reset the writer with a new stream. + /*! + This function reset the writer with a new stream and default settings, + in order to make a Writer object reusable for output multiple JSONs. + + \param os New output stream. + \code + Writer<OutputStream> writer(os1); + writer.StartObject(); + // ... + writer.EndObject(); + + writer.Reset(os2); + writer.StartObject(); + // ... + writer.EndObject(); + \endcode + */ + void Reset(OutputStream& os) { + os_ = &os; + hasRoot_ = false; + level_stack_.Clear(); + } + + //! Checks whether the output is a complete JSON. + /*! + A complete JSON has a complete root object or array. + */ + bool IsComplete() const { + return hasRoot_ && level_stack_.Empty(); + } + + /*!@name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { Prefix(kNullType); return WriteNull(); } + bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); } + bool Int(int i) { Prefix(kNumberType); return WriteInt(i); } + bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); } + bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); } + bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); } + + //! Writes the given \c double value to the stream + /*! + \param d The value to be written. + \return Whether it is succeed. + */ + bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); } + + bool String(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + Prefix(kStringType); + return WriteString(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string<Ch>& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + Prefix(kObjectType); + new (level_stack_.template Push<Level>()) Level(false); + return 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(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); + level_stack_.template Pop<Level>(1); + bool ret = WriteEndObject(); + if (level_stack_.Empty()) // end of json text + os_->Flush(); + return ret; + } + + bool StartArray() { + Prefix(kArrayType); + new (level_stack_.template Push<Level>()) Level(true); + return WriteStartArray(); + } + + bool EndArray(SizeType elementCount = 0) { + (void)elementCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray); + level_stack_.template Pop<Level>(1); + bool ret = WriteEndArray(); + if (level_stack_.Empty()) // end of json text + os_->Flush(); + return ret; + } + //@} + + /*! @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: + //! Information for each nested level + struct Level { + Level(bool inArray_) : valueCount(0), inArray(inArray_) {} + size_t valueCount; //!< number of values in this level + bool inArray; //!< true if in array, otherwise in object + }; + + static const size_t kDefaultLevelDepth = 32; + + bool WriteNull() { + os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true; + } + + bool WriteBool(bool b) { + if (b) { + os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e'); + } + else { + os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e'); + } + return true; + } + + bool WriteInt(int i) { + char buffer[11]; + const char* end = internal::i32toa(i, buffer); + for (const char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteUint(unsigned u) { + char buffer[10]; + const char* end = internal::u32toa(u, buffer); + for (const char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteInt64(int64_t i64) { + char buffer[21]; + const char* end = internal::i64toa(i64, buffer); + for (const char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char* end = internal::u64toa(u64, buffer); + for (char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteDouble(double d) { + char buffer[25]; + char* end = internal::dtoa(d, buffer); + for (char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteString(const Ch* str, SizeType length) { + static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static const char escape[256] = { +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF +#undef Z16 + }; + + os_->Put('\"'); + GenericStringStream<SourceEncoding> is(str); + while (is.Tell() < length) { + const Ch c = is.Peek(); + if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) { + // Unicode escaping + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + os_->Put('\\'); + os_->Put('u'); + if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { + os_->Put(hexDigits[(codepoint >> 12) & 15]); + os_->Put(hexDigits[(codepoint >> 8) & 15]); + os_->Put(hexDigits[(codepoint >> 4) & 15]); + os_->Put(hexDigits[(codepoint ) & 15]); + } + else { + RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); + // Surrogate pair + unsigned s = codepoint - 0x010000; + unsigned lead = (s >> 10) + 0xD800; + unsigned trail = (s & 0x3FF) + 0xDC00; + os_->Put(hexDigits[(lead >> 12) & 15]); + os_->Put(hexDigits[(lead >> 8) & 15]); + os_->Put(hexDigits[(lead >> 4) & 15]); + os_->Put(hexDigits[(lead ) & 15]); + os_->Put('\\'); + os_->Put('u'); + os_->Put(hexDigits[(trail >> 12) & 15]); + os_->Put(hexDigits[(trail >> 8) & 15]); + os_->Put(hexDigits[(trail >> 4) & 15]); + os_->Put(hexDigits[(trail ) & 15]); + } + } + else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) { + is.Take(); + os_->Put('\\'); + os_->Put(escape[(unsigned char)c]); + if (escape[(unsigned char)c] == 'u') { + os_->Put('0'); + os_->Put('0'); + os_->Put(hexDigits[(unsigned char)c >> 4]); + os_->Put(hexDigits[(unsigned char)c & 0xF]); + } + } + else + if (!Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_)) + return false; + } + os_->Put('\"'); + return true; + } + + bool WriteStartObject() { os_->Put('{'); return true; } + bool WriteEndObject() { os_->Put('}'); return true; } + bool WriteStartArray() { os_->Put('['); return true; } + bool WriteEndArray() { os_->Put(']'); return true; } + + void Prefix(Type type) { + (void)type; + if (level_stack_.GetSize() != 0) { // this value is not at root + Level* level = level_stack_.template Top<Level>(); + if (level->valueCount > 0) { + if (level->inArray) + os_->Put(','); // add comma if it is not the first element in array + else // in object + os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); + } + 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(!hasRoot_); // Should only has one and only one root. + hasRoot_ = true; + } + } + + OutputStream* os_; + internal::Stack<StackAllocator> level_stack_; + bool hasRoot_; + +private: + // Prohibit copy constructor & assignment operator. + Writer(const Writer&); + Writer& operator=(const Writer&); +}; + +// Full specialization for StringStream to prevent memory copying + +template<> +inline bool Writer<StringBuffer>::WriteInt(int i) { + char *buffer = os_->Push(11); + const char* end = internal::i32toa(i, buffer); + os_->Pop(static_cast<size_t>(11 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteUint(unsigned u) { + char *buffer = os_->Push(10); + const char* end = internal::u32toa(u, buffer); + os_->Pop(static_cast<size_t>(10 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) { + char *buffer = os_->Push(21); + const char* end = internal::i64toa(i64, buffer); + os_->Pop(static_cast<size_t>(21 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) { + char *buffer = os_->Push(20); + const char* end = internal::u64toa(u, buffer); + os_->Pop(static_cast<size_t>(20 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteDouble(double d) { + char *buffer = os_->Push(25); + char* end = internal::dtoa(d, buffer); + os_->Pop(static_cast<size_t>(25 - (end - buffer))); + return true; +} + +RAPIDJSON_NAMESPACE_END + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ |