Motty
原生桌面 SSH 工作台:终端、SFTP/SCP、端口转发、VNC 与 RDP 远程桌面、AI 助手都在一个窗口里。Go 编写,没有 Electron,空闲时保持安静。免费开源,支持 macOS、Windows 和 Linux。
Translation pending
Mojibake is a fast, self-contained Unicode 18 library for C11 and C++17.
Developer toolsC · TypeScriptGitHub @zaerlOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Mojibake is a small, fast, self-contained Unicode library written in C11.
Translation pending
Loading the full README.
Read the full README ↗Mojibake is a small, fast, self-contained Unicode library written in C11. It gives C, C++ and Rust programs normalization, case mapping, segmentation, bidirectional text, collation, IDNA, emoji, confusable detection, and the full Unicode Character Database, all in one source file and one header, with zero dependencies. It is released under the MIT License.
Live demo and API reference · API.md · C++ wrapper · Rust wrapper · Changelog · Roadmap
mojibake.c and mojibake.h to your project and compile. No build system,
no generated files, no runtime data to ship.U+0000.Mojibake covers the Unicode algorithms listed below and is close to feature-complete for its scope. It is still pre-1.0: the C API is stable in practice, but a minor release may make breaking changes, which are always listed in the changelog. Streaming APIs, configurable collators, and the remaining UTS #39 identifier checks are planned; see the roadmap.
You don't need to install anything. There are two files (mojibake.c, mojibake.h) to add to your
C/C++ project. Download it here mojibake-amalgamation-070.zip.
#include <stdio.h>
#include "mojibake.h"
int main(void) {
mjb_result result;
// "Cafe" + U+0301 COMBINING ACUTE ACCENT (6 bytes) -> "Café" with U+00E9 (5 bytes)
mjb_text cafe = mjb_text_utf8("Cafe\xCC\x81", 6);
if(mjb_normalize(&cafe, MJB_MALFORMED_STOP, MJB_NORMALIZATION_NFC, MJB_ENC_UTF_8, &result,
NULL) == MJB_STATUS_OK) {
printf("NFC: %.*s (%zu bytes)\n", (int)result.output_size, result.output,
result.output_size);
mjb_result_free(&result);
}
// One flag, two codepoints, eight bytes
mjb_text flag = mjb_text_utf8("🇮🇹", MJB_NUL_TERMINATED);
size_t codepoints = 0;
size_t graphemes = 0;
if(mjb_codepoint_count(&flag, MJB_MALFORMED_STOP, &codepoints, NULL) == MJB_STATUS_OK &&
mjb_grapheme_count(&flag, MJB_MALFORMED_STOP, &graphemes, NULL) == MJB_STATUS_OK) {
printf("🇮🇹: %zu codepoints, %zu grapheme\n", codepoints, graphemes);
}
// Caseless identifier matching: "Straße" -> "strasse"
mjb_text street = mjb_text_utf8("Straße", MJB_NUL_TERMINATED);
if(mjb_nfkc_casefold(&street, MJB_MALFORMED_STOP, MJB_ENC_UTF_8, &result, NULL) ==
MJB_STATUS_OK) {
printf("Straße -> %.*s\n", (int)result.output_size, result.output);
mjb_result_free(&result);
}
return 0;
}
cc -std=c11 example.c mojibake.c -o example
./example
NFC: Café (5 bytes)
🇮🇹: 2 codepoints, 1 grapheme
Straße -> strasse
A few conventions apply across the whole API:
mjb_status, and MJB_STATUS_OK is zero: always compare against it.
Predicates such as mjb_is_utf8 return bool.U+0000, or
MJB_NUL_TERMINATED to scan for a terminator sized for the declared encoding.mjb_result that you release with mjb_result_free. Their _into
variants write into a buffer you own instead, and can measure the required size first.API.md explains these rules in depth.
Every function can also be tried in the browser on the demo site, which runs the library compiled to WebAssembly.
Text transformation
mjb_normalize, mjb_normalize_into),
identifier-oriented NFKC case folding (mjb_nfkc_casefold, mjb_nfkc_casefold_into), plus a
fast quick-check
(mjb_normalization_quick_check) (UAX #15, Unicode 18.0.0)mjb_map_case, mjb_map_case_into)mjb_idna_to_ascii, mjb_idna_to_unicode)
(UTS #46)mjb_filter, mjb_filter_into)Text analysis
This is the beginning of the README. Read the rest at the original. Read the full README ↗