Add compile time manipulatable strings
This commit is contained in:
parent
c622eb7323
commit
d878589737
178
include/rexy/cx/string.hpp
Normal file
178
include/rexy/cx/string.hpp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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<size_t N>
|
||||
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<size_t M>
|
||||
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<class Left, class Right>
|
||||
constexpr string(const rexy::string_cat_expr<Left,Right>& expr){
|
||||
rexy::detail::string_appender<cx::string<N>> 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<class T>
|
||||
struct is_cx_string_helper{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template<size_t N>
|
||||
struct is_cx_string_helper<cx::string<N>>{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
template<class... Ts>
|
||||
struct is_cx_string{
|
||||
static constexpr bool value = (is_cx_string_helper<std::decay_t<Ts>>::value && ...);
|
||||
};
|
||||
}
|
||||
|
||||
template<class Str1, class Str2, std::enable_if_t<detail::is_cx_string<Str1,Str2>::value,int> = 0>
|
||||
constexpr auto operator+(Str1&& l, Str2&& r){
|
||||
return string_cat_expr(std::forward<Str1>(l), std::forward<Str2>(r));
|
||||
}
|
||||
template<class Str1, std::enable_if_t<detail::is_cx_string<Str1>::value,int> = 0>
|
||||
constexpr auto operator+(Str1&& l, const char* r){
|
||||
return string_cat_expr(std::forward<Str1>(l), rexy::static_string(r));
|
||||
}
|
||||
template<class Str1, std::enable_if_t<detail::is_cx_string<Str1>::value,int> = 0>
|
||||
constexpr auto operator+(const char* l, Str1&& r){
|
||||
return string_cat_expr(rexy::static_string(l), std::forward<Str1>(r));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@ -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<rexy::static_string>{
|
||||
constexpr size_t operator()(const rexy::static_string& t, size_t salt = 0){
|
||||
template<class Str>
|
||||
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<rexy::static_string> : public string_hash<rexy::static_string>{};
|
||||
template<>
|
||||
struct hash<rexy::string> : public string_hash<rexy::string>{};
|
||||
template<size_t N>
|
||||
struct hash<rexy::cx::string<N>> : public string_hash<rexy::cx::string<N>>{};
|
||||
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user