Repository navigation
Mojibake v0.5.0
Codename: [LATIN CAPITAL LETTER P]
Added
- TypeScript:
graphemeSegments,wordSegments,sentenceSegments, andlineSegmentssplit the
input at its boundaries - C++:
_intotransforms that write into a caller's string and reuse its capacity, for the
std::stringand the UTF-16 and UTF-32 overloads:normalize_into,nfc_into,nfd_into,
nfkc_into,nfkd_into,filter_into,nfkc_casefold_into,case_map_into,
uppercase_into,lowercase_into,titlecase_into,casefold_into,casefold_simple_into,
andconfusable_skeleton_into, plusconvert_encoding_into,collation_key_into,
idna_to_ascii_into, andidna_to_unicode_into, which return the IDNA error flags mjb_textinput structure with themjb_text_make,mjb_text_utf8,mjb_text_utf16le,
mjb_text_utf16be,mjb_text_utf32le, andmjb_text_utf32behelpersmjb_bufferoutput structure, holding caller-provided storage, its capacity or written size, and
its encoding, with themjb_buffer_makehelper andmjb_buffer_textto pass written output to
another call as input- C++ support for UTF-16 and UTF-32 text in the platform's byte order (
mjb::native_utf16_encoding
andmjb::native_utf32_encoding positioninmjb_grapheme_break_state,mjb_word_break_state,mjb_sentence_break_state,
andmjb_line_break_state: the break iterators store the byte offset of each position they
report, so a segment runs from one break position to the next
Changed
- Breaking:
mjb_result.transformedis nowmjb_result.owned. It is true when the library
allocatedoutput; when false,outputpoints into the caller's input. The C++
TextResult::transformed()is nowowned() - Breaking:
mjb_string_validate(buffer, byte_length, encoding, diagnostic)is now
mjb_validate_encoding(const mjb_text *text, diagnostic) - Breaking: all the functions that took a buffer, byte length, and encoding now takes a
const mjb_text* - Breaking: all the functions that took the output encoding, output buffer, and output size now
takes amjb_buffer* - Breaking: the TypeScript
graphemeBreakNext,wordBreakNext,sentenceBreakNext, and
lineBreakNextreturnBreakPosition[], a{ position, type }entry for each position, instead
of the break types alone.positionis the byte offset in the input's encoding, read from the
iterator'sstate.position. The site places its break symbols by position - Breaking: the TypeScript
convertEncoding(input, outputEncoding, options)is now
convertEncoding(input, options)and readsoptions.outputEncodinglike the other
transformations. The output encoding still defaults to UTF-8 - Breaking:
mjb_caseless_match,mjb_collation_compare, andmjb_confusable_matchtake two
const mjb_text *instead of two buffer, byte length, and encoding triples - Breaking:
mjb_collation_compare,mjb_caseless_matchandmjb_confusable_matchnow takes a
malformed_policyand a diagnostic - Breaking:
mjb_map_caseandmjb_map_case_intotake the casing locale as an argument after
type - Breaking:
MJB_LOCALE_NOT_SETselects the default mappings, and an invalid locale returns
MJB_STATUS_INVALID_ARGUMENT. Concurrent calls with different locales no longer interfere - Breaking: removed
mjb_set_locale,mjb_get_locale, andmjb_reset_locale; the library no
longer has a process-global locale. The C++set_locale,get_locale, andreset_localeand the
TypeScriptsetLocaleandgetLocaleare removed too. The C++ casing functions take the locale
as the argument after the input (aftertypeforcase_map), the TypeScriptmapCasereads
options.locale, and the CLI--localeoption is passed to each casing call - Breaking: allocator callbacks receive block sizes, so arena, pool, and accounting allocators
no longer need to record them:mjb_realloc_fnis now(context, ptr, old_size, new_size)and
mjb_free_fnis now(context, ptr, size). The size passed is the one most recently requested
for the block; requested sizes are never 0,reallocreceives NULL with anold_sizeof 0 for a
new block, andfreeis never called with NULL - Breaking:
mjb_resulthas a newcapacityfield that records the allocation size of an owned
outputformjb_result_free - Breaking: the segmentation functions are named after their unit, so each unit's functions
sort together:mjb_next_grapheme_break,mjb_next_word_break,mjb_next_sentence_break, and
mjb_next_line_breakare nowmjb_grapheme_break_next,mjb_word_break_next,
mjb_sentence_break_next, andmjb_line_break_next; their statesmjb_next_state,
mjb_next_word_state,mjb_next_sentence_state, andmjb_next_line_stateare now
mjb_grapheme_break_state,mjb_word_break_state,mjb_sentence_break_state, and
mjb_line_break_state. The TypeScript API follows:graphemeBreakNextand so on - Breaking: the truncation functions are named after what they return, the byte length of a
prefix, since they do not modify their input:mjb_truncate_grapheme,
mjb_truncate_grapheme_width,mjb_truncate_word, andmjb_truncate_word_widthare now
mjb_grapheme_prefix_length,mjb_grapheme_prefix_length_for_width,mjb_word_prefix_length,
andmjb_word_prefix_length_for_width, and the TypeScript methods are now
graphemePrefixLengthand so on. The C++ wrappers return the truncatedstd::string_view, so
they are namedmjb::grapheme_truncate,mjb::grapheme_truncate_width,mjb::word_truncate,
andmjb::word_truncate_width - Breaking:
mjb_for_each_codepointtakes avoid *contextafter the callback and passes it
to every call, so callbacks can keep their own state without global variables:
mjb_for_each_codepoint(text, malformed_policy, callback, context, diagnostic). The callback
type is nowbool (*)(const mjb_character *character, mjb_character_position position, void *context); the character isconstbecause callbacks only read it - Breaking: C++ wrapper changes:
mjb::for_each_codepointaccepts any callable, including a lambda with captures, taking
(const mjb_character &, mjb_character_position); an exception it throws stops the iteration
and is rethrown. The C-callback overload takes thecontextpointer after the callbacknormalize_result,filter_result, andconvert_encoding_resultreject a temporary
std::stringat compile time, because theirTextResultcan borrow the inputLibraryError::what()appends the library's message for the status, and
mjb::status_messageexposesmjb_status_messagemjb::BreakResult::indexis nowposition, the byte offset of the reported position. It
held the iterator's internalindex, which is not a boundary offset.BreakResult::codepoint
is decoded atposition, U+FFFD for a malformed subsequence andMJB_CODEPOINT_NOT_VALIDat
the end of the text; it was the iterator's internal current codepoint, which is the previous
character after a rule absorbs a format or extend character, such as U+200B (SB5) or U+0301
(WB4), and at the end of the text. The breaker classes take anmjb::Text- analysis functions take an
mjb::Textinstead of astd::string_viewand an encoding
parameter:validate_encoding,codepoint_count,for_each_codepoint,grapheme_count,
word_count,sentence_count,terminal_width,is_identifier,normalization_quick_check,
resolved_script_set,emoji_sequence,is_emoji_sequence,is_rgi_emoji,locale_parse,
caseless_match,confusable_match,collation_compare,collation_key, and
collation_key_result. UTF-8 callers drop the encoding argument; for another encoding, pass
mjb::Text(bytes, encoding) - renamed to match the C API:
validate_stringtovalidate_encoding;is_hangul_l,
is_hangul_v, andis_hangul_ttois_hangul_leading_jamo,is_hangul_vowel_jamo, and
is_hangul_trailing_jamo;is_cjk_extensiontois_cjk_extension_ideograph(also on
Character);codepoint_numeric_valuetonumeric_value;parse_localeto
locale_parse; andcomparetocollation_compare
- Breaking:
mjb_hangul_syllable_compositionis no longer public, andmjb_buffer_character
moved out ofmojibake.h - Breaking: The new
mjb_hangul_syllable_compose(leading, vowel, trailing, syllable)
composes a syllable from its jamo, andmjb_hangul_syllable_decompositionis now
mjb_hangul_syllable_decompose. The C++ wrapper follows withhangul_syllable_composeand
hangul_syllable_decompose - Breaking: the
_intofunctions now write in a single pass instead of measuring first make tidynow runs clang-tidy with.clang-tidyover the library, CLI, and tests, replacing
cppcheck
Fixed
mojibake.haccepts C++17 on MSVC without/Zc:__cplusplus. MSVC reports__cplusplusas
199711Lunless that flag is set, so projects including the header from C++ hit the "C++17 or a
later version is required" error and lost[[nodiscard]]; the check now also reads
_MSVC_LANG, which holds the selected standardmjb_map_case,mjb_filter, andmjb_normalizenow returnMJB_STATUS_UNSUPPORTEDinstead of
MJB_STATUS_NO_MEMORYwhen the output encoding cannot represent a result codepoint, matching
their_intovariants- Documented
MJB_STATUS_UNSUPPORTEDfor every function whose output encoding can reject a
codepoint, andMJB_STATUS_INVALID_ENCODINGformjb_confusable_skeleton - CLI: the interactive screen signal handler now restores the cursor and terminal using only
async-signal-safe calls - CLI:
breaknow prints the input bytes between the break positions the iterators report, so a
format or extend character that a rule absorbs, such as U+200B inbreak sentence "a<U+200B>b",
no longer replaces itself with a copy of the previous character (÷aab÷) - Tests: the CLI tests in
tests/shell/now run under CTest; theirassert-command.cmakehelper
was missing, sobreak-json.cmakenever ran - Fixed all clang-tidy findings in the library, CLI, and tests
- Site: the malformed policy is now passed through the API options, so the arguments that follow
it, such as the normalization form, are no longer shifted - Site:
mjb_convert_encodingnow uses the selected output encoding - Tests: the
CollationTest_SHIFTED.txtconformance check compared each string with itself since
themjb_collation_keyconversion, so it could not fail; it now compares the two strings again