/home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-composable-kernel/checkouts/develop/include/rapidjson/internal/stack.h Source File

/home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-composable-kernel/checkouts/develop/include/rapidjson/internal/stack.h Source File#

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