2023-02-14 13:14:18 -05:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// DRIVER_UTIL
|
|
|
|
|
//
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef DRVUTIL_HPP
|
|
|
|
|
#define DRVUTIL_HPP
|
|
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <string_view>
|
|
|
|
|
#include <ostream>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <algorithm>
|
2023-05-10 15:24:47 -04:00
|
|
|
#include <filesystem>
|
2023-02-14 13:14:18 -05:00
|
|
|
|
|
|
|
|
namespace drvutil {
|
|
|
|
|
|
|
|
|
|
// Read the lua source from disk into an ostringstream.
|
|
|
|
|
//
|
|
|
|
|
// To pass the lua source into the DLL, here is what you do: Construct an
|
|
|
|
|
// ostringstream. Use package_lua_source to package all the lua source into
|
|
|
|
|
// the ostringstream. Fetch the packaged source code using ostringstream::str.
|
|
|
|
|
// Pass the packaged source code into drv_set_lua_source.
|
|
|
|
|
//
|
|
|
|
|
// The DLL must then decode the source package. Here is how it does that:
|
|
|
|
|
// It creates a StreamBuffer from the packaged up source. Then it must
|
|
|
|
|
// call these StreamBuffer methods:
|
|
|
|
|
//
|
|
|
|
|
// - read the number of source files using read_uint32.
|
|
|
|
|
// - for each file, read the filename using read_string.
|
|
|
|
|
// - for each file, read the contents using read_string.
|
|
|
|
|
//
|
|
|
|
|
// If package_lua_source encounters an error reading the source code, then it
|
|
|
|
|
// returns an error message. In this case, the ostream contains garbage. If
|
|
|
|
|
// there is no error, returns the empty string.
|
|
|
|
|
//
|
2023-05-10 15:24:47 -04:00
|
|
|
std::string package_lua_source(const std::filesystem::path &base, std::ostream *oss);
|
2023-02-14 13:14:18 -05:00
|
|
|
|
|
|
|
|
// Parse a target designation.
|
|
|
|
|
//
|
|
|
|
|
// A target consists of 'cert::host::port'.
|
|
|
|
|
//
|
|
|
|
|
void split_target(std::string_view target, std::string &cert, std::string &host, std::string &port);
|
|
|
|
|
|
2023-05-19 00:23:23 -04:00
|
|
|
// Return true if the unicode codepoint can be converted to a single 16-bit wchar_t.
|
|
|
|
|
//
|
|
|
|
|
bool is_single_wchar_t(char32_t c);
|
|
|
|
|
|
|
|
|
|
// Convert a codepoint string into a UTF8-string.
|
|
|
|
|
// If the codepoint string contains invalid codepoints, they're silently dropped.
|
|
|
|
|
//
|
2023-05-30 23:35:54 -04:00
|
|
|
std::string utf32_to_utf8(const std::u32string &cps);
|
2023-05-19 00:23:23 -04:00
|
|
|
|
2023-06-01 20:25:24 -04:00
|
|
|
// Convert a UTF8 string to a UTF32 string.
|
2023-05-19 00:23:23 -04:00
|
|
|
//
|
|
|
|
|
// If the UTF8 string contains invalid sequences, they're silently dropped.
|
|
|
|
|
// Some of the bytes may not be consumed, if the source ends with an unfinished
|
|
|
|
|
// utf-8 sequence. Returns the Codepoint string and the number of bytes consumed.
|
|
|
|
|
//
|
2023-05-30 23:35:54 -04:00
|
|
|
std::u32string utf8_to_utf32(std::string_view source, int *consumed);
|
2023-05-19 00:23:23 -04:00
|
|
|
|
2023-05-30 22:36:26 -04:00
|
|
|
// Convert a UTF8 string to a UCS-2 string.
|
|
|
|
|
//
|
2023-05-30 23:35:54 -04:00
|
|
|
// If the UTF8 string contains invalid sequences, they're silently dropped.
|
|
|
|
|
// Some of the bytes may not be consumed, if the source ends with an unfinished
|
|
|
|
|
// utf-8 sequence. Returns the UCS-2 string and the number of bytes consumed.
|
|
|
|
|
// Of course, UCS-2 can't represent all of unicode, so this is lossy.
|
|
|
|
|
// Any character that can't be represented is replaced with a box.
|
|
|
|
|
//
|
2023-05-30 22:36:26 -04:00
|
|
|
std::u16string utf8_to_ucs2(std::string_view source, int *consumed);
|
|
|
|
|
|
2023-06-01 20:25:24 -04:00
|
|
|
// Convert a UTF16 string to a UTF8 string.
|
|
|
|
|
//
|
|
|
|
|
// If the UTF16 string contains invalid sequences, they're silently dropped.
|
|
|
|
|
//
|
|
|
|
|
std::string utf16_to_utf8(std::u16string_view source);
|
|
|
|
|
|
2023-02-14 13:14:18 -05:00
|
|
|
// Get a system error message, in an OS-independent manner.
|
|
|
|
|
//
|
|
|
|
|
// These versions of strerror is thread-safe, and it never fails
|
|
|
|
|
// to put a message into the buffer.
|
|
|
|
|
//
|
|
|
|
|
void strerror_safe(int errnum, char result[256]);
|
|
|
|
|
std::string strerror_str(int errnum);
|
|
|
|
|
|
|
|
|
|
// Get the amount of time elapsed since program start.
|
|
|
|
|
//
|
|
|
|
|
// This is guaranteed to be monotonically increasing. It is not
|
|
|
|
|
// guaranteed to be accurate. Error could gradually accumulate over
|
|
|
|
|
// time.
|
|
|
|
|
//
|
|
|
|
|
double get_monotonic_clock();
|
|
|
|
|
|
|
|
|
|
// drvutil::ostringstream
|
|
|
|
|
//
|
|
|
|
|
// This is a variant of ostringstream in which it is possible
|
|
|
|
|
// to get the contents without copying. To get the contents
|
|
|
|
|
// without copying, use oss.size() and oss.c_str()
|
|
|
|
|
//
|
|
|
|
|
class ostringstream : public std::ostringstream {
|
2023-03-05 01:51:25 -05:00
|
|
|
class rstringbuf : public std::basic_stringbuf<char_type, traits_type, allocator_type> {
|
2023-02-14 13:14:18 -05:00
|
|
|
public:
|
2023-03-05 01:51:25 -05:00
|
|
|
char *eback() const { return std::streambuf::eback(); }
|
|
|
|
|
char *pptr() const { return std::streambuf::pptr(); }
|
2023-02-14 13:14:18 -05:00
|
|
|
};
|
2023-03-05 01:51:25 -05:00
|
|
|
rstringbuf rstringbuf_;
|
2023-02-14 13:14:18 -05:00
|
|
|
public:
|
|
|
|
|
ostringstream() {
|
2023-03-05 01:51:25 -05:00
|
|
|
std::basic_ostream<char>::rdbuf(&rstringbuf_);
|
2023-02-14 13:14:18 -05:00
|
|
|
}
|
2023-03-05 01:51:25 -05:00
|
|
|
std::string_view view() const {
|
|
|
|
|
char *p = rstringbuf_.eback();
|
|
|
|
|
size_t size = rstringbuf_.pptr() - p;
|
|
|
|
|
return std::string_view(p, size);
|
2023-02-14 13:14:18 -05:00
|
|
|
}
|
2023-03-05 01:51:25 -05:00
|
|
|
std::string str() const {
|
|
|
|
|
return rstringbuf_.str();
|
2023-02-14 13:14:18 -05:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-05 01:51:25 -05:00
|
|
|
|
2023-02-14 13:14:18 -05:00
|
|
|
// Remove items from a vector that are marked for deletion.
|
|
|
|
|
//
|
|
|
|
|
template<class T>
|
|
|
|
|
void remove_marked_items(T &vec) {
|
|
|
|
|
auto iter = std::partition(vec.begin(), vec.end(), [] (const auto &x) { return !x.marked_for_deletion(); });
|
|
|
|
|
vec.erase(iter, vec.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace drvutil
|
|
|
|
|
|
|
|
|
|
#endif // DRVUTIL_HPP
|