/** 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_TPP #define REXY_BINARY_BASE_TPP #include //size_t #include //move #include //memcpy #include #include "utility.hpp" //max #include "steal.hpp" #include "detail/string_appender.hpp" #define STOP_STRICT_ALIAS_WARNING(x) (x) namespace rexy{ constexpr binary_base::binary_base(size_type len)noexcept: m_cap(len){} constexpr binary_base::binary_base(pointer data, size_type size)noexcept: m_data(data), m_cap(size){} constexpr binary_base::binary_base(pointer data, size_type size, size_type cap)noexcept: m_data(data), m_size(size), m_cap(cap){} constexpr binary_base::binary_base(const binary_base&)noexcept{} constexpr auto binary_base::release(void)noexcept -> pointer{ return exchange(m_data, nullptr); } constexpr auto binary_base::size(void)const -> size_type{ return m_size; } constexpr auto binary_base::capacity(void)const -> size_type{ return m_cap; } constexpr auto binary_base::get(void) -> pointer{ return m_data; } constexpr auto binary_base::get(void)const -> const_pointer{ return m_data; } constexpr binary_base::operator bool(void)const{ return m_data; } constexpr auto binary_base::operator[](size_type i)noexcept -> reference{ return m_data[i]; } constexpr auto binary_base::operator[](size_type i)const noexcept -> const_reference{ return m_data[i]; } constexpr auto binary_base::begin(void) -> iterator{ return m_data; } constexpr auto binary_base::begin(void)const -> const_iterator{ return m_data; } constexpr auto binary_base::end(void) -> iterator{ return m_data + m_size; } constexpr auto binary_base::end(void)const -> const_iterator{ return m_data + m_size; } constexpr auto binary_base::cbegin(void)const -> const_iterator{ return m_data; } constexpr auto binary_base::cend(void)const -> const_iterator{ return m_data + m_size; } constexpr auto binary_base::rbegin(void) -> reverse_iterator{ return reverse_iterator(m_data + m_size); } constexpr auto binary_base::rbegin(void)const -> const_reverse_iterator{ return reverse_iterator(m_data + m_size); } constexpr auto binary_base::rend(void) -> reverse_iterator{ return reverse_iterator(m_data - 1); } constexpr auto binary_base::rend(void)const -> const_reverse_iterator{ return reverse_iterator(m_data - 1); } constexpr auto binary_base::crbegin(void)const -> const_reverse_iterator{ return rbegin(); } constexpr auto binary_base::crend(void)const -> const_reverse_iterator{ return rend(); } template constexpr basic_binary::basic_binary(void)noexcept{} template constexpr basic_binary::basic_binary(rexy::steal data)noexcept: binary_base(data.value() ? strlen(data.value()) : 0) { m_data = data.value(); m_size = m_cap; } template constexpr basic_binary::basic_binary(rexy::steal data, size_type size)noexcept: binary_base(data.value(), size){} template constexpr basic_binary::basic_binary(rexy::steal data, size_type cap, size_type size)noexcept: binary_base(data.value(), cap, size){} template basic_binary::basic_binary(const_pointer data, size_type size) noexcept(noexcept(this->allocate(0))): binary_base(size ? this->allocate(size) : nullptr, size) { if(size) memcpy(m_data, data, size); } template basic_binary::basic_binary(const_pointer data) noexcept(noexcept(this->allocate(0))): basic_binary(data ? this->allocate(strlen(data)) : nullptr, strlen(data)) { if(data) memcpy(m_data, data, m_cap); } template basic_binary::basic_binary(const_pointer data, size_type size, size_type cap) noexcept(noexcept(this->allocate(0))): binary_base(size ? this->allocate(size) : nullptr, size, cap) { if(size) memcpy(m_data, data, size); } template basic_binary::basic_binary(size_type size) noexcept(noexcept(this->allocate(0))): binary_base(this->allocate(size), size){} template basic_binary::basic_binary(size_type size, size_type cap) noexcept(noexcept(this->allocate(0))): binary_base(size ? this->allocate(size) : nullptr, size, cap){} template basic_binary::basic_binary(const basic_binary& b) noexcept(noexcept(this->allocate(0))): binary_base(b.m_size ? this->allocate(b.m_size) : nullptr, b.m_size, b.m_size) { if(b.m_size) memcpy(m_data, b.m_data, b.m_size); } template constexpr basic_binary::basic_binary(basic_binary&& b)noexcept: binary_base(exchange(b.m_data, nullptr), b.m_size, b.m_cap){} template basic_binary::basic_binary(const binary_base& b) noexcept(noexcept(this->allocate(0))): binary_base(b.size() ? this->allocate(b.size()) : nullptr, b.size(), b.size()) { if(b.size()) memcpy(m_data, b.get(), b.size()); } template basic_binary::~basic_binary(void) noexcept(noexcept(this->deallocate(nullptr,0))) { this->deallocate(m_data, m_cap); } template basic_binary& basic_binary::operator=(const basic_binary& b) noexcept(noexcept(this->allocate(0))) { return _copy_data(b.get(), b.size()); } template constexpr basic_binary& basic_binary::operator=(basic_binary&& b)noexcept{ m_size = b.m_size; m_cap = b.m_cap; swap(m_data, b.m_data); return *this; } template basic_binary& basic_binary::operator=(const_pointer c) noexcept(noexcept(this->allocate(0))) { return _copy_data(c, strlen(c)); } template basic_binary& basic_binary::operator=(const binary_base& b) noexcept(noexcept(this->allocate(0))) { return _copy_data(b.get(), b.size()); } template void basic_binary::reset(void) noexcept(noexcept(this->deallocate(nullptr,0))) { this->deallocate(m_data, m_cap); m_data = nullptr; m_cap = m_size = 0; } template void basic_binary::reset(pointer val, size_type cap, size_type size) noexcept(noexcept(this->deallocate(nullptr,0))) { this->deallocate(m_data, m_cap); m_data = val; m_cap = cap; m_size = size; } template bool basic_binary::resize(size_type newsize) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))) { if(newsize < m_cap) return false; basic_binary tmp(newsize); if(!tmp) return false; memcpy(STOP_STRICT_ALIAS_WARNING(tmp).m_data, m_data, m_size); swap(m_data, STOP_STRICT_ALIAS_WARNING(tmp).m_data); m_cap = STOP_STRICT_ALIAS_WARNING(tmp).m_cap; return true; } template void basic_binary::append(const_pointer data, size_type len) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))) { if(m_size + len > m_cap) resize(max(m_cap*2, m_size+len)); memcpy(m_data+m_size, data, len); m_size += len; } template basic_binary& basic_binary::_copy_data(const_pointer data, size_type len) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))) { if(!len) return (*this = basic_binary(rexy::steal(nullptr), 0, 0)); if(len <= m_size){ m_size = len; memcpy(m_data, data, len); return *this; } return (*this = basic_binary(data, len)); } constexpr static_binary::static_binary(const_pointer str, size_type len)noexcept: binary_base(const_cast(str), len, len){} constexpr static_binary::static_binary(const_pointer str)noexcept: static_binary(str, strlen(str)){} constexpr static_binary::static_binary(const static_binary& s)noexcept: static_binary(s.get(), s.size()){} constexpr static_binary::static_binary(static_binary&& s)noexcept: static_binary(s.get(), s.size()){} constexpr static_binary& static_binary::operator=(const_pointer str)noexcept{ m_data = const_cast(str); m_size = strlen(str); m_cap = m_size; return *this; } constexpr static_binary& static_binary::operator=(const static_binary& str)noexcept{ m_data = str.m_data; m_size = str.m_size; m_cap = str.m_cap; return *this; } constexpr static_binary& static_binary::operator=(static_binary&& str)noexcept{ m_data = str.m_data; m_size = str.m_size; m_cap = str.m_cap; return *this; } template constexpr auto binary_cat_expr::size(void)const noexcept -> size_type{ return this->m_l.size() + this->m_r.size(); } template template binary_cat_expr::operator basic_binary(void) noexcept(std::is_nothrow_constructible, typename basic_binary::size_type>::value && std::is_nothrow_invocable>,decltype(*this)>::value) { auto sz = size(); basic_binary ret(sz); detail::string_appender> append(ret); append(*this); return ret; } } #undef STOP_STRICT_ALIAS_WARNING #endif