mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-07-31 13:11:48 +02:00
Updated the buffer class to include an optional numeric value to be used as an edit cursor or to mark the used buffer size.
Basic implementation of the system path class and several fuctions to retrieve information about the running system.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Buffer.hpp"
|
||||
#include "Base/Buffer.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <cstdlib>
|
||||
@@ -40,7 +40,9 @@ void ThrowMemExcept(const char * msg, ...)
|
||||
int ret = vsnprintf(buffer, sizeof(buffer), msg, args);
|
||||
// Check for formatting errors
|
||||
if (ret < 0)
|
||||
{
|
||||
throw std::runtime_error("Unknown memory error");
|
||||
}
|
||||
// Throw the actual exception
|
||||
throw std::runtime_error(buffer);
|
||||
}
|
||||
@@ -54,7 +56,9 @@ static Buffer::Pointer AllocMem(Buffer::SzType size)
|
||||
Buffer::Pointer ptr = reinterpret_cast< Buffer::Pointer >(malloc(size));
|
||||
// Validate the allocated memory
|
||||
if (!ptr)
|
||||
{
|
||||
ThrowMemExcept("Unable to allocate (%u) bytes of memory", size);
|
||||
}
|
||||
// Return the allocated memory
|
||||
return ptr;
|
||||
}
|
||||
@@ -100,7 +104,9 @@ private:
|
||||
* Base constructor.
|
||||
*/
|
||||
Node(Node * next)
|
||||
: mCap(0), mPtr(nullptr), mNext(next)
|
||||
: mCap(0)
|
||||
, mPtr(nullptr)
|
||||
, mNext(next)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -130,7 +136,9 @@ private:
|
||||
{
|
||||
// Free the memory (if any)
|
||||
if (node->mPtr)
|
||||
{
|
||||
free(node->mPtr);
|
||||
}
|
||||
// Save the next node
|
||||
next = node->mNext;
|
||||
// Release the node instance
|
||||
@@ -149,7 +157,9 @@ private:
|
||||
{
|
||||
// Free the memory (if any)
|
||||
if (node->mPtr)
|
||||
{
|
||||
free(node->mPtr);
|
||||
}
|
||||
// Save the next node
|
||||
next = node->mNext;
|
||||
// Release the node instance
|
||||
@@ -173,10 +183,14 @@ private:
|
||||
{
|
||||
// Was there a previous node?
|
||||
if (prev)
|
||||
{
|
||||
prev->mNext = node->mNext;
|
||||
}
|
||||
// Probably this was the head
|
||||
else
|
||||
{
|
||||
m_Head = node->mNext;
|
||||
}
|
||||
// Assign the memory
|
||||
ptr = node->mPtr;
|
||||
// Assign the size
|
||||
@@ -208,7 +222,9 @@ private:
|
||||
void Drop(Pointer & ptr, SzType & size)
|
||||
{
|
||||
if (!ptr)
|
||||
{
|
||||
ThrowMemExcept("Cannot store invalid memory buffer");
|
||||
}
|
||||
// Request a node instance
|
||||
Node * node = Pull();
|
||||
// Assign the specified memory
|
||||
@@ -232,7 +248,9 @@ private:
|
||||
s_Nodes = new Node(s_Nodes);
|
||||
// Validate the head node
|
||||
if (!s_Nodes)
|
||||
{
|
||||
ThrowMemExcept("Unable to allocate memory nodes");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,7 +261,9 @@ private:
|
||||
{
|
||||
// Are there any nodes available?
|
||||
if (!s_Nodes)
|
||||
{
|
||||
Make(); // Make some!
|
||||
}
|
||||
// Grab the head node
|
||||
Node * node = s_Nodes;
|
||||
// Promote the next node as the head
|
||||
@@ -259,7 +279,9 @@ private:
|
||||
{
|
||||
// See if the node is even valid
|
||||
if (!node)
|
||||
{
|
||||
ThrowMemExcept("Attempting to push invalid node");
|
||||
}
|
||||
// Demote the current head node
|
||||
node->mNext = s_Nodes;
|
||||
// Promote as the head node
|
||||
@@ -324,7 +346,9 @@ MemRef MemRef::s_Mem;
|
||||
void MemRef::Grab()
|
||||
{
|
||||
if (m_Ptr)
|
||||
{
|
||||
++(*m_Ref);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -354,7 +378,8 @@ const MemRef & MemRef::Get()
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Buffer::Buffer(const Buffer & o)
|
||||
: m_Ptr(nullptr)
|
||||
, m_Cap(0)
|
||||
, m_Cap(o.m_Cap)
|
||||
, m_Cur(o.m_Cur)
|
||||
, m_Mem(o.m_Mem)
|
||||
{
|
||||
if (m_Cap)
|
||||
@@ -369,7 +394,9 @@ Buffer::~Buffer()
|
||||
{
|
||||
// Do we have a buffer?
|
||||
if (m_Ptr)
|
||||
{
|
||||
Release(); // Release it!
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -379,30 +406,51 @@ Buffer & Buffer::operator = (const Buffer & o)
|
||||
{
|
||||
// Can we work in the current buffer?
|
||||
if (m_Cap && o.m_Cap <= m_Cap)
|
||||
{
|
||||
// It's safe to copy the data
|
||||
memcpy(m_Ptr, o.m_Ptr, m_Cap);
|
||||
memcpy(m_Ptr, o.m_Ptr, o.m_Cap);
|
||||
}
|
||||
// Do we even have data to copy?
|
||||
else if (!o.m_Cap)
|
||||
{
|
||||
// Do we have a buffer?
|
||||
if (m_Ptr)
|
||||
{
|
||||
Release(); // Release it!
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do we have a buffer?
|
||||
if (m_Ptr)
|
||||
{
|
||||
Release(); // Release it!
|
||||
}
|
||||
// Request a larger buffer
|
||||
Request(o.m_Cap);
|
||||
// Now it's safe to copy the data
|
||||
memcpy(m_Ptr, o.m_Ptr, o.m_Cap);
|
||||
}
|
||||
// Also copy the edit cursor
|
||||
m_Cur = o.m_Cur;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Buffer::Grow(SzType n)
|
||||
{
|
||||
// Backup the current memory
|
||||
Buffer bkp(m_Ptr, m_Cap, m_Cur, m_Mem);
|
||||
// Acquire a bigger buffer
|
||||
Request(bkp.m_Cap + n);
|
||||
// Copy the data from the old buffer
|
||||
memcpy(m_Ptr, bkp.m_Ptr, bkp.m_Cap);
|
||||
// Copy the previous edit cursor
|
||||
m_Cur = bkp.m_Cur;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Buffer::Request(SzType n)
|
||||
{
|
||||
@@ -417,11 +465,17 @@ void Buffer::Request(SzType n)
|
||||
}
|
||||
// Find out in which category does this buffer reside
|
||||
else if (n <= 1024)
|
||||
{
|
||||
m_Mem->m_Small.Grab(m_Ptr, n);
|
||||
}
|
||||
else if (n <= 4096)
|
||||
{
|
||||
m_Mem->m_Medium.Grab(m_Ptr, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Mem->m_Large.Grab(m_Ptr, n);
|
||||
}
|
||||
// If no errors occurred then we can set the size
|
||||
m_Cap = n;
|
||||
}
|
||||
@@ -432,32 +486,41 @@ void Buffer::Release()
|
||||
// TODO: Implement a limit on how much memory can actually be pooled.
|
||||
// Is there a memory manager available?
|
||||
if (!m_Mem)
|
||||
{
|
||||
free(m_Ptr); // Deallocate the memory directly
|
||||
}
|
||||
// Find out to which category does this buffer belong
|
||||
else if (m_Cap <= 1024)
|
||||
{
|
||||
m_Mem->m_Small.Drop(m_Ptr, m_Cap);
|
||||
}
|
||||
else if (m_Cap <= 4096)
|
||||
{
|
||||
m_Mem->m_Medium.Drop(m_Ptr, m_Cap);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Mem->m_Large.Drop(m_Ptr, m_Cap);
|
||||
}
|
||||
// Explicitly reset the buffer
|
||||
m_Ptr = nullptr;
|
||||
m_Cap = 0;
|
||||
m_Cur = 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Buffer::SzType Buffer::Write(SzType pos, ConstPtr data, SzType size)
|
||||
{
|
||||
// Make sure the position is not out of bounds
|
||||
if (pos > m_Cap || !data || !size)
|
||||
// Do we have what to write?
|
||||
if (!data || !size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// See if the buffer size must be adjusted
|
||||
else if ((pos + size) >= m_Cap)
|
||||
{
|
||||
// Allocate a larger memory chunk and backup old data
|
||||
Buffer bkp(Adjust< Value >(NextPow2(pos + size)));
|
||||
// Copy data back from the old buffer
|
||||
memcpy(m_Ptr, bkp.m_Ptr, bkp.m_Cap);
|
||||
// Acquire a larger buffer
|
||||
Grow((pos + size) - m_Cap + 32);
|
||||
}
|
||||
// Copy the data into the internal buffer
|
||||
memcpy(m_Ptr + pos, data, size);
|
||||
@@ -472,7 +535,7 @@ Buffer::SzType Buffer::WriteF(SzType pos, const char * fmt, ...)
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
// Call the function that takes the variable argument list
|
||||
SzType ret = WriteF(pos, fmt, args);
|
||||
const SzType ret = WriteF(pos, fmt, args);
|
||||
// Finalize the variable argument list
|
||||
va_end(args);
|
||||
// Return the result
|
||||
@@ -482,9 +545,12 @@ Buffer::SzType Buffer::WriteF(SzType pos, const char * fmt, ...)
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Buffer::SzType Buffer::WriteF(SzType pos, const char * fmt, va_list args)
|
||||
{
|
||||
// Make sure the position is not out of bounds
|
||||
if (pos > m_Cap)
|
||||
return 0;
|
||||
// Is the specified position within range?
|
||||
if (pos >= m_Cap)
|
||||
{
|
||||
// Acquire a larger buffer
|
||||
Grow(pos - m_Cap + 32);
|
||||
}
|
||||
// Backup the variable argument list
|
||||
va_list args_cpy;
|
||||
va_copy(args_cpy, args);
|
||||
@@ -494,18 +560,53 @@ Buffer::SzType Buffer::WriteF(SzType pos, const char * fmt, va_list args)
|
||||
// Do we need a bigger buffer?
|
||||
if ((pos + ret) >= m_Cap)
|
||||
{
|
||||
// Allocate a larger memory chunk and backup old data
|
||||
Buffer bkp(Adjust< Value >(NextPow2(pos + ret)));
|
||||
// Copy data back from the old buffer
|
||||
memcpy(m_Ptr, bkp.m_Ptr, bkp.m_Cap);
|
||||
// Acquire a larger buffer
|
||||
Grow((pos + ret) - m_Cap + 32);
|
||||
// Retry writing the requested information
|
||||
ret = vsnprintf(m_Ptr + pos, m_Cap, fmt, args_cpy);
|
||||
}
|
||||
// Return the value 0 if data could not be written
|
||||
if (ret < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// Return the number of written characters
|
||||
return static_cast< SzType >(ret);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Buffer::SzType Buffer::WriteS(SzType pos, ConstPtr str)
|
||||
{
|
||||
// Is there any string to write?
|
||||
if (str && *str != '\0')
|
||||
{
|
||||
// Forward this to the regular write function
|
||||
return Write(pos, str, strlen(str));
|
||||
}
|
||||
// Nothing to write
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Buffer::AppendF(const char * fmt, ...)
|
||||
{
|
||||
// Initialize the variable argument list
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
// Forward this to the regular write function
|
||||
m_Cur += WriteF(m_Cur, fmt, args);
|
||||
// Finalize the variable argument list
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Buffer::AppendS(const char * str)
|
||||
{
|
||||
// Is there any string to write?
|
||||
if (str)
|
||||
{
|
||||
m_Cur += Write(m_Cur, str, strlen(str));
|
||||
}
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
@@ -52,7 +52,8 @@ public:
|
||||
* Default constructor (null).
|
||||
*/
|
||||
MemRef()
|
||||
: m_Ptr(s_Mem.m_Ptr), m_Ref(s_Mem.m_Ref)
|
||||
: m_Ptr(s_Mem.m_Ptr)
|
||||
, m_Ref(s_Mem.m_Ref)
|
||||
{
|
||||
Grab();
|
||||
}
|
||||
@@ -61,7 +62,8 @@ public:
|
||||
* Copy constructor.
|
||||
*/
|
||||
MemRef(const MemRef & o)
|
||||
: m_Ptr(o.m_Ptr), m_Ref(o.m_Ref)
|
||||
: m_Ptr(o.m_Ptr)
|
||||
, m_Ref(o.m_Ref)
|
||||
|
||||
{
|
||||
Grab();
|
||||
@@ -189,13 +191,15 @@ private:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Construct and take ownership of the specified buffer.
|
||||
*/
|
||||
Buffer(Pointer & ptr, SzType & cap, const MemRef & mem)
|
||||
Buffer(Pointer & ptr, SzType & cap, SzType & cur, const MemRef & mem)
|
||||
: m_Ptr(ptr)
|
||||
, m_Cap(cap)
|
||||
, m_Cur(cur)
|
||||
, m_Mem(mem)
|
||||
{
|
||||
ptr = nullptr;
|
||||
cap = 0;
|
||||
cur = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -206,6 +210,7 @@ public:
|
||||
Buffer()
|
||||
: m_Ptr(nullptr)
|
||||
, m_Cap(0)
|
||||
, m_Cur(0)
|
||||
, m_Mem(MemRef::Get())
|
||||
{
|
||||
/* ... */
|
||||
@@ -217,6 +222,7 @@ public:
|
||||
Buffer(SzType n)
|
||||
: m_Ptr(nullptr)
|
||||
, m_Cap(0)
|
||||
, m_Cur(0)
|
||||
, m_Mem(MemRef::Get())
|
||||
{
|
||||
Request(n < 8 ? 8 : n);
|
||||
@@ -231,7 +237,10 @@ public:
|
||||
* Move constructor.
|
||||
*/
|
||||
Buffer(Buffer && o)
|
||||
: m_Ptr(o.m_Ptr), m_Cap(o.m_Cap), m_Mem(o.m_Mem)
|
||||
: m_Ptr(o.m_Ptr)
|
||||
, m_Cap(o.m_Cap)
|
||||
, m_Cur(o.m_Cur)
|
||||
, m_Mem(o.m_Mem)
|
||||
{
|
||||
o.m_Ptr = nullptr;
|
||||
}
|
||||
@@ -254,9 +263,12 @@ public:
|
||||
if (m_Ptr != o.m_Ptr)
|
||||
{
|
||||
if (m_Ptr)
|
||||
{
|
||||
Release();
|
||||
}
|
||||
m_Ptr = o.m_Ptr;
|
||||
m_Cap = o.m_Cap;
|
||||
m_Cur = o.m_Cur;
|
||||
m_Mem = o.m_Mem;
|
||||
o.m_Ptr = nullptr;
|
||||
}
|
||||
@@ -319,72 +331,6 @@ public:
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal buffer casted as a different type.
|
||||
*/
|
||||
template < typename T = Value> T * Get()
|
||||
{
|
||||
return reinterpret_cast< T * >(m_Ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal buffer casted as a different type.
|
||||
*/
|
||||
template < typename T = Value> const T * Get() const
|
||||
{
|
||||
return reinterpret_cast< const T * >(m_Ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the a certain element.
|
||||
*/
|
||||
template < typename T = Value> T & At(SzType n)
|
||||
{
|
||||
assert(n < m_Cap);
|
||||
return reinterpret_cast< T * >(m_Ptr)[n];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the a certain element.
|
||||
*/
|
||||
template < typename T = Value> const T & At(SzType n) const
|
||||
{
|
||||
assert(n < m_Cap);
|
||||
return reinterpret_cast< const T * >(m_Ptr)[n];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal buffer casted as a different type.
|
||||
*/
|
||||
template < typename T = Value> T * Begin()
|
||||
{
|
||||
return reinterpret_cast< T * >(m_Ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal buffer casted as a different type.
|
||||
*/
|
||||
template < typename T = Value> const T * Begin() const
|
||||
{
|
||||
return reinterpret_cast< const T * >(m_Ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal buffer casted as a different type.
|
||||
*/
|
||||
template < typename T = Value> T * End()
|
||||
{
|
||||
return reinterpret_cast< T * >(m_Ptr) + (m_Cap / sizeof(T));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal buffer casted as a different type.
|
||||
*/
|
||||
template < typename T = Value> const T * End() const
|
||||
{
|
||||
return reinterpret_cast< const T * >(m_Ptr) + (m_Cap / sizeof(T));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal buffer.
|
||||
*/
|
||||
@@ -401,20 +347,273 @@ public:
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal buffer casted as a different type.
|
||||
*/
|
||||
template < typename T = Value > T * Get()
|
||||
{
|
||||
return reinterpret_cast< T * >(m_Ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal buffer casted as a different type.
|
||||
*/
|
||||
template < typename T = Value > const T * Get() const
|
||||
{
|
||||
return reinterpret_cast< const T * >(m_Ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the a certain element.
|
||||
*/
|
||||
template < typename T = Value > T & At(SzType n)
|
||||
{
|
||||
assert(n < m_Cap);
|
||||
return reinterpret_cast< T * >(m_Ptr)[n];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the a certain element.
|
||||
*/
|
||||
template < typename T = Value > const T & At(SzType n) const
|
||||
{
|
||||
assert(n < m_Cap);
|
||||
return reinterpret_cast< const T * >(m_Ptr)[n];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal buffer casted as a different type.
|
||||
*/
|
||||
template < typename T = Value > T * Begin()
|
||||
{
|
||||
return reinterpret_cast< T * >(m_Ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal buffer casted as a different type.
|
||||
*/
|
||||
template < typename T = Value > const T * Begin() const
|
||||
{
|
||||
return reinterpret_cast< const T * >(m_Ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal buffer casted as a different type.
|
||||
*/
|
||||
template < typename T = Value > T * End()
|
||||
{
|
||||
return reinterpret_cast< T * >(m_Ptr) + (m_Cap / sizeof(T));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the internal buffer casted as a different type.
|
||||
*/
|
||||
template < typename T = Value > const T * End() const
|
||||
{
|
||||
return reinterpret_cast< const T * >(m_Ptr) + (m_Cap / sizeof(T));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element at the front of the buffer.
|
||||
*/
|
||||
template < typename T = Value > T & Front()
|
||||
{
|
||||
assert(m_Cap >= sizeof(T));
|
||||
return reinterpret_cast< T * >(m_Ptr)[0];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element at the front of the buffer.
|
||||
*/
|
||||
template < typename T = Value > const T & Front() const
|
||||
{
|
||||
assert(m_Cap >= sizeof(T));
|
||||
return reinterpret_cast< const T * >(m_Ptr)[0];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element after the first element in the buffer.
|
||||
*/
|
||||
template < typename T = Value > T & Next()
|
||||
{
|
||||
assert(m_Cap >= (sizeof(T) * 2));
|
||||
return reinterpret_cast< T * >(m_Ptr)[1];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element after the first element in the buffer.
|
||||
*/
|
||||
template < typename T = Value > const T & Next() const
|
||||
{
|
||||
assert(m_Cap >= (sizeof(T) * 2));
|
||||
return reinterpret_cast< const T * >(m_Ptr)[1];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element at the back of the buffer.
|
||||
*/
|
||||
template < typename T = Value > T & Back()
|
||||
{
|
||||
assert(m_Cap >= sizeof(T));
|
||||
return reinterpret_cast< T * >(m_Ptr)[m_Cap-1];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element at the back of the buffer.
|
||||
*/
|
||||
template < typename T = Value > const T & Back() const
|
||||
{
|
||||
assert(m_Cap >= sizeof(T));
|
||||
return reinterpret_cast< const T * >(m_Ptr)[m_Cap-1];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element before the last element in the buffer.
|
||||
*/
|
||||
template < typename T = Value > T & Prev()
|
||||
{
|
||||
assert(m_Cap >= (sizeof(T) * 2));
|
||||
return reinterpret_cast< T * >(m_Ptr)[m_Cap-2];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element before the last element in the buffer.
|
||||
*/
|
||||
template < typename T = Value > const T & Prev() const
|
||||
{
|
||||
assert(m_Cap >= (sizeof(T) * 2));
|
||||
return reinterpret_cast< const T * >(m_Ptr)[m_Cap-2];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* 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?
|
||||
if ((m_Cur + (n * sizeof(T))) >= m_Cap)
|
||||
{
|
||||
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?
|
||||
if ((n * sizeof(T)) >= m_Cap)
|
||||
{
|
||||
Grow(n * sizeof(T));
|
||||
}
|
||||
// Move to the specified position
|
||||
m_Cur = (n * sizeof(T));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Reposition the edit cursor to a fixed position within the buffer.
|
||||
*/
|
||||
template < typename T = Value > void Push(T v)
|
||||
{
|
||||
// Do we need to scale the buffer?
|
||||
if ((m_Cur + sizeof(T)) >= m_Cap)
|
||||
{
|
||||
Grow(m_Cap + sizeof(T));
|
||||
}
|
||||
// Assign the specified value
|
||||
reinterpret_cast< T * >(m_Ptr)[m_Cur] = v;
|
||||
// Move to the next element
|
||||
m_Cur += sizeof(T);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element at the cursor position.
|
||||
*/
|
||||
template < typename T = Value > T & Cursor()
|
||||
{
|
||||
assert((m_Cur / sizeof(T)) < (m_Cap / sizeof(T)));
|
||||
return reinterpret_cast< T * >(m_Ptr)[m_Cur];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element at the cursor position.
|
||||
*/
|
||||
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];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element before the cursor position.
|
||||
*/
|
||||
template < typename T = Value > T & Before()
|
||||
{
|
||||
assert(m_Cur >= sizeof(T));
|
||||
return reinterpret_cast< T * >(m_Ptr)[m_Cur-1];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element before the cursor position.
|
||||
*/
|
||||
template < typename T = Value > const T & Before() const
|
||||
{
|
||||
assert(m_Cur >= sizeof(T));
|
||||
return reinterpret_cast< const T * >(m_Ptr)[m_Cur-1];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element after the cursor position.
|
||||
*/
|
||||
template < typename T = Value > T & After()
|
||||
{
|
||||
assert((m_Cur + sizeof(T)) <= (m_Cap - sizeof(T)));
|
||||
return reinterpret_cast< T * >(m_Ptr)[m_Cur+1];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the element after the cursor position.
|
||||
*/
|
||||
template < typename T = Value > const T & After() const
|
||||
{
|
||||
assert((m_Cur + sizeof(T)) <= (m_Cap - sizeof(T)));
|
||||
return reinterpret_cast< const T * >(m_Ptr)[m_Cur+1];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve maximum elements it can hold for a certain type.
|
||||
*/
|
||||
template < typename T = Value> static SzType Max()
|
||||
template < typename T = Value > static SzType Max()
|
||||
{
|
||||
return (0xFFFFFFFF / sizeof(T));
|
||||
return static_cast< SzType >(0xFFFFFFFF / sizeof(T));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the current buffer capacity in element count.
|
||||
*/
|
||||
template < typename T = Value> SzType Size() const
|
||||
template < typename T = Value > SzType Size() const
|
||||
{
|
||||
return (m_Cap / sizeof(T));
|
||||
return static_cast< SzType >(m_Cap / sizeof(T));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -425,25 +624,52 @@ public:
|
||||
return m_Cap;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the current position of the cursor in the buffer.
|
||||
*/
|
||||
template < typename T = Value > SzType Position() const
|
||||
{
|
||||
return static_cast< SzType >(m_Cur / sizeof(T));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the amount of unused buffer after the edit cursor.
|
||||
*/
|
||||
template < typename T = Value > SzType Remaining() const
|
||||
{
|
||||
return static_cast< SzType >((m_Cap - m_Cur) / sizeof(T));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Grow the size of the internal buffer by the specified amount of bytes.
|
||||
*/
|
||||
void Grow(SzType n);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Makes sure there is enough capacity to hold the specified element count.
|
||||
*/
|
||||
template < typename T = Value> Buffer Adjust(SzType n)
|
||||
template < typename T = Value > Buffer Adjust(SzType n)
|
||||
{
|
||||
// Do we meet the minimum size?
|
||||
if (n < 8)
|
||||
{
|
||||
n = 8; // Adjust to minimum size
|
||||
}
|
||||
// See if the requested capacity doesn't exceed the limit
|
||||
if (n > Max< T >())
|
||||
{
|
||||
ThrowMemExcept("Requested buffer of (%u) elements exceeds the (%u) limit", n, Max< T >());
|
||||
}
|
||||
// Is there an existing buffer?
|
||||
else if (n && !m_Cap)
|
||||
{
|
||||
Request(n * sizeof(T)); // Request the memory
|
||||
}
|
||||
// Should the size be increased?
|
||||
else if (n > m_Cap)
|
||||
{
|
||||
// Backup the current memory
|
||||
Buffer bkp(m_Ptr, m_Cap, m_Mem);
|
||||
Buffer bkp(m_Ptr, m_Cap, m_Cur, m_Mem);
|
||||
// Request the memory
|
||||
Request(n * sizeof(T));
|
||||
// Return the backup
|
||||
@@ -459,7 +685,9 @@ public:
|
||||
void Reset()
|
||||
{
|
||||
if (m_Ptr)
|
||||
{
|
||||
Release();
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -476,10 +704,18 @@ public:
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a portion of a buffet to the internal buffer.
|
||||
* Write a portion of a buffer to the internal buffer.
|
||||
*/
|
||||
SzType Write(SzType pos, ConstPtr data, SzType size);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write another buffer to the internal buffer.
|
||||
*/
|
||||
SzType Write(SzType pos, const Buffer & b)
|
||||
{
|
||||
return Write(pos, b.m_Ptr, b.m_Cur);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Write a formatted string to the internal buffer.
|
||||
*/
|
||||
@@ -490,6 +726,61 @@ public:
|
||||
*/
|
||||
SzType WriteF(SzType pos, const char * fmt, va_list args);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* 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);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
@@ -507,9 +798,10 @@ private:
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Pointer m_Ptr; /* Pointer to the memory buffer. */
|
||||
SzType m_Cap; /* The total size of the buffer. */
|
||||
SzType m_Cur; /* The buffer edit cursor. */
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
MemRef m_Mem;
|
||||
MemRef m_Mem; /* Reference to the associated memory manager. */
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
Reference in New Issue
Block a user