/src/rapidjson/include/rapidjson/stringbuffer.h
Line | Count | Source |
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. |
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 | 22 | 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 | 0 | void Put(Ch c) { *stack_.template Push<Ch>() = c; } |
57 | 16.4M | void PutUnsafe(Ch c) { *stack_.template PushUnsafe<Ch>() = c; } |
58 | 22 | 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 | 16 | void Reserve(size_t count) { stack_.template Reserve<Ch>(count); } |
69 | 6 | Ch* Push(size_t count) { return stack_.template Push<Ch>(count); } |
70 | | Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe<Ch>(count); } |
71 | 6 | void Pop(size_t count) { stack_.template Pop<Ch>(count); } |
72 | | |
73 | 22 | const Ch* GetString() const { |
74 | | // Push and pop a null terminator. This is safe. |
75 | 22 | *stack_.template Push<Ch>() = '\0'; |
76 | 22 | stack_.template Pop<Ch>(1); |
77 | | |
78 | 22 | return stack_.template Bottom<Ch>(); |
79 | 22 | } |
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 | 16 | inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) { |
101 | 16 | stream.Reserve(count); |
102 | 16 | } |
103 | | |
104 | | template<typename Encoding, typename Allocator> |
105 | 16.4M | inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) { |
106 | 16.4M | stream.PutUnsafe(c); |
107 | 16.4M | } |
108 | | |
109 | | //! Implement specialized version of PutN() with memset() for better performance. |
110 | | template<> |
111 | 0 | inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) { |
112 | 0 | std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c)); |
113 | 0 | } |
114 | | |
115 | | RAPIDJSON_NAMESPACE_END |
116 | | |
117 | | #if defined(__clang__) |
118 | | RAPIDJSON_DIAG_POP |
119 | | #endif |
120 | | |
121 | | #endif // RAPIDJSON_STRINGBUFFER_H_ |