TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 "../rapidjson.h"
19 
21 namespace internal {
22 
24 // Stack
25 
27 
29 template <typename Allocator>
30 class Stack {
31 public:
32  // Optimization note: Do not allocate memory for stack_ in constructor.
33  // Do it lazily when first Push() -> Expand() -> Resize().
34  Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
35  RAPIDJSON_ASSERT(stackCapacity > 0);
36  }
37 
38 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
39  Stack(Stack&& rhs)
40  : allocator_(rhs.allocator_),
42  stack_(rhs.stack_),
43  stackTop_(rhs.stackTop_),
44  stackEnd_(rhs.stackEnd_),
46  {
47  rhs.allocator_ = 0;
48  rhs.ownAllocator_ = 0;
49  rhs.stack_ = 0;
50  rhs.stackTop_ = 0;
51  rhs.stackEnd_ = 0;
52  rhs.initialCapacity_ = 0;
53  }
54 #endif
55 
56  ~Stack() {
57  Destroy();
58  }
59 
60 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
61  Stack& operator=(Stack&& rhs) {
62  if (&rhs != this)
63  {
64  Destroy();
65 
66  allocator_ = rhs.allocator_;
67  ownAllocator_ = rhs.ownAllocator_;
68  stack_ = rhs.stack_;
69  stackTop_ = rhs.stackTop_;
70  stackEnd_ = rhs.stackEnd_;
71  initialCapacity_ = rhs.initialCapacity_;
72 
73  rhs.allocator_ = 0;
74  rhs.ownAllocator_ = 0;
75  rhs.stack_ = 0;
76  rhs.stackTop_ = 0;
77  rhs.stackEnd_ = 0;
78  rhs.initialCapacity_ = 0;
79  }
80  return *this;
81  }
82 #endif
83 
84  void Clear() { stackTop_ = stack_; }
85 
86  void ShrinkToFit() {
87  if (Empty()) {
88  // If the stack is empty, completely deallocate the memory.
89  Allocator::Free(stack_);
90  stack_ = 0;
91  stackTop_ = 0;
92  stackEnd_ = 0;
93  }
94  else
95  Resize(GetSize());
96  }
97 
98  // Optimization note: try to minimize the size of this function for force inline.
99  // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
100  template<typename T>
101  RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
102  // Expand the stack if needed
103  if (stackTop_ + sizeof(T) * count >= stackEnd_)
104  Expand<T>(count);
105 
106  T* ret = reinterpret_cast<T*>(stackTop_);
107  stackTop_ += sizeof(T) * count;
108  return ret;
109  }
110 
111  template<typename T>
112  T* Pop(size_t count) {
113  RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
114  stackTop_ -= count * sizeof(T);
115  return reinterpret_cast<T*>(stackTop_);
116  }
117 
118  template<typename T>
119  T* Top() {
120  RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
121  return reinterpret_cast<T*>(stackTop_ - sizeof(T));
122  }
123 
124  template<typename T>
125  T* Bottom() { return (T*)stack_; }
126 
127  Allocator& GetAllocator() { return *allocator_; }
128  bool Empty() const { return stackTop_ == stack_; }
129  size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
130  size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
131 
132 private:
133  template<typename T>
134  void Expand(size_t count) {
135  // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
136  size_t newCapacity;
137  if (stack_ == 0) {
138  if (!allocator_)
139  ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
140  newCapacity = initialCapacity_;
141  } else {
142  newCapacity = GetCapacity();
143  newCapacity += (newCapacity + 1) / 2;
144  }
145  size_t newSize = GetSize() + sizeof(T) * count;
146  if (newCapacity < newSize)
147  newCapacity = newSize;
148 
149  Resize(newCapacity);
150  }
151 
152  void Resize(size_t newCapacity) {
153  const size_t size = GetSize(); // Backup the current size
154  stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity);
155  stackTop_ = stack_ + size;
156  stackEnd_ = stack_ + newCapacity;
157  }
158 
159  void Destroy() {
160  Allocator::Free(stack_);
161  RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
162  }
163 
164  // Prohibit copy constructor & assignment operator.
165  Stack(const Stack&);
166  Stack& operator=(const Stack&);
167 
168  Allocator* allocator_;
169  Allocator* ownAllocator_;
170  char *stack_;
171  char *stackTop_;
172  char *stackEnd_;
174 };
175 
176 } // namespace internal
178 
179 #endif // RAPIDJSON_STACK_H_
char * stack_
Definition: stack.h:170
~Stack()
Definition: stack.h:56
Allocator * ownAllocator_
Definition: stack.h:169
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:344
void Expand(size_t count)
Definition: stack.h:134
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:119
void Resize(size_t newCapacity)
Definition: stack.h:152
A type-unsafe stack for storing different types of data.
Definition: stack.h:30
bool Empty() const
Definition: stack.h:128
void Clear()
Definition: stack.h:84
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:116
Stack & operator=(const Stack &)
RAPIDJSON_FORCEINLINE T * Push(size_t count=1)
Definition: stack.h:101
void Destroy()
Definition: stack.h:159
char * stackEnd_
Definition: stack.h:172
#define RAPIDJSON_NEW(x)
! customization point for global new
Definition: rapidjson.h:480
size_t GetSize() const
Definition: stack.h:129
size_t initialCapacity_
Definition: stack.h:173
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition: rapidjson.h:484
Allocator * allocator_
Definition: stack.h:168
Allocator & GetAllocator()
Definition: stack.h:127
T * Bottom()
Definition: stack.h:125
Definition: document.h:390
char * stackTop_
Definition: stack.h:171
void ShrinkToFit()
Definition: stack.h:86
size_t GetCapacity() const
Definition: stack.h:130
Stack(Allocator *allocator, size_t stackCapacity)
Definition: stack.h:34
T * Pop(size_t count)
Definition: stack.h:112
T * Top()
Definition: stack.h:119