/**
 * This file is automatically generated. Do not edit.
 */
/**
 * The Mojibake library
 *
 * This file is distributed under the MIT License. See LICENSE for details.
 */

// #pragma once

#ifndef MJB_MOJIBAKE_H
#define MJB_MOJIBAKE_H

#if defined(__cplusplus)
    #if __cplusplus < 201703L
        #error "C++17 or a later version is required"
    #endif
#else
    #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L
        #error "C11 or a later version is required"
    #endif
#endif

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

// #include "unicode.h"

/**
 * The Mojibake library
 *
 * This file is distributed under the MIT License. See LICENSE for details.
 */

// #pragma once

#ifndef MJB_UNICODE_H
#define MJB_UNICODE_H

// This file is automatically generated. Do not edit.

// See PropertyAliases.txt and PropertyValueAliases.txt files

// ASCII_Hex_Digit (AHex)

/**
 * Bidi_Class (bc)
 */
typedef enum mjb_bidi_class {
    MJB_PR_BIDI_CLASS_NOT_SET, // 0 is "no value"
    MJB_PR_BIDI_CLASS_L,
    MJB_PR_BIDI_CLASS_R,
    MJB_PR_BIDI_CLASS_AL,
    MJB_PR_BIDI_CLASS_EN,
    MJB_PR_BIDI_CLASS_ES,
    MJB_PR_BIDI_CLASS_ET,
    MJB_PR_BIDI_CLASS_AN,
    MJB_PR_BIDI_CLASS_CS,
    MJB_PR_BIDI_CLASS_NSM,
    MJB_PR_BIDI_CLASS_BN,
    MJB_PR_BIDI_CLASS_B,
    MJB_PR_BIDI_CLASS_S,
    MJB_PR_BIDI_CLASS_WS,
    MJB_PR_BIDI_CLASS_ON,
    MJB_PR_BIDI_CLASS_LRE,
    MJB_PR_BIDI_CLASS_LRO,
    MJB_PR_BIDI_CLASS_RLE,
    MJB_PR_BIDI_CLASS_RLO,
    MJB_PR_BIDI_CLASS_PDF,
    MJB_PR_BIDI_CLASS_LRI,
    MJB_PR_BIDI_CLASS_RLI,
    MJB_PR_BIDI_CLASS_FSI,
    MJB_PR_BIDI_CLASS_PDI
} mjb_bidi_class;

#define MJB_BIDI_CLASS_COUNT 24

/**
 * Bidi_Paired_Bracket_Type
 */
typedef enum mjb_bidi_paired_bracket_type {
    MJB_PR_BPT_NOT_SET, // 0 is "no value"
    MJB_PR_BPT_CLOSE,
    MJB_PR_BPT_NONE,
    MJB_PR_BPT_OPEN,
} mjb_bidi_paired_bracket_type;

#define MJB_BPT_COUNT 3

/**
 * Block (blk)
 */
