2020-09-28 23:49:14 +02:00
|
|
|
#include "util.h"
|
|
|
|
|
2020-09-29 14:04:19 +02:00
|
|
|
#include <algorithm>
|
|
|
|
|
2020-09-28 23:49:14 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2020-09-29 14:04:19 +02:00
|
|
|
|
|
|
|
void mrbesen::Util::toLower(const std::string& in, std::string& out) {
|
2020-09-29 14:12:41 +02:00
|
|
|
|
|
|
|
if(&in == &out) {
|
|
|
|
//wenn beide strings identisch sind, inplace funktion verwenden;
|
|
|
|
toLower(out);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-29 14:04:19 +02:00
|
|
|
out = "";
|
|
|
|
out.reserve(in.size());
|
|
|
|
for(char c : in) {
|
|
|
|
out += std::tolower(c);
|
|
|
|
}
|
|
|
|
}
|
2020-09-29 14:12:41 +02:00
|
|
|
|
|
|
|
void mrbesen::Util::toLower(std::string& in) {
|
|
|
|
for(size_t p = 0; p < in.size(); p++) {
|
|
|
|
in[p] = std::tolower(in[p]);
|
|
|
|
}
|
|
|
|
}
|
2020-09-29 15:12:46 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2020-10-01 14:01:54 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2020-10-02 15:54:12 +02:00
|
|
|
|
|
|
|
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;
|
2020-10-02 16:04:47 +02:00
|
|
|
}
|
|
|
|
|
2020-10-04 15:03:06 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
void mrbesen::Util::trim(std::string& str, char c) {
|
|
|
|
size_t first = str.find_first_not_of(c);
|
|
|
|
if(first == std::string::npos) {
|
|
|
|
str = "";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
size_t last = str.find_last_not_of(c)+1;
|
|
|
|
str = str.substr(first, last-first);
|
|
|
|
}
|
|
|
|
|
2020-10-05 13:35:42 +02:00
|
|
|
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 "";
|
|
|
|
|
|
|
|
const uint8_t overlen = len % 3;
|
|
|
|
const uint8_t len_padding = overlen ? (3 - overlen) : 0; //anzahl benötigter padding chars
|
|
|
|
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);
|
|
|
|
|
|
|
|
char nextb = 0;
|
|
|
|
for(unsigned int pos = 0; pos < len; pos ++) {
|
|
|
|
const char c = buffer[pos];
|
|
|
|
uint8_t tripos = pos % 3; //position im trible
|
|
|
|
uint8_t maskShift = (1+tripos) << 1; //2, 4, 6
|
|
|
|
uint8_t mask = 0xff << maskShift;
|
|
|
|
ret.push_back(base64_chars[((c & mask) >> maskShift) | nextb]);
|
|
|
|
|
|
|
|
if(tripos == 2) {
|
|
|
|
ret.push_back(base64_chars[c & ~mask]);
|
|
|
|
nextb = 0;
|
|
|
|
} else {
|
|
|
|
uint8_t invmaskShift = 6 - maskShift;
|
|
|
|
nextb = (c & ~mask) << invmaskShift;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(nextb)
|
|
|
|
ret.push_back(base64_chars[(int) nextb]);
|
|
|
|
|
|
|
|
for(uint8_t i = 0; i < len_padding; ++i) {
|
|
|
|
ret.push_back(trailing_char);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-04 15:03:06 +02:00
|
|
|
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() {}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|