Import string_bt from duckhandy
Modified to use std::make_index_sequence instead of the equivalent duckhandy utility.
This commit is contained in:
parent
751667769c
commit
f70899aed1
1 changed files with 128 additions and 0 deletions
128
src/wren/string_bt.hpp
Normal file
128
src/wren/string_bt.hpp
Normal 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
|
Loading…
Reference in a new issue