typedef enum mjb_block {
    MJB_BLOCK_BASIC_LATIN,
    MJB_BLOCK_LATIN_1_SUPPLEMENT,
    MJB_BLOCK_LATIN_EXTENDED_A,
    MJB_BLOCK_LATIN_EXTENDED_B,
    MJB_BLOCK_IPA_EXTENSIONS,
    MJB_BLOCK_SPACING_MODIFIER_LETTERS,
    MJB_BLOCK_COMBINING_DIACRITICAL_MARKS,
    MJB_BLOCK_GREEK_AND_COPTIC,
    MJB_BLOCK_CYRILLIC,
    MJB_BLOCK_CYRILLIC_SUPPLEMENT,
    MJB_BLOCK_ARMENIAN,
    MJB_BLOCK_HEBREW,
    MJB_BLOCK_ARABIC,
    MJB_BLOCK_SYRIAC,
    MJB_BLOCK_ARABIC_SUPPLEMENT,
    MJB_BLOCK_THAANA,
    MJB_BLOCK_NKO,
    MJB_BLOCK_SAMARITAN,
    MJB_BLOCK_MANDAIC,
    MJB_BLOCK_SYRIAC_SUPPLEMENT,
    MJB_BLOCK_ARABIC_EXTENDED_B,
    MJB_BLOCK_ARABIC_EXTENDED_A,
    MJB_BLOCK_DEVANAGARI,
    MJB_BLOCK_BENGALI,
    MJB_BLOCK_GURMUKHI,
    MJB_BLOCK_GUJARATI,
    MJB_BLOCK_ORIYA,
    MJB_BLOCK_TAMIL,
    MJB_BLOCK_TELUGU,
    MJB_BLOCK_KANNADA,
    MJB_BLOCK_MALAYALAM,
    MJB_BLOCK_SINHALA,
    MJB_BLOCK_THAI,
    MJB_BLOCK_LAO,
    MJB_BLOCK_TIBETAN,
    MJB_BLOCK_MYANMAR,
    MJB_BLOCK_GEORGIAN,
    MJB_BLOCK_HANGUL_JAMO,
    MJB_BLOCK_ETHIOPIC,
    MJB_BLOCK_ETHIOPIC_SUPPLEMENT,
    MJB_BLOCK_CHEROKEE,
    MJB_BLOCK_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS,
    MJB_BLOCK_OGHAM,
    MJB_BLOCK_RUNIC,
    MJB_BLOCK_TAGALOG,
    MJB_BLOCK_HANUNOO,
    MJB_BLOCK_BUHID,
    MJB_BLOCK_TAGBANWA,
    MJB_BLOCK_KHMER,
    MJB_BLOCK_MONGOLIAN,
    MJB_BLOCK_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED,
    MJB_BLOCK_LIMBU,
    MJB_BLOCK_TAI_LE,
    MJB_BLOCK_NEW_TAI_LUE,
    MJB_BLOCK_KHMER_SYMBOLS,
    MJB_BLOCK_BUGINESE,
    MJB_BLOCK_TAI_THAM,
    MJB_BLOCK_COMBINING_DIACRITICAL_MARKS_EXTENDED,
    MJB_BLOCK_BALINESE,
    MJB_BLOCK_SUNDANESE,
    MJB_BLOCK_BATAK,
    MJB_BLOCK_LEPCHA,
    MJB_BLOCK_OL_CHIKI,
    MJB_BLOCK_CYRILLIC_EXTENDED_C,
    MJB_BLOCK_GEORGIAN_EXTENDED,
    MJB_BLOCK_SUNDANESE_SUPPLEMENT,
    MJB_BLOCK_VEDIC_EXTENSIONS,
    MJB_BLOCK_PHONETIC_EXTENSIONS,
    MJB_BLOCK_PHONETIC_EXTENSIONS_SUPPLEMENT,
    MJB_BLOCK_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT,
    MJB_BLOCK_LATIN_EXTENDED_ADDITIONAL,
    MJB_BLOCK_GREEK_EXTENDED,
    MJB_BLOCK_GENERAL_PUNCTUATION,
    MJB_BLOCK_SUPERSCRIPTS_AND_SUBSCRIPTS,
    MJB_BLOCK_CURRENCY_SYMBOLS,
    MJB_BLOCK_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS,
    MJB_BLOCK_LETTERLIKE_SYMBOLS,
    MJB_BLOCK_NUMBER_FORMS,
    MJB_BLOCK_ARROWS,
    MJB_BLOCK_MATHEMATICAL_OPERATORS,
    MJB_BLOCK_MISCELLANEOUS_TECHNICAL,
    MJB_BLOCK_CONTROL_PICTURES,
    MJB_BLOCK_OPTICAL_CHARACTER_RECOGNITION,
    MJB_BLOCK_ENCLOSED_ALPHANUMERICS,
    MJB_BLOCK_BOX_DRAWING,
    MJB_BLOCK_BLOCK_ELEMENTS,
    MJB_BLOCK_GEOMETRIC_SHAPES,
    MJB_BLOCK_MISCELLANEOUS_SYMBOLS,
    MJB_BLOCK_DINGBATS,
    MJB_BLOCK_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A,
    MJB_BLOCK_SUPPLEMENTAL_ARROWS_A,
    MJB_BLOCK_BRAILLE_PATTERNS,
    MJB_BLOCK_SUPPLEMENTAL_ARROWS_B,
    MJB_BLOCK_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B,
    MJB_BLOCK_SUPPLEMENTAL_MATHEMATICAL_OPERATORS,
    MJB_BLOCK_MISCELLANEOUS_SYMBOLS_AND_ARROWS,
    MJB_BLOCK_GLAGOLITIC,
    MJB_BLOCK_LATIN_EXTENDED_C,
    MJB_BLOCK_COPTIC,
    MJB_BLOCK_GEORGIAN_SUPPLEMENT,
    MJB_BLOCK_TIFINAGH,
    MJB_BLOCK_ETHIOPIC_EXTENDED,
    MJB_BLOCK_CYRILLIC_EXTENDED_A,
    MJB_BLOCK_SUPPLEMENTAL_PUNCTUATION,
    MJB_BLOCK_CJK_RADICALS_SUPPLEMENT,
    MJB_BLOCK_KANGXI_RADICALS,
    MJB_BLOCK_IDEOGRAPHIC_DESCRIPTION_CHARACTERS,
    MJB_BLOCK_CJK_SYMBOLS_AND_PUNCTUATION,
    MJB_BLOCK_HIRAGANA,
    MJB_BLOCK_KATAKANA,
    MJB_BLOCK_BOPOMOFO,
    MJB_BLOCK_HANGUL_COMPATIBILITY_JAMO,
    MJB_BLOCK_KANBUN,
    MJB_BLOCK_BOPOMOFO_EXTENDED,
    MJB_BLOCK_CJK_STROKES,
    MJB_BLOCK_KATAKANA_PHONETIC_EXTENSIONS,
    MJB_BLOCK_ENCLOSED_CJK_LETTERS_AND_MONTHS,
    MJB_BLOCK_CJK_COMPATIBILITY,
    MJB_BLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A,
    MJB_BLOCK_YIJING_HEXAGRAM_SYMBOLS,
    MJB_BLOCK_CJK_UNIFIED_IDEOGRAPHS,
    MJB_BLOCK_YI_SYLLABLES,
    MJB_BLOCK_YI_RADICALS,
    MJB_BLOCK_LISU,
    MJB_BLOCK_VAI,
    MJB_BLOCK_CYRILLIC_EXTENDED_B,
    MJB_BLOCK_BAMUM,
    MJB_BLOCK_MODIFIER_TONE_LETTERS,
    MJB_BLOCK_LATIN_EXTENDED_D,
    MJB_BLOCK_SYLOTI_NAGRI,
    MJB_BLOCK_COMMON_INDIC_NUMBER_FORMS,
    MJB_BLOCK_PHAGS_PA,
    MJB_BLOCK_SAURASHTRA,
    MJB_BLOCK_DEVANAGARI_EXTENDED,
    MJB_BLOCK_KAYAH_LI,
    MJB_BLOCK_REJANG,
    MJB_BLOCK_HANGUL_JAMO_EXTENDED_A,
    MJB_BLOCK_JAVANESE,
    MJB_BLOCK_MYANMAR_EXTENDED_B,
    MJB_BLOCK_CHAM,
    MJB_BLOCK_MYANMAR_EXTENDED_A,
    MJB_BLOCK_TAI_VIET,
    MJB_BLOCK_MEETEI_MAYEK_EXTENSIONS,
    MJB_BLOCK_ETHIOPIC_EXTENDED_A,
    MJB_BLOCK_LATIN_EXTENDED_E,
    MJB_BLOCK_CHEROKEE_SUPPLEMENT,
    MJB_BLOCK_MEETEI_MAYEK,
    MJB_BLOCK_HANGUL_SYLLABLES,
    MJB_BLOCK_HANGUL_JAMO_EXTENDED_B,
    MJB_BLOCK_HIGH_SURROGATES,
    MJB_BLOCK_HIGH_PRIVATE_USE_SURROGATES,
    MJB_BLOCK_LOW_SURROGATES,
    MJB_BLOCK_PRIVATE_USE_AREA,
    MJB_BLOCK_CJK_COMPATIBILITY_IDEOGRAPHS,
    MJB_BLOCK_ALPHABETIC_PRESENTATION_FORMS,
    MJB_BLOCK_ARABIC_PRESENTATION_FORMS_A,
    MJB_BLOCK_VARIATION_SELECTORS,
    MJB_BLOCK_VERTICAL_FORMS,
    MJB_BLOCK_COMBINING_HALF_MARKS,
    MJB_BLOCK_CJK_COMPATIBILITY_FORMS,
    MJB_BLOCK_SMALL_FORM_VARIANTS,
    MJB_BLOCK_ARABIC_PRESENTATION_FORMS_B,
    MJB_BLOCK_HALFWIDTH_AND_FULLWIDTH_FORMS,
    MJB_BLOCK_SPECIALS,
    MJB_BLOCK_LINEAR_B_SYLLABARY,
    MJB_BLOCK_LINEAR_B_IDEOGRAMS,
    MJB_BLOCK_AEGEAN_NUMBERS,
    MJB_BLOCK_ANCIENT_GREEK_NUMBERS,
    MJB_BLOCK_ANCIENT_SYMBOLS,
    MJB_BLOCK_PHAISTOS_DISC,
    MJB_BLOCK_LYCIAN,
    MJB_BLOCK_CARIAN,
    MJB_BLOCK_COPTIC_EPACT_NUMBERS,
    MJB_BLOCK_OLD_ITALIC,
    MJB_BLOCK_GOTHIC,
    MJB_BLOCK_OLD_PERMIC,
    MJB_BLOCK_UGARITIC,
    MJB_BLOCK_OLD_PERSIAN,
    MJB_BLOCK_DESERET,
    MJB_BLOCK_SHAVIAN,
    MJB_BLOCK_OSMANYA,
    MJB_BLOCK_OSAGE,
    MJB_BLOCK_ELBASAN,
    MJB_BLOCK_CAUCASIAN_ALBANIAN,
    MJB_BLOCK_VITHKUQI,
    MJB_BLOCK_TODHRI,
    MJB_BLOCK_LINEAR_A,
    MJB_BLOCK_LATIN_EXTENDED_F,
    MJB_BLOCK_CYPRIOT_SYLLABARY,
    MJB_BLOCK_IMPERIAL_ARAMAIC,
    MJB_BLOCK_PALMYRENE,
    MJB_BLOCK_NABATAEAN,
    MJB_BLOCK_HATRAN,
    MJB_BLOCK_PHOENICIAN,
    MJB_BLOCK_LYDIAN,
    MJB_BLOCK_SIDETIC,
    MJB_BLOCK_MEROITIC_HIEROGLYPHS,
    MJB_BLOCK_MEROITIC_CURSIVE,
    MJB_BLOCK_KHAROSHTHI,
    MJB_BLOCK_OLD_SOUTH_ARABIAN,
    MJB_BLOCK_OLD_NORTH_ARABIAN,
    MJB_BLOCK_MANICHAEAN,
    MJB_BLOCK_AVESTAN,
    MJB_BLOCK_INSCRIPTIONAL_PARTHIAN,
    MJB_BLOCK_INSCRIPTIONAL_PAHLAVI,
    MJB_BLOCK_PSALTER_PAHLAVI,
    MJB_BLOCK_OLD_TURKIC,
    MJB_BLOCK_OLD_HUNGARIAN,
    MJB_BLOCK_HANIFI_ROHINGYA,
    MJB_BLOCK_GARAY,
    MJB_BLOCK_RUMI_NUMERAL_SYMBOLS,
    MJB_BLOCK_YEZIDI,
    MJB_BLOCK_ARABIC_EXTENDED_C,
    MJB_BLOCK_OLD_SOGDIAN,
    MJB_BLOCK_SOGDIAN,
    MJB_BLOCK_OLD_UYGHUR,
    MJB_BLOCK_CHORASMIAN,
    MJB_BLOCK_ELYMAIC,
    MJB_BLOCK_BRAHMI,
    MJB_BLOCK_KAITHI,
    MJB_BLOCK_SORA_SOMPENG,
    MJB_BLOCK_CHAKMA,
    MJB_BLOCK_MAHAJANI,
    MJB_BLOCK_SHARADA,
    MJB_BLOCK_SINHALA_ARCHAIC_NUMBERS,
    MJB_BLOCK_KHOJKI,
    MJB_BLOCK_MULTANI,
    MJB_BLOCK_KHUDAWADI,
    MJB_BLOCK_GRANTHA,
    MJB_BLOCK_TULU_TIGALARI,
    MJB_BLOCK_NEWA,
    MJB_BLOCK_TIRHUTA,
    MJB_BLOCK_SIDDHAM,
    MJB_BLOCK_MODI,
    MJB_BLOCK_MONGOLIAN_SUPPLEMENT,
    MJB_BLOCK_TAKRI,
    MJB_BLOCK_MYANMAR_EXTENDED_C,
    MJB_BLOCK_AHOM,
    MJB_BLOCK_DOGRA,
    MJB_BLOCK_WARANG_CITI,
    MJB_BLOCK_DIVES_AKURU,
    MJB_BLOCK_NANDINAGARI,
    MJB_BLOCK_ZANABAZAR_SQUARE,
    MJB_BLOCK_SOYOMBO,
    MJB_BLOCK_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_A,
    MJB_BLOCK_PAU_CIN_HAU,
    MJB_BLOCK_DEVANAGARI_EXTENDED_A,
    MJB_BLOCK_SHARADA_SUPPLEMENT,
    MJB_BLOCK_SUNUWAR,
    MJB_BLOCK_BHAIKSUKI,
    MJB_BLOCK_MARCHEN,
    MJB_BLOCK_MASARAM_GONDI,
    MJB_BLOCK_GUNJALA_GONDI,
    MJB_BLOCK_TOLONG_SIKI,
    MJB_BLOCK_MAKASAR,
    MJB_BLOCK_KAWI,
    MJB_BLOCK_LISU_SUPPLEMENT,
    MJB_BLOCK_TAMIL_SUPPLEMENT,
    MJB_BLOCK_CUNEIFORM,
    MJB_BLOCK_CUNEIFORM_NUMBERS_AND_PUNCTUATION,
    MJB_BLOCK_EARLY_DYNASTIC_CUNEIFORM,
    MJB_BLOCK_CYPRO_MINOAN,
    MJB_BLOCK_EGYPTIAN_HIEROGLYPHS,
    MJB_BLOCK_EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS,
    MJB_BLOCK_EGYPTIAN_HIEROGLYPHS_EXTENDED_A,
    MJB_BLOCK_ANATOLIAN_HIEROGLYPHS,
    MJB_BLOCK_GURUNG_KHEMA,
    MJB_BLOCK_BAMUM_SUPPLEMENT,
    MJB_BLOCK_MRO,
    MJB_BLOCK_TANGSA,
    MJB_BLOCK_BASSA_VAH,
    MJB_BLOCK_PAHAWH_HMONG,
    MJB_BLOCK_KIRAT_RAI,
    MJB_BLOCK_MEDEFAIDRIN,
    MJB_BLOCK_BERIA_ERFE,
    MJB_BLOCK_MIAO,
    MJB_BLOCK_IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION,
    MJB_BLOCK_TANGUT,
    MJB_BLOCK_TANGUT_COMPONENTS,
    MJB_BLOCK_KHITAN_SMALL_SCRIPT,
    MJB_BLOCK_TANGUT_SUPPLEMENT,
    MJB_BLOCK_TANGUT_COMPONENTS_SUPPLEMENT,
    MJB_BLOCK_KANA_EXTENDED_B,
    MJB_BLOCK_KANA_SUPPLEMENT,
    MJB_BLOCK_KANA_EXTENDED_A,
    MJB_BLOCK_SMALL_KANA_EXTENSION,
    MJB_BLOCK_NUSHU,
    MJB_BLOCK_DUPLOYAN,
    MJB_BLOCK_SHORTHAND_FORMAT_CONTROLS,
    MJB_BLOCK_SYMBOLS_FOR_LEGACY_COMPUTING_SUPPLEMENT,
    MJB_BLOCK_MISCELLANEOUS_SYMBOLS_SUPPLEMENT,
    MJB_BLOCK_ZNAMENNY_MUSICAL_NOTATION,
    MJB_BLOCK_BYZANTINE_MUSICAL_SYMBOLS,
    MJB_BLOCK_MUSICAL_SYMBOLS,
    MJB_BLOCK_ANCIENT_GREEK_MUSICAL_NOTATION,
    MJB_BLOCK_KAKTOVIK_NUMERALS,
    MJB_BLOCK_MAYAN_NUMERALS,
    MJB_BLOCK_TAI_XUAN_JING_SYMBOLS,
    MJB_BLOCK_COUNTING_ROD_NUMERALS,
    MJB_BLOCK_MATHEMATICAL_ALPHANUMERIC_SYMBOLS,
    MJB_BLOCK_SUTTON_SIGNWRITING,
    MJB_BLOCK_LATIN_EXTENDED_G,
    MJB_BLOCK_GLAGOLITIC_SUPPLEMENT,
    MJB_BLOCK_CYRILLIC_EXTENDED_D,
    MJB_BLOCK_NYIAKENG_PUACHUE_HMONG,
    MJB_BLOCK_TOTO,
    MJB_BLOCK_WANCHO,
    MJB_BLOCK_NAG_MUNDARI,
    MJB_BLOCK_OL_ONAL,
    MJB_BLOCK_TAI_YO,
    MJB_BLOCK_ETHIOPIC_EXTENDED_B,
    MJB_BLOCK_MENDE_KIKAKUI,
    MJB_BLOCK_ADLAM,
    MJB_BLOCK_INDIC_SIYAQ_NUMBERS,
    MJB_BLOCK_OTTOMAN_SIYAQ_NUMBERS,
    MJB_BLOCK_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS,
    MJB_BLOCK_MAHJONG_TILES,
    MJB_BLOCK_DOMINO_TILES,
    MJB_BLOCK_PLAYING_CARDS,
    MJB_BLOCK_ENCLOSED_ALPHANUMERIC_SUPPLEMENT,
    MJB_BLOCK_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT,
    MJB_BLOCK_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS,
    MJB_BLOCK_EMOTICONS,
    MJB_BLOCK_ORNAMENTAL_DINGBATS,
    MJB_BLOCK_TRANSPORT_AND_MAP_SYMBOLS,
    MJB_BLOCK_ALCHEMICAL_SYMBOLS,
    MJB_BLOCK_GEOMETRIC_SHAPES_EXTENDED,
    MJB_BLOCK_SUPPLEMENTAL_ARROWS_C,
    MJB_BLOCK_SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS,
    MJB_BLOCK_CHESS_SYMBOLS,
    MJB_BLOCK_SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A,
    MJB_BLOCK_SYMBOLS_FOR_LEGACY_COMPUTING,
    MJB_BLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B,
    MJB_BLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C,
    MJB_BLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D,
    MJB_BLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E,
    MJB_BLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F,
    MJB_BLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_I,
    MJB_BLOCK_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT,
    MJB_BLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G,
    MJB_BLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_H,
    MJB_BLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_J,
    MJB_BLOCK_TAGS,
    MJB_BLOCK_VARIATION_SELECTORS_SUPPLEMENT,
    MJB_BLOCK_SUPPLEMENTARY_PRIVATE_USE_AREA_A,
    MJB_BLOCK_SUPPLEMENTARY_PRIVATE_USE_AREA_B
} mjb_block;

