Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
stack.h
Go to the documentation of this file.
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_INTERNAL_STACK_H_
16#define RAPIDJSON_INTERNAL_STACK_H_
17
18#include "../allocators.h"
19#include "swap.h"
20#include <cstddef>
21
22#if defined(__clang__)
23RAPIDJSON_DIAG_PUSH
24RAPIDJSON_DIAG_OFF(c++98-compat)
25#endif
26
28namespace internal {
29
31// Stack
32
34
36template <typename Allocator>
37class Stack {
38public:
39 // Optimization note: Do not allocate memory for stack_ in constructor.
40 // Do it lazily when first Push() -> Expand() -> Resize().
41 Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
42 }
43
44#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
45 Stack(Stack&& rhs)
46 : allocator_(rhs.allocator_),
47 ownAllocator_(rhs.ownAllocator_),
48 stack_(rhs.stack_),
49 stackTop_(rhs.stackTop_),
50 stackEnd_(rhs.stackEnd_),
51 initialCapacity_(rhs.initialCapacity_)
52 {
53 rhs.allocator_ = 0;
54 rhs.ownAllocator_ = 0;
55 rhs.stack_ = 0;
56 rhs.stackTop_ = 0;
57 rhs.stackEnd_ = 0;
58 rhs.initialCapacity_ = 0;
59 }
60#endif
61
63 Destroy();
64 }
65
66#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
67 Stack& operator=(Stack&& rhs) {
68 if (&rhs != this)
69 {
70 Destroy();
71
72 allocator_ = rhs.allocator_;
73 ownAllocator_ = rhs.ownAllocator_;
74 stack_ = rhs.stack_;
75 stackTop_ = rhs.stackTop_;
76 stackEnd_ = rhs.stackEnd_;
77 initialCapacity_ = rhs.initialCapacity_;
78
79 rhs.allocator_ = 0;
80 rhs.ownAllocator_ = 0;
81 rhs.stack_ = 0;
82 rhs.stackTop_ = 0;
83 rhs.stackEnd_ = 0;
84 rhs.initialCapacity_ = 0;
85 }
86 return *this;
87 }
88#endif
89
90 void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
91 internal::Swap(allocator_, rhs.allocator_);
92 internal::Swap(ownAllocator_, rhs.ownAllocator_);
93 internal::Swap(stack_, rhs.stack_);
94 internal::Swap(stackTop_, rhs.stackTop_);
95 internal::Swap(stackEnd_, rhs.stackEnd_);
96 internal::Swap(initialCapacity_, rhs.initialCapacity_);
97 }
98
99 void Clear() { stackTop_ = stack_; }
100
101 void ShrinkToFit() {
102 if (Empty()) {
103 // If the stack is empty, completely deallocate the memory.
104 Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc)
105 stack_ = 0;
106 stackTop_ = 0;
107 stackEnd_ = 0;
108 }
109 else
110 Resize(GetSize());
111 }
112
113 // Optimization note: try to minimize the size of this function for force inline.
114 // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
115 template<typename T>
116 RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
117 // Expand the stack if needed
118 if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
119 Expand<T>(count);
120 }
121
122 template<typename T>
123 RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
125 return PushUnsafe<T>(count);
126 }
127
128 template<typename T>
129 RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
130 RAPIDJSON_ASSERT(stackTop_);
131 RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
132 T* ret = reinterpret_cast<T*>(stackTop_);
133 stackTop_ += sizeof(T) * count;
134 return ret;
135 }
136
137 template<typename T>
138 T* Pop(size_t count) {
139 RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
140 stackTop_ -= count * sizeof(T);
141 return reinterpret_cast<T*>(stackTop_);
142 }
143
144 template<typename T>
145 T* Top() {
146 RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
147 return reinterpret_cast<T*>(stackTop_ - sizeof(T));
148 }
149
150 template<typename T>
151 const T* Top() const {
152 RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
153 return reinterpret_cast<T*>(stackTop_ - sizeof(T));
154 }
155
156 template<typename T>
157 T* End() { return reinterpret_cast<T*>(stackTop_); }
158
159 template<typename T>
160 const T* End() const { return reinterpret_cast<T*>(stackTop_); }
161
162 template<typename T>
163 T* Bottom() { return reinterpret_cast<T*>(stack_); }
164
165 template<typename T>
166 const T* Bottom() const { return reinterpret_cast<T*>(stack_); }
167
168 bool HasAllocator() const {
169 return allocator_ != 0;
170 }
171
173 RAPIDJSON_ASSERT(allocator_);
174 return *allocator_;
175 }
176
177 bool Empty() const { return stackTop_ == stack_; }
178 size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
179 size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
180
181private:
182 template<typename T>
183 void Expand(size_t count) {
184 // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
185 size_t newCapacity;
186 if (stack_ == 0) {
187 if (!allocator_)
188 ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
189 newCapacity = initialCapacity_;
190 } else {
191 newCapacity = GetCapacity();
192 newCapacity += (newCapacity + 1) / 2;
193 }
194 size_t newSize = GetSize() + sizeof(T) * count;
195 if (newCapacity < newSize)
196 newCapacity = newSize;
197
198 Resize(newCapacity);
199 }
200
201 void Resize(size_t newCapacity) {
202 const size_t size = GetSize(); // Backup the current size
203 stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
204 stackTop_ = stack_ + size;
205 stackEnd_ = stack_ + newCapacity;
206 }
207
208 void Destroy() {
209 Allocator::Free(stack_);
210 RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
211 }
212
213 // Prohibit copy constructor & assignment operator.
214 Stack(const Stack&);
215 Stack& operator=(const Stack&);
216
217 Allocator* allocator_;
218 Allocator* ownAllocator_;
219 char *stack_;
220 char *stackTop_;
221 char *stackEnd_;
222 size_t initialCapacity_;
223};
224
225} // namespace internal
227
228#if defined(__clang__)
229RAPIDJSON_DIAG_POP
230#endif
231
232#endif // RAPIDJSON_STACK_H_
A type-unsafe stack for storing different types of data.
Definition stack.h:37
void Clear()
Definition stack.h:99
const T * Top() const
Definition stack.h:151
T * Pop(size_t count)
Definition stack.h:138
const T * End() const
Definition stack.h:160
bool Empty() const
Definition stack.h:177
RAPIDJSON_FORCEINLINE T * Push(size_t count=1)
Definition stack.h:123
void ShrinkToFit()
Definition stack.h:101
void Swap(Stack &rhs) RAPIDJSON_NOEXCEPT
Definition stack.h:90
bool HasAllocator() const
Definition stack.h:168
size_t GetCapacity() const
Definition stack.h:179
T * Bottom()
Definition stack.h:163
RAPIDJSON_FORCEINLINE void Reserve(size_t count=1)
Definition stack.h:116
RAPIDJSON_FORCEINLINE T * PushUnsafe(size_t count=1)
Definition stack.h:129
Allocator & GetAllocator()
Definition stack.h:172
size_t GetSize() const
Definition stack.h:178
const T * Bottom() const
Definition stack.h:166
Stack(Allocator *allocator, size_t stackCapacity)
Definition stack.h:41
Concept for allocating, resizing and freeing memory block.
int * count
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition rapidjson.h:476
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition rapidjson.h:406
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition rapidjson.h:121
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition rapidjson.h:124
void Swap(T &a, T &b) RAPIDJSON_NOEXCEPT
Custom swap() to avoid dependency on C++ <algorithm> header.
Definition swap.h:33
#define T(meth, val, expected)
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition rapidjson.h:631
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition rapidjson.h:627
CK_RV ret