stack.h
Go to the documentation of this file.
1 // Tencent is pleased to support the open source community by making RapidJSON
2 // available.
3 //
4 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All
5 // rights reserved.
6 //
7 // Licensed under the MIT License (the "License"); you may not use this file
8 // except in compliance with the License. You may obtain a copy of the License
9 // at
10 //
11 // http://opensource.org/licenses/MIT
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 // License for the specific language governing permissions and limitations under
17 // the License.
18 
19 #ifndef RAPIDJSON_INTERNAL_STACK_H_
20 #define RAPIDJSON_INTERNAL_STACK_H_
21 
22 #include <cstddef>
23 #include "../allocators.h"
24 #include "swap.h"
25 
26 #if defined(__clang__)
27 RAPIDJSON_DIAG_PUSH
28 RAPIDJSON_DIAG_OFF(c++ 98 - compat)
29 #endif
30 
32 namespace internal {
33 
35 // Stack
36 
38 
40 template <typename Allocator>
41 class Stack {
42  public:
43  // Optimization note: Do not allocate memory for stack_ in constructor.
44  // Do it lazily when first Push() -> Expand() -> Resize().
45  Stack(Allocator *allocator, size_t stackCapacity)
46  : allocator_(allocator),
47  ownAllocator_(0),
48  stack_(0),
49  stackTop_(0),
50  stackEnd_(0),
51  initialCapacity_(stackCapacity) {}
52 
53 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
54  Stack(Stack &&rhs)
55  : allocator_(rhs.allocator_),
56  ownAllocator_(rhs.ownAllocator_),
57  stack_(rhs.stack_),
58  stackTop_(rhs.stackTop_),
59  stackEnd_(rhs.stackEnd_),
60  initialCapacity_(rhs.initialCapacity_) {
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  if (&rhs != this) {
75  Destroy();
76 
77  allocator_ = rhs.allocator_;
78  ownAllocator_ = rhs.ownAllocator_;
79  stack_ = rhs.stack_;
80  stackTop_ = rhs.stackTop_;
81  stackEnd_ = rhs.stackEnd_;
82  initialCapacity_ = rhs.initialCapacity_;
83 
84  rhs.allocator_ = 0;
85  rhs.ownAllocator_ = 0;
86  rhs.stack_ = 0;
87  rhs.stackTop_ = 0;
88  rhs.stackEnd_ = 0;
89  rhs.initialCapacity_ = 0;
90  }
91  return *this;
92  }
93 #endif
94 
95  void Swap(Stack &rhs) RAPIDJSON_NOEXCEPT {
96  internal::Swap(allocator_, rhs.allocator_);
97  internal::Swap(ownAllocator_, rhs.ownAllocator_);
98  internal::Swap(stack_, rhs.stack_);
99  internal::Swap(stackTop_, rhs.stackTop_);
100  internal::Swap(stackEnd_, rhs.stackEnd_);
101  internal::Swap(initialCapacity_, rhs.initialCapacity_);
102  }
103 
104  void Clear() { stackTop_ = stack_; }
105 
106  void ShrinkToFit() {
107  if (Empty()) {
108  // If the stack is empty, completely deallocate the memory.
109  Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc)
110  stack_ = 0;
111  stackTop_ = 0;
112  stackEnd_ = 0;
113  } else
114  Resize(GetSize());
115  }
116 
117  // Optimization note: try to minimize the size of this function for force
118  // inline. Expansion is run very infrequently, so it is moved to another
119  // (probably non-inline) function.
120  template <typename T>
121  RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
122  // Expand the stack if needed
123  if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) >
124  (stackEnd_ - stackTop_)))
125  Expand<T>(count);
126  }
127 
128  template <typename T>
129  RAPIDJSON_FORCEINLINE T *Push(size_t count = 1) {
130  Reserve<T>(count);
131  return PushUnsafe<T>(count);
132  }
133 
134  template <typename T>
135  RAPIDJSON_FORCEINLINE T *PushUnsafe(size_t count = 1) {
137  RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <=
138  (stackEnd_ - stackTop_));
139  T *ret = reinterpret_cast<T *>(stackTop_);
140  stackTop_ += sizeof(T) * count;
141  return ret;
142  }
143 
144  template <typename T>
145  T *Pop(size_t count) {
146  RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
147  stackTop_ -= count * sizeof(T);
148  return reinterpret_cast<T *>(stackTop_);
149  }
150 
151  template <typename T>
152  T *Top() {
153  RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
154  return reinterpret_cast<T *>(stackTop_ - sizeof(T));
155  }
156 
157  template <typename T>
158  const T *Top() const {
159  RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
160  return reinterpret_cast<T *>(stackTop_ - sizeof(T));
161  }
162 
163  template <typename T>
164  T *End() {
165  return reinterpret_cast<T *>(stackTop_);
166  }
167 
168  template <typename T>
169  const T *End() const {
170  return reinterpret_cast<T *>(stackTop_);
171  }
172 
173  template <typename T>
174  T *Bottom() {
175  return reinterpret_cast<T *>(stack_);
176  }
177 
178  template <typename T>
179  const T *Bottom() const {
180  return reinterpret_cast<T *>(stack_);
181  }
182 
183  bool HasAllocator() const { return allocator_ != 0; }
184 
185  Allocator &GetAllocator() {
187  return *allocator_;
188  }
189 
190  bool Empty() const { return stackTop_ == stack_; }
191  size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
192  size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
193 
194  private:
195  template <typename T>
196  void Expand(size_t count) {
197  // Only expand the capacity if the current stack exists. Otherwise just
198  // create a stack with initial capacity.
199  size_t newCapacity;
200  if (stack_ == 0) {
201  if (!allocator_) ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
202  newCapacity = initialCapacity_;
203  } else {
204  newCapacity = GetCapacity();
205  newCapacity += (newCapacity + 1) / 2;
206  }
207  size_t newSize = GetSize() + sizeof(T) * count;
208  if (newCapacity < newSize) newCapacity = newSize;
209 
210  Resize(newCapacity);
211  }
212 
213  void Resize(size_t newCapacity) {
214  const size_t size = GetSize(); // Backup the current size
215  stack_ = static_cast<char *>(
216  allocator_->Realloc(stack_, GetCapacity(), newCapacity));
217  stackTop_ = stack_ + size;
218  stackEnd_ = stack_ + newCapacity;
219  }
220 
221  void Destroy() {
222  Allocator::Free(stack_);
223  RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
224  }
225 
226  // Prohibit copy constructor & assignment operator.
227  Stack(const Stack &);
228  Stack &operator=(const Stack &);
229 
230  Allocator *allocator_;
231  Allocator *ownAllocator_;
232  char *stack_;
233  char *stackTop_;
234  char *stackEnd_;
236 };
237 
238 } // namespace internal
240 
241 #if defined(__clang__)
242 RAPIDJSON_DIAG_POP
243 #endif
244 
245 #endif // RAPIDJSON_STACK_H_
char * stack_
Definition: stack.h:232
Allocator * ownAllocator_
Definition: stack.h:231
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:433
RAPIDJSON_FORCEINLINE T * PushUnsafe(size_t count=1)
Definition: stack.h:135
void Expand(size_t count)
Definition: stack.h:196
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:131
const T * Top() const
Definition: stack.h:158
void Resize(size_t newCapacity)
Definition: stack.h:213
A type-unsafe stack for storing different types of data.
Definition: stack.h:41
bool Empty() const
Definition: stack.h:190
void Clear()
Definition: stack.h:104
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:128
Stack & operator=(const Stack &)
RAPIDJSON_FORCEINLINE T * Push(size_t count=1)
Definition: stack.h:129
void Destroy()
Definition: stack.h:221
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition: rapidjson.h:690
char * stackEnd_
Definition: stack.h:234
T * End()
Definition: stack.h:164
RAPIDJSON_FORCEINLINE void Reserve(size_t count=1)
Definition: stack.h:121
size_t GetSize() const
Definition: stack.h:191
size_t initialCapacity_
Definition: stack.h:235
void Swap(T &a, T &b) RAPIDJSON_NOEXCEPT
Custom swap() to avoid dependency on C++ <algorithm> header.
Definition: swap.h:37
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition: rapidjson.h:694
Allocator * allocator_
Definition: stack.h:230
Allocator & GetAllocator()
Definition: stack.h:185
T * Bottom()
Definition: stack.h:174
bool HasAllocator() const
Definition: stack.h:183
char * stackTop_
Definition: stack.h:233
void ShrinkToFit()
Definition: stack.h:106
size_t GetCapacity() const
Definition: stack.h:192
Stack(Allocator *allocator, size_t stackCapacity)
Definition: stack.h:45
const T * End() const
Definition: stack.h:169
T * Pop(size_t count)
Definition: stack.h:145
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:508
T * Top()
Definition: stack.h:152
void Swap(Stack &rhs) RAPIDJSON_NOEXCEPT
Definition: stack.h:95
const T * Bottom() const
Definition: stack.h:179


livox_ros_driver
Author(s): Livox Dev Team
autogenerated on Mon Mar 15 2021 02:40:46