2016-12-23 03:40:35 +00:00
|
|
|
#include <cstring>
|
2016-11-02 19:22:45 +00:00
|
|
|
#include <sstream>
|
2016-11-25 12:55:15 +00:00
|
|
|
#include <utility>
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
#include "utils/string.hpp"
|
|
|
|
|
2016-11-19 05:22:44 +00:00
|
|
|
POLYBAR_NS
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
namespace string_util {
|
|
|
|
/**
|
|
|
|
* Check if haystack contains needle
|
|
|
|
*/
|
|
|
|
bool contains(const string& haystack, const string& needle) {
|
|
|
|
return haystack.find(needle) != string::npos;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert string to uppercase
|
|
|
|
*/
|
|
|
|
string upper(const string& s) {
|
|
|
|
string str(s);
|
2016-11-25 12:55:15 +00:00
|
|
|
for (auto& c : str) {
|
|
|
|
c = toupper(c);
|
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert string to lowercase
|
|
|
|
*/
|
|
|
|
string lower(const string& s) {
|
|
|
|
string str(s);
|
2016-11-25 12:55:15 +00:00
|
|
|
for (auto& c : str) {
|
|
|
|
c = tolower(c);
|
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test lower case equality
|
|
|
|
*/
|
|
|
|
bool compare(const string& s1, const string& s2) {
|
|
|
|
return lower(s1) == lower(s2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replace first occurence of needle in haystack
|
|
|
|
*/
|
2016-12-23 03:40:35 +00:00
|
|
|
string replace(const string& haystack, const string& needle, const string& replacement, size_t start, size_t end) {
|
2016-11-02 19:22:45 +00:00
|
|
|
string str(haystack);
|
|
|
|
string::size_type pos;
|
2016-11-19 18:18:28 +00:00
|
|
|
|
2016-12-23 03:40:35 +00:00
|
|
|
if (needle != replacement && (pos = str.find(needle, start)) != string::npos) {
|
2016-11-25 12:55:15 +00:00
|
|
|
if (end == string::npos || pos < end) {
|
2016-12-23 03:40:35 +00:00
|
|
|
str = str.replace(pos, needle.length(), replacement);
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-19 18:18:28 +00:00
|
|
|
}
|
|
|
|
|
2016-11-02 19:22:45 +00:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replace all occurences of needle in haystack
|
|
|
|
*/
|
2016-12-23 03:40:35 +00:00
|
|
|
string replace_all(
|
|
|
|
const string& haystack, const string& needle, const string& replacement, size_t start, size_t end) {
|
|
|
|
string result{haystack};
|
|
|
|
string::size_type pos;
|
|
|
|
while ((pos = result.find(needle, start)) != string::npos && pos < result.length() &&
|
|
|
|
(end == string::npos || pos + needle.length() <= end)) {
|
|
|
|
result.replace(pos, needle.length(), replacement);
|
|
|
|
start = pos + replacement.length();
|
2016-11-02 19:22:45 +00:00
|
|
|
}
|
2016-12-23 03:40:35 +00:00
|
|
|
return result;
|
2016-11-02 19:22:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replace all consecutive occurrences of needle in haystack
|
|
|
|
*/
|
|
|
|
string squeeze(const string& haystack, char needle) {
|
|
|
|
string result = haystack;
|
2016-11-25 12:55:15 +00:00
|
|
|
while (result.find({needle, needle}) != string::npos) {
|
|
|
|
result = replace_all(result, {needle, needle}, {needle});
|
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove all occurrences of needle in haystack
|
|
|
|
*/
|
|
|
|
string strip(const string& haystack, char needle) {
|
|
|
|
string str(haystack);
|
|
|
|
string::size_type pos;
|
2016-11-25 12:55:15 +00:00
|
|
|
while ((pos = str.find(needle)) != string::npos) {
|
|
|
|
str.erase(pos, 1);
|
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove trailing newline
|
|
|
|
*/
|
|
|
|
string strip_trailing_newline(const string& haystack) {
|
|
|
|
string str(haystack);
|
2016-11-25 12:55:15 +00:00
|
|
|
if (str[str.length() - 1] == '\n') {
|
2016-11-02 19:22:45 +00:00
|
|
|
str.erase(str.length() - 1, 1);
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove needle from the start of the string
|
|
|
|
*/
|
2016-12-14 10:34:09 +00:00
|
|
|
string ltrim(string&& value, const char& needle) {
|
|
|
|
if (value.empty()) {
|
|
|
|
return "";
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-12-14 10:34:09 +00:00
|
|
|
while (*value.begin() == needle) {
|
|
|
|
value.erase(0, 1);
|
|
|
|
}
|
|
|
|
return forward<string>(value);
|
2016-11-02 19:22:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove needle from the end of the string
|
|
|
|
*/
|
2016-12-14 10:34:09 +00:00
|
|
|
string rtrim(string&& value, const char& needle) {
|
|
|
|
if (value.empty()) {
|
|
|
|
return "";
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-12-14 10:34:09 +00:00
|
|
|
while (*(value.end() - 1) == needle) {
|
|
|
|
value.erase(value.length() - 1, 1);
|
|
|
|
}
|
|
|
|
return forward<string>(value);
|
2016-11-02 19:22:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove needle from the start and end of the string
|
|
|
|
*/
|
2016-12-14 05:51:07 +00:00
|
|
|
string trim(string&& value, const char& needle) {
|
2016-12-14 10:34:09 +00:00
|
|
|
if (value.empty()) {
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
return rtrim(ltrim(forward<string>(value), needle), needle);
|
2016-11-02 19:22:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Join all strings in vector into a single string separated by delim
|
|
|
|
*/
|
2016-11-27 00:32:21 +00:00
|
|
|
string join(const vector<string>& strs, const string& delim) {
|
2016-11-02 19:22:45 +00:00
|
|
|
string str;
|
2016-11-25 12:55:15 +00:00
|
|
|
for (auto& s : strs) {
|
2016-11-27 00:32:21 +00:00
|
|
|
str += (str.empty() ? "" : delim) + s;
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Explode string by delim into container
|
|
|
|
*/
|
2016-11-25 12:55:15 +00:00
|
|
|
vector<string>& split_into(const string& s, char delim, vector<string>& container) {
|
2016-11-02 19:22:45 +00:00
|
|
|
string str;
|
|
|
|
stringstream buffer(s);
|
2016-11-25 12:55:15 +00:00
|
|
|
while (getline(buffer, str, delim)) {
|
|
|
|
container.emplace_back(str);
|
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
return container;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Explode string by delim
|
|
|
|
*/
|
|
|
|
vector<string> split(const string& s, char delim) {
|
|
|
|
vector<string> vec;
|
|
|
|
return split_into(s, delim, vec);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find the nth occurence of needle in haystack starting from pos
|
|
|
|
*/
|
2016-11-25 12:55:15 +00:00
|
|
|
size_t find_nth(const string& haystack, size_t pos, const string& needle, size_t nth) {
|
2016-11-02 19:22:45 +00:00
|
|
|
size_t found_pos = haystack.find(needle, pos);
|
2016-11-25 12:55:15 +00:00
|
|
|
if (1 == nth || string::npos == found_pos) {
|
2016-11-02 19:22:45 +00:00
|
|
|
return found_pos;
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
return find_nth(haystack, found_pos + 1, needle, nth - 1);
|
|
|
|
}
|
|
|
|
|
2016-11-13 05:09:51 +00:00
|
|
|
/**
|
|
|
|
* Create a float value string
|
|
|
|
*/
|
2016-11-25 12:55:15 +00:00
|
|
|
string floatval(float value, int decimals, bool fixed, const string& locale) {
|
2016-11-13 05:09:51 +00:00
|
|
|
stringstream ss;
|
|
|
|
ss.precision(decimals);
|
2016-11-25 12:55:15 +00:00
|
|
|
if (!locale.empty()) {
|
2016-11-13 05:09:51 +00:00
|
|
|
ss.imbue(std::locale(locale.c_str()));
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
|
|
|
if (fixed) {
|
2016-11-13 05:09:51 +00:00
|
|
|
ss << std::fixed;
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-13 05:09:51 +00:00
|
|
|
ss << value;
|
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Format a filesize string
|
|
|
|
*/
|
2016-11-25 12:55:15 +00:00
|
|
|
string filesize(unsigned long long bytes, int decimals, bool fixed, const string& locale) {
|
2016-11-13 05:09:51 +00:00
|
|
|
vector<string> suffixes{"TB", "GB", "MB"};
|
|
|
|
string suffix{"KB"};
|
|
|
|
|
2016-11-13 07:15:20 +00:00
|
|
|
while ((bytes /= 1024) >= 1024) {
|
2016-11-13 05:09:51 +00:00
|
|
|
suffix = suffixes.back();
|
|
|
|
suffixes.pop_back();
|
|
|
|
}
|
|
|
|
|
|
|
|
stringstream ss;
|
|
|
|
ss.precision(decimals);
|
2016-11-25 12:55:15 +00:00
|
|
|
if (!locale.empty()) {
|
2016-11-13 05:09:51 +00:00
|
|
|
ss.imbue(std::locale(locale.c_str()));
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
|
|
|
if (fixed) {
|
2016-11-13 05:09:51 +00:00
|
|
|
ss << std::fixed;
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-13 05:09:51 +00:00
|
|
|
ss << bytes << " " << suffix;
|
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
|
2016-11-02 19:22:45 +00:00
|
|
|
/**
|
|
|
|
* Get the resulting string from a ostream/
|
|
|
|
*
|
|
|
|
* Example usage:
|
|
|
|
* @code cpp
|
2016-11-13 05:09:51 +00:00
|
|
|
* string_util::from_stream(stringstream() << ...);
|
2016-11-02 19:22:45 +00:00
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
string from_stream(const std::basic_ostream<char>& os) {
|
2016-12-15 08:29:14 +00:00
|
|
|
return dynamic_cast<const stringstream&>(os).str();
|
2016-11-02 19:22:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Compute string hash
|
|
|
|
*/
|
2016-11-25 12:55:15 +00:00
|
|
|
hash_type hash(const string& src) {
|
2016-11-02 19:22:45 +00:00
|
|
|
return std::hash<string>()(src);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-19 05:22:44 +00:00
|
|
|
POLYBAR_NS_END
|