#include "drvutil.hpp" #include #include #include #include #include #include #include "../../ext/unicode-stuff.hpp" namespace drvutil { inline static bool ascii_isspace(char c) { return (c==' ')||(c=='\t')||(c=='\r')||(c=='\n')||(c=='\f')||(c=='\v'); } std::string_view trim(std::string_view v) { while ((!v.empty()) && (ascii_isspace(v.front()))) { v.remove_prefix(1); } while ((!v.empty()) && (ascii_isspace(v.back()))) { v.remove_suffix(1); } return v; } static std::string_view read_to_line(std::string_view &source) { size_t pos = source.find('\n'); std::string_view result; if (pos == std::string_view::npos) { result = source; source = std::string_view(); } else { result = source.substr(0, pos); source = source.substr(pos + 1); } if ((!result.empty()) && (result.back() == '\r')) { result.remove_suffix(1); } return result; } std::vector split_view(std::string_view v, char sep) { std::vector result; while (true) { size_t pos = v.find(sep); if (pos == std::string_view::npos) break; result.push_back(v.substr(0, pos)); v = v.substr(pos + 1); } result.push_back(v); return result; } void split_target(std::string_view target, std::string &cert, std::string &host, std::string &port) { std::vector split = split_view(target, ':'); if (split.size() != 3) { cert.clear(); host.clear(); port.clear(); return; } if (split[0].empty() || split[1].empty() || split[2].empty()) { cert.clear(); host.clear(); port.clear(); return; } cert = std::string(split[0]); host = std::string(split[1]); port = std::string(split[2]); } bool is_single_wchar_t(char32_t c) { if ((c >= 0xD800) && (c <= 0xDFFF)) return false; if ((c >= 0) && (c <= 0xFFFF)) return true; return false; } using UC = UnicodeStuff; std::string utf32_to_utf8(const std::u32string &s) { return UC::utf32_to_utf8(s); } std::u32string utf8_to_utf32(std::string_view s, int *consumed) { return UC::utf8_to_utf32(s, consumed); } std::u16string utf8_to_ucs2(std::string_view s, int *consumed) { return UC::utf8_to_ucs2(s, consumed); } std::string utf16_to_utf8(std::u16string_view s) { return UC::utf16_to_utf8(s); } static std::vector parse_control_lst(std::string_view ctrl) { std::vector result; while (!ctrl.empty()) { std::string_view line = read_to_line(ctrl); std::string_view trimmed = trim(line); if ((trimmed.size() > 0) && (trimmed[0] != '#')) { result.emplace_back(trimmed); } } return result; } // Read a source file into a string. // static std::string read_file(const std::filesystem::path &fn, std::string &err) { std::ifstream t(fn); if (t.fail()) { err = std::string("Could not open ") + fn.string(); return ""; } t.seekg(0, std::ios::end); size_t size = t.tellg(); std::string result(size, ' '); t.seekg(0); t.read(&result[0], size); if ((t.fail()) || (size_t(t.tellg()) != size)) { err = std::string("Could not read ") + fn.string(); return ""; } err = ""; return result; } // This encoding can be read by StreamBuffer::read_uint32. // static void sbwrite_uint32(std::ostream *s, uint32_t v) { s->write((const char *)&v, 4); } // This encoding can be read by StreamBuffer::read_uint64. // static void sbwrite_uint64(std::ostream *s, uint64_t v) { s->write((const char *)&v, 8); } // This encoding can be read by StreamBuffer::read_string. // static void sbwrite_string(std::ostream *s, std::string_view sv) { s->put('\xFF'); sbwrite_uint64(s, sv.size()); s->write(sv.data(), sv.size()); } // This encoding can be read by StreamBuffer::read_string. // static bool sbwrite_file(std::ostream *s, const std::filesystem::path &fn) { s->put('\xFF'); uint64_t pos1 = s->tellp(); sbwrite_uint64(s, 0); uint64_t pos2 = s->tellp(); std::ifstream t(fn); if (t.fail()) { return false; } *s << t.rdbuf(); if (t.fail()) { return false; } uint64_t pos3 = s->tellp(); s->seekp(pos1); sbwrite_uint64(s, pos3 - pos2); s->seekp(pos3); return true; } std::string package_lua_source(const std::filesystem::path &base, std::ostream *s) { std::string err; std::filesystem::path cfn = base / "lua/control.lst"; std::string ctrl = read_file(cfn, err); if (!err.empty()) { return err; } std::vector names = parse_control_lst(ctrl); sbwrite_uint32(s, names.size()); for (int i = 0; i < int(names.size()); i++) { sbwrite_string(s, names[i]); std::filesystem::path lfn = base / "lua" / names[i]; if (!sbwrite_file(s, lfn)) { return std::string("Cannot read source file: ") + lfn.string(); } } return ""; } } // namespace drvutil // Include the system-dependent part of drvutil. #if defined(__linux__) #include "drvutil-linux.cpp" #elif defined(_WIN32) #include "drvutil-windows.cpp" #else #error "Only support __linux__ or _WIN32" #endif