#define MJB_BLOCK_NUM 346

/**
 * Unicode codepoint general category
 * [see: https://www.unicode.org/glossary/#general_category]
 */
typedef enum mjb_category {
    MJB_CATEGORY_LU, // 0 (Lu) Letter, uppercase
    MJB_CATEGORY_LL, // 1 (Ll) Letter, lowercase
    MJB_CATEGORY_LT, // 2 (Lt) Letter, titlecase
    MJB_CATEGORY_LM, // 3 (Lm) Letter, modifier
    MJB_CATEGORY_LO, // 4 (Lo) Letter, other
    MJB_CATEGORY_MN, // 5 (Mn) Mark, non-spacing
    MJB_CATEGORY_MC, // 6 (Mc) Mark, spacing combining
    MJB_CATEGORY_ME, // 7 (Me) Mark, enclosing
    MJB_CATEGORY_ND, // 8 (Nd) Number, decimal digit
    MJB_CATEGORY_NL, // 9 (Nl) Number, letter
    MJB_CATEGORY_NO, // 10 (No) Number, other
    MJB_CATEGORY_PC, // 11 (Pc) Punctuation, connector
    MJB_CATEGORY_PD, // 12 (Pd) Punctuation, dash
    MJB_CATEGORY_PS, // 13 (Ps) Punctuation, open
    MJB_CATEGORY_PE, // 14 (Pe) Punctuation, close
    MJB_CATEGORY_PI, // 15 (Pi) Punctuation, initial quote
    MJB_CATEGORY_PF, // 16 (Pf) Punctuation, final quote
    MJB_CATEGORY_PO, // 17 (Po) Punctuation, other
    MJB_CATEGORY_SM, // 18 (Sm) Symbol, math
    MJB_CATEGORY_SC, // 19 (Sc) Symbol, currency
    MJB_CATEGORY_SK, // 20 (Sk) Symbol, modifier
    MJB_CATEGORY_SO, // 21 (So) Symbol, other
    MJB_CATEGORY_ZS, // 22 (Zs) Separator, space
    MJB_CATEGORY_ZL, // 23 (Zl) Separator, line
    MJB_CATEGORY_ZP, // 24 (Zp) Separator, paragraph
    MJB_CATEGORY_CC, // 25 (Cc) Other, control
    MJB_CATEGORY_CF, // 26 (Cf) Other, format
    MJB_CATEGORY_CS, // 27 (Cs) Other, surrogate
    MJB_CATEGORY_CO, // 28 (Co) Other, private use
    MJB_CATEGORY_CN  // 29 (Cn) Other, not assigned
} mjb_category;

#define MJB_CATEGORY_COUNT 30

/**
 * Unicode canonical combining class
 * [see: https://www.unicode.org/glossary/#combining_class]
 */
