diff --git a/examples/format.cc b/examples/format.cc index 204e57a..dbd359e 100644 --- a/examples/format.cc +++ b/examples/format.cc @@ -52,7 +52,7 @@ int main() { return range(v + 1); })); - Map m = { + Map m = { { "foo", 5 }, { "bar", 10 }, { "baz", 15 } @@ -81,7 +81,7 @@ int main() { writefln("%i", Bar{}); /* format into string */ - auto s = appender(); + auto s = appender(); format(s, "hello %s", "world"); writeln(s.get()); } diff --git a/examples/range.cc b/examples/range.cc index 9860958..8bca8d2 100644 --- a/examples/range.cc +++ b/examples/range.cc @@ -26,7 +26,7 @@ int main() { /* prints ABCDEF (ASCII 65, 66, 67, 68, 69, 70) */ writeln("string gen test"); - String s(map(range(6), [](int v) -> char { return v + 65; })); + auto s = make_string(map(range(6), [](int v) -> char { return v + 65; })); writeln(s); /* join a few ranges together - prints 11, 22, 33 ... 99 each on new line */ diff --git a/examples/range_pipe.cc b/examples/range_pipe.cc index e37d4fa..34b4481 100644 --- a/examples/range_pipe.cc +++ b/examples/range_pipe.cc @@ -23,7 +23,7 @@ int main() { /* prints ABCDEF (ASCII 65, 66, 67, 68, 69, 70) */ writeln("string gen test"); - String s(range(6) | map([](int v) -> char { return v + 65; })); + auto s = make_string(range(6) | map([](int v) -> char { return v + 65; })); writeln(s); /* join a few ranges together - prints 11, 22, 33 ... 99 each on new line */ @@ -76,7 +76,7 @@ int main() { | filter([](auto v) { return v >= 65 && v <= 90; }) | map ([](auto v) { return char(v); }); - writeln(String(r)); + writeln(make_string(r)); /* "list comprehensions" */ writeln("list initialization"); diff --git a/examples/stream2.cc b/examples/stream2.cc index 3661b08..c7e2a0c 100644 --- a/examples/stream2.cc +++ b/examples/stream2.cc @@ -9,7 +9,7 @@ int main() { FileStream wtest{"test.txt", StreamMode::write}; - String smpl = + std::string smpl = "This is a test file for later read.\n" "It contains some sample text in order to see whether " "things actually read correctly.\n\n\n" @@ -24,14 +24,14 @@ int main() { writeln("## WHOLE FILE READ ##\n"); - String ts1{test.iter()}; + auto ts1 = make_string(test.iter()); writefln("-- str beg --\n%s-- str end --", ts1); test.seek(0); writeln("\n## PART FILE READ ##\n"); - String ts2{test.iter().take(25)}; + auto ts2 = make_string(test.iter().take(25)); writefln("-- str beg --\n%s\n-- str end --", ts2); return 0; diff --git a/ostd/environ.hh b/ostd/environ.hh index 7b18ff2..e65c131 100644 --- a/ostd/environ.hh +++ b/ostd/environ.hh @@ -12,6 +12,8 @@ #include #include +#include + #include "ostd/maybe.hh" #include "ostd/string.hh" @@ -19,7 +21,7 @@ namespace ostd { -inline Maybe env_get(ConstCharRange name) { +inline Maybe env_get(ConstCharRange name) { char buf[256]; auto tbuf = to_temp_cstr(name, buf, sizeof(buf)); #ifndef OSTD_PLATFORM_WIN32 @@ -27,23 +29,21 @@ inline Maybe env_get(ConstCharRange name) { if (!ret) { return ostd::nothing; } - return std::move(String(ret)); + return std::string{ret}; #else - String rbuf; + std::vector rbuf; + DWORD sz; for (;;) { - auto ret = GetEnvironmentVariable( - tbuf.get(), rbuf.data(), rbuf.capacity() + 1 - ); - if (!ret) { + sz = GetEnvironmentVariable(tbuf.get(), rbuf.data(), rbuf.capacity()); + if (!sz) { return ostd::nothing; } - if (ret <= rbuf.capacity()) { - rbuf.advance(ret); + if (sz < rbuf.capacity()) { break; } - rbuf.reserve(ret - 1); + rbuf.reserve(sz); } - return std::move(rbuf); + return std::string{rbuf.data(), sz}; #endif } @@ -86,9 +86,9 @@ inline bool env_unset(ConstCharRange name) { #endif } #ifndef OSTD_PLATFORM_WIN32 - return !unsetenv(String(name).data()); + return !unsetenv(std::string{name}.data()); #else - return !!SetEnvironmentVariable(String(name).data(), nullptr); + return !!SetEnvironmentVariable(std::string{name}.data(), nullptr); #endif } diff --git a/ostd/filesystem.hh b/ostd/filesystem.hh index afb9eb6..fee3845 100644 --- a/ostd/filesystem.hh +++ b/ostd/filesystem.hh @@ -69,7 +69,7 @@ struct FileInfo { p_path(std::move(i.p_path)), p_atime(i.p_atime), p_mtime(i.p_mtime), p_ctime(i.p_ctime) { - i.p_slash = i.p_dot = npos; + i.p_slash = i.p_dot = std::string::npos; i.p_type = FileType::unknown; i.p_atime = i.p_ctime = i.p_mtime = 0; } @@ -94,23 +94,23 @@ struct FileInfo { return *this; } - ConstCharRange path() const { return p_path.iter(); } + ConstCharRange path() const { return ostd::iter(p_path); } ConstCharRange filename() const { return path().slice( - (p_slash == npos) ? 0 : (p_slash + 1), p_path.size() + (p_slash == std::string::npos) ? 0 : (p_slash + 1), p_path.size() ); } ConstCharRange stem() const { return path().slice( - (p_slash == npos) ? 0 : (p_slash + 1), - (p_dot == npos) ? p_path.size() : p_dot + (p_slash == std::string::npos) ? 0 : (p_slash + 1), + (p_dot == std::string::npos) ? p_path.size() : p_dot ); } ConstCharRange extension() const { - return (p_dot == npos) + return (p_dot == std::string::npos) ? ConstCharRange() : path().slice(p_dot, p_path.size()); } @@ -118,8 +118,8 @@ struct FileInfo { FileType type() const { return p_type; } void normalize() { - path_normalize(p_path.iter()); - init_from_str(p_path.iter()); + path_normalize(ostd::iter(p_path)); + init_from_str(ostd::iter(p_path)); } time_t atime() const { return p_atime; } @@ -150,24 +150,24 @@ private: if (lstat(p_path.data(), &st) < 0) #endif { - p_slash = p_dot = npos; + p_slash = p_dot = std::string::npos; p_type = FileType::unknown; p_path.clear(); p_atime = p_mtime = p_ctime = 0; return; } - ConstCharRange r = p_path.iter(); + ConstCharRange r = p_path; ConstCharRange found = find_last(r, PathSeparator); if (found.empty()) { - p_slash = npos; + p_slash = std::string::npos; } else { p_slash = r.distance_front(found); } found = find(filename(), '.'); if (found.empty()) { - p_dot = npos; + p_dot = std::string::npos; } else { p_dot = r.distance_front(found); } @@ -215,9 +215,9 @@ private: #endif } - Size p_slash = npos, p_dot = npos; + Size p_slash = std::string::npos, p_dot = std::string::npos; FileType p_type = FileType::unknown; - String p_path; + std::string p_path; time_t p_atime = 0, p_mtime = 0, p_ctime = 0; }; @@ -353,7 +353,7 @@ private: if (!p_de) { return FileInfo(); } - String ap = p_path; + std::string ap = p_path; ap += PathSeparator; ap += static_cast(p_de->d_name); return FileInfo(ap); @@ -361,7 +361,7 @@ private: DIR *p_d; struct dirent *p_de; - String p_path; + std::string p_path; }; #else /* OSTD_PLATFORM_WIN32 */ @@ -514,7 +514,7 @@ private: if (empty()) { return FileInfo(); } - String ap = p_path; + std::string ap = p_path; ap += PathSeparator; ap += static_cast(p_data.cFileName); return FileInfo(ap); @@ -522,7 +522,7 @@ private: HANDLE p_handle; WIN32_FIND_DATA p_data; - String p_path; + std::string p_path; }; #endif /* OSTD_PLATFORM_WIN32 */ @@ -570,7 +570,7 @@ namespace detail { template struct PathJoin { template - static void join(String &s, T const &a, A const &...b) { + static void join(std::string &s, T const &a, A const &...b) { s += a; s += PathSeparator; PathJoin::join(s, b...); @@ -580,7 +580,7 @@ namespace detail { template<> struct PathJoin<1> { template - static void join(String &s, T const &a) { + static void join(std::string &s, T const &a) { s += a; } }; @@ -588,9 +588,9 @@ namespace detail { template inline FileInfo path_join(A const &...args) { - String path; + std::string path; detail::PathJoin::join(path, args...); - path_normalize(path.iter()); + path_normalize(ostd::iter(path)); return FileInfo(path); } diff --git a/ostd/format.hh b/ostd/format.hh index 446b534..b2f5fb5 100644 --- a/ostd/format.hh +++ b/ostd/format.hh @@ -644,19 +644,19 @@ namespace detail { return nullptr; } - inline String escape_fmt_str(ConstCharRange val) { - String ret; - ret.push('"'); + inline std::string escape_fmt_str(ConstCharRange val) { + std::string ret; + ret.push_back('"'); while (!val.empty()) { char const *esc = escape_fmt_char(val.front(), '"'); if (esc) { ret.append(esc); } else { - ret.push(val.front()); + ret.push_back(val.front()); } val.pop_front(); } - ret.push('"'); + ret.push_back('"'); return ret; } diff --git a/ostd/io.hh b/ostd/io.hh index 03ed168..94cc35a 100644 --- a/ostd/io.hh +++ b/ostd/io.hh @@ -163,7 +163,7 @@ namespace detail { !IsConstructible, IoNat > = IoNat() ) { - write(ostd::to_string(v)); + write_impl(ostd::to_string(v)); } } diff --git a/ostd/range.hh b/ostd/range.hh index 987e4b3..31f2530 100644 --- a/ostd/range.hh +++ b/ostd/range.hh @@ -1693,8 +1693,8 @@ public: }; template -struct AppenderRange: OutputRange, typename T::Value, - typename T::Reference, typename T::Size, typename T::Difference> { +struct AppenderRange: OutputRange, typename T::value_type, + typename T::reference, typename T::size_type, typename T::difference_type> { AppenderRange(): p_data() {} AppenderRange(T const &v): p_data(v) {} AppenderRange(T &&v): p_data(std::move(v)) {} @@ -1723,19 +1723,19 @@ struct AppenderRange: OutputRange, typename T::Value, void clear() { p_data.clear(); } - void reserve(typename T::Size cap) { p_data.reserve(cap); } - void resize(typename T::Size len) { p_data.resize(len); } + void reserve(typename T::size_type cap) { p_data.reserve(cap); } + void resize(typename T::size_type len) { p_data.resize(len); } - typename T::Size size() const { return p_data.size(); } - typename T::Size capacity() const { return p_data.capacity(); } + typename T::size_type size() const { return p_data.size(); } + typename T::size_type capacity() const { return p_data.capacity(); } - bool put(typename T::ConstReference v) { - p_data.push(v); + bool put(typename T::const_reference v) { + p_data.push_back(v); return true; } - bool put(typename T::Value &&v) { - p_data.push(std::move(v)); + bool put(typename T::value_type &&v) { + p_data.push_back(std::move(v)); return true; } diff --git a/ostd/string.hh b/ostd/string.hh index a6ff989..e93685d 100644 --- a/ostd/string.hh +++ b/ostd/string.hh @@ -1,4 +1,4 @@ -/* String for OctaSTD. +/* String utilities for OctaSTD. * * This file is part of OctaSTD. See COPYING.md for futher information. */ @@ -21,10 +21,6 @@ #include "ostd/algorithm.hh" namespace ostd { -static constexpr Size npos = -1; - -template> -class StringBase; template struct CharRangeBase: InputRange< @@ -56,8 +52,8 @@ public: p_beg(beg), p_end(beg + N - (beg[N - 1] == '\0')) {} - template - CharRangeBase(StringBase const &s, EnableIf< + template + CharRangeBase(std::basic_string const &s, EnableIf< IsConvertible, Nat > = Nat()): p_beg(s.data()), p_end(s.data() + s.size()) @@ -72,8 +68,8 @@ public: p_beg = v.p_beg; p_end = v.p_end; return *this; } - template - CharRangeBase &operator=(StringBase const &s) { + template + CharRangeBase &operator=(std::basic_string const &s) { 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 */ @@ -268,439 +264,26 @@ struct ranged_traits const> { } }; -template -class StringBase { - using StrPair = detail::CompressedPair, A>; - - ostd::Size p_len, p_cap; - StrPair p_buf; - - template - void ctor_from_range(R &range, EnableIf< - IsFiniteRandomAccessRange && IsSame>>, bool - > = true) { - if (range.empty()) { - return; - } - RangeSize l = range.size(); - reserve(l); - p_len = l; - range.copy(p_buf.first(), l); - p_buf.first()[l] = '\0'; +template +inline std::basic_string make_string(R range) { + /* TODO: specialize for contiguous ranges and matching value types */ + std::basic_string ret; + for (; !range.empty(); range.pop_front()) { + ret.push_back(range.front()); } - - template - void ctor_from_range(R &range, EnableIf< - !IsFiniteRandomAccessRange || !IsSame>>, - bool - > = true) { - if (range.empty()) { - return; - } - Size i = 0; - for (; !range.empty(); range.pop_front()) { - reserve(i + 1); - allocator_construct( - p_buf.second(), &p_buf.first()[i], - range.front() - ); - ++i; - p_len = i; - } - p_buf.first()[p_len] = '\0'; - } - -public: - using Size = ostd::Size; - using Difference = Ptrdiff; - using Value = T; - using Reference = T &; - using ConstReference = T const &; - using Pointer = AllocatorPointer; - using ConstPointer = AllocatorConstPointer; - using Range = CharRangeBase; - using ConstRange = CharRangeBase; - using Allocator = A; - - StringBase(A const &a = A()): - p_len(0), p_cap(0), - p_buf(reinterpret_cast(&p_len), a) - {} - - explicit StringBase(Size n, T val = T(), A const &al = A()): - StringBase(al) - { - if (!n) { - return; - } - p_buf.first() = allocator_allocate(p_buf.second(), n + 1); - p_len = p_cap = n; - Pointer cur = p_buf.first(), last = p_buf.first() + n; - while (cur != last) { - *cur++ = val; - } - *cur = '\0'; - } - - StringBase(StringBase const &s): - p_len(0), p_cap(0), p_buf(reinterpret_cast(&p_len), - allocator_container_copy(s.p_buf.second())) - { - if (!s.p_len) { - return; - } - reserve(s.p_len); - p_len = s.p_len; - memcpy(p_buf.first(), s.p_buf.first(), (p_len + 1) * sizeof(T)); - } - StringBase(StringBase const &s, A const &a): - p_len(0), p_cap(0), p_buf(reinterpret_cast(&p_len), a) - { - if (!s.p_len) { - return; - } - reserve(s.p_len); - p_len = s.p_len; - memcpy(p_buf.first(), s.p_buf.first(), (p_len + 1) * sizeof(T)); - } - StringBase(StringBase &&s): - p_len(s.p_len), p_cap(s.p_cap), - p_buf(s.p_buf.first(), std::move(s.p_buf.second())) - { - s.p_len = s.p_cap = 0; - s.p_buf.first() = reinterpret_cast(&s.p_len); - } - StringBase(StringBase &&s, A const &a): - p_len(0), p_cap(0), p_buf(reinterpret_cast(&p_len), a) - { - if (!s.p_len) { - return; - } - if (a != s.p_buf.second()) { - reserve(s.p_cap); - p_len = s.p_len; - memcpy(p_buf.first(), s.p_buf.first(), (p_len + 1) * sizeof(T)); - return; - } - p_buf.first() = s.p_buf.first(); - p_len = s.p_len; - p_cap = s.p_cap; - s.p_len = s.p_cap = 0; - s.p_buf.first() = &s.p_cap; - } - - StringBase( - StringBase const &s, Size pos, Size len = npos, A const &a = A() - ): StringBase(a) { - Size end = (len == npos) ? s.size() : (pos + len); - Size nch = (end - pos); - reserve(nch); - memcpy(p_buf.first(), s.p_buf.first() + pos, nch); - p_len += nch; - p_buf.first()[p_len] = '\0'; - } - - /* TODO: traits for utf-16/utf-32 string lengths, for now assume char */ - StringBase(ConstRange v, A const &a = A()): StringBase(a) { - if (!v.size()) { - return; - } - reserve(v.size()); - memcpy(p_buf.first(), &v[0], v.size()); - p_buf.first()[v.size()] = '\0'; - p_len = v.size(); - } - - template - StringBase(U v, EnableIf< - IsConvertible && !IsArray, A - > const &a = A()): StringBase(ConstRange(v), a) {} - - template - StringBase(U (&v)[N], EnableIf< - IsConvertible, A - > const &a = A()): StringBase(ConstRange(v), a) {} - - template && IsConvertible, Value> - >> - StringBase(R range, A const &a = A()): StringBase(a) { - ctor_from_range(range); - } - - ~StringBase() { - if (!p_cap) { - return; - } - allocator_deallocate(p_buf.second(), p_buf.first(), p_cap + 1); - } - - void clear() { - if (!p_len) { - return; - } - p_len = 0; - *p_buf.first() = '\0'; - } - - StringBase &operator=(StringBase const &v) { - if (this == &v) { - return *this; - } - clear(); - if (AllocatorPropagateOnContainerCopyAssignment) { - if ((p_buf.second() != v.p_buf.second()) && p_cap) { - allocator_deallocate(p_buf.second(), p_buf.first(), p_cap); - p_cap = 0; - p_buf.first() = reinterpret_cast(&p_len); - } - p_buf.second() = v.p_buf.second(); - } - reserve(v.p_cap); - p_len = v.p_len; - if (p_len) { - memcpy(p_buf.first(), v.p_buf.first(), p_len); - p_buf.first()[p_len] = '\0'; - } else { - p_buf.first() = reinterpret_cast(&p_len); - } - return *this; - } - - StringBase &operator=(StringBase &&v) { - clear(); - if (p_cap) { - allocator_deallocate(p_buf.second(), p_buf.first(), p_cap); - } - if (AllocatorPropagateOnContainerMoveAssignment) { - p_buf.second() = v.p_buf.second(); - } - p_len = v.p_len; - p_cap = v.p_cap; - p_buf.~StrPair(); - new (&p_buf) StrPair(v.release(), std::move(v.p_buf.second())); - if (!p_cap) { - p_buf.first() = reinterpret_cast(&p_len); - } - return *this; - } - - StringBase &operator=(ConstRange v) { - reserve(v.size()); - if (v.size()) { - memcpy(p_buf.first(), &v[0], v.size()); - } - p_buf.first()[v.size()] = '\0'; - p_len = v.size(); - return *this; - } - - template - EnableIf< - IsConvertible && !IsArray, StringBase & - > operator=(U v) { - return operator=(ConstRange(v)); - } - - template - EnableIf< - IsConvertible, StringBase & - > operator=(U (&v)[N]) { - return operator=(ConstRange(v)); - } - - template && IsConvertible, Value> - >> StringBase &operator=(R const &r) { - clear(); - ctor_from_range(r); - return *this; - } - - void resize(Size n, T v = T()) { - if (!n) { - clear(); - return; - } - Size l = p_len; - reserve(n); - p_len = n; - for (Size i = l; i < p_len; ++i) { - p_buf.first()[i] = T(v); - } - p_buf.first()[l] = '\0'; - } - - void reserve(Size n) { - if (n <= p_cap) { - return; - } - Size oc = p_cap; - if (!oc) { - p_cap = max(n, Size(8)); - } else { - while (p_cap < n) p_cap *= 2; - } - Pointer tmp = allocator_allocate(p_buf.second(), p_cap + 1); - if (oc > 0) { - memcpy(tmp, p_buf.first(), (p_len + 1) * sizeof(T)); - allocator_deallocate(p_buf.second(), p_buf.first(), oc + 1); - } - tmp[p_len] = '\0'; - p_buf.first() = tmp; - } - - T &operator[](Size i) { return p_buf.first()[i]; } - T const &operator[](Size i) const { return p_buf.first()[i]; } - - T &at(Size i) { return p_buf.first()[i]; } - T const &at(Size i) const { return p_buf.first()[i]; } - - T &front() { return p_buf.first()[0]; } - T const &front() const { return p_buf.first()[0]; }; - - T &back() { return p_buf.first()[size() - 1]; } - T const &back() const { return p_buf.first()[size() - 1]; } - - Value *data() { return p_buf.first(); } - Value const *data() const { return p_buf.first(); } - - Size size() const { - return p_len; - } - - Size capacity() const { - return p_cap; - } - - void advance(Size s) { p_len += s; } - - Size length() const { - /* TODO: unicode */ - return size(); - } - - bool empty() const { return (size() == 0); } - - Value *release() { - Pointer r = p_buf.first(); - p_buf.first() = nullptr; - p_len = p_cap = 0; - return reinterpret_cast(r); - } - - void push(T v) { - reserve(p_len + 1); - p_buf.first()[p_len++] = v; - p_buf.first()[p_len] = '\0'; - } - - StringBase &append(ConstRange r) { - if (!r.size()) { - return *this; - } - reserve(p_len + r.size()); - memcpy(p_buf.first() + p_len, &r[0], r.size()); - p_len += r.size(); - p_buf.first()[p_len] = '\0'; - return *this; - } - - StringBase &append(Size n, T c) { - if (!n) { - return *this; - } - reserve(p_len + n); - for (Size i = 0; i < n; ++i) { - p_buf.first()[p_len + i] = c; - } - p_len += n; - p_buf.first()[p_len] = '\0'; - return *this; - } - - template && IsConvertible, Value> && - !IsConvertible - >> StringBase &append(R range) { - Size nadd = 0; - for (; !range.empty(); range.pop_front()) { - reserve(p_len + nadd + 1); - p_buf.first()[p_len + nadd++] = range.front(); - } - p_len += nadd; - p_buf.first()[p_len] = '\0'; - return *this; - } - - StringBase &operator+=(ConstRange r) { - return append(r); - } - StringBase &operator+=(T c) { - return append(1, c); - } - template - StringBase &operator+=(R const &v) { - return append(v); - } - - int compare(ConstRange r) const { - return iter().compare(r); - } - - int case_compare(ConstRange r) const { - return iter().case_compare(r); - } - - Range iter() { - return Range(p_buf.first(), size()); - } - ConstRange iter() const { - return ConstRange(p_buf.first(), size()); - } - ConstRange citer() const { - return ConstRange(p_buf.dfirst(), size()); - } - - Range iter_cap() { - return Range(p_buf.first(), capacity()); - } - - void swap(StringBase &v) { - using std::swap; - swap(p_len, v.p_len); - swap(p_cap, v.p_cap); - swap(p_buf.first(), v.p_buf.first()); - if (AllocatorPropagateOnContainerSwap) { - swap(p_buf.second(), v.p_buf.second()); - } - } - - Size to_hash() const { - return iter().to_hash(); - } - - A get_allocator() const { - return p_buf.second(); - } -}; - -template -inline void swap(StringBase &a, StringBase &b) { - a.swap(b); + return ret; } -using String = StringBase; +template +inline std::basic_string>> make_string(R range) { + return make_string>>(std::move(range)); +} /* string literals */ inline namespace literals { inline namespace string_literals { - inline String operator "" _s(char const *str, Size len) { - return String(ConstCharRange(str, len)); - } - - inline ConstCharRange operator "" _S(char const *str, Size len) { + inline ConstCharRange operator "" _sr(char const *str, Size len) { return ConstCharRange(str, len); } } @@ -807,7 +390,7 @@ namespace detail { template static auto test_stringify(int) -> - BoolConstant().stringify()), String>>; + BoolConstant().stringify()), std::string>>; template static True test_stringify(decltype(std::declval().to_string @@ -834,11 +417,11 @@ struct ToString; template struct ToString>> { using Argument = RemoveCv>; - using Result = String; + using Result = std::string; - String operator()(T const &v) const { - String ret("{"); - auto x = appender(); + std::string operator()(T const &v) const { + std::string ret("{"); + auto x = appender(); if (concat(x, ostd::iter(v), ", ", ToString< RemoveConst @@ -853,44 +436,26 @@ struct ToString>> { template struct ToString>> + detail::StringifyTest>> >> { using Argument = RemoveCv>; - using Result = String; + using Result = std::string; - String operator()(T const &v) const { - auto app = appender(); - detail::TostrRange> sink(app); + std::string operator()(T const &v) const { + auto app = appender(); + detail::TostrRange> sink(app); if (!v.to_string(sink)) { - return String(); + return std::string{}; } return std::move(app.get()); } }; -namespace detail { - template - void str_printf(String &s, char const *fmt, T v) { - char buf[256]; - int n = snprintf(buf, sizeof(buf), fmt, v); - s.clear(); - s.reserve(n); - if (n >= int(sizeof(buf))) { - snprintf(s.data(), n + 1, fmt, v); - } else if (n > 0) { - memcpy(s.data(), buf, n + 1); - } else { - s.clear(); - } - *reinterpret_cast(&s) = n; - } -} - template<> struct ToString { using Argument = bool; - using Result = String; - String operator()(bool b) { + using Result = std::string; + std::string operator()(bool b) { return b ? "true" : "false"; } }; @@ -898,77 +463,66 @@ struct ToString { template<> struct ToString { using Argument = char; - using Result = String; - String operator()(char c) { - String ret; - ret.push(c); + using Result = std::string; + std::string operator()(char c) { + std::string ret; + ret += c; return ret; } }; -#define OSTD_TOSTR_NUM(T, fmt) \ +#define OSTD_TOSTR_NUM(T) \ template<> \ struct ToString { \ using Argument = T; \ - using Result = String; \ - String operator()(T v) { \ - String ret; \ - detail::str_printf(ret, fmt, v); \ - return ret; \ + using Result = std::string; \ + std::string operator()(T v) { \ + return std::to_string(v); \ } \ }; -OSTD_TOSTR_NUM(sbyte, "%hhd") -OSTD_TOSTR_NUM(short, "%hd") -OSTD_TOSTR_NUM(int, "%d") -OSTD_TOSTR_NUM(long, "%ld") -OSTD_TOSTR_NUM(float, "%f") -OSTD_TOSTR_NUM(double, "%f") +OSTD_TOSTR_NUM(sbyte) +OSTD_TOSTR_NUM(short) +OSTD_TOSTR_NUM(int) +OSTD_TOSTR_NUM(long) +OSTD_TOSTR_NUM(float) +OSTD_TOSTR_NUM(double) -OSTD_TOSTR_NUM(byte, "%hhu") -OSTD_TOSTR_NUM(ushort, "%hu") -OSTD_TOSTR_NUM(uint, "%u") -OSTD_TOSTR_NUM(ulong, "%lu") -OSTD_TOSTR_NUM(llong, "%lld") -OSTD_TOSTR_NUM(ullong, "%llu") -OSTD_TOSTR_NUM(ldouble, "%Lf") +OSTD_TOSTR_NUM(byte) +OSTD_TOSTR_NUM(ushort) +OSTD_TOSTR_NUM(uint) +OSTD_TOSTR_NUM(ulong) +OSTD_TOSTR_NUM(llong) +OSTD_TOSTR_NUM(ullong) +OSTD_TOSTR_NUM(ldouble) #undef OSTD_TOSTR_NUM template struct ToString { using Argument = T *; - using Result = String; - String operator()(Argument v) { - String ret; - detail::str_printf(ret, "%p", v); - return ret; + using Result = std::string; + std::string operator()(Argument v) { + char buf[16]; + sprintf(buf, "%p", v); + return buf; } }; template<> struct ToString { using Argument = char const *; - using Result = String; - String operator()(char const *s) { - return String(s); + using Result = std::string; + std::string operator()(char const *s) { + return s; } }; template<> struct ToString { using Argument = char *; - using Result = String; - String operator()(char *s) { - return String(s); - } -}; - -template<> -struct ToString { - using Argument = String; - using Result = String; - String operator()(Argument const &s) { + using Result = std::string; + std::string operator()(char *s) { return s; } }; @@ -976,36 +530,36 @@ struct ToString { template<> struct ToString { using Argument = std::string; - using Result = String; - String operator()(Argument const &s) { - return iter(s); + using Result = std::string; + std::string operator()(Argument const &s) { + return s; } }; template<> struct ToString { using Argument = CharRange; - using Result = String; - String operator()(Argument const &s) { - return String(s); + using Result = std::string; + std::string operator()(Argument const &s) { + return std::string{s}; } }; template<> struct ToString { using Argument = ConstCharRange; - using Result = String; - String operator()(Argument const &s) { - return String(s); + using Result = std::string; + std::string operator()(Argument const &s) { + return std::string{s}; } }; template struct ToString> { using Argument = std::pair; - using Result = String; - String operator()(Argument const &v) { - String ret("{"); + using Result = std::string; + std::string operator()(Argument const &v) { + std::string ret{"{"}; ret += ToString>>()(v.first); ret += ", "; ret += ToString>>()(v.second); @@ -1018,7 +572,7 @@ namespace detail { template struct TupleToString { template - static void append(String &ret, T const &tup) { + static void append(std::string &ret, T const &tup) { ret += ", "; ret += ToString(tup)) @@ -1030,13 +584,13 @@ namespace detail { template struct TupleToString { template - static void append(String &, T const &) {} + static void append(std::string &, T const &) {} }; template struct TupleToString<0, N> { template - static void append(String &ret, T const &tup) { + static void append(std::string &ret, T const &tup) { ret += ToString(tup)) >>>()(std::get<0>(tup)); @@ -1048,9 +602,9 @@ namespace detail { template struct ToString> { using Argument = std::tuple; - using Result = String; - String operator()(Argument const &v) { - String ret("{"); + using Result = std::string; + std::string operator()(Argument const &v) { + std::string ret("{"); detail::TupleToString<0, sizeof...(T)>::append(ret, v); ret += "}"; return ret; @@ -1063,36 +617,10 @@ typename ToString::Result to_string(T const &v) { } template -String to_string(std::initializer_list init) { +std::string to_string(std::initializer_list init) { return to_string(iter(init)); } -/* TODO: rvalue ref versions for rhs when we have efficient prepend */ - -inline String operator+(String const &lhs, ConstCharRange rhs) { - String ret(lhs); ret += rhs; return ret; -} - -inline String operator+(ConstCharRange lhs, String const &rhs) { - String ret(lhs); ret += rhs; return ret; -} - -inline String operator+(String const &lhs, char rhs) { - String ret(lhs); ret += rhs; return ret; -} - -inline String operator+(char lhs, String const &rhs) { - String ret(lhs); ret += rhs; return ret; -} - -inline String operator+(String &&lhs, ConstCharRange rhs) { - String ret(std::move(lhs)); ret += rhs; return ret; -} - -inline String operator+(String &&lhs, char rhs) { - String ret(std::move(lhs)); ret += rhs; return ret; -} - template struct TempCString { private: @@ -1153,6 +681,17 @@ inline TempCString to_temp_cstr( return TempCString(input, buf, bufsize); } +/* temporary */ +template<> +struct ToHash { + using Argument = std::string; + using Result = size_t; + + size_t operator()(std::string const &v) const { + return std::hash{}(v); + } +}; + } /* namespace ostd */ namespace std {