mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-09-24 07:06:36 +00:00
Merge branch 'master' into mac
This commit is contained in:
150
GpCommon/GpString.h
Normal file
150
GpCommon/GpString.h
Normal file
@@ -0,0 +1,150 @@
|
||||
#pragma once
|
||||
|
||||
#include "GpVector.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
template<class TChar>
|
||||
class GpString
|
||||
{
|
||||
public:
|
||||
explicit GpString(IGpAllocator *alloc);
|
||||
GpString(GpString<TChar> &&other);
|
||||
|
||||
bool Set(const TChar *str);
|
||||
bool Set(const TChar *str, size_t len);
|
||||
bool Set(const GpString<TChar> &other);
|
||||
|
||||
bool Append(const TChar *str);
|
||||
bool Append(const TChar *str, size_t len);
|
||||
bool Append(const GpString<TChar> &other);
|
||||
|
||||
TChar *Buffer();
|
||||
const TChar *Buffer() const ;
|
||||
|
||||
|
||||
private:
|
||||
static const size_t kStaticSize = 32;
|
||||
|
||||
GpVector<TChar, kStaticSize> m_chars;
|
||||
size_t m_length;
|
||||
};
|
||||
|
||||
typedef GpString<char> GpCString;
|
||||
typedef GpString<wchar_t> GpWString;
|
||||
|
||||
#include <new>
|
||||
#include <string.h>
|
||||
|
||||
template<class TChar>
|
||||
GpString<TChar>::GpString(IGpAllocator *alloc)
|
||||
: m_chars(alloc)
|
||||
, m_length(0)
|
||||
{
|
||||
(void)m_chars.Resize(1);
|
||||
m_chars[0] = static_cast<TChar>(0);
|
||||
}
|
||||
|
||||
template<class TChar>
|
||||
GpString<TChar>::GpString(GpString<TChar> &&other)
|
||||
: m_chars(static_cast<GpVector<TChar, kStaticSize>&&>(other.m_chars))
|
||||
, m_length(other.m_length)
|
||||
{
|
||||
other.m_length = 0;
|
||||
}
|
||||
|
||||
|
||||
template<class TChar>
|
||||
bool GpString<TChar>::Set(const TChar *str)
|
||||
{
|
||||
size_t len = 0;
|
||||
while (str[len] != static_cast<TChar>(0))
|
||||
len++;
|
||||
|
||||
return this->Set(str, len);
|
||||
}
|
||||
|
||||
template<class TChar>
|
||||
bool GpString<TChar>::Set(const TChar *str, size_t len)
|
||||
{
|
||||
if (!m_chars.ResizeNoConstruct(len + 1))
|
||||
return false;
|
||||
|
||||
TChar *chars = m_chars.Buffer();
|
||||
memcpy(chars, str, sizeof(TChar) * len);
|
||||
chars[len] = static_cast<TChar>(0);
|
||||
|
||||
m_length = len;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class TChar>
|
||||
bool GpString<TChar>::Set(const GpString<TChar> &other)
|
||||
{
|
||||
if (&other == this)
|
||||
return true;
|
||||
|
||||
return this->Set(other.Buffer(), other.m_length);
|
||||
}
|
||||
|
||||
template<class TChar>
|
||||
bool GpString<TChar>::Append(const TChar *str)
|
||||
{
|
||||
size_t len = 0;
|
||||
while (str[len] != static_cast<TChar>(0))
|
||||
len++;
|
||||
|
||||
return this->Append(str, len);
|
||||
}
|
||||
|
||||
template<class TChar>
|
||||
bool GpString<TChar>::Append(const TChar *str, size_t len)
|
||||
{
|
||||
// This is a special path in case we're appending the string to itself and the resize relocates the buffer
|
||||
if (len == 0)
|
||||
return true;
|
||||
|
||||
assert(str != this->Buffer());
|
||||
|
||||
if (!m_chars.ResizeNoConstruct(m_length + len + 1))
|
||||
return false;
|
||||
|
||||
memcpy(m_chars.Buffer() + m_length, str, sizeof(TChar) * len);
|
||||
m_chars[m_length + len] = static_cast<TChar>(0);
|
||||
|
||||
m_length += len;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class TChar>
|
||||
bool GpString<TChar>::Append(const GpString<TChar> &other)
|
||||
{
|
||||
// This is a special path in case we're appending the string to itself and the resize relocates the buffer
|
||||
if (other.m_length == 0)
|
||||
return true;
|
||||
|
||||
if (!m_chars.ResizeNoConstruct(m_length + other.m_length))
|
||||
return false;
|
||||
|
||||
memcpy(m_chars.Buffer() + m_length, other.Buffer(), sizeof(TChar) * other.m_length);
|
||||
m_chars[m_length + other.m_length] = static_cast<TChar>(0);
|
||||
|
||||
m_length += other.m_length;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class TChar>
|
||||
TChar *GpString<TChar>::Buffer()
|
||||
{
|
||||
return m_chars.Buffer();
|
||||
}
|
||||
|
||||
template<class TChar>
|
||||
const TChar *GpString<TChar>::Buffer() const
|
||||
{
|
||||
return m_chars.Buffer();
|
||||
}
|
230
GpCommon/GpVector.h
Normal file
230
GpCommon/GpVector.h
Normal file
@@ -0,0 +1,230 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreDefs.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct IGpAllocator;
|
||||
|
||||
template<class T, size_t TStaticSize>
|
||||
class GpVectorStaticData
|
||||
{
|
||||
protected:
|
||||
GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) uint8_t m_staticElementData[sizeof(T) * TStaticSize];
|
||||
|
||||
T *GetStaticElements();
|
||||
const T *GetStaticElements() const;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class GpVectorStaticData<T, 0>
|
||||
{
|
||||
protected:
|
||||
T *GetStaticElements();
|
||||
const T *GetStaticElements() const;
|
||||
};
|
||||
|
||||
|
||||
template<class T, size_t TStaticSize = 0>
|
||||
class GpVector : public GpVectorStaticData<T, TStaticSize>
|
||||
{
|
||||
public:
|
||||
explicit GpVector(IGpAllocator *alloc);
|
||||
GpVector(GpVector<T, TStaticSize> &&other);
|
||||
~GpVector();
|
||||
|
||||
T &operator[](size_t index);
|
||||
const T &operator[](size_t index) const;
|
||||
|
||||
bool Resize(size_t newSize);
|
||||
bool ResizeNoConstruct(size_t newSize);
|
||||
|
||||
T *Buffer();
|
||||
const T *Buffer() const;
|
||||
|
||||
const size_t Count() const;
|
||||
|
||||
private:
|
||||
GpVector(const GpVector<T, TStaticSize> &other) GP_DELETED;
|
||||
|
||||
static const size_t kStaticSize = TStaticSize;
|
||||
|
||||
T *m_elements;
|
||||
size_t m_capacity;
|
||||
size_t m_count;
|
||||
IGpAllocator *m_alloc;
|
||||
};
|
||||
|
||||
#include <new>
|
||||
#include <cassert>
|
||||
#include "IGpAllocator.h"
|
||||
|
||||
template<class T, size_t TStaticSize>
|
||||
T *GpVectorStaticData<T, TStaticSize>::GetStaticElements()
|
||||
{
|
||||
return reinterpret_cast<T*>(this->m_staticElementData);
|
||||
}
|
||||
|
||||
template<class T, size_t TStaticSize>
|
||||
const T *GpVectorStaticData<T, TStaticSize>::GetStaticElements() const
|
||||
{
|
||||
return reinterpret_cast<const T*>(this->m_staticElementData);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T *GpVectorStaticData<T, 0>::GetStaticElements()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
const T *GpVectorStaticData<T, 0>::GetStaticElements() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GpVector
|
||||
template<class T, size_t TStaticSize>
|
||||
GpVector<T, TStaticSize>::GpVector(IGpAllocator *alloc)
|
||||
: m_elements(this->GetStaticElements())
|
||||
, m_capacity(TStaticSize)
|
||||
, m_count(0)
|
||||
, m_alloc(alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T, size_t TStaticSize>
|
||||
GpVector<T, TStaticSize>::GpVector(GpVector<T, TStaticSize> &&other)
|
||||
: m_elements(other.m_elements)
|
||||
, m_capacity(other.m_capacity)
|
||||
, m_count(other.m_count)
|
||||
, m_alloc(other.m_alloc)
|
||||
{
|
||||
if (m_capacity <= TStaticSize)
|
||||
{
|
||||
const size_t count = m_count;
|
||||
T *elements = this->GetStaticElements();
|
||||
const T *srcElements = other.m_elements;
|
||||
m_elements = elements;
|
||||
for (size_t i = 0; i < count; i++)
|
||||
new (m_elements + i) T(static_cast<T&&>(other.m_elements));
|
||||
}
|
||||
|
||||
other.m_count = 0;
|
||||
other.m_capacity = 0;
|
||||
other.m_elements = nullptr;
|
||||
}
|
||||
|
||||
template<class T, size_t TStaticSize>
|
||||
GpVector<T, TStaticSize>::~GpVector()
|
||||
{
|
||||
T *elements = m_elements;
|
||||
size_t remaining = m_count;
|
||||
|
||||
while (remaining > 0)
|
||||
{
|
||||
remaining--;
|
||||
elements[remaining].~T();
|
||||
}
|
||||
|
||||
if (m_capacity > TStaticSize)
|
||||
{
|
||||
m_alloc->Release(m_elements);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, size_t TStaticSize>
|
||||
T &GpVector<T, TStaticSize>::operator[](size_t index)
|
||||
{
|
||||
assert(index <= m_count);
|
||||
return m_elements[index];
|
||||
}
|
||||
|
||||
template<class T, size_t TStaticSize>
|
||||
const T &GpVector<T, TStaticSize>::operator[](size_t index) const
|
||||
{
|
||||
assert(index <= m_count);
|
||||
return m_elements[index];
|
||||
}
|
||||
|
||||
|
||||
template<class T, size_t TStaticSize>
|
||||
bool GpVector<T, TStaticSize>::Resize(size_t newSize)
|
||||
{
|
||||
const size_t oldCount = m_count;
|
||||
|
||||
if (!ResizeNoConstruct(newSize))
|
||||
return false;
|
||||
|
||||
for (size_t i = oldCount; i < newSize; i++)
|
||||
new (m_elements + i) T();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T, size_t TStaticSize>
|
||||
bool GpVector<T, TStaticSize>::ResizeNoConstruct(size_t newSize)
|
||||
{
|
||||
T *elements = m_elements;
|
||||
|
||||
if (newSize <= m_count)
|
||||
{
|
||||
size_t count = m_count;
|
||||
while (count > newSize)
|
||||
{
|
||||
count--;
|
||||
m_elements[count].~T();
|
||||
}
|
||||
|
||||
m_count = count;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (newSize <= m_capacity)
|
||||
{
|
||||
m_count = newSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t newCapacity = newSize;
|
||||
assert(newCapacity > kStaticSize);
|
||||
|
||||
T *newElements = static_cast<T*>(m_alloc->Alloc(newCapacity * sizeof(T)));
|
||||
if (!newElements)
|
||||
return false;
|
||||
|
||||
const size_t oldCount = m_count;
|
||||
for (size_t i = 0; i < oldCount; i++)
|
||||
new (newElements + i) T(static_cast<T&&>(elements[i]));
|
||||
|
||||
for (size_t i = 0; i < oldCount; i++)
|
||||
elements[oldCount - 1 - i].~T();
|
||||
|
||||
if (m_capacity > kStaticSize)
|
||||
m_alloc->Release(m_elements);
|
||||
|
||||
m_elements = newElements;
|
||||
m_capacity = newCapacity;
|
||||
m_count = newSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T, size_t TStaticSize>
|
||||
const size_t GpVector<T, TStaticSize>::Count() const
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
template<class T, size_t TStaticSize>
|
||||
T *GpVector<T, TStaticSize>::Buffer()
|
||||
{
|
||||
return m_elements;
|
||||
}
|
||||
|
||||
template<class T, size_t TStaticSize>
|
||||
const T *GpVector<T, TStaticSize>::Buffer() const
|
||||
{
|
||||
return m_elements;
|
||||
}
|
Reference in New Issue
Block a user