/** This file is a part of rexy's matrix client Copyright (C) 2019 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 RAII_BINARY_HPP #define RAII_BINARY_HPP #include //size_t #include //move #include //memcpy #include //max #include #include #include "raii/default_allocator.hpp" namespace raii{ class binary_base { protected: char* m_data = nullptr; size_t m_size = 0; size_t m_cap = 0; public: protected: constexpr binary_base(void) = default; constexpr binary_base(char* data, size_t size): m_data(data), m_cap(size){} template binary_base(const binary_base& b): m_data(Allocator::copy(b.m_data, b.m_cap)), m_size(b.m_size), m_cap(b.m_cap){} binary_base(binary_base&&); ~binary_base(void) = default; public: char* release(void); constexpr size_t size(void)const{return m_size;} constexpr size_t capacity(void)const{return m_cap;} constexpr char* get(void){return m_data;} constexpr const char* get(void)const{return m_data;} constexpr operator bool(void)const{return m_data;} char& operator[](size_t i); const char& operator[](size_t i)const; }; template> class binary_data : public binary_base { public: using allocator_type = Allocator; public: constexpr binary_data(void) = default; binary_data(char* data, size_t size): binary_base(reinterpret_cast(Allocator::copy(data, size)), size){} binary_data(size_t size): binary_base(reinterpret_cast(Allocator::allocate(size)), size){} binary_data(const binary_data& b): binary_base(b) { m_data = Allocator::copy(b.m_data, b.m_cap); } binary_data(binary_data&& b): binary_base(std::move(b)){} ~binary_data(void){ Allocator::free(m_data); } binary_data& operator=(const binary_data& b){ binary_data tmp(b); return (*this = std::move(tmp)); } binary_data& operator=(binary_data&& b){ m_size = b.m_size; m_cap = b.m_cap; std::swap(m_data, b.m_data); return *this; } void reset(void){ Allocator::free(m_data); m_data = nullptr; m_cap = m_size = 0; } void reset(char* val, size_t cap, size_t size = 0){ Allocator::free(m_data); m_data = val; m_cap = cap; m_size = size; } bool resize(size_t newsize){ if(newsize < m_cap) return false; binary_data tmp(newsize); if(!tmp) return false; memcpy(tmp.m_data, m_data, m_size); std::swap(m_data, tmp.m_data); m_cap = tmp.m_cap; return true; } void append(const char* data, size_t len){ if(m_size + len > m_cap) resize(std::max(m_cap*2, m_size+len)); memcpy(m_data+m_size, data, len); m_size += len; } }; using binary = binary_data<>; namespace detail{ std::true_type is_binary_type_helper(binary_base); std::false_type is_binary_type_helper(...); template struct is_binary_type{ constexpr static bool value = std::is_same::type>())),std::true_type>::value; }; } } template::value && raii::detail::is_binary_type::value,void>::type* = nullptr> bool operator==(Left&& l, Right&& r){ return l && r && l.size() == r.size() && l.capacity() == r.capacity() && !memcmp(l.get(), r.get(), l.size()); } template::value && raii::detail::is_binary_type::value,void>::type* = nullptr> bool operator!=(Left&& l, Right&& r){ return !(std::forward(l) == std::forward(r)); } template auto operator+(const raii::binary_data& l, const raii::binary_data& r){ raii::binary_data retval(l.size() + r.size()); memcpy(retval.get(), l.get(), l.size()); memcpy(retval.get()+l.size(), r.get(), r.size()); return retval; } template decltype(auto) operator+=(raii::binary_data& l, const raii::binary_data& r){ l.resize(l.size() + r.size()); memcpy(l.get()+l.size(), r.get(), r.size()); return l; } #ifdef RAII_STRING_BASE_HPP #include "raii/binary_string_conv.hpp" #endif #endif