This commit is contained in:
2026-03-25 14:14:07 +01:00
parent d6b31e2ef7
commit a0073b4fb1
10368 changed files with 2214340 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,72 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
# This script uses the database of mimetypes distributed here: https://github.com/jshttp/mime-db
# to produce the X-header file mimetypes.inc
import os
import argparse
CRC32_POLY = 0xEDB88320
CRC32C_POLY = 0x82F63B78
CRC64_XZ_POLY = 0xC96C5795D7870F42
CRC64_NVME_POLY = 0x9A6C9329AC4BC9B5
LICENSE_HEADER = """// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>"""
def write_crc32_table(f, name, poly):
f.write(f'static const uint32_t {name}[256] = {{')
for i in range(0, 256):
value = i
for j in range(0, 8):
value = (value >> 1) ^ (poly if value & 1 else 0)
if i % 6 == 0:
f.write('\n ')
f.write(f' 0x{value:08X}u,')
f.write('\n};\n\n')
def write_crc64_tables(f, name, poly):
for table in range(0, 16):
count = table * 8 + 8
f.write(f'static const uint64_t {name}{table}[256] = {{')
for i in range(0, 256):
value = i
for j in range(0, count):
value = (value >> 1) ^ (poly if value & 1 else 0)
if i % 4 == 0:
f.write('\n ')
f.write(f' 0x{value:016X}ull,')
f.write('\n};\n')
f.write('\n')
if __name__ == "__main__":
parser = argparse.ArgumentParser(description = 'Update CRC tables header file')
parser.add_argument('-O', '--output_file', dest = 'output_file', action = 'store', help = 'Output file')
args = parser.parse_args()
if args.output_file is None:
output_file = os.path.join(os.path.dirname(__file__), 'crc.inc')
else:
output_file = args.output_file
with open(output_file, 'w') as f:
f.write(f'''{LICENSE_HEADER}
// This file is autogenerated by crc_gen.py
namespace K {{
''')
write_crc32_table(f, 'Crc32Table', CRC32_POLY)
write_crc32_table(f, 'Crc32CTable', CRC32C_POLY)
write_crc64_tables(f, 'Crc64XzTable', CRC64_XZ_POLY)
write_crc64_tables(f, 'Crc64NvmeTable', CRC64_NVME_POLY)
f.write('}\n')

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
# This script uses the database of mimetypes distributed here: https://github.com/jshttp/mime-db
# to produce the X-header file mimetypes.inc
import os
import argparse
import json
if __name__ == "__main__":
parser = argparse.ArgumentParser(description = 'Update mimetypes include file')
parser.add_argument('-O', '--output_file', dest = 'output_file', action = 'store', help = 'Output file')
parser.add_argument('json', help = 'Source JSON database')
args = parser.parse_args()
if args.output_file is None:
output_file = os.path.join(os.path.dirname(__file__), 'mimetypes.inc')
else:
output_file = args.output_file
with open(args.json) as f:
db = json.load(f)
extensions = {}
for (k, v) in db.items():
if 'extensions' not in v:
continue
for ext in v['extensions']:
if not ext in extensions:
extensions[ext] = 'application/x-'
if extensions[ext].startswith('application/x-'):
extensions[ext] = k
extensions = [(k, extensions[k]) for k in sorted(extensions.keys())]
extensions.sort()
with open(output_file) as f:
lines = f.readlines()
with open(output_file, 'w') as f:
for line in lines:
if not line.startswith('//'):
break
f.write(line)
print('', file = f)
print('#if !defined(MIMETYPE)', file = f)
print(' #error Please define MIMETYPE() before including mimetypes.inc', file = f)
print('#endif', file = f)
print('', file = f)
for k, v in extensions:
print(f'MIMETYPE(".{k}", "{v}")', file = f)
print('', file = f)
print('#undef MIMETYPE', file = f)

View File

