ByteArray rewritten

Now works internally with std::vector


Former-commit-id: 643f1d88b2959aed324743dbf91f831130a9198e
This commit is contained in:
Gawaboumga 2015-08-21 11:28:04 +02:00
parent 3dbcb25384
commit 0b390e45a1
3 changed files with 365 additions and 434 deletions

View File

@ -8,120 +8,156 @@
#define NAZARA_BYTEARRAY_HPP #define NAZARA_BYTEARRAY_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Hashable.hpp> #include <Nazara/Core/Hashable.hpp>
#include <atomic> #include <Nazara/Core/String.hpp>
#include <memory>
#include <vector>
class NzAbstractHash; class NzAbstractHash;
class NzHashDigest;
class NAZARA_API NzByteArray : public NzHashable class NAZARA_API NzByteArray : public NzHashable
{ {
using Container = std::vector<nzUInt8>;
public: public:
struct SharedArray; // types:
using value_type = typename Container::value_type;
using allocator_type = typename Container::allocator_type;
using size_type = typename Container::size_type;
using difference_type = typename Container::difference_type;
using reference = typename Container::reference;
using const_reference = typename Container::const_reference;
using pointer = typename Container::pointer;
using const_pointer = typename Container::const_pointer;
using iterator = typename Container::iterator;
using const_iterator = typename Container::const_iterator;
using reverse_iterator = typename Container::reverse_iterator;
using const_reverse_iterator = typename Container::const_reverse_iterator;
// iterators:
iterator begin() noexcept;
const_iterator begin() const noexcept;
iterator end() noexcept;
const_iterator end() const noexcept;
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
// construct/destroy:
NzByteArray(); NzByteArray();
explicit NzByteArray(unsigned int size); explicit NzByteArray(size_type n);
NzByteArray(const void* buffer, unsigned int size); NzByteArray(const void* buffer, size_type n);
NzByteArray(const NzByteArray& buffer); NzByteArray(size_type n, const value_type value);
NzByteArray(NzByteArray&& buffer) noexcept; template <class InputIterator>
NzByteArray(SharedArray* sharedArray); NzByteArray(InputIterator first, InputIterator last);
~NzByteArray(); NzByteArray(const NzByteArray& other);
NzByteArray(NzByteArray&& other);
virtual ~NzByteArray();
NzByteArray& Append(const void* buffer, unsigned int size); iterator Append(const void* buffer, size_type size);
NzByteArray& Append(const NzByteArray& array); iterator Append(const NzByteArray& other);
template <class InputIterator>
void Assign(InputIterator first, InputIterator last);
void Assign(size_type n, const value_type value);
reference Back();
const_reference Back() const;
void Clear(bool keepBuffer = false); void Clear(bool keepBuffer = false);
nzUInt8* GetBuffer(); pointer data();
unsigned int GetCapacity() const; const_pointer data() const;
const nzUInt8* GetConstBuffer() const;
unsigned int GetSize() const;
NzByteArray& Insert(int pos, const void* buffer, unsigned int size); bool empty() const noexcept;
NzByteArray& Insert(int pos, const NzByteArray& array); iterator Erase(const_iterator pos);
iterator Erase(const_iterator first, const_iterator last);
bool IsEmpty() const; reference Front();
const_reference Front() const;
NzByteArray& Prepend(const void* buffer, unsigned int size); iterator Insert(const_iterator pos, const void* buffer, size_type n);
NzByteArray& Prepend(const NzByteArray& array); iterator Insert(const_iterator pos, const NzByteArray& other);
iterator Insert(const_iterator pos, size_type n, const value_type byte);
template <class InputIterator>
iterator Insert(const_iterator pos, InputIterator first, InputIterator last);
bool IsEmpty() const noexcept;
void Reserve(unsigned int bufferSize); allocator_type GetAllocator() const;
pointer GetBuffer();
size_type GetCapacity() const noexcept;
const_pointer GetConstBuffer() const;
size_type GetSize() const noexcept;
NzByteArray& Resize(int size); size_type MaxSize() const noexcept;
NzByteArray& Resize(int size, nzUInt8 byte);
NzByteArray Resized(int size) const;
NzByteArray Resized(int size, nzUInt8 byte) const;
NzByteArray SubArray(int startPos, int endPos = -1) const;
void Swap(NzByteArray& array);
// Méthodes compatibles STD
nzUInt8* begin();
const nzUInt8* begin() const;
nzUInt8* end();
const nzUInt8* end() const;
void push_front(nzUInt8 byte);
void push_back(nzUInt8 byte);
/*nzUInt8* rbegin();
const nzUInt8* rbegin() const;
nzUInt8* rend();
const nzUInt8* rend() const;*/
typedef const nzUInt8& const_reference;
typedef nzUInt8* iterator;
//typedef nzUInt8* reverse_iterator;
typedef nzUInt8 value_type;
// Méthodes compatibles STD
nzUInt8& operator[](unsigned int pos);
nzUInt8 operator[](unsigned int pos) const;
// operators:
reference operator[](size_type pos);
const_reference operator[](size_type pos) const;
NzByteArray& operator=(const NzByteArray& array); NzByteArray& operator=(const NzByteArray& array);
NzByteArray& operator=(NzByteArray&& array) noexcept; NzByteArray& operator=(NzByteArray&& array);
NzByteArray operator+(const NzByteArray& array) const; NzByteArray operator+(const NzByteArray& array) const;
NzByteArray& operator+=(const NzByteArray& array); NzByteArray& operator+=(const NzByteArray& array);
static int Compare(const NzByteArray& first, const NzByteArray& second); bool operator==(const NzByteArray& rhs) const;
bool operator!=(const NzByteArray& rhs) const;
bool operator<(const NzByteArray& rhs) const;
bool operator<=(const NzByteArray& rhs) const;
bool operator>(const NzByteArray& rhs) const;
bool operator>=(const NzByteArray& rhs) const;
struct NAZARA_API SharedArray void PopBack();
{ void PopFront();
SharedArray() : iterator Prepend(const void* buffer, size_type size);
refCount(1) iterator Prepend(const NzByteArray& other);
{ void PushBack(const value_type byte);
} void PushFront(const value_type byte);
SharedArray(unsigned short referenceCount, unsigned int bufferSize, unsigned int arraySize, nzUInt8* ptr) : void Reserve(size_type bufferSize);
capacity(bufferSize), void Resize(size_type newSize);
size(arraySize), void Resize(size_type newSize, const value_type byte);
buffer(ptr),
refCount(referenceCount)
{
}
unsigned int capacity; size_type size() const noexcept;
unsigned int size; void ShrinkToFit();
nzUInt8* buffer; NzByteArray SubArray(const_iterator startPos, const_iterator endPos) const;
void Swap(NzByteArray& other);
std::atomic_ushort refCount; NzString ToString() const;
};
static SharedArray emptyArray;
static unsigned int npos;
private: private:
void EnsureOwnership();
bool FillHash(NzAbstractHash* hash) const;
void ReleaseArray();
SharedArray* m_sharedArray; bool FillHash(NzAbstractHash* hash) const;
Container m_array;
}; };
NAZARA_API std::ostream& operator<<(std::ostream& out, const NzByteArray& byteArray);
namespace std namespace std
{ {
NAZARA_API void swap(NzByteArray& lhs, NzByteArray& rhs); NAZARA_API void swap(NzByteArray& lhs, NzByteArray& rhs);
} }
template <class InputIterator>
NzByteArray::NzByteArray(InputIterator first, InputIterator last) :
m_array(first, last)
{
}
template <class InputIterator>
void NzByteArray::Assign(InputIterator first, InputIterator last)
{
m_array.assign(first, last);
}
template <class InputIterator>
NzByteArray::iterator NzByteArray::Insert(const_iterator pos, InputIterator first, InputIterator last)
{
return m_array.insert(pos, first, last);
}
#endif // NAZARA_BYTEARRAY_HPP #endif // NAZARA_BYTEARRAY_HPP

