/** 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 Affero 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 Affero General Public License for more details. You should have received a copy of the GNU Affero 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 "cx/utility.hpp" //max #include "detail/default_allocator.hpp" #include "steal.hpp" #include "detail/string_appender.hpp" #include "cx/utility.hpp" //strlen #define STOP_STRICT_ALIAS_WARNING(x) (x) namespace rexy{ constexpr binary_base::binary_base(size_t len)noexcept: m_cap(len){} constexpr binary_base::binary_base(char* data, size_t size)noexcept: m_data(data), m_cap(size){} constexpr binary_base::binary_base(char* data, size_t size, size_t cap)noexcept: m_data(data), m_size(size), m_cap(cap){} constexpr binary_base::binary_base(const binary_base&)noexcept{} constexpr char* binary_base::release(void)noexcept{ return cx::exchange(m_data, nullptr); } constexpr size_t binary_base::size(void)const{ return m_size; } constexpr size_t binary_base::capacity(void)const{ return m_cap; } constexpr char* binary_base::get(void){ return m_data; } constexpr const char* binary_base::get(void)const{ return m_data; } constexpr binary_base::operator bool(void)const{ return m_data; } constexpr char& binary_base::operator[](size_t i)noexcept{ return m_data[i]; } constexpr const char& binary_base::operator[](size_t i)const noexcept{ return m_data[i]; } template constexpr basic_binary::basic_binary(void)noexcept{} template constexpr basic_binary::basic_binary(rexy::steal data)noexcept: binary_base(data.value() ? cx::strlen(data.value()) : 0) { m_data = data.value(); m_size = m_cap; } template constexpr basic_binary::basic_binary(rexy::steal data, size_t size)noexcept: binary_base(data.value(), size){} template constexpr basic_binary::basic_binary(rexy::steal data, size_t cap, size_t size)noexcept: binary_base(data.value(), cap, size){} template basic_binary::basic_binary(const char* data, size_t size) noexcept(noexcept(Allocator::copy(data, size))): binary_base(reinterpret_cast(Allocator::copy(data, size)), size){} template basic_binary::basic_binary(const char* data) noexcept(noexcept(Allocator::copy(data, 0))): basic_binary(data, cx::strlen(data)){} template basic_binary::basic_binary(const char* data, size_t size, size_t cap) noexcept(noexcept(Allocator::copy(data, size))): binary_base(reinterpret_cast(Allocator::copy(data, size)), size, cap){} template basic_binary::basic_binary(size_t size) noexcept(noexcept(Allocator::allocate(size))): binary_base(reinterpret_cast(Allocator::allocate(size)), size){} template basic_binary::basic_binary(size_t size, size_t cap) noexcept(noexcept(Allocator::allocate(size))): binary_base(reinterpret_cast(size ? Allocator::allocate(size) : nullptr), size, cap){} template basic_binary::basic_binary(const basic_binary& b) noexcept(noexcept(Allocator::copy(b.m_data, b.m_cap))): binary_base(reinterpret_cast(b.m_size ? Allocator::copy(b.m_data, b.m_size) : nullptr), b.m_size, b.m_size){} template constexpr basic_binary::basic_binary(basic_binary&& b)noexcept: binary_base(cx::exchange(b.m_data, nullptr), b.m_size, b.m_cap){} template basic_binary::basic_binary(const binary_base& b)noexcept(noexcept(Allocator::copy(b.get(),b.size()))): binary_base(reinterpret_cast(b.size() ? Allocator::copy(b.get(), b.size()) : nullptr), b.size(), b.size()){} template basic_binary::~basic_binary(void) noexcept(noexcept(Allocator::free(m_data))) { Allocator::free(m_data); } template basic_binary& basic_binary::operator=(const basic_binary& b) noexcept(noexcept(Allocator::copy(b.m_data, b.m_size))) { 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; cx::swap(m_data, b.m_data); return *this; } template basic_binary& basic_binary::operator=(const char* c) noexcept(noexcept(Allocator::copy(c, 0))) { return _copy_data(c, strlen(c)); } template basic_binary& basic_binary::operator=(const binary_base& b) noexcept(noexcept(Allocator::copy(b.get(), b.size()))) { return _copy_data(b.get(), b.size()); } template void basic_binary::reset(void) noexcept(noexcept(Allocator::free(m_data))) { Allocator::free(m_data); m_data = nullptr; m_cap = m_size = 0; } template void basic_binary::reset(char* val, size_t cap, size_t size) noexcept(noexcept(Allocator::free(m_data))) { Allocator::free(m_data); m_data = val; m_cap = cap; m_size = size; } template bool basic_binary::resize(size_t newsize) noexcept(noexcept(Allocator::allocate(0)) && noexcept(Allocator::free(nullptr))) { 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); cx::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 char* data, size_t len) noexcept(noexcept(Allocator::allocate(0)) && noexcept(Allocator::free(nullptr))) { if(m_size + len > m_cap) resize(cx::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 char* data, size_t len) noexcept(noexcept(Allocator::copy(nullptr,0)) && noexcept(Allocator::free(nullptr))) { 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 char* str, size_t len)noexcept: binary_base(const_cast(str), len, len){} constexpr static_binary::static_binary(const char* str)noexcept: static_binary(str, cx::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 char* str)noexcept{ m_data = const_cast(str); m_size = cx::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 size_t binary_cat_expr::size(void)const noexcept{ return this->m_l.size() + this->m_r.size(); } template template binary_cat_expr::operator basic_binary(void) noexcept(std::is_nothrow_constructible, size_t>::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