stack.h (rapidjson-1.0.2) | : | stack.h (rapidjson-1.1.0) | ||
---|---|---|---|---|
skipping to change at line 18 | skipping to change at line 18 | |||
// http://opensource.org/licenses/MIT | // http://opensource.org/licenses/MIT | |||
// | // | |||
// Unless required by applicable law or agreed to in writing, software distribut ed | // Unless required by applicable law or agreed to in writing, software distribut ed | |||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR | |||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the | // CONDITIONS OF ANY KIND, either express or implied. See the License for the | |||
// specific language governing permissions and limitations under the License. | // specific language governing permissions and limitations under the License. | |||
#ifndef RAPIDJSON_INTERNAL_STACK_H_ | #ifndef RAPIDJSON_INTERNAL_STACK_H_ | |||
#define RAPIDJSON_INTERNAL_STACK_H_ | #define RAPIDJSON_INTERNAL_STACK_H_ | |||
#include "../rapidjson.h" | #include "../allocators.h" | |||
#include "swap.h" | ||||
#if defined(__clang__) | ||||
RAPIDJSON_DIAG_PUSH | ||||
RAPIDJSON_DIAG_OFF(c++98-compat) | ||||
#endif | ||||
RAPIDJSON_NAMESPACE_BEGIN | RAPIDJSON_NAMESPACE_BEGIN | |||
namespace internal { | namespace internal { | |||
/////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | |||
// Stack | // Stack | |||
//! A type-unsafe stack for storing different types of data. | //! A type-unsafe stack for storing different types of data. | |||
/*! \tparam Allocator Allocator for allocating stack memory. | /*! \tparam Allocator Allocator for allocating stack memory. | |||
*/ | */ | |||
template <typename Allocator> | template <typename Allocator> | |||
class Stack { | class Stack { | |||
public: | public: | |||
// Optimization note: Do not allocate memory for stack_ in constructor. | // Optimization note: Do not allocate memory for stack_ in constructor. | |||
// Do it lazily when first Push() -> Expand() -> Resize(). | // Do it lazily when first Push() -> Expand() -> Resize(). | |||
Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), o wnAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCa pacity) { | Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), o wnAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCa pacity) { | |||
RAPIDJSON_ASSERT(stackCapacity > 0); | ||||
} | } | |||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS | |||
Stack(Stack&& rhs) | Stack(Stack&& rhs) | |||
: allocator_(rhs.allocator_), | : allocator_(rhs.allocator_), | |||
ownAllocator_(rhs.ownAllocator_), | ownAllocator_(rhs.ownAllocator_), | |||
stack_(rhs.stack_), | stack_(rhs.stack_), | |||
stackTop_(rhs.stackTop_), | stackTop_(rhs.stackTop_), | |||
stackEnd_(rhs.stackEnd_), | stackEnd_(rhs.stackEnd_), | |||
initialCapacity_(rhs.initialCapacity_) | initialCapacity_(rhs.initialCapacity_) | |||
skipping to change at line 84 | skipping to change at line 89 | |||
rhs.ownAllocator_ = 0; | rhs.ownAllocator_ = 0; | |||
rhs.stack_ = 0; | rhs.stack_ = 0; | |||
rhs.stackTop_ = 0; | rhs.stackTop_ = 0; | |||
rhs.stackEnd_ = 0; | rhs.stackEnd_ = 0; | |||
rhs.initialCapacity_ = 0; | rhs.initialCapacity_ = 0; | |||
} | } | |||
return *this; | return *this; | |||
} | } | |||
#endif | #endif | |||
void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { | ||||
internal::Swap(allocator_, rhs.allocator_); | ||||
internal::Swap(ownAllocator_, rhs.ownAllocator_); | ||||
internal::Swap(stack_, rhs.stack_); | ||||
internal::Swap(stackTop_, rhs.stackTop_); | ||||
internal::Swap(stackEnd_, rhs.stackEnd_); | ||||
internal::Swap(initialCapacity_, rhs.initialCapacity_); | ||||
} | ||||
void Clear() { stackTop_ = stack_; } | void Clear() { stackTop_ = stack_; } | |||
void ShrinkToFit() { | void ShrinkToFit() { | |||
if (Empty()) { | if (Empty()) { | |||
// If the stack is empty, completely deallocate the memory. | // If the stack is empty, completely deallocate the memory. | |||
Allocator::Free(stack_); | Allocator::Free(stack_); | |||
stack_ = 0; | stack_ = 0; | |||
stackTop_ = 0; | stackTop_ = 0; | |||
stackEnd_ = 0; | stackEnd_ = 0; | |||
} | } | |||
else | else | |||
Resize(GetSize()); | Resize(GetSize()); | |||
} | } | |||
// Optimization note: try to minimize the size of this function for force in line. | // Optimization note: try to minimize the size of this function for force in line. | |||
// Expansion is run very infrequently, so it is moved to another (probably n on-inline) function. | // Expansion is run very infrequently, so it is moved to another (probably n on-inline) function. | |||
template<typename T> | template<typename T> | |||
RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { | RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { | |||
// Expand the stack if needed | // Expand the stack if needed | |||
if (stackTop_ + sizeof(T) * count >= stackEnd_) | if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_)) | |||
Expand<T>(count); | Expand<T>(count); | |||
} | ||||
template<typename T> | ||||
RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { | ||||
Reserve<T>(count); | ||||
return PushUnsafe<T>(count); | ||||
} | ||||
template<typename T> | ||||
RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { | ||||
RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_); | ||||
T* ret = reinterpret_cast<T*>(stackTop_); | T* ret = reinterpret_cast<T*>(stackTop_); | |||
stackTop_ += sizeof(T) * count; | stackTop_ += sizeof(T) * count; | |||
return ret; | return ret; | |||
} | } | |||
template<typename T> | template<typename T> | |||
T* Pop(size_t count) { | T* Pop(size_t count) { | |||
RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); | RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); | |||
stackTop_ -= count * sizeof(T); | stackTop_ -= count * sizeof(T); | |||
return reinterpret_cast<T*>(stackTop_); | return reinterpret_cast<T*>(stackTop_); | |||
} | } | |||
template<typename T> | template<typename T> | |||
T* Top() { | T* Top() { | |||
RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); | RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); | |||
return reinterpret_cast<T*>(stackTop_ - sizeof(T)); | return reinterpret_cast<T*>(stackTop_ - sizeof(T)); | |||
} | } | |||
template<typename T> | template<typename T> | |||
T* Bottom() { return (T*)stack_; } | const T* Top() const { | |||
RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); | ||||
return reinterpret_cast<T*>(stackTop_ - sizeof(T)); | ||||
} | ||||
template<typename T> | ||||
T* End() { return reinterpret_cast<T*>(stackTop_); } | ||||
template<typename T> | ||||
const T* End() const { return reinterpret_cast<T*>(stackTop_); } | ||||
template<typename T> | ||||
T* Bottom() { return reinterpret_cast<T*>(stack_); } | ||||
template<typename T> | ||||
const T* Bottom() const { return reinterpret_cast<T*>(stack_); } | ||||
bool HasAllocator() const { | ||||
return allocator_ != 0; | ||||
} | ||||
Allocator& GetAllocator() { | ||||
RAPIDJSON_ASSERT(allocator_); | ||||
return *allocator_; | ||||
} | ||||
Allocator& GetAllocator() { return *allocator_; } | ||||
bool Empty() const { return stackTop_ == stack_; } | bool Empty() const { return stackTop_ == stack_; } | |||
size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); } | size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); } | |||
size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); } | size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); } | |||
private: | private: | |||
template<typename T> | template<typename T> | |||
void Expand(size_t count) { | void Expand(size_t count) { | |||
// Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. | // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. | |||
size_t newCapacity; | size_t newCapacity; | |||
if (stack_ == 0) { | if (stack_ == 0) { | |||
skipping to change at line 154 | skipping to change at line 201 | |||
} | } | |||
size_t newSize = GetSize() + sizeof(T) * count; | size_t newSize = GetSize() + sizeof(T) * count; | |||
if (newCapacity < newSize) | if (newCapacity < newSize) | |||
newCapacity = newSize; | newCapacity = newSize; | |||
Resize(newCapacity); | Resize(newCapacity); | |||
} | } | |||
void Resize(size_t newCapacity) { | void Resize(size_t newCapacity) { | |||
const size_t size = GetSize(); // Backup the current size | const size_t size = GetSize(); // Backup the current size | |||
stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity); | stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), n ewCapacity)); | |||
stackTop_ = stack_ + size; | stackTop_ = stack_ + size; | |||
stackEnd_ = stack_ + newCapacity; | stackEnd_ = stack_ + newCapacity; | |||
} | } | |||
void Destroy() { | void Destroy() { | |||
Allocator::Free(stack_); | Allocator::Free(stack_); | |||
RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the st ack | RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the st ack | |||
} | } | |||
// Prohibit copy constructor & assignment operator. | // Prohibit copy constructor & assignment operator. | |||
skipping to change at line 179 | skipping to change at line 226 | |||
Allocator* ownAllocator_; | Allocator* ownAllocator_; | |||
char *stack_; | char *stack_; | |||
char *stackTop_; | char *stackTop_; | |||
char *stackEnd_; | char *stackEnd_; | |||
size_t initialCapacity_; | size_t initialCapacity_; | |||
}; | }; | |||
} // namespace internal | } // namespace internal | |||
RAPIDJSON_NAMESPACE_END | RAPIDJSON_NAMESPACE_END | |||
#if defined(__clang__) | ||||
RAPIDJSON_DIAG_POP | ||||
#endif | ||||
#endif // RAPIDJSON_STACK_H_ | #endif // RAPIDJSON_STACK_H_ | |||
End of changes. 11 change blocks. | ||||
7 lines changed or deleted | 58 lines changed or added |