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>{};
}