stack.h
1 #ifndef RAPIDJSON_INTERNAL_STACK_H_
2 #define RAPIDJSON_INTERNAL_STACK_H_
3 
4 namespace rapidjson {
5 namespace internal {
6 
7 ///////////////////////////////////////////////////////////////////////////////
8 // Stack
9 
10 //! A type-unsafe stack for storing different types of data.
11 /*! \tparam Allocator Allocator for allocating stack memory.
12 */
13 template <typename Allocator>
14 class Stack {
15 public:
16  Stack(Allocator* allocator, size_t stack_capacity) : allocator_(allocator), own_allocator_(0), stack_(0), stack_top_(0), stack_end_(0), stack_capacity_(stack_capacity) {
17  RAPIDJSON_ASSERT(stack_capacity_ > 0);
18  if (!allocator_)
19  own_allocator_ = allocator_ = new Allocator();
20  stack_top_ = stack_ = (char*)allocator_->Malloc(stack_capacity_);
21  stack_end_ = stack_ + stack_capacity_;
22  }
23 
24  ~Stack() {
25  Allocator::Free(stack_);
26  delete own_allocator_; // Only delete if it is owned by the stack
27  }
28 
29  void Clear() { /*stack_top_ = 0;*/ stack_top_ = stack_; }
30 
31  // Optimization note: try to minimize the size of this function for force inline.
32  // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
33  template<typename T>
34  RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
35  // Expand the stack if needed
36  if (stack_top_ + sizeof(T) * count >= stack_end_)
37  Expand<T>(count);
38 
39  T* ret = reinterpret_cast<T*>(stack_top_);
40  stack_top_ += sizeof(T) * count;
41  return ret;
42  }
43 
44  template<typename T>
45  T* Pop(size_t count) {
46  RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
47  stack_top_ -= count * sizeof(T);
48  return reinterpret_cast<T*>(stack_top_);
49  }
50 
51  template<typename T>
52  T* Top() {
53  RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
54  return reinterpret_cast<T*>(stack_top_ - sizeof(T));
55  }
56 
57  template<typename T>
58  T* Bottom() { return (T*)stack_; }
59 
60  Allocator& GetAllocator() { return *allocator_; }
61  bool Empty() const { return stack_top_ == stack_; }
62  size_t GetSize() const { return static_cast<size_t>(stack_top_ - stack_); }
63  size_t GetCapacity() const { return stack_capacity_; }
64 
65 private:
66  template<typename T>
67  void Expand(size_t count) {
68  size_t new_capacity = stack_capacity_ * 2;
69  size_t size = GetSize();
70  size_t new_size = GetSize() + sizeof(T) * count;
71  if (new_capacity < new_size)
72  new_capacity = new_size;
73  stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity);
74  stack_capacity_ = new_capacity;
75  stack_top_ = stack_ + size;
76  stack_end_ = stack_ + stack_capacity_;
77  }
78 
79  // Prohibit copy constructor & assignment operator.
80  Stack(const Stack&);
81  Stack& operator=(const Stack&);
82 
83  Allocator* allocator_;
84  Allocator* own_allocator_;
85  char *stack_;
86  char *stack_top_;
87  char *stack_end_;
88  size_t stack_capacity_;
89 };
90 
91 } // namespace internal
92 } // namespace rapidjson
93 
94 #endif // RAPIDJSON_STACK_H_
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:146
main RapidJSON namespace
Definition: allocators.h:6