From 6232d13f5321b87ddf12a1aa36b4545da45f173d Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Wed, 17 Nov 2021 22:34:57 +0100 Subject: Travel3: Simple image and video display site Reads the images and videos from filesystem and builds a site in memroy. --- src/strutil.cc | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 src/strutil.cc (limited to 'src/strutil.cc') diff --git a/src/strutil.cc b/src/strutil.cc new file mode 100644 index 0000000..adee769 --- /dev/null +++ b/src/strutil.cc @@ -0,0 +1,211 @@ +#include "common.hh" + +#include "strutil.hh" + +#include +#include +#include + +namespace str { + +namespace { + +// Sadly strtoul(l) doesn't treat negative values an error but instead returns +// ULONG_MAX - value which is indistinguable from ULONG_MAX - value the positive +// way. +bool is_negative(std::string const& str) { + for (auto i = str.begin(); i != str.end(); ++i) { + if (!isspace(*i)) { + return *i == '-'; + } + } + return false; +} + +} // namespace + +std::optional parse_uint16(std::string const& str) { + static_assert(sizeof(unsigned long) >= sizeof(uint16_t), + "Need unsigned long to be >= uint16_t"); + if (str.empty() || is_negative(str)) + return std::nullopt; + char* end = nullptr; + errno = 0; + auto tmp = strtoul(str.c_str(), &end, 10); + if (errno || end != str.c_str() + str.size() || + tmp > std::numeric_limits::max()) + return std::nullopt; + return static_cast(tmp); +} + +std::optional parse_uint32(std::string const& str) { + static_assert(sizeof(unsigned long long) >= sizeof(uint32_t), + "Need unsigned long long to be >= uint32_t"); + if (str.empty() || is_negative(str)) + return std::nullopt; + char* end = nullptr; + errno = 0; + auto tmp = strtoull(str.c_str(), &end, 10); + if (errno || end != str.c_str() + str.size() || + tmp > std::numeric_limits::max()) + return std::nullopt; + return static_cast(tmp); +} + +std::optional parse_uint64(std::string const& str) { + static_assert(sizeof(unsigned long long) >= sizeof(uint64_t), + "Need unsigned long long to be >= uint64_t"); + if (str.empty() || is_negative(str)) + return std::nullopt; + char* end = nullptr; + errno = 0; + auto tmp = strtoull(str.c_str(), &end, 10); + if (errno || end != str.c_str() + str.size() || + tmp > std::numeric_limits::max()) + return std::nullopt; + return static_cast(tmp); +} + +std::vector split(std::string_view str, char delim) { + std::vector ret; + size_t last = 0; + while (true) { + size_t next = str.find(delim, last); + if (next == std::string::npos) + break; + if (next > last) + ret.push_back(str.substr(last, next - last)); + last = next + 1; + } + if (last < str.size() || ret.empty()) + ret.push_back(str.substr(last)); + return ret; +} + +std::vector split(std::string const& str, char delim) { + std::vector ret; + size_t last = 0; + while (true) { + size_t next = str.find(delim, last); + if (next == std::string::npos) + break; + if (next > last) + ret.push_back(str.substr(last, next - last)); + last = next + 1; + } + if (last < str.size() || ret.empty()) + ret.push_back(str.substr(last)); + return ret; +} + +std::string join(std::vector const& in, char delim) { + std::string ret; + join(in, delim, ret); + return ret; +} + +std::string join(std::vector const& in, std::string_view delim) { + std::string ret; + join(in, delim, ret); + return ret; +} + +void join(std::vector const& in, char delim, std::string& out) { + join(in, std::string_view(&delim, 1), out); +} + +void join(std::vector const& in, std::string_view delim, + std::string& out) { + auto it = in.begin(); + if (it == in.end()) + return; + out.append(*it); + for (++it; it != in.end(); ++it) { + out.append(delim); + out.append(*it); + } +} + +std::string join(std::vector const& in, char delim) { + std::string ret; + join(in, delim, ret); + return ret; +} + +std::string join(std::vector const& in, + std::string_view delim) { + std::string ret; + join(in, delim, ret); + return ret; +} + +void join(std::vector const& in, char delim, + std::string& out) { + join(in, std::string_view(&delim, 1), out); +} + +void join(std::vector const& in, std::string_view delim, + std::string& out) { + auto it = in.begin(); + if (it == in.end()) + return; + out.append(*it); + for (++it; it != in.end(); ++it) { + out.append(delim); + out.append(*it); + } +} + +bool starts_with(std::string_view str, std::string_view prefix) { + return str.size() >= prefix.size() && + str.compare(0, prefix.size(), prefix) == 0; +} + +bool ends_with(std::string_view str, std::string_view suffix) { + return str.size() >= suffix.size() && + str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; +} + +std::string_view trim(std::string_view str) { + return ltrim(rtrim(str)); +} + +std::string_view ltrim(std::string_view str) { + size_t start = 0; + while (start < str.size() && str[start] == ' ') + ++start; + return str.substr(start); +} + +std::string_view rtrim(std::string_view str) { + size_t end = str.size(); + while (end > 0 && str[end - 1] == ' ') + --end; + return str.substr(0, end); +} + +std::string trim(std::string const& str) { + size_t start = 0; + while (start < str.size() && str[start] == ' ') + ++start; + size_t end = str.size(); + while (end > start && str[end - 1] == ' ') + --end; + return str.substr(start, end - start); +} + +std::string ltrim(std::string const& str) { + size_t start = 0; + while (start < str.size() && str[start] == ' ') + ++start; + return str.substr(start); +} + +std::string rtrim(std::string const& str) { + size_t end = str.size(); + while (end > 0 && str[end - 1] == ' ') + --end; + return str.substr(0, end); +} + +} // namespace str -- cgit v1.2.3-70-g09d2