generate-shapes/src/util/String.h
Patrick Brosi 63f0b61ea1 clean up and refactor half-baked development commits and squash them into a new version.
Changes:

* support for multiple GTFS feeds as input in filtering, read default global and local configuration files
* be a bit more memory conservative
* make caching optional
* dont delete orphan edge if it would transform a degree 3 node with a possible full turn into a degree 2 node eligible for contraction
* dedicated filters for funicular and gondola
* make max snap level option more intuitive
* allow filter rules for level 0
* additional fallback for station snapping
* dont try to route for MOT unequal to trip in -T mode, force-snap to orphaned OSM station if not snap was possible
* write bounds to filtered osm
* remove unused surrounding heuristic
* use bus lanes info
* be a bit more tolerant for bus oneway streets
* create missing directories
* error if no cfg is present, clean up evaluation Makefile
2019-01-12 01:08:13 +01:00

201 lines
6 KiB
C++

// Copyright 2017, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
#ifndef UTIL_STRING_H_
#define UTIL_STRING_H_
#include <algorithm>
#include <cstring>
#include <sstream>
#include <string>
#include <vector>
namespace util {
// _____________________________________________________________________________
inline std::string urlDecode(const std::string& encoded) {
std::string decoded;
for (size_t i = 0; i < encoded.size(); ++i) {
char c = encoded[i];
if (c == '%') {
std::string ah = encoded.substr(i + 1, 2);
char* nonProced = 0;
char hexVal = strtol(ah.c_str(), &nonProced, 16);
if (ah.find_first_of("+-") > 1 && ah.size() - strlen(nonProced) == 2) {
c = hexVal;
i += 2;
}
} else if (c == '+') {
c = ' ';
}
decoded += c;
}
return decoded;
}
// _____________________________________________________________________________
inline std::string jsonStringEscape(const std::string& unescaped) {
std::string escaped;
for (size_t i = 0; i < unescaped.size(); ++i) {
if (unescaped[i] == '"' || unescaped[i] == '\\') {
escaped += "\\";
}
if (iscntrl(unescaped[i])) {
escaped += " ";
}
escaped += unescaped[i];
}
return escaped;
}
// _____________________________________________________________________________
inline bool replace(std::string& subj, const std::string& from,
const std::string& to) {
if (from.empty()) return false;
size_t start_pos = subj.find(from);
if (start_pos != std::string::npos) {
subj.replace(start_pos, from.length(), to);
return true;
}
return false;
}
// _____________________________________________________________________________
inline bool replaceAll(std::string& subj, const std::string& from,
const std::string& to) {
if (from.empty()) return false;
bool found = false;
size_t s = subj.find(from, 0);
for (; s != std::string::npos; s = subj.find(from, s + to.length())) {
found = true;
subj.replace(s, from.length(), to);
}
return found;
}
// _____________________________________________________________________________
inline std::string unixBasename(const std::string& pathname) {
return {std::find_if(pathname.rbegin(), pathname.rend(),
[](char c) { return c == '/'; })
.base(),
pathname.end()};
}
// _____________________________________________________________________________
template <typename T>
inline std::string toString(T obj) {
std::stringstream ss;
ss << obj;
return ss.str();
}
// _____________________________________________________________________________
inline std::vector<std::string> split(std::string in, char sep) {
std::stringstream ss(in);
std::vector<std::string> ret(1);
while (std::getline(ss, ret.back(), sep)) {
ret.push_back("");
}
ret.pop_back();
return ret;
}
// _____________________________________________________________________________
inline std::string ltrim(std::string str) {
str.erase(0, str.find_first_not_of(" \t\n\v\f\r"));
return str;
}
// _____________________________________________________________________________
inline std::string rtrim(std::string str) {
str.erase(str.find_last_not_of(" \t\n\v\f\r") + 1);
return str;
}
// _____________________________________________________________________________
inline std::string trim(std::string str) { return ltrim(rtrim(str)); }
// _____________________________________________________________________________
inline size_t editDist(const std::string& s1, const std::string& s2) {
// https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C++
size_t len1 = s1.size();
size_t len2 = s2.size();
std::vector<size_t> cur(len2 + 1);
std::vector<size_t> prev(len2 + 1);
for (size_t i = 0; i < prev.size(); i++) prev[i] = i;
for (size_t i = 0; i < len1; i++) {
cur[0] = i + 1;
for (size_t j = 0; j < len2; j++) {
cur[j + 1] =
std::min(prev[1 + j] + 1,
std::min(cur[j] + 1, prev[j] + (s1[i] == s2[j] ? 0 : 1)));
}
std::swap(cur, prev);
}
return prev[len2];
}
// _____________________________________________________________________________
inline size_t prefixEditDist(const std::string& prefix, const std::string& s,
size_t deltaMax) {
// https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C++
size_t len1 = prefix.size();
size_t len2 = std::min(s.size(), prefix.size() + deltaMax + 1);
std::vector<size_t> d((len1 + 1) * (len2 + 1));
d[0] = 0;
for (size_t i = 1; i <= len1; ++i) d[i * (len2 + 1)] = i;
for (size_t i = 1; i <= len2; ++i) d[ i] = i;
for (size_t i = 1; i <= len1; i++) {
for (size_t j = 1; j <= len2; j++) {
d[i * (len2 + 1) + j] = std::min(std::min(d[(i - 1) * (len2 + 1) + j] + 1, d[i * (len2 + 1) + j - 1] + 1),
d[(i - 1) * (len2 + 1) + j - 1] + (prefix[i - 1] == s[j - 1] ? 0 : 1));
}
}
// take min of last row
size_t deltaMin = std::max(std::max(deltaMax + 1, prefix.size()), s.size());
for (size_t i = 0; i <= len2; i++) {
if (d[len1 * (len2 + 1) + i] < deltaMin) deltaMin = d[len1 * (len2 + 1) + i];
}
return deltaMin;
}
// _____________________________________________________________________________
inline size_t prefixEditDist(const std::string& prefix, const std::string& s) {
return prefixEditDist(prefix, s, s.size());
}
// _____________________________________________________________________________
template <class Iter>
inline std::string implode(Iter begin, const Iter& end, const char* del) {
std::stringstream ss;
size_t i = 0;
while (begin != end) {
if (i != 0) ss << del;
ss << *begin;
begin++;
i++;
}
return ss.str();
}
// _____________________________________________________________________________
template <typename T>
inline std::string implode(const std::vector<T>& vec, const char* del) {
return implode(vec.begin(), vec.end(), del);
}
}
#endif // UTIL_STRING_H_