SheenBidi, the Unicode Bidirectional Algorithm, through C++23 modules.
English · 简体中文 · Upstream · Releases · mcpp · Index
SheenBidi turns text stored in logical order into the visual order a display
needs for Arabic, Hebrew and mixed-direction text (UAX #9, Unicode 17.0.0). It
is Apache-2.0 C with no dependencies, so it links statically without copyleft
terms. The upstream C API is unchanged: SBAlgorithmCreate,
SBParagraphGetLevelsPtr, SBLineGetRunsPtr and SBMirrorLocatorMoveNext
are the upstream globals of <SheenBidi/SheenBidi.h>. The library is
compat.sheenbidi 3.0.0. This package maps SheenBidi's macros and the
enumerators of its unnamed enums to constants and constexpr functions, each
checked against the header. Unicode's conformance tests pass on every CI run:
all 770,241 cases of BidiTest.txt and all 91,707 of BidiCharacterTest.txt, on
programs written against the module.
import mcpplibs.mwrap.sheenbidi;: the whole API of<SheenBidi/SheenBidi.h>(SBAlgorithm, SBParagraph, SBLine, SBRun, SBMirrorLocator, SBScriptLocator, SBCodepoint, SBCodepointSequence, SBAllocator, SBVersion), re-exporting the module belowimport mcpplibs.mwrap.sheenbidi.macros;:SBBidiTypeR,SBScriptARAB,SBStringEncodingUTF8,SBLevelDefaultLTR,SBBidiTypeIsStrong… inmcpplibs::mwrap::sheenbidi::macros
More Modules API -> Usage and API
mcpp new bidi --template mcpplibs.mwrap.sheenbidi@3.0.0
cd bidi
mcpp runThe default template lays out UTF-8 lines as a renderer does: it resolves a
paragraph's embedding levels, then draws the line's runs in visual order with
mirrored brackets. Run mcpp run -- "your text" for your own lines.
[dependencies]
"mcpplibs.mwrap.sheenbidi" = "3.0.0"import std;
import mcpplibs.mwrap.sheenbidi;
using namespace mcpplibs::mwrap::sheenbidi::macros; // SBStringEncodingUTF8, SBLevelDefaultLTR …
int main() {
std::string_view text = "abc אבג (123)";
SBCodepointSequence seq{SBStringEncodingUTF8, text.data(), text.size()};
SBAlgorithmRef algorithm = SBAlgorithmCreate(&seq);
SBParagraphRef paragraph = SBAlgorithmCreateParagraph(algorithm, 0, text.size(), SBLevelDefaultLTR);
SBLineRef line = SBParagraphCreateLine(paragraph, 0, SBParagraphGetLength(paragraph));
const SBRun* runs = SBLineGetRunsPtr(line); // in visual order, offsets in UTF-8 bytes
for (SBUInteger i = 0; i < SBLineGetRunCount(line); ++i)
std::println("[{}, {}) level {}", runs[i].offset, runs[i].offset + runs[i].length, runs[i].level);
SBLineRelease(line);
SBParagraphRelease(paragraph);
SBAlgorithmRelease(algorithm);
}Constants such as SBLevelMax keep the type their macro has (int).
Computations such as SBBidiTypeIsStrong and SBCodepointIsValid are
constexpr functions whose body is the macro itself, matching its value and
type for every argument type. SheenBidi's enumerators (SBBidiTypeL,
SBScriptARAB …) belong to unnamed enums, which a module cannot export, so
they are constants of the typedef the header gives them (SBBidiType,
SBScript …). SB_PUBLIC, SB_DEPRECATED and the extern "C" brackets stay
macros in <mwrap/sheenbidi/macros.hpp>, included before the import. Details:
docs/usage.md.
- examples/sheenbidi: a layout tool (logical to visual order, levels, runs and script runs of each paragraph) and Unicode's two conformance runners, written against the module. tools/run_conformance.py runs BidiTest.txt and BidiCharacterTest.txt on them.
Linux (x86_64 GCC and LLVM, arm64 GCC), macOS and Windows CI build the modules, then run the tests and the export audit (tools/check_exports.py). The audit checks that the generated sources are fresh, that every declaration is exported and that every macro is mapped or listed with its reason. CI also runs Unicode 17.0.0's conformance tests from the pinned release, each file checked against the one Unicode publishes: BidiTest.txt (770,241 cases) and BidiCharacterTest.txt (91,707 cases, with mirroring). A separate job scaffolds the default template as an installed package and runs it.
Apache-2.0 for the wrapper, by mcpp-community (NOTICE). SheenBidi is Apache-2.0 too (upstream/sheenbidi/LICENSE). Its tables come from the Unicode Character Database (Unicode License v3). Both notices are deployed beside every program that depends on this package.