1 | // Tencent is pleased to support the open source community by making RapidJSON available. |
2 | // |
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. |
4 | // |
5 | // Licensed under the MIT License (the "License"); you may not use this file except |
6 | // in compliance with the License. You may obtain a copy of the License at |
7 | // |
8 | // http://opensource.org/licenses/MIT |
9 | // |
10 | // Unless required by applicable law or agreed to in writing, software distributed |
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the |
13 | // specific language governing permissions and limitations under the License. |
14 | |
15 | #ifndef RAPIDJSON_STRINGBUFFER_H_ |
16 | #define RAPIDJSON_STRINGBUFFER_H_ |
17 | |
18 | #include "stream.h" |
19 | #include "internal/stack.h" |
20 | |
21 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
22 | #include <utility> // std::move |
23 | #endif |
24 | |
25 | #include "internal/stack.h" |
26 | |
27 | #if defined(__clang__) |
28 | RAPIDJSON_DIAG_PUSH |
29 | RAPIDJSON_DIAG_OFF(c++98-compat) |
30 | #endif |
31 | |
32 | RAPIDJSON_NAMESPACE_BEGIN |
33 | |
34 | //! Represents an in-memory output stream. |
35 | /*! |
36 | \tparam Encoding Encoding of the stream. |
37 | \tparam Allocator type for allocating memory buffer. |
38 | \note implements Stream concept |
39 | */ |
40 | template <typename Encoding, typename Allocator = CrtAllocator> |
41 | class GenericStringBuffer { |
42 | public: |
43 | typedef typename Encoding::Ch Ch; |
44 | |
45 | GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} |
46 | |
47 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
48 | GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} |
49 | GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { |
50 | if (&rhs != this) |
51 | stack_ = std::move(rhs.stack_); |
52 | return *this; |
53 | } |
54 | #endif |
55 | |
56 | void Put(Ch c) { *stack_.template Push<Ch>() = c; } |
57 | void PutUnsafe(Ch c) { *stack_.template PushUnsafe<Ch>() = c; } |
58 | void Flush() {} |
59 | |
60 | void Clear() { stack_.Clear(); } |
61 | void ShrinkToFit() { |
62 | // Push and pop a null terminator. This is safe. |
63 | *stack_.template Push<Ch>() = '\0'; |
64 | stack_.ShrinkToFit(); |
65 | stack_.template Pop<Ch>(1); |
66 | } |
67 | |
68 | void Reserve(size_t count) { stack_.template Reserve<Ch>(count); } |
69 | Ch* Push(size_t count) { return stack_.template Push<Ch>(count); } |
70 | Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe<Ch>(count); } |
71 | void Pop(size_t count) { stack_.template Pop<Ch>(count); } |
72 | |
73 | const Ch* GetString() const { |
74 | // Push and pop a null terminator. This is safe. |
75 | *stack_.template Push<Ch>() = '\0'; |
76 | stack_.template Pop<Ch>(1); |
77 | |
78 | return stack_.template Bottom<Ch>(); |
79 | } |
80 | |
81 | //! Get the size of string in bytes in the string buffer. |
82 | size_t GetSize() const { return stack_.GetSize(); } |
83 | |
84 | //! Get the length of string in Ch in the string buffer. |
85 | size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); } |
86 | |
87 | static const size_t kDefaultCapacity = 256; |
88 | mutable internal::Stack<Allocator> stack_; |
89 | |
90 | private: |
91 | // Prohibit copy constructor & assignment operator. |
92 | GenericStringBuffer(const GenericStringBuffer&); |
93 | GenericStringBuffer& operator=(const GenericStringBuffer&); |
94 | }; |
95 | |
96 | //! String buffer with UTF8 encoding |
97 | typedef GenericStringBuffer<UTF8<> > StringBuffer; |
98 | |
99 | template<typename Encoding, typename Allocator> |
100 | inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) { |
101 | stream.Reserve(count); |
102 | } |
103 | |
104 | template<typename Encoding, typename Allocator> |
105 | inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) { |
106 | stream.PutUnsafe(c); |
107 | } |
108 | |
109 | //! Implement specialized version of PutN() with memset() for better performance. |
110 | template<> |
111 | inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) { |
112 | std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c)); |
113 | } |
114 | |
115 | RAPIDJSON_NAMESPACE_END |
116 | |
117 | #if defined(__clang__) |
118 | RAPIDJSON_DIAG_POP |
119 | #endif |
120 | |
121 | #endif // RAPIDJSON_STRINGBUFFER_H_ |
122 | |