#include "util.h" #include #include #include #include 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 suffixes{"B", "KiB", "MiB", "GiB", "TiB"}; if (bytes < unit) return std::to_string(bytes) + " B"; double value = static_cast(bytes); size_t i = 0; while (value >= unit && i + 1 < suffixes.size()) { value /= unit; ++i; } std::array 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 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); } 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