#include "util.hpp" #include "utf8.hpp" #include <ctime> #include <algorithm> #include "upper2lower" int util::printedLength(std::string_view s) { return splitAsUtf8(s).size(); } std::string_view util::getFilenameFromPath(std::string_view s) { int indexOfSlash = s.find_last_of('/'); return {s.data()+indexOfSlash+1, s.size()-1-indexOfSlash}; } bool util::isSeparator(utf8char c) { return c == ' ' || isIllegal(c); } bool util::isIllegal(utf8char c) { return c == '\n' || c == '\t'; } std::vector<std::string> util::split(std::string_view remaining, char delimiter) { std::vector<std::string> result; for (auto firstDelimiterIndex = remaining.find_first_of(delimiter); firstDelimiterIndex != std::string_view::npos; firstDelimiterIndex = remaining.find_first_of(delimiter)) { if (remaining[0] != delimiter) result.emplace_back(remaining.data(), firstDelimiterIndex); remaining = std::string_view(remaining.data()+firstDelimiterIndex+1, remaining.size()-1-firstDelimiterIndex); } if (remaining.size() > 0) result.emplace_back(remaining); return result; } util::utf8string util::splitAsUtf8(std::string_view s) { utf8string result; const char * beginPtr = s.data(); const char * currentPtr = beginPtr; const char * endPtr = s.data()+s.size(); while (currentPtr < endPtr) { try {utf8::next(currentPtr, endPtr);} catch (std::exception &) { break; } if (currentPtr - beginPtr > 4 || currentPtr - beginPtr == 0) myThrow(fmt::format("Invalid utf8 character at index {}", beginPtr-s.data())); utf8char c; for (int i = 0; i < currentPtr - beginPtr; i++) c[i] = beginPtr[i]; beginPtr = currentPtr; result.push_back(c); } return result; } std::string util::shrink(const std::string & s, int printedSize) { static const std::string filler = "…"; if (printedLength(s) <= printedSize) return s; auto splited = splitAsUtf8(s); std::string result; std::string begin, end; int nbLoop = 0; while (printedLength(begin)+printedLength(end)+printedLength(filler) <= printedSize) { result = begin + filler + end; if (nbLoop % 2) end = fmt::format("{}{}", splited[splited.size()-1-(nbLoop/2)], end); else begin = fmt::format("{}{}", begin, splited[nbLoop/2]); ++nbLoop; } return result; } void util::warning(std::string_view message, const std::experimental::source_location & location) { fmt::print(stderr, "WARNING ({}) : {}\n", location, message); } void util::error(std::string_view message, const std::experimental::source_location & location) { fmt::print(stderr, "ERROR ({}) : {}\n", location, message); exit(1); } void util::error(const std::exception & e, const std::experimental::source_location & location) { error(e.what(), location); } void util::myThrow(std::string_view message, const std::experimental::source_location & location) { throw std::invalid_argument(fmt::format("from ({}) {}", location, message)); } std::string util::int2HumanStr(int number) { std::string nb = std::to_string(number); std::string result; for (unsigned int i = 0; i < nb.size(); i++) { result.push_back(nb[i]); if (((nb.size()-i-1) % 3 == 0) && i < nb.size()-1) result.push_back(' '); } return result; } bool util::doIfNameMatch(const std::regex & reg, std::string_view name, const std::function<void(const std::smatch &)> & f) { std::smatch sm; std::string sname(name); std::regex_match(sname, sm, reg); if (sm.empty()) return false; f(sm); return true; } std::string util::strip(const std::string & s) { std::string striped; if (s.empty()) return striped; std::size_t first = 0; while (first < s.size() and (s[first] == ' ' or s[first] == '\t')) ++first; std::size_t last = s.size()-1; while (last > first and (s[last] == ' ' or s[last] == '\t' or s[last] == '\n')) --last; return std::string(s.begin()+first, s.begin()+last+1); } std::vector<std::filesystem::path> util::findFilesByExtension(std::filesystem::path directory, std::string extension) { std::vector<std::filesystem::path> files; for (auto entry : std::filesystem::directory_iterator(directory)) if (entry.is_regular_file()) { auto path = entry.path(); if (path.extension() == extension) files.push_back(path); } return files; } std::string util::getTime() { std::time_t rawtime; char buffer[80]; std::time(&rawtime); std::strftime(buffer, sizeof(buffer), "%H:%M:%S", std::localtime(&rawtime)); return std::string(buffer); } bool util::choiceWithProbability(float probability) { int maxVal = 100000; int threshold = maxVal * probability; return (std::rand() % maxVal) < threshold; } bool util::isUppercase(utf8char c) { return upper2lower.count(c); } std::string util::lower(const std::string & s) { auto splited = util::splitAsUtf8(s); for (auto & c : splited) { auto it = upper2lower.find(c); if (it != upper2lower.end()) c = it->second; } return fmt::format("{}", splited); }