/*
* Copyright (c), Zeriph Enterprises
* All rights reserved.
*
* Contributor(s):
* Zechariah Perez, omni (at) zeriph (dot) com
*
* THIS SOFTWARE IS PROVIDED BY ZERIPH AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ZERIPH AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(OMNI_STACK_BUFFER_HPP)
#define OMNI_STACK_BUFFER_HPP 1
#include <omni/defs/class_macros.hpp>
#include <omni/string/util.hpp>
#include <cstdarg>
namespace omni {
template <
typename T,
uint16_t SZ >
class stack_buffer
{
public:
typedef const T* const_iterator;
typedef T* iterator;
typedef T value_type;
stack_buffer() :
OMNI_CTOR_FW(
omni::stack_buffer)
m_data()
{
if (SZ ==
0) {
OMNI_ERR_FW(
OMNI_INDEX_OOR_STR,
omni::exceptions::index_out_of_range())
}
std::memset(
this->m_data,
0, SZ);
}
stack_buffer(
const T (&data)[SZ]) :
OMNI_CTOR_FW(
omni::stack_buffer)
m_data()
{
if (SZ ==
0) {
OMNI_ERR_FW(
OMNI_INDEX_OOR_STR,
omni::exceptions::index_out_of_range())
}
std::memcpy(
this->m_data, data, SZ);
}
stack_buffer(T val1, ...) :
OMNI_CTOR_FW(
omni::stack_buffer)
m_data()
{
if (SZ ==
0) {
OMNI_ERR_FW(
OMNI_INDEX_OOR_STR,
omni::exceptions::index_out_of_range())
}
std::va_list args;
va_start(args, val1);
this->m_data[
0] = val1;
for (
std::size_t i =
1; i < SZ; ++i) {
this->m_data[i] =
static_cast<T>(va_arg(args, T));
}
va_end(args);
}
template <
uint16_t OTHER_SZ >
stack_buffer(
const T (&data)[OTHER_SZ]) :
OMNI_CTOR_FW(
omni::stack_buffer)
m_data()
{
if ((OTHER_SZ ==
0) || (OTHER_SZ > SZ)) {
OMNI_ERR_FW(
OMNI_INDEX_OOR_STR,
omni::exceptions::index_out_of_range())
}
std::memset(
this->m_data,
0, SZ);
std::memcpy(
this->m_data, data, OTHER_SZ);
}
stack_buffer(
const stack_buffer& cp) :
OMNI_CTOR_FW(
omni::stack_buffer)
m_data()
{
if (SZ ==
0) {
OMNI_ERR_FW(
OMNI_INDEX_OOR_STR,
omni::exceptions::index_out_of_range())
}
std::memcpy(
this->m_data, cp.m_data, SZ);
}
~stack_buffer()
{
OMNI_TRY_FW
std::memset(
this->m_data,
0, SZ);
OMNI_DTOR_FW
OMNI_CATCH_FW
OMNI_D5_FW(
"destroyed");
}
T& at(
uint16_t index)
{
if (index > SZ) {
OMNI_ERRV_RETV_FW(
OMNI_INDEX_OOR_STR, index,
omni::exceptions::index_out_of_range(index), T())
}
return this->m_data[index];
}
T* back()
{
return this->m_data + SZ;
}
iterator begin()
{
return this->m_data;
}
const_iterator begin()
const
{
return const_cast<
const T*>(&
this->m_data[
0]);
}
std::size_t capacity()
const
{
return SZ;
}
T* data()
{
return this->m_data;
}
const T *
const data()
const
{
return this->m_data;
}
iterator end()
{
return this->m_data + SZ;
}
const_iterator end()
const
{
return this->m_data + SZ;
}
T* front()
{
return this->m_data;
}
void fill(T value)
{
for (
std::size_t i =
0; i < SZ; ++i) {
this->m_data[i] = value;
}
}
std::size_t memory_size()
const
{
return SZ *
sizeof(T);
}
void swap(stack_buffer& other)
{
if (
this != &other) {
std::swap(
this->m_data, other.m_data);
}
}
void swap(T (&data)[SZ])
{
if (&
this->m_data != &data) {
std::swap(
this->m_data, data);
}
}
std::size_t size()
const
{
return SZ;
}
void zeroize()
{
std::memset(
this->m_data,
0,
sizeof(T)*SZ);
}
omni::string_t to_string_t()
const
{
omni::sstream_t s;
s <<
this->m_data;
return s.str();
}
std::string to_string()
const
{
std::stringstream s;
s <<
this->m_data;
return s.str();
}
std::wstring to_wstring()
const
{
std::wstringstream s;
s <<
this->m_data;
return s.str();
}
stack_buffer&
operator=(
const stack_buffer& other)
{
if (
this != &other) {
OMNI_ASSIGN_FW(other)
std::memcpy(
this->m_data, other.m_data, SZ);
}
return *
this;
}
stack_buffer&
operator=(
const T (&data)[SZ])
{
if (&
this->m_data != &data) {
std::memcpy(
this->m_data, data, SZ);
}
return *
this;
}
template <
uint16_t OTHER_SZ >
stack_buffer&
operator=(
const T (&data)[OTHER_SZ])
{
if ((OTHER_SZ ==
0) || (OTHER_SZ > SZ)) {
OMNI_ERR_FW(
OMNI_INDEX_OOR_STR,
omni::exceptions::index_out_of_range())
}
std::memset(
this->m_data,
0, SZ);
std::memcpy(
this->m_data, data, OTHER_SZ);
return *
this;
}
bool operator==(
const stack_buffer& other)
const
{
if (
this != &other) {
return (
std::memcmp(
this->m_data, other.m_data, SZ) ==
0);
}
return true;
}
bool operator==(
const T (&data)[SZ])
const
{
return (
std::memcmp(
this->m_data, data, SZ) ==
0);
}
inline bool operator!=(
const stack_buffer& other)
const
{
return !(*
this == other);
}
inline bool operator!=(
const T (&data)[SZ])
const
{
return !(*
this == data);
}
bool operator<(
const stack_buffer& other)
const
{
if (
this == &other) {
return false; }
for (
uint16_t i =
0; i < SZ; ++i) {
if (
this->m_data[i] >= other.m_data[i]) {
return false;
}
}
return true;
}
bool operator<(
const T (&data)[SZ])
const
{
if (&
this->m_data == &data) {
return false; }
for (
uint16_t i =
0; i < SZ; ++i) {
if (
this->m_data[i] >= data[i]) {
return false;
}
}
return true;
}
bool operator>(
const stack_buffer& other)
const
{
if (
this == &other) {
return false; }
for (
uint16_t i =
0; i < SZ; ++i) {
if (
this->m_data[i] <= other.m_data[i]) {
return false;
}
}
return true;
}
bool operator>(
const T (&data)[SZ])
const
{
if (&
this->m_data == &data) {
return false; }
for (
uint16_t i =
0; i < SZ; ++i) {
if (
this->m_data[i] <= data[i]) {
return false;
}
}
return true;
}
bool operator<=(
const stack_buffer& other)
const
{
if (
this == &other) {
return true; }
for (
uint16_t i =
0; i < SZ; ++i) {
if (
this->m_data[i] > other.m_data[i]) {
return false;
}
}
return true;
}
bool operator<=(
const T (&data)[SZ])
const
{
if (&
this->m_data == &data) {
return true; }
for (
uint16_t i =
0; i < SZ; ++i) {
if (
this->m_data[i] > data[i]) {
return false;
}
}
return true;
}
bool operator>=(
const stack_buffer& other)
const
{
if (
this == &other) {
return true; }
for (
uint16_t i =
0; i < SZ; ++i) {
if (
this->m_data[i] < other.m_data[i]) {
return false;
}
}
return true;
}
bool operator>=(
const T (&data)[SZ])
const
{
if (&
this->m_data == &data) {
return true; }
for (
uint16_t i =
0; i < SZ; ++i) {
if (
this->m_data[i] < data[i]) {
return false;
}
}
return true;
}
operator std::string()
const
{
return this->to_string();
}
operator std::wstring()
const
{
return this->to_wstring();
}
template <
template <
class,
class >
class std_seq_t,
typename std_allocator_t >
operator std_seq_t < T, std_allocator_t >()
const
{
return std_seq_t < T, std_allocator_t >(
this->begin(),
this->end());
}
template <
template <
class,
class >
class std_seq_t >
operator std_seq_t < T,
std::allocator<T> >()
const
{
return std_seq_t < T,
std::allocator<T> >(
this->begin(),
this->end());
}
T
operator[](
std::size_t index)
const
{
return this->m_data[index];
}
T&
operator[](
std::size_t index)
{
return this->m_data[index];
}
operator const T *
const()
const
{
return this->m_data;
}
operator T *
const()
{
return this->m_data;
}
OMNI_MEMBERS_FW(
omni::stack_buffer<T, SZ>)
// disposing,name,type(),hash()
OMNI_OSTREAM_FW(
omni::stack_buffer<T, SZ>)
static
std::size_t max_size()
{
return std::numeric_limits<
uint16_t>::max();
}
private:
T m_data[SZ];
};
}
namespace std {
template <
typename T,
uint16_t SZ >
inline void swap(
omni::stack_buffer<T, SZ>& o1,
omni::stack_buffer<T, SZ>& o2)
{
o1.swap(o2);
}
template <
typename T,
uint16_t SZ >
inline void swap(
omni::stack_buffer<T, SZ>& o1, T (&data)[SZ])
{
o1.swap(data);
}
template <
typename T,
uint16_t SZ >
inline void swap(T (&data)[SZ],
omni::stack_buffer<T, SZ>& o1)
{
o1.swap(data);
}
}
#endif // OMNI_STACK_BUFFER_HPP