From e1dbd98c40ecee7867b087ea84e429cca6b7fc1f Mon Sep 17 00:00:00 2001 From: Michael Carlberg Date: Fri, 13 Jan 2017 11:09:56 +0100 Subject: [PATCH] feat(string_util): Custom stringstream --- include/common.hpp | 1 - include/utils/string.hpp | 51 ++++++++++++++++++++++++++++++- src/adapters/net.cpp | 4 +-- src/utils/http.cpp | 4 +-- src/utils/string.cpp | 16 ++-------- src/x11/connection.cpp | 2 +- tests/unit_tests/utils/string.cpp | 23 +++++++++----- 7 files changed, 73 insertions(+), 28 deletions(-) diff --git a/include/common.hpp b/include/common.hpp index 1a4c0c6e..65a7faa6 100644 --- a/include/common.hpp +++ b/include/common.hpp @@ -23,7 +23,6 @@ POLYBAR_NS using std::string; -using std::stringstream; using std::size_t; using std::move; using std::forward; diff --git a/include/utils/string.hpp b/include/utils/string.hpp index ffecf688..df56611c 100644 --- a/include/utils/string.hpp +++ b/include/utils/string.hpp @@ -1,11 +1,61 @@ #pragma once #include +#include #include "common.hpp" POLYBAR_NS +namespace { + /** + * Overload that allows sub-string removal at the end of given string + */ + inline string& operator-(string& a, const string& b) { + if (a.size() >= b.size() && a.substr(a.size() - b.size()) == b) { + return a.erase(a.size() - b.size()); + } else { + return a; + } + } + + /** + * Overload that allows sub-string removal at the end of given string + */ + inline void operator-=(string& a, const string& b) { + if (a.size() >= b.size() && a.substr(a.size() - b.size()) == b) { + a.erase(a.size() - b.size()); + } + } +} + +class stringstream { + public: + stringstream() : m_stream() {} + + template + stringstream& operator<<(const T& object) { + m_stream << object; + return *this; + } + + stringstream& operator<<(const char* cz) { + m_stream << cz; + return *this; + } + + operator string() const { + return m_stream.str(); + } + + const string to_string() const { + return m_stream.str(); + } + + private: + std::stringstream m_stream; +}; + namespace string_util { /** * Hash type @@ -42,7 +92,6 @@ namespace string_util { string filesize_gb(unsigned long long kbytes, size_t precision = 0, const string& locale = ""); string filesize(unsigned long long bytes, size_t precision = 0, bool fixed = false, const string& locale = ""); - string from_stream(const std::basic_ostream& os); hash_type hash(const string& src); } diff --git a/src/adapters/net.cpp b/src/adapters/net.cpp index cd24c591..992e0579 100644 --- a/src/adapters/net.cpp +++ b/src/adapters/net.cpp @@ -193,8 +193,8 @@ namespace net { suffixes.pop_back(); } - return string_util::from_stream(stringstream() << std::setw(minwidth) << std::setfill(' ') << std::setprecision(0) - << std::fixed << speedrate << " " << suffix << "/s"); + return stringstream() << std::setw(minwidth) << std::setfill(' ') << std::setprecision(0) << std::fixed << speedrate + << " " << suffix << "/s"; } // }}} diff --git a/src/utils/http.cpp b/src/utils/http.cpp index 2bd3fe95..365dd3be 100644 --- a/src/utils/http.cpp +++ b/src/utils/http.cpp @@ -24,7 +24,7 @@ http_downloader::~http_downloader() { } string http_downloader::get(const string& url) { - stringstream out{}; + std::stringstream out{}; curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &out); @@ -44,7 +44,7 @@ long http_downloader::response_code() { size_t http_downloader::write(void* p, size_t size, size_t bytes, void* stream) { string data{static_cast(p), size * bytes}; - *(static_cast(stream)) << data << '\n'; + *(static_cast(stream)) << data << '\n'; return size * bytes; } diff --git a/src/utils/string.cpp b/src/utils/string.cpp index 29827e24..14ad7220 100644 --- a/src/utils/string.cpp +++ b/src/utils/string.cpp @@ -161,7 +161,7 @@ namespace string_util { */ vector& split_into(const string& s, char delim, vector& container) { string str; - stringstream buffer(s); + std::stringstream buffer(s); while (getline(buffer, str, delim)) { container.emplace_back(str); } @@ -191,7 +191,7 @@ namespace string_util { * Create a floating point string */ string floating_point(double value, size_t precision, bool fixed, const string& locale) { - stringstream ss; + std::stringstream ss; ss.imbue(!locale.empty() ? std::locale(locale.c_str()) : std::locale::classic()); ss << std::fixed << std::setprecision(precision) << value; return fixed ? ss.str() : replace(ss.str(), ".00", ""); @@ -225,18 +225,6 @@ namespace string_util { return floating_point(value, precision, fixed, locale) + " GB"; } - /** - * Get the resulting string from a ostream/ - * - * Example usage: - * @code cpp - * string_util::from_stream(stringstream() << ...); - * @endcode - */ - string from_stream(const std::basic_ostream& os) { - return dynamic_cast(os).str(); - } - /** * Compute string hash */ diff --git a/src/x11/connection.cpp b/src/x11/connection.cpp index 383153e9..e75328b7 100644 --- a/src/x11/connection.cpp +++ b/src/x11/connection.cpp @@ -107,7 +107,7 @@ Visual* connection::visual(uint8_t depth) { * Create X window id string */ string connection::id(xcb_window_t w) const { - return string_util::from_stream(std::stringstream() << "0x" << std::hex << std::setw(7) << std::setfill('0') << w); + return stringstream() << "0x" << std::hex << std::setw(7) << std::setfill('0') << w; } /** diff --git a/tests/unit_tests/utils/string.cpp b/tests/unit_tests/utils/string.cpp index aebd4ce7..2e13b2c8 100644 --- a/tests/unit_tests/utils/string.cpp +++ b/tests/unit_tests/utils/string.cpp @@ -72,13 +72,6 @@ int main() { expect(string_util::find_nth("foobarfoobar", 0, "o", 3) == size_t{7}); }; - "from_stream"_test = [] { - auto result = - string_util::from_stream(std::stringstream() << std::setw(6) << std::setfill('z') << "foo" - << "bar"); - expect(result == "zzzfoobar"); - }; - "hash"_test = [] { unsigned long hashA1{string_util::hash("foo")}; unsigned long hashA2{string_util::hash("foo")}; @@ -106,4 +99,20 @@ int main() { expect(string_util::filesize_gb(3 * 1024 * 1024 + 800 * 1024) == "4 GB"); expect(string_util::filesize(3 * 1024 * 1024) == "3 GB"); }; + + "stringstream"_test = [] { + string s; + expect((s = (stringstream() << "test")) == "test"s); + expect((s = (stringstream() << std::setprecision(2) << std::fixed << 1.25)).erase(0, 2) == "25"s); + }; + + "operators"_test = [] { + string foo = "foobar"; + expect(foo - "bar" == "foo"); + string baz = "bazbaz"; + expect(baz - "ba" == "bazbaz"); + expect(baz - "bazbz" == "bazbaz"); + string aaa = "aaa"; + expect(aaa - "aaaaa" == "aaa"); + }; }