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

// Embedded database enabled
#ifndef MJB_USE_EMBEDDED_DB
#define MJB_USE_EMBEDDED_DB
#endif

/**
 * 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.

/**
 * Unicode blocks
 */
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, // Spacing, split, enclosing, reordrant, and Tibetan subjoined
    MJB_CCC_OVERLAYS =             1, // Overlays and interior
    MJB_CCC_VIETNAMES_ALT =        6, // Vietnamese alternate reading
    MJB_CCC_NUKTA =                7, // Nukta
    MJB_CCC_KANA_VOICING =         8, // Hiragana/Katakana voicing marks
    MJB_CCC_VIRAMA =               9, // Viramas
    MJB_CCC_10 =                   10, // Start of fixed position classes
    MJB_CCC_11 =                   11, // No name
    MJB_CCC_12 =                   12, // No name
    MJB_CCC_13 =                   13, // No name
    MJB_CCC_14 =                   14, // No name
    MJB_CCC_15 =                   15, // No name
    MJB_CCC_16 =                   16, // No name
    MJB_CCC_17 =                   17, // No name
    MJB_CCC_18 =                   18, // No name
    MJB_CCC_19 =                   19, // No name
    MJB_CCC_20 =                   20, // No name
    MJB_CCC_21 =                   21, // No name
    MJB_CCC_22 =                   22, // No name
    MJB_CCC_23 =                   23, // No name
    MJB_CCC_24 =                   24, // No name
    MJB_CCC_25 =                   25, // No name
    MJB_CCC_26 =                   26, // No name
    MJB_CCC_27 =                   27, // No name
    MJB_CCC_28 =                   28, // No name
    MJB_CCC_29 =                   29, // No name
    MJB_CCC_30 =                   30, // No name
    MJB_CCC_31 =                   31, // No name
    MJB_CCC_32 =                   32, // No name
    MJB_CCC_33 =                   33, // No name
    MJB_CCC_34 =                   34, // No name
    MJB_CCC_35 =                   35, // No name
    MJB_CCC_36 =                   36, // No name
    MJB_CCC_84 =                   84, // No name
    MJB_CCC_91 =                   91, // No name
    MJB_CCC_103 =                  103, // No name
    MJB_CCC_107 =                  107, // No name
    MJB_CCC_118 =                  118, // No name
    MJB_CCC_122 =                  122, // No name
    MJB_CCC_129 =                  129, // No name
    MJB_CCC_130 =                  130, // No name
    MJB_CCC_132 =                  132, // No name
    // MJB_CCC_FIXED_END =            199, // End of fixed position classes
    MJB_CCC_BELOW_LEFT_ATTACHED =  200, // Below left attached
    MJB_CCC_BELOW_ATTACHED =       202, // Below attached
    MJB_CCC_BELOW_RIGHT_ATTACHED = 204, // Below right attached
    MJB_CCC_LEFT_ATTACHED =        208, // Left attached (reordrant around single base character)
    MJB_CCC_RIGHT_ATTACHED =       210, // Right attached
    MJB_CCC_ABOVE_LEFT_ATTACHED =  212, // Above left attached
    MJB_CCC_ABOVE_ATTACHED =       214, // Above attached
    MJB_CCC_ABOVE_RIGHT_ATTACHED = 216, // Above right attached
    MJB_CCC_BELOW_LEFT =           218, // Below left
    MJB_CCC_BELOW =                220, // Below
    MJB_CCC_BELOW_RIGHT =          222, // Below right
    MJB_CCC_LEFT =                 224, // Left (reordrant around single base character)
    MJB_CCC_RIGHT =                226, // Right
    MJB_CCC_ABOVE_LEFT =           228, // Above left
    MJB_CCC_ABOVE =                230, // Above
    MJB_CCC_ABOVE_RIGHT =          232, // Above right
    MJB_CCC_DOUBLE_BELOW =         233, // Double below
    MJB_CCC_DOUBLE_ABOVE =         234, // Double above
    MJB_CCC_BELOW_IOTA =           240  // Below (iota subscript)
} mjb_canonical_combining_class;

#define MJB_CCC_COUNT 62

/**
 * Bidirectional categories
 * [see: https://www.unicode.org/glossary/#combining_class]
 */
typedef enum mjb_bidi_categories {
    MJB_BIDI_NONE, // Nothing specified
    MJB_BIDI_L,    // Left-to-right
    MJB_BIDI_R,    // Right-to-left
    MJB_BIDI_AL,   // Right-to-left arabic
    MJB_BIDI_EN,   // European number
    MJB_BIDI_ES,   // European number separator
    MJB_BIDI_ET,   // European number terminator
    MJB_BIDI_AN,   // Arabic number
    MJB_BIDI_CS,   // Common number separator
    MJB_BIDI_NSM,  // Nonspacing mark
    MJB_BIDI_BN,   // Boundary neutral
    MJB_BIDI_B,    // Paragraph separator
    MJB_BIDI_S,    // Segment separator
    MJB_BIDI_WS,   // Whitespace
    MJB_BIDI_ON,   // Other neutrals
    MJB_BIDI_LRE,  // Left-to-right embedding
    MJB_BIDI_LRO,  // Left-to-right override
    MJB_BIDI_RLE,  // Right-to-left embedding
    MJB_BIDI_RLO,  // Right-to-left override
    MJB_BIDI_PDF,  // Pop Directional format
    MJB_BIDI_LRI,  // Left-to-right isolate
    MJB_BIDI_RLI,  // Right-to-Left isolate
    MJB_BIDI_FSI,  // First strong isolate
    MJB_BIDI_PDI   // Pop directional isolate
} mjb_bidi_categories;

#define MJB_BIDI_COUNT 24

/**
 * 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

/**
 * Decomposition
 * [see: https://www.unicode.org/glossary/#compatibility_decomposition]
 */
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;

#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   0x9 // MAJOR << 8 | MINOR << 4 | REVISION
#define MJB_VERSION_MAJOR    0
#define MJB_VERSION_MINOR    0
#define MJB_VERSION_REVISION 9

#ifdef __EMSCRIPTEN__
    #define MJB_VERSION "0.0.9-WASM"
#else
    #define MJB_VERSION "0.0.9"
#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);

/**
 * Mojibake is represented by a pointer to an instance of the opaque structure
 * named "mojibake". The [mjb_initialize()] and [mjb_initialize_v2()] functions
 * are its constructor. Every function accept an instance to this allocated
 * pointer. This is used to ensure reentrancy.
 */
typedef struct mojibake mojibake;

/**
 * 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/Unicode16.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_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_CJK_COMPATIBILITY_IDEOGRAPH_SUPPLEMENT_START 0x2F800
#define MJB_CJK_COMPATIBILITY_IDEOGRAPH_SUPPLEMENT_END   0x2FA1D

// 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;

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

typedef struct mjb_line_break {
    size_t index;
    bool mandatory;
} mjb_line_break;

// 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;

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

// 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 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_line_break *mjb_break_line(const char *buffer, size_t size, mjb_encoding encoding, size_t *output_size);

// Word and grapheme cluster breaking
MJB_NONNULL(1) bool mjb_segmentation(const char *buffer, size_t size, mjb_encoding encoding);

// 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);

// 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