typedef enum mjb_canonical_combining_class {
    MJB_CCC_NOT_REORDERED = 0,
    MJB_CCC_OVERLAY = 1,
    MJB_CCC_HAN_READING = 6,
    MJB_CCC_NUKTA = 7,
    MJB_CCC_KANA_VOICING = 8,
    MJB_CCC_VIRAMA = 9,
    MJB_CCC_10 = 10,
    MJB_CCC_11 = 11,
    MJB_CCC_12 = 12,
    MJB_CCC_13 = 13,
    MJB_CCC_14 = 14,
    MJB_CCC_15 = 15,
    MJB_CCC_16 = 16,
    MJB_CCC_17 = 17,
    MJB_CCC_18 = 18,
    MJB_CCC_19 = 19,
    MJB_CCC_20 = 20,
    MJB_CCC_21 = 21,
    MJB_CCC_22 = 22,
    MJB_CCC_23 = 23,
    MJB_CCC_24 = 24,
    MJB_CCC_25 = 25,
    MJB_CCC_26 = 26,
    MJB_CCC_27 = 27,
    MJB_CCC_28 = 28,
    MJB_CCC_29 = 29,
    MJB_CCC_30 = 30,
    MJB_CCC_31 = 31,
    MJB_CCC_32 = 32,
    MJB_CCC_33 = 33,
    MJB_CCC_34 = 34,
    MJB_CCC_35 = 35,
    MJB_CCC_36 = 36,
    MJB_CCC_84 = 84,
    MJB_CCC_91 = 91,
    MJB_CCC_103 = 103,
    MJB_CCC_107 = 107,
    MJB_CCC_118 = 118,
    MJB_CCC_122 = 122,
    MJB_CCC_129 = 129,
    MJB_CCC_130 = 130,
    MJB_CCC_132 = 132,
    // MJB_CCC_133 reserved
    MJB_CCC_ATTACHED_BELOW_LEFT = 200,
    MJB_CCC_ATTACHED_BELOW = 202,
    MJB_CCC_ATTACHED_ABOVE = 214,
    MJB_CCC_ATTACHED_ABOVE_RIGHT = 216,
    MJB_CCC_BELOW_LEFT = 218,
    MJB_CCC_BELOW = 220,
    MJB_CCC_BELOW_RIGHT = 222,
    MJB_CCC_LEFT = 224,
    MJB_CCC_RIGHT = 226,
    MJB_CCC_ABOVE_LEFT = 228,
    MJB_CCC_ABOVE = 230,
    MJB_CCC_ABOVE_RIGHT = 232,
    MJB_CCC_DOUBLE_BELOW = 233,
    MJB_CCC_DOUBLE_ABOVE = 234,
    MJB_CCC_BELOW_IOTA = 240
} mjb_canonical_combining_class;

#define MJB_CCC_COUNT 62

/**
 * Decomposition_Type (dt)
 */
typedef enum mjb_decomposition {
    MJB_DECOMPOSITION_NONE,
    MJB_DECOMPOSITION_CANONICAL,
    MJB_DECOMPOSITION_CIRCLE,
    MJB_DECOMPOSITION_COMPAT,
    MJB_DECOMPOSITION_FINAL,
    MJB_DECOMPOSITION_FONT,
    MJB_DECOMPOSITION_FRACTION,
    MJB_DECOMPOSITION_INITIAL,
    MJB_DECOMPOSITION_ISOLATED,
    MJB_DECOMPOSITION_MEDIAL,
    MJB_DECOMPOSITION_NARROW,
    MJB_DECOMPOSITION_NOBREAK,
    MJB_DECOMPOSITION_SMALL,
    MJB_DECOMPOSITION_SQUARE,
    MJB_DECOMPOSITION_SUB,
    MJB_DECOMPOSITION_SUPER,
    MJB_DECOMPOSITION_VERTICAL,
    MJB_DECOMPOSITION_WIDE
} mjb_decomposition;

/**
 * East_Asian_Width (ea)
 */
typedef enum mjb_east_asian_width {
    MJB_EAW_NOT_SET, // 0 is "no value"
    MJB_EAW_AMBIGUOUS,
    MJB_EAW_FULL_WIDTH,
    MJB_EAW_HALF_WIDTH,
    MJB_EAW_NEUTRAL,
    MJB_EAW_NARROW,
    MJB_EAW_WIDE
} mjb_east_asian_width;

#define MJB_EAW_COUNT 6

/**
 * General_Category (gc)
 */
typedef enum mjb_general_category {
    MJB_GC_NOT_SET, // 0 is "no value"
    MJB_GC_OTHER,
    MJB_GC_CONTROL,
    MJB_GC_FORMAT,
    MJB_GC_UNASSIGNED,
    MJB_GC_PRIVATE_USE,
    MJB_GC_SURROGATE,
    MJB_GC_LETTER,
    MJB_GC_CASED_LETTER,
    MJB_GC_LOWERCASE_LETTER,
    MJB_GC_MODIFIER_LETTER,
    MJB_GC_OTHER_LETTER,
    MJB_GC_TITLECASE_LETTER,
    MJB_GC_UPPERCASE_LETTER,
    MJB_GC_MARK,
    MJB_GC_SPACING_MARK,
    MJB_GC_ENCLOSING_MARK,
    MJB_GC_NONSPACING_MARK,
    MJB_GC_NUMBER,
    MJB_GC_DECIMAL_NUMBER,
    MJB_GC_LETTER_NUMBER,
    MJB_GC_OTHER_NUMBER,
    MJB_GC_PUNCTUATION,
    MJB_GC_CONNECTOR_PUNCTUATION,
    MJB_GC_DASH_PUNCTUATION,
    MJB_GC_CLOSE_PUNCTUATION,
    MJB_GC_FINAL_PUNCTUATION,
    MJB_GC_INITIAL_PUNCTUATION,
    MJB_GC_OTHER_PUNCTUATION,
    MJB_GC_OPEN_PUNCTUATION,
    MJB_GC_SYMBOL,
    MJB_GC_CURRENCY_SYMBOL,
    MJB_GC_MODIFIER_SYMBOL,
    MJB_GC_MATH_SYMBOL,
    MJB_GC_OTHER_SYMBOL,
    MJB_GC_SEPARATOR,
    MJB_GC_LINE_SEPARATOR,
    MJB_GC_PARAGRAPH_SEPARATOR,
    MJB_GC_SPACE_SEPARATOR
} mjb_general_category;

#define MJB_GC_COUNT 24

/**
 * Grapheme_Cluster_Break (GCB)
 */
typedef enum mjb_gcb {
    MJB_GBP_NOT_SET, // 0 is "no value"
    MJB_GBP_CONTROL,
    MJB_GBP_CR,
    MJB_GBP_E_BASE, // obsolete
    MJB_GBP_E_BASE_GAZ, // obsolete
    MJB_GBP_E_MODIFIER, // obsolete
    MJB_GBP_EXTEND,
    MJB_GBP_GLUE_AFTER_ZWJ,
    MJB_GBP_L,
    MJB_GBP_LF,
    MJB_GBP_LV,
    MJB_GBP_LVT,
    MJB_GBP_PREPEND,
    MJB_GBP_REGIONAL_INDICATOR,
    MJB_GBP_SPACING_MARK,
    MJB_GBP_T,
    MJB_GBP_V,
    MJB_GBP_OTHER,
    MJB_GBP_ZWJ
} mjb_gcb;

#define MJB_GCB_COUNT 18

/**
 * Hangul_Syllable_Type (hst)
 */
typedef enum mjb_hangul_syllable_type {
    MJB_HST_NOT_SET, // 0 is "no value"
    MJB_HST_L,
    MJB_HST_LV,
    MJB_HST_LVT,
    MJB_HST_NA,
    MJB_HST_T,
    MJB_HST_V,
} mjb_hangul_syllable_type;

#define MJB_HST_COUNT 6

typedef enum mjb_indic_conjunct_break {
    MJB_INCB_NOT_SET, // 0 is "no value"
    MJB_INCB_CONSONANT,
    MJB_INCB_EXTEND,
    MJB_INCB_LINKER,
    MJB_INCB_NONE,
} mjb_indic_conjunct_break;

#define MJB_INCB_COUNT 5

/**
 * Unicode plane
 * [see: https://www.unicode.org/glossary/#plane]
 */
typedef enum mjb_plane {
    MJB_PLANE_NOT_VALID = -1,
    MJB_PLANE_BMP =        0,
    MJB_PLANE_SMP =        1,
    MJB_PLANE_SIP =        2,
    MJB_PLANE_TIP =        3,
    MJB_PLANE_SSP =        4,
    MJB_PLANE_PUA_A =      5,
    MJB_PLANE_PUA_B =     16
} mjb_plane;

#define MJB_PLANE_NUM 17 // 17 planes
#define MJB_PLANE_SIZE 65536 // 2^16 code points per plane

/**
 * Word_Break Property Values
 * https://www.unicode.org/reports/tr29/#Table_Word_Break_Property_Values
 */
typedef enum mjb_wbp {
    MJB_WBP_NOT_SET, // 0 is "no value"
    MJB_WBP_CR,
    MJB_WBP_DOUBLE_QUOTE,
    MJB_WBP_E_BASE,
    MJB_WBP_E_BASE_GAZ,
    MJB_WBP_E_MODIFIER,
    MJB_WBP_EXTEND_NUM_LET,
    MJB_WBP_EXTEND,
    MJB_WBP_FORMAT,
    MJB_WBP_GLUE_AFTER_ZWJ,
    MJB_WBP_HEBREW_LETTER,
    MJB_WBP_KATAKANA,
    MJB_WBP_A_LETTER,
    MJB_WBP_LF,
    MJB_WBP_MID_NUM_LET,
    MJB_WBP_MID_LETTER,
    MJB_WBP_MID_NUM,
    MJB_WBP_NEWLINE,
    MJB_WBP_NUMERIC,
    MJB_WBP_REGIONAL_INDICATOR,
    MJB_WBP_SINGLE_QUOTE,
    MJB_WBP_W_SEG_SPACE,
    MJB_WBP_OTHER,
    MJB_WBP_ZWJ
} mjb_wbp;

