First
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
#pragma once
|
||||
|
||||
#include "tl/detail/prologue.h"
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
#include "tl/api.h"
|
||||
#include "tl/hash_map.h"
|
||||
#include "tl/plain_assert.h"
|
||||
#include "tl/murmur_hash.h"
|
||||
#include <unordered_map>
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
class TL_API memory_buffer
|
||||
{
|
||||
public:
|
||||
using iterator = uint8_t *;
|
||||
using const_iterator = const uint8_t *;
|
||||
using value_type = uint8_t;
|
||||
|
||||
memory_buffer();
|
||||
~memory_buffer();
|
||||
|
||||
explicit memory_buffer(size_t size, uint8_t value = 0);
|
||||
memory_buffer(const uint8_t* start, const uint8_t* end);
|
||||
memory_buffer(const uint8_t* start, size_t size);
|
||||
|
||||
memory_buffer(const memory_buffer& other);
|
||||
memory_buffer& operator=(const memory_buffer& other);
|
||||
|
||||
memory_buffer(memory_buffer&& other) noexcept;
|
||||
memory_buffer& operator=(memory_buffer&& other) noexcept;
|
||||
|
||||
bool operator==(const memory_buffer& other) const;
|
||||
bool operator!=(const memory_buffer& other) const;
|
||||
|
||||
inline void push_back(uint8_t c);
|
||||
void append(const memory_buffer& other);
|
||||
void append(const uint8_t* start, const uint8_t* end);
|
||||
void append(const uint8_t* start, size_t size);
|
||||
void assign(const uint8_t* start, const uint8_t* end);
|
||||
void erase(iterator begin, iterator end);
|
||||
|
||||
void resize(size_t size, uint8_t value = 0);
|
||||
void resize_uninitialized(size_t size);
|
||||
void reserve(size_t capacity);
|
||||
void shrink_to_fit();
|
||||
|
||||
inline void swap(memory_buffer& other) noexcept;
|
||||
|
||||
void clear();
|
||||
|
||||
inline const uint8_t* data() const;
|
||||
inline uint8_t* data();
|
||||
|
||||
inline const uint8_t& operator[](size_t i) const;
|
||||
inline uint8_t& operator[](size_t i);
|
||||
|
||||
inline uint8_t front() const;
|
||||
inline uint8_t back() const;
|
||||
inline uint8_t& front();
|
||||
inline uint8_t& back();
|
||||
|
||||
inline bool empty() const;
|
||||
inline size_t size() const;
|
||||
inline size_t capacity() const;
|
||||
|
||||
inline iterator begin();
|
||||
inline iterator end();
|
||||
|
||||
inline const_iterator begin() const;
|
||||
inline const_iterator end() const;
|
||||
|
||||
private:
|
||||
//inline uint32_t& _capacity_unsafe();
|
||||
//inline const uint32_t& _capacity_unsafe() const;
|
||||
static size_t get_grow_capacity(size_t needed, size_t capacity);
|
||||
|
||||
//We're storing the sizes in uint32_t and in the allocated buffer itself to save some memory.
|
||||
//This means the memory_buffer is limited to 4GB!
|
||||
//Trying to go over 4GB will result in a crash
|
||||
struct Header// this is only for sizeof purposes
|
||||
{
|
||||
uint32_t m_capacity;
|
||||
uint32_t m_size;
|
||||
};
|
||||
|
||||
uint8_t* m_buf;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define _size() (*reinterpret_cast<uint32_t*>(m_buf))
|
||||
#define _capacity() (*reinterpret_cast<uint32_t*>(m_buf + sizeof(uint32_t)))
|
||||
#define _data() (m_buf + sizeof(Header))
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
inline void memory_buffer::swap(memory_buffer& other) noexcept
|
||||
{
|
||||
std::swap(m_buf, other.m_buf);
|
||||
}
|
||||
|
||||
inline void memory_buffer::push_back(uint8_t c)
|
||||
{
|
||||
const size_t size = _size();
|
||||
const size_t capacity = _capacity();
|
||||
if (size >= capacity)
|
||||
reserve(get_grow_capacity(size + 1u, capacity));
|
||||
|
||||
m_buf[sizeof(Header) + size] = c;
|
||||
_size() = uint32_t(size + 1);
|
||||
}
|
||||
inline const uint8_t* memory_buffer::data() const
|
||||
{
|
||||
return size() > 0 ? _data() : nullptr;
|
||||
}
|
||||
inline uint8_t* memory_buffer::data()
|
||||
{
|
||||
return size() > 0 ? _data() : nullptr;
|
||||
}
|
||||
inline size_t memory_buffer::size() const
|
||||
{
|
||||
return _size();
|
||||
}
|
||||
inline size_t memory_buffer::capacity() const
|
||||
{
|
||||
return _capacity();
|
||||
}
|
||||
inline const uint8_t& memory_buffer::operator[](size_t i) const
|
||||
{
|
||||
TL_PLAIN_ASSERT(i < size());
|
||||
return _data()[i];
|
||||
}
|
||||
inline uint8_t& memory_buffer::operator[](size_t i)
|
||||
{
|
||||
TL_PLAIN_ASSERT(i < size());
|
||||
return _data()[i];
|
||||
}
|
||||
inline uint8_t memory_buffer::front() const
|
||||
{
|
||||
TL_PLAIN_ASSERT(size() > 0);
|
||||
return *_data();
|
||||
}
|
||||
inline uint8_t memory_buffer::back() const
|
||||
{
|
||||
TL_PLAIN_ASSERT(size() > 0);
|
||||
return _data()[_size() - 1];
|
||||
}
|
||||
inline uint8_t& memory_buffer::front()
|
||||
{
|
||||
TL_PLAIN_ASSERT(size() > 0);
|
||||
return *_data();
|
||||
}
|
||||
inline uint8_t& memory_buffer::back()
|
||||
{
|
||||
TL_PLAIN_ASSERT(size() > 0);
|
||||
return _data()[_size() - 1];
|
||||
}
|
||||
|
||||
inline bool memory_buffer::empty() const
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
inline memory_buffer::iterator memory_buffer::begin()
|
||||
{
|
||||
return _data();
|
||||
}
|
||||
inline memory_buffer::iterator memory_buffer::end()
|
||||
{
|
||||
return _data() + _size();
|
||||
}
|
||||
|
||||
inline memory_buffer::const_iterator memory_buffer::begin() const
|
||||
{
|
||||
return _data();
|
||||
}
|
||||
inline memory_buffer::const_iterator memory_buffer::end() const
|
||||
{
|
||||
return _data() + _size();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline void swap(tl::memory_buffer& a, tl::memory_buffer& b) noexcept
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template <> struct std::hash<tl::memory_buffer>
|
||||
{
|
||||
size_t operator()(tl::memory_buffer const& s) const noexcept
|
||||
{
|
||||
if (s.empty())
|
||||
return 0;
|
||||
return tl::murmur32(s.data(), s.size(), 0u);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct eastl::hash<tl::memory_buffer>
|
||||
{
|
||||
size_t operator()(tl::memory_buffer const& s) const
|
||||
{
|
||||
if (s.empty())
|
||||
return 0;
|
||||
return tl::murmur32(s.data(), s.size(), 0u);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#undef _size
|
||||
#undef _capacity
|
||||
#undef _data
|
||||
|
||||
Reference in New Issue
Block a user