diff options
Diffstat (limited to 'src/rapidjson/internal/stack.h')
-rwxr-xr-x | src/rapidjson/internal/stack.h | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/rapidjson/internal/stack.h b/src/rapidjson/internal/stack.h new file mode 100755 index 0000000000..966893b3fc --- /dev/null +++ b/src/rapidjson/internal/stack.h @@ -0,0 +1,82 @@ +#ifndef RAPIDJSON_INTERNAL_STACK_H_ +#define RAPIDJSON_INTERNAL_STACK_H_ + +namespace rapidjson { +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// Stack + +//! A type-unsafe stack for storing different types of data. +/*! \tparam Allocator Allocator for allocating stack memory. +*/ +template <typename Allocator> +class Stack { +public: + Stack(Allocator* allocator, size_t stack_capacity) : allocator_(allocator), own_allocator_(0), stack_(0), stack_top_(0), stack_end_(0), stack_capacity_(stack_capacity) { + RAPIDJSON_ASSERT(stack_capacity_ > 0); + if (!allocator_) + own_allocator_ = allocator_ = new Allocator(); + stack_top_ = stack_ = (char*)allocator_->Malloc(stack_capacity_); + stack_end_ = stack_ + stack_capacity_; + } + + ~Stack() { + Allocator::Free(stack_); + delete own_allocator_; // Only delete if it is owned by the stack + } + + void Clear() { /*stack_top_ = 0;*/ stack_top_ = stack_; } + + template<typename T> + T* Push(size_t count = 1) { + // Expand the stack if needed + if (stack_top_ + sizeof(T) * count >= stack_end_) { + size_t new_capacity = stack_capacity_ * 2; + size_t size = GetSize(); + size_t new_size = GetSize() + sizeof(T) * count; + if (new_capacity < new_size) + new_capacity = new_size; + stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity); + stack_capacity_ = new_capacity; + stack_top_ = stack_ + size; + stack_end_ = stack_ + stack_capacity_; + } + T* ret = (T*)stack_top_; + stack_top_ += sizeof(T) * count; + return ret; + } + + template<typename T> + T* Pop(size_t count) { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stack_top_ -= count * sizeof(T); + return (T*)stack_top_; + } + + template<typename T> + T* Top() { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return (T*)(stack_top_ - sizeof(T)); + } + + template<typename T> + T* Bottom() { return (T*)stack_; } + + Allocator& GetAllocator() { return *allocator_; } + size_t GetSize() const { return stack_top_ - stack_; } + size_t GetCapacity() const { return stack_capacity_; } + +private: + Allocator* allocator_; + Allocator* own_allocator_; + char *stack_; + char *stack_top_; + char *stack_end_; + size_t stack_capacity_; +}; + +} // namespace internal +} // namespace rapidjson + +#endif // RAPIDJSON_STACK_H_ |