src/util.cpp
browsing at commit = f94948ee920ac4654a97980edc83bf249aa160f5
#include "util.h"
#include <algorithm>
#include <array>
#include <cstdio>
#include <cstdlib>
namespace util {
namespace {
constexpr int MIN_OID_LEN = 4;
constexpr int MAX_OID_LEN = 40;
} // namespace
bool is_hex_oid(const std::string &s) {
if (s.length() < MIN_OID_LEN || s.length() > MAX_OID_LEN)
return false;
for (char c : s) {
const bool is_digit = c >= '0' && c <= '9';
const bool is_lower_hex = c >= 'a' && c <= 'f';
if (!is_digit && !is_lower_hex)
return false;
}
return true;
}
std::string human_size(uint64_t bytes) {
constexpr uint64_t unit = 1024;
const std::array<const char *, 5> suffixes{"B", "KiB", "MiB", "GiB", "TiB"};
if (bytes < unit)
return std::to_string(bytes) + " B";
double value = static_cast<double>(bytes);
size_t i = 0;
while (value >= unit && i + 1 < suffixes.size()) {
value /= unit;
++i;
}
std::array<char, 32> buf{};
std::snprintf(buf.data(), buf.size(), "%.1f %s", value, suffixes[i]);
return std::string(buf.data());
}
std::string format_time(std::time_t t) {
std::tm tm{};
gmtime_r(&t, &tm);
std::array<char, 32> buf{};
std::strftime(buf.data(), buf.size(), "%Y-%m-%d %H:%M", &tm);
return std::string(buf.data());
}
std::string basename(const std::string &path) {
const size_t pos = path.find_last_of('/');
if (pos == std::string::npos)
return path;
return path.substr(pos + 1);
}
std::string parent_path(const std::string &path) {
const size_t pos = path.find_last_of('/');
if (pos == std::string::npos)
return "";
return path.substr(0, pos);
}
std::string trim_slashes(const std::string &path) {
size_t start = 0;
size_t end = path.length();
while (start < end && path[start] == '/')
++start;
while (end > start && path[end - 1] == '/')
--end;
return path.substr(start, end - start);
}
std::string sanitize_filename(const std::string &name) {
std::string out = name;
for (char &c : out) {
const bool is_digit = c >= '0' && c <= '9';
const bool is_upper = c >= 'A' && c <= 'Z';
const bool is_lower = c >= 'a' && c <= 'z';
const bool is_safe_punct = c == '.' || c == '_' || c == '-';
if (!is_digit && !is_upper && !is_lower && !is_safe_punct)
c = '_';
}
return out;
}
bool is_markdown_path(const std::string &path) {
const size_t dot = path.find_last_of('.');
if (dot == std::string::npos)
return false;
std::string ext = path.substr(dot + 1);
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
return ext == "md" || ext == "markdown";
}
std::string image_mime_type(const std::string &path) {
const size_t dot = path.find_last_of('.');
if (dot == std::string::npos)
return "";
std::string ext = path.substr(dot + 1);
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
if (ext == "png")
return "image/png";
if (ext == "jpg" || ext == "jpeg")
return "image/jpeg";
if (ext == "gif")
return "image/gif";
if (ext == "webp")
return "image/webp";
if (ext == "svg")
return "image/svg+xml";
if (ext == "bmp")
return "image/bmp";
if (ext == "ico")
return "image/x-icon";
if (ext == "avif")
return "image/avif";
return "";
}
bool show_emails() {
static const bool value = [] {
const char *flag = std::getenv("SHOW_EMAILS");
return flag && std::string(flag) == "1";
}();
return value;
}
} // namespace util