@@ -0,0 +1,821 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
#include "base.hh"
#include "tower.hh"
#if defined(_WIN32)
#if !defined(NOMINMAX)
#define NOMINMAX
#endif
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#define SECURITY_WIN32
#include <windows.h>
#include <security.h>
#else
#include <fcntl.h>
#include <poll.h>
#include <sys/socket.h>
#endif
namespace K {
#if defined(_WIN32)
struct OverlappedPipe {
OVERLAPPED ov = {};
HANDLE h = nullptr;
uint8_t buf[1024];
~OverlappedPipe();
};
OverlappedPipe::~OverlappedPipe()
{
if (h) {
CancelIo(h);
CloseHandle(h);
}
if (ov.hEvent) {
CloseHandle(ov.hEvent);
}
}
static bool CheckPipePath(const char *path)
{
if (!StartsWith(path, "\\\\.\\pipe\\")) {
LogError("Control pipe names must start with '%1'", "\\\\.\\pipe\\");
return false;
}
if (!path[9]) {
LogError("Truncated control pipe name '%1'", path);
return false;
}
return true;
}
static OverlappedPipe *BindPipe(const char *path)
{
OverlappedPipe *pipe = new OverlappedPipe();
K_DEFER_N(err_guard) { delete pipe; };
pipe->ov.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
if (!pipe->ov.hEvent) {
LogError("Failed to create event: %1", GetWin32ErrorString());
return nullptr;
}
pipe->h = CreateNamedPipeA(path, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 8192, 8192, 0, nullptr);
if (pipe->h == INVALID_HANDLE_VALUE) {
pipe->h = nullptr;
LogError("Failed to create named control pipe: %1", GetWin32ErrorString());
return nullptr;
}
if (ConnectNamedPipe(pipe->h, &pipe->ov) || GetLastError() == ERROR_PIPE_CONNECTED) {
SetEvent(pipe->ov.hEvent);
} else if (GetLastError() != ERROR_IO_PENDING) {
LogError("Failed to connect to named pipe: %1", GetWin32ErrorString());
return nullptr;
}
err_guard.Disable();
return pipe;
}
static OverlappedPipe *ConnectPipe(const char *path)
{
OverlappedPipe *pipe = new OverlappedPipe();
K_DEFER_N(err_guard) { delete pipe; };
pipe->ov.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
if (!pipe->ov.hEvent) {
LogError("Failed to create event: %1", GetWin32ErrorString());
return nullptr;
}
for (int i = 0; i < 10; i++) {
if (!WaitNamedPipeA(path, 10))
continue;
pipe->h = CreateFileA(path, GENERIC_READ | GENERIC_WRITE,
0, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
if (pipe->h != INVALID_HANDLE_VALUE)
break;
pipe->h = nullptr;
if (GetLastError() != ERROR_PIPE_BUSY) {
LogError("Failed to connect to named pipe: %1", GetWin32ErrorString());
return nullptr;
}
}
if (!pipe->h) {
LogError("Failed to connect to named pipe: %1", GetWin32ErrorString());
return nullptr;
}
err_guard.Disable();
return pipe;
}
// Does not print errors
static bool StartRead(OverlappedPipe *pipe)
{
ResetEvent(pipe->ov.hEvent);
if (!::ReadFile(pipe->h, pipe->buf, K_SIZE(pipe->buf), nullptr, &pipe->ov) &&
GetLastError() != ERROR_IO_PENDING)
return false;
return true;
}
// Does not print errors
static Size FinalizeRead(OverlappedPipe *pipe)
{
DWORD len = 0;
if (!GetOverlappedResult(pipe->h, &pipe->ov, &len, TRUE))
return -1;
return len;
}
// Does not print errors
static Size ReadSync(OverlappedPipe *pipe, void *buf, Size buf_len, int timeout)
{
DWORD len = 0;
if (!::ReadFile(pipe->h, buf, (DWORD)buf_len, nullptr, &pipe->ov) &&
GetLastError() != ERROR_IO_PENDING)
return -1;
if (timeout > 0)
WaitForSingleObject(pipe->ov.hEvent, timeout);
if (!GetOverlappedResult(pipe->h, &pipe->ov, &len, timeout < 0) &&
GetLastError() != ERROR_IO_INCOMPLETE)
return -1;
return (Size)len;
}
// Does not print errors
static Size WriteSync(OverlappedPipe *pipe, const void *buf, Size buf_len)
{
OVERLAPPED ov = {};
DWORD written = 0;
if (!::WriteFile(pipe->h, buf, (DWORD)buf_len, nullptr, &ov) &&
GetLastError() != ERROR_IO_PENDING)
return -1;
if (!GetOverlappedResult(pipe->h, &ov, &written, TRUE))
return -1;
return (Size)written;
}
bool TowerServer::Bind(const char *path)
{
K_ASSERT(!name[0]);
K_ASSERT(!pipes.len);
K_DEFER_N(err_guard) { Stop(); };
if (!CheckPipePath(path))
return false;
if (!CopyString(path, name)) {
LogError("Control pipe name '%1' is too long", path);
return false;
}
OverlappedPipe *pipe = BindPipe(path);
if (!pipe)
return false;
pipes.Append(pipe);
err_guard.Disable();
return true;
}
void TowerServer::Start(std::function<bool(StreamReader *, StreamWriter *)> func)
{
K_ASSERT(pipes.len == 1);
K_ASSERT(!sources.len);
K_ASSERT(!handle_func);
sources.Append({ pipes[0]->ov.hEvent, -1 });
handle_func = func;
}
void TowerServer::Stop()
{
for (OverlappedPipe *pipe: pipes) {
delete pipe;
}
pipes.Clear();
sources.Clear();
MemSet(name, 0, K_SIZE(name));
handle_func = {};
}
static bool IsSignaled(HANDLE h)
{
DWORD ret = WaitForSingleObject(h, 0);
return ret == WAIT_OBJECT_0;
}
bool TowerServer::Process(uint64_t ready)
{
// Accept new clients
if (ready & 1) {
OverlappedPipe *client = pipes[0];
if (IsSignaled(client->ov.hEvent)) {
OverlappedPipe *pipe = BindPipe(name);
// We're kind of screwed if this happens, let the caller know and fail hard
if (!pipe) {
sources.len = 0;
return false;
}
pipes[0] = pipe;
sources[0].handle = pipe->ov.hEvent;
if (pipes.Available()) [[likely]] {
if (FinalizeRead(client) == 0 && StartRead(client)) {
pipes.Append(client);
sources.Append({ client->ov.hEvent, -1 });
LogDebug("Client has connected");
} else {
LogError("Failed to accept client: %1", GetWin32ErrorString());
delete client;
}
} else {
LogError("Too many connections, refusing new client");
delete client;
}
}
}
RunClients([&](Size idx, OverlappedPipe *pipe) {
if (!(ready & (1ull << idx)))
return true;
Span<uint8_t> buf = MakeSpan(pipe->buf, FinalizeRead(pipe));
if (buf.len < 0) {
LogDebug("Client has disconnected");
return false;
}
const auto read = [&](Span<uint8_t> out_buf) {
if (buf.len) {
Size copy_len = std::min(buf.len, out_buf.len);
MemCpy(out_buf.ptr, buf.ptr, copy_len);
buf.ptr += copy_len;
buf.len -= copy_len;
return copy_len;
}
Size received = ReadSync(pipe, out_buf.ptr, out_buf.len, 1000);
if (received < 0) {
LogError("Failed to receive data from client: %1", GetWin32ErrorString());
} else if (!received) {
LogError("Client has timed out");
received = -1;
}
return received;
};
const auto write = [&](Span<const uint8_t> buf) {
while (buf.len) {
Size sent = WriteSync(pipe, buf.ptr, buf.len);
if (sent < 0) {
LogError("Failed to send data to server: %1", GetWin32ErrorString());
return false;
}
buf.ptr += sent;
buf.len -= sent;
}
return true;
};
StreamReader reader(read, "<client>");
StreamWriter writer(write, "<client>");
if (!handle_func(&reader, &writer))
return false;
if (!reader.Close())
return false;
if (!writer.Close())
return false;
if (!StartRead(pipe)) {
LogDebug("Client has disconnected");
return false;
}
return true;
});
return true;
}
void TowerServer::Send(FunctionRef<void(StreamWriter *)> func)
{
RunClients([&](Size, OverlappedPipe *pipe) {
const auto write = [&](Span<const uint8_t> buf) {
while (buf.len) {
Size sent = WriteSync(pipe, buf.ptr, buf.len);
if (sent < 0) {
LogError("Failed to send data to server: %1", GetWin32ErrorString());
return false;
}
buf.ptr += sent;
buf.len -= sent;
}
return true;
};
StreamWriter writer(write, "<client>");
func(&writer);
return writer.Close();
});
}
void TowerServer::RunClients(FunctionRef<bool(Size, OverlappedPipe *)> func)
{
Size j = 1;
for (Size i = 1; i < pipes.len; i++) {
OverlappedPipe *pipe = pipes[i];
pipes[j] = pipe;
sources[j].handle = pipe->ov.hEvent;
if (!func(i, pipe)) {
delete pipe;
continue;
}
j++;
}
pipes.len = j;
sources.len = j;
}
bool TowerClient::Connect(const char *path)
{
Stop();
K_DEFER_N(err_guard) { Stop(); };
if (!CheckPipePath(path))
return false;
pipe = ConnectPipe(path);
if (!pipe)
return false;
if (!StartRead(pipe)) {
LogError("Failed to connect to named pipe: %1", GetWin32ErrorString());
return false;
}
err_guard.Disable();
return true;
}
void TowerClient::Start(std::function<void(StreamReader *)> func)
{
K_ASSERT(pipe);
K_ASSERT(!handle_func);
src = { pipe->ov.hEvent, -1 };
handle_func = func;
}
void TowerClient::Stop()
{
if (pipe) {
delete pipe;
pipe = nullptr;
}
handle_func = {};
}
bool TowerClient::Process()
{
if (!IsSignaled(pipe->ov.hEvent))
return true;
Span<uint8_t> buf = MakeSpan(pipe->buf, FinalizeRead(pipe));
if (buf.len < 0) {
LogError("Lost connection to server");
return false;
}
const auto read = [&](Span<uint8_t> out_buf) {
if (buf.len) {
Size copy_len = std::min(buf.len, out_buf.len);
MemCpy(out_buf.ptr, buf.ptr, copy_len);
buf.ptr += copy_len;
buf.len -= copy_len;
return copy_len;
}
Size received = ReadSync(pipe, out_buf.ptr, out_buf.len, -1);
if (received < 0) {
LogError("Failed to receive data from server: %1", strerror(errno));
}
return received;
};
StreamReader reader(read, "<client>");
handle_func(&reader);
if (!reader.Close())
return false;
if (!StartRead(pipe)) {
LogError("Lost connection to server");
return false;
}
return true;
}
bool TowerClient::Send(FunctionRef<void(StreamWriter *)> func)
{
const auto write = [&](Span<const uint8_t> buf) {
while (buf.len) {
Size sent = WriteSync(pipe, buf.ptr, buf.len);
if (sent < 0) {
LogError("Failed to send data to server: %1", GetWin32ErrorString());
return false;
}
buf.ptr += sent;
buf.len -= sent;
}
return true;
};
StreamWriter writer(write, "<server>");
func(&writer);
return writer.Close();
}
const char *GetControlSocketPath(ControlScope scope, const char *name, Allocator *alloc)
{
K_ASSERT(strlen(name) < 64);
switch (scope) {
case ControlScope::System: return Fmt(alloc, "\\\\.\\pipe\\tower\\system\\%1", name).ptr;
case ControlScope::User: {
char buf[128] = {};
ULONG size = K_SIZE(buf);
BOOL success = GetUserNameExA(NameUniqueId, buf, &size);
K_CRITICAL(success, "Failed to get user name");
Span<const char> uuid = MakeSpan(buf, size);
return Fmt(alloc, "\\\\.\\pipe\\tower\\%1\\%2", TrimStr(uuid, "{}"), name).ptr;
} break;
}
K_UNREACHABLE();
}
#else
bool TowerServer::Bind(const char *path)
{
K_ASSERT(fd < 0);
K_DEFER_N(err_guard) { Stop(); };
fd = CreateSocket(SocketType::Unix, SOCK_STREAM);
if (fd < 0)
return false;
SetDescriptorNonBlock(fd, true);
if (!BindUnixSocket(fd, path))
return false;
if (listen(fd, 4) < 0) {
LogError("listen() failed: %1", strerror(errno));
return false;
}
err_guard.Disable();
return true;
}
void TowerServer::Start(std::function<bool(StreamReader *, StreamWriter *)> func)
{
K_ASSERT(fd >= 0);
K_ASSERT(!handle_func);
sources.Append({ fd, -1 });
handle_func = func;
}
void TowerServer::Stop()
{
if (fd >= 0) {
CloseDescriptor(fd);
fd = -1;
}
for (Size i = 1; i < sources.len; i++) {
CloseDescriptor(sources[i].fd);
}
sources.Clear();
handle_func = {};
}
static bool IsReadable(int fd, int timeout)
{
struct pollfd pfd = { fd, POLLIN, 0 };
if (poll(&pfd, 1, timeout) < 0)
return true;
if (pfd.revents)
return true;
return false;
}
bool TowerServer::Process(uint64_t ready)
{
// Accept new clients
if (ready & 1) {
#if defined(SOCK_CLOEXEC)
int sock = accept4(fd, nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);
#else
int sock = accept(fd, nullptr, nullptr);
#endif
if (sock >= 0) {
#if !defined(SOCK_CLOEXEC)
fcntl(sock, F_SETFD, FD_CLOEXEC);
#endif
#if !defined(MSG_DONTWAIT)
SetDescriptorNonBlock(sock, true);
#endif
if (sources.Available()) [[likely]] {
sources.Append({ sock, -1 });
LogDebug("Client has connected");
} else {
LogError("Too many connections, refusing new client");
CloseDescriptor(sock);
}
} else if (errno != EAGAIN) {
LogError("Failed to accept client: %1", strerror(errno));
}
}
RunClients([&](Size idx, int sock) {
if (!(ready & (1ull << idx)))
return true;
// Handle disconnection and errors first
{
struct pollfd pfd = { sock, POLLIN, 0 };
K_IGNORE poll(&pfd, 1, 1000);
if (pfd.revents & (POLLHUP | POLLERR)) {
LogDebug("Client has disconnected");
return false;
}
}
const auto read = [&](Span<uint8_t> out_buf) {
Size received = recv(sock, out_buf.ptr, out_buf.len, 0);
if (received < 0) {
if (errno == EAGAIN) {
if (IsReadable(sock, 1000)) {
received = recv(sock, out_buf.ptr, out_buf.len, 0);
} else {
LogError("Client has timed out");
}
} else {
LogError("Failed to receive data from client: %1", strerror(errno));
}
}
return received;
};
const auto write = [&](Span<const uint8_t> buf) {
while (buf.len) {
Size sent = send(sock, buf.ptr, (size_t)buf.len, 0);
if (sent < 0) {
LogError("Failed to send data to server: %1", strerror(errno));
return false;
}
buf.ptr += sent;
buf.len -= sent;
}
return true;
};
StreamReader reader(read, "<client>");
StreamWriter writer(write, "<client>");
if (!handle_func(&reader, &writer))
return false;
if (!reader.Close())
return false;
if (!writer.Close())
return false;
return true;
});
return true;
}
void TowerServer::Send(FunctionRef<void(StreamWriter *)> func)
{
RunClients([&](Size, int sock) {
const auto write = [&](Span<const uint8_t> buf) {
while (buf.len) {
Size sent = send(sock, buf.ptr, (size_t)buf.len, 0);
if (sent < 0) {
LogError("Failed to send data to server: %1", strerror(errno));
return false;
}
buf.ptr += sent;
buf.len -= sent;
}
return true;
};
StreamWriter writer(write, "<client>");
func(&writer);
return writer.Close();
});
}
void TowerServer::RunClients(FunctionRef<bool(Size, int)> func)
{
Size j = 1;
for (Size i = 1; i < sources.len; i++) {
const WaitSource &src = sources[i];
sources[j] = src;
if (!func(i, src.fd)) {
close(src.fd);
continue;
}
j++;
}
sources.len = j;
}
bool TowerClient::Connect(const char *path)
{
Stop();
K_DEFER_N(err_guard) { Stop(); };
sock = CreateSocket(SocketType::Unix, SOCK_STREAM);
if (sock < 0)
return false;
if (!ConnectUnixSocket(sock, path))
return false;
err_guard.Disable();
return true;
}
void TowerClient::Start(std::function<void(StreamReader *)> func)
{
K_ASSERT(sock >= 0);
K_ASSERT(!handle_func);
src = { sock, -1 };
handle_func = func;
}
void TowerClient::Stop()
{
CloseDescriptor(sock);
sock = -1;
handle_func = {};
}
bool TowerClient::Process()
{
// We need to poll because StreamReader does not support non-blocking reads,
// so make sure there's data on the other end. The caller probably knows and may
// have skipped the call to Process but we don't want to enforce this; Process()
// should work and do nothing if there's nothing to do.
if (!IsReadable(sock, 0))
return true;
const auto read = [&](Span<uint8_t> out_buf) {
Size received = recv(sock, out_buf.ptr, out_buf.len, 0);
if (received < 0) {
LogError("Failed to receive data from server: %1", strerror(errno));
}
return received;
};
StreamReader reader(read, "<client>");
handle_func(&reader);
return reader.Close();
}
bool TowerClient::Send(FunctionRef<void(StreamWriter *)> func)
{
const auto write = [&](Span<const uint8_t> buf) {
while (buf.len) {
Size sent = send(sock, buf.ptr, (size_t)buf.len, 0);
if (sent < 0) {
LogError("Failed to send data to server: %1", strerror(errno));
return false;
}
buf.ptr += sent;
buf.len -= sent;
}
return true;
};
StreamWriter writer(write, "<server>");
func(&writer);
return writer.Close();
}
const char *GetControlSocketPath(ControlScope scope, const char *name, Allocator *alloc)
{
K_ASSERT(strlen(name) < 64);
switch (scope) {
case ControlScope::System: {
const char *prefix = TestFile("/run", FileType::Directory) ? "/run" : "/var/run";
return Fmt(alloc, "%1/%2.sock", prefix, name).ptr;
} break;
case ControlScope::User: {
const char *xdg = GetEnv("XDG_RUNTIME_DIR");
const char *path = nullptr;
if (xdg) {
path = Fmt(alloc, "%1/%2.sock", xdg, name).ptr;
} else {
const char *prefix = TestFile("/run", FileType::Directory) ? "/run" : "/var/run";
uid_t uid = getuid();
path = Fmt(alloc, "%1/%2/%3.sock", prefix, uid, name).ptr;
}
// Best effort
EnsureDirectoryExists(path);
return path;
} break;
}
K_UNREACHABLE();
}
#endif
}

View File

@@ -0,0 +1,81 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
#pragma once
#include "lib/native/base/base.hh"
#include "lib/native/wrap/json.hh"
namespace K {
static const int MaxTowerSources = 10;
class TowerServer {
#if defined(_WIN32)
char name[512] = {};
LocalArray<struct OverlappedPipe *, MaxTowerSources> pipes;
#else
int fd = -1;
#endif
LocalArray<WaitSource, MaxTowerSources> sources;
std::function<bool(StreamReader *, StreamWriter *)> handle_func;
public:
TowerServer() {}
~TowerServer() { Stop(); }
bool Bind(const char *path);
void Start(std::function<bool(StreamReader *, StreamWriter *)> func);
void Stop();
Span<const WaitSource> GetWaitSources() const { return sources; }
bool Process(uint64_t ready = UINT64_MAX);
void Send(FunctionRef<void(StreamWriter *)> func);
void Send(Span<const uint8_t> buf) { Send([&](StreamWriter *writer) { writer->Write(buf); }); }
void Send(Span<const char> buf) { Send([&](StreamWriter *writer) { writer->Write(buf); }); }
private:
#if defined(_WIN32)
void RunClients(FunctionRef<bool(Size, struct OverlappedPipe *)> func);
#else
void RunClients(FunctionRef<bool(Size, int)> func);
#endif
};
class TowerClient {
#if defined(_WIN32)
struct OverlappedPipe *pipe = nullptr;
#else
int sock = -1;
#endif
std::function<void(StreamReader *)> handle_func;
WaitSource src = {};
public:
~TowerClient() { Stop(); }
bool Connect(const char *path);
void Start(std::function<void(StreamReader *)> func);
void Stop();
WaitSource GetWaitSource() const { return src; }
bool Process();
bool Send(FunctionRef<void(StreamWriter *)> func);
bool Send(Span<const uint8_t> buf) { return Send([&](StreamWriter *writer) { writer->Write(buf); }); }
bool Send(Span<const char> buf) { return Send([&](StreamWriter *writer) { writer->Write(buf); }); }
};
enum class ControlScope {
System,
User
};
const char *GetControlSocketPath(ControlScope scope, const char *name, Allocator *alloc);
}

View File

@@ -0,0 +1,408 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
// This file is autogenerated by unicode_gen.py
// Version: DerivedCoreProperties-16.0.0.txt -- Date: 2024-05-31, 18:09:32 GMT
namespace K {
static const int32_t WcWidthNull[] = {
0x000AD, 0x000AE, 0x00300, 0x00370, 0x00483, 0x0048A, 0x00591, 0x005BE, 0x005BF, 0x005C0,
0x005C1, 0x005C3, 0x005C4, 0x005C6, 0x005C7, 0x005C8, 0x00600, 0x00606, 0x00610, 0x0061B,
0x0061C, 0x0061D, 0x0064B, 0x00660, 0x00670, 0x00671, 0x006D6, 0x006DE, 0x006DF, 0x006E5,
0x006E7, 0x006E9, 0x006EA, 0x006EE, 0x0070F, 0x00710, 0x00711, 0x00712, 0x00730, 0x0074B,
0x007A6, 0x007B1, 0x007EB, 0x007F4, 0x007FD, 0x007FE, 0x00816, 0x0081A, 0x0081B, 0x00824,
0x00825, 0x00828, 0x00829, 0x0082E, 0x00859, 0x0085C, 0x00890, 0x00892, 0x00897, 0x008A0,
0x008CA, 0x00904, 0x0093A, 0x0093D, 0x0093E, 0x00950, 0x00951, 0x00958, 0x00962, 0x00964,
0x00981, 0x00984, 0x009BC, 0x009BD, 0x009BE, 0x009C5, 0x009C7, 0x009C9, 0x009CB, 0x009CE,
0x009D7, 0x009D8, 0x009E2, 0x009E4, 0x009FE, 0x009FF, 0x00A01, 0x00A04, 0x00A3C, 0x00A3D,
0x00A3E, 0x00A43, 0x00A47, 0x00A49, 0x00A4B, 0x00A4E, 0x00A51, 0x00A52, 0x00A70, 0x00A72,
0x00A75, 0x00A76, 0x00A81, 0x00A84, 0x00ABC, 0x00ABD, 0x00ABE, 0x00AC6, 0x00AC7, 0x00ACA,
0x00ACB, 0x00ACE, 0x00AE2, 0x00AE4, 0x00AFA, 0x00B00, 0x00B01, 0x00B04, 0x00B3C, 0x00B3D,
0x00B3E, 0x00B45, 0x00B47, 0x00B49, 0x00B4B, 0x00B4E, 0x00B55, 0x00B58, 0x00B62, 0x00B64,
0x00B82, 0x00B83, 0x00BBE, 0x00BC3, 0x00BC6, 0x00BC9, 0x00BCA, 0x00BCE, 0x00BD7, 0x00BD8,
0x00C00, 0x00C05, 0x00C3C, 0x00C3D, 0x00C3E, 0x00C45, 0x00C46, 0x00C49, 0x00C4A, 0x00C4E,
0x00C55, 0x00C57, 0x00C62, 0x00C64, 0x00C81, 0x00C84, 0x00CBC, 0x00CBD, 0x00CBE, 0x00CC5,
0x00CC6, 0x00CC9, 0x00CCA, 0x00CCE, 0x00CD5, 0x00CD7, 0x00CE2, 0x00CE4, 0x00CF3, 0x00CF4,
0x00D00, 0x00D04, 0x00D3B, 0x00D3D, 0x00D3E, 0x00D45, 0x00D46, 0x00D49, 0x00D4A, 0x00D4E,
0x00D57, 0x00D58, 0x00D62, 0x00D64, 0x00D81, 0x00D84, 0x00DCA, 0x00DCB, 0x00DCF, 0x00DD5,
0x00DD6, 0x00DD7, 0x00DD8, 0x00DE0, 0x00DF2, 0x00DF4, 0x00E31, 0x00E32, 0x00E34, 0x00E3B,
0x00E47, 0x00E4F, 0x00EB1, 0x00EB2, 0x00EB4, 0x00EBD, 0x00EC8, 0x00ECF, 0x00F18, 0x00F1A,
0x00F35, 0x00F36, 0x00F37, 0x00F38, 0x00F39, 0x00F3A, 0x00F3E, 0x00F40, 0x00F71, 0x00F85,
0x00F86, 0x00F88, 0x00F8D, 0x00F98, 0x00F99, 0x00FBD, 0x00FC6, 0x00FC7, 0x0102B, 0x0103F,
0x01056, 0x0105A, 0x0105E, 0x01061, 0x01062, 0x01065, 0x01067, 0x0106E, 0x01071, 0x01075,
0x01082, 0x0108E, 0x0108F, 0x01090, 0x0109A, 0x0109E, 0x0135D, 0x01360, 0x01712, 0x01716,
0x01732, 0x01735, 0x01752, 0x01754, 0x01772, 0x01774, 0x017B4, 0x017D4, 0x017DD, 0x017DE,
0x0180B, 0x01810, 0x01885, 0x01887, 0x018A9, 0x018AA, 0x01920, 0x0192C, 0x01930, 0x0193C,
0x01A17, 0x01A1C, 0x01A55, 0x01A5F, 0x01A60, 0x01A7D, 0x01A7F, 0x01A80, 0x01AB0, 0x01ACF,
0x01B00, 0x01B05, 0x01B34, 0x01B45, 0x01B6B, 0x01B74, 0x01B80, 0x01B83, 0x01BA1, 0x01BAE,
0x01BE6, 0x01BF4, 0x01C24, 0x01C38, 0x01CD0, 0x01CD3, 0x01CD4, 0x01CE9, 0x01CED, 0x01CEE,
0x01CF4, 0x01CF5, 0x01CF7, 0x01CFA, 0x01DC0, 0x01E00, 0x0200B, 0x02010, 0x0202A, 0x0202F,
0x02060, 0x02065, 0x02066, 0x02070, 0x020D0, 0x020F1, 0x02CEF, 0x02CF2, 0x02D7F, 0x02D80,
0x02DE0, 0x02E00, 0x0302A, 0x03030, 0x03099, 0x0309B, 0x0A66F, 0x0A673, 0x0A674, 0x0A67E,
0x0A69E, 0x0A6A0, 0x0A6F0, 0x0A6F2, 0x0A802, 0x0A803, 0x0A806, 0x0A807, 0x0A80B, 0x0A80C,
0x0A823, 0x0A828, 0x0A82C, 0x0A82D, 0x0A880, 0x0A882, 0x0A8B4, 0x0A8C6, 0x0A8E0, 0x0A8F2,
0x0A8FF, 0x0A900, 0x0A926, 0x0A92E, 0x0A947, 0x0A954, 0x0A980, 0x0A984, 0x0A9B3, 0x0A9C1,
0x0A9E5, 0x0A9E6, 0x0AA29, 0x0AA37, 0x0AA43, 0x0AA44, 0x0AA4C, 0x0AA4E, 0x0AA7B, 0x0AA7E,
0x0AAB0, 0x0AAB1, 0x0AAB2, 0x0AAB5, 0x0AAB7, 0x0AAB9, 0x0AABE, 0x0AAC0, 0x0AAC1, 0x0AAC2,
0x0AAEB, 0x0AAF0, 0x0AAF5, 0x0AAF7, 0x0ABE3, 0x0ABEB, 0x0ABEC, 0x0ABEE, 0x0FB1E, 0x0FB1F,
0x0FE00, 0x0FE10, 0x0FE20, 0x0FE30, 0x0FEFF, 0x0FF00, 0x0FFF9, 0x0FFFC, 0x101FD, 0x101FE,
0x102E0, 0x102E1, 0x10376, 0x1037B, 0x10A01, 0x10A04, 0x10A05, 0x10A07, 0x10A0C, 0x10A10,
0x10A38, 0x10A3B, 0x10A3F, 0x10A40, 0x10AE5, 0x10AE7, 0x10D24, 0x10D28, 0x10D69, 0x10D6E,
0x10EAB, 0x10EAD, 0x10EFC, 0x10F00, 0x10F46, 0x10F51, 0x10F82, 0x10F86, 0x11000, 0x11003,
0x11038, 0x11047, 0x11070, 0x11071, 0x11073, 0x11075, 0x1107F, 0x11083, 0x110B0, 0x110BB,
0x110BD, 0x110BE, 0x110C2, 0x110C3, 0x110CD, 0x110CE, 0x11100, 0x11103, 0x11127, 0x11135,
0x11145, 0x11147, 0x11173, 0x11174, 0x11180, 0x11183, 0x111B3, 0x111C1, 0x111C9, 0x111CD,
0x111CE, 0x111D0, 0x1122C, 0x11238, 0x1123E, 0x1123F, 0x11241, 0x11242, 0x112DF, 0x112EB,
0x11300, 0x11304, 0x1133B, 0x1133D, 0x1133E, 0x11345, 0x11347, 0x11349, 0x1134B, 0x1134E,
0x11357, 0x11358, 0x11362, 0x11364, 0x11366, 0x1136D, 0x11370, 0x11375, 0x113B8, 0x113C1,
0x113C2, 0x113C3, 0x113C5, 0x113C6, 0x113C7, 0x113CB, 0x113CC, 0x113D1, 0x113D2, 0x113D3,
0x113E1, 0x113E3, 0x11435, 0x11447, 0x1145E, 0x1145F, 0x114B0, 0x114C4, 0x115AF, 0x115B6,
0x115B8, 0x115C1, 0x115DC, 0x115DE, 0x11630, 0x11641, 0x116AB, 0x116B8, 0x1171D, 0x1172C,
0x1182C, 0x1183B, 0x11930, 0x11936, 0x11937, 0x11939, 0x1193B, 0x1193F, 0x11940, 0x11941,
0x11942, 0x11944, 0x119D1, 0x119D8, 0x119DA, 0x119E1, 0x119E4, 0x119E5, 0x11A01, 0x11A0B,
0x11A33, 0x11A3A, 0x11A3B, 0x11A3F, 0x11A47, 0x11A48, 0x11A51, 0x11A5C, 0x11A8A, 0x11A9A,
0x11C2F, 0x11C37, 0x11C38, 0x11C40, 0x11C92, 0x11CA8, 0x11CA9, 0x11CB7, 0x11D31, 0x11D37,
0x11D3A, 0x11D3B, 0x11D3C, 0x11D3E, 0x11D3F, 0x11D46, 0x11D47, 0x11D48, 0x11D8A, 0x11D8F,
0x11D90, 0x11D92, 0x11D93, 0x11D98, 0x11EF3, 0x11EF7, 0x11F00, 0x11F02, 0x11F03, 0x11F04,
0x11F34, 0x11F3B, 0x11F3E, 0x11F43, 0x11F5A, 0x11F5B, 0x13430, 0x13441, 0x13447, 0x13456,
0x1611E, 0x16130, 0x16AF0, 0x16AF5, 0x16B30, 0x16B37, 0x16F4F, 0x16F50, 0x16F51, 0x16F88,
0x16F8F, 0x16F93, 0x16FE4, 0x16FE5, 0x16FF0, 0x16FF2, 0x1BC9D, 0x1BC9F, 0x1BCA0, 0x1BCA4,
0x1CF00, 0x1CF2E, 0x1CF30, 0x1CF47, 0x1D165, 0x1D16A, 0x1D16D, 0x1D183, 0x1D185, 0x1D18C,
0x1D1AA, 0x1D1AE, 0x1D242, 0x1D245, 0x1DA00, 0x1DA37, 0x1DA3B, 0x1DA6D, 0x1DA75, 0x1DA76,
0x1DA84, 0x1DA85, 0x1DA9B, 0x1DAA0, 0x1DAA1, 0x1DAB0, 0x1E000, 0x1E007, 0x1E008, 0x1E019,
0x1E01B, 0x1E022, 0x1E023, 0x1E025, 0x1E026, 0x1E02B, 0x1E08F, 0x1E090, 0x1E130, 0x1E137,
0x1E2AE, 0x1E2AF, 0x1E2EC, 0x1E2F0, 0x1E4EC, 0x1E4F0, 0x1E5EE, 0x1E5F0, 0x1E8D0, 0x1E8D7,
0x1E944, 0x1E94B, 0xE0001, 0xE0002, 0xE0020, 0xE0080, 0xE0100, 0xE01F0
};
static const int32_t WcWidthWide[] = {
0x01100, 0x01160, 0x0231A, 0x0231C, 0x02329, 0x0232B, 0x023E9, 0x023ED, 0x023F0, 0x023F1,
0x023F3, 0x023F4, 0x025FD, 0x025FF, 0x02614, 0x02616, 0x02630, 0x02638, 0x02648, 0x02654,
0x0267F, 0x02680, 0x0268A, 0x02690, 0x02693, 0x02694, 0x026A1, 0x026A2, 0x026AA, 0x026AC,
0x026BD, 0x026BF, 0x026C4, 0x026C6, 0x026CE, 0x026CF, 0x026D4, 0x026D5, 0x026EA, 0x026EB,
0x026F2, 0x026F4, 0x026F5, 0x026F6, 0x026FA, 0x026FB, 0x026FD, 0x026FE, 0x02705, 0x02706,
0x0270A, 0x0270C, 0x02728, 0x02729, 0x0274C, 0x0274D, 0x0274E, 0x0274F, 0x02753, 0x02756,
0x02757, 0x02758, 0x02795, 0x02798, 0x027B0, 0x027B1, 0x027BF, 0x027C0, 0x02B1B, 0x02B1D,
0x02B50, 0x02B51, 0x02B55, 0x02B56, 0x02E80, 0x02E9A, 0x02E9B, 0x02EF4, 0x02F00, 0x02FD6,
0x02FF0, 0x0302A, 0x03030, 0x0303F, 0x03041, 0x03097, 0x0309B, 0x03100, 0x03105, 0x03130,
0x03131, 0x0318F, 0x03190, 0x031E6, 0x031EF, 0x0321F, 0x03220, 0x03248, 0x03250, 0x0A48D,
0x0A490, 0x0A4C7, 0x0A960, 0x0A97D, 0x0AC00, 0x0D7A4, 0x0F900, 0x0FB00, 0x0FE10, 0x0FE1A,
0x0FE30, 0x0FE53, 0x0FE54, 0x0FE67, 0x0FE68, 0x0FE6C, 0x0FF01, 0x0FF61, 0x0FFE0, 0x0FFE7,
0x16FE0, 0x16FE4, 0x17000, 0x187F8, 0x18800, 0x18CD6, 0x18CFF, 0x18D09, 0x1AFF0, 0x1AFF4,
0x1AFF5, 0x1AFFC, 0x1AFFD, 0x1AFFF, 0x1B000, 0x1B123, 0x1B132, 0x1B133, 0x1B150, 0x1B153,
0x1B155, 0x1B156, 0x1B164, 0x1B168, 0x1B170, 0x1B2FC, 0x1D300, 0x1D357, 0x1D360, 0x1D377,
0x1F004, 0x1F005, 0x1F0CF, 0x1F0D0, 0x1F18E, 0x1F18F, 0x1F191, 0x1F19B, 0x1F200, 0x1F203,
0x1F210, 0x1F23C, 0x1F240, 0x1F249, 0x1F250, 0x1F252, 0x1F260, 0x1F266, 0x1F300, 0x1F321,
0x1F32D, 0x1F336, 0x1F337, 0x1F37D, 0x1F37E, 0x1F394, 0x1F3A0, 0x1F3CB, 0x1F3CF, 0x1F3D4,
0x1F3E0, 0x1F3F1, 0x1F3F4, 0x1F3F5, 0x1F3F8, 0x1F43F, 0x1F440, 0x1F441, 0x1F442, 0x1F4FD,
0x1F4FF, 0x1F53E, 0x1F54B, 0x1F54F, 0x1F550, 0x1F568, 0x1F57A, 0x1F57B, 0x1F595, 0x1F597,
0x1F5A4, 0x1F5A5, 0x1F5FB, 0x1F650, 0x1F680, 0x1F6C6, 0x1F6CC, 0x1F6CD, 0x1F6D0, 0x1F6D3,
0x1F6D5, 0x1F6D8, 0x1F6DC, 0x1F6E0, 0x1F6EB, 0x1F6ED, 0x1F6F4, 0x1F6FD, 0x1F7E0, 0x1F7EC,
0x1F7F0, 0x1F7F1, 0x1F90C, 0x1F93B, 0x1F93C, 0x1F946, 0x1F947, 0x1FA00, 0x1FA70, 0x1FA7D,
0x1FA80, 0x1FA8A, 0x1FA8F, 0x1FAC7, 0x1FACE, 0x1FADD, 0x1FADF, 0x1FAEA, 0x1FAF0, 0x1FAF9,
0x20000, 0x2FFFE, 0x30000, 0x3FFFE
};
static const int32_t XidStartTable[] = {
0x00041, 0x0005B, 0x00061, 0x0007B, 0x000AA, 0x000AB, 0x000B5, 0x000B6, 0x000BA, 0x000BB,
0x000C0, 0x000D7, 0x000D8, 0x000F7, 0x000F8, 0x002C2, 0x002C6, 0x002D2, 0x002E0, 0x002E5,
0x002EC, 0x002ED, 0x002EE, 0x002EF, 0x00370, 0x00375, 0x00376, 0x00378, 0x0037A, 0x0037E,
0x0037F, 0x00380, 0x00386, 0x00387, 0x00388, 0x0038B, 0x0038C, 0x0038D, 0x0038E, 0x003A2,
0x003A3, 0x003F6, 0x003F7, 0x00482, 0x0048A, 0x00530, 0x00531, 0x00557, 0x00559, 0x0055A,
0x00560, 0x00589, 0x005D0, 0x005EB, 0x005EF, 0x005F3, 0x00620, 0x0064B, 0x0066E, 0x00670,
0x00671, 0x006D4, 0x006D5, 0x006D6, 0x006E5, 0x006E7, 0x006EE, 0x006F0, 0x006FA, 0x006FD,
0x006FF, 0x00700, 0x00710, 0x00711, 0x00712, 0x00730, 0x0074D, 0x007A6, 0x007B1, 0x007B2,
0x007CA, 0x007EB, 0x007F4, 0x007F6, 0x007FA, 0x007FB, 0x00800, 0x00816, 0x0081A, 0x0081B,
0x00824, 0x00825, 0x00828, 0x00829, 0x00840, 0x00859, 0x00860, 0x0086B, 0x00870, 0x00888,
0x00889, 0x0088F, 0x008A0, 0x008CA, 0x00904, 0x0093A, 0x0093D, 0x0093E, 0x00950, 0x00951,
0x00958, 0x00962, 0x00971, 0x00981, 0x00985, 0x0098D, 0x0098F, 0x00991, 0x00993, 0x009A9,
0x009AA, 0x009B1, 0x009B2, 0x009B3, 0x009B6, 0x009BA, 0x009BD, 0x009BE, 0x009CE, 0x009CF,
0x009DC, 0x009DE, 0x009DF, 0x009E2, 0x009F0, 0x009F2, 0x009FC, 0x009FD, 0x00A05, 0x00A0B,
0x00A0F, 0x00A11, 0x00A13, 0x00A29, 0x00A2A, 0x00A31, 0x00A32, 0x00A34, 0x00A35, 0x00A37,
0x00A38, 0x00A3A, 0x00A59, 0x00A5D, 0x00A5E, 0x00A5F, 0x00A72, 0x00A75, 0x00A85, 0x00A8E,
0x00A8F, 0x00A92, 0x00A93, 0x00AA9, 0x00AAA, 0x00AB1, 0x00AB2, 0x00AB4, 0x00AB5, 0x00ABA,
0x00ABD, 0x00ABE, 0x00AD0, 0x00AD1, 0x00AE0, 0x00AE2, 0x00AF9, 0x00AFA, 0x00B05, 0x00B0D,
0x00B0F, 0x00B11, 0x00B13, 0x00B29, 0x00B2A, 0x00B31, 0x00B32, 0x00B34, 0x00B35, 0x00B3A,
0x00B3D, 0x00B3E, 0x00B5C, 0x00B5E, 0x00B5F, 0x00B62, 0x00B71, 0x00B72, 0x00B83, 0x00B84,
0x00B85, 0x00B8B, 0x00B8E, 0x00B91, 0x00B92, 0x00B96, 0x00B99, 0x00B9B, 0x00B9C, 0x00B9D,
0x00B9E, 0x00BA0, 0x00BA3, 0x00BA5, 0x00BA8, 0x00BAB, 0x00BAE, 0x00BBA, 0x00BD0, 0x00BD1,
0x00C05, 0x00C0D, 0x00C0E, 0x00C11, 0x00C12, 0x00C29, 0x00C2A, 0x00C3A, 0x00C3D, 0x00C3E,
0x00C58, 0x00C5B, 0x00C5D, 0x00C5E, 0x00C60, 0x00C62, 0x00C80, 0x00C81, 0x00C85, 0x00C8D,
0x00C8E, 0x00C91, 0x00C92, 0x00CA9, 0x00CAA, 0x00CB4, 0x00CB5, 0x00CBA, 0x00CBD, 0x00CBE,
0x00CDD, 0x00CDF, 0x00CE0, 0x00CE2, 0x00CF1, 0x00CF3, 0x00D04, 0x00D0D, 0x00D0E, 0x00D11,
0x00D12, 0x00D3B, 0x00D3D, 0x00D3E, 0x00D4E, 0x00D4F, 0x00D54, 0x00D57, 0x00D5F, 0x00D62,
0x00D7A, 0x00D80, 0x00D85, 0x00D97, 0x00D9A, 0x00DB2, 0x00DB3, 0x00DBC, 0x00DBD, 0x00DBE,
0x00DC0, 0x00DC7, 0x00E01, 0x00E31, 0x00E32, 0x00E34, 0x00E40, 0x00E47, 0x00E81, 0x00E83,
0x00E84, 0x00E85, 0x00E86, 0x00E8B, 0x00E8C, 0x00EA4, 0x00EA5, 0x00EA6, 0x00EA7, 0x00EB1,
0x00EB2, 0x00EB4, 0x00EBD, 0x00EBE, 0x00EC0, 0x00EC5, 0x00EC6, 0x00EC7, 0x00EDC, 0x00EE0,
0x00F00, 0x00F01, 0x00F40, 0x00F48, 0x00F49, 0x00F6D, 0x00F88, 0x00F8D, 0x01000, 0x0102B,
0x0103F, 0x01040, 0x01050, 0x01056, 0x0105A, 0x0105E, 0x01061, 0x01062, 0x01065, 0x01067,
0x0106E, 0x01071, 0x01075, 0x01082, 0x0108E, 0x0108F, 0x010A0, 0x010C6, 0x010C7, 0x010C8,
0x010CD, 0x010CE, 0x010D0, 0x010FB, 0x010FC, 0x01249, 0x0124A, 0x0124E, 0x01250, 0x01257,
0x01258, 0x01259, 0x0125A, 0x0125E, 0x01260, 0x01289, 0x0128A, 0x0128E, 0x01290, 0x012B1,
0x012B2, 0x012B6, 0x012B8, 0x012BF, 0x012C0, 0x012C1, 0x012C2, 0x012C6, 0x012C8, 0x012D7,
0x012D8, 0x01311, 0x01312, 0x01316, 0x01318, 0x0135B, 0x01380, 0x01390, 0x013A0, 0x013F6,
0x013F8, 0x013FE, 0x01401, 0x0166D, 0x0166F, 0x01680, 0x01681, 0x0169B, 0x016A0, 0x016EB,
0x016EE, 0x016F9, 0x01700, 0x01712, 0x0171F, 0x01732, 0x01740, 0x01752, 0x01760, 0x0176D,
0x0176E, 0x01771, 0x01780, 0x017B4, 0x017D7, 0x017D8, 0x017DC, 0x017DD, 0x01820, 0x01879,
0x01880, 0x018A9, 0x018AA, 0x018AB, 0x018B0, 0x018F6, 0x01900, 0x0191F, 0x01950, 0x0196E,
0x01970, 0x01975, 0x01980, 0x019AC, 0x019B0, 0x019CA, 0x01A00, 0x01A17, 0x01A20, 0x01A55,
0x01AA7, 0x01AA8, 0x01B05, 0x01B34, 0x01B45, 0x01B4D, 0x01B83, 0x01BA1, 0x01BAE, 0x01BB0,
0x01BBA, 0x01BE6, 0x01C00, 0x01C24, 0x01C4D, 0x01C50, 0x01C5A, 0x01C7E, 0x01C80, 0x01C8B,
0x01C90, 0x01CBB, 0x01CBD, 0x01CC0, 0x01CE9, 0x01CED, 0x01CEE, 0x01CF4, 0x01CF5, 0x01CF7,
0x01CFA, 0x01CFB, 0x01D00, 0x01DC0, 0x01E00, 0x01F16, 0x01F18, 0x01F1E, 0x01F20, 0x01F46,
0x01F48, 0x01F4E, 0x01F50, 0x01F58, 0x01F59, 0x01F5A, 0x01F5B, 0x01F5C, 0x01F5D, 0x01F5E,
0x01F5F, 0x01F7E, 0x01F80, 0x01FB5, 0x01FB6, 0x01FBD, 0x01FBE, 0x01FBF, 0x01FC2, 0x01FC5,
0x01FC6, 0x01FCD, 0x01FD0, 0x01FD4, 0x01FD6, 0x01FDC, 0x01FE0, 0x01FED, 0x01FF2, 0x01FF5,
0x01FF6, 0x01FFD, 0x02071, 0x02072, 0x0207F, 0x02080, 0x02090, 0x0209D, 0x02102, 0x02103,
0x02107, 0x02108, 0x0210A, 0x02114, 0x02115, 0x02116, 0x02118, 0x0211E, 0x02124, 0x02125,
0x02126, 0x02127, 0x02128, 0x02129, 0x0212A, 0x0213A, 0x0213C, 0x02140, 0x02145, 0x0214A,
0x0214E, 0x0214F, 0x02160, 0x02189, 0x02C00, 0x02CE5, 0x02CEB, 0x02CEF, 0x02CF2, 0x02CF4,
0x02D00, 0x02D26, 0x02D27, 0x02D28, 0x02D2D, 0x02D2E, 0x02D30, 0x02D68, 0x02D6F, 0x02D70,
0x02D80, 0x02D97, 0x02DA0, 0x02DA7, 0x02DA8, 0x02DAF, 0x02DB0, 0x02DB7, 0x02DB8, 0x02DBF,
0x02DC0, 0x02DC7, 0x02DC8, 0x02DCF, 0x02DD0, 0x02DD7, 0x02DD8, 0x02DDF, 0x03005, 0x03008,
0x03021, 0x0302A, 0x03031, 0x03036, 0x03038, 0x0303D, 0x03041, 0x03097, 0x0309B, 0x030A0,
0x030A1, 0x030FB, 0x030FC, 0x03100, 0x03105, 0x03130, 0x03131, 0x0318F, 0x031A0, 0x031C0,
0x031F0, 0x03200, 0x03400, 0x04DC0, 0x04E00, 0x0A48D, 0x0A4D0, 0x0A4FE, 0x0A500, 0x0A60D,
0x0A610, 0x0A620, 0x0A62A, 0x0A62C, 0x0A640, 0x0A66F, 0x0A67F, 0x0A69E, 0x0A6A0, 0x0A6F0,
0x0A717, 0x0A720, 0x0A722, 0x0A789, 0x0A78B, 0x0A7CE, 0x0A7D0, 0x0A7D2, 0x0A7D3, 0x0A7D4,
0x0A7D5, 0x0A7DD, 0x0A7F2, 0x0A802, 0x0A803, 0x0A806, 0x0A807, 0x0A80B, 0x0A80C, 0x0A823,
0x0A840, 0x0A874, 0x0A882, 0x0A8B4, 0x0A8F2, 0x0A8F8, 0x0A8FB, 0x0A8FC, 0x0A8FD, 0x0A8FF,
0x0A90A, 0x0A926, 0x0A930, 0x0A947, 0x0A960, 0x0A97D, 0x0A984, 0x0A9B3, 0x0A9CF, 0x0A9D0,
0x0A9E0, 0x0A9E5, 0x0A9E6, 0x0A9F0, 0x0A9FA, 0x0A9FF, 0x0AA00, 0x0AA29, 0x0AA40, 0x0AA43,
0x0AA44, 0x0AA4C, 0x0AA60, 0x0AA77, 0x0AA7A, 0x0AA7B, 0x0AA7E, 0x0AAB0, 0x0AAB1, 0x0AAB2,
0x0AAB5, 0x0AAB7, 0x0AAB9, 0x0AABE, 0x0AAC0, 0x0AAC1, 0x0AAC2, 0x0AAC3, 0x0AADB, 0x0AADE,
0x0AAE0, 0x0AAEB, 0x0AAF2, 0x0AAF5, 0x0AB01, 0x0AB07, 0x0AB09, 0x0AB0F, 0x0AB11, 0x0AB17,
0x0AB20, 0x0AB27, 0x0AB28, 0x0AB2F, 0x0AB30, 0x0AB5B, 0x0AB5C, 0x0AB6A, 0x0AB70, 0x0ABE3,
0x0AC00, 0x0D7A4, 0x0D7B0, 0x0D7C7, 0x0D7CB, 0x0D7FC, 0x0F900, 0x0FA6E, 0x0FA70, 0x0FADA,
0x0FB00, 0x0FB07, 0x0FB13, 0x0FB18, 0x0FB1D, 0x0FB1E, 0x0FB1F, 0x0FB29, 0x0FB2A, 0x0FB37,
0x0FB38, 0x0FB3D, 0x0FB3E, 0x0FB3F, 0x0FB40, 0x0FB42, 0x0FB43, 0x0FB45, 0x0FB46, 0x0FBB2,
0x0FBD3, 0x0FD3E, 0x0FD50, 0x0FD90, 0x0FD92, 0x0FDC8, 0x0FDF0, 0x0FDFC, 0x0FE70, 0x0FE75,
0x0FE76, 0x0FEFD, 0x0FF21, 0x0FF3B, 0x0FF41, 0x0FF5B, 0x0FF66, 0x0FFBF, 0x0FFC2, 0x0FFC8,
0x0FFCA, 0x0FFD0, 0x0FFD2, 0x0FFD8, 0x0FFDA, 0x0FFDD, 0x10000, 0x1000C, 0x1000D, 0x10027,
0x10028, 0x1003B, 0x1003C, 0x1003E, 0x1003F, 0x1004E, 0x10050, 0x1005E, 0x10080, 0x100FB,
0x10140, 0x10175, 0x10280, 0x1029D, 0x102A0, 0x102D1, 0x10300, 0x10320, 0x1032D, 0x1034B,
0x10350, 0x10376, 0x10380, 0x1039E, 0x103A0, 0x103C4, 0x103C8, 0x103D0, 0x103D1, 0x103D6,
0x10400, 0x1049E, 0x104B0, 0x104D4, 0x104D8, 0x104FC, 0x10500, 0x10528, 0x10530, 0x10564,
0x10570, 0x1057B, 0x1057C, 0x1058B, 0x1058C, 0x10593, 0x10594, 0x10596, 0x10597, 0x105A2,
0x105A3, 0x105B2, 0x105B3, 0x105BA, 0x105BB, 0x105BD, 0x105C0, 0x105F4, 0x10600, 0x10737,
0x10740, 0x10756, 0x10760, 0x10768, 0x10780, 0x10786, 0x10787, 0x107B1, 0x107B2, 0x107BB,
0x10800, 0x10806, 0x10808, 0x10809, 0x1080A, 0x10836, 0x10837, 0x10839, 0x1083C, 0x1083D,
0x1083F, 0x10856, 0x10860, 0x10877, 0x10880, 0x1089F, 0x108E0, 0x108F3, 0x108F4, 0x108F6,
0x10900, 0x10916, 0x10920, 0x1093A, 0x10980, 0x109B8, 0x109BE, 0x109C0, 0x10A00, 0x10A01,
0x10A10, 0x10A14, 0x10A15, 0x10A18, 0x10A19, 0x10A36, 0x10A60, 0x10A7D, 0x10A80, 0x10A9D,
0x10AC0, 0x10AC8, 0x10AC9, 0x10AE5, 0x10B00, 0x10B36, 0x10B40, 0x10B56, 0x10B60, 0x10B73,
0x10B80, 0x10B92, 0x10C00, 0x10C49, 0x10C80, 0x10CB3, 0x10CC0, 0x10CF3, 0x10D00, 0x10D24,
0x10D4A, 0x10D66, 0x10D6F, 0x10D86, 0x10E80, 0x10EAA, 0x10EB0, 0x10EB2, 0x10EC2, 0x10EC5,
0x10F00, 0x10F1D, 0x10F27, 0x10F28, 0x10F30, 0x10F46, 0x10F70, 0x10F82, 0x10FB0, 0x10FC5,
0x10FE0, 0x10FF7, 0x11003, 0x11038, 0x11071, 0x11073, 0x11075, 0x11076, 0x11083, 0x110B0,
0x110D0, 0x110E9, 0x11103, 0x11127, 0x11144, 0x11145, 0x11147, 0x11148, 0x11150, 0x11173,
0x11176, 0x11177, 0x11183, 0x111B3, 0x111C1, 0x111C5, 0x111DA, 0x111DB, 0x111DC, 0x111DD,
0x11200, 0x11212, 0x11213, 0x1122C, 0x1123F, 0x11241, 0x11280, 0x11287, 0x11288, 0x11289,
0x1128A, 0x1128E, 0x1128F, 0x1129E, 0x1129F, 0x112A9, 0x112B0, 0x112DF, 0x11305, 0x1130D,
0x1130F, 0x11311, 0x11313, 0x11329, 0x1132A, 0x11331, 0x11332, 0x11334, 0x11335, 0x1133A,
0x1133D, 0x1133E, 0x11350, 0x11351, 0x1135D, 0x11362, 0x11380, 0x1138A, 0x1138B, 0x1138C,
0x1138E, 0x1138F, 0x11390, 0x113B6, 0x113B7, 0x113B8, 0x113D1, 0x113D2, 0x113D3, 0x113D4,
0x11400, 0x11435, 0x11447, 0x1144B, 0x1145F, 0x11462, 0x11480, 0x114B0, 0x114C4, 0x114C6,
0x114C7, 0x114C8, 0x11580, 0x115AF, 0x115D8, 0x115DC, 0x11600, 0x11630, 0x11644, 0x11645,
0x11680, 0x116AB, 0x116B8, 0x116B9, 0x11700, 0x1171B, 0x11740, 0x11747, 0x11800, 0x1182C,
0x118A0, 0x118E0, 0x118FF, 0x11907, 0x11909, 0x1190A, 0x1190C, 0x11914, 0x11915, 0x11917,
0x11918, 0x11930, 0x1193F, 0x11940, 0x11941, 0x11942, 0x119A0, 0x119A8, 0x119AA, 0x119D1,
0x119E1, 0x119E2, 0x119E3, 0x119E4, 0x11A00, 0x11A01, 0x11A0B, 0x11A33, 0x11A3A, 0x11A3B,
0x11A50, 0x11A51, 0x11A5C, 0x11A8A, 0x11A9D, 0x11A9E, 0x11AB0, 0x11AF9, 0x11BC0, 0x11BE1,
0x11C00, 0x11C09, 0x11C0A, 0x11C2F, 0x11C40, 0x11C41, 0x11C72, 0x11C90, 0x11D00, 0x11D07,
0x11D08, 0x11D0A, 0x11D0B, 0x11D31, 0x11D46, 0x11D47, 0x11D60, 0x11D66, 0x11D67, 0x11D69,
0x11D6A, 0x11D8A, 0x11D98, 0x11D99, 0x11EE0, 0x11EF3, 0x11F02, 0x11F03, 0x11F04, 0x11F11,
0x11F12, 0x11F34, 0x11FB0, 0x11FB1, 0x12000, 0x1239A, 0x12400, 0x1246F, 0x12480, 0x12544,
0x12F90, 0x12FF1, 0x13000, 0x13430, 0x13441, 0x13447, 0x13460, 0x143FB, 0x14400, 0x14647,
0x16100, 0x1611E, 0x16800, 0x16A39, 0x16A40, 0x16A5F, 0x16A70, 0x16ABF, 0x16AD0, 0x16AEE,
0x16B00, 0x16B30, 0x16B40, 0x16B44, 0x16B63, 0x16B78, 0x16B7D, 0x16B90, 0x16D40, 0x16D6D,
0x16E40, 0x16E80, 0x16F00, 0x16F4B, 0x16F50, 0x16F51, 0x16F93, 0x16FA0, 0x16FE0, 0x16FE2,
0x16FE3, 0x16FE4, 0x17000, 0x187F8, 0x18800, 0x18CD6, 0x18CFF, 0x18D09, 0x1AFF0, 0x1AFF4,
0x1AFF5, 0x1AFFC, 0x1AFFD, 0x1AFFF, 0x1B000, 0x1B123, 0x1B132, 0x1B133, 0x1B150, 0x1B153,
0x1B155, 0x1B156, 0x1B164, 0x1B168, 0x1B170, 0x1B2FC, 0x1BC00, 0x1BC6B, 0x1BC70, 0x1BC7D,
0x1BC80, 0x1BC89, 0x1BC90, 0x1BC9A, 0x1D400, 0x1D455, 0x1D456, 0x1D49D, 0x1D49E, 0x1D4A0,
0x1D4A2, 0x1D4A3, 0x1D4A5, 0x1D4A7, 0x1D4A9, 0x1D4AD, 0x1D4AE, 0x1D4BA, 0x1D4BB, 0x1D4BC,
0x1D4BD, 0x1D4C4, 0x1D4C5, 0x1D506, 0x1D507, 0x1D50B, 0x1D50D, 0x1D515, 0x1D516, 0x1D51D,
0x1D51E, 0x1D53A, 0x1D53B, 0x1D53F, 0x1D540, 0x1D545, 0x1D546, 0x1D547, 0x1D54A, 0x1D551,
0x1D552, 0x1D6A6, 0x1D6A8, 0x1D6C1, 0x1D6C2, 0x1D6DB, 0x1D6DC, 0x1D6FB, 0x1D6FC, 0x1D715,
0x1D716, 0x1D735, 0x1D736, 0x1D74F, 0x1D750, 0x1D76F, 0x1D770, 0x1D789, 0x1D78A, 0x1D7A9,
0x1D7AA, 0x1D7C3, 0x1D7C4, 0x1D7CC, 0x1DF00, 0x1DF1F, 0x1DF25, 0x1DF2B, 0x1E030, 0x1E06E,
0x1E100, 0x1E12D, 0x1E137, 0x1E13E, 0x1E14E, 0x1E14F, 0x1E290, 0x1E2AE, 0x1E2C0, 0x1E2EC,
0x1E4D0, 0x1E4EC, 0x1E5D0, 0x1E5EE, 0x1E5F0, 0x1E5F1, 0x1E7E0, 0x1E7E7, 0x1E7E8, 0x1E7EC,
0x1E7ED, 0x1E7EF, 0x1E7F0, 0x1E7FF, 0x1E800, 0x1E8C5, 0x1E900, 0x1E944, 0x1E94B, 0x1E94C,
0x1EE00, 0x1EE04, 0x1EE05, 0x1EE20, 0x1EE21, 0x1EE23, 0x1EE24, 0x1EE25, 0x1EE27, 0x1EE28,
0x1EE29, 0x1EE33, 0x1EE34, 0x1EE38, 0x1EE39, 0x1EE3A, 0x1EE3B, 0x1EE3C, 0x1EE42, 0x1EE43,
0x1EE47, 0x1EE48, 0x1EE49, 0x1EE4A, 0x1EE4B, 0x1EE4C, 0x1EE4D, 0x1EE50, 0x1EE51, 0x1EE53,
0x1EE54, 0x1EE55, 0x1EE57, 0x1EE58, 0x1EE59, 0x1EE5A, 0x1EE5B, 0x1EE5C, 0x1EE5D, 0x1EE5E,
0x1EE5F, 0x1EE60, 0x1EE61, 0x1EE63, 0x1EE64, 0x1EE65, 0x1EE67, 0x1EE6B, 0x1EE6C, 0x1EE73,
0x1EE74, 0x1EE78, 0x1EE79, 0x1EE7D, 0x1EE7E, 0x1EE7F, 0x1EE80, 0x1EE8A, 0x1EE8B, 0x1EE9C,
0x1EEA1, 0x1EEA4, 0x1EEA5, 0x1EEAA, 0x1EEAB, 0x1EEBC, 0x20000, 0x2A6E0, 0x2A700, 0x2B73A,
0x2B740, 0x2B81E, 0x2B820, 0x2CEA2, 0x2CEB0, 0x2EBE1, 0x2EBF0, 0x2EE5E, 0x2F800, 0x2FA1E,
0x30000, 0x3134B, 0x31350, 0x323B0
};
static const int32_t XidContinueTable[] = {
0x00030, 0x0003A, 0x00041, 0x0005B, 0x0005F, 0x00060, 0x00061, 0x0007B, 0x000AA, 0x000AB,
0x000B5, 0x000B6, 0x000B7, 0x000B8, 0x000BA, 0x000BB, 0x000C0, 0x000D7, 0x000D8, 0x000F7,
0x000F8, 0x002C2, 0x002C6, 0x002D2, 0x002E0, 0x002E5, 0x002EC, 0x002ED, 0x002EE, 0x002EF,
0x00300, 0x00375, 0x00376, 0x00378, 0x0037A, 0x0037E, 0x0037F, 0x00380, 0x00386, 0x0038B,
0x0038C, 0x0038D, 0x0038E, 0x003A2, 0x003A3, 0x003F6, 0x003F7, 0x00482, 0x00483, 0x00488,
0x0048A, 0x00530, 0x00531, 0x00557, 0x00559, 0x0055A, 0x00560, 0x00589, 0x00591, 0x005BE,
0x005BF, 0x005C0, 0x005C1, 0x005C3, 0x005C4, 0x005C6, 0x005C7, 0x005C8, 0x005D0, 0x005EB,
0x005EF, 0x005F3, 0x00610, 0x0061B, 0x00620, 0x0066A, 0x0066E, 0x006D4, 0x006D5, 0x006DD,
0x006DF, 0x006E9, 0x006EA, 0x006FD, 0x006FF, 0x00700, 0x00710, 0x0074B, 0x0074D, 0x007B2,
0x007C0, 0x007F6, 0x007FA, 0x007FB, 0x007FD, 0x007FE, 0x00800, 0x0082E, 0x00840, 0x0085C,
0x00860, 0x0086B, 0x00870, 0x00888, 0x00889, 0x0088F, 0x00897, 0x008E2, 0x008E3, 0x00964,
0x00966, 0x00970, 0x00971, 0x00984, 0x00985, 0x0098D, 0x0098F, 0x00991, 0x00993, 0x009A9,
0x009AA, 0x009B1, 0x009B2, 0x009B3, 0x009B6, 0x009BA, 0x009BC, 0x009C5, 0x009C7, 0x009C9,
0x009CB, 0x009CF, 0x009D7, 0x009D8, 0x009DC, 0x009DE, 0x009DF, 0x009E4, 0x009E6, 0x009F2,
0x009FC, 0x009FD, 0x009FE, 0x009FF, 0x00A01, 0x00A04, 0x00A05, 0x00A0B, 0x00A0F, 0x00A11,
0x00A13, 0x00A29, 0x00A2A, 0x00A31, 0x00A32, 0x00A34, 0x00A35, 0x00A37, 0x00A38, 0x00A3A,
0x00A3C, 0x00A3D, 0x00A3E, 0x00A43, 0x00A47, 0x00A49, 0x00A4B, 0x00A4E, 0x00A51, 0x00A52,
0x00A59, 0x00A5D, 0x00A5E, 0x00A5F, 0x00A66, 0x00A76, 0x00A81, 0x00A84, 0x00A85, 0x00A8E,
0x00A8F, 0x00A92, 0x00A93, 0x00AA9, 0x00AAA, 0x00AB1, 0x00AB2, 0x00AB4, 0x00AB5, 0x00ABA,
0x00ABC, 0x00AC6, 0x00AC7, 0x00ACA, 0x00ACB, 0x00ACE, 0x00AD0, 0x00AD1, 0x00AE0, 0x00AE4,
0x00AE6, 0x00AF0, 0x00AF9, 0x00B00, 0x00B01, 0x00B04, 0x00B05, 0x00B0D, 0x00B0F, 0x00B11,
0x00B13, 0x00B29, 0x00B2A, 0x00B31, 0x00B32, 0x00B34, 0x00B35, 0x00B3A, 0x00B3C, 0x00B45,
0x00B47, 0x00B49, 0x00B4B, 0x00B4E, 0x00B55, 0x00B58, 0x00B5C, 0x00B5E, 0x00B5F, 0x00B64,
0x00B66, 0x00B70, 0x00B71, 0x00B72, 0x00B82, 0x00B84, 0x00B85, 0x00B8B, 0x00B8E, 0x00B91,
0x00B92, 0x00B96, 0x00B99, 0x00B9B, 0x00B9C, 0x00B9D, 0x00B9E, 0x00BA0, 0x00BA3, 0x00BA5,
0x00BA8, 0x00BAB, 0x00BAE, 0x00BBA, 0x00BBE, 0x00BC3, 0x00BC6, 0x00BC9, 0x00BCA, 0x00BCE,
0x00BD0, 0x00BD1, 0x00BD7, 0x00BD8, 0x00BE6, 0x00BF0, 0x00C00, 0x00C0D, 0x00C0E, 0x00C11,
0x00C12, 0x00C29, 0x00C2A, 0x00C3A, 0x00C3C, 0x00C45, 0x00C46, 0x00C49, 0x00C4A, 0x00C4E,
0x00C55, 0x00C57, 0x00C58, 0x00C5B, 0x00C5D, 0x00C5E, 0x00C60, 0x00C64, 0x00C66, 0x00C70,
0x00C80, 0x00C84, 0x00C85, 0x00C8D, 0x00C8E, 0x00C91, 0x00C92, 0x00CA9, 0x00CAA, 0x00CB4,
0x00CB5, 0x00CBA, 0x00CBC, 0x00CC5, 0x00CC6, 0x00CC9, 0x00CCA, 0x00CCE, 0x00CD5, 0x00CD7,
0x00CDD, 0x00CDF, 0x00CE0, 0x00CE4, 0x00CE6, 0x00CF0, 0x00CF1, 0x00CF4, 0x00D00, 0x00D0D,
0x00D0E, 0x00D11, 0x00D12, 0x00D45, 0x00D46, 0x00D49, 0x00D4A, 0x00D4F, 0x00D54, 0x00D58,
0x00D5F, 0x00D64, 0x00D66, 0x00D70, 0x00D7A, 0x00D80, 0x00D81, 0x00D84, 0x00D85, 0x00D97,
0x00D9A, 0x00DB2, 0x00DB3, 0x00DBC, 0x00DBD, 0x00DBE, 0x00DC0, 0x00DC7, 0x00DCA, 0x00DCB,
0x00DCF, 0x00DD5, 0x00DD6, 0x00DD7, 0x00DD8, 0x00DE0, 0x00DE6, 0x00DF0, 0x00DF2, 0x00DF4,
0x00E01, 0x00E3B, 0x00E40, 0x00E4F, 0x00E50, 0x00E5A, 0x00E81, 0x00E83, 0x00E84, 0x00E85,
0x00E86, 0x00E8B, 0x00E8C, 0x00EA4, 0x00EA5, 0x00EA6, 0x00EA7, 0x00EBE, 0x00EC0, 0x00EC5,
0x00EC6, 0x00EC7, 0x00EC8, 0x00ECF, 0x00ED0, 0x00EDA, 0x00EDC, 0x00EE0, 0x00F00, 0x00F01,
0x00F18, 0x00F1A, 0x00F20, 0x00F2A, 0x00F35, 0x00F36, 0x00F37, 0x00F38, 0x00F39, 0x00F3A,
0x00F3E, 0x00F48, 0x00F49, 0x00F6D, 0x00F71, 0x00F85, 0x00F86, 0x00F98, 0x00F99, 0x00FBD,
0x00FC6, 0x00FC7, 0x01000, 0x0104A, 0x01050, 0x0109E, 0x010A0, 0x010C6, 0x010C7, 0x010C8,
0x010CD, 0x010CE, 0x010D0, 0x010FB, 0x010FC, 0x01249, 0x0124A, 0x0124E, 0x01250, 0x01257,
0x01258, 0x01259, 0x0125A, 0x0125E, 0x01260, 0x01289, 0x0128A, 0x0128E, 0x01290, 0x012B1,
0x012B2, 0x012B6, 0x012B8, 0x012BF, 0x012C0, 0x012C1, 0x012C2, 0x012C6, 0x012C8, 0x012D7,
0x012D8, 0x01311, 0x01312, 0x01316, 0x01318, 0x0135B, 0x0135D, 0x01360, 0x01369, 0x01372,
0x01380, 0x01390, 0x013A0, 0x013F6, 0x013F8, 0x013FE, 0x01401, 0x0166D, 0x0166F, 0x01680,
0x01681, 0x0169B, 0x016A0, 0x016EB, 0x016EE, 0x016F9, 0x01700, 0x01716, 0x0171F, 0x01735,
0x01740, 0x01754, 0x01760, 0x0176D, 0x0176E, 0x01771, 0x01772, 0x01774, 0x01780, 0x017D4,
0x017D7, 0x017D8, 0x017DC, 0x017DE, 0x017E0, 0x017EA, 0x0180B, 0x0180E, 0x0180F, 0x0181A,
0x01820, 0x01879, 0x01880, 0x018AB, 0x018B0, 0x018F6, 0x01900, 0x0191F, 0x01920, 0x0192C,
0x01930, 0x0193C, 0x01946, 0x0196E, 0x01970, 0x01975, 0x01980, 0x019AC, 0x019B0, 0x019CA,
0x019D0, 0x019DB, 0x01A00, 0x01A1C, 0x01A20, 0x01A5F, 0x01A60, 0x01A7D, 0x01A7F, 0x01A8A,
0x01A90, 0x01A9A, 0x01AA7, 0x01AA8, 0x01AB0, 0x01ABE, 0x01ABF, 0x01ACF, 0x01B00, 0x01B4D,
0x01B50, 0x01B5A, 0x01B6B, 0x01B74, 0x01B80, 0x01BF4, 0x01C00, 0x01C38, 0x01C40, 0x01C4A,
0x01C4D, 0x01C7E, 0x01C80, 0x01C8B, 0x01C90, 0x01CBB, 0x01CBD, 0x01CC0, 0x01CD0, 0x01CD3,
0x01CD4, 0x01CFB, 0x01D00, 0x01F16, 0x01F18, 0x01F1E, 0x01F20, 0x01F46, 0x01F48, 0x01F4E,
0x01F50, 0x01F58, 0x01F59, 0x01F5A, 0x01F5B, 0x01F5C, 0x01F5D, 0x01F5E, 0x01F5F, 0x01F7E,
0x01F80, 0x01FB5, 0x01FB6, 0x01FBD, 0x01FBE, 0x01FBF, 0x01FC2, 0x01FC5, 0x01FC6, 0x01FCD,
0x01FD0, 0x01FD4, 0x01FD6, 0x01FDC, 0x01FE0, 0x01FED, 0x01FF2, 0x01FF5, 0x01FF6, 0x01FFD,
0x0200C, 0x0200E, 0x0203F, 0x02041, 0x02054, 0x02055, 0x02071, 0x02072, 0x0207F, 0x02080,
0x02090, 0x0209D, 0x020D0, 0x020DD, 0x020E1, 0x020E2, 0x020E5, 0x020F1, 0x02102, 0x02103,
0x02107, 0x02108, 0x0210A, 0x02114, 0x02115, 0x02116, 0x02118, 0x0211E, 0x02124, 0x02125,
0x02126, 0x02127, 0x02128, 0x02129, 0x0212A, 0x0213A, 0x0213C, 0x02140, 0x02145, 0x0214A,
0x0214E, 0x0214F, 0x02160, 0x02189, 0x02C00, 0x02CE5, 0x02CEB, 0x02CF4, 0x02D00, 0x02D26,
0x02D27, 0x02D28, 0x02D2D, 0x02D2E, 0x02D30, 0x02D68, 0x02D6F, 0x02D70, 0x02D7F, 0x02D97,
0x02DA0, 0x02DA7, 0x02DA8, 0x02DAF, 0x02DB0, 0x02DB7, 0x02DB8, 0x02DBF, 0x02DC0, 0x02DC7,
0x02DC8, 0x02DCF, 0x02DD0, 0x02DD7, 0x02DD8, 0x02DDF, 0x02DE0, 0x02E00, 0x03005, 0x03008,
0x03021, 0x03030, 0x03031, 0x03036, 0x03038, 0x0303D, 0x03041, 0x03097, 0x03099, 0x030A0,
0x030A1, 0x03100, 0x03105, 0x03130, 0x03131, 0x0318F, 0x031A0, 0x031C0, 0x031F0, 0x03200,
0x03400, 0x04DC0, 0x04E00, 0x0A48D, 0x0A4D0, 0x0A4FE, 0x0A500, 0x0A60D, 0x0A610, 0x0A62C,
0x0A640, 0x0A670, 0x0A674, 0x0A67E, 0x0A67F, 0x0A6F2, 0x0A717, 0x0A720, 0x0A722, 0x0A789,
0x0A78B, 0x0A7CE, 0x0A7D0, 0x0A7D2, 0x0A7D3, 0x0A7D4, 0x0A7D5, 0x0A7DD, 0x0A7F2, 0x0A828,
0x0A82C, 0x0A82D, 0x0A840, 0x0A874, 0x0A880, 0x0A8C6, 0x0A8D0, 0x0A8DA, 0x0A8E0, 0x0A8F8,
0x0A8FB, 0x0A8FC, 0x0A8FD, 0x0A92E, 0x0A930, 0x0A954, 0x0A960, 0x0A97D, 0x0A980, 0x0A9C1,
0x0A9CF, 0x0A9DA, 0x0A9E0, 0x0A9FF, 0x0AA00, 0x0AA37, 0x0AA40, 0x0AA4E, 0x0AA50, 0x0AA5A,
0x0AA60, 0x0AA77, 0x0AA7A, 0x0AAC3, 0x0AADB, 0x0AADE, 0x0AAE0, 0x0AAF0, 0x0AAF2, 0x0AAF7,
0x0AB01, 0x0AB07, 0x0AB09, 0x0AB0F, 0x0AB11, 0x0AB17, 0x0AB20, 0x0AB27, 0x0AB28, 0x0AB2F,
0x0AB30, 0x0AB5B, 0x0AB5C, 0x0AB6A, 0x0AB70, 0x0ABEB, 0x0ABEC, 0x0ABEE, 0x0ABF0, 0x0ABFA,
0x0AC00, 0x0D7A4, 0x0D7B0, 0x0D7C7, 0x0D7CB, 0x0D7FC, 0x0F900, 0x0FA6E, 0x0FA70, 0x0FADA,
0x0FB00, 0x0FB07, 0x0FB13, 0x0FB18, 0x0FB1D, 0x0FB29, 0x0FB2A, 0x0FB37, 0x0FB38, 0x0FB3D,
0x0FB3E, 0x0FB3F, 0x0FB40, 0x0FB42, 0x0FB43, 0x0FB45, 0x0FB46, 0x0FBB2, 0x0FBD3, 0x0FD3E,
0x0FD50, 0x0FD90, 0x0FD92, 0x0FDC8, 0x0FDF0, 0x0FDFC, 0x0FE00, 0x0FE10, 0x0FE20, 0x0FE30,
0x0FE33, 0x0FE35, 0x0FE4D, 0x0FE50, 0x0FE70, 0x0FE75, 0x0FE76, 0x0FEFD, 0x0FF10, 0x0FF1A,
0x0FF21, 0x0FF3B, 0x0FF3F, 0x0FF40, 0x0FF41, 0x0FF5B, 0x0FF65, 0x0FFBF, 0x0FFC2, 0x0FFC8,
0x0FFCA, 0x0FFD0, 0x0FFD2, 0x0FFD8, 0x0FFDA, 0x0FFDD, 0x10000, 0x1000C, 0x1000D, 0x10027,
0x10028, 0x1003B, 0x1003C, 0x1003E, 0x1003F, 0x1004E, 0x10050, 0x1005E, 0x10080, 0x100FB,
0x10140, 0x10175, 0x101FD, 0x101FE, 0x10280, 0x1029D, 0x102A0, 0x102D1, 0x102E0, 0x102E1,
0x10300, 0x10320, 0x1032D, 0x1034B, 0x10350, 0x1037B, 0x10380, 0x1039E, 0x103A0, 0x103C4,
0x103C8, 0x103D0, 0x103D1, 0x103D6, 0x10400, 0x1049E, 0x104A0, 0x104AA, 0x104B0, 0x104D4,
0x104D8, 0x104FC, 0x10500, 0x10528, 0x10530, 0x10564, 0x10570, 0x1057B, 0x1057C, 0x1058B,
0x1058C, 0x10593, 0x10594, 0x10596, 0x10597, 0x105A2, 0x105A3, 0x105B2, 0x105B3, 0x105BA,
0x105BB, 0x105BD, 0x105C0, 0x105F4, 0x10600, 0x10737, 0x10740, 0x10756, 0x10760, 0x10768,
0x10780, 0x10786, 0x10787, 0x107B1, 0x107B2, 0x107BB, 0x10800, 0x10806, 0x10808, 0x10809,
0x1080A, 0x10836, 0x10837, 0x10839, 0x1083C, 0x1083D, 0x1083F, 0x10856, 0x10860, 0x10877,
0x10880, 0x1089F, 0x108E0, 0x108F3, 0x108F4, 0x108F6, 0x10900, 0x10916, 0x10920, 0x1093A,
0x10980, 0x109B8, 0x109BE, 0x109C0, 0x10A00, 0x10A04, 0x10A05, 0x10A07, 0x10A0C, 0x10A14,
0x10A15, 0x10A18, 0x10A19, 0x10A36, 0x10A38, 0x10A3B, 0x10A3F, 0x10A40, 0x10A60, 0x10A7D,
0x10A80, 0x10A9D, 0x10AC0, 0x10AC8, 0x10AC9, 0x10AE7, 0x10B00, 0x10B36, 0x10B40, 0x10B56,
0x10B60, 0x10B73, 0x10B80, 0x10B92, 0x10C00, 0x10C49, 0x10C80, 0x10CB3, 0x10CC0, 0x10CF3,
0x10D00, 0x10D28, 0x10D30, 0x10D3A, 0x10D40, 0x10D66, 0x10D69, 0x10D6E, 0x10D6F, 0x10D86,
0x10E80, 0x10EAA, 0x10EAB, 0x10EAD, 0x10EB0, 0x10EB2, 0x10EC2, 0x10EC5, 0x10EFC, 0x10F1D,
0x10F27, 0x10F28, 0x10F30, 0x10F51, 0x10F70, 0x10F86, 0x10FB0, 0x10FC5, 0x10FE0, 0x10FF7,
0x11000, 0x11047, 0x11066, 0x11076, 0x1107F, 0x110BB, 0x110C2, 0x110C3, 0x110D0, 0x110E9,
0x110F0, 0x110FA, 0x11100, 0x11135, 0x11136, 0x11140, 0x11144, 0x11148, 0x11150, 0x11174,
0x11176, 0x11177, 0x11180, 0x111C5, 0x111C9, 0x111CD, 0x111CE, 0x111DB, 0x111DC, 0x111DD,
0x11200, 0x11212, 0x11213, 0x11238, 0x1123E, 0x11242, 0x11280, 0x11287, 0x11288, 0x11289,
0x1128A, 0x1128E, 0x1128F, 0x1129E, 0x1129F, 0x112A9, 0x112B0, 0x112EB, 0x112F0, 0x112FA,
0x11300, 0x11304, 0x11305, 0x1130D, 0x1130F, 0x11311, 0x11313, 0x11329, 0x1132A, 0x11331,
0x11332, 0x11334, 0x11335, 0x1133A, 0x1133B, 0x11345, 0x11347, 0x11349, 0x1134B, 0x1134E,
0x11350, 0x11351, 0x11357, 0x11358, 0x1135D, 0x11364, 0x11366, 0x1136D, 0x11370, 0x11375,
0x11380, 0x1138A, 0x1138B, 0x1138C, 0x1138E, 0x1138F, 0x11390, 0x113B6, 0x113B7, 0x113C1,
0x113C2, 0x113C3, 0x113C5, 0x113C6, 0x113C7, 0x113CB, 0x113CC, 0x113D4, 0x113E1, 0x113E3,
0x11400, 0x1144B, 0x11450, 0x1145A, 0x1145E, 0x11462, 0x11480, 0x114C6, 0x114C7, 0x114C8,
0x114D0, 0x114DA, 0x11580, 0x115B6, 0x115B8, 0x115C1, 0x115D8, 0x115DE, 0x11600, 0x11641,
0x11644, 0x11645, 0x11650, 0x1165A, 0x11680, 0x116B9, 0x116C0, 0x116CA, 0x116D0, 0x116E4,
0x11700, 0x1171B, 0x1171D, 0x1172C, 0x11730, 0x1173A, 0x11740, 0x11747, 0x11800, 0x1183B,
0x118A0, 0x118EA, 0x118FF, 0x11907, 0x11909, 0x1190A, 0x1190C, 0x11914, 0x11915, 0x11917,
0x11918, 0x11936, 0x11937, 0x11939, 0x1193B, 0x11944, 0x11950, 0x1195A, 0x119A0, 0x119A8,
0x119AA, 0x119D8, 0x119DA, 0x119E2, 0x119E3, 0x119E5, 0x11A00, 0x11A3F, 0x11A47, 0x11A48,
0x11A50, 0x11A9A, 0x11A9D, 0x11A9E, 0x11AB0, 0x11AF9, 0x11BC0, 0x11BE1, 0x11BF0, 0x11BFA,
0x11C00, 0x11C09, 0x11C0A, 0x11C37, 0x11C38, 0x11C41, 0x11C50, 0x11C5A, 0x11C72, 0x11C90,
0x11C92, 0x11CA8, 0x11CA9, 0x11CB7, 0x11D00, 0x11D07, 0x11D08, 0x11D0A, 0x11D0B, 0x11D37,
0x11D3A, 0x11D3B, 0x11D3C, 0x11D3E, 0x11D3F, 0x11D48, 0x11D50, 0x11D5A, 0x11D60, 0x11D66,
0x11D67, 0x11D69, 0x11D6A, 0x11D8F, 0x11D90, 0x11D92, 0x11D93, 0x11D99, 0x11DA0, 0x11DAA,
0x11EE0, 0x11EF7, 0x11F00, 0x11F11, 0x11F12, 0x11F3B, 0x11F3E, 0x11F43, 0x11F50, 0x11F5B,
0x11FB0, 0x11FB1, 0x12000, 0x1239A, 0x12400, 0x1246F, 0x12480, 0x12544, 0x12F90, 0x12FF1,
0x13000, 0x13430, 0x13440, 0x13456, 0x13460, 0x143FB, 0x14400, 0x14647, 0x16100, 0x1613A,
0x16800, 0x16A39, 0x16A40, 0x16A5F, 0x16A60, 0x16A6A, 0x16A70, 0x16ABF, 0x16AC0, 0x16ACA,
0x16AD0, 0x16AEE, 0x16AF0, 0x16AF5, 0x16B00, 0x16B37, 0x16B40, 0x16B44, 0x16B50, 0x16B5A,
0x16B63, 0x16B78, 0x16B7D, 0x16B90, 0x16D40, 0x16D6D, 0x16D70, 0x16D7A, 0x16E40, 0x16E80,
0x16F00, 0x16F4B, 0x16F4F, 0x16F88, 0x16F8F, 0x16FA0, 0x16FE0, 0x16FE2, 0x16FE3, 0x16FE5,
0x16FF0, 0x16FF2, 0x17000, 0x187F8, 0x18800, 0x18CD6, 0x18CFF, 0x18D09, 0x1AFF0, 0x1AFF4,
0x1AFF5, 0x1AFFC, 0x1AFFD, 0x1AFFF, 0x1B000, 0x1B123, 0x1B132, 0x1B133, 0x1B150, 0x1B153,
0x1B155, 0x1B156, 0x1B164, 0x1B168, 0x1B170, 0x1B2FC, 0x1BC00, 0x1BC6B, 0x1BC70, 0x1BC7D,
0x1BC80, 0x1BC89, 0x1BC90, 0x1BC9A, 0x1BC9D, 0x1BC9F, 0x1CCF0, 0x1CCFA, 0x1CF00, 0x1CF2E,
0x1CF30, 0x1CF47, 0x1D165, 0x1D16A, 0x1D16D, 0x1D173, 0x1D17B, 0x1D183, 0x1D185, 0x1D18C,
0x1D1AA, 0x1D1AE, 0x1D242, 0x1D245, 0x1D400, 0x1D455, 0x1D456, 0x1D49D, 0x1D49E, 0x1D4A0,
0x1D4A2, 0x1D4A3, 0x1D4A5, 0x1D4A7, 0x1D4A9, 0x1D4AD, 0x1D4AE, 0x1D4BA, 0x1D4BB, 0x1D4BC,
0x1D4BD, 0x1D4C4, 0x1D4C5, 0x1D506, 0x1D507, 0x1D50B, 0x1D50D, 0x1D515, 0x1D516, 0x1D51D,
0x1D51E, 0x1D53A, 0x1D53B, 0x1D53F, 0x1D540, 0x1D545, 0x1D546, 0x1D547, 0x1D54A, 0x1D551,
0x1D552, 0x1D6A6, 0x1D6A8, 0x1D6C1, 0x1D6C2, 0x1D6DB, 0x1D6DC, 0x1D6FB, 0x1D6FC, 0x1D715,
0x1D716, 0x1D735, 0x1D736, 0x1D74F, 0x1D750, 0x1D76F, 0x1D770, 0x1D789, 0x1D78A, 0x1D7A9,
0x1D7AA, 0x1D7C3, 0x1D7C4, 0x1D7CC, 0x1D7CE, 0x1D800, 0x1DA00, 0x1DA37, 0x1DA3B, 0x1DA6D,
0x1DA75, 0x1DA76, 0x1DA84, 0x1DA85, 0x1DA9B, 0x1DAA0, 0x1DAA1, 0x1DAB0, 0x1DF00, 0x1DF1F,
0x1DF25, 0x1DF2B, 0x1E000, 0x1E007, 0x1E008, 0x1E019, 0x1E01B, 0x1E022, 0x1E023, 0x1E025,
0x1E026, 0x1E02B, 0x1E030, 0x1E06E, 0x1E08F, 0x1E090, 0x1E100, 0x1E12D, 0x1E130, 0x1E13E,
0x1E140, 0x1E14A, 0x1E14E, 0x1E14F, 0x1E290, 0x1E2AF, 0x1E2C0, 0x1E2FA, 0x1E4D0, 0x1E4FA,
0x1E5D0, 0x1E5FB, 0x1E7E0, 0x1E7E7, 0x1E7E8, 0x1E7EC, 0x1E7ED, 0x1E7EF, 0x1E7F0, 0x1E7FF,
0x1E800, 0x1E8C5, 0x1E8D0, 0x1E8D7, 0x1E900, 0x1E94C, 0x1E950, 0x1E95A, 0x1EE00, 0x1EE04,
0x1EE05, 0x1EE20, 0x1EE21, 0x1EE23, 0x1EE24, 0x1EE25, 0x1EE27, 0x1EE28, 0x1EE29, 0x1EE33,
0x1EE34, 0x1EE38, 0x1EE39, 0x1EE3A, 0x1EE3B, 0x1EE3C, 0x1EE42, 0x1EE43, 0x1EE47, 0x1EE48,
0x1EE49, 0x1EE4A, 0x1EE4B, 0x1EE4C, 0x1EE4D, 0x1EE50, 0x1EE51, 0x1EE53, 0x1EE54, 0x1EE55,
0x1EE57, 0x1EE58, 0x1EE59, 0x1EE5A, 0x1EE5B, 0x1EE5C, 0x1EE5D, 0x1EE5E, 0x1EE5F, 0x1EE60,
0x1EE61, 0x1EE63, 0x1EE64, 0x1EE65, 0x1EE67, 0x1EE6B, 0x1EE6C, 0x1EE73, 0x1EE74, 0x1EE78,
0x1EE79, 0x1EE7D, 0x1EE7E, 0x1EE7F, 0x1EE80, 0x1EE8A, 0x1EE8B, 0x1EE9C, 0x1EEA1, 0x1EEA4,
0x1EEA5, 0x1EEAA, 0x1EEAB, 0x1EEBC, 0x1FBF0, 0x1FBFA, 0x20000, 0x2A6E0, 0x2A700, 0x2B73A,
0x2B740, 0x2B81E, 0x2B820, 0x2CEA2, 0x2CEB0, 0x2EBE1, 0x2EBF0, 0x2EE5E, 0x2F800, 0x2FA1E,
0x30000, 0x3134B, 0x31350, 0x323B0, 0xE0100, 0xE01F0
};
}

View File

@@ -0,0 +1,152 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
import sys
import re
import argparse
import urllib.request
import os.path
from collections import namedtuple
DEFAULT_URL = 'https://unicode.org/Public/16.0.0'
LICENSE_HEADER = """// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>"""
WcWidthResult = namedtuple('WcWidthResult', ['null', 'wide'])
XidResult = namedtuple('XidResult', ['id_start', 'id_continue'])
def parse_version(core):
lines = iter(core.splitlines())
version = next(lines).strip("\n\r \t#") + ' -- ' + next(lines).strip("\n\r \t#")
return version
def parse_properties_wcwidth(core, asian):
null = []
wide = []
for (chars, parts, comments) in parse_properties(core):
if comments[0] in ['Me', 'Mn', 'Mc', 'Cf', 'Zl', 'Zp']:
null.extend(chars)
for (chars, parts, comments) in parse_properties(asian):
if parts[1] in ['F', 'W'] and not comments[0] in ['Mn', 'Mc']:
wide.extend(chars)
return WcWidthResult(null = compress(null),
wide = compress(wide))
def parse_properties_xid(core):
id_start = []
id_continue = []
for (chars, parts, comments) in parse_properties(core):
if parts[1] == 'ID_Start':
id_start.extend(chars)
elif parts[1] == 'ID_Continue':
id_continue.extend(chars)
return XidResult(id_start = compress(id_start),
id_continue = compress(id_continue))
def parse_properties(text):
for line in text.splitlines():
line = line.strip()
if not line or line[0] == '#':
continue
parts = [part.strip() for part in re.split('[;#]', line)]
if len(parts) < 3:
continue
comments = parts[2].split(' ')
if '..' in parts[0]:
start, end = parts[0].split('..')
else:
start, end = parts[0], parts[0]
start, end = int(start, 16), int(end, 16)
chars = list(range(start, end + 1))
yield (chars, parts, comments)
def compress(chars):
ranges = []
if chars:
chars = sorted(set(chars))
iterator = iter(chars)
prev = next(iterator)
start = prev
for c in iterator:
if c != prev + 1:
ranges.append((start, prev + 1))
start = c
prev = c
end = chars[-1] + 1
ranges.append((start, end))
return ranges
def write_header(version, wcwidth, xid, f):
f.write(f"""{LICENSE_HEADER}
// This file is autogenerated by unicode_gen.py
// Version: {version}
namespace K {{
static const int32_t WcWidthNull[] = {{""")
for i, v in enumerate(wcwidth.null):
if i % 5 == 0: f.write('\n ')
f.write(f' 0x{v[0]:05X}, 0x{v[1]:05X}{"," if i + 1 < len(wcwidth.null) else ""}')
f.write("""
};
static const int32_t WcWidthWide[] = {""")
for i, v in enumerate(wcwidth.wide):
if i % 5 == 0: f.write('\n ')
f.write(f' 0x{v[0]:05X}, 0x{v[1]:05X}{"," if i + 1 < len(wcwidth.wide) else ""}')
f.write("""
};
static const int32_t XidStartTable[] = {""")
for i, v in enumerate(xid.id_start):
if i % 5 == 0: f.write('\n ')
f.write(f' 0x{v[0]:05X}, 0x{v[1]:05X}{"," if i + 1 < len(xid.id_start) else ""}')
f.write("""
};
static const int32_t XidContinueTable[] = {""")
for i, v in enumerate(xid.id_continue):
if i % 5 == 0: f.write('\n ')
f.write(f' 0x{v[0]:05X}, 0x{v[1]:05X}{"," if i + 1 < len(xid.id_continue) else ""}')
f.write("""
};
}
""")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description = 'Extract xid and wcwidth information from Unicode standard')
parser.add_argument('url', metavar = 'url', type = str, nargs = '?', help = 'URL of Unicode standard', default = DEFAULT_URL)
parser.add_argument('-O', '--output_dir', metavar = 'directory', type = str, help = 'output directory for generated files', default = '.')
args = parser.parse_args()
url = args.url.strip('/') + '/ucd/'
with urllib.request.urlopen(url + 'DerivedCoreProperties.txt') as f:
core = f.read().decode('UTF-8')
with urllib.request.urlopen(url + 'EastAsianWidth.txt') as f:
asian = f.read().decode('UTF-8')
version = parse_version(core)
wcwidth = parse_properties_wcwidth(core, asian)
xid = parse_properties_xid(core)
with open(os.path.join(args.output_dir, 'unicode.inc'), 'w') as f:
write_header(version, wcwidth, xid, f)