#define MJB_WBP_COUNT 24

typedef enum mjb_lbp {
    MJB_LBP_NOT_SET, // 0 is "no value"
    MJB_LBP_AI,
    MJB_LBP_AK,
    MJB_LBP_AL,
    MJB_LBP_AP,
    MJB_LBP_AS,
    MJB_LBP_B2,
    MJB_LBP_BA,
    MJB_LBP_BB,
    MJB_LBP_BK,
    MJB_LBP_CB,
    MJB_LBP_CJ,
    MJB_LBP_CL,
    MJB_LBP_CM,
    MJB_LBP_CP,
    MJB_LBP_CR,
    MJB_LBP_EB,
    MJB_LBP_EM,
    MJB_LBP_EX,
    MJB_LBP_GL,
    MJB_LBP_H2,
    MJB_LBP_H3,
    MJB_LBP_HH,
    MJB_LBP_HL,
    MJB_LBP_HY,
    MJB_LBP_ID,
    MJB_LBP_IN,
    MJB_LBP_IS,
    MJB_LBP_JL,
    MJB_LBP_JT,
    MJB_LBP_JV,
    MJB_LBP_LF,
    MJB_LBP_NL,
    MJB_LBP_NS,
    MJB_LBP_NU,
    MJB_LBP_OP,
    MJB_LBP_PO,
    MJB_LBP_PR,
    MJB_LBP_QU,
    MJB_LBP_RI,
    MJB_LBP_SA,
    MJB_LBP_SG,
    MJB_LBP_SP,
    MJB_LBP_SY,
    MJB_LBP_VF,
    MJB_LBP_VI,
    MJB_LBP_WJ,
    MJB_LBP_XX,
    MJB_LBP_ZW,
    MJB_LBP_ZWJ
} mjb_lbp;

#define MJB_LBP_COUNT 50

typedef enum mjb_sbp {
    MJB_SBP_NOT_SET, // 0 is "no value"
    MJB_SBP_ATERM,
    MJB_SBP_CLOSE,
    MJB_SBP_CR,
    MJB_SBP_EXTEND,
    MJB_SBP_FORMAT,
    MJB_SBP_OLETTER,
    MJB_SBP_LF,
    MJB_SBP_LOWER,
    MJB_SBP_NUMERIC,
    MJB_SBP_SCONTINUE,
    MJB_SBP_SEP,
    MJB_SBP_SP,
    MJB_SBP_STERM,
    MJB_SBP_UPPER,
    MJB_SBP_OTHER
} mjb_sbp;

#define MJB_SBP_COUNT 16

typedef enum mjb_property {
    MJB_PR_KACCOUNTINGNUMERIC, // enumerated
    MJB_PR_KOTHERNUMERIC, // enumerated
    MJB_PR_KPRIMARYNUMERIC, // enumerated
    MJB_PR_NUMERIC_VALUE, // enumerated
    MJB_PR_BIDI_MIRRORING_GLYPH, // enumerated
    MJB_PR_BIDI_PAIRED_BRACKET, // enumerated
    MJB_PR_CASE_FOLDING, // enumerated
    MJB_PR_KCOMPATIBILITYVARIANT, // enumerated
    MJB_PR_DECOMPOSITION_MAPPING, // enumerated
    MJB_PR_EQUIVALENT_UNIFIED_IDEOGRAPH, // enumerated
    MJB_PR_FC_NFKC_CLOSURE, // enumerated
    MJB_PR_LOWERCASE_MAPPING, // enumerated
    MJB_PR_NFKC_CASEFOLD, // enumerated
    MJB_PR_NFKC_SIMPLE_CASEFOLD, // enumerated
    MJB_PR_SIMPLE_CASE_FOLDING, // enumerated
    MJB_PR_SIMPLE_LOWERCASE_MAPPING, // enumerated
    MJB_PR_SIMPLE_TITLECASE_MAPPING, // enumerated
    MJB_PR_SIMPLE_UPPERCASE_MAPPING, // enumerated
    MJB_PR_TITLECASE_MAPPING, // enumerated
    MJB_PR_UPPERCASE_MAPPING, // enumerated
    MJB_PR_KIICORE, // enumerated
    MJB_PR_KIRG_GSOURCE, // enumerated
    MJB_PR_KIRG_HSOURCE, // enumerated
    MJB_PR_KIRG_JSOURCE, // enumerated
    MJB_PR_KIRG_KPSOURCE, // enumerated
    MJB_PR_KIRG_KSOURCE, // enumerated
    MJB_PR_KIRG_MSOURCE, // enumerated
    MJB_PR_KIRG_SSOURCE, // enumerated
    MJB_PR_KIRG_TSOURCE, // enumerated
    MJB_PR_KIRG_UKSOURCE, // enumerated
    MJB_PR_KIRG_USOURCE, // enumerated
    MJB_PR_KIRG_VSOURCE, // enumerated
    MJB_PR_KMANDARIN, // enumerated
    MJB_PR_KRSUNICODE, // enumerated
    MJB_PR_KTOTALSTROKES, // enumerated
    MJB_PR_KUNIHANCORE2020, // enumerated
    MJB_PR_ISO_COMMENT, // enumerated
    MJB_PR_JAMO_SHORT_NAME, // enumerated
    MJB_PR_KEH_CAT, // enumerated
    MJB_PR_KEH_DESC, // enumerated
    MJB_PR_KEH_HG, // enumerated
    MJB_PR_KEH_IFAO, // enumerated
    MJB_PR_KEH_JSESH, // enumerated
    MJB_PR_NAME, // enumerated
    MJB_PR_NAME_ALIAS, // enumerated
    MJB_PR_SCRIPT_EXTENSIONS, // enumerated
    MJB_PR_AGE, // enumerated
    MJB_PR_SCRIPT, // enumerated
    MJB_PR_BIDI_PAIRED_BRACKET_TYPE, // enumerated
    MJB_PR_CANONICAL_COMBINING_CLASS, // enumerated
    MJB_PR_DECOMPOSITION_TYPE, // enumerated
    MJB_PR_EAST_ASIAN_WIDTH, // enumerated
    MJB_PR_GENERAL_CATEGORY, // enumerated
    MJB_PR_GRAPHEME_CLUSTER_BREAK, // enumerated
    MJB_PR_HANGUL_SYLLABLE_TYPE, // enumerated
    MJB_PR_INDIC_CONJUNCT_BREAK, // enumerated
    MJB_PR_INDIC_POSITIONAL_CATEGORY, // enumerated
    MJB_PR_INDIC_SYLLABIC_CATEGORY, // enumerated
    MJB_PR_JOINING_GROUP, // enumerated
    MJB_PR_JOINING_TYPE, // enumerated
    MJB_PR_LINE_BREAK, // enumerated
    MJB_PR_NFC_QUICK_CHECK, // enumerated
    MJB_PR_NFD_QUICK_CHECK,
    MJB_PR_NFKC_QUICK_CHECK, // enumerated
    MJB_PR_NFKD_QUICK_CHECK,
    MJB_PR_NUMERIC_TYPE, // enumerated
    MJB_PR_SENTENCE_BREAK, // enumerated
    MJB_PR_VERTICAL_ORIENTATION, // enumerated
    MJB_PR_WORD_BREAK, // enumerated
    MJB_PR_ASCII_HEX_DIGIT,
    MJB_PR_ALPHABETIC,
    MJB_PR_BIDI_CONTROL,
    MJB_PR_BIDI_MIRRORED,
    MJB_PR_CASED,
    MJB_PR_COMPOSITION_EXCLUSION,
    MJB_PR_CASE_IGNORABLE,
    MJB_PR_FULL_COMPOSITION_EXCLUSION,
    MJB_PR_CHANGES_WHEN_CASEFOLDED,
    MJB_PR_CHANGES_WHEN_CASEMAPPED,
    MJB_PR_CHANGES_WHEN_NFKC_CASEFOLDED,
    MJB_PR_CHANGES_WHEN_LOWERCASED,
    MJB_PR_CHANGES_WHEN_TITLECASED,
    MJB_PR_CHANGES_WHEN_UPPERCASED,
    MJB_PR_DASH,
    MJB_PR_DEPRECATED,
    MJB_PR_DEFAULT_IGNORABLE_CODE_POINT,
    MJB_PR_DIACRITIC,
    MJB_PR_EMOJI_MODIFIER_BASE,
    MJB_PR_EMOJI_COMPONENT,
    MJB_PR_EMOJI_MODIFIER,
    MJB_PR_EMOJI,
    MJB_PR_EMOJI_PRESENTATION,
    MJB_PR_EXTENDER,
    MJB_PR_EXTENDED_PICTOGRAPHIC,
    MJB_PR_GRAPHEME_BASE,
    MJB_PR_GRAPHEME_EXTEND,
    MJB_PR_GRAPHEME_LINK,
    MJB_PR_HEX_DIGIT,
    MJB_PR_HYPHEN,
    MJB_PR_ID_COMPAT_MATH_CONTINUE,
    MJB_PR_ID_COMPAT_MATH_START,
    MJB_PR_ID_CONTINUE,
    MJB_PR_IDEOGRAPHIC,
    MJB_PR_ID_START,
    MJB_PR_IDS_BINARY_OPERATOR,
    MJB_PR_IDS_TRINARY_OPERATOR,
    MJB_PR_IDS_UNARY_OPERATOR,
    MJB_PR_JOIN_CONTROL,
    MJB_PR_KEH_NOMIRROR,
    MJB_PR_KEH_NOROTATE,
    MJB_PR_LOGICAL_ORDER_EXCEPTION,
    MJB_PR_LOWERCASE,
    MJB_PR_MATH,
    MJB_PR_MODIFIER_COMBINING_MARK,
    MJB_PR_NONCHARACTER_CODE_POINT,
    MJB_PR_OTHER_ALPHABETIC,
    MJB_PR_OTHER_DEFAULT_IGNORABLE_CODE_POINT,
    MJB_PR_OTHER_GRAPHEME_EXTEND,
    MJB_PR_OTHER_ID_CONTINUE,
    MJB_PR_OTHER_ID_START,
    MJB_PR_OTHER_LOWERCASE,
    MJB_PR_OTHER_MATH,
    MJB_PR_OTHER_UPPERCASE,
    MJB_PR_PATTERN_SYNTAX,
    MJB_PR_PATTERN_WHITE_SPACE,
    MJB_PR_PREPENDED_CONCATENATION_MARK,
    MJB_PR_QUOTATION_MARK,
    MJB_PR_RADICAL,
    MJB_PR_REGIONAL_INDICATOR,
    MJB_PR_SOFT_DOTTED,
    MJB_PR_SENTENCE_TERMINAL,
    MJB_PR_TERMINAL_PUNCTUATION,
    MJB_PR_UNIFIED_IDEOGRAPH,
    MJB_PR_UPPERCASE,
    MJB_PR_VARIATION_SELECTOR,
    MJB_PR_WHITE_SPACE,
    MJB_PR_XID_CONTINUE,
    MJB_PR_XID_START,
    MJB_PR_EXPANDS_ON_NFC,
    MJB_PR_EXPANDS_ON_NFD,
    MJB_PR_EXPANDS_ON_NFKC,
    MJB_PR_EXPANDS_ON_NFKD
} mjb_property;

