/**
This file is a part of rexy's general purpose library
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#ifndef REXY_BINARY_BASE_HPP
#define REXY_BINARY_BASE_HPP
#include //size_t
#include //move
#include //memcpy
#include //ptrdiff_t
#include
#include //reverse_iterator
#include "utility.hpp" //max
#include "steal.hpp"
#include "expression.hpp"
#include "traits.hpp"
#include "detail/string_appender.hpp"
#include "detail/hasallocator.hpp"
namespace rexy{
class binary_base
{
public:
using value_type = char;
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = value_type*;
using const_pointer = const value_type*;
using reference = value_type&;
using const_reference = const value_type&;
using iterator = pointer;
using const_iterator = const_pointer;
using reverse_iterator = std::reverse_iterator;
using const_reverse_iterator = std::reverse_iterator;
protected:
pointer m_data = nullptr;
size_type m_size = 0;
size_type m_cap = 0;
protected:
constexpr binary_base(void)noexcept = default;
constexpr binary_base(size_type len)noexcept;
constexpr binary_base(pointer data, size_type size)noexcept;
constexpr binary_base(pointer data, size_type size, size_type cap)noexcept;
constexpr binary_base(const binary_base& b)noexcept;
~binary_base(void)noexcept = default;
public:
constexpr pointer release(void)noexcept;
constexpr size_type size(void)const;
constexpr size_type capacity(void)const;
constexpr pointer get(void);
constexpr const_pointer get(void)const;
constexpr operator bool(void)const;
constexpr reference operator[](size_type i)noexcept;
constexpr const_reference operator[](size_type i)const noexcept;
constexpr iterator begin(void);
constexpr const_iterator begin(void)const;
constexpr iterator end(void);
constexpr const_iterator end(void)const;
constexpr const_iterator cbegin(void)const;
constexpr const_iterator cend(void)const;
constexpr reverse_iterator rbegin(void);
constexpr const_reverse_iterator rbegin(void)const;
constexpr reverse_iterator rend(void);
constexpr const_reverse_iterator rend(void)const;
constexpr const_reverse_iterator crbegin(void)const;
constexpr const_reverse_iterator crend(void)const;
};
template
class basic_binary : protected detail::hasallocator, public binary_base
{
public:
using allocator_type = Allocator;
public:
constexpr basic_binary(void)noexcept;
constexpr basic_binary(rexy::steal data, size_type size)noexcept;
constexpr basic_binary(rexy::steal data, size_type cap, size_type size)noexcept;
constexpr basic_binary(rexy::steal data)noexcept;
basic_binary(const_pointer data, size_type size)noexcept(noexcept(this->allocate(0)));
basic_binary(const_pointer data)noexcept(noexcept(this->allocate(0)));
basic_binary(const_pointer data, size_type size, size_type cap)noexcept(noexcept(this->allocate(0)));
explicit basic_binary(size_type size)noexcept(noexcept(this->allocate(0)));
basic_binary(size_type size, size_type cap)noexcept(noexcept(this->allocate(0)));
basic_binary(const basic_binary& b)noexcept(noexcept(this->allocate(0)));
constexpr basic_binary(basic_binary&& b)noexcept;
basic_binary(const binary_base& b)noexcept(noexcept(this->allocate(0)));
~basic_binary(void)noexcept(noexcept(this->deallocate(nullptr,0)));
basic_binary& operator=(const basic_binary& b)noexcept(noexcept(this->allocate(0)));
constexpr basic_binary& operator=(basic_binary&& b)noexcept;
basic_binary& operator=(const_pointer c)noexcept(noexcept(this->allocate(0)));
basic_binary& operator=(const binary_base& b)noexcept(noexcept(this->allocate(0)));
void reset(void)
noexcept(noexcept(this->deallocate(nullptr,0)));
void reset(pointer val, size_type cap, size_type size = 0)
noexcept(noexcept(this->deallocate(nullptr,0)));
bool resize(size_type newsize)
noexcept(noexcept(this->allocate(0)) &&
noexcept(this->deallocate(nullptr,0)));
void append(const_pointer data, size_type len)
noexcept(noexcept(this->allocate(0)) &&
noexcept(this->deallocate(nullptr,0)));
using detail::hasallocator::allocator;
private:
basic_binary& _copy_data(const_pointer data, size_type len)
noexcept(noexcept(this->allocate(0)) &&
noexcept(this->deallocate(nullptr,0)));
};
template
class binary_cat_expr : public rexy::binary_expression
{
private:
using left_t = std::decay_t;
using right_t = std::decay_t;
static_assert(std::is_same::value);
public:
using value_type = typename left_t::value_type;
using size_type = decltype(typename left_t::size_type{0} + typename right_t::size_type{0});
using difference_type = decltype(typename left_t::difference_type{0} - typename right_t::difference_type{0});
using pointer = value_type*;
using const_pointer = const value_type*;
using reference = value_type&;
using const_reference = const value_type&;
using iterator = pointer;
using const_iterator = const_pointer;
public:
using binary_expression::binary_expression;
constexpr binary_cat_expr(const binary_cat_expr&) = default;
constexpr binary_cat_expr(binary_cat_expr&&) = default;
constexpr size_type size(void)const noexcept;
template
operator basic_binary(void)
noexcept(std::is_nothrow_constructible, typename basic_binary::size_type>::value &&
std::is_nothrow_invocable>,decltype(*this)>::value);
};
class static_binary : public binary_base
{
public:
constexpr static_binary(void)noexcept = default;
constexpr static_binary(const_pointer str, size_type len)noexcept;
constexpr static_binary(const_pointer str)noexcept;
constexpr static_binary(const static_binary&)noexcept;
constexpr static_binary(static_binary&&)noexcept;
~static_binary(void)noexcept = default;
constexpr static_binary& operator=(const_pointer str)noexcept;
constexpr static_binary& operator=(const static_binary& str)noexcept;
constexpr static_binary& operator=(static_binary&& str)noexcept;
};
template
binary_cat_expr(Left&&, Right&&) -> binary_cat_expr;
template
struct is_binary{
static constexpr bool value = rexy::is_type::value || rexy::is_template_type::value;
};
template
struct is_concrete_binary{
static constexpr bool value = rexy::is_type::value;
};
namespace detail{
template
using enable_if_binary = std::enable_if_t<(is_binary::value && ...),int>;
template
using enable_if_concrete_binary = std::enable_if_t<(is_concrete_binary::value && ...),int>;
}
template = 0>
bool operator==(Left&& l, Right&& r)noexcept{
return l && r && l.size() == r.size() && l.capacity() == r.capacity() && !memcmp(l.get(), r.get(), l.size());
}
template = 0>
bool operator!=(Left&& l, Right&& r)noexcept{
return !(std::forward(l) == std::forward(r));
}
template = 0>
auto operator+(Left&& l, Right&& r)
noexcept(noexcept(::new (nullptr) binary_cat_expr(std::forward(l), std::forward(r))))
{
return binary_cat_expr(std::forward(l), std::forward(r));
}
template = 0>
auto operator+(Left&& l, const char* c)
noexcept(noexcept(::new (nullptr) binary_cat_expr(std::forward(l), rexy::static_binary(c))))
{
return binary_cat_expr(std::forward(l), rexy::static_binary(c));
}
template = 0>
auto operator+(const char* c, Right&& r)
noexcept(noexcept(::new (nullptr) binary_cat_expr(rexy::static_binary(c), std::forward(r))))
{
return binary_cat_expr(rexy::static_binary(c), std::forward(r));
}
template = 0, detail::enable_if_binary = 0>
decltype(auto) operator+=(Left& l, Right&& r)
noexcept(noexcept(l + std::forward(r)) && std::is_nothrow_assignable(r))>::value)
{
return l = (l + std::forward(r));
}
template = 0>
decltype(auto) operator+=(Left& l, const char* c)
noexcept(noexcept(l + c) && std::is_nothrow_assignable::value)
{
return l = (l + c);
}
} //namespace rexy
#include "binary_base.tpp"
namespace{
constexpr inline rexy::static_binary operator"" _sb(const char* str, size_t len)noexcept{
return rexy::static_binary(str, len);
}
}
#ifdef REXY_STRING_HPP
#include "detail/binary_string_conv.hpp"
#endif
#endif