All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
stack.h
1 // Copyright (C) 2011 Milo Yip
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE.
20 
21 #ifndef RAPIDJSON_INTERNAL_STACK_H_
22 #define RAPIDJSON_INTERNAL_STACK_H_
23 
24 namespace rapidjson {
25 namespace internal {
26 
27 ///////////////////////////////////////////////////////////////////////////////
28 // Stack
29 
30 //! A type-unsafe stack for storing different types of data.
31 /*! \tparam Allocator Allocator for allocating stack memory.
32 */
33 template <typename Allocator>
34 class Stack {
35 public:
36  Stack(Allocator* allocator, size_t stack_capacity) : allocator_(allocator), own_allocator_(0), stack_(0), stack_top_(0), stack_end_(0), stack_capacity_(stack_capacity) {
37  RAPIDJSON_ASSERT(stack_capacity_ > 0);
38  if (!allocator_)
39  own_allocator_ = allocator_ = new Allocator();
40  stack_top_ = stack_ = (char*)allocator_->Malloc(stack_capacity_);
41  stack_end_ = stack_ + stack_capacity_;
42  }
43 
44  ~Stack() {
45  Allocator::Free(stack_);
46  delete own_allocator_; // Only delete if it is owned by the stack
47  }
48 
49  void Clear() { /*stack_top_ = 0;*/ stack_top_ = stack_; }
50 
51  // Optimization note: try to minimize the size of this function for force inline.
52  // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
53  template<typename T>
54  RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
55  // Expand the stack if needed
56  if (stack_top_ + sizeof(T) * count >= stack_end_)
57  Expand<T>(count);
58 
59  T* ret = reinterpret_cast<T*>(stack_top_);
60  stack_top_ += sizeof(T) * count;
61  return ret;
62  }
63 
64  template<typename T>
65  T* Pop(size_t count) {
66  RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
67  stack_top_ -= count * sizeof(T);
68  return reinterpret_cast<T*>(stack_top_);
69  }
70 
71  template<typename T>
72  T* Top() {
73  RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
74  return reinterpret_cast<T*>(stack_top_ - sizeof(T));
75  }
76 
77  template<typename T>
78  T* Bottom() { return (T*)stack_; }
79 
80  Allocator& GetAllocator() { return *allocator_; }
81  bool Empty() const { return stack_top_ == stack_; }
82  size_t GetSize() const { return static_cast<size_t>(stack_top_ - stack_); }
83  size_t GetCapacity() const { return stack_capacity_; }
84 
85 private:
86  template<typename T>
87  void Expand(size_t count) {
88  size_t new_capacity = stack_capacity_ * 2;
89  size_t size = GetSize();
90  size_t new_size = GetSize() + sizeof(T) * count;
91  if (new_capacity < new_size)
92  new_capacity = new_size;
93  stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity);
94  stack_capacity_ = new_capacity;
95  stack_top_ = stack_ + size;
96  stack_end_ = stack_ + stack_capacity_;
97  }
98 
99  // Prohibit copy constructor & assignment operator.
100  Stack(const Stack&);
101  Stack& operator=(const Stack&);
102 
103  Allocator* allocator_;
104  Allocator* own_allocator_;
105  char *stack_;
106  char *stack_top_;
107  char *stack_end_;
108  size_t stack_capacity_;
109 };
110 
111 } // namespace internal
112 } // namespace rapidjson
113 
114 #endif // RAPIDJSON_STACK_H_
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:175