liberty/tools/lxdrgen-cpp-posix.cpp
Přemysl Eric Janouch 2edc9c6fd1
Add a C++ backend for LibertyXDR
Also change the C backend so that it also de/serializes
unions without any other fields besides the tag.
2023-07-07 16:43:52 +02:00

68 lines
1.7 KiB
C++

// lxdrgen-cpp-posix.cpp: POSIX support code for lxdrgen-cpp.awk.
//
// Copyright (c) 2023, Přemysl Eric Janouch <p@janouch.name>
// SPDX-License-Identifier: 0BSD
#include <iconv.h>
#include <cstdint>
#include <string>
// Various BSD derivatives may have a problem here.
// Linux defines __STDC_ISO_10646__, but also supports "WCHAR_T".
#ifdef APPLE
#define ICONV_WCHAR "UTF-32"
#else
#define ICONV_WCHAR "WCHAR_T"
#endif
namespace LibertyXDR {
bool utf8_to_wstring(const uint8_t *utf8, size_t length, std::wstring &wide) {
iconv_t conv = iconv_open(ICONV_WCHAR, "UTF-8");
if (conv == (iconv_t) -1)
return false;
wchar_t buffer[1024] = {};
char *start = (char *) buffer, *out = start, *in = (char *) utf8;
size_t available = sizeof buffer;
wide.clear();
while (iconv(conv, &in, &length, &out, &available) == (size_t) -1) {
if (errno != E2BIG) {
iconv_close(conv);
return false;
}
wide.append(buffer, (out - start) / sizeof *buffer);
out = start;
available = sizeof buffer;
}
wide.append(buffer, (out - start) / sizeof *buffer);
iconv_close(conv);
return true;
}
bool wstring_to_utf8(const std::wstring &wide, std::string &utf8) {
iconv_t conv = iconv_open("UTF-8", ICONV_WCHAR);
if (conv == (iconv_t) -1)
return false;
char buffer[1024] = {}, *out = buffer, *in = (char *) wide.data();
size_t available = sizeof buffer, length = wide.size() * sizeof wide[0];
utf8.clear();
while (iconv(conv, &in, &length, &out, &available) == (size_t) -1) {
if (errno != E2BIG) {
iconv_close(conv);
return false;
}
utf8.append(buffer, out - buffer);
out = buffer;
available = sizeof buffer;
}
utf8.append(buffer, out - buffer);
iconv_close(conv);
return true;
}
} // namespace LibertyXDR