1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-07-17 14:27:11 +02:00

Initial revision of the buffer implementation.

This commit is contained in:
Sandu Liviu Catalin
2016-07-08 00:56:54 +03:00
parent e5f9fffd8e
commit 4e93e58397
13 changed files with 1001 additions and 1201 deletions

View File

@ -2,6 +2,7 @@
#define _BASE_BUFFER_HPP_
// ------------------------------------------------------------------------------------------------
#include <cmath>
#include <cassert>
#include <cstdarg>
@ -214,6 +215,14 @@ private:
cur = 0;
}
/* --------------------------------------------------------------------------------------------
* Round a size value.
*/
template < typename T > static inline SzType RoundSz(T n)
{
return static_cast< SzType >(floor(n));
}
public:
/* --------------------------------------------------------------------------------------------
@ -380,7 +389,15 @@ public:
*/
operator bool () const
{
return m_Ptr;
return (m_Ptr != nullptr);
}
/* --------------------------------------------------------------------------------------------
* Negation operator.
*/
operator ! () const
{
return (!m_Ptr);
}
/* --------------------------------------------------------------------------------------------
@ -420,8 +437,20 @@ public:
*/
template < typename T = Value > T & At(SzType n)
{
assert(n < static_cast< SzType >(m_Cap / sizeof(T)));
return reinterpret_cast< T * >(m_Ptr)[n];
// Make sure that the buffer can host at least one element of this type
if (m_Cap < sizeof(T))
{
ThrowMemExcept("Buffer capacity of (%u) is unable to host an element of size (%u)",
m_Cap, sizeof(T));
}
// Make sure that the specified element is withing buffer range
else if (n > (m_Cap - sizeof(T)))
{
ThrowMemExcept("Element of size (%d) at index (%u) is out of buffer capacity (%u)",
sizeof(T), n, m_Cap);
}
// Return the requested element
return *reinterpret_cast< T * >(m_Ptr + n);
}
/* --------------------------------------------------------------------------------------------
@ -429,8 +458,20 @@ public:
*/
template < typename T = Value > const T & At(SzType n) const
{
assert(n < static_cast< SzType >(m_Cap / sizeof(T)));
return reinterpret_cast< const T * >(m_Ptr)[n];
// Make sure that the buffer can host at least one element of this type
if (m_Cap < sizeof(T))
{
ThrowMemExcept("Buffer capacity of (%u) is unable to host an element of size (%u)",
m_Cap, sizeof(T));
}
// Make sure that the specified element is withing buffer range
else if (n > (m_Cap - sizeof(T)))
{
ThrowMemExcept("Element of size (%d) at index (%u) is out of buffer capacity (%u)",
sizeof(T), n, m_Cap);
}
// Return the requested element
return *reinterpret_cast< const T * >(m_Ptr + n);
}
/* --------------------------------------------------------------------------------------------
@ -470,8 +511,14 @@ public:
*/
template < typename T = Value > T & Front()
{
assert(m_Cap >= sizeof(T));
return reinterpret_cast< T * >(m_Ptr)[0];
// Make sure that the buffer can host at least one element of this type
if (m_Cap < sizeof(T))
{
ThrowMemExcept("Buffer capacity of (%u) is unable to host an element of size (%u)",
m_Cap, sizeof(T));
}
// Return the requested element
return *reinterpret_cast< T * >(m_Ptr);
}
/* --------------------------------------------------------------------------------------------
@ -479,8 +526,14 @@ public:
*/
template < typename T = Value > const T & Front() const
{
assert(m_Cap >= sizeof(T));
return reinterpret_cast< const T * >(m_Ptr)[0];
// Make sure that the buffer can host at least one element of this type
if (m_Cap < sizeof(T))
{
ThrowMemExcept("Buffer capacity of (%u) is unable to host an element of size (%u)",
m_Cap, sizeof(T));
}
// Return the requested element
return *reinterpret_cast< T * >(m_Ptr);
}
/* --------------------------------------------------------------------------------------------
@ -488,8 +541,14 @@ public:
*/
template < typename T = Value > T & Next()
{
assert(m_Cap >= (sizeof(T) * 2));
return reinterpret_cast< T * >(m_Ptr)[1];
// Make sure that the buffer can host at least two elements of this type
if (m_Cap < (sizeof(T) * 2))
{
ThrowMemExcept("Buffer capacity of (%u) is unable to host two elements of size (%u)",
m_Cap, sizeof(T));
}
// Return the requested element
return *reinterpret_cast< T * >(m_Ptr + sizeof(T));
}
/* --------------------------------------------------------------------------------------------
@ -497,8 +556,14 @@ public:
*/
template < typename T = Value > const T & Next() const
{
assert(m_Cap >= (sizeof(T) * 2));
return reinterpret_cast< const T * >(m_Ptr)[1];
// Make sure that the buffer can host at least two elements of this type
if (m_Cap < (sizeof(T) * 2))
{
ThrowMemExcept("Buffer capacity of (%u) is unable to host two elements of size (%u)",
m_Cap, sizeof(T));
}
// Return the requested element
return *reinterpret_cast< const T * >(m_Ptr + sizeof(T));
}
/* --------------------------------------------------------------------------------------------
@ -506,8 +571,14 @@ public:
*/
template < typename T = Value > T & Back()
{
assert(m_Cap >= sizeof(T));
return reinterpret_cast< T * >(m_Ptr)[(m_Cap / sizeof(T))-1];
// Make sure that the buffer can host at least one element of this type
if (m_Cap < sizeof(T))
{
ThrowMemExcept("Buffer capacity of (%u) is unable to host an element of size (%u)",
m_Cap, sizeof(T));
}
// Return the requested element
return *reinterpret_cast< T * >(m_Ptr + (m_Cap - sizeof(T)));
}
/* --------------------------------------------------------------------------------------------
@ -515,8 +586,14 @@ public:
*/
template < typename T = Value > const T & Back() const
{
assert(m_Cap >= sizeof(T));
return reinterpret_cast< const T * >(m_Ptr)[(m_Cap / sizeof(T))-1];
// Make sure that the buffer can host at least one element of this type
if (m_Cap < sizeof(T))
{
ThrowMemExcept("Buffer capacity of (%u) is unable to host an element of size (%u)",
m_Cap, sizeof(T));
}
// Return the requested element
return *reinterpret_cast< const T * >(m_Ptr + (m_Cap - sizeof(T)));
}
/* --------------------------------------------------------------------------------------------
@ -524,8 +601,14 @@ public:
*/
template < typename T = Value > T & Prev()
{
assert(m_Cap >= (sizeof(T) * 2));
return reinterpret_cast< T * >(m_Ptr)[(m_Cap / sizeof(T))-2];
// Make sure that the buffer can host at least two elements of this type
if (m_Cap < (sizeof(T) * 2))
{
ThrowMemExcept("Buffer capacity of (%u) is unable to host two elements of size (%u)",
m_Cap, sizeof(T));
}
// Return the requested element
return *reinterpret_cast< T * >(m_Ptr + (m_Cap - (sizeof(T) * 2)));
}
/* --------------------------------------------------------------------------------------------
@ -533,8 +616,14 @@ public:
*/
template < typename T = Value > const T & Prev() const
{
assert(m_Cap >= (sizeof(T) * 2));
return reinterpret_cast< const T * >(m_Ptr)[(m_Cap / sizeof(T))-2];
// Make sure that the buffer can host at least two elements of this type
if (m_Cap < (sizeof(T) * 2))
{
ThrowMemExcept("Buffer capacity of (%u) is unable to host two elements of size (%u)",
m_Cap, sizeof(T));
}
// Return the requested element
return *reinterpret_cast< const T * >(m_Ptr + (m_Cap - (sizeof(T) * 2)));
}
/* --------------------------------------------------------------------------------------------
@ -543,7 +632,7 @@ public:
template < typename T = Value > void Advance(SzType n)
{
// Do we need to scale the buffer?
if ((m_Cur + (n * sizeof(T))) >= m_Cap)
if ((m_Cur + (n * sizeof(T))) > m_Cap)
{
Grow(m_Cur + (n * sizeof(T)));
}
@ -574,7 +663,7 @@ public:
template < typename T = Value > void Move(SzType n)
{
// Do we need to scale the buffer?
if ((n * sizeof(T)) >= m_Cap)
if ((n * sizeof(T)) > m_Cap)
{
Grow(n * sizeof(T));
}
@ -588,12 +677,12 @@ public:
template < typename T = Value > void Push(T v)
{
// Do we need to scale the buffer?
if ((m_Cur + sizeof(T)) >= m_Cap)
if ((m_Cur + sizeof(T)) > m_Cap)
{
Grow(m_Cap + sizeof(T));
}
// Assign the specified value
reinterpret_cast< T * >(m_Ptr)[m_Cur] = v;
*reinterpret_cast< T * >(m_Ptr + m_Cur) = v;
// Move to the next element
m_Cur += sizeof(T);
}
@ -603,8 +692,14 @@ public:
*/
template < typename T = Value > T & Cursor()
{
assert((m_Cur / sizeof(T)) < (m_Cap / sizeof(T)));
return reinterpret_cast< T * >(m_Ptr)[m_Cur];
// Make sure that at least one element of this type exists after the cursor
if ((m_Cur + sizeof(T)) > m_Cap)
{
ThrowMemExcept("Element of size (%u) starting at (%u) exceeds buffer capacity (%u)",
sizeof(T), m_Cur, m_Cap);
}
// Return the requested element
return *reinterpret_cast< T * >(m_Ptr + m_Cur);
}
/* --------------------------------------------------------------------------------------------
@ -612,8 +707,14 @@ public:
*/
template < typename T = Value > const T & Cursor() const
{
assert((m_Cur / sizeof(T)) < (m_Cap / sizeof(T)));
return reinterpret_cast< const T * >(m_Ptr)[m_Cur];
// Make sure that at least one element of this type exists after the cursor
if ((m_Cur + sizeof(T)) > m_Cap)
{
ThrowMemExcept("Element of size (%u) starting at (%u) exceeds buffer capacity (%u)",
sizeof(T), m_Cur, m_Cap);
}
// Return the requested element
return *reinterpret_cast< const T * >(m_Ptr + m_Cur);
}
/* --------------------------------------------------------------------------------------------
@ -621,8 +722,14 @@ public:
*/
template < typename T = Value > T & Before()
{
assert(m_Cur >= sizeof(T));
return reinterpret_cast< T * >(m_Ptr)[(m_Cur / sizeof(T))-1];
// The cursor must have at least one element of this type behind
if (m_Cur < sizeof(T))
{
ThrowMemExcept("Cannot read an element of size (%u) before the cursor at (%u)",
sizeof(T), m_Cur);
}
// Return the requested element
return *reinterpret_cast< T * >(m_Ptr + (m_Cur - sizeof(T)));
}
/* --------------------------------------------------------------------------------------------
@ -630,8 +737,14 @@ public:
*/
template < typename T = Value > const T & Before() const
{
assert(m_Cur >= sizeof(T));
return reinterpret_cast< const T * >(m_Ptr)[(m_Cur / sizeof(T))-1];
// The cursor must have at least one element of this type behind
if (m_Cur < sizeof(T))
{
ThrowMemExcept("Cannot read an element of size (%u) before the cursor at (%u)",
sizeof(T), m_Cur);
}
// Return the requested element
return *reinterpret_cast< const T * >(m_Ptr + (m_Cur - sizeof(T)));
}
/* --------------------------------------------------------------------------------------------
@ -639,8 +752,20 @@ public:
*/
template < typename T = Value > T & After()
{
assert(m_Cap >= sizeof(T) && (m_Cur + sizeof(T)) <= (m_Cap - sizeof(T)));
return reinterpret_cast< T * >(m_Ptr)[(m_Cur / sizeof(T))+1];
// Make sure that the buffer can host at least one element of this type
if (m_Cap < sizeof(T))
{
ThrowMemExcept("Buffer capacity of (%u) is unable to host an element of size (%u)",
m_Cap, sizeof(T));
}
// There must be buffer left for at least two elements of this type after the cursor
else if ((m_Cur + (sizeof(T) * 2)) > m_Cap)
{
ThrowMemExcept("Element of size (%u) starting at (%u) exceeds buffer capacity (%u)",
sizeof(T), m_Cur + sizeof(T), m_Cap);
}
// Return the requested element
return *reinterpret_cast< T * >(m_Ptr + m_Cur + sizeof(T));
}
/* --------------------------------------------------------------------------------------------
@ -648,8 +773,20 @@ public:
*/
template < typename T = Value > const T & After() const
{
assert(m_Cap >= sizeof(T) && (m_Cur + sizeof(T)) <= (m_Cap - sizeof(T)));
return reinterpret_cast< const T * >(m_Ptr)[(m_Cur / sizeof(T))+1];
// Make sure that the buffer can host at least one element of this type
if (m_Cap < sizeof(T))
{
ThrowMemExcept("Buffer capacity of (%u) is unable to host an element of size (%u)",
m_Cap, sizeof(T));
}
// There must be buffer left for at least two elements of this type after the cursor
else if ((m_Cur + (sizeof(T) * 2)) > m_Cap)
{
ThrowMemExcept("Element of size (%u) starting at (%u) exceeds buffer capacity (%u)",
sizeof(T), m_Cur + sizeof(T), m_Cap);
}
// Return the requested element
return *reinterpret_cast< const T * >(m_Ptr + m_Cur + sizeof(T));
}
/* --------------------------------------------------------------------------------------------
@ -676,10 +813,26 @@ public:
return m_Cap;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the current buffer capacity in byte count.
*/
template < typename T = Value > SzType CapacityAs() const
{
return static_cast< SzType >(m_Cap / sizeof(T));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the current position of the cursor in the buffer.
*/
template < typename T = Value > SzType Position() const
SzType Position() const
{
return m_Cur;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the current position of the cursor in the buffer.
*/
template < typename T = Value > SzType PositionAs() const
{
return static_cast< SzType >(m_Cur / sizeof(T));
}
@ -687,9 +840,9 @@ public:
/* --------------------------------------------------------------------------------------------
* Retrieve the amount of unused buffer after the edit cursor.
*/
template < typename T = Value > SzType Remaining() const
SzType Remaining() const
{
return static_cast< SzType >((m_Cap - m_Cur) / sizeof(T));
return m_Cap - m_Cur;
}
/* --------------------------------------------------------------------------------------------