forked from OctaForge/libostd
StringRange -> CharRange
This commit is contained in:
parent
f2082d17cd
commit
7a2f8581d7
|
@ -27,7 +27,7 @@ enum FormatFlags {
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
inline int parse_fmt_flags(ConstStringRange &fmt, int ret) {
|
inline int parse_fmt_flags(ConstCharRange &fmt, int ret) {
|
||||||
while (!fmt.empty()) {
|
while (!fmt.empty()) {
|
||||||
switch (fmt.front()) {
|
switch (fmt.front()) {
|
||||||
case '-': ret |= FMT_FLAG_DASH; fmt.pop_front(); break;
|
case '-': ret |= FMT_FLAG_DASH; fmt.pop_front(); break;
|
||||||
|
@ -42,7 +42,7 @@ namespace detail {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Size read_digits(ConstStringRange &fmt, char *buf) {
|
inline Size read_digits(ConstCharRange &fmt, char *buf) {
|
||||||
Size ret = 0;
|
Size ret = 0;
|
||||||
for (; !fmt.empty() && isdigit(fmt.front()); ++ret) {
|
for (; !fmt.empty() && isdigit(fmt.front()); ++ret) {
|
||||||
*buf++ = fmt.front();
|
*buf++ = fmt.front();
|
||||||
|
@ -143,7 +143,7 @@ namespace detail {
|
||||||
|
|
||||||
struct FormatSpec {
|
struct FormatSpec {
|
||||||
FormatSpec(): p_nested_escape(false), p_fmt() {}
|
FormatSpec(): p_nested_escape(false), p_fmt() {}
|
||||||
FormatSpec(ConstStringRange fmt, bool escape = false):
|
FormatSpec(ConstCharRange fmt, bool escape = false):
|
||||||
p_nested_escape(escape), p_fmt(fmt) {}
|
p_nested_escape(escape), p_fmt(fmt) {}
|
||||||
|
|
||||||
template<typename R>
|
template<typename R>
|
||||||
|
@ -177,7 +177,7 @@ struct FormatSpec {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstStringRange rest() const {
|
ConstCharRange rest() const {
|
||||||
return p_fmt;
|
return p_fmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,15 +218,15 @@ struct FormatSpec {
|
||||||
|
|
||||||
byte index() const { return p_index; }
|
byte index() const { return p_index; }
|
||||||
|
|
||||||
ConstStringRange nested() const { return p_nested; }
|
ConstCharRange nested() const { return p_nested; }
|
||||||
ConstStringRange nested_sep() const { return p_nested_sep; }
|
ConstCharRange nested_sep() const { return p_nested_sep; }
|
||||||
|
|
||||||
bool is_nested() const { return p_is_nested; }
|
bool is_nested() const { return p_is_nested; }
|
||||||
bool nested_escape() const { return p_nested_escape; }
|
bool nested_escape() const { return p_nested_escape; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ConstStringRange p_nested;
|
ConstCharRange p_nested;
|
||||||
ConstStringRange p_nested_sep;
|
ConstCharRange p_nested_sep;
|
||||||
|
|
||||||
int p_flags = 0;
|
int p_flags = 0;
|
||||||
|
|
||||||
|
@ -263,21 +263,21 @@ protected:
|
||||||
int sflags = p_flags;
|
int sflags = p_flags;
|
||||||
p_nested_escape = !(sflags & FMT_FLAG_DASH);
|
p_nested_escape = !(sflags & FMT_FLAG_DASH);
|
||||||
p_fmt.pop_front();
|
p_fmt.pop_front();
|
||||||
ConstStringRange begin_inner(p_fmt);
|
ConstCharRange begin_inner(p_fmt);
|
||||||
if (!read_until_dummy()) {
|
if (!read_until_dummy()) {
|
||||||
p_is_nested = false;
|
p_is_nested = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* skip to the last spec in case multiple specs are present */
|
/* skip to the last spec in case multiple specs are present */
|
||||||
ConstStringRange curfmt(p_fmt);
|
ConstCharRange curfmt(p_fmt);
|
||||||
while (read_until_dummy()) {
|
while (read_until_dummy()) {
|
||||||
curfmt = p_fmt;
|
curfmt = p_fmt;
|
||||||
}
|
}
|
||||||
p_fmt = curfmt;
|
p_fmt = curfmt;
|
||||||
p_flags = sflags;
|
p_flags = sflags;
|
||||||
/* find delimiter or ending */
|
/* find delimiter or ending */
|
||||||
ConstStringRange begin_delim(p_fmt);
|
ConstCharRange begin_delim(p_fmt);
|
||||||
ConstStringRange p = find(begin_delim, '%');
|
ConstCharRange p = find(begin_delim, '%');
|
||||||
for (; !p.empty(); p = find(p, '%')) {
|
for (; !p.empty(); p = find(p, '%')) {
|
||||||
p.pop_front();
|
p.pop_front();
|
||||||
/* escape, skip */
|
/* escape, skip */
|
||||||
|
@ -391,7 +391,7 @@ protected:
|
||||||
return (sp >= 65) && (detail::fmt_specs[sp - 65] != 0);
|
return (sp >= 65) && (detail::fmt_specs[sp - 65] != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstStringRange p_fmt;
|
ConstCharRange p_fmt;
|
||||||
char p_buf[32];
|
char p_buf[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -458,7 +458,7 @@ namespace detail {
|
||||||
|
|
||||||
template<typename R, typename ...A>
|
template<typename R, typename ...A>
|
||||||
static Ptrdiff format_impl(R &writer, Size &fmtn, bool escape,
|
static Ptrdiff format_impl(R &writer, Size &fmtn, bool escape,
|
||||||
ConstStringRange fmt, const A &...args);
|
ConstCharRange fmt, const A &...args);
|
||||||
|
|
||||||
template<typename T, typename = RangeOf<T>>
|
template<typename T, typename = RangeOf<T>>
|
||||||
static True test_fmt_range(int);
|
static True test_fmt_range(int);
|
||||||
|
@ -472,7 +472,7 @@ namespace detail {
|
||||||
struct FmtTupleUnpacker {
|
struct FmtTupleUnpacker {
|
||||||
template<typename R, typename T, typename ...A>
|
template<typename R, typename T, typename ...A>
|
||||||
static inline Ptrdiff unpack(R &writer, Size &fmtn, bool esc,
|
static inline Ptrdiff unpack(R &writer, Size &fmtn, bool esc,
|
||||||
ConstStringRange fmt, const T &item,
|
ConstCharRange fmt, const T &item,
|
||||||
const A &...args) {
|
const A &...args) {
|
||||||
return FmtTupleUnpacker<I - 1>::unpack(writer, fmtn, esc, fmt,
|
return FmtTupleUnpacker<I - 1>::unpack(writer, fmtn, esc, fmt,
|
||||||
item, get<I - 1>(item), args...);
|
item, get<I - 1>(item), args...);
|
||||||
|
@ -483,7 +483,7 @@ namespace detail {
|
||||||
struct FmtTupleUnpacker<0> {
|
struct FmtTupleUnpacker<0> {
|
||||||
template<typename R, typename T, typename ...A>
|
template<typename R, typename T, typename ...A>
|
||||||
static inline Ptrdiff unpack(R &writer, Size &fmtn, bool esc,
|
static inline Ptrdiff unpack(R &writer, Size &fmtn, bool esc,
|
||||||
ConstStringRange fmt, const T &,
|
ConstCharRange fmt, const T &,
|
||||||
const A &...args) {
|
const A &...args) {
|
||||||
return format_impl(writer, fmtn, esc, fmt, args...);
|
return format_impl(writer, fmtn, esc, fmt, args...);
|
||||||
}
|
}
|
||||||
|
@ -491,7 +491,7 @@ namespace detail {
|
||||||
|
|
||||||
template<typename R, typename T>
|
template<typename R, typename T>
|
||||||
inline Ptrdiff format_ritem(R &writer, Size &fmtn, bool esc, bool,
|
inline Ptrdiff format_ritem(R &writer, Size &fmtn, bool esc, bool,
|
||||||
ConstStringRange fmt, const T &item,
|
ConstCharRange fmt, const T &item,
|
||||||
EnableIf<!IsTupleLike<T>::value, bool>
|
EnableIf<!IsTupleLike<T>::value, bool>
|
||||||
= true) {
|
= true) {
|
||||||
return format_impl(writer, fmtn, esc, fmt, item);
|
return format_impl(writer, fmtn, esc, fmt, item);
|
||||||
|
@ -499,7 +499,7 @@ namespace detail {
|
||||||
|
|
||||||
template<typename R, typename T>
|
template<typename R, typename T>
|
||||||
inline Ptrdiff format_ritem(R &writer, Size &fmtn, bool esc,
|
inline Ptrdiff format_ritem(R &writer, Size &fmtn, bool esc,
|
||||||
bool expandval, ConstStringRange fmt,
|
bool expandval, ConstCharRange fmt,
|
||||||
const T &item,
|
const T &item,
|
||||||
EnableIf<IsTupleLike<T>::value, bool>
|
EnableIf<IsTupleLike<T>::value, bool>
|
||||||
= true) {
|
= true) {
|
||||||
|
@ -513,7 +513,7 @@ namespace detail {
|
||||||
template<typename R, typename T>
|
template<typename R, typename T>
|
||||||
inline Ptrdiff write_range(R &writer, const FormatSpec *fl,
|
inline Ptrdiff write_range(R &writer, const FormatSpec *fl,
|
||||||
bool escape, bool expandval,
|
bool escape, bool expandval,
|
||||||
ConstStringRange sep,
|
ConstCharRange sep,
|
||||||
const T &val,
|
const T &val,
|
||||||
EnableIf<FmtRangeTest<T>::value, bool>
|
EnableIf<FmtRangeTest<T>::value, bool>
|
||||||
= true) {
|
= true) {
|
||||||
|
@ -543,7 +543,7 @@ namespace detail {
|
||||||
|
|
||||||
template<typename R, typename T>
|
template<typename R, typename T>
|
||||||
inline Ptrdiff write_range(R &, const FormatSpec *, bool, bool,
|
inline Ptrdiff write_range(R &, const FormatSpec *, bool, bool,
|
||||||
ConstStringRange, const T &,
|
ConstCharRange, const T &,
|
||||||
EnableIf<!FmtRangeTest<T>::value, bool>
|
EnableIf<!FmtRangeTest<T>::value, bool>
|
||||||
= true) {
|
= true) {
|
||||||
assert(false && "invalid value for ranged format");
|
assert(false && "invalid value for ranged format");
|
||||||
|
@ -627,7 +627,7 @@ namespace detail {
|
||||||
|
|
||||||
struct WriteSpec: FormatSpec {
|
struct WriteSpec: FormatSpec {
|
||||||
WriteSpec(): FormatSpec() {}
|
WriteSpec(): FormatSpec() {}
|
||||||
WriteSpec(ConstStringRange fmt, bool esc): FormatSpec(fmt, esc) {}
|
WriteSpec(ConstCharRange fmt, bool esc): FormatSpec(fmt, esc) {}
|
||||||
|
|
||||||
/* C string */
|
/* C string */
|
||||||
template<typename R>
|
template<typename R>
|
||||||
|
@ -817,7 +817,7 @@ namespace detail {
|
||||||
/* range writer */
|
/* range writer */
|
||||||
template<typename R, typename T>
|
template<typename R, typename T>
|
||||||
Ptrdiff write_range(R &writer, Size idx, bool expandval,
|
Ptrdiff write_range(R &writer, Size idx, bool expandval,
|
||||||
ConstStringRange sep, const T &val) {
|
ConstCharRange sep, const T &val) {
|
||||||
if (idx) {
|
if (idx) {
|
||||||
assert(false && "not enough format args");
|
assert(false && "not enough format args");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -828,7 +828,7 @@ namespace detail {
|
||||||
|
|
||||||
template<typename R, typename T, typename ...A>
|
template<typename R, typename T, typename ...A>
|
||||||
Ptrdiff write_range(R &writer, Size idx, bool expandval,
|
Ptrdiff write_range(R &writer, Size idx, bool expandval,
|
||||||
ConstStringRange sep, const T &val,
|
ConstCharRange sep, const T &val,
|
||||||
const A &...args) {
|
const A &...args) {
|
||||||
if (idx) {
|
if (idx) {
|
||||||
return write_range(writer, idx - 1, expandval, sep, args...);
|
return write_range(writer, idx - 1, expandval, sep, args...);
|
||||||
|
@ -840,7 +840,7 @@ namespace detail {
|
||||||
|
|
||||||
template<typename R, typename ...A>
|
template<typename R, typename ...A>
|
||||||
inline Ptrdiff format_impl(R &writer, Size &fmtn, bool escape,
|
inline Ptrdiff format_impl(R &writer, Size &fmtn, bool escape,
|
||||||
ConstStringRange fmt, const A &...args) {
|
ConstCharRange fmt, const A &...args) {
|
||||||
Size argidx = 1, retn = 0, twr = 0;
|
Size argidx = 1, retn = 0, twr = 0;
|
||||||
Ptrdiff written = 0;
|
Ptrdiff written = 0;
|
||||||
detail::WriteSpec spec(fmt, escape);
|
detail::WriteSpec spec(fmt, escape);
|
||||||
|
@ -900,7 +900,7 @@ namespace detail {
|
||||||
|
|
||||||
template<typename R, typename ...A>
|
template<typename R, typename ...A>
|
||||||
inline Ptrdiff format_impl(R &writer, Size &fmtn, bool,
|
inline Ptrdiff format_impl(R &writer, Size &fmtn, bool,
|
||||||
ConstStringRange fmt) {
|
ConstCharRange fmt) {
|
||||||
Size written = 0;
|
Size written = 0;
|
||||||
detail::WriteSpec spec(fmt, false);
|
detail::WriteSpec spec(fmt, false);
|
||||||
if (spec.read_until_spec(writer, &written)) return -1;
|
if (spec.read_until_spec(writer, &written)) return -1;
|
||||||
|
@ -910,13 +910,13 @@ namespace detail {
|
||||||
} /* namespace detail */
|
} /* namespace detail */
|
||||||
|
|
||||||
template<typename R, typename ...A>
|
template<typename R, typename ...A>
|
||||||
inline Ptrdiff format(R &&writer, Size &fmtn, ConstStringRange fmt,
|
inline Ptrdiff format(R &&writer, Size &fmtn, ConstCharRange fmt,
|
||||||
const A &...args) {
|
const A &...args) {
|
||||||
return detail::format_impl(writer, fmtn, false, fmt, args...);
|
return detail::format_impl(writer, fmtn, false, fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename R, typename ...A>
|
template<typename R, typename ...A>
|
||||||
Ptrdiff format(R &&writer, ConstStringRange fmt, const A &...args) {
|
Ptrdiff format(R &&writer, ConstCharRange fmt, const A &...args) {
|
||||||
Size fmtn = 0;
|
Size fmtn = 0;
|
||||||
return format(writer, fmtn, fmt, args...);
|
return format(writer, fmtn, fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,50 +21,50 @@ static constexpr Size npos = -1;
|
||||||
template<typename T, typename A = Allocator<T>> class StringBase;
|
template<typename T, typename A = Allocator<T>> class StringBase;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct StringRangeBase: InputRange<
|
struct CharRangeBase: InputRange<
|
||||||
StringRangeBase<T>, FiniteRandomAccessRangeTag, T
|
CharRangeBase<T>, FiniteRandomAccessRangeTag, T
|
||||||
> {
|
> {
|
||||||
private:
|
private:
|
||||||
struct Nat {};
|
struct Nat {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StringRangeBase(): p_beg(nullptr), p_end(nullptr) {};
|
CharRangeBase(): p_beg(nullptr), p_end(nullptr) {};
|
||||||
StringRangeBase(T *beg, T *end): p_beg(beg), p_end(end) {}
|
CharRangeBase(T *beg, T *end): p_beg(beg), p_end(end) {}
|
||||||
StringRangeBase(T *beg, Size n): p_beg(beg), p_end(beg + n) {}
|
CharRangeBase(T *beg, Size n): p_beg(beg), p_end(beg + n) {}
|
||||||
|
|
||||||
/* TODO: traits for utf-16/utf-32 string lengths, for now assume char */
|
/* TODO: traits for utf-16/utf-32 string lengths, for now assume char */
|
||||||
template<typename U>
|
template<typename U>
|
||||||
StringRangeBase(U beg, EnableIf<
|
CharRangeBase(U beg, EnableIf<
|
||||||
IsConvertible<U, T *>::value && !IsArray<U>::value, Nat
|
IsConvertible<U, T *>::value && !IsArray<U>::value, Nat
|
||||||
> = Nat()): p_beg(beg), p_end((T *)beg + strlen(beg)) {}
|
> = Nat()): p_beg(beg), p_end((T *)beg + strlen(beg)) {}
|
||||||
|
|
||||||
template<typename U, Size N>
|
template<typename U, Size N>
|
||||||
StringRangeBase(U (&beg)[N], EnableIf<
|
CharRangeBase(U (&beg)[N], EnableIf<
|
||||||
IsConvertible<U *, T *>::value, Nat
|
IsConvertible<U *, T *>::value, Nat
|
||||||
> = Nat()): p_beg(beg),
|
> = Nat()): p_beg(beg),
|
||||||
p_end(beg + N - (beg[N - 1] == '\0')) {}
|
p_end(beg + N - (beg[N - 1] == '\0')) {}
|
||||||
|
|
||||||
template<typename U, typename A>
|
template<typename U, typename A>
|
||||||
StringRangeBase(const StringBase<U, A> &s, EnableIf<
|
CharRangeBase(const StringBase<U, A> &s, EnableIf<
|
||||||
IsConvertible<U *, T *>::value, Nat
|
IsConvertible<U *, T *>::value, Nat
|
||||||
> = Nat()): p_beg(s.data()),
|
> = Nat()): p_beg(s.data()),
|
||||||
p_end(s.data() + s.size()) {}
|
p_end(s.data() + s.size()) {}
|
||||||
|
|
||||||
template<typename U, typename = EnableIf<
|
template<typename U, typename = EnableIf<
|
||||||
IsConvertible<U *, T *>::value
|
IsConvertible<U *, T *>::value
|
||||||
>> StringRangeBase(const StringRangeBase<U> &v):
|
>> CharRangeBase(const CharRangeBase<U> &v):
|
||||||
p_beg(&v[0]), p_end(&v[v.size()]) {}
|
p_beg(&v[0]), p_end(&v[v.size()]) {}
|
||||||
|
|
||||||
StringRangeBase &operator=(const StringRangeBase &v) {
|
CharRangeBase &operator=(const CharRangeBase &v) {
|
||||||
p_beg = v.p_beg; p_end = v.p_end; return *this;
|
p_beg = v.p_beg; p_end = v.p_end; return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename A>
|
template<typename A>
|
||||||
StringRangeBase &operator=(const StringBase<T, A> &s) {
|
CharRangeBase &operator=(const StringBase<T, A> &s) {
|
||||||
p_beg = s.data(); p_end = s.data() + s.size(); return *this;
|
p_beg = s.data(); p_end = s.data() + s.size(); return *this;
|
||||||
}
|
}
|
||||||
/* TODO: traits for utf-16/utf-32 string lengths, for now assume char */
|
/* TODO: traits for utf-16/utf-32 string lengths, for now assume char */
|
||||||
StringRangeBase &operator=(T *s) {
|
CharRangeBase &operator=(T *s) {
|
||||||
p_beg = s; p_end = s + strlen(s); return *this;
|
p_beg = s; p_end = s + strlen(s); return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,11 +91,11 @@ public:
|
||||||
|
|
||||||
T &front() const { return *p_beg; }
|
T &front() const { return *p_beg; }
|
||||||
|
|
||||||
bool equals_front(const StringRangeBase &range) const {
|
bool equals_front(const CharRangeBase &range) const {
|
||||||
return p_beg == range.p_beg;
|
return p_beg == range.p_beg;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptrdiff distance_front(const StringRangeBase &range) const {
|
Ptrdiff distance_front(const CharRangeBase &range) const {
|
||||||
return range.p_beg - p_beg;
|
return range.p_beg - p_beg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,18 +120,18 @@ public:
|
||||||
|
|
||||||
T &back() const { return *(p_end - 1); }
|
T &back() const { return *(p_end - 1); }
|
||||||
|
|
||||||
bool equals_back(const StringRangeBase &range) const {
|
bool equals_back(const CharRangeBase &range) const {
|
||||||
return p_end == range.p_end;
|
return p_end == range.p_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptrdiff distance_back(const StringRangeBase &range) const {
|
Ptrdiff distance_back(const CharRangeBase &range) const {
|
||||||
return range.p_end - p_end;
|
return range.p_end - p_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
Size size() const { return p_end - p_beg; }
|
Size size() const { return p_end - p_beg; }
|
||||||
|
|
||||||
StringRangeBase slice(Size start, Size end) const {
|
CharRangeBase slice(Size start, Size end) const {
|
||||||
return StringRangeBase(p_beg + start, p_beg + end);
|
return CharRangeBase(p_beg + start, p_beg + end);
|
||||||
}
|
}
|
||||||
|
|
||||||
T &operator[](Size i) const { return p_beg[i]; }
|
T &operator[](Size i) const { return p_beg[i]; }
|
||||||
|
@ -199,8 +199,8 @@ public:
|
||||||
using ConstReference = const T &;
|
using ConstReference = const T &;
|
||||||
using Pointer = AllocatorPointer<A>;
|
using Pointer = AllocatorPointer<A>;
|
||||||
using ConstPointer = AllocatorConstPointer<A>;
|
using ConstPointer = AllocatorConstPointer<A>;
|
||||||
using Range = StringRangeBase<T>;
|
using Range = CharRangeBase<T>;
|
||||||
using ConstRange = StringRangeBase<const T>;
|
using ConstRange = CharRangeBase<const T>;
|
||||||
using Allocator = A;
|
using Allocator = A;
|
||||||
|
|
||||||
StringBase(const A &a = A()): p_len(0), p_cap(0),
|
StringBase(const A &a = A()): p_len(0), p_cap(0),
|
||||||
|
@ -515,8 +515,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
using String = StringBase<char>;
|
using String = StringBase<char>;
|
||||||
using StringRange = StringRangeBase<char>;
|
using CharRange = CharRangeBase<char>;
|
||||||
using ConstStringRange = StringRangeBase<const char>;
|
using ConstCharRange = CharRangeBase<const char>;
|
||||||
|
|
||||||
template<typename A> using AnyString = StringBase<char, A>;
|
template<typename A> using AnyString = StringBase<char, A>;
|
||||||
|
|
||||||
|
@ -819,16 +819,16 @@ template<> struct ToString<String> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct ToString<StringRange> {
|
template<> struct ToString<CharRange> {
|
||||||
using Argument = StringRange;
|
using Argument = CharRange;
|
||||||
using Result = String;
|
using Result = String;
|
||||||
String operator()(const Argument &s) {
|
String operator()(const Argument &s) {
|
||||||
return String(s);
|
return String(s);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct ToString<ConstStringRange> {
|
template<> struct ToString<ConstCharRange> {
|
||||||
using Argument = ConstStringRange;
|
using Argument = ConstCharRange;
|
||||||
using Result = String;
|
using Result = String;
|
||||||
String operator()(const Argument &s) {
|
String operator()(const Argument &s) {
|
||||||
return String(s);
|
return String(s);
|
||||||
|
|
Loading…
Reference in a new issue