/** 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