View File

@ -3,492 +3,387 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/ByteArray.hpp> #include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/AbstractHash.hpp> #include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Math/Algorithm.hpp> #include <Nazara/Core/Error.hpp>
#include <algorithm> #include <Nazara/Core/StringStream.hpp>
#include <cstring>
#include <limits>
#include <Nazara/Core/Debug.hpp> #include <Nazara/Core/Debug.hpp>
// Cet algorithme est inspiré de la documentation de Qt NzByteArray::iterator NzByteArray::begin() noexcept
inline unsigned int nzGetNewSize(unsigned int newSize)
{ {
if (newSize < 20) return m_array.begin();
return newSize+4; }
else
{ NzByteArray::const_iterator NzByteArray::begin() const noexcept
if (newSize < (1 << 12)-12) {
return NzGetNearestPowerOfTwo(newSize << 1)-12; return m_array.begin();
else }
return newSize + (1 << 11);
} NzByteArray::iterator NzByteArray::end() noexcept
{
return m_array.end();
}
NzByteArray::const_iterator NzByteArray::end() const noexcept
{
return m_array.end();
}
NzByteArray::reverse_iterator NzByteArray::rbegin() noexcept
{
return m_array.rbegin();
}
NzByteArray::const_reverse_iterator NzByteArray::rbegin() const noexcept
{
return m_array.rbegin();
}
NzByteArray::reverse_iterator NzByteArray::rend() noexcept
{
return m_array.rend();
}
NzByteArray::const_iterator NzByteArray::cbegin() const noexcept
{
return m_array.cbegin();
}
NzByteArray::const_iterator NzByteArray::cend() const noexcept
{
return m_array.cend();
}
NzByteArray::const_reverse_iterator NzByteArray::crbegin() const noexcept
{
return m_array.crbegin();
}
NzByteArray::const_reverse_iterator NzByteArray::crend() const noexcept
{
return m_array.crend();
} }
NzByteArray::NzByteArray() : NzByteArray::NzByteArray() :
m_sharedArray(&emptyArray) m_array()
{ {
} }
NzByteArray::NzByteArray(unsigned int size) NzByteArray::NzByteArray(size_type n) :
m_array()
{ {
if (size > 0) m_array.reserve(n);
{
m_sharedArray = new SharedArray;
m_sharedArray->buffer = new nzUInt8[size];
m_sharedArray->capacity = size;
m_sharedArray->size = size;
}
else
m_sharedArray = &emptyArray;
} }
NzByteArray::NzByteArray(const void* buffer, unsigned int size) NzByteArray::NzByteArray(const void* buffer, size_type n) :
m_array(static_cast<const_pointer>(buffer), static_cast<const_pointer>(buffer) + n)
{ {
if (size > 0)
{
m_sharedArray = new SharedArray;
m_sharedArray->buffer = new nzUInt8[size];
m_sharedArray->capacity = size;
m_sharedArray->size = size;
std::memcpy(m_sharedArray->buffer, buffer, size);
}
else
m_sharedArray = &emptyArray;
} }
NzByteArray::NzByteArray(const NzByteArray& buffer) : NzByteArray::NzByteArray(size_type n, const value_type value) :
m_sharedArray(buffer.m_sharedArray) m_array(n, value)
{ {
if (m_sharedArray != &emptyArray)
m_sharedArray->refCount++;
} }
NzByteArray::NzByteArray(NzByteArray&& buffer) noexcept : NzByteArray::NzByteArray(const NzByteArray& other) :
m_sharedArray(buffer.m_sharedArray) m_array(other.m_array)
{ {
buffer.m_sharedArray = &emptyArray;
} }
NzByteArray::NzByteArray(SharedArray* sharedArray) : NzByteArray::NzByteArray(NzByteArray&& other) :
m_sharedArray(sharedArray) m_array(std::move(other.m_array))
{ {
} }
NzByteArray::~NzByteArray() NzByteArray::~NzByteArray()
{ {
ReleaseArray();
} }
NzByteArray& NzByteArray::Append(const void* buffer, unsigned int size) NzByteArray::iterator NzByteArray::Append(const void* buffer, size_type n)
{ {
return Insert(m_sharedArray->size, buffer, size); return Insert(end(), static_cast<const_pointer>(buffer), static_cast<const_pointer>(buffer) + n);
} }
NzByteArray& NzByteArray::Append(const NzByteArray& array) NzByteArray::iterator NzByteArray::Append(const NzByteArray& other)
{ {
return Insert(m_sharedArray->size, array); return Insert(end(), other.begin(), other.end());
}
void NzByteArray::Assign(size_type n, const value_type value)
{
m_array.assign(n, value);
}
NzByteArray::reference NzByteArray::Back()
{
return m_array.back();
}
NzByteArray::const_reference NzByteArray::Back() const
{
return m_array.back();
} }
void NzByteArray::Clear(bool keepBuffer) void NzByteArray::Clear(bool keepBuffer)
{ {
if (keepBuffer) m_array.clear();
{
EnsureOwnership(); if (!keepBuffer)
m_sharedArray->size = 0; ShrinkToFit();
}
else
ReleaseArray();
} }
nzUInt8* NzByteArray::GetBuffer() NzByteArray::pointer NzByteArray::data()
{ {
EnsureOwnership(); return GetBuffer();
return m_sharedArray->buffer;
} }
unsigned int NzByteArray::GetCapacity() const NzByteArray::const_pointer NzByteArray::data() const
{ {
return m_sharedArray->capacity; return GetConstBuffer();
} }
const nzUInt8* NzByteArray::GetConstBuffer() const bool NzByteArray::empty() const noexcept
{ {
return m_sharedArray->buffer; return IsEmpty();
} }
unsigned int NzByteArray::GetSize() const NzByteArray::iterator NzByteArray::Erase(const_iterator pos)
{ {
return m_sharedArray->size; return m_array.erase(pos);
} }
NzByteArray& NzByteArray::Insert(int pos, const void* buffer, unsigned int size) NzByteArray::iterator NzByteArray::Erase(const_iterator first, const_iterator last)
{ {
if (size == 0) return m_array.erase(first, last);
return *this;
if (pos < 0)
pos = std::max(static_cast<int>(m_sharedArray->size + pos), 0);
unsigned int start = std::min(static_cast<unsigned int>(pos), m_sharedArray->size);
// Si le buffer est déjà suffisamment grand
if (m_sharedArray->capacity >= m_sharedArray->size + size)
{
EnsureOwnership();
std::memmove(&m_sharedArray->buffer[start+size], &m_sharedArray->buffer[start], m_sharedArray->size - start);
std::memcpy(&m_sharedArray->buffer[start], buffer, size);
m_sharedArray->size += size;
}
else
{
unsigned int newSize = m_sharedArray->size + size;
nzUInt8* newBuffer = new nzUInt8[newSize];
nzUInt8* ptr = newBuffer;
if (start > 0)
{
std::memcpy(ptr, m_sharedArray->buffer, start*sizeof(nzUInt8));
ptr += start;
}
std::memcpy(ptr, buffer, size*sizeof(nzUInt8));
ptr += size;
if (m_sharedArray->size > 0)
std::memcpy(ptr, &m_sharedArray->buffer[start], m_sharedArray->size - start);
ReleaseArray();
m_sharedArray = new SharedArray;
m_sharedArray->buffer = newBuffer;
m_sharedArray->capacity = newSize;
m_sharedArray->size = newSize;
}
return *this;
} }
NzByteArray& NzByteArray::Insert(int pos, const NzByteArray& array) NzByteArray::reference NzByteArray::Front()
{ {
return Insert(pos, array.m_sharedArray->buffer, array.m_sharedArray->size); return m_array.front();
} }
bool NzByteArray::IsEmpty() const NzByteArray::const_reference NzByteArray::Front() const
{ {
return m_sharedArray->size == 0; return m_array.front();
} }
NzByteArray& NzByteArray::Prepend(const void* buffer, unsigned int size) NzByteArray::iterator NzByteArray::Insert(const_iterator pos, const void* buffer, size_type n)
{ {
return Insert(0, buffer, size); return Insert(pos, static_cast<const_pointer>(buffer), static_cast<const_pointer>(buffer) + n);
} }
NzByteArray& NzByteArray::Prepend(const NzByteArray& array) NzByteArray::iterator NzByteArray::Insert(const_iterator pos, const NzByteArray& other)
{ {
return Insert(0, array); return Insert(pos, other.begin(), other.end());
} }
void NzByteArray::Reserve(unsigned int bufferSize) NzByteArray::iterator NzByteArray::Insert(const_iterator pos, size_type n, const value_type byte)
{ {
if (m_sharedArray->capacity >= bufferSize) return Insert(pos, n, byte);
return;
nzUInt8* newBuffer = new nzUInt8[bufferSize];
if (m_sharedArray->size > 0)
std::memcpy(newBuffer, m_sharedArray->buffer, m_sharedArray->size);
unsigned int size = m_sharedArray->size;
ReleaseArray();
m_sharedArray = new SharedArray;
m_sharedArray->buffer = newBuffer;
m_sharedArray->capacity = bufferSize;
m_sharedArray->size = size;
} }
NzByteArray& NzByteArray::Resize(int size) bool NzByteArray::IsEmpty() const noexcept
{ {
if (size == 0) return m_array.empty();
{
Clear(true);
return *this;
}
if (size < 0)
size = std::max(static_cast<int>(m_sharedArray->size + size), 0);
unsigned int newSize = static_cast<unsigned int>(size);
if (m_sharedArray->capacity >= newSize)
{
EnsureOwnership();
// Nous avons déjà la place requise
m_sharedArray->size = newSize;
}
else // On veut forcément agrandir la chaine
{
nzUInt8* newBuffer = new nzUInt8[newSize];
if (m_sharedArray->size != 0)
std::memcpy(newBuffer, m_sharedArray->buffer, newSize);
ReleaseArray();
m_sharedArray = new SharedArray;
m_sharedArray->buffer = newBuffer;
m_sharedArray->capacity = newSize;
m_sharedArray->size = newSize;
}
return *this;
} }
NzByteArray& NzByteArray::Resize(int size, nzUInt8 byte) NzByteArray::allocator_type NzByteArray::GetAllocator() const
{ {
if (size == 0) return m_array.get_allocator();
{
Clear(true);
return *this;
}
if (size < 0)
size = std::max(static_cast<int>(m_sharedArray->size + size), 0);
unsigned int newSize = static_cast<unsigned int>(size);
if (m_sharedArray->capacity >= newSize)
{
EnsureOwnership();
// Nous avons déjà la place requise, contentons-nous de remplir le buffer
if (newSize > m_sharedArray->size)
std::memset(&m_sharedArray->buffer[m_sharedArray->size], byte, newSize-m_sharedArray->size);
m_sharedArray->size = newSize;
}
else // On veut forcément agrandir la chaine
{
nzUInt8* newBuffer = new nzUInt8[newSize];
if (m_sharedArray->size != 0)
std::memcpy(newBuffer, m_sharedArray->buffer, newSize);
std::memset(&newBuffer[m_sharedArray->size], byte, newSize-m_sharedArray->size);
ReleaseArray();
m_sharedArray = new SharedArray;
m_sharedArray->buffer = newBuffer;
m_sharedArray->capacity = newSize;
m_sharedArray->size = newSize;
}
return *this;
} }
NzByteArray NzByteArray::Resized(int size) const NzByteArray::pointer NzByteArray::GetBuffer()
{ {
if (size < 0) return m_array.data();
size = m_sharedArray->size + size;
if (size <= 0)
return NzByteArray();
unsigned int newSize = static_cast<unsigned int>(size);
if (newSize == m_sharedArray->size)
return *this;
nzUInt8* buffer = new nzUInt8[newSize];
std::memcpy(buffer, m_sharedArray->buffer, (newSize > m_sharedArray->size) ? m_sharedArray->size : newSize);
return NzByteArray(new SharedArray(1, newSize, newSize, buffer));
} }
NzByteArray NzByteArray::Resized(int size, nzUInt8 byte) const NzByteArray::size_type NzByteArray::GetCapacity() const noexcept
{ {
if (size < 0) return m_array.capacity();
size = m_sharedArray->size + size;
if (size <= 0)
return NzByteArray();
unsigned int newSize = static_cast<unsigned int>(size);
if (newSize == m_sharedArray->size)
return *this;
nzUInt8* buffer = new nzUInt8[newSize];
if (newSize > m_sharedArray->size)
{
std::memcpy(buffer, m_sharedArray->buffer, m_sharedArray->size);
std::memset(&buffer[m_sharedArray->size], byte, newSize - m_sharedArray->size);
}
else
std::memcpy(buffer, m_sharedArray->buffer, newSize);
return NzByteArray(new SharedArray(1, newSize, newSize, buffer));
} }
NzByteArray NzByteArray::SubArray(int startPos, int endPos) const NzByteArray::const_pointer NzByteArray::GetConstBuffer() const
{ {
if (startPos < 0) return m_array.data();
startPos = std::max(m_sharedArray->size+startPos, 0U);
unsigned int start = static_cast<unsigned int>(startPos);
if (endPos < 0)
{
endPos = m_sharedArray->size + endPos;
if (endPos < 0)
return NzByteArray();
}
unsigned int minEnd = std::min(static_cast<unsigned int>(endPos), m_sharedArray->size-1);
if (start > minEnd || start >= m_sharedArray->size)
return NzByteArray();
unsigned int size = minEnd - start + 1;
nzUInt8* buffer = new nzUInt8[size];
std::memcpy(buffer, &m_sharedArray->buffer[start], size);
return NzByteArray(new SharedArray(1, size, size, buffer));
} }
void NzByteArray::Swap(NzByteArray& array) NzByteArray::size_type NzByteArray::GetSize() const noexcept
{ {
std::swap(m_sharedArray, array.m_sharedArray); return m_array.size();
} }
nzUInt8* NzByteArray::begin() NzByteArray::size_type NzByteArray::MaxSize() const noexcept
{ {
return m_sharedArray->buffer; return m_array.max_size();
} }
const nzUInt8* NzByteArray::begin() const NzByteArray::reference NzByteArray::operator[](size_type pos)
{
return m_sharedArray->buffer;
}
nzUInt8* NzByteArray::end()
{
return &m_sharedArray->buffer[m_sharedArray->size];
}
const nzUInt8* NzByteArray::end() const
{
return &m_sharedArray->buffer[m_sharedArray->size];
}
nzUInt8& NzByteArray::operator[](unsigned int pos)
{
EnsureOwnership();
if (pos >= m_sharedArray->size)
Resize(pos+1);
return m_sharedArray->buffer[pos];
}
nzUInt8 NzByteArray::operator[](unsigned int pos) const
{ {
#if NAZARA_CORE_SAFE #if NAZARA_CORE_SAFE
if (pos >= m_sharedArray->size) if (pos >= GetSize())
{ NazaraError("Index out of range (" + NzString::Number(pos) + " >= " + NzString::Number(GetSize()) + ')');
NazaraError("Index out of range (" + NzString::Number(pos) + " >= " + NzString::Number(m_sharedArray->size) + ')');
return 0;
}
#endif #endif
return m_sharedArray->buffer[pos]; return m_array[pos];
} }
NzByteArray& NzByteArray::operator=(const NzByteArray& array) NzByteArray::const_reference NzByteArray::operator[](size_type pos) const
{ {
if (this != &array) #if NAZARA_CORE_SAFE
{ if (pos >= GetSize())
ReleaseArray(); NazaraError("Index out of range (" + NzString::Number(pos) + " >= " + NzString::Number(GetSize()) + ')');
#endif
m_sharedArray = array.m_sharedArray; return m_array[pos];
if (m_sharedArray != &emptyArray) }
m_sharedArray->refCount++;
} NzByteArray& NzByteArray::operator=(const NzByteArray& other)
{
m_array = other.m_array;
return *this; return *this;
} }
NzByteArray& NzByteArray::operator=(NzByteArray&& array) noexcept NzByteArray& NzByteArray::operator=(NzByteArray&& other)
{ {
std::swap(m_sharedArray, array.m_sharedArray); m_array = std::move(other.m_array);
return *this; return *this;
} }
NzByteArray NzByteArray::operator+(const NzByteArray& array) const NzByteArray NzByteArray::operator+(const NzByteArray& other) const
{ {
if (array.m_sharedArray->size == 0) NzByteArray tmp(*this);
return *this; tmp += other;
if (m_sharedArray->size == 0) return tmp;
return array;
unsigned int totalSize = m_sharedArray->size + array.m_sharedArray->size;
nzUInt8* buffer = new nzUInt8[totalSize];
std::memcpy(buffer, m_sharedArray->buffer, m_sharedArray->size);
std::memcpy(&buffer[m_sharedArray->size], array.m_sharedArray->buffer, array.m_sharedArray->size);
return NzByteArray(new SharedArray(1, totalSize, totalSize, buffer));
} }
NzByteArray& NzByteArray::operator+=(const NzByteArray& array) NzByteArray& NzByteArray::operator+=(const NzByteArray& other)
{ {
return Append(array); Append(other);
return *this;
} }
int NzByteArray::Compare(const NzByteArray& first, const NzByteArray& second) bool NzByteArray::operator==(const NzByteArray& rhs) const
{ {
return std::memcmp(first.m_sharedArray->buffer, second.m_sharedArray->buffer, std::min(first.m_sharedArray->size, second.m_sharedArray->size)); return m_array == rhs.m_array;
} }
void NzByteArray::EnsureOwnership() bool NzByteArray::operator!=(const NzByteArray& rhs) const
{ {
if (m_sharedArray == &emptyArray) return !operator==(rhs);
return; }
if (m_sharedArray->refCount > 1) bool NzByteArray::operator<(const NzByteArray& rhs) const
{ {
m_sharedArray->refCount--; return m_array < rhs.m_array;
}
nzUInt8* buffer = new nzUInt8[m_sharedArray->capacity]; bool NzByteArray::operator<=(const NzByteArray& rhs) const
std::memcpy(buffer, m_sharedArray->buffer, m_sharedArray->size); {
return m_array <= rhs.m_array;
}
m_sharedArray = new SharedArray(1, m_sharedArray->capacity, m_sharedArray->size, buffer); bool NzByteArray::operator>(const NzByteArray& rhs) const
} {
return m_array > rhs.m_array;
}
bool NzByteArray::operator>=(const NzByteArray& rhs) const
{
return m_array >= rhs.m_array;
}
void NzByteArray::PopBack()
{
Erase(end() - 1);
}
void NzByteArray::PopFront()
{
Erase(begin());
}
NzByteArray::iterator NzByteArray::Prepend(const void* buffer, size_type n)
{
return Insert(begin(), buffer, n);
}
NzByteArray::iterator NzByteArray::Prepend(const NzByteArray& other)
{
return Insert(begin(), other);
}
void NzByteArray::PushBack(const value_type byte)
{
m_array.push_back(byte);
}
void NzByteArray::PushFront(const value_type byte)
{
m_array.insert(begin(), 1, byte);
}
void NzByteArray::Reserve(size_type bufferSize)
{
m_array.reserve(bufferSize);
}
void NzByteArray::Resize(size_type newSize)
{
m_array.resize(newSize);
}
void NzByteArray::Resize(size_type newSize, const value_type byte)
{
m_array.resize(newSize, byte);
}
NzByteArray::size_type NzByteArray::size() const noexcept
{
return GetSize();
}
void NzByteArray::ShrinkToFit()
{
m_array.shrink_to_fit();
}
NzByteArray NzByteArray::SubArray(const_iterator startPos, const_iterator endPos) const
{
return NzByteArray(startPos, endPos);
}
void NzByteArray::Swap(NzByteArray& other)
{
m_array.swap(other.m_array);
}
NzString NzByteArray::ToString() const
{
NzStringStream ss;
for (const auto& it : m_array)
ss << it;
return ss;
} }
bool NzByteArray::FillHash(NzAbstractHash* hash) const bool NzByteArray::FillHash(NzAbstractHash* hash) const
{ {
hash->Append(m_sharedArray->buffer, m_sharedArray->size); hash->Append(GetConstBuffer(), GetSize());
return true; return true;
} }
void NzByteArray::ReleaseArray() std::ostream& operator<<(std::ostream& out, const NzByteArray& byteArray)
{ {
if (m_sharedArray == &emptyArray) out << byteArray.ToString();
return; return out;
if (--m_sharedArray->refCount == 0)
{
delete[] m_sharedArray->buffer;
delete m_sharedArray;
}
m_sharedArray = &emptyArray;
} }
NzByteArray::SharedArray NzByteArray::emptyArray(0, 0, 0, nullptr);
unsigned int NzByteArray::npos(std::numeric_limits<unsigned int>::max());
namespace std namespace std
{ {
void swap(NzByteArray& lhs, NzByteArray& rhs) void swap(NzByteArray& lhs, NzByteArray& rhs)

View File

@ -192,7 +192,7 @@ NzByteArray NzShader::GetBinary() const
if (binaryLength > 0) if (binaryLength > 0)
{ {
byteArray.Resize(sizeof(nzUInt64) + binaryLength); byteArray.Reserve(sizeof(nzUInt64) + binaryLength);
nzUInt8* buffer = byteArray.GetBuffer(); nzUInt8* buffer = byteArray.GetBuffer();