2020-03-22 00:45:04 +01:00
|
|
|
#pragma once
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2016-07-07 23:56:54 +02:00
|
|
|
#include <cmath>
|
2016-03-10 04:57:13 +01:00
|
|
|
#include <cassert>
|
2016-03-27 17:41:10 +02:00
|
|
|
#include <cstdarg>
|
2016-03-10 04:57:13 +01:00
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#include <utility>
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
namespace SqMod {
|
|
|
|
|
2016-02-20 23:25:00 +01:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
class Memory;
|
|
|
|
class Buffer;
|
|
|
|
|
2015-11-07 11:17:39 +01:00
|
|
|
/* ------------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* A counted reference to a memory manager instance.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-02-20 23:25:00 +01:00
|
|
|
class MemRef
|
2015-11-07 11:17:39 +01:00
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
private:
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
static MemRef s_Mem;
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
typedef unsigned int Counter;
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------
|
2016-06-03 20:26:19 +02:00
|
|
|
Memory* m_Ptr; // The memory manager instance.
|
|
|
|
Counter* m_Ref; // Reference count to the managed instance.
|
2015-11-07 11:17:39 +01:00
|
|
|
|
2016-02-20 23:25:00 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Grab a strong reference to a memory manager.
|
|
|
|
*/
|
|
|
|
void Grab();
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Drop a strong reference to a memory manager.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-02-20 23:25:00 +01:00
|
|
|
void Drop();
|
|
|
|
|
|
|
|
public:
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Get a reference to the global memory manager instance.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-02-20 23:25:00 +01:00
|
|
|
static const MemRef & Get();
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Default constructor (null).
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2020-03-22 08:16:40 +01:00
|
|
|
MemRef() noexcept
|
2016-03-11 03:14:28 +01:00
|
|
|
: m_Ptr(s_Mem.m_Ptr)
|
|
|
|
, m_Ref(s_Mem.m_Ref)
|
2016-02-20 23:25:00 +01:00
|
|
|
{
|
|
|
|
Grab();
|
|
|
|
}
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Copy constructor.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2020-03-22 08:16:40 +01:00
|
|
|
MemRef(const MemRef & o) noexcept
|
2016-03-11 03:14:28 +01:00
|
|
|
: m_Ptr(o.m_Ptr)
|
|
|
|
, m_Ref(o.m_Ref)
|
2016-02-20 23:25:00 +01:00
|
|
|
|
|
|
|
{
|
|
|
|
Grab();
|
|
|
|
}
|
2015-11-07 11:17:39 +01:00
|
|
|
|
2016-03-10 04:57:13 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Move constructor.
|
|
|
|
*/
|
2020-03-22 08:16:40 +01:00
|
|
|
MemRef(MemRef && o) noexcept
|
2016-03-10 04:57:13 +01:00
|
|
|
: m_Ptr(o.m_Ptr), m_Ref(o.m_Ref)
|
|
|
|
|
|
|
|
{
|
|
|
|
o.m_Ptr = nullptr;
|
|
|
|
o.m_Ref = nullptr;
|
|
|
|
}
|
|
|
|
|
2015-11-07 11:17:39 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Destructor.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-02-20 23:25:00 +01:00
|
|
|
~MemRef()
|
|
|
|
{
|
|
|
|
Drop();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Copy assignment operator.
|
|
|
|
*/
|
2020-03-22 08:16:40 +01:00
|
|
|
MemRef & operator = (const MemRef & o) noexcept // NOLINT(bugprone-unhandled-self-assignment,cert-oop54-cpp)
|
2016-02-20 23:25:00 +01:00
|
|
|
{
|
|
|
|
if (m_Ptr != o.m_Ptr)
|
|
|
|
{
|
|
|
|
Drop();
|
|
|
|
m_Ptr = o.m_Ptr;
|
|
|
|
m_Ref = o.m_Ref;
|
|
|
|
Grab();
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
2015-11-07 11:17:39 +01:00
|
|
|
|
2016-03-10 04:57:13 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Move assignment operator.
|
|
|
|
*/
|
2020-03-22 08:16:40 +01:00
|
|
|
MemRef & operator = (MemRef && o) noexcept
|
2016-03-10 04:57:13 +01:00
|
|
|
{
|
|
|
|
if (m_Ptr != o.m_Ptr)
|
|
|
|
{
|
|
|
|
Drop();
|
|
|
|
m_Ptr = o.m_Ptr;
|
|
|
|
m_Ref = o.m_Ref;
|
|
|
|
o.m_Ptr = nullptr;
|
|
|
|
o.m_Ref = nullptr;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-11-07 11:17:39 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Perform an equality comparison between two memory managers.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-02-20 23:25:00 +01:00
|
|
|
bool operator == (const MemRef & o) const
|
|
|
|
{
|
|
|
|
return (m_Ptr == o.m_Ptr);
|
|
|
|
}
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Perform an inequality comparison between two memory managers.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-02-20 23:25:00 +01:00
|
|
|
bool operator != (const MemRef & o) const
|
|
|
|
{
|
|
|
|
return (m_Ptr != o.m_Ptr);
|
|
|
|
}
|
|
|
|
|
2015-11-07 11:17:39 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Implicit conversion to boolean for use in boolean operations.
|
|
|
|
*/
|
2020-03-22 05:53:04 +01:00
|
|
|
operator bool () const // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
2016-02-20 23:25:00 +01:00
|
|
|
{
|
2020-03-22 05:53:04 +01:00
|
|
|
return static_cast<bool>(m_Ptr);
|
2016-02-20 23:25:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Member operator for dereferencing the managed pointer.
|
|
|
|
*/
|
|
|
|
Memory * operator -> () const
|
|
|
|
{
|
2016-03-10 04:57:13 +01:00
|
|
|
assert(m_Ptr);
|
2016-02-20 23:25:00 +01:00
|
|
|
return m_Ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Indirection operator for obtaining a reference of the managed pointer.
|
|
|
|
*/
|
|
|
|
Memory & operator * () const
|
|
|
|
{
|
2016-03-10 04:57:13 +01:00
|
|
|
assert(m_Ptr);
|
2016-02-20 23:25:00 +01:00
|
|
|
return *m_Ptr;
|
|
|
|
}
|
2016-05-22 05:20:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Release the reference to the managed instance.
|
|
|
|
*/
|
|
|
|
void Reset()
|
|
|
|
{
|
|
|
|
if (m_Ptr)
|
|
|
|
{
|
|
|
|
Drop();
|
|
|
|
}
|
|
|
|
}
|
2016-02-20 23:25:00 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void ThrowMemExcept(const char * msg, ...);
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
2016-03-10 04:57:13 +01:00
|
|
|
* Reusable and re-scalable buffer memory for quick memory allocations.
|
2016-02-20 23:25:00 +01:00
|
|
|
*/
|
|
|
|
class Buffer
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------
|
2016-03-10 04:57:13 +01:00
|
|
|
typedef char Value; // The type of value used to represent a byte.
|
2016-02-20 23:25:00 +01:00
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------
|
2016-03-10 04:57:13 +01:00
|
|
|
typedef Value & Reference; // A reference to the stored value type.
|
|
|
|
typedef const Value & ConstRef; // A const reference to the stored value type.
|
2016-02-20 23:25:00 +01:00
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------
|
2016-03-10 04:57:13 +01:00
|
|
|
typedef Value * Pointer; // A pointer to the stored value type.
|
|
|
|
typedef const Value * ConstPtr; // A const pointer to the stored value type.
|
2016-02-20 23:25:00 +01:00
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------
|
2016-03-10 04:57:13 +01:00
|
|
|
typedef unsigned int SzType; // The type used to represent size in general.
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Construct and take ownership of the specified buffer.
|
|
|
|
*/
|
2020-03-22 08:16:40 +01:00
|
|
|
Buffer(Pointer & ptr, SzType & cap, SzType & cur, MemRef mem)
|
2016-03-10 04:57:13 +01:00
|
|
|
: m_Ptr(ptr)
|
|
|
|
, m_Cap(cap)
|
2016-03-11 03:14:28 +01:00
|
|
|
, m_Cur(cur)
|
2020-03-22 08:16:40 +01:00
|
|
|
, m_Mem(std::move(mem))
|
2016-03-10 04:57:13 +01:00
|
|
|
{
|
|
|
|
ptr = nullptr;
|
|
|
|
cap = 0;
|
2016-03-11 03:14:28 +01:00
|
|
|
cur = 0;
|
2016-03-10 04:57:13 +01:00
|
|
|
}
|
|
|
|
|
2016-07-07 23:56:54 +02:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Round a size value.
|
|
|
|
*/
|
|
|
|
template < typename T > static inline SzType RoundSz(T n)
|
|
|
|
{
|
|
|
|
return static_cast< SzType >(floor(n));
|
|
|
|
}
|
|
|
|
|
2016-03-10 04:57:13 +01:00
|
|
|
public:
|
2016-02-20 23:25:00 +01:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-05-22 05:20:38 +02:00
|
|
|
* Default constructor. (null)
|
2016-02-20 23:25:00 +01:00
|
|
|
*/
|
|
|
|
Buffer()
|
2016-03-10 04:57:13 +01:00
|
|
|
: m_Ptr(nullptr)
|
|
|
|
, m_Cap(0)
|
2016-03-11 03:14:28 +01:00
|
|
|
, m_Cur(0)
|
2016-02-20 23:25:00 +01:00
|
|
|
, m_Mem(MemRef::Get())
|
|
|
|
{
|
2016-03-10 04:57:13 +01:00
|
|
|
/* ... */
|
2016-02-20 23:25:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Explicit size constructor.
|
|
|
|
*/
|
2020-03-22 08:16:40 +01:00
|
|
|
explicit Buffer(SzType size)
|
2016-03-10 04:57:13 +01:00
|
|
|
: m_Ptr(nullptr)
|
2016-02-20 23:25:00 +01:00
|
|
|
, m_Cap(0)
|
2016-03-11 03:14:28 +01:00
|
|
|
, m_Cur(0)
|
2016-02-20 23:25:00 +01:00
|
|
|
, m_Mem(MemRef::Get())
|
|
|
|
{
|
2016-06-15 09:00:28 +02:00
|
|
|
Request(size < 8 ? 8 : size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Explicit size and cursor position constructor.
|
|
|
|
*/
|
|
|
|
Buffer(SzType size, SzType pos)
|
|
|
|
: m_Ptr(nullptr)
|
|
|
|
, m_Cap(0)
|
|
|
|
, m_Cur(0)
|
|
|
|
, m_Mem(MemRef::Get())
|
|
|
|
{
|
|
|
|
Request(size < 8 ? 8 : size);
|
|
|
|
Move(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Explicit size and buffer constructor.
|
|
|
|
*/
|
|
|
|
Buffer(ConstPtr data, SzType size)
|
|
|
|
: m_Ptr(nullptr)
|
|
|
|
, m_Cap(0)
|
|
|
|
, m_Cur(0)
|
|
|
|
, m_Mem(MemRef::Get())
|
|
|
|
{
|
|
|
|
Request(size < 8 ? 8 : size);
|
|
|
|
m_Cur += Write(m_Cur, data, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Explicit size, data and cursor position constructor.
|
|
|
|
*/
|
|
|
|
Buffer(ConstPtr data, SzType size, SzType pos)
|
|
|
|
: m_Ptr(nullptr)
|
|
|
|
, m_Cap(0)
|
|
|
|
, m_Cur(0)
|
|
|
|
, m_Mem(MemRef::Get())
|
|
|
|
{
|
|
|
|
Request(size < 8 ? 8 : size);
|
2020-04-20 03:46:05 +02:00
|
|
|
Write(m_Cur, data, size);
|
2016-06-15 09:00:28 +02:00
|
|
|
Move(pos);
|
2016-02-20 23:25:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Copy constructor.
|
|
|
|
*/
|
|
|
|
Buffer(const Buffer & o);
|
|
|
|
|
2016-03-10 04:57:13 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Move constructor.
|
|
|
|
*/
|
2020-03-22 08:16:40 +01:00
|
|
|
Buffer(Buffer && o) noexcept
|
2016-03-11 03:14:28 +01:00
|
|
|
: m_Ptr(o.m_Ptr)
|
|
|
|
, m_Cap(o.m_Cap)
|
|
|
|
, m_Cur(o.m_Cur)
|
2020-03-22 08:16:40 +01:00
|
|
|
, m_Mem(std::forward< MemRef >(o.m_Mem))
|
2016-03-10 04:57:13 +01:00
|
|
|
{
|
|
|
|
o.m_Ptr = nullptr;
|
|
|
|
}
|
|
|
|
|
2016-02-20 23:25:00 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Destructor.
|
|
|
|
*/
|
|
|
|
~Buffer();
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Copy assignment operator.
|
|
|
|
*/
|
|
|
|
Buffer & operator = (const Buffer & o);
|
|
|
|
|
2016-03-10 04:57:13 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Copy assignment operator.
|
|
|
|
*/
|
2020-03-22 08:16:40 +01:00
|
|
|
Buffer & operator = (Buffer && o) noexcept
|
2016-03-10 04:57:13 +01:00
|
|
|
{
|
|
|
|
if (m_Ptr != o.m_Ptr)
|
|
|
|
{
|
|
|
|
if (m_Ptr)
|
2016-03-11 03:14:28 +01:00
|
|
|
{
|
2016-03-10 04:57:13 +01:00
|
|
|
Release();
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
2016-03-10 04:57:13 +01:00
|
|
|
m_Ptr = o.m_Ptr;
|
|
|
|
m_Cap = o.m_Cap;
|
2016-03-11 03:14:28 +01:00
|
|
|
m_Cur = o.m_Cur;
|
2016-03-10 04:57:13 +01:00
|
|
|
m_Mem = o.m_Mem;
|
|
|
|
o.m_Ptr = nullptr;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-02-20 23:25:00 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Equality comparison operator.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
|
|
|
bool operator == (const Buffer & o) const
|
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
return (m_Cap == o.m_Cap);
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Inequality comparison operator.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
|
|
|
bool operator != (const Buffer & o) const
|
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
return (m_Cap != o.m_Cap);
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Less than comparison operator.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
|
|
|
bool operator < (const Buffer & o) const
|
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
return (m_Cap < o.m_Cap);
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Greater than comparison operator.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
|
|
|
bool operator > (const Buffer & o) const
|
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
return (m_Cap > o.m_Cap);
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Less than or equal comparison operator.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
|
|
|
bool operator <= (const Buffer & o) const
|
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
return (m_Cap <= o.m_Cap);
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Greater than or equal comparison operator.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
|
|
|
bool operator >= (const Buffer & o) const
|
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
return (m_Cap >= o.m_Cap);
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Implicit conversion to boolean.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2020-03-22 08:16:40 +01:00
|
|
|
explicit operator bool () const // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
2015-11-07 11:17:39 +01:00
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
return (m_Ptr != nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Negation operator.
|
|
|
|
*/
|
2016-07-10 15:05:56 +02:00
|
|
|
bool operator ! () const
|
2016-07-07 23:56:54 +02:00
|
|
|
{
|
|
|
|
return (!m_Ptr);
|
2016-02-20 23:25:00 +01:00
|
|
|
}
|
|
|
|
|
2016-03-11 03:14:28 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the internal buffer.
|
|
|
|
*/
|
|
|
|
Pointer Data()
|
|
|
|
{
|
|
|
|
return m_Ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the internal buffer.
|
|
|
|
*/
|
|
|
|
ConstPtr Data() const
|
|
|
|
{
|
|
|
|
return m_Ptr;
|
|
|
|
}
|
|
|
|
|
2016-02-20 23:25:00 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the internal buffer casted as a different type.
|
|
|
|
*/
|
2016-03-11 03:14:28 +01:00
|
|
|
template < typename T = Value > T * Get()
|
2016-02-20 23:25:00 +01:00
|
|
|
{
|
|
|
|
return reinterpret_cast< T * >(m_Ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the internal buffer casted as a different type.
|
|
|
|
*/
|
2016-03-11 03:14:28 +01:00
|
|
|
template < typename T = Value > const T * Get() const
|
2016-02-20 23:25:00 +01:00
|
|
|
{
|
|
|
|
return reinterpret_cast< const T * >(m_Ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-05-22 05:20:38 +02:00
|
|
|
* Retrieve a certain element type at the specified position.
|
2016-02-20 23:25:00 +01:00
|
|
|
*/
|
2016-03-11 03:14:28 +01:00
|
|
|
template < typename T = Value > T & At(SzType n)
|
2016-02-20 23:25:00 +01:00
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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);
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-05-22 05:20:38 +02:00
|
|
|
* Retrieve a certain element type at the specified position.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-03-11 03:14:28 +01:00
|
|
|
template < typename T = Value > const T & At(SzType n) const
|
2015-11-07 11:17:39 +01:00
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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);
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Retrieve the internal buffer casted as a different type.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-03-11 03:14:28 +01:00
|
|
|
template < typename T = Value > T * Begin()
|
2015-11-07 11:17:39 +01:00
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
return reinterpret_cast< T * >(m_Ptr);
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Retrieve the internal buffer casted as a different type.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-03-11 03:14:28 +01:00
|
|
|
template < typename T = Value > const T * Begin() const
|
2015-11-07 11:17:39 +01:00
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
return reinterpret_cast< const T * >(m_Ptr);
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Retrieve the internal buffer casted as a different type.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-03-11 03:14:28 +01:00
|
|
|
template < typename T = Value > T * End()
|
2015-11-07 11:17:39 +01:00
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
return reinterpret_cast< T * >(m_Ptr) + (m_Cap / sizeof(T));
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Retrieve the internal buffer casted as a different type.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-03-11 03:14:28 +01:00
|
|
|
template < typename T = Value > const T * End() const
|
2015-11-07 11:17:39 +01:00
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
return reinterpret_cast< const T * >(m_Ptr) + (m_Cap / sizeof(T));
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-03-11 03:14:28 +01:00
|
|
|
* Retrieve the element at the front of the buffer.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-03-11 03:14:28 +01:00
|
|
|
template < typename T = Value > T & Front()
|
2015-11-07 11:17:39 +01:00
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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);
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-03-11 03:14:28 +01:00
|
|
|
* Retrieve the element at the front of the buffer.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-03-11 03:14:28 +01:00
|
|
|
template < typename T = Value > const T & Front() const
|
2015-11-07 11:17:39 +01:00
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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);
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the element after the first element in the buffer.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > T & Next()
|
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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));
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the element after the first element in the buffer.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > const T & Next() const
|
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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));
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the element at the back of the buffer.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > T & Back()
|
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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)));
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the element at the back of the buffer.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > const T & Back() const
|
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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)));
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the element before the last element in the buffer.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > T & Prev()
|
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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)));
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the element before the last element in the buffer.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > const T & Prev() const
|
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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)));
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Reposition the edit cursor to the specified number of elements ahead.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > void Advance(SzType n)
|
|
|
|
{
|
|
|
|
// Do we need to scale the buffer?
|
2016-07-07 23:56:54 +02:00
|
|
|
if ((m_Cur + (n * sizeof(T))) > m_Cap)
|
2016-03-11 03:14:28 +01:00
|
|
|
{
|
|
|
|
Grow(m_Cur + (n * sizeof(T)));
|
|
|
|
}
|
|
|
|
// Advance to the specified position
|
|
|
|
m_Cur += (n * sizeof(T));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Reposition the edit cursor to the specified number of elements behind.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > void Retreat(SzType n)
|
|
|
|
{
|
|
|
|
// Can we move that much backward?
|
|
|
|
if ((n * sizeof(T)) <= m_Cur)
|
|
|
|
{
|
|
|
|
m_Cur -= (n * sizeof(T));
|
|
|
|
}
|
|
|
|
// Just got to the beginning
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_Cur = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Reposition the edit cursor to a fixed position within the buffer.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > void Move(SzType n)
|
|
|
|
{
|
|
|
|
// Do we need to scale the buffer?
|
2016-07-07 23:56:54 +02:00
|
|
|
if ((n * sizeof(T)) > m_Cap)
|
2016-03-11 03:14:28 +01:00
|
|
|
{
|
|
|
|
Grow(n * sizeof(T));
|
|
|
|
}
|
|
|
|
// Move to the specified position
|
|
|
|
m_Cur = (n * sizeof(T));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-05-22 05:20:38 +02:00
|
|
|
* Append a value to the current cursor location and advance the cursor.
|
2016-03-11 03:14:28 +01:00
|
|
|
*/
|
|
|
|
template < typename T = Value > void Push(T v)
|
|
|
|
{
|
|
|
|
// Do we need to scale the buffer?
|
2016-07-07 23:56:54 +02:00
|
|
|
if ((m_Cur + sizeof(T)) > m_Cap)
|
2016-03-11 03:14:28 +01:00
|
|
|
{
|
|
|
|
Grow(m_Cap + sizeof(T));
|
|
|
|
}
|
|
|
|
// Assign the specified value
|
2016-07-07 23:56:54 +02:00
|
|
|
*reinterpret_cast< T * >(m_Ptr + m_Cur) = v;
|
2016-03-11 03:14:28 +01:00
|
|
|
// Move to the next element
|
|
|
|
m_Cur += sizeof(T);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the element at the cursor position.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > T & Cursor()
|
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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);
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the element at the cursor position.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > const T & Cursor() const
|
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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);
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the element before the cursor position.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > T & Before()
|
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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)));
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the element before the cursor position.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > const T & Before() const
|
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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)));
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the element after the cursor position.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > T & After()
|
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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));
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the element after the cursor position.
|
|
|
|
*/
|
|
|
|
template < typename T = Value > const T & After() const
|
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
// 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));
|
2016-02-20 23:25:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve maximum elements it can hold for a certain type.
|
|
|
|
*/
|
2016-03-11 03:14:28 +01:00
|
|
|
template < typename T = Value > static SzType Max()
|
2016-02-20 23:25:00 +01:00
|
|
|
{
|
2016-03-11 03:14:28 +01:00
|
|
|
return static_cast< SzType >(0xFFFFFFFF / sizeof(T));
|
2016-02-20 23:25:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the current buffer capacity in element count.
|
|
|
|
*/
|
2016-03-11 03:14:28 +01:00
|
|
|
template < typename T = Value > SzType Size() const
|
2016-02-20 23:25:00 +01:00
|
|
|
{
|
2016-03-11 03:14:28 +01:00
|
|
|
return static_cast< SzType >(m_Cap / sizeof(T));
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Retrieve the current buffer capacity in byte count.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-02-20 23:25:00 +01:00
|
|
|
SzType Capacity() const
|
2015-11-07 11:17:39 +01:00
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
return m_Cap;
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
2016-07-07 23:56:54 +02:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
SzType Position() const
|
|
|
|
{
|
|
|
|
return m_Cur;
|
|
|
|
}
|
|
|
|
|
2016-03-11 03:14:28 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the current position of the cursor in the buffer.
|
|
|
|
*/
|
2016-07-07 23:56:54 +02:00
|
|
|
template < typename T = Value > SzType PositionAs() const
|
2016-03-11 03:14:28 +01:00
|
|
|
{
|
|
|
|
return static_cast< SzType >(m_Cur / sizeof(T));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the amount of unused buffer after the edit cursor.
|
|
|
|
*/
|
2016-07-07 23:56:54 +02:00
|
|
|
SzType Remaining() const
|
2016-03-11 03:14:28 +01:00
|
|
|
{
|
2016-07-07 23:56:54 +02:00
|
|
|
return m_Cap - m_Cur;
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Grow the size of the internal buffer by the specified amount of bytes.
|
|
|
|
*/
|
|
|
|
void Grow(SzType n);
|
|
|
|
|
2015-11-07 11:17:39 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Makes sure there is enough capacity to hold the specified element count.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-03-11 03:14:28 +01:00
|
|
|
template < typename T = Value > Buffer Adjust(SzType n)
|
2016-02-20 23:25:00 +01:00
|
|
|
{
|
2016-03-10 04:57:13 +01:00
|
|
|
// Do we meet the minimum size?
|
2016-02-20 23:25:00 +01:00
|
|
|
if (n < 8)
|
2016-03-11 03:14:28 +01:00
|
|
|
{
|
2016-03-10 04:57:13 +01:00
|
|
|
n = 8; // Adjust to minimum size
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
2016-02-20 23:25:00 +01:00
|
|
|
// See if the requested capacity doesn't exceed the limit
|
|
|
|
if (n > Max< T >())
|
2016-03-11 03:14:28 +01:00
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
ThrowMemExcept("Requested buffer of (%u) elements exceeds the (%u) limit", n, Max< T >());
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
2016-02-20 23:25:00 +01:00
|
|
|
// Is there an existing buffer?
|
|
|
|
else if (n && !m_Cap)
|
2016-03-11 03:14:28 +01:00
|
|
|
{
|
2016-03-10 04:57:13 +01:00
|
|
|
Request(n * sizeof(T)); // Request the memory
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
2016-02-20 23:25:00 +01:00
|
|
|
// Should the size be increased?
|
|
|
|
else if (n > m_Cap)
|
|
|
|
{
|
|
|
|
// Backup the current memory
|
2016-03-11 03:14:28 +01:00
|
|
|
Buffer bkp(m_Ptr, m_Cap, m_Cur, m_Mem);
|
2016-02-20 23:25:00 +01:00
|
|
|
// Request the memory
|
|
|
|
Request(n * sizeof(T));
|
2016-03-10 04:57:13 +01:00
|
|
|
// Return the backup
|
|
|
|
return std::move(bkp);
|
2016-02-20 23:25:00 +01:00
|
|
|
}
|
2016-03-10 04:57:13 +01:00
|
|
|
// Return an empty buffer
|
2016-02-20 23:25:00 +01:00
|
|
|
return Buffer();
|
|
|
|
}
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Release the managed memory.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-02-20 23:25:00 +01:00
|
|
|
void Reset()
|
|
|
|
{
|
|
|
|
if (m_Ptr)
|
2016-03-11 03:14:28 +01:00
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
Release();
|
2016-03-11 03:14:28 +01:00
|
|
|
}
|
2016-05-22 05:20:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Release the managed memory and manager.
|
|
|
|
*/
|
|
|
|
void ResetAll()
|
|
|
|
{
|
|
|
|
if (m_Ptr)
|
|
|
|
{
|
|
|
|
Release();
|
|
|
|
}
|
|
|
|
m_Mem.Reset();
|
2016-02-20 23:25:00 +01:00
|
|
|
}
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Swap the contents of two buffers.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-02-20 23:25:00 +01:00
|
|
|
void Swap(Buffer & o)
|
2015-11-07 11:17:39 +01:00
|
|
|
{
|
2016-02-20 23:25:00 +01:00
|
|
|
Pointer p = m_Ptr;
|
|
|
|
SzType n = m_Cap;
|
|
|
|
m_Ptr = o.m_Ptr;
|
|
|
|
m_Cap = o.m_Cap;
|
|
|
|
o.m_Ptr = p;
|
|
|
|
o.m_Cap = n;
|
2015-11-07 11:17:39 +01:00
|
|
|
}
|
|
|
|
|
2016-02-20 23:25:00 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-03-11 03:14:28 +01:00
|
|
|
* Write a portion of a buffer to the internal buffer.
|
2016-02-20 23:25:00 +01:00
|
|
|
*/
|
|
|
|
SzType Write(SzType pos, ConstPtr data, SzType size);
|
|
|
|
|
2016-03-11 03:14:28 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Write another buffer to the internal buffer.
|
|
|
|
*/
|
|
|
|
SzType Write(SzType pos, const Buffer & b)
|
|
|
|
{
|
|
|
|
return Write(pos, b.m_Ptr, b.m_Cur);
|
|
|
|
}
|
|
|
|
|
2016-02-20 23:25:00 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Write a formatted string to the internal buffer.
|
|
|
|
*/
|
|
|
|
SzType WriteF(SzType pos, const char * fmt, ...);
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Write a formatted string to the internal buffer.
|
|
|
|
*/
|
|
|
|
SzType WriteF(SzType pos, const char * fmt, va_list args);
|
|
|
|
|
2016-03-11 03:14:28 +01:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Write a string to the internal buffer.
|
|
|
|
*/
|
|
|
|
SzType WriteS(SzType pos, const char * str);
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Write a portion of a string to the internal buffer.
|
|
|
|
*/
|
|
|
|
SzType WriteS(SzType pos, const char * str, SzType size)
|
|
|
|
{
|
|
|
|
return Write(pos, str, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Append a portion of a buffer to the internal buffer.
|
|
|
|
*/
|
|
|
|
void Append(ConstPtr data, SzType size)
|
|
|
|
{
|
|
|
|
m_Cur += Write(m_Cur, data, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Append another buffer to the internal buffer.
|
|
|
|
*/
|
|
|
|
void Append(const Buffer & b)
|
|
|
|
{
|
|
|
|
m_Cur += Write(m_Cur, b.m_Ptr, b.m_Cur);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Append a formatted string to the internal buffer.
|
|
|
|
*/
|
|
|
|
void AppendF(const char * fmt, ...);
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Append a formatted string to the internal buffer.
|
|
|
|
*/
|
|
|
|
void AppendF(const char * fmt, va_list args)
|
|
|
|
{
|
|
|
|
m_Cur += WriteF(m_Cur, fmt, args);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Append a string to the internal buffer.
|
|
|
|
*/
|
|
|
|
void AppendS(const char * str);
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Append a portion of a string to the internal buffer.
|
|
|
|
*/
|
|
|
|
void AppendS(const char * str, SzType size)
|
|
|
|
{
|
|
|
|
m_Cur += Write(m_Cur, str, size);
|
|
|
|
}
|
|
|
|
|
2015-11-07 11:17:39 +01:00
|
|
|
protected:
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Request the memory specified in the capacity.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-02-20 23:25:00 +01:00
|
|
|
void Request(SzType n);
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
* Release the managed memory buffer.
|
2015-11-07 11:17:39 +01:00
|
|
|
*/
|
2016-02-20 23:25:00 +01:00
|
|
|
void Release();
|
2015-11-07 11:17:39 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------
|
2016-02-20 23:25:00 +01:00
|
|
|
Pointer m_Ptr; /* Pointer to the memory buffer. */
|
|
|
|
SzType m_Cap; /* The total size of the buffer. */
|
2016-03-11 03:14:28 +01:00
|
|
|
SzType m_Cur; /* The buffer edit cursor. */
|
2016-02-20 23:25:00 +01:00
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------
|
2016-03-11 03:14:28 +01:00
|
|
|
MemRef m_Mem; /* Reference to the associated memory manager. */
|
2015-11-07 11:17:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
} // Namespace:: SqMod
|