#ifndef __STRING_H__
#define __STRING_H__
#include <algorithm>
#include <cctype>
#include <iostream>
#include <iterator>
#include <limits>
#include <sstream>
#include <string>
#include <vector>
namespace String {
template<int (&F)(int)>
int TypeCheck(unsigned char c) {
return F(c);
}
inline bool EndsWith(const std::string &s, char ch) {
return !s.empty() && s.back() == ch;
}
inline bool EndsWith(const std::string &s, const std::string &suffix) {
return std::mismatch(suffix.rbegin(), suffix.rend(), s.rbegin()).first == suffix.rend();
}
inline bool StartsWith(const std::string &s, char ch) {
return !s.empty() && s.front() == ch;
}
inline bool StartsWith(const std::string &s, const std::string &prefix) {
return std::mismatch(prefix.begin(), prefix.end(), s.begin()).first == prefix.end();
}
inline void RTrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
return !TypeCheck<std::isspace>(ch);
}).base(), s.end());
}
inline void LTrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
return !TypeCheck<std::isspace>(ch);
}));
}
inline void Trim(std::string &s) {
LTrim(s);
RTrim(s);
}
inline std::string RTrimCopy(std::string s) {
RTrim(s);
return s;
}
inline std::string LTrimCopy(std::string s) {
LTrim(s);
return s;
}
inline std::string TrimCopy(std::string &s) {
Trim(s);
return s;
}
inline void ToUpper(std::string &s) {
std::transform(s.begin(), s.end(), s.begin(), [](int ch) {
return std::toupper(ch);
});
}
inline void ToLower(std::string &s) {
std::transform(s.begin(), s.end(), s.begin(), [](int ch) {
return std::tolower(ch);
});
}
inline std::string ToupperCopy(std::string s) {
ToUpper(s);
return s;
}
inline std::string TolowerCopy(std::string s) {
ToLower(s);
return s;
}
//------------------------------------------------------------------------------
// Desc: join elements with a char
//------------------------------------------------------------------------------
inline std::string Implode(char glue, const std::vector<std::string> &pieces) {
std::string s;
if(!pieces.empty()) {
s.append(pieces[0]);
for(size_t i = 1; i < pieces.size(); ++i) {
s.push_back(glue);
s.append(pieces[i]);
}
}
return s;
}
//------------------------------------------------------------------------------
// Desc: join elements with a string
//------------------------------------------------------------------------------
inline std::string Implode(const std::string &glue, const std::vector<std::string> &pieces) {
std::string s;
if(!pieces.empty()) {
s.append(pieces[0]);
for(size_t i = 1; i < pieces.size(); ++i) {
s.append(glue);
s.append(pieces[i]);
}
}
return s;
}
inline std::vector<std::string> Explode(const std::string &delimeter, const std::string &string, int limit) {
std::vector<std::string> r;
if(!string.empty()) {
if(limit >= 0) {
if(limit == 0) {
limit = 1;
}
size_t first = 0;
size_t last = string.find(delimeter);
while(last != std::string::npos) {
if(--limit == 0) {
break;
}
r.emplace_back(string.substr(first, last - first));
first = last + delimeter.size();
last = string.find(delimeter, last + delimeter.size());
}
r.emplace_back(string.substr(first));
} else {
size_t first = 0;
size_t last = string.find(delimeter);
while(last != std::string::npos) {
r.emplace_back(string.substr(first, last - first));
first = last + delimeter.size();
last = string.find(delimeter, last + delimeter.size());
}
r.emplace_back(string.substr(first));
while(limit < 0) {
r.pop_back();
++limit;
}
}
}
return r;
}
inline std::vector<std::string> Explode(const std::string &delimeter, const std::string &string) {
return Explode(delimeter, string, std::numeric_limits<int>::max());
}
inline std::vector<std::string> Explode(char delimeter, const std::string &string, int limit) {
std::vector<std::string> r;
if(!string.empty()) {
if(limit >= 0) {
if(limit == 0) {
limit = 1;
}
size_t first = 0;
size_t last = string.find(delimeter);
while(last != std::string::npos) {
if(--limit == 0) {
break;
}
r.emplace_back(string.substr(first, last - first));
first = last + 1;
last = string.find(delimeter, last + 1);
}
r.emplace_back(string.substr(first));
} else {
size_t first = 0;
size_t last = string.find(delimeter);
while(last != std::string::npos) {
r.emplace_back(string.substr(first, last - first));
first = last + 1;
last = string.find(delimeter, last + 1);
}
r.emplace_back(string.substr(first));
while(limit < 0) {
r.pop_back();
++limit;
}
}
}
return r;
}
inline std::vector<std::string> Explode(char delimeter, const std::string &string) {
return Explode(delimeter, string, std::numeric_limits<int>::max());
}
template <class Op>
void Split(const std::string &s, char delim, Op op) {
std::stringstream ss(s);
for(std::string item; std::getline(ss, item, delim); ) {
*op++ = item;
}
}
inline std::vector<std::string> Split(const std::string &s, char delim) {
std::vector<std::string> elems;
Split(s, delim, std::back_inserter(elems));
return elems;
}
}
#endif