libmrbesen/src/util.cpp

275 lines
6.9 KiB
C++

#include "util.h"
#include <algorithm>
#include <sstream>
unsigned int mrbesen::util::count(const std::string& str, char c) {
size_t pos = 0;
long count = -1;
do {
pos = str.find(c, pos);
++count;
} while((pos++) != std::string::npos);
return (unsigned int) count;
}
bool icompare_pred(unsigned char a, unsigned char b) {
return std::tolower(a) == std::tolower(b);
}
bool mrbesen::util::equalsIgnoreCase(const std::string& a, const std::string& b, size_t max) {
size_t al = a.size(), bl = b.size();
if((al == 0 && bl == 0) || max == 0) return true;
if(al != bl && (al < max || bl < max)) {
return false;
}
if(max == std::string::npos) {
return std::equal(b.begin(), b.end(), a.begin(), icompare_pred);
} else {
if(max > al) max = al;
if(max > bl) max = bl;
return std::equal(b.begin(), b.begin()+max, a.begin(), icompare_pred);
}
}
void mrbesen::util::toLower(const std::string& in, std::string& out) {
if(&in == &out) {
//wenn beide strings identisch sind, inplace funktion verwenden;
toLower(out);
return;
}
out = "";
out.reserve(in.size());
for(char c : in) {
out += std::tolower(c);
}
}
void mrbesen::util::toLower(std::string& in) {
for(size_t p = 0; p < in.size(); p++) {
in[p] = std::tolower(in[p]);
}
}
bool mrbesen::util::endsWith(const std::string& str, const std::string& ending) {
size_t es = ending.size();
size_t ss = str.size();
if(es > ss) return false;
if(es == 0) return true;
return str.rfind(ending) == (ss - es);
}
bool mrbesen::util::startsWith(const std::string& str, const std::string& start) {
if(start.size() > str.size()) return false;
if(start.size() == 0) return true;
return str.find(start) == 0;
}
bool mrbesen::util::removeEnd(std::string& str, const std::string& ending) {
if(ending.empty()) return false;
if(endsWith(str, ending)) {
str.resize(str.size() - ending.length());
return true;
}
return false;
}
bool mrbesen::util::removeStart(std::string& str, const std::string& start) {
if(start.empty()) return false;
if(startsWith(str, start)) {
str = str.substr(start.length());
return true;
}
return false;
}
bool mrbesen::util::insertEnd(std::string& str, const std::string& ending) {
if(ending.empty()) return false;
if(endsWith(str, ending)) return false;
str.append(ending);
return true;
}
bool mrbesen::util::insertStart(std::string& str, const std::string& start) {
if(start.empty()) return false;
if(startsWith(str, start)) return false;
str = start + str;
return true;
}
unsigned int mrbesen::util::split(const std::string& str, const std::string& token, std::string* out, unsigned int count) {
StringSpliterator spl(str, token);
for(unsigned int i = 0; i < count; ++i) {
out[i] = *spl;
++spl;
if(!spl) return ++i;
}
return count;
}
bool mrbesen::util::trim(std::string& str, char c) {
size_t first = str.find_first_not_of(c);
if(first == std::string::npos) {
bool changed = !str.empty();
str = "";
return changed;
}
size_t last = str.find_last_not_of(c)+1;
bool changed = (last-first) < str.size();
if(changed)
str = str.substr(first, last-first);
return changed;
}
bool mrbesen::util::trimOnce(std::string& str, char c) {
bool a = removeStart(str, std::string(1, c));
bool b = removeEnd(str, std::string(1, c));
return a || b;
}
std::string mrbesen::util::bytesToBase16(char* buffer, unsigned int len) {
static const char hexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
std::string s(len << 1, ' ');
for (unsigned int i = 0; i < len; ++i) {
s[ i<<1 ] = hexmap[(buffer[i] & 0xF0) >> 4];
s[(i<<1) + 1] = hexmap[buffer[i] & 0x0F];
}
return s;
}
std::string mrbesen::util::bytesToBase64(char* buffer, unsigned int len) {
//from: https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp/index#cpp-base64-cpp
if(len == 0) return "";
size_t len_encoded = (len+2) / 3 * 4;
static const unsigned char trailing_char = '=';
static const char* base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
std::string ret;
ret.reserve(len_encoded);
for(unsigned int pos = 0; pos < len; pos += 3) {
ret.push_back(base64_chars[(buffer[pos] & 0xfc) >> 2]);
if (pos+1 < len) {
ret.push_back(base64_chars[((buffer[pos] & 0x03) << 4) + ((buffer[pos + 1] & 0xf0) >> 4)]);
if (pos+2 < len) {
ret.push_back(base64_chars[((buffer[pos + 1] & 0x0f) << 2) + ((buffer[pos + 2] & 0xc0) >> 6)]);
ret.push_back(base64_chars[ buffer[pos + 2] & 0x3f]);
} else {
ret.push_back(base64_chars[(buffer[pos + 1] & 0x0f) << 2]);
ret.push_back(trailing_char);
}
} else {
ret.push_back(base64_chars[(buffer[pos] & 0x03) << 4]);
ret.push_back(trailing_char);
ret.push_back(trailing_char);
}
}
return ret;
}
bool mrbesen::util::replace(std::string& modify, const std::string& search, char replace) {
bool changed = false;
for(size_t pos = modify.find_first_of(search); pos < std::string::npos; ) {
modify[pos] = replace;
changed = true;
//search next
pos = modify.find_first_of(search, pos+1);
}
return changed;
}
bool mrbesen::util::replace(std::string& modify, const std::string& search, const std::string& replacement) {
if(search.empty()) return false;
if(search.size() > modify.size()) return false;
if(modify.find(search) == std::string::npos) return false;
std::ostringstream out;
size_t pos = 0;
while(pos < modify.size()) {
//search for next occurance of search
size_t nextp = modify.find(search, pos);
bool end = (nextp == std::string::npos);
if(end) nextp = modify.size();
if(nextp > pos) {
out << modify.substr(pos, (nextp)-pos);
pos = nextp;
}
if(!end)
out << replacement;
pos += search.size();
}
modify = out.str();
return true;
}
mrbesen::util::StringSpliterator::StringSpliterator(const std::string& d, const std::string& token) : data(d), token(token) {
//trim
while(mrbesen::util::removeStart(data, token));
while(mrbesen::util::removeEnd(data, token));
findNext();
}
mrbesen::util::StringSpliterator::StringSpliterator(const std::string& d, char token) : StringSpliterator(d, std::string(1, token)) {}
mrbesen::util::StringSpliterator::~StringSpliterator() {}
std::string mrbesen::util::StringSpliterator::operator*() const {
return data.substr(lasttok, (nexttok - lasttok)-token.size());
}
mrbesen::util::StringSpliterator& mrbesen::util::StringSpliterator::operator++() {
findNext();
return *this;
}
mrbesen::util::StringSpliterator mrbesen::util::StringSpliterator::operator++(int) {
StringSpliterator ret = *this;
findNext();
return ret;
}
void mrbesen::util::StringSpliterator::findNext() {
if(!operator bool()) return;
lasttok = nexttok;
size_t test = 0;
while((test = data.find(token, nexttok + token.size())) == (nexttok + token.size())) {
lasttok = test;
nexttok = test;
}
nexttok = test;
if(nexttok != std::string::npos)
nexttok += token.size();
}
mrbesen::util::StringSpliterator::operator bool() const {
return lasttok < data.length() && nexttok >= lasttok;
}