aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/string.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/string.hpp')
-rw-r--r--src/string.hpp154
1 files changed, 154 insertions, 0 deletions
diff --git a/src/string.hpp b/src/string.hpp
new file mode 100644
index 0000000..3621ca6
--- /dev/null
+++ b/src/string.hpp
@@ -0,0 +1,154 @@
+#pragma once
+
+#include <cctype>
+#include <cstddef>
+
+#include <algorithm>
+#include <locale>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+namespace string
+{
+ template <typename Char>
+ inline void ltrim(std::basic_string<Char>& s)
+ {
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), [] (const Char& c)
+ {
+ return !std::isspace(c);
+ }));
+ }
+
+ template <typename Char>
+ inline void rtrim(std::basic_string<Char>& s)
+ {
+ s.erase(std::find_if(s.rbegin(), s.rend(), [] (const Char& c)
+ {
+ return !std::isspace(c);
+ }).base(), s.end());
+ }
+
+ template <typename Char>
+ inline void trim(std::basic_string<Char>& s)
+ {
+ ltrim(s);
+ rtrim(s);
+ }
+
+ template <typename Char, typename Sep, typename InputIterator>
+ inline std::basic_string<Char> join(
+ const Sep& sep,
+ InputIterator beg,
+ InputIterator end)
+ {
+ std::basic_ostringstream<Char> oss;
+
+ if (beg != end)
+ {
+ oss << *beg;
+ ++beg;
+ }
+
+ for (; beg != end; ++beg)
+ oss << sep << *beg;
+
+ return oss.str();
+ }
+
+ template <typename Char, typename Sep>
+ inline std::basic_string<Char> join(
+ const Sep& sep,
+ const std::vector<std::basic_string<Char>>& args)
+ {
+ return join<Char>(sep, args.cbegin(), args.cend());
+ }
+
+ template <typename Char, typename String, typename = void>
+ struct StringHelper
+ { };
+
+ template <typename Char, typename String>
+ struct StringHelper<Char, String, typename std::enable_if<std::is_same<typename std::decay<typename std::remove_pointer<String>::type>::type, Char>::value>::type>
+ {
+ inline StringHelper(const Char& c)
+ : buf{&c}
+ , len{1}
+ { }
+
+ inline StringHelper(const Char* s)
+ : buf{s}
+ , len{std::char_traits<Char>::length(s)}
+ { }
+
+ inline const Char* buffer() const { return buf; }
+
+ inline std::size_t length() const { return len; }
+
+ private:
+ const Char* const buf;
+ const std::size_t len;
+ };
+
+ template <typename Char, typename String>
+ struct StringHelper<Char, String, typename std::enable_if<std::is_same<String, std::basic_string<Char>>::value>::type>
+ {
+ inline StringHelper(const std::basic_string<Char>& s)
+ : s{s}
+ { }
+
+ inline const Char* buffer() const { return s.c_str(); }
+
+ inline std::size_t length() const { return s.length(); }
+
+ private:
+ const std::basic_string<Char>& s;
+ };
+
+ template <typename Char, typename What, typename By>
+ inline void replace(
+ std::basic_string<Char>& s,
+ const What& what,
+ const By& by)
+ {
+ std::size_t pos = 0;
+
+ const StringHelper<Char, typename std::decay<What>::type> what_helper{what};
+ const StringHelper<Char, typename std::decay<By>::type> by_helper{by};
+
+ const auto what_buf = what_helper.buffer();
+ const auto what_len = what_helper.length();
+
+ const auto by_buf = by_helper.buffer();
+ const auto by_len = by_helper.length();
+
+ while ((pos = s.find(what_buf, pos, what_len)) != std::basic_string<Char>::npos)
+ {
+ s.replace(pos, what_len, by_buf, by_len);
+ pos += by_len;
+ }
+ }
+
+ template <typename Char, typename What>
+ inline void prefix_with(
+ std::basic_string<Char>& s,
+ const What& what,
+ const Char& by)
+ {
+ const StringHelper<Char, typename std::decay<What>::type> what_helper{what};
+
+ const auto what_buf = what_helper.buffer();
+ const auto what_len = what_helper.length();
+
+ std::size_t numof_by = 0;
+
+ for (std::size_t i = 0; i < what_len; ++i)
+ numof_by += std::count(s.cbegin(), s.cend(), what_buf[i]);
+
+ s.reserve(s.capacity() + numof_by);
+
+ for (std::size_t i = 0; i < what_len; ++i)
+ replace(s, what_buf[i], by);
+ }
+}