diff options
Diffstat (limited to 'ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_Deque.h')
-rw-r--r-- | ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_Deque.h | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_Deque.h b/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_Deque.h new file mode 100644 index 0000000..b83f7ed --- /dev/null +++ b/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_Deque.h @@ -0,0 +1,287 @@ +/************************************************************************************ + +Filename : OVR_Deque.h +Content : Deque container +Created : Nov. 15, 2013 +Authors : Dov Katz + +Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved. + +Licensed under the Oculus Master SDK License Version 1.0 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/oculusmastersdk-1.0 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed 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 specific language governing permissions and +limitations under the License. + +*************************************************************************************/ + +#pragma once + +#include "OVR_ContainerAllocator.h" + +namespace OVR { + +template <class Elem, class Allocator = ContainerAllocator<Elem>> +class Deque { + public: + enum { DefaultCapacity = 500 }; + + Deque(int capacity = DefaultCapacity); + virtual ~Deque(void); + + virtual void PushBack(const Elem& Item); // Adds Item to the end + virtual void PushFront(const Elem& Item); // Adds Item to the beginning + virtual Elem PopBack(void); // Removes Item from the end + virtual Elem PopFront(void); // Removes Item from the beginning + virtual const Elem& PeekBack(int count = 0) const; // Returns count-th Item from the end + virtual const Elem& PeekFront(int count = 0) const; // Returns count-th Item from the beginning + + virtual inline size_t GetSize(void) const; // Returns Number of Elements + OVR_FORCE_INLINE int GetSizeI(void) const { + return (int)GetSize(); + } + virtual inline size_t GetCapacity(void) const; // Returns the maximum possible number of elements + virtual void Clear(void); // Remove all elements + virtual inline bool IsEmpty() const; + virtual inline bool IsFull() const; + + protected: + Elem* Data; // The actual Data array + const int Capacity; // Deque capacity + int Beginning; // Index of the first element + int End; // Index of the next after last element + + // Instead of calculating the number of elements, using this variable + // is much more convenient. + int ElemCount; + + private: + OVR_NON_COPYABLE(Deque); +}; + +template <class Elem, class Allocator = ContainerAllocator<Elem>> +class InPlaceMutableDeque : public Deque<Elem, Allocator> { + typedef Deque<Elem, Allocator> BaseType; + + public: + InPlaceMutableDeque(int capacity = BaseType::DefaultCapacity) : BaseType(capacity) {} + virtual ~InPlaceMutableDeque(){}; + + using BaseType::PeekBack; + using BaseType::PeekFront; + virtual Elem& PeekBack(int count = 0); // Returns count-th Item from the end + virtual Elem& PeekFront(int count = 0); // Returns count-th Item from the beginning +}; + +// Same as Deque, but allows to write more elements than maximum capacity +// Old elements are lost as they are overwritten with the new ones +template <class Elem, class Allocator = ContainerAllocator<Elem>> +class CircularBuffer : public InPlaceMutableDeque<Elem, Allocator> { + typedef InPlaceMutableDeque<Elem, Allocator> BaseType; + + public: + CircularBuffer(int MaxSize = BaseType::DefaultCapacity) : BaseType(MaxSize){}; + virtual ~CircularBuffer() {} + + // The following methods are inline as a workaround for a VS bug causing erroneous C4505 warnings + // See: http://stackoverflow.com/questions/3051992/compiler-warning-at-c-template-base-class + inline virtual void PushBack(const Elem& Item); // Adds Item to the end, overwriting the oldest + // element at the beginning if necessary + inline virtual void PushFront(const Elem& Item); // Adds Item to the beginning, overwriting the + // oldest element at the end if necessary +}; + +//---------------------------------------------------------------------------------- + +// Deque Constructor function +template <class Elem, class Allocator> +Deque<Elem, Allocator>::Deque(int capacity) + : Capacity(capacity), Beginning(0), End(0), ElemCount(0) { + Data = (Elem*)Allocator::Alloc(Capacity * sizeof(Elem)); +} + +// Deque Destructor function +template <class Elem, class Allocator> +Deque<Elem, Allocator>::~Deque(void) { + Clear(); + Allocator::Free(Data); +} + +template <class Elem, class Allocator> +void Deque<Elem, Allocator>::Clear() { + if (!IsEmpty()) { + if (Beginning < End) { + // no wrap-around + Allocator::DestructArray(Data + Beginning, End - Beginning); + } else { + // wrap-around + Allocator::DestructArray(Data + Beginning, Capacity - Beginning); + Allocator::DestructArray(Data, End); + } + } + + Beginning = 0; + End = 0; + ElemCount = 0; +} + +// Push functions +template <class Elem, class Allocator> +void Deque<Elem, Allocator>::PushBack(const Elem& Item) { + // Error Check: Make sure we aren't + // exceeding our maximum storage space + OVR_ASSERT(ElemCount < Capacity); + + Allocator::Construct(Data + End, Item); + ++End; + ++ElemCount; + + // Check for wrap-around + if (End >= Capacity) + End -= Capacity; +} + +template <class Elem, class Allocator> +void Deque<Elem, Allocator>::PushFront(const Elem& Item) { + // Error Check: Make sure we aren't + // exceeding our maximum storage space + OVR_ASSERT(ElemCount < Capacity); + + --Beginning; + // Check for wrap-around + if (Beginning < 0) + Beginning += Capacity; + + Allocator::Construct(Data + Beginning, Item); + ++ElemCount; +} + +// Pop functions +template <class Elem, class Allocator> +Elem Deque<Elem, Allocator>::PopFront(void) { + // Error Check: Make sure we aren't reading from an empty Deque + OVR_ASSERT(ElemCount > 0); + + Elem ReturnValue = Data[Beginning]; + Allocator::Destruct(Data + Beginning); + + ++Beginning; + --ElemCount; + + // Check for wrap-around + if (Beginning >= Capacity) + Beginning -= Capacity; + + return ReturnValue; +} + +template <class Elem, class Allocator> +Elem Deque<Elem, Allocator>::PopBack(void) { + // Error Check: Make sure we aren't reading from an empty Deque + OVR_ASSERT(ElemCount > 0); + + --End; + --ElemCount; + + // Check for wrap-around + if (End < 0) + End += Capacity; + + Elem ReturnValue = Data[End]; + Allocator::Destruct(Data + End); + + return ReturnValue; +} + +// Peek functions +template <class Elem, class Allocator> +const Elem& Deque<Elem, Allocator>::PeekFront(int count) const { + // Error Check: Make sure we aren't reading from an empty Deque + OVR_ASSERT(ElemCount > count); + + int idx = Beginning + count; + if (idx >= Capacity) + idx -= Capacity; + return Data[idx]; +} + +template <class Elem, class Allocator> +const Elem& Deque<Elem, Allocator>::PeekBack(int count) const { + // Error Check: Make sure we aren't reading from an empty Deque + OVR_ASSERT(ElemCount > count); + + int idx = End - count - 1; + if (idx < 0) + idx += Capacity; + return Data[idx]; +} + +// Mutable Peek functions +template <class Elem, class Allocator> +Elem& InPlaceMutableDeque<Elem, Allocator>::PeekFront(int count) { + // Error Check: Make sure we aren't reading from an empty Deque + OVR_ASSERT(BaseType::ElemCount > count); + + int idx = BaseType::Beginning + count; + if (idx >= BaseType::Capacity) + idx -= BaseType::Capacity; + return BaseType::Data[idx]; +} + +template <class Elem, class Allocator> +Elem& InPlaceMutableDeque<Elem, Allocator>::PeekBack(int count) { + // Error Check: Make sure we aren't reading from an empty Deque + OVR_ASSERT(BaseType::ElemCount > count); + + int idx = BaseType::End - count - 1; + if (idx < 0) + idx += BaseType::Capacity; + return BaseType::Data[idx]; +} + +template <class Elem, class Allocator> +inline size_t Deque<Elem, Allocator>::GetCapacity(void) const { + return Capacity; +} + +template <class Elem, class Allocator> +inline size_t Deque<Elem, Allocator>::GetSize(void) const { + return ElemCount; +} + +template <class Elem, class Allocator> +inline bool Deque<Elem, Allocator>::IsEmpty(void) const { + return ElemCount == 0; +} + +template <class Elem, class Allocator> +inline bool Deque<Elem, Allocator>::IsFull(void) const { + return ElemCount == Capacity; +} + +// ******* CircularBuffer<Elem> ******* +// Push functions +template <class Elem, class Allocator> +void CircularBuffer<Elem, Allocator>::PushBack(const Elem& Item) { + if (this->IsFull()) + this->PopFront(); + BaseType::PushBack(Item); +} + +template <class Elem, class Allocator> +void CircularBuffer<Elem, Allocator>::PushFront(const Elem& Item) { + if (this->IsFull()) + this->PopBack(); + BaseType::PushFront(Item); +} + +} // namespace OVR |