#define MJB_PR_COUNT 142

#define MJB_PR_ENUM_COUNT 67

#define MJB_PR_BOOL_COUNT 75

#define MJB_PR_BUFFER_SIZE 209

#endif // MJB_UNICODE_H

#ifdef __cplusplus
extern "C" {
#endif

// Static assertions for important constants
#if defined(__cplusplus)
    static_assert(sizeof(uint32_t) == 4, "uint32_t must be 4 bytes");
    static_assert(sizeof(char) == 1, "char must be 1 byte");
#else
    _Static_assert(sizeof(uint32_t) == 4, "uint32_t must be 4 bytes");
    _Static_assert(sizeof(char) == 1, "char must be 1 byte");
#endif

#define MJB_VERSION_NUMBER   0x14 // MAJOR << 8 | MINOR << 4 | REVISION
#define MJB_VERSION_MAJOR    0
#define MJB_VERSION_MINOR    1
#define MJB_VERSION_REVISION 4

#ifdef __EMSCRIPTEN__
    #define MJB_VERSION "0.1.4-WASM"
#else
    #define MJB_VERSION "0.1.4"
#endif

#define MJB_UNICODE_VERSION       "17.0.0"
#define MJB_UNICODE_VERSION_MAJOR 17
#define MJB_UNICODE_VERSION_MINOR 0
#define MJB_UNICODE_VERSION_REVISION 0

#ifndef MJB_EXTERN
    #define MJB_EXTERN extern
#endif

#ifndef MJB_EXPORT
    #if defined(_WIN32) || defined(_WIN64)
        #define MJB_EXPORT
    #elif defined(__GNUC__) || defined(__clang__)
        #define MJB_EXPORT __attribute__((visibility("default")))
    #else
        #define MJB_EXPORT
    #endif
#endif

// Modern compiler attributes with fallbacks
#if defined(__GNUC__) || defined(__clang__)
    #define MJB_NODISCARD __attribute__((warn_unused_result))
    #define MJB_NONNULL(...) __attribute__((nonnull(__VA_ARGS__)))
    #define MJB_PURE __attribute__((pure))
    #define MJB_CONST __attribute__((const))
#elif defined(__cplusplus) && __cplusplus >= 201703L
    #define MJB_NODISCARD [[nodiscard]]
    #define MJB_NONNULL(...)
    #define MJB_PURE
    #define MJB_CONST
#else
    #define MJB_NODISCARD
    #define MJB_NONNULL(...)
    #define MJB_PURE
    #define MJB_CONST
#endif

// See c standard memory allocation functions
typedef void *(*mjb_alloc_fn)(size_t size);
typedef void *(*mjb_realloc_fn)(void *ptr, size_t new_size);
typedef void (*mjb_free_fn)(void *ptr);

/**
 * A unicode codepoint, a value in the range 0 to 0x10FFFF
 * [see: https://www.unicode.org/glossary/#code_point]
 */
typedef uint32_t mjb_codepoint;

#define MJB_CODEPOINT_MIN         0x0
#define MJB_CODEPOINT_MAX         0x10FFFF // Maximum valid unicode code point
#define MJB_CODEPOINT_REPLACEMENT 0xFFFD   // The character used when there is invalid data "�"
#define MJB_PRIVATE_USE_START     0xF0000  // Private use area start
#define MJB_PRIVATE_USE_END       0x10FFFD // Private use area end
#define MJB_CODEPOINT_NOT_VALID   0x110000 // Not a valid codepoint

// Hangul Syllables constants
// See: https://www.unicode.org/versions/Unicode17.0.0/core-spec/chapter-3/#G61399
#define MJB_CP_HANGUL_S_BASE  0xAC00
#define MJB_CP_HANGUL_L_BASE  0x1100
#define MJB_CP_HANGUL_V_BASE  0x1161
#define MJB_CP_HANGUL_T_BASE  0x11A7
#define MJB_CP_HANGUL_L_COUNT 19
#define MJB_CP_HANGUL_V_COUNT 21
#define MJB_CP_HANGUL_T_COUNT 28
#define MJB_CP_HANGUL_N_COUNT 588   // V_COUNT * T_COUNT
#define MJB_CP_HANGUL_S_COUNT 11172 // L_COUNT * N_COUNT

// CJK Ideographs
#define MJB_CJK_IDEOGRAPH_START   0x4E00
#define MJB_CJK_IDEOGRAPH_END     0x9FFF
#define MJB_CJK_EXTENSION_A_START 0x3400
#define MJB_CJK_EXTENSION_A_END   0x4DBF
#define MJB_CJK_EXTENSION_B_START 0x20000
#define MJB_CJK_EXTENSION_B_END   0x2A6DF
#define MJB_CJK_EXTENSION_C_START 0x2A700
#define MJB_CJK_EXTENSION_C_END   0x2B739
#define MJB_CJK_EXTENSION_D_START 0x2B740
#define MJB_CJK_EXTENSION_D_END   0x2B81D
#define MJB_CJK_EXTENSION_E_START 0x2B820
#define MJB_CJK_EXTENSION_E_END   0x2CEA1
#define MJB_CJK_EXTENSION_F_START 0x2CEB0
#define MJB_CJK_EXTENSION_F_END   0x2EBE0
#define MJB_CJK_EXTENSION_I_START 0x2EBF0
#define MJB_CJK_EXTENSION_I_END   0x2EE5D

#define MJB_CJK_COMPATIBILITY_IDEOGRAPH_START 0xF900
#define MJB_CJK_COMPATIBILITY_IDEOGRAPH_END   0xFAD9

#define MJB_CJK_COMPATIBILITY_IDEOGRAPH_SUPPLEMENT_START 0x2F800
#define MJB_CJK_COMPATIBILITY_IDEOGRAPH_SUPPLEMENT_END   0x2FA1D

#define MJB_EGYPTIAN_H_START            0x13000
#define MJB_EGYPTIAN_H_FORMAT_EXT_START 0x13460
#define MJB_EGYPTIAN_H_EXT_END          0x143FF

// Tangut Ideographs
#define MJB_TANGUT_IDEOGRAPH_START 0x17000
#define MJB_TANGUT_IDEOGRAPH_END   0x187F7

#define MJB_TANGUT_IDEOGRAPH_SUPPLEMENT_START 0x18D00
#define MJB_TANGUT_IDEOGRAPH_SUPPLEMENT_END   0x18D1E

// Tangut components
#define MJB_TANGUT_COMPONENT_START 0x18800
#define MJB_TANGUT_COMPONENT_END   0x18AFF

#define MJB_TANGUT_COMPONENT_SUPPLEMENT_START 0x18D80
#define MJB_TANGUT_COMPONENT_SUPPLEMENT_END   0x18DF2

// Khitan Small Script Characters
#define MJB_KHITAN_SMALL_SCRIPT_CHARACTER_START 0x18B00
#define MJB_KHITAN_SMALL_SCRIPT_CHARACTER_END   0x18CFF

// Numeric values, to be used when the decimal and digit mjb_character fields are not valid
#define MJB_NUMBER_NOT_VALID -1

/**
 * Unicode encoding
 * [see: https://www.unicode.org/glossary/#character_encoding_scheme]
 */
typedef enum mjb_encoding {
    MJB_ENCODING_UNKNOWN =   0x0,
    MJB_ENCODING_ASCII =     0x1,
    MJB_ENCODING_UTF_8 =     0x2,
    MJB_ENCODING_UTF_16 =    0x4,
    MJB_ENCODING_UTF_16_BE = 0x8,
    MJB_ENCODING_UTF_16_LE = 0x10,
    MJB_ENCODING_UTF_32 =    0x20,
    MJB_ENCODING_UTF_32_BE = 0x40,
    MJB_ENCODING_UTF_32_LE = 0x80
} mjb_encoding;

/**
 * Normalization form
 * [see: https://www.unicode.org/glossary/#normalization_form]
 */
typedef enum mjb_normalization {
    MJB_NORMALIZATION_NFC,  // Canonical decomposition followed by canonical composition
    MJB_NORMALIZATION_NFD,  // Canonical decomposition without recomposition
    MJB_NORMALIZATION_NFKC, // Compatibility decomposition followed by canonical composition
    MJB_NORMALIZATION_NFKD  // Compatibility decomposition without recomposition
} mjb_normalization;

typedef enum mjb_quick_check_result {
    MJB_QC_YES        = 0x0,
    MJB_QC_NO         = 0x1,
    MJB_QC_MAYBE      = 0x2,
    // See: DerivedNormalizationProps.txt
    MJB_QC_NFD_NO     = 0x4,
    MJB_QC_NFD_MAYBE  = 0x8, // Impossible to happen
    MJB_QC_NFC_NO     = 0x10,
    MJB_QC_NFC_MAYBE  = 0x20,
    MJB_QC_NFKC_NO    = 0x40,
    MJB_QC_NFKC_MAYBE = 0x80,
    MJB_QC_NFKD_NO    = 0x100,
    MJB_QC_NFKD_MAYBE = 0x200 // Impossible to happen
} mjb_quick_check_result;

typedef enum mjb_filter {
    MJB_FILTER_NONE            = 0x0,
    MJB_FILTER_NORMALIZE       = 0x1,
    MJB_FILTER_SPACES          = 0x2,
    MJB_FILTER_COLLAPSE_SPACES = 0x4,
    MJB_FILTER_CONTROLS        = 0x8,
    MJB_FILTER_NUMERIC         = 0x10
} mjb_filter;

typedef enum mjb_case_type {
    MJB_CASE_NONE,
    MJB_CASE_UPPER,
    MJB_CASE_LOWER,
    MJB_CASE_TITLE,
    MJB_CASE_CASEFOLD
} mjb_case_type;

typedef struct mjb_result {
    char *output;
    size_t output_size;
    bool transformed;
} mjb_result;

/**
 * Unicode block
 * [see: https://www.unicode.org/glossary/#block]
 */
typedef struct mjb_block_info {
    mjb_block id;
    char name[128];
    uint32_t start;
    uint32_t end;
} mjb_block_info;

/**
 * A unicode character
 * [see: https://www.unicode.org/glossary/#character]
 */
typedef struct mjb_character {
    mjb_codepoint codepoint;
    char name[128];
    mjb_category category;
    mjb_canonical_combining_class combining;
    unsigned short bidirectional;
    mjb_decomposition decomposition;
    int decimal;
    int digit;
    char numeric[16];
    bool mirrored;
    mjb_codepoint uppercase;
    mjb_codepoint lowercase;
    mjb_codepoint titlecase;
} mjb_character;

/**
 * Emoji data
 * [see: https://www.unicode.org/reports/tr51]
 */
typedef struct mjb_emoji_properties {
    mjb_codepoint codepoint;
    bool emoji;
    bool presentation;
    bool modifier;
    bool modifier_base;
    bool component;
    bool extended_pictographic;
} mjb_emoji_properties;

typedef enum mjb_break_type {
    MJB_BT_NOT_SET, // Not set
    MJB_BT_MANDATORY, // !
    MJB_BT_NO_BREAK, // ×
    MJB_BT_ALLOWED // ÷
} mjb_break_type;

// Buffer character used in composition phase
typedef struct mjb_buffer_character {
    uint32_t codepoint;
    uint16_t combining;
} mjb_buffer_character;

// UTF-8 next character type
typedef enum mjb_next_character_type {
    MJB_NEXT_CHAR_NONE  = 0x0,
    MJB_NEXT_CHAR_FIRST = 0x1,
    MJB_NEXT_CHAR_LAST  = 0x2
} mjb_next_character_type;

// Display width context for ambiguous-width characters
typedef enum mjb_width_context {
    MJB_WIDTH_CONTEXT_WESTERN,    // Treat ambiguous characters as narrow (width 1)
    MJB_WIDTH_CONTEXT_EAST_ASIAN, // Treat ambiguous characters as wide (width 2)
    MJB_WIDTH_CONTEXT_AUTO        // Auto-detect from string content
} mjb_width_context;

typedef struct mjb_next_state {
    uint8_t state;
    size_t index;
    unsigned int previous;
    unsigned int current;
    mjb_codepoint previous_codepoint;
    mjb_codepoint current_codepoint;
    bool in_error;
    unsigned short ri_count;
    bool ext_pict_seen;
    bool zwj_seen;
    bool incb_consonant_seen;
    bool incb_linker_seen;
} mjb_next_state;

typedef struct mjb_next_line_state {
    uint8_t state;
    size_t index;
    mjb_lbp previous;
    mjb_lbp current;
    mjb_codepoint prev_prev_codepoint;
    mjb_codepoint previous_codepoint;
    mjb_codepoint current_codepoint;
    bool in_error;
    bool zw_seen;
    bool pi_qu_context;
    bool cm_merged;
    bool zwj_absorbed;
    unsigned short ri_count;
    mjb_lbp prev_resolved;
    mjb_east_asian_width prev_ea;
    mjb_east_asian_width qu_prev_ea;
    mjb_lbp prev_prev_lbp;
    mjb_lbp prev_num_lbp;
} mjb_next_line_state;

typedef struct mjb_next_word_state {
    uint8_t state;
    size_t index;
    mjb_wbp previous;
    mjb_wbp current;
    mjb_codepoint prev_prev_codepoint;
    mjb_codepoint previous_codepoint;
    mjb_codepoint current_codepoint;
    mjb_wbp prev_prev_wbp;
    bool in_error;
    unsigned short ri_count;
    bool wb4_merged;
    bool zwj_pending;
    bool prev_was_zwj;
} mjb_next_word_state;

typedef struct mjb_next_sentence_state {
    uint8_t state;
    size_t index;
    mjb_sbp previous;
    mjb_sbp current;
    mjb_sbp prev_prev;
    mjb_codepoint previous_codepoint;
    mjb_codepoint current_codepoint;
    bool in_error;
    bool sb5_merged;
    bool in_sat;
    bool sat_has_sp;
    bool sat_is_aterm;
} mjb_next_sentence_state;

typedef bool (*mjb_next_character_fn)(mjb_character *character, mjb_next_character_type type);

typedef enum mjb_direction {
    MJB_DIRECTION_LTR  = 0,
    MJB_DIRECTION_RTL  = 1,
    MJB_DIRECTION_AUTO = 2,
} mjb_direction;

typedef struct mjb_bidi_char {
    mjb_codepoint codepoint;
    size_t byte_offset;
    uint8_t level;
    mjb_bidi_class resolved_class;
    mjb_codepoint mirroring_glyph;
} mjb_bidi_char;

typedef struct mjb_bidi_paragraph {
    mjb_bidi_char *chars;
    size_t count;
    uint8_t paragraph_level;
    mjb_direction direction;
} mjb_bidi_paragraph;

typedef struct mjb_bidi_run {
    size_t start;
    size_t end;
    uint8_t level;
    mjb_direction direction;
} mjb_bidi_run;

// This functions list is automatically generated. Do not edit.

// Return the codepoint character
MJB_NONNULL(2) bool mjb_codepoint_character(mjb_codepoint codepoint, mjb_character *character);

// Normalize a string to NFC/NFKC/NFD/NFKD form
MJB_NONNULL(1, 5) bool mjb_normalize(const char *buffer, size_t size, mjb_encoding encoding, mjb_normalization form, mjb_result *result);

// Return the next character from a string
MJB_NONNULL(1, 4) bool mjb_next_character(const char *buffer, size_t size, mjb_encoding encoding, mjb_next_character_fn fn);

// Check if a string is normalized to NFC/NFKC/NFD/NFKD form
MJB_NONNULL(1) mjb_quick_check_result mjb_string_is_normalized(const char *buffer, size_t size, mjb_encoding encoding, mjb_normalization form);

// Filter a string to remove invalid characters
MJB_NONNULL(1, 6) bool mjb_string_filter(const char *buffer, size_t size, mjb_encoding encoding, mjb_encoding output_encoding, mjb_filter filters, mjb_result *result);

// Return if a codepoint has a property
bool mjb_codepoint_has_property(mjb_codepoint codepoint, mjb_property property, uint8_t *value);

// Return all properties of a codepoint
bool mjb_codepoint_properties(mjb_codepoint codepoint, uint8_t *buffer);

// Return a property value
uint8_t mjb_codepoint_property(uint8_t *properties, mjb_property property);

// Return the string encoding (the most probable)
MJB_PURE mjb_encoding mjb_string_encoding(const char *buffer, size_t size);

// Return true if the string is encoded in UTF-8
MJB_PURE bool mjb_string_is_utf8(const char *buffer, size_t size);

// Return true if the string is encoded in UTF-16BE or UTF-16LE
MJB_PURE bool mjb_string_is_utf16(const char *buffer, size_t size);

// Return true if the string is encoded in ASCII
MJB_PURE bool mjb_string_is_ascii(const char *buffer, size_t size);

// Encode a codepoint to a string
unsigned int mjb_codepoint_encode(mjb_codepoint codepoint, char *buffer, size_t size, mjb_encoding encoding);

// Convert from an encoding to another
MJB_NONNULL(1, 5) bool mjb_string_convert_encoding(const char *buffer, size_t size, mjb_encoding encoding, mjb_encoding output_encoding, mjb_result *result);

// Return the length of a string
MJB_PURE size_t mjb_strnlen(const char *buffer, size_t max_length, mjb_encoding encoding);

// Compare two strings
MJB_PURE MJB_NONNULL(1, 4) int mjb_string_compare(const char *s1, size_t s1_length, mjb_encoding s1_encoding, const char *s2, size_t s2_length, mjb_encoding s2_encoding);

// Change string case
MJB_NONNULL(1) char *mjb_case(const char *buffer, size_t size, mjb_case_type type, mjb_encoding encoding);

// Return true if the codepoint is valid
MJB_CONST bool mjb_codepoint_is_valid(mjb_codepoint codepoint);

// Return true if the codepoint is graphic
MJB_CONST bool mjb_codepoint_is_graphic(mjb_codepoint codepoint);

// Return true if the codepoint is combining
MJB_CONST bool mjb_codepoint_is_combining(mjb_codepoint codepoint);

// Return if the codepoint is an hangul L
MJB_CONST bool mjb_codepoint_is_hangul_l(mjb_codepoint codepoint);

// Return if the codepoint is an hangul V
MJB_CONST bool mjb_codepoint_is_hangul_v(mjb_codepoint codepoint);

// Return if the codepoint is an hangul T
MJB_CONST bool mjb_codepoint_is_hangul_t(mjb_codepoint codepoint);

// Return if the codepoint is an hangul jamo
MJB_CONST bool mjb_codepoint_is_hangul_jamo(mjb_codepoint codepoint);

// Return if the codepoint is an hangul syllable
MJB_CONST bool mjb_codepoint_is_hangul_syllable(mjb_codepoint codepoint);

// Return if the codepoint is CJK ideograph
MJB_CONST bool mjb_codepoint_is_cjk_ideograph(mjb_codepoint codepoint);

// Return true if the category is graphic
MJB_CONST bool mjb_category_is_graphic(mjb_category category);

// Return true if the category is combining
MJB_CONST bool mjb_category_is_combining(mjb_category category);

// Return the character block
MJB_CONST bool mjb_codepoint_block(mjb_codepoint codepoint, mjb_block_info *block);

// Return the codepoint lowercase codepoint
MJB_CONST mjb_codepoint mjb_codepoint_to_lowercase(mjb_codepoint codepoint);

// Return the codepoint uppercase codepoint
MJB_CONST mjb_codepoint mjb_codepoint_to_uppercase(mjb_codepoint codepoint);

// Return the codepoint titlecase codepoint
MJB_CONST mjb_codepoint mjb_codepoint_to_titlecase(mjb_codepoint codepoint);

// Unicode line break algorithm
MJB_NONNULL(1, 4) mjb_break_type mjb_break_line(const char *buffer, size_t size, mjb_encoding encoding, mjb_next_line_state *state);

// Word cluster breaking
MJB_NONNULL(1, 4) mjb_break_type mjb_break_word(const char *buffer, size_t size, mjb_encoding encoding, mjb_next_word_state *state);

// Sentence boundaries breaking
MJB_NONNULL(1, 4) mjb_break_type mjb_break_sentence(const char *buffer, size_t size, mjb_encoding encoding, mjb_next_sentence_state *state);

// Grapheme cluster breaking
MJB_NONNULL(1, 4) mjb_break_type mjb_segmentation(const char *buffer, size_t size, mjb_encoding encoding, mjb_next_state *state);

// Resolve bidirectional text (TR9) for a paragraph
MJB_NONNULL(1, 5) bool mjb_bidi_resolve(const char *buffer, size_t size, mjb_encoding encoding, mjb_direction direction, mjb_bidi_paragraph *result);

// Free a bidi paragraph allocated by mjb_bidi_resolve
MJB_NONNULL(1) void mjb_bidi_free(mjb_bidi_paragraph *paragraph);

// Reorder a line visually (L1-L4); visual_order is caller-allocated
MJB_NONNULL(1, 4) bool mjb_bidi_reorder_line(const mjb_bidi_paragraph *paragraph, size_t line_start, size_t line_end, size_t *visual_order);

// Compute visual level runs; pass runs=NULL to count first
MJB_NONNULL(1, 5) bool mjb_bidi_line_runs(const mjb_bidi_paragraph *paragraph, const size_t *visual_order, size_t count, mjb_bidi_run *runs, size_t *run_count);

// Return the plane of the codepoint
MJB_CONST mjb_plane mjb_codepoint_plane(mjb_codepoint codepoint);

// Return true if the plane is valid
MJB_CONST bool mjb_plane_is_valid(mjb_plane plane);

// Return the name of a plane, NULL if the place specified is not valid
MJB_CONST const char *mjb_plane_name(mjb_plane plane, bool abbreviation);

// Return the emoji properties
MJB_NONNULL(2) bool mjb_codepoint_emoji(mjb_codepoint codepoint, mjb_emoji_properties *emoji);

// Return hangul syllable name
MJB_NONNULL(2) bool mjb_hangul_syllable_name(mjb_codepoint codepoint, char *buffer, size_t size);

// Hangul syllable decomposition
MJB_NODISCARD MJB_NONNULL(2) bool mjb_hangul_syllable_decomposition(mjb_codepoint codepoint, mjb_codepoint *codepoints);

// Hangul syllable composition
MJB_NONNULL(1) size_t mjb_hangul_syllable_composition(mjb_buffer_character *characters, size_t characters_len);

// Return the east asian width of a codepoint
MJB_NONNULL(2) bool mjb_codepoint_east_asian_width(mjb_codepoint codepoint, mjb_east_asian_width *width);

// Return the display width of a string
MJB_NONNULL(1, 5) bool mjb_display_width(const char *buffer, size_t size, mjb_encoding encoding, mjb_width_context context, size_t *width);

// Output the current library version (MJB_VERSION)
MJB_CONST const char *mjb_version(void);

// Output the current library version number (MJB_VERSION_NUMBER)
MJB_CONST unsigned int mjb_version_number(void);

// Output the current supported unicode version (MJB_UNICODE_VERSION)
MJB_CONST const char *mjb_unicode_version(void);

// Initialize the library. Not needed to be called
MJB_NODISCARD bool mjb_initialize(void);

// Initialize the library with custom values. Not needed to be called
MJB_NODISCARD bool mjb_initialize_v2(mjb_alloc_fn alloc_fn, mjb_realloc_fn realloc_fn, mjb_free_fn free_fn, const char *db, size_t db_size);

// Shutdown the library. Not needed to be called
void mjb_shutdown(void);

// Allocate and zero memory
MJB_NODISCARD void *mjb_alloc(size_t size);

// Reallocate memory
MJB_NODISCARD MJB_NONNULL(1) void *mjb_realloc(void *ptr, size_t new_size);

// Free memory
MJB_NONNULL(1) void mjb_free(void *ptr);

#ifdef __cplusplus
}
#endif

#endif // MJB_MOJIBAKE_H
