diff --git a/include/rexy/cx/string.hpp b/include/rexy/cx/string.hpp new file mode 100644 index 0000000..4ea3820 --- /dev/null +++ b/include/rexy/cx/string.hpp @@ -0,0 +1,178 @@ +/** + 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_CX_STRING_HPP +#define REXY_CX_STRING_HPP + +#include "../string_base.hpp" +#include "utility.hpp" + + +//This is different from rexy::static_string in that this doesn't hold a pointer to a constant string array. +//This holds a mutable array of data which can be modified during compile time. static_string is +//designed to be a thin wrapper around a raw char*, this is designed to allow compile time string concatenation + +namespace rexy::cx{ + + template + class string + { + public: + static constexpr size_t max_size = N; + private: + char m_data[N] = {}; + size_t m_length = 0; + + public: + constexpr string(void) = default; + template + constexpr string(const char(&data)[M]): + m_length(M) + { + static_assert(M <= N); + for(size_t i = 0;i < M;++i){ + m_data[i] = data[i]; + } + } + constexpr string(const char* data): + m_length(cx::strlen(data)) + { + for(size_t i = 0;i < m_length;++i){ + m_data[i] = data[i]; + } + } + constexpr string(const char* data, size_t len): + m_length(len) + { + for(size_t i = 0;i < m_length;++i){ + m_data[i] = data[i]; + } + } + + constexpr string(const rexy::static_string& str): + m_length(str.length()) + { + for(size_t i = 0;i < m_length;++i){ + m_data[i] = str[i]; + } + } + template + constexpr string(const rexy::string_cat_expr& expr){ + rexy::detail::string_appender> append(*this); + append(expr); + } + + constexpr string(const string&) = default; + constexpr string(string&&) = default; + ~string(void) = default; + + constexpr string& operator=(const char* c){ + m_length = cx::strlen(c); + for(size_t i = 0;i < m_length;++i){ + m_data[i] = c[i]; + } + return *this; + } + constexpr string& operator=(const string&) = default; + constexpr string& operator=(string&&) = default; + + + constexpr size_t length(void)const{ + return m_length; + } + constexpr size_t capacity(void)const{ + return max_size; + } + constexpr char* get(void){ + return m_data; + } + constexpr const char* get(void)const{ + return m_data; + } + constexpr operator char*(void){ + return m_data; + } + constexpr operator const char*(void)const{ + return m_data; + } + + constexpr bool valid(void)const{ + return m_length > 0; + } + constexpr char& operator[](size_t i){ + return m_data[i]; + } + constexpr const char& operator[](size_t i)const{ + return m_data[i]; + } + + constexpr bool resize(size_t i){ + if(i >= capacity()) + return false; + m_length = i; + m_data[m_length] = 0; + return true; + } + + constexpr void append(const char* data, size_t len){ + for(size_t i = 0;i < len;++i){ + m_data[m_length++] = data[i]; + } + } + constexpr void append(const char* data){ + append(data, cx::strlen(data)); + } + constexpr void append(const string& s){ + append(s.get(), s.length()); + } + constexpr void append(const rexy::static_string& s){ + append(s.get(), s.length()); + } + }; + + namespace detail{ + template + struct is_cx_string_helper{ + static constexpr bool value = false; + }; + template + struct is_cx_string_helper>{ + static constexpr bool value = true; + }; + template + struct is_cx_string{ + static constexpr bool value = (is_cx_string_helper>::value && ...); + }; + } + + template::value,int> = 0> + constexpr auto operator+(Str1&& l, Str2&& r){ + return string_cat_expr(std::forward(l), std::forward(r)); + } + template::value,int> = 0> + constexpr auto operator+(Str1&& l, const char* r){ + return string_cat_expr(std::forward(l), rexy::static_string(r)); + } + template::value,int> = 0> + constexpr auto operator+(const char* l, Str1&& r){ + return string_cat_expr(rexy::static_string(l), std::forward(r)); + } +} + + +#endif diff --git a/include/rexy/cx/string_hash.hpp b/include/rexy/cx/string_hash.hpp index 6c13386..36c43f8 100644 --- a/include/rexy/cx/string_hash.hpp +++ b/include/rexy/cx/string_hash.hpp @@ -20,20 +20,27 @@ #define REXY_CX_STRING_HASH_HPP #include "hash.hpp" -#include "../string_base.hpp" +#include "../string.hpp" +#include "string.hpp" namespace rexy::cx{ - template<> - struct hash{ - constexpr size_t operator()(const rexy::static_string& t, size_t salt = 0){ + template + struct string_hash{ + constexpr size_t operator()(const Str& s, size_t salt = 0){ size_t hash = 5381 + salt; - for(size_t i = 0;i < t.length();++i){ - hash = ((hash << 5) + hash) ^ t[i]; + for(size_t i = 0;i < s.length();++i){ + hash = ((hash << 5) + hash) ^ s[i]; } return hash; } }; + template<> + struct hash : public string_hash{}; + template<> + struct hash : public string_hash{}; + template + struct hash> : public string_hash>{}; }