From c83d2ce686913d790f986c3e0de9f96ff3fe1848 Mon Sep 17 00:00:00 2001 From: rexy712 Date: Tue, 28 Jul 2020 06:18:20 -0700 Subject: [PATCH] Explicit template instantiation for rexy::string and rexy::binary --- CMakeLists.txt | 4 +- include/rexy/binary.hpp | 184 +--------------- include/rexy/binary_base.hpp | 209 +++++++++++++++++++ include/rexy/{binary.tpp => binary_base.tpp} | 4 +- include/rexy/detail/binary_string_conv.hpp | 39 +--- include/rexy/string.hpp | 5 +- include/rexy/string_base.hpp | 3 + src/binary.cpp | 26 +++ src/ensure.cpp | 3 +- src/string.cpp | 26 +++ 10 files changed, 283 insertions(+), 220 deletions(-) create mode 100644 include/rexy/binary_base.hpp rename include/rexy/{binary.tpp => binary_base.tpp} (99%) create mode 100644 src/binary.cpp create mode 100644 src/string.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a1f6d8..ca7c4f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ option(ENABLE_SHARED "Build shared library" ON) option(ENABLE_PROFILING "Enable asan" OFF) mark_as_advanced(ENABLE_PROFILING) -set(SOURCE_LIST "src/filerd.cpp") +set(SOURCE_LIST "src/filerd.cpp" "src/string.cpp" "src/binary.cpp") add_library(ensure OBJECT "src/ensure.cpp") target_compile_options(ensure PRIVATE -Wall -Wextra -pedantic -std=c++17) if(ENABLE_SHARED) @@ -29,7 +29,7 @@ if(ENABLE_PROFILING) target_link_options(rexy PRIVATE -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls) endif() -set(LIBREXY_PUBLIC_HEADERS "include/rexy/traits.hpp" "include/rexy/steal.hpp" "include/rexy/binary.hpp" "include/rexy/expression.hpp" "include/rexy/binary.tpp" "include/rexy/string_base.hpp" "include/rexy/string.hpp" "include/rexy/filerd.hpp" "include/rexy/string_base.tpp") +set(LIBREXY_PUBLIC_HEADERS "include/rexy/traits.hpp" "include/rexy/steal.hpp" "include/rexy/binary.hpp" "include/rexy/expression.hpp" "include/rexy/binary_base.hpp" "include/rexy/binary_base.tpp" "include/rexy/string_base.hpp" "include/rexy/string.hpp" "include/rexy/filerd.hpp" "include/rexy/string_base.tpp") target_compile_options(rexy PRIVATE -Wall -Wextra -pedantic -std=c++17) install(TARGETS rexy diff --git a/include/rexy/binary.hpp b/include/rexy/binary.hpp index bb0af5b..ea7beaf 100644 --- a/include/rexy/binary.hpp +++ b/include/rexy/binary.hpp @@ -19,193 +19,15 @@ #ifndef REXY_BINARY_HPP #define REXY_BINARY_HPP -#include //size_t -#include //move -#include //memcpy -#include -#include "cx/utility.hpp" //max +#include "binary_base.hpp" #include "detail/default_allocator.hpp" -#include "steal.hpp" -#include "expression.hpp" -#include "traits.hpp" -#include "detail/string_appender.hpp" namespace rexy{ - class binary_base - { - protected: - char* m_data = nullptr; - size_t m_size = 0; - size_t m_cap = 0; - public: - protected: - constexpr binary_base(void)noexcept = default; - constexpr binary_base(size_t len)noexcept; - constexpr binary_base(char* data, size_t size)noexcept; - constexpr binary_base(char* data, size_t size, size_t cap)noexcept; - constexpr binary_base(const binary_base& b)noexcept; - ~binary_base(void)noexcept = default; + using binary = binary_data>; - public: - constexpr char* release(void)noexcept; + extern template class binary_data>; - constexpr size_t size(void)const; - constexpr size_t capacity(void)const; - constexpr char* get(void); - constexpr const char* get(void)const; - constexpr operator bool(void)const; - - constexpr char& operator[](size_t i)noexcept; - constexpr const char& operator[](size_t i)const noexcept; - - }; - template> - class binary_data : public binary_base - { - public: - using allocator_type = Allocator; - public: - constexpr binary_data(void)noexcept; - constexpr binary_data(rexy::steal data, size_t size)noexcept; - constexpr binary_data(rexy::steal data, size_t cap, size_t size)noexcept; - constexpr binary_data(rexy::steal data)noexcept; - binary_data(const char* data, size_t size)noexcept(noexcept(Allocator::copy(data, size))); - binary_data(const char* data)noexcept(noexcept(Allocator::copy(data, 0))); - binary_data(const char* data, size_t size, size_t cap)noexcept(noexcept(Allocator::copy(data, size))); - explicit binary_data(size_t size)noexcept(noexcept(Allocator::allocate(size))); - binary_data(size_t size, size_t cap)noexcept(noexcept(Allocator::allocate(size))); - - binary_data(const binary_data& b)noexcept(noexcept(Allocator::copy(b.m_data, b.m_cap))); - constexpr binary_data(binary_data&& b)noexcept; - binary_data(const binary_base& b)noexcept(noexcept(Allocator::copy(b.get(),b.size()))); - - ~binary_data(void)noexcept(noexcept(Allocator::free(m_data))); - - binary_data& operator=(const binary_data& b)noexcept(noexcept(Allocator::copy(b.m_data, b.m_size))); - constexpr binary_data& operator=(binary_data&& b)noexcept; - binary_data& operator=(const char* c)noexcept(noexcept(Allocator::copy(c, 0))); - binary_data& operator=(const binary_base& b)noexcept(noexcept(Allocator::copy(b.get(), b.size()))); - - void reset(void) - noexcept(noexcept(Allocator::free(m_data))); - void reset(char* val, size_t cap, size_t size = 0) - noexcept(noexcept(Allocator::free(m_data))); - bool resize(size_t newsize) - noexcept(noexcept(Allocator::allocate(0)) && - noexcept(Allocator::free(nullptr))); - void append(const char* data, size_t len) - noexcept(noexcept(Allocator::allocate(0)) && - noexcept(Allocator::free(nullptr))); - private: - binary_data& _copy_data(const char* data, size_t len) - noexcept(noexcept(Allocator::copy(nullptr,0)) && - noexcept(Allocator::free(nullptr))); - }; - using binary = binary_data<>; - - template - class binary_cat_expr : public rexy::binary_expression - { - 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_t size(void)const noexcept; - - template - operator binary_data(void) - noexcept(std::is_nothrow_constructible, size_t>::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 char* str, size_t len)noexcept; - constexpr static_binary(const char* 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 char* 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.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_BASE_HPP -#include "detail/binary_string_conv.hpp" -#endif - #endif diff --git a/include/rexy/binary_base.hpp b/include/rexy/binary_base.hpp new file mode 100644 index 0000000..572eb3c --- /dev/null +++ b/include/rexy/binary_base.hpp @@ -0,0 +1,209 @@ +/** + 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_HPP +#define REXY_BINARY_BASE_HPP + +#include //size_t +#include //move +#include //memcpy +#include +#include "cx/utility.hpp" //max +#include "detail/default_allocator.hpp" +#include "steal.hpp" +#include "expression.hpp" +#include "traits.hpp" +#include "detail/string_appender.hpp" + +namespace rexy{ + + class binary_base + { + protected: + char* m_data = nullptr; + size_t m_size = 0; + size_t m_cap = 0; + public: + protected: + constexpr binary_base(void)noexcept = default; + constexpr binary_base(size_t len)noexcept; + constexpr binary_base(char* data, size_t size)noexcept; + constexpr binary_base(char* data, size_t size, size_t cap)noexcept; + constexpr binary_base(const binary_base& b)noexcept; + ~binary_base(void)noexcept = default; + + public: + constexpr char* release(void)noexcept; + + constexpr size_t size(void)const; + constexpr size_t capacity(void)const; + constexpr char* get(void); + constexpr const char* get(void)const; + constexpr operator bool(void)const; + + constexpr char& operator[](size_t i)noexcept; + constexpr const char& operator[](size_t i)const noexcept; + + }; + template> + class binary_data : public binary_base + { + public: + using allocator_type = Allocator; + public: + constexpr binary_data(void)noexcept; + constexpr binary_data(rexy::steal data, size_t size)noexcept; + constexpr binary_data(rexy::steal data, size_t cap, size_t size)noexcept; + constexpr binary_data(rexy::steal data)noexcept; + binary_data(const char* data, size_t size)noexcept(noexcept(Allocator::copy(data, size))); + binary_data(const char* data)noexcept(noexcept(Allocator::copy(data, 0))); + binary_data(const char* data, size_t size, size_t cap)noexcept(noexcept(Allocator::copy(data, size))); + explicit binary_data(size_t size)noexcept(noexcept(Allocator::allocate(size))); + binary_data(size_t size, size_t cap)noexcept(noexcept(Allocator::allocate(size))); + + binary_data(const binary_data& b)noexcept(noexcept(Allocator::copy(b.m_data, b.m_cap))); + constexpr binary_data(binary_data&& b)noexcept; + binary_data(const binary_base& b)noexcept(noexcept(Allocator::copy(b.get(),b.size()))); + + ~binary_data(void)noexcept(noexcept(Allocator::free(m_data))); + + binary_data& operator=(const binary_data& b)noexcept(noexcept(Allocator::copy(b.m_data, b.m_size))); + constexpr binary_data& operator=(binary_data&& b)noexcept; + binary_data& operator=(const char* c)noexcept(noexcept(Allocator::copy(c, 0))); + binary_data& operator=(const binary_base& b)noexcept(noexcept(Allocator::copy(b.get(), b.size()))); + + void reset(void) + noexcept(noexcept(Allocator::free(m_data))); + void reset(char* val, size_t cap, size_t size = 0) + noexcept(noexcept(Allocator::free(m_data))); + bool resize(size_t newsize) + noexcept(noexcept(Allocator::allocate(0)) && + noexcept(Allocator::free(nullptr))); + void append(const char* data, size_t len) + noexcept(noexcept(Allocator::allocate(0)) && + noexcept(Allocator::free(nullptr))); + private: + binary_data& _copy_data(const char* data, size_t len) + noexcept(noexcept(Allocator::copy(nullptr,0)) && + noexcept(Allocator::free(nullptr))); + }; + + template + class binary_cat_expr : public rexy::binary_expression + { + 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_t size(void)const noexcept; + + template + operator binary_data(void) + noexcept(std::is_nothrow_constructible, size_t>::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 char* str, size_t len)noexcept; + constexpr static_binary(const char* 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 char* 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 diff --git a/include/rexy/binary.tpp b/include/rexy/binary_base.tpp similarity index 99% rename from include/rexy/binary.tpp rename to include/rexy/binary_base.tpp index 2cb8e4d..7d3dc44 100644 --- a/include/rexy/binary.tpp +++ b/include/rexy/binary_base.tpp @@ -16,8 +16,8 @@ along with this program. If not, see . */ -#ifndef REXY_BINARY_TPP -#define REXY_BINARY_TPP +#ifndef REXY_BINARY_BASE_TPP +#define REXY_BINARY_BASE_TPP #include //size_t #include //move diff --git a/include/rexy/detail/binary_string_conv.hpp b/include/rexy/detail/binary_string_conv.hpp index ed61f1d..46404b0 100644 --- a/include/rexy/detail/binary_string_conv.hpp +++ b/include/rexy/detail/binary_string_conv.hpp @@ -19,24 +19,24 @@ #ifndef REXY_BINARY_STRING_CONV_HPP #define REXY_BINARY_STRING_CONV_HPP -#include "rexy/string.hpp" -#include "rexy/binary.hpp" +#include "rexy/string_base.hpp" +#include "rexy/binary_base.hpp" #include //memcpy namespace rexy{ - template = 0> - auto binary_to_string(const binary_data& b) + template = 0> + auto binary_to_string(const binary_base& b) noexcept(std::is_nothrow_constructible::value) { Str s(b.size()+1); s.append(b.get(), b.size()); return s; } - template = 0, std::enable_if_t,typename Str::allocator_type>::value,int> = 0> + template = 0, std::enable_if_t,typename Str::allocator_type>::value,int> = 0> auto binary_to_string(binary_data&& b)noexcept{ return Str(rexy::steal(b.release()), b.size()); } - template = 0> + template = 0> auto string_to_binary(const string_base& s) noexcept(std::is_nothrow_constructible::value && noexcept(std::decay_t::allocator_type::allocate(0))) @@ -45,34 +45,11 @@ namespace rexy{ b.append(s.get(), s.length()+1); return b; } - template = 0, std::enable_if_t,typename Bin::allocator_type>::value,int> = 0> + template = 0, std::enable_if_t,typename Bin::allocator_type>::value,int> = 0> auto string_to_binary(string_intermediary&& s)noexcept{ return Bin(rexy::steal(s.release()), s.length()); } - template = 0, detail::enable_if_concrete_string = 0> - decltype(auto) operator+=(L& l, R&& r) - noexcept(noexcept(std::decay_t::allocator_type::allocate(0)) && - noexcept(std::decay_t::allocator_type::free(nullptr))) - { - l.append(r.get(), r.length()+1); - return l; - } - template = 0, detail::enable_if_string = 0, std::enable_if_t::value,int> = 0> - decltype(auto) operator+=(L& l, R&& r) - noexcept(std::is_nothrow_constructible::value && - (noexcept(std::decay_t::allocator_type::allocate(0)))) - { - rexy::string concrete = r; - return (l += concrete); - } - template = 0, detail::enable_if_binary = 0> - decltype(auto) operator+=(L& l, R&& r) - noexcept(noexcept(std::decay_t::allocator_type::allocate(0)) && - noexcept(std::decay_t::allocator_type::free(nullptr))) - { - l.append(r.get(), r.size()); - return l; - } + } //namespace rexy #endif diff --git a/include/rexy/string.hpp b/include/rexy/string.hpp index 258d253..24239ea 100644 --- a/include/rexy/string.hpp +++ b/include/rexy/string.hpp @@ -27,11 +27,10 @@ namespace rexy{ //new allocated string using string = string_intermediary>; + extern template class string_intermediary>; + } -#ifdef REXY_BINARY_HPP -#include "detail/binary_string_conv.hpp" -#endif #ifdef REXY_CX_HASH_HPP #include "cx/basic_string_hash.hpp" #endif diff --git a/include/rexy/string_base.hpp b/include/rexy/string_base.hpp index 6b044eb..5c13c13 100644 --- a/include/rexy/string_base.hpp +++ b/include/rexy/string_base.hpp @@ -245,6 +245,9 @@ namespace{ } } +#ifdef REXY_BINARY_BASE_HPP +#include "detail/binary_string_conv.hpp" +#endif #ifdef REXY_CX_HASH_HPP #include "cx/static_string_hash.hpp" #endif diff --git a/src/binary.cpp b/src/binary.cpp new file mode 100644 index 0000000..1959e5c --- /dev/null +++ b/src/binary.cpp @@ -0,0 +1,26 @@ +/** + 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 . +*/ + +#include "rexy/binary.hpp" +#include "rexy/detail/default_allocator.hpp" + +namespace rexy{ + + template class binary_data>; + +} diff --git a/src/ensure.cpp b/src/ensure.cpp index fd8a394..7204ec3 100644 --- a/src/ensure.cpp +++ b/src/ensure.cpp @@ -1,7 +1,8 @@ //Never actually used in the project. This just ensures that all syntax is correct during builds. #include "rexy/binary.hpp" -#include "rexy/binary.tpp" +#include "rexy/binary_base.hpp" +#include "rexy/binary_base.tpp" #include "rexy/expression.hpp" #include "rexy/filerd.hpp" #include "rexy/steal.hpp" diff --git a/src/string.cpp b/src/string.cpp new file mode 100644 index 0000000..6f5f3b5 --- /dev/null +++ b/src/string.cpp @@ -0,0 +1,26 @@ +/** + 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 . +*/ + +#include "rexy/string.hpp" +#include "rexy/detail/default_allocator.hpp" + +namespace rexy{ + + template class string_intermediary>; + +}