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 | size_t GetSize() const { return stack_.GetSize(); } |
82 | |
83 | static const size_t kDefaultCapacity = 256; |
84 | mutable internal::Stack<Allocator> stack_; |
85 | |
86 | private: |
87 | // Prohibit copy constructor & assignment operator. |
88 | GenericStringBuffer(const GenericStringBuffer&); |
89 | GenericStringBuffer& operator=(const GenericStringBuffer&); |
90 | }; |
91 | |
92 | //! String buffer with UTF8 encoding |
93 | typedef GenericStringBuffer<UTF8<> > StringBuffer; |
94 | |
95 | template<typename Encoding, typename Allocator> |
96 | inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) { |
97 | stream.Reserve(count); |
98 | } |
99 | |
100 | template<typename Encoding, typename Allocator> |
101 | inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) { |
102 | stream.PutUnsafe(c); |
103 | } |
104 | |
105 | //! Implement specialized version of PutN() with memset() for better performance. |
106 | template<> |
107 | inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) { |
108 | std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c)); |
109 | } |
110 | |
111 | RAPIDJSON_NAMESPACE_END |
112 | |
113 | #if defined(__clang__) |
114 | RAPIDJSON_DIAG_POP |
115 | #endif |
116 | |
117 | #endif // RAPIDJSON_STRINGBUFFER_H_ |
118 | |