stack.h 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #ifndef RAPIDJSON_INTERNAL_STACK_H_
  2. #define RAPIDJSON_INTERNAL_STACK_H_
  3. namespace rapidjson {
  4. namespace internal {
  5. ///////////////////////////////////////////////////////////////////////////////
  6. // Stack
  7. //! A type-unsafe stack for storing different types of data.
  8. /*! \tparam Allocator Allocator for allocating stack memory.
  9. */
  10. template <typename Allocator>
  11. class Stack {
  12. public:
  13. Stack(Allocator* allocator, size_t stack_capacity) : allocator_(allocator), own_allocator_(0), stack_(0), stack_top_(0), stack_end_(0), stack_capacity_(stack_capacity) {
  14. RAPIDJSON_ASSERT(stack_capacity_ > 0);
  15. if (!allocator_)
  16. own_allocator_ = allocator_ = new Allocator();
  17. stack_top_ = stack_ = (char*)allocator_->Malloc(stack_capacity_);
  18. stack_end_ = stack_ + stack_capacity_;
  19. }
  20. ~Stack() {
  21. Allocator::Free(stack_);
  22. delete own_allocator_; // Only delete if it is owned by the stack
  23. }
  24. void Clear() { /*stack_top_ = 0;*/ stack_top_ = stack_; }
  25. template<typename T>
  26. T* Push(size_t count = 1) {
  27. // Expand the stack if needed
  28. if (stack_top_ + sizeof(T) * count >= stack_end_) {
  29. size_t new_capacity = stack_capacity_ * 2;
  30. size_t size = GetSize();
  31. size_t new_size = GetSize() + sizeof(T) * count;
  32. if (new_capacity < new_size)
  33. new_capacity = new_size;
  34. stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity);
  35. stack_capacity_ = new_capacity;
  36. stack_top_ = stack_ + size;
  37. stack_end_ = stack_ + stack_capacity_;
  38. }
  39. T* ret = (T*)stack_top_;
  40. stack_top_ += sizeof(T) * count;
  41. return ret;
  42. }
  43. template<typename T>
  44. T* Pop(size_t count) {
  45. RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
  46. stack_top_ -= count * sizeof(T);
  47. return (T*)stack_top_;
  48. }
  49. template<typename T>
  50. T* Top() {
  51. RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
  52. return (T*)(stack_top_ - sizeof(T));
  53. }
  54. template<typename T>
  55. T* Bottom() { return (T*)stack_; }
  56. Allocator& GetAllocator() { return *allocator_; }
  57. bool Empty() const { return stack_top_ == stack_; }
  58. size_t GetSize() const { return stack_top_ - stack_; }
  59. size_t GetCapacity() const { return stack_capacity_; }
  60. private:
  61. Allocator* allocator_;
  62. Allocator* own_allocator_;
  63. char *stack_;
  64. char *stack_top_;
  65. char *stack_end_;
  66. size_t stack_capacity_;
  67. };
  68. } // namespace internal
  69. } // namespace rapidjson
  70. #endif // RAPIDJSON_STACK_H_