From a63cf1edb112674bdabf283f14211ec88300649e Mon Sep 17 00:00:00 2001 From: q66 Date: Sat, 19 Mar 2016 19:52:46 +0000 Subject: [PATCH] add experimental api to turn unterminated string ranges to terminated c strings --- ostd/environ.hh | 9 +-------- ostd/string.hh | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/ostd/environ.hh b/ostd/environ.hh index 0493d87..a9b8a08 100644 --- a/ostd/environ.hh +++ b/ostd/environ.hh @@ -17,14 +17,7 @@ namespace environ { inline Maybe get(ConstCharRange name) { char buf[256]; - const char *ret = nullptr; - if (name.size() < sizeof(buf)) { - memcpy(buf, name.data(), name.size()); - buf[name.size()] = '\0'; - ret = getenv(buf); - } else { - ret = getenv(String(name).data()); - } + const char *ret = getenv(to_temp_cstr(name, buf, sizeof(buf)).get()); if (!ret) return ostd::nothing; return ostd::move(ConstCharRange(ret)); } diff --git a/ostd/string.hh b/ostd/string.hh index 28f4662..c6708c5 100644 --- a/ostd/string.hh +++ b/ostd/string.hh @@ -850,6 +850,57 @@ String to_string(std::initializer_list init) { return to_string(iter(init)); } +template +struct TempCString { +private: + T *p_buf; + bool p_allocated; + +public: + TempCString() = delete; + TempCString(const TempCString &) = delete; + TempCString(TempCString &&s): p_buf(s.p_buf), p_allocated(s.p_allocated) { + s.p_buf = nullptr; + s.p_allocated = false; + } + TempCString(CharRangeBase input, char *sbuf, Size bufsize) + : p_buf(nullptr), p_allocated(false) { + if (!input.size()) return; + if (input[input.size() - 1] == '\0') { + p_buf = (T *)input.data(); + return; + } + if (input.size() >= bufsize) { + p_buf = new T[input.size() + 1]; + p_allocated = true; + } else p_buf = sbuf; + memcpy(p_buf, input.data(), input.size()); + p_buf[input.size()] = '\0'; + } + ~TempCString() { + if (p_allocated) delete[] p_buf; + } + + TempCString &operator=(const TempCString &) = delete; + TempCString &operator=(TempCString &&s) { + swap(s); + return *this; + } + + operator const T *() const { return p_buf; } + const T *get() const { return p_buf; } + + void swap(TempCString &s) { + detail::swap_adl(p_buf, s.p_buf); + detail::swap_adl(p_allocated, s.p_allocated); + } +}; + +inline TempCString to_temp_cstr(ConstCharRange input, + char *buf, Size bufsize) { + return TempCString(input, buf, bufsize); +} + } /* namespace ostd */ #endif