Import string_bt from duckhandy

Modified to use std::make_index_sequence instead of the
equivalent duckhandy utility.
This commit is contained in:
King_DuckZ 2020-04-30 20:47:22 +02:00
parent 751667769c
commit f70899aed1

128
src/wren/string_bt.hpp Normal file
View file

@ -0,0 +1,128 @@
/* Copyright 2016-2018 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef id170B0E6C34D14EBA9B92A35977BDBFB3
#define id170B0E6C34D14EBA9B92A35977BDBFB3
#include <utility>
#include <cstddef>
#include <iostream>
#include <stdexcept>
namespace dhandy {
namespace bt {
template <std::size_t S, typename Ch=char>
class string;
template <std::size_t S, typename Ch>
std::basic_ostream<Ch>& operator<< ( std::basic_ostream<Ch>& parStream, const string<S, Ch>& parString );
namespace implem {
template <std::size_t S, typename Ch> constexpr bool eq (const string<S, Ch>& l, const string<S, Ch>& r);
} //namespace implem
template <std::size_t S, typename Ch>
class string {
friend std::ostream& operator<< <>( std::ostream& parStream, const string<S>& parString );
friend constexpr bool implem::eq<S, Ch> (const string<S, Ch>&, const string<S, Ch>&);
public:
using value_type = Ch;
constexpr string ( const value_type* parString );
constexpr std::size_t size ( void ) const { return S - 1; }
template <std::size_t S2>
constexpr string<S + S2 - 1, Ch> operator+ ( const string<S2, Ch>& parOther ) const;
constexpr value_type operator[] ( std::size_t parIndex ) const;
constexpr bool operator== (const string<S, Ch>& other) const;
template <std::size_t S2> constexpr bool operator== (const string<S2, Ch>&) const { return false; }
template <typename... Args>
constexpr string ( Args... );
constexpr const value_type (&data_arr() const)[S] { return m_data; }
constexpr const value_type* data() const { return m_data; }
private:
template <std::size_t... I>
constexpr string ( std::index_sequence<I...>, const value_type* parString );
const value_type m_data[S];
};
namespace implem {
template <std::size_t S, std::size_t S2, std::size_t... I>
constexpr string<S + S2 - 1> concat ( std::index_sequence<I...>, const string<S>& parLeft, const string<S2>& parRight ) {
return string<S + S2 - 1>(
(I < S - 1 ? parLeft[I] : (I < S + S2 - 2 ? parRight[I - (S - 1)] : '\0'))...
);
}
template <> constexpr inline bool eq (const string<1>& l, const string<1>& r) { return l[0] == r[0]; }
template <std::size_t S, typename Ch>
constexpr inline bool eq (const string<S, Ch>& l, const string<S, Ch>& r) { return l[0] == r[0] and eq(string<S-1>(l.m_data+1), string<S-1>(r.m_data+1)); }
} //namespace implem
template <std::size_t S, typename Ch>
template <std::size_t... I>
constexpr string<S, Ch>::string (std::index_sequence<I...>, const value_type* parString) :
m_data{parString[I]...}
{
}
template <std::size_t S, typename Ch>
inline constexpr string<S, Ch>::string (const value_type* parString) :
string(std::make_index_sequence<S>(), parString)
{
}
template <std::size_t S, typename Ch>
template <typename... Args>
inline constexpr string<S, Ch>::string (Args... parArgs) :
m_data{parArgs...}
{
}
template <std::size_t S, typename Ch>
template <std::size_t S2>
constexpr inline string<S + S2 - 1, Ch> string<S, Ch>::operator+ (const string<S2, Ch>& parOther) const {
return implem::concat(std::make_index_sequence<S + S2 - 1>(), string<S>(m_data), parOther);
}
template <std::size_t S, typename Ch>
inline std::ostream& operator<< (std::ostream& parStream, const string<S, Ch>& parString) {
parStream << parString.m_data;
return parStream;
}
template <std::size_t S, typename Ch>
constexpr auto string<S, Ch>::operator[] (std::size_t parIndex) const -> value_type {
return (parIndex < S ? m_data[parIndex] : throw std::out_of_range(""));
}
template <std::size_t S, typename Ch>
constexpr string<S, Ch> make_string (const Ch (&parData)[S]) {
return string<S>(parData);
}
template <std::size_t S, typename Ch>
constexpr bool string<S, Ch>::operator== (const string<S, Ch>& other) const {
return implem::eq(*this, other);
}
} //namespace bt
} //namespace dhandy
#endif