There are no doc comments for this declaration.
";
+ }
+ domTldDocs.classList.remove("hidden");
+ }
+
+ function typeIsErrSet(typeIndex) {
+ let typeObj = getType(typeIndex);
+ return typeObj.kind === typeKinds.ErrorSet;
+ }
+
+ function typeIsStructWithNoFields(typeIndex) {
+ let typeObj = getType(typeIndex);
+ if (typeObj.kind !== typeKinds.Struct) return false;
+ return typeObj.field_types.length == 0;
+ }
+
+ function typeIsGenericFn(typeIndex) {
+ let typeObj = getType(typeIndex);
+ if (typeObj.kind !== typeKinds.Fn) {
+ return false;
+ }
+ return typeObj.generic_ret != null;
+ }
+
+ function renderFn(fnDecl) {
+ if ("refPath" in fnDecl.value.expr) {
+ let last = fnDecl.value.expr.refPath.length - 1;
+ let lastExpr = fnDecl.value.expr.refPath[last];
+ console.assert("declRef" in lastExpr);
+ fnDecl = getDecl(lastExpr.declRef);
+ }
+
+ let value = resolveValue(fnDecl.value);
+ console.assert("type" in value.expr);
+ let typeObj = getType(value.expr.type);
+
+ domFnProtoCode.innerHTML = renderTokens(ex(value.expr, { fnDecl: fnDecl }));
+ domFnSourceLink.classList.remove("hidden");
+ domFnSourceLink.innerHTML = "[" + short + "
" + "
" + long + "
";
+ }
+ else {
+ tdDesc.innerHTML = markdown(short, container);
+ }
+ } else {
+ tdDesc.innerHTML = "
No documentation provided.
";
+ }
+ }
+ domSectFns.classList.remove("hidden");
+ }
+
+ let containerNode = getAstNode(container.src);
+ if (containerNode.fields && containerNode.fields.length > 0) {
+ resizeDomList(domListFields, containerNode.fields.length, "
");
+
+ for (let i = 0; i < containerNode.fields.length; i += 1) {
+ let fieldNode = getAstNode(containerNode.fields[i]);
+ let divDom = domListFields.children[i];
+ let fieldName = fieldNode.name;
+ let docs = fieldNode.docs;
+ let docsNonEmpty = docs != null && docs !== "";
+ let extraPreClass = docsNonEmpty ? " fieldHasDocs" : "";
+
+ let html =
+ '
";
+
+ if (docsNonEmpty) {
+ html += '
' + markdown(docs) + "
";
+ }
+ divDom.innerHTML = html;
+ }
+ domSectFields.classList.remove("hidden");
+ }
+
+ if (varsList.length !== 0) {
+ resizeDomList(
+ domListGlobalVars,
+ varsList.length,
+ '
| | |
'
+ );
+ for (let i = 0; i < varsList.length; i += 1) {
+ let decl = varsList[i];
+ let trDom = domListGlobalVars.children[i];
+
+ let tdName = trDom.children[0];
+ let tdNameA = tdName.children[0];
+ let tdType = trDom.children[1];
+ let preType = tdType.children[0];
+ let tdDesc = trDom.children[2];
+
+ tdNameA.setAttribute("href", navLinkDecl(decl.name));
+ tdNameA.textContent = decl.name;
+
+ preType.innerHTML = renderTokens(ex(walkResultTypeRef(decl.value), {}));
+
+ let docs = getAstNode(decl.src).docs;
+ if (docs != null) {
+ tdDesc.innerHTML = shortDescMarkdown(docs);
+ } else {
+ tdDesc.textContent = "";
+ }
+ }
+ domSectGlobalVars.classList.remove("hidden");
+ }
+
+ if (valsList.length !== 0) {
+ resizeDomList(
+ domListValues,
+ valsList.length,
+ '
| | |
'
+ );
+ for (let i = 0; i < valsList.length; i += 1) {
+ let decl = valsList[i];
+ let trDom = domListValues.children[i];
+
+ let tdName = trDom.children[0];
+ let tdNameA = tdName.children[0];
+ let tdType = trDom.children[1];
+ let preType = tdType.children[0];
+ let tdDesc = trDom.children[2];
+
+ tdNameA.setAttribute("href", navLinkDecl(decl.name));
+ tdNameA.textContent = decl.name;
+
+ preType.innerHTML = renderTokens(ex(walkResultTypeRef(decl.value), {}));
+
+ let docs = getAstNode(decl.src).docs;
+ if (docs != null) {
+ tdDesc.innerHTML = shortDescMarkdown(docs);
+ } else {
+ tdDesc.textContent = "";
+ }
+ }
+ domSectValues.classList.remove("hidden");
+ }
+
+ if (testsList.length !== 0) {
+ resizeDomList(
+ domListTests,
+ testsList.length,
+ '
| | |
'
+ );
+ for (let i = 0; i < testsList.length; i += 1) {
+ let decl = testsList[i];
+ let trDom = domListTests.children[i];
+
+ let tdName = trDom.children[0];
+ let tdNamePre = tdName.children[0];
+ let tdType = trDom.children[1];
+ let tdTypePre = tdType.children[0];
+ let tdDesc = trDom.children[2];
+
+ tdNamePre.innerHTML = renderSingleToken(Tok.identifier(decl.name));
+
+ tdTypePre.innerHTML = ex(walkResultTypeRef(decl.value), {});
+
+ let docs = getAstNode(decl.src).docs;
+ if (docs != null) {
+ tdDesc.innerHTML = shortDescMarkdown(docs);
+ } else {
+ tdDesc.textContent = "";
+ }
+ }
+ domSectTests.classList.remove("hidden");
+ }
+
+ if (container.kind !== typeKinds.Struct || containerNode.fields.length > 0) {
+ domHdrName.innerHTML = "
" +
+ zigAnalysis.typeKinds[container.kind] +
+ "
";
+ domHdrName.classList.remove("hidden");
+ }
+ }
+
+ function operatorCompare(a, b) {
+ if (a === b) {
+ return 0;
+ } else if (a < b) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+
+ function detectRootIsStd() {
+ let rootMod = zigAnalysis.modules[zigAnalysis.rootMod];
+ if (rootMod.table["std"] == null) {
+ // no std mapped into the root module
+ return false;
+ }
+ let stdMod = zigAnalysis.modules[rootMod.table["std"]];
+ if (stdMod == null) return false;
+ return rootMod.file === stdMod.file;
+ }
+
+ function indexTypeKinds() {
+ let map = {};
+ for (let i = 0; i < zigAnalysis.typeKinds.length; i += 1) {
+ map[zigAnalysis.typeKinds[i]] = i;
+ }
+ // This is just for debugging purposes, not needed to function
+ let assertList = [
+ "Type",
+ "Void",
+ "Bool",
+ "NoReturn",
+ "Int",
+ "Float",
+ "Pointer",
+ "Array",
+ "Struct",
+ "ComptimeFloat",
+ "ComptimeInt",
+ "Undefined",
+ "Null",
+ "Optional",
+ "ErrorUnion",
+ "ErrorSet",
+ "Enum",
+ "Union",
+ "Fn",
+ "Opaque",
+ "Frame",
+ "AnyFrame",
+ "Vector",
+ "EnumLiteral",
+ ];
+ for (let i = 0; i < assertList.length; i += 1) {
+ if (map[assertList[i]] == null)
+ throw new Error("No type kind '" + assertList[i] + "' found");
+ }
+ return map;
+ }
+
+ function findTypeTypeId() {
+ for (let i = 0; i < zigAnalysis.types.length; i += 1) {
+ if (getType(i).kind == typeKinds.Type) {
+ return i;
+ }
+ }
+ throw new Error("No type 'type' found");
+ }
+
+
+ function updateCurNav() {
+ curNav = {
+ hash: location.hash,
+ mode: NAV_MODES.API,
+ modNames: [],
+ modObjs: [],
+ declNames: [],
+ declObjs: [],
+ callName: null,
+ activeGuide: null,
+ activeGuideScrollTo: null,
+ };
+ curNavSearch = "";
+
+ const mode = location.hash.substring(0, 3);
+ let query = location.hash.substring(3);
+
+ let qpos = query.indexOf("?");
+ let nonSearchPart;
+ if (qpos === -1) {
+ nonSearchPart = query;
+ } else {
+ nonSearchPart = query.substring(0, qpos);
+ curNavSearch = decodeURIComponent(query.substring(qpos + 1));
+ }
+
+ const DEFAULT_HASH = NAV_MODES.API + zigAnalysis.modules[zigAnalysis.rootMod].name;
+ switch (mode) {
+ case NAV_MODES.API:
+ // #A;MODULE:decl.decl.decl?search-term
+ curNav.mode = mode;
+ {
+ let parts = nonSearchPart.split(":");
+ if (parts[0] == "") {
+ location.hash = DEFAULT_HASH;
+ } else {
+ curNav.modNames = decodeURIComponent(parts[0]).split(".");
+ }
+
+ if (parts[1] != null) {
+ curNav.declNames = decodeURIComponent(parts[1]).split(".");
+ }
+ }
+ return;
+ case NAV_MODES.GUIDES:
+ curNav.mode = mode;
+
+ {
+ let parts = nonSearchPart.split(":");
+ curNav.activeGuide = parts[0];
+ if (parts[1] != null) {
+ curNav.activeGuideScrollTo = decodeURIComponent(":" + parts[1]);
+ }
+ }
+ return;
+ default:
+ location.hash = DEFAULT_HASH;
+ return;
+ }
+ }
+
+ function onHashChange(ev) {
+ scrollHistory[curNav.hash] = scrollMonitor.map(function (x) {
+ return [x, x.scrollTop]
+ });
+
+ if (skipNextHashChange == decodeURIComponent(location.hash)) {
+ skipNextHashChange = null;
+ return;
+ }
+ skipNextHashChange = null;
+ updateCurNav();
+
+ if (domSearch.value !== curNavSearch) {
+ domSearch.value = curNavSearch;
+ if (domSearch.value.length == 0)
+ domSearchPlaceholder.classList.remove("hidden");
+ else
+ domSearchPlaceholder.classList.add("hidden");
+ }
+ render();
+ if (imFeelingLucky) {
+ imFeelingLucky = false;
+ activateSelectedResult();
+ }
+
+ scroll();
+ }
+
+ function scroll() {
+ const cur = scrollHistory[location.hash];
+ if (cur) {
+ for (let [elem, offset] of cur) {
+ elem.scrollTo(0, offset);
+ }
+ } else {
+ if (curNav.activeGuideScrollTo) return;
+ for (let elem of scrollMonitor) {
+ elem.scrollTo(0, 0);
+ }
+ }
+ }
+
+ function findSubDecl(parentTypeOrDecl, childName) {
+ let parentType = parentTypeOrDecl;
+ {
+ // Generic functions / resolving decls
+ if ("value" in parentType) {
+ const rv = resolveValue(parentType.value);
+ if ("type" in rv.expr) {
+ const t = getType(rv.expr.type);
+ parentType = t;
+ if (t.kind == typeKinds.Fn && t.generic_ret != null) {
+ let resolvedGenericRet = resolveValue({ expr: t.generic_ret });
+
+ if ("call" in resolvedGenericRet.expr) {
+ let call = zigAnalysis.calls[resolvedGenericRet.expr.call];
+ let resolvedFunc = resolveValue({ expr: call.func });
+ if (!("type" in resolvedFunc.expr)) return null;
+ let callee = getType(resolvedFunc.expr.type);
+ if (!callee.generic_ret) return null;
+ resolvedGenericRet = resolveValue({ expr: callee.generic_ret });
+ }
+
+ if ("type" in resolvedGenericRet.expr) {
+ parentType = getType(resolvedGenericRet.expr.type);
+ }
+ }
+ }
+ }
+ }
+
+ if (parentType.pubDecls) {
+ for (let i = 0; i < parentType.pubDecls.length; i += 1) {
+ let declIndex = parentType.pubDecls[i];
+ let childDecl = getDecl(declIndex);
+ if (childDecl.name === childName) {
+ childDecl.find_subdecl_idx = declIndex;
+ return childDecl;
+ } else if (childDecl.is_uns) {
+ let declValue = resolveValue(childDecl.value);
+ if (!("type" in declValue.expr)) continue;
+ let uns_container = getType(declValue.expr.type);
+ let uns_res = findSubDecl(uns_container, childName);
+ if (uns_res !== null) return uns_res;
+ }
+ }
+ }
+
+ if (parentType.privDecls) {
+ for (let i = 0; i < parentType.privDecls.length; i += 1) {
+ let declIndex = parentType.privDecls[i];
+ let childDecl = getDecl(declIndex);
+ if (childDecl.name === childName) {
+ childDecl.find_subdecl_idx = declIndex;
+ childDecl.is_private = true;
+ return childDecl;
+ } else if (childDecl.is_uns) {
+ let declValue = resolveValue(childDecl.value);
+ if (!("type" in declValue.expr)) continue;
+ let uns_container = getType(declValue.expr.type);
+ let uns_res = findSubDecl(uns_container, childName);
+ uns_res.is_private = true;
+ if (uns_res !== null) return uns_res;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ function computeCanonicalModulePaths() {
+ let list = new Array(zigAnalysis.modules.length);
+ // Now we try to find all the modules from root.
+ let rootMod = zigAnalysis.modules[zigAnalysis.rootMod];
+ // Breadth-first to keep the path shortest possible.
+ let stack = [
+ {
+ path: [],
+ mod: rootMod,
+ },
+ ];
+ while (stack.length !== 0) {
+ let item = stack.shift();
+ for (let key in item.mod.table) {
+ let childModIndex = item.mod.table[key];
+ if (list[childModIndex] != null) continue;
+ let childMod = zigAnalysis.modules[childModIndex];
+ if (childMod == null) continue;
+
+ let newPath = item.path.concat([key]);
+ list[childModIndex] = newPath;
+ stack.push({
+ path: newPath,
+ mod: childMod,
+ });
+ }
+ }
+
+ for (let i = 0; i < zigAnalysis.modules.length; i += 1) {
+ const p = zigAnalysis.modules[i];
+ // TODO
+ // declSearchIndex.add(p.name, {moduleId: i});
+ }
+ return list;
+ }
+
+ function computeCanonDeclPaths() {
+ let list = new Array(zigAnalysis.decls.length);
+ canonTypeDecls = new Array(zigAnalysis.types.length);
+
+ for (let modI = 0; modI < zigAnalysis.modules.length; modI += 1) {
+ let mod = zigAnalysis.modules[modI];
+ let modNames = canonModPaths[modI];
+ if (modNames === undefined) continue;
+
+ let stack = [
+ {
+ declNames: [],
+ declIndexes: [],
+ type: getType(mod.main),
+ },
+ ];
+ while (stack.length !== 0) {
+ let item = stack.shift();
+
+ if (isContainerType(item.type)) {
+ let t = item.type;
+
+ let len = t.pubDecls ? t.pubDecls.length : 0;
+ for (let declI = 0; declI < len; declI += 1) {
+ let declIndex = t.pubDecls[declI];
+ if (list[declIndex] != null) continue;
+
+ let decl = getDecl(declIndex);
+
+ if (decl.is_uns) {
+ let unsDeclList = [decl];
+ while (unsDeclList.length != 0) {
+ let unsDecl = unsDeclList.pop();
+ let unsDeclVal = resolveValue(unsDecl.value);
+ if (!("type" in unsDeclVal.expr)) continue;
+ let unsType = getType(unsDeclVal.expr.type);
+ if (!isContainerType(unsType)) continue;
+ let unsPubDeclLen = unsType.pubDecls ? unsType.pubDecls.length : 0;
+ for (let unsDeclI = 0; unsDeclI < unsPubDeclLen; unsDeclI += 1) {
+ let childDeclIndex = unsType.pubDecls[unsDeclI];
+ let childDecl = getDecl(childDeclIndex);
+
+ if (childDecl.is_uns) {
+ unsDeclList.push(childDecl);
+ } else {
+ addDeclToSearchResults(childDecl, childDeclIndex, modNames, item, list, stack);
+ }
+ }
+ }
+ } else {
+ addDeclToSearchResults(decl, declIndex, modNames, item, list, stack);
+ }
+ }
+ }
+ }
+ }
+ window.cdp = list;
+ return list;
+ }
+
+ function addDeclToSearchResults(decl, declIndex, modNames, item, list, stack) {
+ let {value: declVal, seenDecls} = resolveValue(decl.value, true);
+ let declNames = item.declNames.concat([decl.name]);
+ let declIndexes = item.declIndexes.concat([declIndex]);
+
+ if (list[declIndex] != null) return;
+ list[declIndex] = {
+ modNames: modNames,
+ declNames: declNames,
+ declIndexes: declIndexes,
+ };
+
+ for (let sd of seenDecls) {
+ if (list[sd] != null) continue;
+ list[sd] = {
+ modNames: modNames,
+ declNames: declNames,
+ declIndexes: declIndexes,
+ };
+ }
+
+ // add to search index
+ {
+ declSearchIndex.add(decl.name, { declIndex });
+ }
+
+
+ if ("type" in declVal.expr) {
+ let value = getType(declVal.expr.type);
+ if (declCanRepresentTypeKind(value.kind)) {
+ canonTypeDecls[declVal.type] = declIndex;
+ }
+
+ if (isContainerType(value)) {
+ stack.push({
+ declNames: declNames,
+ declIndexes: declIndexes,
+ type: value,
+ });
+ }
+
+ // Generic function
+ if (typeIsGenericFn(declVal.expr.type)) {
+ let ret = resolveGenericRet(value);
+ if (ret != null && "type" in ret.expr) {
+ let generic_type = getType(ret.expr.type);
+ if (isContainerType(generic_type)) {
+ stack.push({
+ declNames: declNames,
+ declIndexes: declIndexes,
+ type: generic_type,
+ });
+ }
+ }
+ }
+ }
+ }
+
+ function declLinkOrSrcLink(index) {
+
+ let match = getCanonDeclPath(index);
+ if (match) return navLink(match.modNames, match.declNames);
+
+ // could not find a precomputed decl path
+ const decl = getDecl(index);
+
+ // try to find a public decl by scanning declRefs and declPaths
+ let value = decl.value;
+ let i = 0;
+ while (true) {
+ i += 1;
+ if (i >= 10000) {
+ throw "getCanonDeclPath quota exceeded"
+ }
+
+ if ("refPath" in value.expr) {
+ value = { expr: value.expr.refPath[value.expr.refPath.length - 1] };
+ continue;
+ }
+
+ if ("declRef" in value.expr) {
+ let cp = canonDeclPaths[value.expr.declRef];
+ if (cp) return navLink(cp.modNames, cp.declNames);
+
+ value = getDecl(value.expr.declRef).value;
+ continue;
+ }
+
+ if ("as" in value.expr) {
+ value = {
+ typeRef: zigAnalysis.exprs[value.expr.as.typeRefArg],
+ expr: zigAnalysis.exprs[value.expr.as.exprArg],
+ };
+ continue;
+ }
+
+ // if we got here it means that we failed
+ // produce a link to source code instead
+ return sourceFileLink(decl);
+
+ }
+
+ }
+
+ function getCanonDeclPath(index) {
+ if (canonDeclPaths == null) {
+ canonDeclPaths = computeCanonDeclPaths();
+ }
+
+ return canonDeclPaths[index];
+
+
+ }
+
+ function getCanonTypeDecl(index) {
+ getCanonDeclPath(0);
+ //let ct = (canonTypeDecls);
+ return canonTypeDecls[index];
+ }
+
+ function escapeHtml(text) {
+ return text.replace(/[&"<>]/g, function(m) {
+ return escapeHtmlReplacements[m];
+ });
+ }
+
+ function shortDesc(docs) {
+ const trimmed_docs = docs.trim();
+ let index = trimmed_docs.indexOf("\n\n");
+ let cut = false;
+
+ if (index < 0 || index > 130) {
+ if (trimmed_docs.length > 130) {
+ index = 130;
+ cut = true;
+ } else {
+ index = trimmed_docs.length;
+ }
+ }
+
+ let slice = trimmed_docs.slice(0, index);
+ if (cut) slice += "...";
+ return slice;
+ }
+
+ function shortDescMarkdown(docs) {
+ return markdown(shortDesc(docs));
+ }
+
+ function parseGuides() {
+ for (let j = 0; j < zigAnalysis.guideSections.length; j += 1) {
+ const section = zigAnalysis.guideSections[j];
+ for (let i = 0; i < section.guides.length; i += 1) {
+ let reader = new commonmark.Parser({ smart: true });
+ const guide = section.guides[i];
+
+ // Find the first text thing to use as a sidebar title
+ guide.title = null;
+ guide.toc = "";
+
+ // Discover Title & TOC for this guide
+ {
+ let reader = new commonmark.Parser({smart: true});
+ let ast = reader.parse(guide.body);
+ let walker = ast.walker();
+ let heading_idx = 0;
+ let event, node, doc, last, last_ul;
+ while ((event = walker.next())) {
+ node = event.node;
+ if (event.entering) {
+ if (node.type === 'document') {
+ doc = node;
+ continue;
+ }
+
+
+ if (node.next) {
+ walker.resumeAt(node.next, true);
+ } else {
+ walker.resumeAt(node, false);
+ }
+ node.unlink();
+
+ if (node.type === 'heading') {
+ if (node.level == 1) {
+ if (guide.title == null) {
+ let doc_node = new commonmark.Node("document", node.sourcepos);
+ while (node.firstChild) {
+ doc_node.appendChild(node.firstChild);
+ }
+ let writer = new commonmark.HtmlRenderer();
+ let result = writer.render(doc_node);
+ guide.title = result;
+ }
+
+ continue; // don't index H1
+ }
+
+ // turn heading node into list item & add link node to it
+ {
+ node._type = "link";
+ node.destination = NAV_MODES.GUIDES + guide.name + ":" + heading_idx;
+ heading_idx += 1;
+ let listItem = new commonmark.Node("item", node.sourcepos);
+ // TODO: strip links from inside node
+ listItem.appendChild(node);
+ listItem.level = node.level;
+ node = listItem;
+ }
+
+ if (last_ul) {
+ // are we inside or outside of it?
+
+ let target_ul = last_ul;
+ while(target_ul.level > node.level) {
+ target_ul = target_ul.parent;
+ }
+ while(target_ul.level < node.level) {
+ let ul_node = new commonmark.Node("list", node.sourcepos);
+ ul_node.level = target_ul.level + 1;
+ ul_node.listType = "bullet";
+ ul_node.listStart = null;
+ target_ul.appendChild(ul_node);
+ target_ul = ul_node;
+ }
+
+ target_ul.appendChild(node);
+ last_ul = target_ul;
+ } else {
+ let ul_node = new commonmark.Node("list", node.sourcepos);
+ ul_node.level = 2;
+ ul_node.listType = "bullet";
+ ul_node.listStart = null;
+ doc.prependChild(ul_node);
+
+ while (ul_node.level < node.level) {
+ let current_ul_node = new commonmark.Node("list", node.sourcepos);
+ current_ul_node.level = ul_node.level + 1;
+ current_ul_node.listType = "bullet";
+ current_ul_node.listStart = null;
+ ul_node.appendChild(current_ul_node);
+ ul_node = current_ul_node;
+ }
+
+ last_ul = ul_node;
+
+ ul_node.appendChild(node);
+ }
+ }
+ }
+ }
+
+ let writer = new commonmark.HtmlRenderer();
+ let result = writer.render(ast);
+ guide.toc = result;
+ }
+
+ // Index this guide
+ {
+ // let walker = guide.ast.walker();
+ // let event, node;
+ // while ((event = walker.next())) {
+ // node = event.node;
+ // if (event.entering == true && node.type === 'text') {
+ // indexTextForGuide(j, i, node);
+ // }
+ // }
+ }
+ }
+ }
+ }
+
+ function indexTextForGuide(section_idx, guide_idx, node) {
+ const terms = node.literal.split(" ");
+ for (let i = 0; i < terms.length; i += 1) {
+ const t = terms[i];
+ if (!guidesSearchIndex[t]) guidesSearchIndex[t] = new Set();
+ node.guide = { section_idx, guide_idx };
+ guidesSearchIndex[t].add(node);
+ }
+ }
+
+
+ function markdown(input, contextType) {
+ const parsed = new commonmark.Parser({ smart: true }).parse(input);
+
+ // Look for decl references in inline code (`ref`)
+ const walker = parsed.walker();
+ let event;
+ while ((event = walker.next())) {
+ const node = event.node;
+ if (node.type === "code") {
+ const declHash = detectDeclPath(node.literal, contextType);
+ if (declHash) {
+ const link = new commonmark.Node("link");
+ link.destination = declHash;
+ node.insertBefore(link);
+ link.appendChild(node);
+ }
+ }
+ }
+
+ return new commonmark.HtmlRenderer({ safe: true }).render(parsed);
+
+ }
+
+
+
+ // function detectDeclPath(text, context) {
+ // let result = "";
+ // let separator = ":";
+ // const components = text.split(".");
+ // let curDeclOrType = undefined;
+
+ // let curContext = context;
+ // let limit = 10000;
+ // while (curContext) {
+ // limit -= 1;
+
+ // if (limit == 0) {
+ // throw "too many iterations";
+ // }
+
+ // curDeclOrType = findSubDecl(curContext, components[0]);
+
+ // if (!curDeclOrType) {
+ // if (curContext.parent_container == null) break;
+ // curContext = getType(curContext.parent_container);
+ // continue;
+ // }
+
+ // if (curContext == context) {
+ // separator = '.';
+ // result = location.hash + separator + components[0];
+ // } else {
+ // // We had to go up, which means we need a new path!
+ // const canonPath = getCanonDeclPath(curDeclOrType.find_subdecl_idx);
+ // if (!canonPath) return;
+
+ // let lastModName = canonPath.modNames[canonPath.modNames.length - 1];
+ // let fullPath = lastModName + ":" + canonPath.declNames.join(".");
+
+ // separator = '.';
+ // result = "#A;" + fullPath;
+ // }
+
+ // break;
+ // }
+
+ // if (!curDeclOrType) {
+ // for (let i = 0; i < zigAnalysis.modules.length; i += 1) {
+ // const p = zigAnalysis.modules[i];
+ // if (p.name == components[0]) {
+ // curDeclOrType = getType(p.main);
+ // result += "#A;" + components[0];
+ // break;
+ // }
+ // }
+ // }
+
+ // if (!curDeclOrType) return null;
+
+ // for (let i = 1; i < components.length; i += 1) {
+ // curDeclOrType = findSubDecl(curDeclOrType, components[i]);
+ // if (!curDeclOrType) return null;
+ // result += separator + components[i];
+ // separator = '.';
+ // }
+
+ // return result;
+
+ // }
+
+ function activateSelectedResult() {
+ if (domSectSearchResults.classList.contains("hidden")) {
+ return;
+ }
+
+ const searchResults = domListSearchResults.getElementsByTagName("li");
+ let liDom = searchResults[curSearchIndex];
+ if (liDom == null && searchResults.length !== 0) {
+ liDom = searchResults[0];
+ }
+ if (liDom != null) {
+ let aDom = liDom.children[0];
+ location.href = aDom.getAttribute("href");
+ curSearchIndex = -1;
+ }
+ domSearch.blur();
+ }
+
+ // hide the modal if it's visible or return to the previous result page and unfocus the search
+ function onEscape(ev) {
+ if (isModalVisible(domHelpModal)) {
+ hideModal(domHelpModal);
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (isModalVisible(domPrefsModal)) {
+ hideModal(domPrefsModal);
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else {
+ domSearch.value = "";
+ domSearch.blur();
+ domSearchPlaceholder.classList.remove("hidden");
+ curSearchIndex = -1;
+ ev.preventDefault();
+ ev.stopPropagation();
+ startSearch();
+ }
+ }
+
+
+ function onSearchKeyDown(ev) {
+ switch (getKeyString(ev)) {
+ case "Enter":
+ // detect if this search changes anything
+ let terms1 = getSearchTerms();
+ startSearch();
+ updateCurNav();
+ let terms2 = getSearchTerms();
+ // we might have to wait for onHashChange to trigger
+ imFeelingLucky = terms1.join(" ") !== terms2.join(" ");
+ if (!imFeelingLucky) activateSelectedResult();
+
+ ev.preventDefault();
+ ev.stopPropagation();
+ return;
+ case "Esc":
+ onEscape(ev);
+ return
+ case "Up":
+ moveSearchCursor(-1);
+ ev.preventDefault();
+ ev.stopPropagation();
+ return;
+ case "Down":
+ // TODO: make the page scroll down if the search cursor is out of the screen
+ moveSearchCursor(1);
+ ev.preventDefault();
+ ev.stopPropagation();
+ return;
+ default:
+ // Search is triggered via an `input` event handler, not on arbitrary `keydown` events.
+ ev.stopPropagation();
+ return;
+ }
+ }
+
+ let domDotsToggleTimeout = null;
+ function onSearchInput(ev) {
+ curSearchIndex = -1;
+
+ let replaced = domSearch.value.replaceAll(".", " ")
+
+ // Ping red the help text if the user typed a dot.
+ if (replaced != domSearch.value) {
+ domSearchHelpSummary.classList.remove("normal");
+ if (domDotsToggleTimeout != null) {
+ clearTimeout(domDotsToggleTimeout);
+ domDotsToggleTimeout = null;
+ }
+ domDotsToggleTimeout = setTimeout(function () {
+ domSearchHelpSummary.classList.add("normal");
+ }, 1000);
+ }
+
+ replaced = replaced.replace(/ +/g, ' ');
+ if (replaced != domSearch.value) {
+ domSearch.value = replaced;
+ }
+
+ startAsyncSearch();
+ }
+
+ function moveSearchCursor(dir) {
+ const searchResults = domListSearchResults.getElementsByTagName("li");
+ if (
+ curSearchIndex < 0 ||
+ curSearchIndex >= searchResults.length
+ ) {
+ if (dir > 0) {
+ curSearchIndex = -1 + dir;
+ } else if (dir < 0) {
+ curSearchIndex = searchResults.length + dir;
+ }
+ } else {
+ curSearchIndex += dir;
+ }
+ if (curSearchIndex < 0) {
+ curSearchIndex = 0;
+ }
+ if (curSearchIndex >= searchResults.length) {
+ curSearchIndex = searchResults.length - 1;
+ }
+ renderSearchCursor();
+ }
+
+ function getKeyString(ev) {
+ let name;
+ let ignoreShift = false;
+ switch (ev.which) {
+ case 13:
+ name = "Enter";
+ break;
+ case 27:
+ name = "Esc";
+ break;
+ case 38:
+ name = "Up";
+ break;
+ case 40:
+ name = "Down";
+ break;
+ default:
+ ignoreShift = true;
+ name =
+ ev.key != null
+ ? ev.key
+ : String.fromCharCode(ev.charCode || ev.keyCode);
+ }
+ if (!ignoreShift && ev.shiftKey) name = "Shift+" + name;
+ if (ev.altKey) name = "Alt+" + name;
+ if (ev.ctrlKey) name = "Ctrl+" + name;
+ return name;
+ }
+
+ function onWindowKeyDown(ev) {
+ switch (getKeyString(ev)) {
+ case "Esc":
+ onEscape(ev);
+ break;
+ case "/":
+ if (!getPrefSlashSearch()) break;
+ // fallthrough
+ case "s":
+ if (!isModalVisible(domHelpModal) && !isModalVisible(domPrefsModal)) {
+ if (ev.target == domSearch) break;
+
+ domSearch.focus();
+ domSearch.select();
+ domDocs.scrollTo(0, 0);
+ ev.preventDefault();
+ ev.stopPropagation();
+ startAsyncSearch();
+ }
+ break;
+ case "?":
+ if (!canToggleModal) break;
+
+ if (isModalVisible(domPrefsModal)) {
+ hideModal(domPrefsModal);
+ }
+
+ // toggle the help modal
+ if (isModalVisible(domHelpModal)) {
+ hideModal(domHelpModal);
+ } else {
+ showModal(domHelpModal);
+ }
+ ev.preventDefault();
+ ev.stopPropagation();
+ break;
+ case "p":
+ if (!canToggleModal) break;
+
+ if (isModalVisible(domHelpModal)) {
+ hideModal(domHelpModal);
+ }
+
+ // toggle the preferences modal
+ if (isModalVisible(domPrefsModal)) {
+ hideModal(domPrefsModal);
+ } else {
+ showModal(domPrefsModal);
+ }
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ }
+
+ function isModalVisible(modal) {
+ return !modal.classList.contains("hidden");
+ }
+
+ function showModal(modal) {
+ modal.classList.remove("hidden");
+ modal.style.left =
+ window.innerWidth / 2 - modal.clientWidth / 2 + "px";
+ modal.style.top =
+ window.innerHeight / 2 - modal.clientHeight / 2 + "px";
+ const firstInput = modal.querySelector("input");
+ if (firstInput) {
+ firstInput.focus();
+ } else {
+ modal.focus();
+ }
+ domSearch.blur();
+ domBanner.inert = true;
+ domMain.inert = true;
+ }
+
+ function hideModal(modal) {
+ modal.classList.add("hidden");
+ domBanner.inert = false;
+ domMain.inert = false;
+ modal.blur();
+ }
+
+ function clearAsyncSearch() {
+ if (searchTimer != null) {
+ clearTimeout(searchTimer);
+ searchTimer = null;
+ }
+ }
+
+ function startAsyncSearch() {
+ clearAsyncSearch();
+ searchTimer = setTimeout(startSearch, 100);
+ }
+ function startSearch() {
+ clearAsyncSearch();
+ let oldHash = location.hash;
+ let parts = oldHash.split("?");
+ let newPart2 = domSearch.value === "" ? "" : "?" + domSearch.value;
+ location.replace(parts.length === 1 ? oldHash + newPart2 : parts[0] + newPart2);
+ }
+ function getSearchTerms() {
+ let list = curNavSearch.trim().split(/[ \r\n\t]+/);
+ return list;
+ }
+
+ function renderSearchGuides() {
+ const searchTrimmed = false;
+ let ignoreCase = curNavSearch.toLowerCase() === curNavSearch;
+
+ let terms = getSearchTerms();
+ let matchedItems = new Set();
+
+ for (let i = 0; i < terms.length; i += 1) {
+ const nodes = guidesSearchIndex[terms[i]];
+ if (nodes) {
+ for (const n of nodes) {
+ matchedItems.add(n);
+ }
+ }
+ }
+
+
+
+ if (matchedItems.size !== 0) {
+ // Build up the list of search results
+ let matchedItemsHTML = "";
+
+ for (const node of matchedItems) {
+ const text = node.literal;
+ const href = "";
+
+ matchedItemsHTML += "
" + text + "";
+ }
+
+ // Replace the search results using our newly constructed HTML string
+ domListSearchResults.innerHTML = matchedItemsHTML;
+ if (searchTrimmed) {
+ domSectSearchAllResultsLink.classList.remove("hidden");
+ }
+ renderSearchCursor();
+
+ domSectSearchResults.classList.remove("hidden");
+ } else {
+ domSectSearchNoResults.classList.remove("hidden");
+ }
+ }
+
+ function renderSearchAPI() {
+ domSectSearchResults.prepend(
+ domSearchHelp.parentElement.removeChild(domSearchHelp)
+ );
+ if (canonDeclPaths == null) {
+ canonDeclPaths = computeCanonDeclPaths();
+ }
+ let declSet = new Set();
+ let otherDeclSet = new Set(); // for low quality results
+ let declScores = {};
+
+ let ignoreCase = curNavSearch.toLowerCase() === curNavSearch;
+ let term_list = getSearchTerms();
+ for (let i = 0; i < term_list.length; i += 1) {
+ let term = term_list[i];
+ let result = declSearchIndex.search(term.toLowerCase());
+ if (result == null) {
+ domSectSearchNoResults.prepend(
+ domSearchHelp.parentElement.removeChild(domSearchHelp)
+ );
+ domSectSearchNoResults.classList.remove("hidden");
+
+ domSectSearchResults.classList.add("hidden");
+ return;
+ }
+
+ let termSet = new Set();
+ let termOtherSet = new Set();
+
+ for (let list of [result.full, result.partial]) {
+ for (let r of list) {
+ const d = r.declIndex;
+ const decl = getDecl(d);
+ const canonPath = getCanonDeclPath(d);
+
+ // collect unconditionally for the first term
+ if (i == 0) {
+ declSet.add(d);
+ } else {
+ // path intersection for subsequent terms
+ let found = false;
+ for (let p of canonPath.declIndexes) {
+ if (declSet.has(p)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ otherDeclSet.add(d);
+ } else {
+ termSet.add(d);
+ }
+ }
+
+ if (declScores[d] == undefined) declScores[d] = 0;
+
+ // scores (lower is better)
+ let decl_name = decl.name;
+ if (ignoreCase) decl_name = decl_name.toLowerCase();
+
+ // shallow path are preferable
+ const path_depth = canonPath.declNames.length * 50;
+ // matching the start of a decl name is good
+ const match_from_start = decl_name.startsWith(term) ? -term.length * (2 - ignoreCase) : (decl_name.length - term.length) + 1;
+ // being a perfect match is good
+ const is_full_match = (decl_name === term) ? -decl_name.length * (1 - ignoreCase) : Math.abs(decl_name.length - term.length);
+ // matching the end of a decl name is good
+ const matches_the_end = decl_name.endsWith(term) ? -term.length * (1 - ignoreCase) : (decl_name.length - term.length) + 1;
+ // explicitly penalizing scream case decls
+ const decl_is_scream_case = decl.name.toUpperCase() != decl.name ? 0 : decl.name.length;
+
+ const score = path_depth
+ + match_from_start
+ + is_full_match
+ + matches_the_end
+ + decl_is_scream_case;
+
+ declScores[d] += score;
+ }
+ }
+ if (i != 0) {
+ for (let d of declSet) {
+ if (termSet.has(d)) continue;
+ let found = false;
+ for (let p of getCanonDeclPath(d).declIndexes) {
+ if (termSet.has(p) || otherDeclSet.has(p)) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ declScores[d] = declScores[d] / term_list.length;
+ }
+
+ termOtherSet.add(d);
+ }
+ declSet = termSet;
+ for (let d of termOtherSet) {
+ otherDeclSet.add(d);
+ }
+
+ }
+ }
+
+ let matchedItems = {
+ high_quality: [],
+ low_quality: [],
+ };
+ for (let idx of declSet) {
+ matchedItems.high_quality.push({ points: declScores[idx], declIndex: idx })
+ }
+ for (let idx of otherDeclSet) {
+ matchedItems.low_quality.push({ points: declScores[idx], declIndex: idx })
+ }
+
+ matchedItems.high_quality.sort(function(a, b) {
+ let cmp = operatorCompare(a.points, b.points);
+ return cmp;
+ });
+ matchedItems.low_quality.sort(function(a, b) {
+ let cmp = operatorCompare(a.points, b.points);
+ return cmp;
+ });
+
+ // Build up the list of search results
+ let matchedItemsHTML = "";
+
+ for (let list of [matchedItems.high_quality, matchedItems.low_quality]) {
+ if (list == matchedItems.low_quality && list.length > 0) {
+ matchedItemsHTML += "
"
+ }
+ for (let result of list) {
+ const points = result.points;
+ const match = result.declIndex;
+
+ let canonPath = getCanonDeclPath(match);
+ if (canonPath == null) continue;
+
+ let lastModName = canonPath.modNames[canonPath.modNames.length - 1];
+ let text = lastModName + "." + canonPath.declNames.join(".");
+
+
+ const href = navLink(canonPath.modNames, canonPath.declNames);
+
+ matchedItemsHTML += "
" + text + "";
+ }
+ }
+
+ // Replace the search results using our newly constructed HTML string
+ domListSearchResults.innerHTML = matchedItemsHTML;
+ renderSearchCursor();
+
+ domSectSearchResults.classList.remove("hidden");
+ }
+
+
+
+ function renderSearchCursor() {
+ const searchResults = domListSearchResults.getElementsByTagName("li");
+ for (let i = 0; i < searchResults.length; i += 1) {
+ let liDom = searchResults[i];
+ if (curSearchIndex === i) {
+ liDom.classList.add("selected");
+ } else {
+ liDom.classList.remove("selected");
+ }
+ }
+ }
+
+ function scrollGuidesTop(ev) {
+ document.getElementById("activeGuide").children[0].scrollIntoView({
+ behavior: "smooth",
+ });
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ document.scrollGuidesTop = scrollGuidesTop;
+
+ function scrollToHeading(id, alreadyThere) {
+ // Don't scroll if the current location has a scrolling history.
+ if (scrollHistory[location.hash]) return;
+
+ const c = document.getElementById(id);
+ if (c && alreadyThere) {
+ requestAnimationFrame(() => c.scrollIntoView({behavior: "smooth"}));
+ } else {
+ requestAnimationFrame(() => c.scrollIntoView());
+ }
+ return;
+ }
+ // function indexNodesToCalls() {
+ // let map = {};
+ // for (let i = 0; i < zigAnalysis.calls.length; i += 1) {
+ // let call = zigAnalysis.calls[i];
+ // let fn = zigAnalysis.fns[call.fn];
+ // if (map[fn.src] == null) {
+ // map[fn.src] = [i];
+ // } else {
+ // map[fn.src].push(i);
+ // }
+ // }
+ // return map;
+ // }
+
+ function byNameProperty(a, b) {
+ return operatorCompare(a.name, b.name);
+ }
+
+
+ function getDecl(idx) {
+ const decl = zigAnalysis.decls[idx];
+ return {
+ name: decl[0],
+ kind: decl[1],
+ src: decl[2],
+ value: decl[3],
+ decltest: decl[4],
+ is_uns: decl[5],
+ parent_container: decl[6],
+ };
+ }
+
+ function getAstNode(idx) {
+ const ast = zigAnalysis.astNodes[idx];
+ return {
+ file: ast[0],
+ line: ast[1],
+ col: ast[2],
+ name: ast[3],
+ code: ast[4],
+ docs: ast[5],
+ fields: ast[6],
+ comptime: ast[7],
+ };
+ }
+
+ function getFile(idx) {
+ const file = zigAnalysis.files[idx];
+ return {
+ name: file[0],
+ modIndex: file[1],
+ };
+ }
+
+ function getType(idx) {
+ const ty = zigAnalysis.types[idx];
+ switch (ty[0]) {
+ default:
+ throw "unhandled type kind!";
+ case typeKinds.Unanalyzed:
+ throw "unanalyzed type!";
+ case typeKinds.Type:
+ case typeKinds.Void:
+ case typeKinds.Bool:
+ case typeKinds.NoReturn:
+ case typeKinds.Int:
+ case typeKinds.Float:
+ return { kind: ty[0], name: ty[1] };
+ case typeKinds.Pointer:
+ return {
+ kind: ty[0],
+ size: ty[1],
+ child: ty[2],
+ sentinel: ty[3],
+ align: ty[4],
+ address_space: ty[5],
+ bit_start: ty[6],
+ host_size: ty[7],
+ is_ref: ty[8],
+ is_allowzero: ty[9],
+ is_mutable: ty[10],
+ is_volatile: ty[11],
+ has_sentinel: ty[12],
+ has_align: ty[13],
+ has_addrspace: ty[14],
+ has_bit_range: ty[15],
+ };
+ case typeKinds.Array:
+ return {
+ kind: ty[0],
+ len: ty[1],
+ child: ty[2],
+ sentinel: ty[3],
+ };
+ case typeKinds.Struct:
+ return {
+ kind: ty[0],
+ name: ty[1],
+ src: ty[2],
+ privDecls: ty[3],
+ pubDecls: ty[4],
+ field_types: ty[5],
+ field_defaults: ty[6],
+ backing_int: ty[7],
+ is_tuple: ty[8],
+ line_number: ty[9],
+ parent_container: ty[10],
+ layout: ty[11],
+ };
+ case typeKinds.ComptimeExpr:
+ case typeKinds.ComptimeFloat:
+ case typeKinds.ComptimeInt:
+ case typeKinds.Undefined:
+ case typeKinds.Null:
+ return { kind: ty[0], name: ty[1] };
+ case typeKinds.Optional:
+ return {
+ kind: ty[0],
+ name: ty[1],
+ child: ty[2],
+ };
+ case typeKinds.ErrorUnion:
+ return {
+ kind: ty[0],
+ lhs: ty[1],
+ rhs: ty[2],
+ };
+ case typeKinds.InferredErrorUnion:
+ return {
+ kind: ty[0],
+ payload: ty[1],
+ };
+ case typeKinds.ErrorSet:
+ return {
+ kind: ty[0],
+ name: ty[1],
+ fields: ty[2],
+ };
+ case typeKinds.Enum:
+ return {
+ kind: ty[0],
+ name: ty[1],
+ src: ty[2],
+ privDecls: ty[3],
+ pubDecls: ty[4],
+ tag: ty[5],
+ values: ty[6],
+ nonexhaustive: ty[7],
+ parent_container: ty[8],
+ };
+ case typeKinds.Union:
+ return {
+ kind: ty[0],
+ name: ty[1],
+ src: ty[2],
+ privDecls: ty[3],
+ pubDecls: ty[4],
+ field_types: ty[5],
+ tag: ty[6],
+ auto_tag: ty[7],
+ parent_container: ty[8],
+ layout: ty[9],
+ };
+ case typeKinds.Fn:
+ return {
+ kind: ty[0],
+ name: ty[1],
+ src: ty[2],
+ ret: ty[3],
+ generic_ret: ty[4],
+ params: ty[5],
+ lib_name: ty[6],
+ is_var_args: ty[7],
+ is_inferred_error: ty[8],
+ has_lib_name: ty[9],
+ has_cc: ty[10],
+ cc: ty[11],
+ align: ty[12],
+ has_align: ty[13],
+ is_test: ty[14],
+ is_extern: ty[15],
+ };
+ case typeKinds.Opaque:
+ return {
+ kind: ty[0],
+ name: ty[1],
+ src: ty[2],
+ privDecls: ty[3],
+ pubDecls: ty[4],
+ parent_container: ty[5],
+ };
+ case typeKinds.Frame:
+ case typeKinds.AnyFrame:
+ case typeKinds.Vector:
+ case typeKinds.EnumLiteral:
+ return { kind: ty[0], name: ty[1] };
+ }
+ }
+
+ function getLocalStorage() {
+ if ("localStorage" in window) {
+ try {
+ return window.localStorage;
+ } catch (ignored) {
+ // localStorage may be disabled (SecurityError)
+ }
+ }
+ // If localStorage isn't available, persist preferences only for the current session
+ const sessionPrefs = {};
+ return {
+ getItem(key) {
+ return key in sessionPrefs ? sessionPrefs[key] : null;
+ },
+ setItem(key, value) {
+ sessionPrefs[key] = String(value);
+ },
+ };
+ }
+
+ function loadPrefs() {
+ const storedPrefSlashSearch = prefs.getItem("slashSearch");
+ if (storedPrefSlashSearch === null) {
+ // Slash search defaults to enabled for all browsers except Firefox
+ setPrefSlashSearch(navigator.userAgent.indexOf("Firefox") === -1);
+ } else {
+ setPrefSlashSearch(storedPrefSlashSearch === "true");
+ }
+ }
+
+ function getPrefSlashSearch() {
+ return prefs.getItem("slashSearch") === "true";
+ }
+
+ function setPrefSlashSearch(enabled) {
+ prefs.setItem("slashSearch", String(enabled));
+ domPrefSlashSearch.checked = enabled;
+ const searchKeys = enabled ? "
/ or
s" : "
s";
+ domSearchKeys.innerHTML = searchKeys;
+ domSearchPlaceholderText.innerHTML = searchKeys + " to search,
? for more options";
+ }
+})();
+
+function toggleExpand(event) {
+ const parent = event.target.parentElement;
+ parent.toggleAttribute("open");
+
+ if (!parent.open && parent.getBoundingClientRect().top < 0) {
+ parent.parentElement.parentElement.scrollIntoView(true);
+ }
+}
+
+function RadixTree() {
+ this.root = null;
+
+ RadixTree.prototype.search = function(query) {
+ return this.root.search(query);
+
+ }
+
+ RadixTree.prototype.add = function(declName, value) {
+ if (this.root == null) {
+ this.root = new Node(declName.toLowerCase(), null, [value]);
+ } else {
+ this.root.add(declName.toLowerCase(), value);
+ }
+
+ const not_scream_case = declName.toUpperCase() != declName;
+ let found_separator = false;
+ for (let i = 1; i < declName.length; i += 1) {
+ if (declName[i] == '_' || declName[i] == '.') {
+ found_separator = true;
+ continue;
+ }
+
+
+ if (found_separator || (declName[i].toLowerCase() !== declName[i])) {
+ if (declName.length > i + 1
+ && declName[i + 1].toLowerCase() != declName[i + 1]) continue;
+ let suffix = declName.slice(i);
+ this.root.add(suffix.toLowerCase(), value);
+ found_separator = false;
+ }
+ }
+ }
+
+ function Node(labels, next, values) {
+ this.labels = labels;
+ this.next = next;
+ this.values = values;
+ }
+
+ Node.prototype.isCompressed = function() {
+ return !Array.isArray(this.next);
+ }
+
+ Node.prototype.search = function(word) {
+ let full_matches = [];
+ let partial_matches = [];
+ let subtree_root = null;
+
+ let cn = this;
+ char_loop: for (let i = 0; i < word.length;) {
+ if (cn.isCompressed()) {
+ for (let j = 0; j < cn.labels.length; j += 1) {
+ let current_idx = i + j;
+
+ if (current_idx == word.length) {
+ partial_matches = cn.values;
+ subtree_root = cn.next;
+ break char_loop;
+ }
+
+ if (word[current_idx] != cn.labels[j]) return null;
+ }
+
+ // the full label matched
+ let new_idx = i + cn.labels.length;
+ if (new_idx == word.length) {
+ full_matches = cn.values;
+ subtree_root = cn.next;
+ break char_loop;
+ }
+
+
+ i = new_idx;
+ cn = cn.next;
+ continue;
+ } else {
+ for (let j = 0; j < cn.labels.length; j += 1) {
+ if (word[i] == cn.labels[j]) {
+ if (i == word.length - 1) {
+ full_matches = cn.values[j];
+ subtree_root = cn.next[j];
+ break char_loop;
+ }
+
+ let next = cn.next[j];
+ if (next == null) return null;
+ cn = next;
+ i += 1;
+ continue char_loop;
+ }
+ }
+
+ // didn't find a match
+ return null;
+ }
+ }
+
+ // Match was found, let's collect all other
+ // partial matches from the subtree
+ let stack = [subtree_root];
+ let node;
+ while (node = stack.pop()) {
+ if (node.isCompressed()) {
+ partial_matches = partial_matches.concat(node.values);
+ if (node.next != null) {
+ stack.push(node.next);
+ }
+ } else {
+ for (let v of node.values) {
+ partial_matches = partial_matches.concat(v);
+ }
+
+ for (let n of node.next) {
+ if (n != null) stack.push(n);
+ }
+ }
+ }
+
+ return { full: full_matches, partial: partial_matches };
+ }
+
+ Node.prototype.add = function(word, value) {
+ let cn = this;
+ char_loop: for (let i = 0; i < word.length;) {
+ if (cn.isCompressed()) {
+ for (let j = 0; j < cn.labels.length; j += 1) {
+ let current_idx = i + j;
+
+ if (current_idx == word.length) {
+ if (j < cn.labels.length - 1) {
+ let node = new Node(cn.labels.slice(j), cn.next, cn.values);
+ cn.labels = cn.labels.slice(0, j);
+ cn.next = node;
+ cn.values = [];
+ }
+ cn.values.push(value);
+ return;
+ }
+
+ if (word[current_idx] == cn.labels[j]) continue;
+
+ // if we're here, a mismatch was found
+ if (j != cn.labels.length - 1) {
+ // create a suffix node
+ const label_suffix = cn.labels.slice(j + 1);
+ let node = new Node(label_suffix, cn.next, [...cn.values]);
+ cn.next = node;
+ cn.values = [];
+ }
+
+ // turn current node into a split node
+ let node = null;
+ let word_values = [];
+ if (current_idx == word.length - 1) {
+ // mismatch happened in the last character of word
+ // meaning that the current node should hold its value
+ word_values.push(value);
+ } else {
+ node = new Node(word.slice(current_idx + 1), null, [value]);
+ }
+
+ cn.labels = cn.labels[j] + word[current_idx];
+ cn.next = [cn.next, node];
+ cn.values = [cn.values, word_values];
+
+ if (j != 0) {
+ // current node must be turned into a prefix node
+ let splitNode = new Node(cn.labels, cn.next, cn.values);
+ cn.labels = word.slice(i, current_idx);
+ cn.next = splitNode;
+ cn.values = [];
+ }
+
+ return;
+ }
+ // label matched fully with word, are there any more chars?
+ const new_idx = i + cn.labels.length;
+ if (new_idx == word.length) {
+ cn.values.push(value);
+ return;
+ } else {
+ if (cn.next == null) {
+ let node = new Node(word.slice(new_idx), null, [value]);
+ cn.next = node;
+ return;
+ } else {
+ cn = cn.next;
+ i = new_idx;
+ continue;
+ }
+ }
+ } else { // node is not compressed
+ let letter = word[i];
+ for (let j = 0; j < cn.labels.length; j += 1) {
+ if (letter == cn.labels[j]) {
+ if (i == word.length - 1) {
+ cn.values[j].push(value);
+ return;
+ }
+ if (cn.next[j] == null) {
+ let node = new Node(word.slice(i + 1), null, [value]);
+ cn.next[j] = node;
+ return;
+ } else {
+ cn = cn.next[j];
+ i += 1;
+ continue char_loop;
+ }
+ }
+ }
+
+ // if we're here we didn't find a match
+ cn.labels += letter;
+ if (i == word.length - 1) {
+ cn.next.push(null);
+ cn.values.push([value]);
+ } else {
+ let node = new Node(word.slice(i + 1), null, [value]);
+ cn.next.push(node);
+ cn.values.push([]);
+ }
+ return;
+ }
+ }
+ }
+}
+
+
+function slugify(str) {
+ return str.toLowerCase().trim().replace(/[^\w\s-]/g, '').replace(/[\s_-]+/g, '-').replace(/^-+|-+$/g, '');
+}
+
diff --git a/docs/src/builtin/builtin.zig.html b/docs/src/builtin/builtin.zig.html
new file mode 100644
index 0000000..7c2aab4
--- /dev/null
+++ b/docs/src/builtin/builtin.zig.html
@@ -0,0 +1,233 @@
+
+
+
+
+
builtin.zig - source view
+
+
+
+
+
+
const std = @import("std");
+
+
+pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable;
+pub const zig_version_string = "0.12.0-dev.2824+0b7af2563";
+pub const zig_backend = std.builtin.CompilerBackend.stage2_llvm;
+
+pub const output_mode = std.builtin.OutputMode.Exe;
+pub const link_mode = std.builtin.LinkMode.Static;
+pub const is_test = true;
+pub const single_threaded = false;
+pub const abi = std.Target.Abi.gnu;
+pub const cpu: std.Target.Cpu = .{
+ .arch = .x86_64,
+ .model = &std.Target.x86.cpu.x86_64,
+ .features = std.Target.x86.featureSet(&[_]std.Target.x86.Feature{
+ .@"64bit",
+ .adx,
+ .aes,
+ .avx,
+ .avx2,
+ .bmi,
+ .bmi2,
+ .clflushopt,
+ .clwb,
+ .cmov,
+ .cx16,
+ .cx8,
+ .f16c,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .gfni,
+ .idivq_to_divl,
+ .invpcid,
+ .lzcnt,
+ .macrofusion,
+ .mmx,
+ .movbe,
+ .movdir64b,
+ .movdiri,
+ .nopl,
+ .pclmul,
+ .pconfig,
+ .pku,
+ .popcnt,
+ .prfchw,
+ .ptwrite,
+ .rdpid,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .sha,
+ .shstk,
+ .slow_3ops_lea,
+ .slow_incdec,
+ .sse,
+ .sse2,
+ .sse3,
+ .sse4_1,
+ .sse4_2,
+ .ssse3,
+ .vaes,
+ .vpclmulqdq,
+ .vzeroupper,
+ .waitpkg,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+};
+pub const os = std.Target.Os{
+ .tag = .linux,
+ .version_range = .{ .linux = .{
+ .range = .{
+ .min = .{
+ .major = 5,
+ .minor = 15,
+ .patch = 0,
+ },
+ .max = .{
+ .major = 5,
+ .minor = 15,
+ .patch = 0,
+ },
+ },
+ .glibc = .{
+ .major = 2,
+ .minor = 35,
+ .patch = 0,
+ },
+ }},
+};
+pub const target: std.Target = .{
+ .cpu = cpu,
+ .os = os,
+ .abi = abi,
+ .ofmt = object_format,
+ .dynamic_linker = std.Target.DynamicLinker.init("/lib64/ld-linux-x86-64.so.2"),
+};
+pub const object_format = std.Target.ObjectFormat.elf;
+pub const mode = std.builtin.OptimizeMode.Debug;
+pub const link_libc = false;
+pub const link_libcpp = false;
+pub const have_error_return_tracing = true;
+pub const valgrind_support = true;
+pub const sanitize_thread = false;
+pub const position_independent_code = false;
+pub const position_independent_executable = false;
+pub const strip_debug_info = false;
+pub const code_model = std.builtin.CodeModel.default;
+pub const omit_frame_pointer = false;
+pub var test_functions: []const std.builtin.TestFn = undefined;
+
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/Cell.zig.html b/docs/src/main/Cell.zig.html
new file mode 100644
index 0000000..40d4dca
--- /dev/null
+++ b/docs/src/main/Cell.zig.html
@@ -0,0 +1,175 @@
+
+
+
+
+
Cell.zig - source view
+
+
+
+
+
+
const Image = @import("Image.zig");
+
+char: Character = .{},
+style: Style = .{},
+link: Hyperlink = .{},
+image: ?Image.Placement = null,
+
+
+pub const Segment = struct {
+ text: []const u8,
+ style: Style = .{},
+ link: Hyperlink = .{},
+};
+
+pub const Character = struct {
+ grapheme: []const u8 = " ",
+
+
+
+
+ width: usize = 1,
+};
+
+pub const Hyperlink = struct {
+ uri: []const u8 = "",
+
+ params: []const u8 = "",
+};
+
+pub const Style = struct {
+ pub const Underline = enum {
+ off,
+ single,
+ double,
+ curly,
+ dotted,
+ dashed,
+ };
+
+ fg: Color = .default,
+ bg: Color = .default,
+ ul: Color = .default,
+ ul_style: Underline = .off,
+
+ bold: bool = false,
+ dim: bool = false,
+ italic: bool = false,
+ blink: bool = false,
+ reverse: bool = false,
+ invisible: bool = false,
+ strikethrough: bool = false,
+};
+
+pub const Color = union(enum) {
+ default,
+ index: u8,
+ rgb: [3]u8,
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/GraphemeCache.zig.html b/docs/src/main/GraphemeCache.zig.html
new file mode 100644
index 0000000..870f86c
--- /dev/null
+++ b/docs/src/main/GraphemeCache.zig.html
@@ -0,0 +1,142 @@
+
+
+
+
+
GraphemeCache.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const testing = std.testing;
+
+const GraphemeCache = @This();
+
+
+buf: [1024 * 8]u8 = undefined,
+
+
+
+idx: usize = 0,
+
+
+pub fn put(self: *GraphemeCache, bytes: []const u8) []u8 {
+
+
+ if (self.idx + bytes.len > self.buf.len) self.idx = 0;
+ defer self.idx += bytes.len;
+
+
+ @memcpy(self.buf[self.idx .. self.idx + bytes.len], bytes);
+
+
+ return self.buf[self.idx .. self.idx + bytes.len];
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/Image.zig.html b/docs/src/main/Image.zig.html
new file mode 100644
index 0000000..b521895
--- /dev/null
+++ b/docs/src/main/Image.zig.html
@@ -0,0 +1,191 @@
+
+
+
+
+
Image.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const fmt = std.fmt;
+const math = std.math;
+const testing = std.testing;
+const base64 = std.base64.standard.Encoder;
+const zigimg = @import("zigimg");
+
+const Window = @import("Window.zig");
+
+const log = std.log.scoped(.image);
+
+const Image = @This();
+
+const transmit_opener = "\x1b_Gf=32,i={d},s={d},v={d},m={d};";
+
+pub const Source = union(enum) {
+ path: []const u8,
+ mem: []const u8,
+};
+
+pub const Placement = struct {
+ img_id: u32,
+ z_index: i32,
+ size: ?CellSize = null,
+};
+
+pub const CellSize = struct {
+ rows: usize,
+ cols: usize,
+};
+
+
+id: u32,
+
+
+
+width: usize,
+
+
+height: usize,
+
+pub fn draw(self: Image, win: Window, scale: bool, z_index: i32) void {
+ const p = Placement{
+ .img_id = self.id,
+ .z_index = z_index,
+ .size = sz: {
+ if (!scale) break :sz null;
+ break :sz CellSize{
+ .rows = win.height,
+ .cols = win.width,
+ };
+ },
+ };
+ win.writeCell(0, 0, .{ .image = p });
+}
+
+pub fn cellSize(self: Image, win: Window) !CellSize {
+
+
+ const x_pix = win.screen.width_pix;
+ const y_pix = win.screen.height_pix;
+ const w = win.screen.width;
+ const h = win.screen.height;
+
+ const pix_per_col = try std.math.divCeil(usize, x_pix, w);
+ const pix_per_row = try std.math.divCeil(usize, y_pix, h);
+
+ const cell_width = std.math.divCeil(usize, self.width, pix_per_col) catch 0;
+ const cell_height = std.math.divCeil(usize, self.height, pix_per_row) catch 0;
+ return .{
+ .rows = cell_height,
+ .cols = cell_width,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/InternalScreen.zig.html b/docs/src/main/InternalScreen.zig.html
new file mode 100644
index 0000000..aa0e257
--- /dev/null
+++ b/docs/src/main/InternalScreen.zig.html
@@ -0,0 +1,215 @@
+
+
+
+
+
InternalScreen.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const assert = std.debug.assert;
+const Style = @import("Cell.zig").Style;
+const Cell = @import("Cell.zig");
+const Shape = @import("Mouse.zig").Shape;
+
+const log = std.log.scoped(.internal_screen);
+
+const InternalScreen = @This();
+
+pub const InternalCell = struct {
+ char: std.ArrayList(u8) = undefined,
+ style: Style = .{},
+ uri: std.ArrayList(u8) = undefined,
+ uri_id: std.ArrayList(u8) = undefined,
+
+
+ skipped: bool = false,
+
+ pub fn eql(self: InternalCell, cell: Cell) bool {
+ return std.mem.eql(u8, self.char.items, cell.char.grapheme) and
+ std.meta.eql(self.style, cell.style) and
+ std.mem.eql(u8, self.uri.items, cell.link.uri) and
+ std.mem.eql(u8, self.uri_id.items, cell.link.params);
+ }
+};
+
+width: usize = 0,
+height: usize = 0,
+
+buf: []InternalCell = undefined,
+
+cursor_row: usize = 0,
+cursor_col: usize = 0,
+cursor_vis: bool = false,
+
+mouse_shape: Shape = .default,
+
+
+pub fn init(alloc: std.mem.Allocator, w: usize, h: usize) !InternalScreen {
+ var screen = InternalScreen{
+ .buf = try alloc.alloc(InternalCell, w * h),
+ };
+ for (screen.buf, 0..) |_, i| {
+ screen.buf[i] = .{
+ .char = try std.ArrayList(u8).initCapacity(alloc, 1),
+ .uri = std.ArrayList(u8).init(alloc),
+ .uri_id = std.ArrayList(u8).init(alloc),
+ };
+ }
+ screen.width = w;
+ screen.height = h;
+ return screen;
+}
+
+pub fn deinit(self: *InternalScreen, alloc: std.mem.Allocator) void {
+ for (self.buf, 0..) |_, i| {
+ self.buf[i].char.deinit();
+ self.buf[i].uri.deinit();
+ self.buf[i].uri_id.deinit();
+ }
+
+ alloc.free(self.buf);
+}
+
+
+pub fn writeCell(
+ self: *InternalScreen,
+ col: usize,
+ row: usize,
+ cell: Cell,
+) void {
+ if (self.width < col) {
+
+
+ return;
+ }
+ if (self.height < row) {
+
+
+ return;
+ }
+ const i = (row * self.width) + col;
+ assert(i < self.buf.len);
+ self.buf[i].char.clearRetainingCapacity();
+ self.buf[i].char.appendSlice(cell.char.grapheme) catch {
+ log.warn("couldn't write grapheme", .{});
+ };
+ self.buf[i].uri.clearRetainingCapacity();
+ self.buf[i].uri.appendSlice(cell.link.uri) catch {
+ log.warn("couldn't write uri", .{});
+ };
+ self.buf[i].uri.clearRetainingCapacity();
+ self.buf[i].uri_id.appendSlice(cell.link.params) catch {
+ log.warn("couldn't write uri_id", .{});
+ };
+ self.buf[i].style = cell.style;
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/Key.zig.html b/docs/src/main/Key.zig.html
new file mode 100644
index 0000000..7995ea7
--- /dev/null
+++ b/docs/src/main/Key.zig.html
@@ -0,0 +1,427 @@
+
+
+
+
+
Key.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const testing = std.testing;
+const ziglyph = @import("ziglyph");
+
+const Key = @This();
+
+pub const Modifiers = packed struct(u8) {
+ shift: bool = false,
+ alt: bool = false,
+ ctrl: bool = false,
+ super: bool = false,
+ hyper: bool = false,
+ meta: bool = false,
+ caps_lock: bool = false,
+ num_lock: bool = false,
+};
+
+pub const KittyFlags = packed struct(u5) {
+ disambiguate: bool = true,
+ report_events: bool = false,
+ report_alternate_keys: bool = true,
+ report_all_as_ctl_seqs: bool = true,
+ report_text: bool = true,
+};
+
+
+codepoint: u21,
+
+
+
+
+
+text: ?[]const u8 = null,
+
+
+
+shifted_codepoint: ?u21 = null,
+
+
+
+base_layout_codepoint: ?u21 = null,
+
+mods: Modifiers = .{},
+
+
+
+
+
+
+
+
+
+
+
+pub fn matches(self: Key, cp: u21, mods: Modifiers) bool {
+
+
+ if (self.matchExact(cp, mods)) return true;
+
+
+
+ if (self.matchText(cp, mods)) return true;
+
+
+
+ if (self.matchShiftedCodepoint(cp, mods)) return true;
+
+
+
+ if (self.matchShiftedCodepoint(cp, mods)) return true;
+
+ return false;
+}
+
+
+
+
+
+pub fn matchShortcut(self: Key, cp: u21, mods: Modifiers) bool {
+ if (self.base_layout_codepoint == null) return false;
+ return cp == self.base_layout_codepoint.? and std.meta.eql(self.mods, mods);
+}
+
+
+
+
+
+
+
+pub fn matchShiftedCodepoint(self: Key, cp: u21, mods: Modifiers) bool {
+ if (self.shifted_codepoint == null) return false;
+ if (!self.mods.shift) return false;
+ var self_mods = self.mods;
+ self_mods.shift = false;
+ return cp == self.shifted_codepoint.? and std.meta.eql(self_mods, mods);
+}
+
+
+
+
+
+pub fn matchText(self: Key, cp: u21, mods: Modifiers) bool {
+
+
+ if (self.text == null) return false;
+
+ var self_mods = self.mods;
+ var arg_mods = mods;
+ var code = cp;
+
+
+
+
+ if (ziglyph.isUpper(cp)) {
+
+
+ self_mods.shift = false;
+ self_mods.caps_lock = false;
+ arg_mods.shift = false;
+ arg_mods.caps_lock = false;
+ } else if (mods.shift or mods.caps_lock) {
+
+
+ code = ziglyph.toUpper(cp);
+ self_mods.shift = false;
+ self_mods.caps_lock = false;
+ arg_mods.shift = false;
+ arg_mods.caps_lock = false;
+ }
+
+ var buf: [4]u8 = undefined;
+ const n = std.unicode.utf8Encode(cp, buf[0..]) catch return false;
+ return std.mem.eql(u8, self.text.?, buf[0..n]) and std.meta.eql(self_mods, arg_mods);
+}
+
+
+
+pub fn matchExact(self: Key, cp: u21, mods: Modifiers) bool {
+ return self.codepoint == cp and std.meta.eql(self.mods, mods);
+}
+
+
+
+pub const enter: u21 = 0x0D;
+pub const tab: u21 = 0x09;
+pub const escape: u21 = 0x1B;
+pub const space: u21 = 0x20;
+pub const backspace: u21 = 0x7F;
+
+
+
+
+
+pub const multicodepoint: u21 = 1_114_112 + 1;
+
+
+
+
+
+pub const insert: u21 = 57348;
+pub const delete: u21 = 57349;
+pub const left: u21 = 57350;
+pub const right: u21 = 57351;
+pub const up: u21 = 57352;
+pub const down: u21 = 57353;
+pub const page_up: u21 = 57354;
+pub const page_down: u21 = 57355;
+pub const home: u21 = 57356;
+pub const end: u21 = 57357;
+pub const caps_lock: u21 = 57358;
+pub const scroll_lock: u21 = 57359;
+pub const num_lock: u21 = 57360;
+pub const print_screen: u21 = 57361;
+pub const pause: u21 = 57362;
+pub const menu: u21 = 57363;
+pub const f1: u21 = 57364;
+pub const f2: u21 = 57365;
+pub const f3: u21 = 57366;
+pub const f4: u21 = 57367;
+pub const f5: u21 = 57368;
+pub const f6: u21 = 57369;
+pub const f7: u21 = 57370;
+pub const f8: u21 = 57371;
+pub const f9: u21 = 57372;
+pub const f10: u21 = 57373;
+pub const f11: u21 = 57374;
+pub const f12: u21 = 57375;
+pub const f13: u21 = 57376;
+pub const f14: u21 = 57377;
+pub const f15: u21 = 57378;
+pub const @"f16": u21 = 57379;
+pub const f17: u21 = 57380;
+pub const f18: u21 = 57381;
+pub const f19: u21 = 57382;
+pub const f20: u21 = 57383;
+pub const f21: u21 = 57384;
+pub const f22: u21 = 57385;
+pub const f23: u21 = 57386;
+pub const f24: u21 = 57387;
+pub const f25: u21 = 57388;
+pub const f26: u21 = 57389;
+pub const f27: u21 = 57390;
+pub const f28: u21 = 57391;
+pub const f29: u21 = 57392;
+pub const f30: u21 = 57393;
+pub const f31: u21 = 57394;
+pub const @"f32": u21 = 57395;
+pub const f33: u21 = 57396;
+pub const f34: u21 = 57397;
+pub const f35: u21 = 57398;
+pub const kp_0: u21 = 57399;
+pub const kp_1: u21 = 57400;
+pub const kp_2: u21 = 57401;
+pub const kp_3: u21 = 57402;
+pub const kp_4: u21 = 57403;
+pub const kp_5: u21 = 57404;
+pub const kp_6: u21 = 57405;
+pub const kp_7: u21 = 57406;
+pub const kp_8: u21 = 57407;
+pub const kp_9: u21 = 57408;
+pub const kp_decimal: u21 = 57409;
+pub const kp_divide: u21 = 57410;
+pub const kp_multiply: u21 = 57411;
+pub const kp_subtract: u21 = 57412;
+pub const kp_add: u21 = 57413;
+pub const kp_enter: u21 = 57414;
+pub const kp_equal: u21 = 57415;
+pub const kp_separator: u21 = 57416;
+pub const kp_left: u21 = 57417;
+pub const kp_right: u21 = 57418;
+pub const kp_up: u21 = 57419;
+pub const kp_down: u21 = 57420;
+pub const kp_page_up: u21 = 57421;
+pub const kp_page_down: u21 = 57422;
+pub const kp_home: u21 = 57423;
+pub const kp_end: u21 = 57424;
+pub const kp_insert: u21 = 57425;
+pub const kp_delete: u21 = 57426;
+pub const kp_begin: u21 = 57427;
+pub const media_play: u21 = 57428;
+pub const media_pause: u21 = 57429;
+pub const media_play_pause: u21 = 57430;
+pub const media_reverse: u21 = 57431;
+pub const media_stop: u21 = 57432;
+pub const media_fast_forward: u21 = 57433;
+pub const media_rewind: u21 = 57434;
+pub const media_track_next: u21 = 57435;
+pub const media_track_previous: u21 = 57436;
+pub const media_record: u21 = 57437;
+pub const lower_volume: u21 = 57438;
+pub const raise_volume: u21 = 57439;
+pub const mute_volume: u21 = 57440;
+pub const left_shift: u21 = 57441;
+pub const left_control: u21 = 57442;
+pub const left_alt: u21 = 57443;
+pub const left_super: u21 = 57444;
+pub const left_hyper: u21 = 57445;
+pub const left_meta: u21 = 57446;
+pub const right_shift: u21 = 57447;
+pub const right_control: u21 = 57448;
+pub const right_alt: u21 = 57449;
+pub const right_super: u21 = 57450;
+pub const right_hyper: u21 = 57451;
+pub const right_meta: u21 = 57452;
+pub const iso_level_3_shift: u21 = 57453;
+pub const iso_level_5_shift: u21 = 57454;
+
+test "matches 'a'" {
+ const key: Key = .{
+ .codepoint = 'a',
+ };
+ try testing.expect(key.matches('a', .{}));
+}
+
+test "matches 'shift+a'" {
+ const key: Key = .{
+ .codepoint = 'a',
+ .mods = .{ .shift = true },
+ .text = "A",
+ };
+ try testing.expect(key.matches('a', .{ .shift = true }));
+ try testing.expect(key.matches('A', .{}));
+ try testing.expect(!key.matches('A', .{ .ctrl = true }));
+}
+
+test "matches 'shift+tab'" {
+ const key: Key = .{
+ .codepoint = Key.tab,
+ .mods = .{ .shift = true },
+ };
+ try testing.expect(key.matches(Key.tab, .{ .shift = true }));
+ try testing.expect(!key.matches(Key.tab, .{}));
+}
+
+test "matches 'shift+;'" {
+ const key: Key = .{
+ .codepoint = ';',
+ .shifted_codepoint = ':',
+ .mods = .{ .shift = true },
+ .text = ":",
+ };
+ try testing.expect(key.matches(';', .{ .shift = true }));
+ try testing.expect(key.matches(':', .{}));
+
+ const colon: Key = .{
+ .codepoint = ':',
+ .mods = .{},
+ };
+ try testing.expect(colon.matches(':', .{}));
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/Mouse.zig.html b/docs/src/main/Mouse.zig.html
new file mode 100644
index 0000000..3398d21
--- /dev/null
+++ b/docs/src/main/Mouse.zig.html
@@ -0,0 +1,163 @@
+
+
+
+
+
Mouse.zig - source view
+
+
+
+
+
+
+pub const Mouse = @This();
+
+pub const Shape = enum {
+ default,
+ text,
+ pointer,
+ help,
+ progress,
+ wait,
+ @"ew-resize",
+ @"ns-resize",
+ cell,
+};
+
+pub const Button = enum(u8) {
+ left,
+ middle,
+ right,
+ none,
+ wheel_up = 64,
+ wheel_down = 65,
+ button_8 = 128,
+ button_9 = 129,
+ button_10 = 130,
+ button_11 = 131,
+};
+
+pub const Modifiers = packed struct(u3) {
+ shift: bool = false,
+ alt: bool = false,
+ ctrl: bool = false,
+};
+
+pub const Type = enum {
+ press,
+ release,
+ motion,
+ drag,
+};
+
+col: usize,
+row: usize,
+button: Button,
+mods: Modifiers,
+type: Type,
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/Options.zig.html b/docs/src/main/Options.zig.html
new file mode 100644
index 0000000..de07c0e
--- /dev/null
+++ b/docs/src/main/Options.zig.html
@@ -0,0 +1,119 @@
+
+
+
+
+
Options.zig - source view
+
+
+
+
+
+
+const Options = @This();
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/Parser.zig.html b/docs/src/main/Parser.zig.html
new file mode 100644
index 0000000..7df686f
--- /dev/null
+++ b/docs/src/main/Parser.zig.html
@@ -0,0 +1,1007 @@
+
+
+
+
+
Parser.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const testing = std.testing;
+const Event = @import("event.zig").Event;
+const Key = @import("Key.zig");
+const Mouse = @import("Mouse.zig");
+const CodePointIterator = @import("ziglyph").CodePointIterator;
+const graphemeBreak = @import("ziglyph").graphemeBreak;
+
+const log = std.log.scoped(.parser);
+
+const Parser = @This();
+
+
+
+pub const Result = struct {
+ event: ?Event,
+ n: usize,
+};
+
+
+
+
+
+const Sequence = struct {
+
+
+ private_indicator: ?u8 = null,
+
+
+ intermediate: ?u8 = null,
+
+
+ params: [16]u16 = undefined,
+ param_idx: usize = 0,
+ param_buf: [8]u8 = undefined,
+ param_buf_idx: usize = 0,
+ sub_state: std.StaticBitSet(16) = std.StaticBitSet(16).initEmpty(),
+ empty_state: std.StaticBitSet(16) = std.StaticBitSet(16).initEmpty(),
+};
+
+const mouse_bits = struct {
+ const motion: u8 = 0b00100000;
+ const buttons: u8 = 0b11000011;
+ const shift: u8 = 0b00000100;
+ const alt: u8 = 0b00001000;
+ const ctrl: u8 = 0b00010000;
+};
+
+
+
+const State = enum {
+ ground,
+ escape,
+ csi,
+ osc,
+ dcs,
+ sos,
+ pm,
+ apc,
+ ss2,
+ ss3,
+};
+
+
+
+
+
+buf: [128]u8 = undefined,
+
+pub fn parse(self: *Parser, input: []const u8) !Result {
+ const n = input.len;
+
+ var seq: Sequence = .{};
+
+ var state: State = .ground;
+
+ var i: usize = 0;
+ var start: usize = 0;
+
+
+
+
+ while (i < n) : (i += 1) {
+ const b = input[i];
+ switch (state) {
+ .ground => {
+
+
+
+
+
+
+
+
+ const key: Key = switch (b) {
+ 0x00 => .{ .codepoint = '@', .mods = .{ .ctrl = true } },
+ 0x08 => .{ .codepoint = Key.backspace },
+ 0x01...0x07,
+ 0x09...0x1A,
+ => .{ .codepoint = b + 0x60, .mods = .{ .ctrl = true } },
+ 0x1B => escape: {
+
+
+
+
+
+
+ if (i == (n - 1)) {
+ const event = Key{
+ .codepoint = Key.escape,
+ };
+ break :escape event;
+ }
+ state = .escape;
+ continue;
+ },
+ 0x7F => .{ .codepoint = Key.backspace },
+ else => blk: {
+ var iter: CodePointIterator = .{ .bytes = input[i..] };
+
+
+ var cp = iter.next() orelse return .{ .event = null, .n = 0 };
+
+ var code = cp.code;
+ i += cp.len - 1;
+
+ var g_state: u3 = 0;
+ while (iter.next()) |next_cp| {
+ if (graphemeBreak(cp.code, next_cp.code, &g_state)) {
+ break;
+ }
+ code = Key.multicodepoint;
+ i += next_cp.len;
+ cp = next_cp;
+ }
+
+ break :blk .{ .codepoint = code, .text = input[start .. i + 1] };
+ },
+ };
+ return .{
+ .event = .{ .key_press = key },
+ .n = i + 1,
+ };
+ },
+ .escape => {
+ seq = .{};
+ start = i;
+ switch (b) {
+ 0x4F => state = .ss3,
+ 0x50 => state = .dcs,
+ 0x58 => state = .sos,
+ 0x5B => state = .csi,
+ 0x5D => state = .osc,
+ 0x5E => state = .pm,
+ 0x5F => state = .apc,
+ else => {
+
+
+ const key: Key = .{
+ .codepoint = b,
+ .mods = .{ .alt = true },
+ };
+ return .{
+ .event = .{ .key_press = key },
+ .n = i + 1,
+ };
+ },
+ }
+ },
+ .ss3 => {
+ const key: Key = switch (b) {
+ 'A' => .{ .codepoint = Key.up },
+ 'B' => .{ .codepoint = Key.down },
+ 'C' => .{ .codepoint = Key.right },
+ 'D' => .{ .codepoint = Key.left },
+ 'F' => .{ .codepoint = Key.end },
+ 'H' => .{ .codepoint = Key.home },
+ 'P' => .{ .codepoint = Key.f1 },
+ 'Q' => .{ .codepoint = Key.f2 },
+ 'R' => .{ .codepoint = Key.f3 },
+ 'S' => .{ .codepoint = Key.f4 },
+ else => {
+ log.warn("unhandled ss3: {x}", .{b});
+ return .{
+ .event = null,
+ .n = i + 1,
+ };
+ },
+ };
+ return .{
+ .event = .{ .key_press = key },
+ .n = i + 1,
+ };
+ },
+ .csi => {
+ switch (b) {
+
+
+
+
+ 0x00...0x1F => {},
+
+
+
+
+ 0x20...0x2F => seq.intermediate = b,
+ 0x30...0x39 => {
+ seq.param_buf[seq.param_buf_idx] = b;
+ seq.param_buf_idx += 1;
+ },
+
+
+ 0x3C...0x3F => seq.private_indicator = b,
+ ';' => {
+ if (seq.param_buf_idx == 0) {
+
+
+
+
+ seq.params[seq.param_idx] = 0;
+ seq.empty_state.set(seq.param_idx);
+ seq.param_idx += 1;
+ } else {
+ const p = try std.fmt.parseUnsigned(u16, seq.param_buf[0..seq.param_buf_idx], 10);
+ seq.param_buf_idx = 0;
+ seq.params[seq.param_idx] = p;
+ seq.param_idx += 1;
+ }
+ },
+ ':' => {
+ if (seq.param_buf_idx == 0) {
+
+
+
+
+ seq.params[seq.param_idx] = 0;
+ seq.empty_state.set(seq.param_idx);
+ seq.param_idx += 1;
+
+
+ seq.sub_state.set(seq.param_idx);
+ } else {
+ const p = try std.fmt.parseUnsigned(u16, seq.param_buf[0..seq.param_buf_idx], 10);
+ seq.param_buf_idx = 0;
+ seq.params[seq.param_idx] = p;
+ seq.param_idx += 1;
+
+
+ seq.sub_state.set(seq.param_idx);
+ }
+ },
+ 0x40...0xFF => {
+ if (seq.param_buf_idx > 0) {
+ const p = try std.fmt.parseUnsigned(u16, seq.param_buf[0..seq.param_buf_idx], 10);
+ seq.param_buf_idx = 0;
+ seq.params[seq.param_idx] = p;
+ seq.param_idx += 1;
+ }
+
+
+ state = .ground;
+ const codepoint: u21 = switch (b) {
+ 'A' => Key.up,
+ 'B' => Key.down,
+ 'C' => Key.right,
+ 'D' => Key.left,
+ 'E' => Key.kp_begin,
+ 'F' => Key.end,
+ 'H' => Key.home,
+ 'M', 'm' => {
+
+ const priv = seq.private_indicator orelse {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{ .event = null, .n = i + 1 };
+ };
+ if (priv != '<') {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{ .event = null, .n = i + 1 };
+ }
+ if (seq.param_idx != 3) {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{ .event = null, .n = i + 1 };
+ }
+ const button: Mouse.Button = @enumFromInt(seq.params[0] & mouse_bits.buttons);
+ const motion = seq.params[0] & mouse_bits.motion > 0;
+ const shift = seq.params[0] & mouse_bits.shift > 0;
+ const alt = seq.params[0] & mouse_bits.alt > 0;
+ const ctrl = seq.params[0] & mouse_bits.ctrl > 0;
+ const col: usize = seq.params[1] - 1;
+ const row: usize = seq.params[2] - 1;
+
+ const mouse = Mouse{
+ .button = button,
+ .mods = .{
+ .shift = shift,
+ .alt = alt,
+ .ctrl = ctrl,
+ },
+ .col = col,
+ .row = row,
+ .type = blk: {
+ if (motion and button != Mouse.Button.none) {
+ break :blk .drag;
+ }
+ if (motion and button == Mouse.Button.none) {
+ break :blk .motion;
+ }
+ if (b == 'm') break :blk .release;
+ break :blk .press;
+ },
+ };
+ return .{ .event = .{ .mouse = mouse }, .n = i + 1 };
+ },
+ 'P' => Key.f1,
+ 'Q' => Key.f2,
+ 'R' => Key.f3,
+ 'S' => Key.f4,
+ '~' => blk: {
+
+
+
+
+ if (seq.param_idx < 1) {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{
+ .event = null,
+ .n = i + 1,
+ };
+ }
+ switch (seq.params[0]) {
+ 2 => break :blk Key.insert,
+ 3 => break :blk Key.delete,
+ 5 => break :blk Key.page_up,
+ 6 => break :blk Key.page_down,
+ 7 => break :blk Key.home,
+ 8 => break :blk Key.end,
+ 11 => break :blk Key.f1,
+ 12 => break :blk Key.f2,
+ 13 => break :blk Key.f3,
+ 14 => break :blk Key.f4,
+ 15 => break :blk Key.f5,
+ 17 => break :blk Key.f6,
+ 18 => break :blk Key.f7,
+ 19 => break :blk Key.f8,
+ 20 => break :blk Key.f9,
+ 21 => break :blk Key.f10,
+ 23 => break :blk Key.f11,
+ 24 => break :blk Key.f12,
+ 200 => {
+ return .{
+ .event = .paste_start,
+ .n = i + 1,
+ };
+ },
+ 201 => {
+ return .{
+ .event = .paste_end,
+ .n = i + 1,
+ };
+ },
+ 57427 => break :blk Key.kp_begin,
+ else => {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{
+ .event = null,
+ .n = i + 1,
+ };
+ },
+ }
+ },
+ 'u' => blk: {
+ if (seq.private_indicator) |priv| {
+
+
+ if (priv == '?') {
+ return .{
+ .event = .cap_kitty_keyboard,
+ .n = i + 1,
+ };
+ } else {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{
+ .event = null,
+ .n = i + 1,
+ };
+ }
+ }
+ if (seq.param_idx == 0) {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{
+ .event = null,
+ .n = i + 1,
+ };
+ }
+
+
+
+
+ break :blk seq.params[0];
+ },
+
+ 'I' => {
+
+ return .{ .event = .focus_in, .n = i + 1 };
+ },
+ 'O' => {
+
+ return .{ .event = .focus_out, .n = i + 1 };
+ },
+ 'y' => {
+
+ const priv = seq.private_indicator orelse {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{ .event = null, .n = i + 1 };
+ };
+ if (priv != '?') {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{ .event = null, .n = i + 1 };
+ }
+ const intm = seq.intermediate orelse {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{ .event = null, .n = i + 1 };
+ };
+ if (intm != '$') {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{ .event = null, .n = i + 1 };
+ }
+ if (seq.param_idx != 2) {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{ .event = null, .n = i + 1 };
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ switch (seq.params[0]) {
+ 2027 => {
+ switch (seq.params[1]) {
+ 0, 4 => return .{ .event = null, .n = i + 1 },
+ else => return .{ .event = .cap_unicode, .n = i + 1 },
+ }
+ },
+ 2031 => {},
+ else => {
+ log.warn("unhandled DECRPM: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{ .event = null, .n = i + 1 };
+ },
+ }
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{ .event = null, .n = i + 1 };
+ },
+ 'c' => {
+
+ const priv = seq.private_indicator orelse {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{ .event = null, .n = i + 1 };
+ };
+ if (priv != '?') {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{ .event = null, .n = i + 1 };
+ }
+ return .{ .event = .cap_da1, .n = i + 1 };
+ },
+ else => {
+ log.warn("unhandled csi: CSI {s}", .{input[start + 1 .. i + 1]});
+ return .{
+ .event = null,
+ .n = i + 1,
+ };
+ },
+ };
+
+ var key: Key = .{ .codepoint = codepoint };
+
+ var idx: usize = 0;
+ var field: u8 = 0;
+
+
+ while (idx < seq.param_idx) : (idx += 1) {
+ switch (field) {
+ 0 => {
+ defer field += 1;
+
+
+
+
+
+
+
+
+
+
+
+ if (!seq.sub_state.isSet(idx + 1)) {
+ continue;
+ }
+ idx += 1;
+
+
+
+
+ if (!seq.empty_state.isSet(idx)) {
+ key.shifted_codepoint = seq.params[idx];
+ }
+
+
+
+
+ if (!seq.sub_state.isSet(idx + 1)) {
+ continue;
+ }
+ idx += 1;
+ key.base_layout_codepoint = seq.params[idx];
+ },
+ 1 => {
+ defer field += 1;
+
+
+
+
+ if (seq.empty_state.isSet(idx)) {
+ continue;
+ }
+
+
+ const ps: u8 = blk: {
+ if (seq.params[idx] == 0) break :blk 1;
+ break :blk @truncate(seq.params[idx]);
+ };
+ key.mods = @bitCast(ps - 1);
+ },
+ 2 => {
+
+
+ var total: usize = 0;
+ while (idx < seq.param_idx) : (idx += 1) {
+ total += try std.unicode.utf8Encode(seq.params[idx], self.buf[total..]);
+ }
+ key.text = self.buf[0..total];
+ },
+ else => {},
+ }
+ }
+ return .{
+ .event = .{ .key_press = key },
+ .n = i + 1,
+ };
+ },
+ }
+ },
+ .apc => {
+ switch (b) {
+ 0x1B => {
+ state = .ground;
+
+
+ i += 1;
+ switch (input[start + 1]) {
+ 'G' => {
+ return .{
+ .event = .cap_kitty_graphics,
+ .n = i + 1,
+ };
+ },
+ else => {
+ log.warn("unhandled apc: APC {s}", .{input[start + 1 .. i + 1]});
+ return .{
+ .event = null,
+ .n = i + 1,
+ };
+ },
+ }
+ },
+ else => {},
+ }
+ },
+ .sos, .pm => {
+ switch (b) {
+ 0x1B => {
+ state = .ground;
+
+
+ i += 1;
+ log.warn("unhandled sos/pm: SOS/PM {s}", .{input[start + 1 .. i + 1]});
+ return .{
+ .event = null,
+ .n = i + 1,
+ };
+ },
+ else => {},
+ }
+ },
+ else => {},
+ }
+ }
+
+
+
+
+ return .{
+ .event = null,
+ .n = 0,
+ };
+}
+
+test "parse: single xterm keypress" {
+ const input = "a";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{
+ .codepoint = 'a',
+ .text = "a",
+ };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(1, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: single xterm keypress backspace" {
+ const input = "\x08";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{
+ .codepoint = Key.backspace,
+ };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(1, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: single xterm keypress with more buffer" {
+ const input = "ab";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{
+ .codepoint = 'a',
+ .text = "a",
+ };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(1, result.n);
+ try testing.expectEqualStrings(expected_key.text.?, result.event.?.key_press.text.?);
+ try testing.expectEqualDeep(expected_event, result.event);
+}
+
+test "parse: xterm escape keypress" {
+ const input = "\x1b";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{ .codepoint = Key.escape };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(1, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: xterm ctrl+a" {
+ const input = "\x01";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{ .codepoint = 'a', .mods = .{ .ctrl = true } };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(1, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: xterm alt+a" {
+ const input = "\x1ba";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{ .codepoint = 'a', .mods = .{ .alt = true } };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(2, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: xterm invalid ss3" {
+ const input = "\x1bOZ";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+
+ try testing.expectEqual(3, result.n);
+ try testing.expectEqual(null, result.event);
+}
+
+test "parse: xterm key up" {
+ {
+
+
+ const input = "\x1bOA";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{ .codepoint = Key.up };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(3, result.n);
+ try testing.expectEqual(expected_event, result.event);
+ }
+
+ {
+
+
+ const input = "\x1b[2~";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{ .codepoint = Key.insert };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(4, result.n);
+ try testing.expectEqual(expected_event, result.event);
+ }
+}
+
+test "parse: xterm shift+up" {
+ const input = "\x1b[1;2A";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{ .codepoint = Key.up, .mods = .{ .shift = true } };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(6, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: xterm insert" {
+ const input = "\x1b[1;2A";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{ .codepoint = Key.up, .mods = .{ .shift = true } };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(6, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: paste_start" {
+ const input = "\x1b[200~";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_event: Event = .paste_start;
+
+ try testing.expectEqual(6, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: paste_end" {
+ const input = "\x1b[201~";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_event: Event = .paste_end;
+
+ try testing.expectEqual(6, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: focus_in" {
+ const input = "\x1b[I";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_event: Event = .focus_in;
+
+ try testing.expectEqual(3, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: focus_out" {
+ const input = "\x1b[O";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_event: Event = .focus_out;
+
+ try testing.expectEqual(3, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: kitty: shift+a without text reporting" {
+ const input = "\x1b[97:65;2u";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{
+ .codepoint = 'a',
+ .shifted_codepoint = 'A',
+ .mods = .{ .shift = true },
+ };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(10, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: kitty: alt+shift+a without text reporting" {
+ const input = "\x1b[97:65;4u";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{
+ .codepoint = 'a',
+ .shifted_codepoint = 'A',
+ .mods = .{ .shift = true, .alt = true },
+ };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(10, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: kitty: a without text reporting" {
+ const input = "\x1b[97u";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{
+ .codepoint = 'a',
+ };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(5, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: single codepoint" {
+ const input = "🙂";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{
+ .codepoint = 0x1F642,
+ .text = input,
+ };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(4, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: single codepoint with more in buffer" {
+ const input = "🙂a";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{
+ .codepoint = 0x1F642,
+ .text = "🙂",
+ };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(4, result.n);
+ try testing.expectEqualDeep(expected_event, result.event);
+}
+
+test "parse: multiple codepoint grapheme" {
+ const input = "👩🚀";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{
+ .codepoint = Key.multicodepoint,
+ .text = input,
+ };
+ const expected_event: Event = .{ .key_press = expected_key };
+
+ try testing.expectEqual(input.len, result.n);
+ try testing.expectEqual(expected_event, result.event);
+}
+
+test "parse: multiple codepoint grapheme with more after" {
+ const input = "👩🚀abc";
+ var parser: Parser = .{};
+ const result = try parser.parse(input);
+ const expected_key: Key = .{
+ .codepoint = Key.multicodepoint,
+ .text = "👩🚀",
+ };
+
+ try testing.expectEqual(expected_key.text.?.len, result.n);
+ const actual = result.event.?.key_press;
+ try testing.expectEqualStrings(expected_key.text.?, actual.text.?);
+ try testing.expectEqual(expected_key.codepoint, actual.codepoint);
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/Screen.zig.html b/docs/src/main/Screen.zig.html
new file mode 100644
index 0000000..d072119
--- /dev/null
+++ b/docs/src/main/Screen.zig.html
@@ -0,0 +1,181 @@
+
+
+
+
+
Screen.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const assert = std.debug.assert;
+
+const Cell = @import("Cell.zig");
+const Shape = @import("Mouse.zig").Shape;
+const Image = @import("Image.zig");
+const Winsize = @import("Tty.zig").Winsize;
+
+const log = std.log.scoped(.screen);
+
+const Screen = @This();
+
+width: usize = 0,
+height: usize = 0,
+
+width_pix: usize = 0,
+height_pix: usize = 0,
+
+buf: []Cell = undefined,
+
+cursor_row: usize = 0,
+cursor_col: usize = 0,
+cursor_vis: bool = false,
+
+
+unicode: bool = false,
+
+mouse_shape: Shape = .default,
+
+pub fn init(alloc: std.mem.Allocator, winsize: Winsize) !Screen {
+ const w = winsize.cols;
+ const h = winsize.rows;
+ var self = Screen{
+ .buf = try alloc.alloc(Cell, w * h),
+ .width = w,
+ .height = h,
+ .width_pix = winsize.x_pixel,
+ .height_pix = winsize.y_pixel,
+ };
+ for (self.buf, 0..) |_, i| {
+ self.buf[i] = .{};
+ }
+ return self;
+}
+pub fn deinit(self: *Screen, alloc: std.mem.Allocator) void {
+ alloc.free(self.buf);
+}
+
+
+pub fn writeCell(self: *Screen, col: usize, row: usize, cell: Cell) void {
+ if (self.width < col) {
+
+
+ return;
+ }
+ if (self.height < row) {
+
+
+ return;
+ }
+ const i = (row * self.width) + col;
+ assert(i < self.buf.len);
+ self.buf[i] = cell;
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/Tty.zig.html b/docs/src/main/Tty.zig.html
new file mode 100644
index 0000000..a88c798
--- /dev/null
+++ b/docs/src/main/Tty.zig.html
@@ -0,0 +1,410 @@
+
+
+
+
+
Tty.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const builtin = @import("builtin");
+const os = std.os;
+const Vaxis = @import("vaxis.zig").Vaxis;
+const Parser = @import("Parser.zig");
+const GraphemeCache = @import("GraphemeCache.zig");
+
+const log = std.log.scoped(.tty);
+
+const Tty = @This();
+
+const Writer = std.io.Writer(os.fd_t, os.WriteError, os.write);
+
+const BufferedWriter = std.io.BufferedWriter(4096, Writer);
+
+
+termios: os.termios,
+
+
+fd: os.fd_t,
+
+
+quit_fd: ?os.fd_t = null,
+
+buffered_writer: BufferedWriter,
+
+
+pub fn init() !Tty {
+
+
+ const fd = try os.open("/dev/tty", .{ .ACCMODE = .RDWR }, 0);
+
+
+
+ const termios = try makeRaw(fd);
+
+ return Tty{
+ .fd = fd,
+ .termios = termios,
+ .buffered_writer = std.io.bufferedWriter(Writer{ .context = fd }),
+ };
+}
+
+
+pub fn deinit(self: *Tty) void {
+ os.tcsetattr(self.fd, .FLUSH, self.termios) catch |err| {
+ log.err("couldn't restore terminal: {}", .{err});
+ };
+ os.close(self.fd);
+}
+
+
+pub fn stop(self: *Tty) void {
+ if (self.quit_fd) |fd| {
+ _ = std.os.write(fd, "q") catch {};
+ }
+}
+
+
+pub fn run(
+ self: *Tty,
+ comptime Event: type,
+ vx: *Vaxis(Event),
+) !void {
+
+
+ const pipe = try os.pipe();
+ defer os.close(pipe[0]);
+ defer os.close(pipe[1]);
+
+
+
+ const winsize = try getWinsize(self.fd);
+ if (@hasField(Event, "winsize")) {
+ vx.postEvent(.{ .winsize = winsize });
+ }
+
+
+
+ self.quit_fd = pipe[1];
+
+
+
+
+
+
+
+ const WinchHandler = struct {
+ const Self = @This();
+
+ var vx_winch: *Vaxis(Event) = undefined;
+ var fd: os.fd_t = undefined;
+
+ fn init(vx_arg: *Vaxis(Event), fd_arg: os.fd_t) !void {
+ vx_winch = vx_arg;
+ fd = fd_arg;
+ var act = os.Sigaction{
+ .handler = .{ .handler = Self.handleWinch },
+ .mask = switch (builtin.os.tag) {
+ .macos => 0,
+ .linux => std.os.empty_sigset,
+ else => @compileError("os not supported"),
+ },
+ .flags = 0,
+ };
+
+ try os.sigaction(os.SIG.WINCH, &act, null);
+ }
+
+ fn handleWinch(_: c_int) callconv(.C) void {
+ const ws = getWinsize(fd) catch {
+ return;
+ };
+ if (@hasField(Event, "winsize")) {
+ vx_winch.postEvent(.{ .winsize = ws });
+ }
+ }
+ };
+ try WinchHandler.init(vx, self.fd);
+
+
+
+ var cache: GraphemeCache = .{};
+
+
+
+ var pollfds: [2]std.os.pollfd = .{
+ .{ .fd = self.fd, .events = std.os.POLL.IN, .revents = undefined },
+ .{ .fd = pipe[0], .events = std.os.POLL.IN, .revents = undefined },
+ };
+
+ var parser: Parser = .{};
+
+
+
+ var buf: [1024]u8 = undefined;
+
+
+ while (true) {
+ _ = try std.os.poll(&pollfds, -1);
+ if (pollfds[1].revents & std.os.POLL.IN != 0) {
+ log.info("quitting read thread", .{});
+ return;
+ }
+
+ const n = try os.read(self.fd, &buf);
+ var start: usize = 0;
+ while (start < n) {
+ const result = try parser.parse(buf[start..n]);
+ start += result.n;
+
+
+
+
+
+
+
+
+
+
+
+ const event = result.event orelse continue;
+ switch (event) {
+ .key_press => |key| {
+ if (@hasField(Event, "key_press")) {
+
+
+ var mut_key = key;
+ if (key.text) |text| {
+ mut_key.text = cache.put(text);
+ }
+ vx.postEvent(.{ .key_press = mut_key });
+ }
+ },
+ .mouse => |mouse| {
+ if (@hasField(Event, "mouse")) {
+ vx.postEvent(.{ .mouse = mouse });
+ }
+ },
+ .focus_in => {
+ if (@hasField(Event, "focus_in")) {
+ vx.postEvent(.focus_in);
+ }
+ },
+ .focus_out => {
+ if (@hasField(Event, "focus_out")) {
+ vx.postEvent(.focus_out);
+ }
+ },
+ .paste_start => {
+ if (@hasField(Event, "paste_start")) {
+ vx.postEvent(.paste_start);
+ }
+ },
+ .paste_end => {
+ if (@hasField(Event, "paste_end")) {
+ vx.postEvent(.paste_end);
+ }
+ },
+ .cap_kitty_keyboard => {
+ log.info("kitty keyboard capability detected", .{});
+ vx.caps.kitty_keyboard = true;
+ },
+ .cap_kitty_graphics => {
+ if (!vx.caps.kitty_graphics) {
+ log.info("kitty graphics capability detected", .{});
+ vx.caps.kitty_graphics = true;
+ }
+ },
+ .cap_rgb => {
+ log.info("rgb capability detected", .{});
+ vx.caps.rgb = true;
+ },
+ .cap_unicode => {
+ log.info("unicode capability detected", .{});
+ vx.caps.unicode = true;
+ vx.screen.unicode = true;
+ },
+ .cap_da1 => {
+ std.Thread.Futex.wake(&vx.query_futex, 10);
+ },
+ }
+ }
+ }
+}
+
+
+
+pub fn write(self: *Tty, bytes: []const u8) !usize {
+ return self.buffered_writer.write(bytes);
+}
+
+
+pub fn flush(self: *Tty) !void {
+ try self.buffered_writer.flush();
+}
+
+
+pub fn makeRaw(fd: os.fd_t) !os.termios {
+ const state = try os.tcgetattr(fd);
+ var raw = state;
+
+
+ raw.iflag.IGNBRK = false;
+ raw.iflag.BRKINT = false;
+ raw.iflag.ISTRIP = false;
+ raw.iflag.INLCR = false;
+ raw.iflag.IGNCR = false;
+ raw.iflag.ICRNL = false;
+ raw.iflag.IXON = false;
+
+ raw.oflag.OPOST = false;
+
+ raw.lflag.ECHO = false;
+ raw.lflag.ECHONL = false;
+ raw.lflag.ICANON = false;
+ raw.lflag.IEXTEN = false;
+
+ raw.cflag.CSIZE = .CS8;
+ raw.cflag.PARENB = false;
+
+ raw.cc[@intFromEnum(std.posix.V.MIN)] = 1;
+ raw.cc[@intFromEnum(std.posix.V.TIME)] = 0;
+ try os.tcsetattr(fd, .FLUSH, raw);
+ return state;
+}
+
+
+pub const Winsize = struct {
+ rows: usize,
+ cols: usize,
+ x_pixel: usize,
+ y_pixel: usize,
+};
+
+fn getWinsize(fd: os.fd_t) !Winsize {
+ var winsize = os.winsize{
+ .ws_row = 0,
+ .ws_col = 0,
+ .ws_xpixel = 0,
+ .ws_ypixel = 0,
+ };
+
+ const err = os.system.ioctl(fd, os.T.IOCGWINSZ, @intFromPtr(&winsize));
+ if (os.errno(err) == .SUCCESS)
+ return Winsize{
+ .rows = winsize.ws_row,
+ .cols = winsize.ws_col,
+ .x_pixel = winsize.ws_xpixel,
+ .y_pixel = winsize.ws_ypixel,
+ };
+ return error.IoctlError;
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/Window.zig.html b/docs/src/main/Window.zig.html
new file mode 100644
index 0000000..c175b99
--- /dev/null
+++ b/docs/src/main/Window.zig.html
@@ -0,0 +1,338 @@
+
+
+
+
+
Window.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const ziglyph = @import("ziglyph");
+const WordIterator = ziglyph.WordIterator;
+const GraphemeIterator = ziglyph.GraphemeIterator;
+
+const Screen = @import("Screen.zig");
+const Cell = @import("Cell.zig");
+const Segment = @import("Cell.zig").Segment;
+const gw = @import("gwidth.zig");
+
+const log = std.log.scoped(.window);
+
+const Window = @This();
+
+pub const Size = union(enum) {
+ expand,
+ limit: usize,
+};
+
+
+x_off: usize,
+
+y_off: usize,
+
+width: usize,
+
+height: usize,
+
+screen: *Screen,
+
+
+
+
+pub fn initChild(
+ self: Window,
+ x_off: usize,
+ y_off: usize,
+ width: Size,
+ height: Size,
+) Window {
+ const resolved_width = switch (width) {
+ .expand => self.width - x_off,
+ .limit => |w| blk: {
+ if (w + x_off > self.width) {
+ break :blk self.width - x_off;
+ }
+ break :blk w;
+ },
+ };
+ const resolved_height = switch (height) {
+ .expand => self.height - y_off,
+ .limit => |h| blk: {
+ if (h + y_off > self.height) {
+ break :blk self.height - y_off;
+ }
+ break :blk h;
+ },
+ };
+ return Window{
+ .x_off = x_off + self.x_off,
+ .y_off = y_off + self.y_off,
+ .width = resolved_width,
+ .height = resolved_height,
+ .screen = self.screen,
+ };
+}
+
+
+pub fn writeCell(self: Window, col: usize, row: usize, cell: Cell) void {
+ if (self.height == 0 or self.width == 0) return;
+ if (self.height <= row or self.width <= col) return;
+ self.screen.writeCell(col + self.x_off, row + self.y_off, cell);
+}
+
+
+pub fn clear(self: Window) void {
+ self.fill(.{});
+}
+
+
+pub fn gwidth(self: Window, str: []const u8) usize {
+ const m: gw.Method = if (self.screen.unicode) .unicode else .wcwidth;
+ return gw.gwidth(str, m) catch 1;
+}
+
+
+pub fn fill(self: Window, cell: Cell) void {
+ var row: usize = self.y_off;
+ while (row < (self.height + self.y_off)) : (row += 1) {
+ var col: usize = self.x_off;
+ while (col < (self.width + self.x_off)) : (col += 1) {
+ self.screen.writeCell(col, row, cell);
+ }
+ }
+}
+
+
+pub fn hideCursor(self: Window) void {
+ self.screen.cursor_vis = false;
+}
+
+
+pub fn showCursor(self: Window, col: usize, row: usize) void {
+ if (self.height == 0 or self.width == 0) return;
+ if (self.height <= row or self.width <= col) return;
+ self.screen.cursor_vis = true;
+ self.screen.cursor_row = row + self.y_off;
+ self.screen.cursor_col = col + self.x_off;
+}
+
+
+pub fn wrap(self: Window, segments: []Segment) !void {
+
+
+ var row: usize = 0;
+ var col: usize = 0;
+ var wrapped: bool = false;
+ for (segments) |segment| {
+ var word_iter = try WordIterator.init(segment.text);
+ while (word_iter.next()) |word| {
+
+
+ if (word.bytes[0] == '\r' or word.bytes[0] == '\n') {
+ row += 1;
+ col = 0;
+ wrapped = false;
+ continue;
+ }
+
+
+
+
+ const word_width = self.gwidth(word.bytes);
+ if (word_width + col >= self.width and word_width < self.width) {
+ row += 1;
+ col = 0;
+ wrapped = true;
+ }
+
+
+
+
+ if (col == 0 and std.mem.eql(u8, word.bytes, " ") and wrapped) continue;
+ var iter = GraphemeIterator.init(word.bytes);
+ while (iter.next()) |grapheme| {
+ if (col >= self.width) {
+ row += 1;
+ col = 0;
+ wrapped = true;
+ }
+ const s = grapheme.slice(word.bytes);
+ const w = self.gwidth(s);
+ self.writeCell(col, row, .{
+ .char = .{
+ .grapheme = s,
+ .width = w,
+ },
+ .style = segment.style,
+ .link = segment.link,
+ });
+ col += w;
+ }
+ }
+ }
+}
+
+test "Window size set" {
+ var parent = Window{
+ .x_off = 0,
+ .y_off = 0,
+ .width = 20,
+ .height = 20,
+ .screen = undefined,
+ };
+
+ const child = parent.initChild(1, 1, .expand, .expand);
+ try std.testing.expectEqual(19, child.width);
+ try std.testing.expectEqual(19, child.height);
+}
+
+test "Window size set too big" {
+ var parent = Window{
+ .x_off = 0,
+ .y_off = 0,
+ .width = 20,
+ .height = 20,
+ .screen = undefined,
+ };
+
+ const child = parent.initChild(0, 0, .{ .limit = 21 }, .{ .limit = 21 });
+ try std.testing.expectEqual(20, child.width);
+ try std.testing.expectEqual(20, child.height);
+}
+
+test "Window size set too big with offset" {
+ var parent = Window{
+ .x_off = 0,
+ .y_off = 0,
+ .width = 20,
+ .height = 20,
+ .screen = undefined,
+ };
+
+ const child = parent.initChild(10, 10, .{ .limit = 21 }, .{ .limit = 21 });
+ try std.testing.expectEqual(10, child.width);
+ try std.testing.expectEqual(10, child.height);
+}
+
+test "Window size nested offsets" {
+ var parent = Window{
+ .x_off = 1,
+ .y_off = 1,
+ .width = 20,
+ .height = 20,
+ .screen = undefined,
+ };
+
+ const child = parent.initChild(10, 10, .{ .limit = 21 }, .{ .limit = 21 });
+ try std.testing.expectEqual(11, child.x_off);
+ try std.testing.expectEqual(11, child.y_off);
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/ctlseqs.zig.html b/docs/src/main/ctlseqs.zig.html
new file mode 100644
index 0000000..dd6c6a7
--- /dev/null
+++ b/docs/src/main/ctlseqs.zig.html
@@ -0,0 +1,228 @@
+
+
+
+
+
ctlseqs.zig - source view
+
+
+
+
+
+
+
+pub const primary_device_attrs = "\x1b[c";
+pub const tertiary_device_attrs = "\x1b[=c";
+pub const xtversion = "\x1b[>0q";
+pub const decrqm_focus = "\x1b[?1004$p";
+pub const decrqm_sync = "\x1b[?2026$p";
+pub const decrqm_unicode = "\x1b[?2027$p";
+pub const decrqm_color_theme = "\x1b[?2031$p";
+pub const csi_u_query = "\x1b[?u";
+pub const kitty_graphics_query = "\x1b_Gi=1,a=q\x1b\\";
+pub const sixel_geometry_query = "\x1b[?2;1;0S";
+
+
+
+pub const mouse_set = "\x1b[?1003;1004;1006h";
+pub const mouse_reset = "\x1b[?1003;1004;1006l";
+
+
+
+pub const sync_set = "\x1b[?2026h";
+pub const sync_reset = "\x1b[?2026l";
+
+
+
+pub const unicode_set = "\x1b[?2027h";
+pub const unicode_reset = "\x1b[?2027l";
+
+
+
+pub const bp_set = "\x1b[?2004h";
+pub const bp_reset = "\x1b[?2004l";
+
+
+
+pub const csi_u_push = "\x1b[>{d}u";
+pub const csi_u_pop = "\x1b[<u";
+
+
+
+pub const home = "\x1b[H";
+pub const cup = "\x1b[{d};{d}H";
+pub const hide_cursor = "\x1b[?25l";
+pub const show_cursor = "\x1b[?25h";
+
+
+
+pub const smcup = "\x1b[?1049h";
+pub const rmcup = "\x1b[?1049l";
+
+
+
+pub const sgr_reset = "\x1b[m";
+
+
+
+pub const fg_base = "\x1b[3{d}m";
+pub const fg_bright = "\x1b[9{d}m";
+pub const bg_base = "\x1b[4{d}m";
+pub const bg_bright = "\x1b[10{d}m";
+
+pub const fg_reset = "\x1b[39m";
+pub const bg_reset = "\x1b[49m";
+pub const ul_reset = "\x1b[59m";
+pub const fg_indexed = "\x1b[38:5:{d}m";
+pub const bg_indexed = "\x1b[48:5:{d}m";
+pub const ul_indexed = "\x1b[58:5:{d}m";
+pub const fg_rgb = "\x1b[38:2:{d}:{d}:{d}m";
+pub const bg_rgb = "\x1b[48:2:{d}:{d}:{d}m";
+pub const ul_rgb = "\x1b[58:2:{d}:{d}:{d}m";
+
+
+
+pub const ul_off = "\x1b[24m";
+
+pub const ul_single = "\x1b[4m";
+pub const ul_double = "\x1b[4:2m";
+pub const ul_curly = "\x1b[4:3m";
+pub const ul_dotted = "\x1b[4:4m";
+pub const ul_dashed = "\x1b[4:5m";
+
+
+
+pub const bold_set = "\x1b[1m";
+pub const dim_set = "\x1b[2m";
+pub const italic_set = "\x1b[3m";
+pub const blink_set = "\x1b[5m";
+pub const reverse_set = "\x1b[7m";
+pub const invisible_set = "\x1b[8m";
+pub const strikethrough_set = "\x1b[9m";
+pub const bold_dim_reset = "\x1b[22m";
+pub const italic_reset = "\x1b[23m";
+pub const blink_reset = "\x1b[25m";
+pub const reverse_reset = "\x1b[27m";
+pub const invisible_reset = "\x1b[28m";
+pub const strikethrough_reset = "\x1b[29m";
+
+
+
+pub const osc2_set_title = "\x1b]2;{s}\x1b\\";
+pub const osc8 = "\x1b]8;{s};{s}\x1b\\";
+pub const osc8_clear = "\x1b]8;;\x1b\\";
+pub const osc9_notify = "\x1b]9;{s}\x1b\\";
+pub const osc777_notify = "\x1b]777;notify;{s};{s}\x1b\\";
+pub const osc22_mouse_shape = "\x1b]22;{s}\x1b\\";
+
+
+
+pub const kitty_graphics_clear = "\x1b_Ga=d\x1b\\";
+pub const kitty_graphics_place = "\x1b_Ga=p,i={d},z={d},C=1\x1b\\";
+pub const kitty_graphics_scale = "\x1b_Ga=p,i={d},z={d},c={d},r={d},C=1\x1b\\";
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/event.zig.html b/docs/src/main/event.zig.html
new file mode 100644
index 0000000..85330a0
--- /dev/null
+++ b/docs/src/main/event.zig.html
@@ -0,0 +1,137 @@
+
+
+
+
+
event.zig - source view
+
+
+
+
+
+
pub const Key = @import("Key.zig");
+pub const Mouse = @import("Mouse.zig");
+
+
+pub const Event = union(enum) {
+ key_press: Key,
+ mouse: Mouse,
+ focus_in,
+ focus_out,
+ paste_start,
+ paste_end,
+
+
+
+ cap_kitty_keyboard,
+ cap_kitty_graphics,
+ cap_rgb,
+ cap_unicode,
+ cap_da1,
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/gwidth.zig.html b/docs/src/main/gwidth.zig.html
new file mode 100644
index 0000000..00d5c89
--- /dev/null
+++ b/docs/src/main/gwidth.zig.html
@@ -0,0 +1,185 @@
+
+
+
+
+
gwidth.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const unicode = std.unicode;
+const testing = std.testing;
+const ziglyph = @import("ziglyph");
+
+
+pub const Method = enum {
+ unicode,
+ wcwidth,
+ no_zwj,
+};
+
+
+pub fn gwidth(str: []const u8, method: Method) !usize {
+ switch (method) {
+ .unicode => {
+ return try ziglyph.display_width.strWidth(str, .half);
+ },
+ .wcwidth => {
+ var total: usize = 0;
+ const utf8 = try unicode.Utf8View.init(str);
+ var iter = utf8.iterator();
+
+ while (iter.nextCodepoint()) |cp| {
+ const w = ziglyph.display_width.codePointWidth(cp, .half);
+ if (w < 0) continue;
+ total += @intCast(w);
+ }
+ return total;
+ },
+ .no_zwj => {
+ var out: [256]u8 = undefined;
+ if (str.len > out.len) return error.OutOfMemory;
+ const n = std.mem.replace(u8, str, "\u{200D}", "", &out);
+ return gwidth(out[0..n], .unicode);
+ },
+ }
+}
+
+test "gwidth: a" {
+ try testing.expectEqual(1, try gwidth("a", .unicode));
+ try testing.expectEqual(1, try gwidth("a", .wcwidth));
+ try testing.expectEqual(1, try gwidth("a", .no_zwj));
+}
+
+test "gwidth: emoji with ZWJ" {
+ try testing.expectEqual(2, try gwidth("👩🚀", .unicode));
+ try testing.expectEqual(4, try gwidth("👩🚀", .wcwidth));
+ try testing.expectEqual(4, try gwidth("👩🚀", .no_zwj));
+}
+
+test "gwidth: emoji with VS16 selector" {
+ try testing.expectEqual(2, try gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .unicode));
+ try testing.expectEqual(1, try gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .wcwidth));
+ try testing.expectEqual(2, try gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .no_zwj));
+}
+
+test "gwidth: emoji with skin tone selector" {
+ try testing.expectEqual(2, try gwidth("👋🏿", .unicode));
+ try testing.expectEqual(4, try gwidth("👋🏿", .wcwidth));
+ try testing.expectEqual(2, try gwidth("👋🏿", .no_zwj));
+}
+
+test "gwidth: invalid string" {
+ try testing.expectError(error.InvalidUtf8, gwidth("\xc3\x28", .unicode));
+ try testing.expectError(error.InvalidUtf8, gwidth("\xc3\x28", .wcwidth));
+ try testing.expectError(error.InvalidUtf8, gwidth("\xc3\x28", .no_zwj));
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/main.zig.html b/docs/src/main/main.zig.html
new file mode 100644
index 0000000..2b6ac59
--- /dev/null
+++ b/docs/src/main/main.zig.html
@@ -0,0 +1,139 @@
+
+
+
+
+
main.zig - source view
+
+
+
+
+
+
const std = @import("std");
+
+pub const Vaxis = @import("vaxis.zig").Vaxis;
+pub const Options = @import("Options.zig");
+
+pub const Key = @import("Key.zig");
+pub const Cell = @import("Cell.zig");
+pub const Style = Cell.Style;
+pub const Image = @import("Image.zig");
+pub const Mouse = @import("Mouse.zig");
+pub const Winsize = @import("Tty.zig").Winsize;
+
+pub const widgets = @import("widgets.zig");
+
+
+pub fn init(comptime Event: type, opts: Options) !Vaxis(Event) {
+ return Vaxis(Event).init(opts);
+}
+
+test {
+ std.testing.refAllDecls(@This());
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/queue.zig.html b/docs/src/main/queue.zig.html
new file mode 100644
index 0000000..a573f8c
--- /dev/null
+++ b/docs/src/main/queue.zig.html
@@ -0,0 +1,244 @@
+
+
+
+
+
queue.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const assert = std.debug.assert;
+const atomic = std.atomic;
+const Futex = std.Thread.Futex;
+
+const log = std.log.scoped(.queue);
+
+
+pub fn Queue(
+ comptime T: type,
+ comptime size: usize,
+) type {
+ return struct {
+ buf: [size]T = undefined,
+
+ read_index: usize = 0,
+ write_index: usize = 0,
+
+ mutex: std.Thread.Mutex = .{},
+
+
+ futex: atomic.Value(u32) = atomic.Value(u32).init(0),
+
+ const Self = @This();
+
+
+ pub fn pop(self: *Self) T {
+ self.mutex.lock();
+ defer self.mutex.unlock();
+ if (self.isEmpty()) {
+
+
+ self.mutex.unlock();
+ Futex.wait(&self.futex, 0);
+
+
+ self.mutex.lock();
+ }
+ if (self.isFull()) {
+
+
+ Futex.wake(&self.futex, 1);
+ }
+ const i = self.read_index;
+ self.read_index += 1;
+ self.read_index = self.read_index % self.buf.len;
+ return self.buf[i];
+ }
+
+
+
+ pub fn push(self: *Self, item: T) void {
+ self.mutex.lock();
+ defer self.mutex.unlock();
+ if (self.isFull()) {
+ self.mutex.unlock();
+ Futex.wait(&self.futex, 0);
+ self.mutex.lock();
+ }
+ if (self.isEmpty()) {
+ Futex.wake(&self.futex, 1);
+ }
+ const i = self.write_index;
+ self.write_index += 1;
+ self.write_index = self.write_index % self.buf.len;
+ self.buf[i] = item;
+ }
+
+
+
+ pub fn tryPush(self: *Self, item: T) bool {
+ self.mutex.lock();
+ if (self.isFull()) {
+ self.mutex.unlock();
+ return false;
+ }
+ self.mutex.unlock();
+ self.push(item);
+ return true;
+ }
+
+
+ pub fn tryPop(self: *Self) ?T {
+ self.mutex.lock();
+ if (self.isEmpty()) {
+ self.mutex.unlock();
+ return null;
+ }
+ self.mutex.unlock();
+ return self.pop();
+ }
+
+
+ fn isEmpty(self: Self) bool {
+ return self.write_index == self.read_index;
+ }
+
+
+ fn isFull(self: Self) bool {
+ return self.mask2(self.write_index + self.buf.len) == self.read_index;
+ }
+
+
+ fn len(self: Self) usize {
+ const wrap_offset = 2 * self.buf.len * @intFromBool(self.write_index < self.read_index);
+ const adjusted_write_index = self.write_index + wrap_offset;
+ return adjusted_write_index - self.read_index;
+ }
+
+
+ fn mask(self: Self, index: usize) usize {
+ return index % self.buf.len;
+ }
+
+
+ fn mask2(self: Self, index: usize) usize {
+ return index % (2 * self.buf.len);
+ }
+ };
+}
+
+test "Queue: simple push / pop" {
+ var queue: Queue(u8, 16) = .{};
+ queue.push(1);
+ const pop = queue.pop();
+ try std.testing.expectEqual(1, pop);
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/vaxis.zig.html b/docs/src/main/vaxis.zig.html
new file mode 100644
index 0000000..27f3d44
--- /dev/null
+++ b/docs/src/main/vaxis.zig.html
@@ -0,0 +1,851 @@
+
+
+
+
+
vaxis.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const atomic = std.atomic;
+const base64 = std.base64.standard.Encoder;
+
+const Queue = @import("queue.zig").Queue;
+const ctlseqs = @import("ctlseqs.zig");
+const Tty = @import("Tty.zig");
+const Winsize = Tty.Winsize;
+const Key = @import("Key.zig");
+const Screen = @import("Screen.zig");
+const InternalScreen = @import("InternalScreen.zig");
+const Window = @import("Window.zig");
+const Options = @import("Options.zig");
+const Style = @import("Cell.zig").Style;
+const Hyperlink = @import("Cell.zig").Hyperlink;
+const gwidth = @import("gwidth.zig");
+const Shape = @import("Mouse.zig").Shape;
+const Image = @import("Image.zig");
+const zigimg = @import("zigimg");
+
+
+
+
+
+
+
+
+
+
+
+pub fn Vaxis(comptime T: type) type {
+ return struct {
+ const Self = @This();
+
+ const log = std.log.scoped(.vaxis);
+
+ pub const Event = T;
+
+ pub const Capabilities = struct {
+ kitty_keyboard: bool = false,
+ kitty_graphics: bool = false,
+ rgb: bool = false,
+ unicode: bool = false,
+ };
+
+
+
+
+
+
+ queue: Queue(T, 512),
+
+ tty: ?Tty,
+
+
+ screen: Screen,
+
+
+ screen_last: InternalScreen = undefined,
+
+ state: struct {
+
+ alt_screen: bool = false,
+
+ kitty_keyboard: bool = false,
+ bracketed_paste: bool = false,
+ mouse: bool = false,
+ } = .{},
+
+ caps: Capabilities = .{},
+
+
+ refresh: bool = false,
+
+
+
+ query_futex: atomic.Value(u32) = atomic.Value(u32).init(0),
+
+
+
+ next_img_id: u32 = 1,
+
+
+
+ renders: usize = 0,
+ render_dur: i128 = 0,
+
+
+ pub fn init(_: Options) !Self {
+ return .{
+ .queue = .{},
+ .tty = null,
+ .screen = .{},
+ .screen_last = .{},
+ };
+ }
+
+
+
+
+
+ pub fn deinit(self: *Self, alloc: ?std.mem.Allocator) void {
+ if (self.tty) |_| {
+ var tty = &self.tty.?;
+ if (self.state.kitty_keyboard) {
+ _ = tty.write(ctlseqs.csi_u_pop) catch {};
+ }
+ if (self.state.mouse) {
+ _ = tty.write(ctlseqs.mouse_reset) catch {};
+ }
+ if (self.state.bracketed_paste) {
+ _ = tty.write(ctlseqs.bp_reset) catch {};
+ }
+ if (self.state.alt_screen) {
+ _ = tty.write(ctlseqs.rmcup) catch {};
+ }
+ tty.flush() catch {};
+ tty.deinit();
+ }
+ if (alloc) |a| {
+ self.screen.deinit(a);
+ self.screen_last.deinit(a);
+ }
+ if (self.renders > 0) {
+ const tpr = @divTrunc(self.render_dur, self.renders);
+ log.info("total renders = {d}", .{self.renders});
+ log.info("microseconds per render = {d}", .{tpr});
+ }
+ }
+
+
+ pub fn startReadThread(self: *Self) !void {
+ self.tty = try Tty.init();
+
+
+ const read_thread = try std.Thread.spawn(.{}, Tty.run, .{ &self.tty.?, T, self });
+ try read_thread.setName("tty");
+ }
+
+
+ pub fn stopReadThread(self: *Self) void {
+ if (self.tty) |_| {
+ var tty = &self.tty.?;
+ tty.stop();
+ }
+ }
+
+
+ pub fn nextEvent(self: *Self) T {
+ return self.queue.pop();
+ }
+
+
+
+ pub fn postEvent(self: *Self, event: T) void {
+ self.queue.push(event);
+ }
+
+
+
+
+ pub fn resize(self: *Self, alloc: std.mem.Allocator, winsize: Winsize) !void {
+ log.debug("resizing screen: width={d} height={d}", .{ winsize.cols, winsize.rows });
+ self.screen.deinit(alloc);
+ self.screen = try Screen.init(alloc, winsize);
+ self.screen.unicode = self.caps.unicode;
+
+
+
+
+
+
+ self.screen_last.deinit(alloc);
+ self.screen_last = try InternalScreen.init(alloc, winsize.cols, winsize.rows);
+
+
+ }
+
+
+ pub fn window(self: *Self) Window {
+ return .{
+ .x_off = 0,
+ .y_off = 0,
+ .width = self.screen.width,
+ .height = self.screen.height,
+ .screen = &self.screen,
+ };
+ }
+
+
+
+ pub fn enterAltScreen(self: *Self) !void {
+ if (self.state.alt_screen) return;
+ var tty = self.tty orelse return;
+ _ = try tty.write(ctlseqs.smcup);
+ try tty.flush();
+ self.state.alt_screen = true;
+ }
+
+
+ pub fn exitAltScreen(self: *Self) !void {
+ if (!self.state.alt_screen) return;
+ var tty = self.tty orelse return;
+ _ = try tty.write(ctlseqs.rmcup);
+ try tty.flush();
+ self.state.alt_screen = false;
+ }
+
+
+
+
+ pub fn queryTerminal(self: *Self) !void {
+ var tty = self.tty orelse return;
+
+ const colorterm = std.os.getenv("COLORTERM") orelse "";
+ if (std.mem.eql(u8, colorterm, "truecolor") or
+ std.mem.eql(u8, colorterm, "24bit"))
+ {
+ if (@hasField(Event, "cap_rgb")) {
+ self.postEvent(.cap_rgb);
+ }
+ }
+
+
+
+
+
+
+
+
+
+ _ = try tty.write(ctlseqs.decrqm_unicode);
+ _ = try tty.write(ctlseqs.decrqm_color_theme);
+
+
+
+
+
+
+ _ = try tty.write(ctlseqs.csi_u_query);
+ _ = try tty.write(ctlseqs.kitty_graphics_query);
+
+
+
+
+
+
+
+
+ _ = try tty.write(ctlseqs.primary_device_attrs);
+ try tty.flush();
+
+
+
+ std.Thread.Futex.timedWait(&self.query_futex, 0, 1 * std.time.ns_per_s) catch {};
+
+
+
+ if (self.caps.kitty_keyboard) {
+ try self.enableKittyKeyboard(.{});
+ }
+ if (self.caps.unicode) {
+ _ = try tty.write(ctlseqs.unicode_set);
+ }
+ }
+
+
+
+ pub fn queueRefresh(self: *Self) void {
+ self.refresh = true;
+ }
+
+
+ pub fn render(self: *Self) !void {
+ var tty = self.tty orelse return;
+ self.renders += 1;
+ const timer_start = std.time.microTimestamp();
+ defer {
+ self.render_dur += std.time.microTimestamp() - timer_start;
+ }
+
+ defer self.refresh = false;
+ defer tty.flush() catch {};
+
+
+
+
+
+
+
+
+
+ _ = try tty.write(ctlseqs.sync_set);
+ defer _ = tty.write(ctlseqs.sync_reset) catch {};
+
+
+
+
+
+
+
+
+
+ _ = try tty.write(ctlseqs.hide_cursor);
+ _ = try tty.write(ctlseqs.home);
+ _ = try tty.write(ctlseqs.sgr_reset);
+
+
+
+ var reposition: bool = false;
+ var row: usize = 0;
+ var col: usize = 0;
+ var cursor: Style = .{};
+ var link: Hyperlink = .{};
+
+
+
+ _ = try tty.write(ctlseqs.kitty_graphics_clear);
+
+ var i: usize = 0;
+ while (i < self.screen.buf.len) {
+ const cell = self.screen.buf[i];
+ defer {
+
+
+ const w = blk: {
+ if (cell.char.width != 0) break :blk cell.char.width;
+
+ const method: gwidth.Method = if (self.caps.unicode) .unicode else .wcwidth;
+ break :blk gwidth.gwidth(cell.char.grapheme, method) catch 1;
+ };
+ var j = i + 1;
+ while (j < i + w) : (j += 1) {
+ self.screen_last.buf[j].skipped = true;
+ }
+ col += w;
+ i += w;
+ }
+ if (col >= self.screen.width) {
+ row += 1;
+ col = 0;
+ }
+
+
+
+
+ const last = self.screen_last.buf[i];
+ if (!self.refresh and last.eql(cell) and !last.skipped and cell.image == null) {
+ reposition = true;
+
+
+
+
+ if (link.uri.len > 0) {
+ _ = try tty.write(ctlseqs.osc8_clear);
+ }
+ continue;
+ }
+ self.screen_last.buf[i].skipped = false;
+ defer {
+ cursor = cell.style;
+ link = cell.link;
+ }
+
+
+ self.screen_last.writeCell(col, row, cell);
+
+
+
+ if (reposition) {
+ try std.fmt.format(tty.buffered_writer.writer(), ctlseqs.cup, .{ row + 1, col + 1 });
+ }
+
+ if (cell.image) |img| {
+ if (img.size) |size| {
+ try std.fmt.format(
+ tty.buffered_writer.writer(),
+ ctlseqs.kitty_graphics_scale,
+ .{ img.img_id, img.z_index, size.cols, size.rows },
+ );
+ } else {
+ try std.fmt.format(
+ tty.buffered_writer.writer(),
+ ctlseqs.kitty_graphics_place,
+ .{ img.img_id, img.z_index },
+ );
+ }
+ }
+
+
+
+
+
+
+
+
+ if (!std.meta.eql(cursor.fg, cell.style.fg)) {
+ const writer = tty.buffered_writer.writer();
+ switch (cell.style.fg) {
+ .default => _ = try tty.write(ctlseqs.fg_reset),
+ .index => |idx| {
+ switch (idx) {
+ 0...7 => try std.fmt.format(writer, ctlseqs.fg_base, .{idx}),
+ 8...15 => try std.fmt.format(writer, ctlseqs.fg_bright, .{idx - 8}),
+ else => try std.fmt.format(writer, ctlseqs.fg_indexed, .{idx}),
+ }
+ },
+ .rgb => |rgb| {
+ try std.fmt.format(writer, ctlseqs.fg_rgb, .{ rgb[0], rgb[1], rgb[2] });
+ },
+ }
+ }
+
+
+ if (!std.meta.eql(cursor.bg, cell.style.bg)) {
+ const writer = tty.buffered_writer.writer();
+ switch (cell.style.bg) {
+ .default => _ = try tty.write(ctlseqs.bg_reset),
+ .index => |idx| {
+ switch (idx) {
+ 0...7 => try std.fmt.format(writer, ctlseqs.bg_base, .{idx}),
+ 8...15 => try std.fmt.format(writer, ctlseqs.bg_bright, .{idx - 8}),
+ else => try std.fmt.format(writer, ctlseqs.bg_indexed, .{idx}),
+ }
+ },
+ .rgb => |rgb| {
+ try std.fmt.format(writer, ctlseqs.bg_rgb, .{ rgb[0], rgb[1], rgb[2] });
+ },
+ }
+ }
+
+
+ if (!std.meta.eql(cursor.ul, cell.style.ul)) {
+ const writer = tty.buffered_writer.writer();
+ switch (cell.style.bg) {
+ .default => _ = try tty.write(ctlseqs.ul_reset),
+ .index => |idx| {
+ try std.fmt.format(writer, ctlseqs.ul_indexed, .{idx});
+ },
+ .rgb => |rgb| {
+ try std.fmt.format(writer, ctlseqs.ul_rgb, .{ rgb[0], rgb[1], rgb[2] });
+ },
+ }
+ }
+
+
+ if (!std.meta.eql(cursor.ul_style, cell.style.ul_style)) {
+ const seq = switch (cell.style.ul_style) {
+ .off => ctlseqs.ul_off,
+ .single => ctlseqs.ul_single,
+ .double => ctlseqs.ul_double,
+ .curly => ctlseqs.ul_curly,
+ .dotted => ctlseqs.ul_dotted,
+ .dashed => ctlseqs.ul_dashed,
+ };
+ _ = try tty.write(seq);
+ }
+
+
+ if (cursor.bold != cell.style.bold) {
+ const seq = switch (cell.style.bold) {
+ true => ctlseqs.bold_set,
+ false => ctlseqs.bold_dim_reset,
+ };
+ _ = try tty.write(seq);
+ if (cell.style.dim) {
+ _ = try tty.write(ctlseqs.dim_set);
+ }
+ }
+
+
+ if (cursor.dim != cell.style.dim) {
+ const seq = switch (cell.style.dim) {
+ true => ctlseqs.dim_set,
+ false => ctlseqs.bold_dim_reset,
+ };
+ _ = try tty.write(seq);
+ if (cell.style.bold) {
+ _ = try tty.write(ctlseqs.bold_set);
+ }
+ }
+
+
+ if (cursor.italic != cell.style.italic) {
+ const seq = switch (cell.style.italic) {
+ true => ctlseqs.italic_set,
+ false => ctlseqs.italic_reset,
+ };
+ _ = try tty.write(seq);
+ }
+
+
+ if (cursor.blink != cell.style.blink) {
+ const seq = switch (cell.style.blink) {
+ true => ctlseqs.blink_set,
+ false => ctlseqs.blink_reset,
+ };
+ _ = try tty.write(seq);
+ }
+
+
+ if (cursor.reverse != cell.style.reverse) {
+ const seq = switch (cell.style.reverse) {
+ true => ctlseqs.reverse_set,
+ false => ctlseqs.reverse_reset,
+ };
+ _ = try tty.write(seq);
+ }
+
+
+ if (cursor.invisible != cell.style.invisible) {
+ const seq = switch (cell.style.invisible) {
+ true => ctlseqs.invisible_set,
+ false => ctlseqs.invisible_reset,
+ };
+ _ = try tty.write(seq);
+ }
+
+
+ if (cursor.strikethrough != cell.style.strikethrough) {
+ const seq = switch (cell.style.strikethrough) {
+ true => ctlseqs.strikethrough_set,
+ false => ctlseqs.strikethrough_reset,
+ };
+ _ = try tty.write(seq);
+ }
+
+
+
+ if (!std.meta.eql(link.uri, cell.link.uri)) {
+ var ps = cell.link.params;
+ if (cell.link.uri.len == 0) {
+
+
+
+
+ ps = "";
+ }
+ const writer = tty.buffered_writer.writer();
+ try std.fmt.format(writer, ctlseqs.osc8, .{ ps, cell.link.uri });
+ }
+ _ = try tty.write(cell.char.grapheme);
+ }
+ if (self.screen.cursor_vis) {
+ try std.fmt.format(
+ tty.buffered_writer.writer(),
+ ctlseqs.cup,
+ .{
+ self.screen.cursor_row + 1,
+ self.screen.cursor_col + 1,
+ },
+ );
+ _ = try tty.write(ctlseqs.show_cursor);
+ }
+ if (self.screen.mouse_shape != self.screen_last.mouse_shape) {
+ try std.fmt.format(
+ tty.buffered_writer.writer(),
+ ctlseqs.osc22_mouse_shape,
+ .{@tagName(self.screen.mouse_shape)},
+ );
+ }
+ }
+
+ fn enableKittyKeyboard(self: *Self, flags: Key.KittyFlags) !void {
+ self.state.kitty_keyboard = true;
+ const flag_int: u5 = @bitCast(flags);
+ try std.fmt.format(
+ self.tty.?.buffered_writer.writer(),
+ ctlseqs.csi_u_push,
+ .{
+ flag_int,
+ },
+ );
+ try self.tty.?.flush();
+ }
+
+
+ pub fn notify(self: *Self, title: ?[]const u8, body: []const u8) !void {
+ if (self.tty == null) return;
+ if (title) |t| {
+ try std.fmt.format(
+ self.tty.?.buffered_writer.writer(),
+ ctlseqs.osc777_notify,
+ .{ t, body },
+ );
+ } else {
+ try std.fmt.format(
+ self.tty.?.buffered_writer.writer(),
+ ctlseqs.osc9_notify,
+ .{body},
+ );
+ }
+ try self.tty.?.flush();
+ }
+
+
+ pub fn setTitle(self: *Self, title: []const u8) !void {
+ if (self.tty == null) return;
+ try std.fmt.format(
+ self.tty.?.buffered_writer.writer(),
+ ctlseqs.osc2_set_title,
+ .{title},
+ );
+ try self.tty.?.flush();
+ }
+
+
+
+
+
+
+
+ pub fn setBracketedPaste(self: *Self, enable: bool) !void {
+ if (self.tty == null) return;
+ self.state.bracketed_paste = enable;
+ const seq = if (enable) {
+ self.state.bracketed_paste = true;
+ ctlseqs.bp_set;
+ } else {
+ self.state.bracketed_paste = true;
+ ctlseqs.bp_reset;
+ };
+ _ = try self.tty.?.write(seq);
+ try self.tty.?.flush();
+ }
+
+
+ pub fn setMouseShape(self: *Self, shape: Shape) void {
+ self.screen.mouse_shape = shape;
+ }
+
+
+ pub fn setMouseMode(self: *Self, enable: bool) !void {
+ var tty = self.tty orelse return;
+ self.state.mouse = enable;
+ if (enable) {
+ _ = try tty.write(ctlseqs.mouse_set);
+ try tty.flush();
+ } else {
+ _ = try tty.write(ctlseqs.mouse_reset);
+ try tty.flush();
+ }
+ }
+
+ pub fn loadImage(
+ self: *Self,
+ alloc: std.mem.Allocator,
+ src: Image.Source,
+ ) !Image {
+ if (!self.caps.kitty_graphics) return error.NoGraphicsCapability;
+ var tty = self.tty orelse return error.NoTTY;
+ defer self.next_img_id += 1;
+
+ const writer = tty.buffered_writer.writer();
+
+ var img = switch (src) {
+ .path => |path| try zigimg.Image.fromFilePath(alloc, path),
+ .mem => |bytes| try zigimg.Image.fromMemory(alloc, bytes),
+ };
+ defer img.deinit();
+ const png_buf = try alloc.alloc(u8, img.imageByteSize());
+ defer alloc.free(png_buf);
+ const png = try img.writeToMemory(png_buf, .{ .png = .{} });
+ const b64_buf = try alloc.alloc(u8, base64.calcSize(png.len));
+ const encoded = base64.encode(b64_buf, png);
+ defer alloc.free(b64_buf);
+
+ const id = self.next_img_id;
+
+ log.debug("transmitting kitty image: id={d}, len={d}", .{ id, encoded.len });
+
+ if (encoded.len < 4096) {
+ try std.fmt.format(
+ writer,
+ "\x1b_Gf=100,i={d};{s}\x1b\\",
+ .{
+ id,
+ encoded,
+ },
+ );
+ } else {
+ var n: usize = 4096;
+
+ try std.fmt.format(
+ writer,
+ "\x1b_Gf=100,i={d},m=1;{s}\x1b\\",
+ .{ id, encoded[0..n] },
+ );
+ while (n < encoded.len) : (n += 4096) {
+ const end: usize = @min(n + 4096, encoded.len);
+ const m: u2 = if (end == encoded.len) 0 else 1;
+ try std.fmt.format(
+ writer,
+ "\x1b_Gm={d};{s}\x1b\\",
+ .{
+ m,
+ encoded[n..end],
+ },
+ );
+ }
+ }
+ try tty.buffered_writer.flush();
+ return .{
+ .id = id,
+ .width = img.width,
+ .height = img.height,
+ };
+ }
+
+
+ pub fn freeImage(self: Self, id: u32) void {
+ var tty = self.tty orelse return;
+ const writer = tty.buffered_writer.writer();
+ std.fmt.format(writer, "\x1b_Ga=d,d=I,i={d};\x1b\\", .{id}) catch |err| {
+ log.err("couldn't delete image {d}: {}", .{ id, err });
+ return;
+ };
+ tty.buffered_writer.flush() catch |err| {
+ log.err("couldn't flush writer: {}", .{err});
+ };
+ }
+ };
+}
+
+test "Vaxis: event queueing" {
+ const Event = union(enum) {
+ key,
+ };
+ var vx: Vaxis(Event) = try Vaxis(Event).init(.{});
+ defer vx.deinit(null);
+ vx.postEvent(.key);
+ const event = vx.nextEvent();
+ try std.testing.expect(event == .key);
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/widgets.zig.html b/docs/src/main/widgets.zig.html
new file mode 100644
index 0000000..0b6ef81
--- /dev/null
+++ b/docs/src/main/widgets.zig.html
@@ -0,0 +1,120 @@
+
+
+
+
+
widgets.zig - source view
+
+
+
+
+
+
pub const border = @import("widgets/border.zig");
+pub const alignment = @import("widgets/alignment.zig");
+pub const TextInput = @import("widgets/TextInput.zig");
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/widgets/TextInput.zig.html b/docs/src/main/widgets/TextInput.zig.html
new file mode 100644
index 0000000..b214b1d
--- /dev/null
+++ b/docs/src/main/widgets/TextInput.zig.html
@@ -0,0 +1,260 @@
+
+
+
+
+
widgets/TextInput.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const Key = @import("../Key.zig");
+const Cell = @import("../Cell.zig");
+const Window = @import("../Window.zig");
+const GraphemeIterator = @import("ziglyph").GraphemeIterator;
+
+const log = std.log.scoped(.text_input);
+
+const TextInput = @This();
+
+
+const Event = union(enum) {
+ key_press: Key,
+};
+
+
+
+cursor_idx: usize = 0,
+grapheme_count: usize = 0,
+
+
+
+
+
+
+
+buf: std.ArrayList(u8),
+
+pub fn init(alloc: std.mem.Allocator) TextInput {
+ return TextInput{
+ .buf = std.ArrayList(u8).init(alloc),
+ };
+}
+
+pub fn deinit(self: *TextInput) void {
+ self.buf.deinit();
+}
+
+pub fn update(self: *TextInput, event: Event) !void {
+ switch (event) {
+ .key_press => |key| {
+ if (key.matches(Key.backspace, .{})) {
+ if (self.cursor_idx == 0) return;
+ self.deleteBeforeCursor();
+ } else if (key.matches(Key.delete, .{}) or key.matches('d', .{ .ctrl = true })) {
+ if (self.cursor_idx == self.grapheme_count) return;
+ self.deleteAtCursor();
+ } else if (key.matches(Key.left, .{}) or key.matches('b', .{ .ctrl = true })) {
+ if (self.cursor_idx > 0) self.cursor_idx -= 1;
+ } else if (key.matches(Key.right, .{}) or key.matches('f', .{ .ctrl = true })) {
+ if (self.cursor_idx < self.grapheme_count) self.cursor_idx += 1;
+ } else if (key.matches('a', .{ .ctrl = true })) {
+ self.cursor_idx = 0;
+ } else if (key.matches('e', .{ .ctrl = true })) {
+ self.cursor_idx = self.grapheme_count;
+ } else if (key.matches('k', .{ .ctrl = true })) {
+ while (self.cursor_idx < self.grapheme_count) {
+ self.deleteAtCursor();
+ }
+ } else if (key.matches('u', .{ .ctrl = true })) {
+ while (self.cursor_idx > 0) {
+ self.deleteBeforeCursor();
+ }
+ } else if (key.text) |text| {
+ try self.buf.insertSlice(self.byteOffsetToCursor(), text);
+ self.cursor_idx += 1;
+ self.grapheme_count += 1;
+ }
+ },
+ }
+}
+
+pub fn draw(self: *TextInput, win: Window) void {
+ var iter = GraphemeIterator.init(self.buf.items);
+ var col: usize = 0;
+ var i: usize = 0;
+ var cursor_idx: usize = 0;
+ while (iter.next()) |grapheme| {
+ const g = grapheme.slice(self.buf.items);
+ const w = win.gwidth(g);
+ win.writeCell(col, 0, .{
+ .char = .{
+ .grapheme = g,
+ .width = w,
+ },
+ });
+ col += w;
+ i += 1;
+ if (i == self.cursor_idx) cursor_idx = col;
+ }
+ win.showCursor(cursor_idx, 0);
+}
+
+
+
+fn byteOffsetToCursor(self: TextInput) usize {
+ var iter = GraphemeIterator.init(self.buf.items);
+ var offset: usize = 0;
+ var i: usize = 0;
+ while (iter.next()) |grapheme| {
+ if (i == self.cursor_idx) break;
+ offset += grapheme.len;
+ i += 1;
+ }
+ return offset;
+}
+
+fn deleteBeforeCursor(self: *TextInput) void {
+ var iter = GraphemeIterator.init(self.buf.items);
+ var offset: usize = 0;
+ var i: usize = 1;
+ while (iter.next()) |grapheme| {
+ if (i == self.cursor_idx) {
+ var j: usize = 0;
+ while (j < grapheme.len) : (j += 1) {
+ _ = self.buf.orderedRemove(offset);
+ }
+ self.cursor_idx -= 1;
+ self.grapheme_count -= 1;
+ return;
+ }
+ offset += grapheme.len;
+ i += 1;
+ }
+}
+
+fn deleteAtCursor(self: *TextInput) void {
+ var iter = GraphemeIterator.init(self.buf.items);
+ var offset: usize = 0;
+ var i: usize = 1;
+ while (iter.next()) |grapheme| {
+ if (i == self.cursor_idx + 1) {
+ var j: usize = 0;
+ while (j < grapheme.len) : (j += 1) {
+ _ = self.buf.orderedRemove(offset);
+ }
+ self.grapheme_count -= 1;
+ return;
+ }
+ offset += grapheme.len;
+ i += 1;
+ }
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/widgets/alignment.zig.html b/docs/src/main/widgets/alignment.zig.html
new file mode 100644
index 0000000..00d70ef
--- /dev/null
+++ b/docs/src/main/widgets/alignment.zig.html
@@ -0,0 +1,124 @@
+
+
+
+
+
widgets/alignment.zig - source view
+
+
+
+
+
+
const Window = @import("../Window.zig");
+
+pub fn center(parent: Window, cols: usize, rows: usize) Window {
+ const y_off = (parent.height / 2) - (rows / 2);
+ const x_off = (parent.width / 2) - (cols / 2);
+ return parent.initChild(x_off, y_off, .{ .limit = cols }, .{ .limit = rows });
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/main/widgets/border.zig.html b/docs/src/main/widgets/border.zig.html
new file mode 100644
index 0000000..df040bb
--- /dev/null
+++ b/docs/src/main/widgets/border.zig.html
@@ -0,0 +1,149 @@
+
+
+
+
+
widgets/border.zig - source view
+
+
+
+
+
+
const Cell = @import("../Cell.zig");
+const Window = @import("../Window.zig");
+
+const Style = Cell.Style;
+const Character = Cell.Character;
+
+const horizontal = Character{ .grapheme = "─", .width = 1 };
+const vertical = Character{ .grapheme = "│", .width = 1 };
+const top_left = Character{ .grapheme = "╭", .width = 1 };
+const top_right = Character{ .grapheme = "╮", .width = 1 };
+const bottom_right = Character{ .grapheme = "╯", .width = 1 };
+const bottom_left = Character{ .grapheme = "╰", .width = 1 };
+
+pub fn all(win: Window, style: Style) Window {
+ const h = win.height;
+ const w = win.width;
+ win.writeCell(0, 0, .{ .char = top_left, .style = style });
+ win.writeCell(0, h - 1, .{ .char = bottom_left, .style = style });
+ win.writeCell(w - 1, 0, .{ .char = top_right, .style = style });
+ win.writeCell(w - 1, h - 1, .{ .char = bottom_right, .style = style });
+ var i: usize = 1;
+ while (i < (h - 1)) : (i += 1) {
+ win.writeCell(0, i, .{ .char = vertical, .style = style });
+ win.writeCell(w - 1, i, .{ .char = vertical, .style = style });
+ }
+ i = 1;
+ while (i < w - 1) : (i += 1) {
+ win.writeCell(i, 0, .{ .char = horizontal, .style = style });
+ win.writeCell(i, h - 1, .{ .char = horizontal, .style = style });
+ }
+ return win.initChild(1, 1, .{ .limit = w - 2 }, .{ .limit = w - 2 });
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/FormatInterface.zig.html b/docs/src/zigimg/src/FormatInterface.zig.html
new file mode 100644
index 0000000..0c89bcf
--- /dev/null
+++ b/docs/src/zigimg/src/FormatInterface.zig.html
@@ -0,0 +1,132 @@
+
+
+
+
+
src/FormatInterface.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const Image = @import("Image.zig");
+const color = @import("color.zig");
+
+
+
+format: *const FormatFn,
+formatDetect: *const FormatDetectFn,
+readImage: *const ReadImageFn,
+writeImage: *const WriteImageFn,
+
+pub const FormatFn = fn () Image.Format;
+pub const FormatDetectFn = fn (stream: *Image.Stream) Image.ReadError!bool;
+pub const ReadImageFn = fn (allocator: std.mem.Allocator, stream: *Image.Stream) Image.ReadError!Image;
+pub const WriteImageFn = fn (allocator: std.mem.Allocator, write_stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) Image.WriteError!void;
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/Image.zig.html b/docs/src/zigimg/src/Image.zig.html
new file mode 100644
index 0000000..ae13e74
--- /dev/null
+++ b/docs/src/zigimg/src/Image.zig.html
@@ -0,0 +1,370 @@
+
+
+
+
+
src/Image.zig - source view
+
+
+
+
+
+
const AllImageFormats = @import("formats/all.zig");
+const FormatInterface = @import("FormatInterface.zig");
+const PixelFormat = @import("pixel_format.zig").PixelFormat;
+const color = @import("color.zig");
+const std = @import("std");
+const utils = @import("utils.zig");
+
+pub const Error = error{
+ Unsupported,
+};
+
+pub const ReadError = Error ||
+ std.mem.Allocator.Error ||
+ utils.StructReadError ||
+ std.io.StreamSource.SeekError ||
+ std.io.StreamSource.GetSeekPosError ||
+ error{ EndOfStream, StreamTooLong, InvalidData };
+
+pub const WriteError = Error ||
+ std.mem.Allocator.Error ||
+ std.io.StreamSource.WriteError ||
+ std.io.StreamSource.SeekError ||
+ std.io.StreamSource.GetSeekPosError ||
+ std.fs.File.OpenError ||
+ error{ EndOfStream, InvalidData };
+
+pub const Format = enum {
+ bmp,
+ gif,
+ jpg,
+ pbm,
+ pcx,
+ pgm,
+ png,
+ ppm,
+ qoi,
+ tga,
+ pam,
+};
+
+pub const Stream = std.io.StreamSource;
+
+pub const EncoderOptions = AllImageFormats.ImageEncoderOptions;
+
+pub const AnimationLoopInfinite = -1;
+
+pub const AnimationFrame = struct {
+ pixels: color.PixelStorage,
+ duration: f32,
+
+ pub fn deinit(self: AnimationFrame, allocator: std.mem.Allocator) void {
+ self.pixels.deinit(allocator);
+ }
+};
+
+pub const Animation = struct {
+ frames: FrameList = .{},
+ loop_count: i32 = AnimationLoopInfinite,
+
+ pub const FrameList = std.ArrayListUnmanaged(AnimationFrame);
+
+ pub fn deinit(self: *Animation, allocator: std.mem.Allocator) void {
+
+
+ if (self.frames.items.len >= 2) {
+ for (self.frames.items[1..]) |frame| {
+ frame.pixels.deinit(allocator);
+ }
+ }
+
+ self.frames.deinit(allocator);
+ }
+};
+
+
+allocator: std.mem.Allocator = undefined,
+width: usize = 0,
+height: usize = 0,
+pixels: color.PixelStorage = .{ .invalid = void{} },
+animation: Animation = .{},
+
+const Image = @This();
+
+const FormatInteraceFnType = *const fn () FormatInterface;
+const all_interface_funcs = blk: {
+ const allFormatDecls = std.meta.declarations(AllImageFormats);
+ var result: [allFormatDecls.len]FormatInteraceFnType = undefined;
+ var index: usize = 0;
+ for (allFormatDecls) |decl| {
+ const decl_value = @field(AllImageFormats, decl.name);
+ const entry_type = @TypeOf(decl_value);
+ if (entry_type == type) {
+ const entryTypeInfo = @typeInfo(decl_value);
+ if (entryTypeInfo == .Struct) {
+ for (entryTypeInfo.Struct.decls) |structEntry| {
+ if (std.mem.eql(u8, structEntry.name, "formatInterface")) {
+ result[index] = @field(decl_value, structEntry.name);
+ index += 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ break :blk result[0..index];
+};
+
+
+pub fn init(allocator: std.mem.Allocator) Image {
+ return Image{
+ .allocator = allocator,
+ };
+}
+
+
+pub fn deinit(self: *Image) void {
+ self.pixels.deinit(self.allocator);
+ self.animation.deinit(self.allocator);
+}
+
+
+pub fn fromFilePath(allocator: std.mem.Allocator, file_path: []const u8) !Image {
+ var file = try std.fs.cwd().openFile(file_path, .{});
+ defer file.close();
+
+ return fromFile(allocator, &file);
+}
+
+
+pub fn fromFile(allocator: std.mem.Allocator, file: *std.fs.File) !Image {
+ var stream_source = std.io.StreamSource{ .file = file.* };
+ return internalRead(allocator, &stream_source);
+}
+
+
+pub fn fromMemory(allocator: std.mem.Allocator, buffer: []const u8) !Image {
+ var stream_source = std.io.StreamSource{ .const_buffer = std.io.fixedBufferStream(buffer) };
+ return internalRead(allocator, &stream_source);
+}
+
+
+pub fn create(allocator: std.mem.Allocator, width: usize, height: usize, pixel_format: PixelFormat) !Image {
+ const result = Image{
+ .allocator = allocator,
+ .width = width,
+ .height = height,
+ .pixels = try color.PixelStorage.init(allocator, pixel_format, width * height),
+ };
+
+ return result;
+}
+
+
+pub fn pixelFormat(self: Image) PixelFormat {
+ return std.meta.activeTag(self.pixels);
+}
+
+
+pub fn rawBytes(self: Image) []const u8 {
+ return self.pixels.asBytes();
+}
+
+
+pub fn rowByteSize(self: Image) usize {
+ return self.imageByteSize() / self.height;
+}
+
+
+pub fn imageByteSize(self: Image) usize {
+ return self.rawBytes().len;
+}
+
+
+pub fn isAnimation(self: Image) bool {
+ return self.animation.frames.items.len > 0;
+}
+
+
+pub fn writeToFilePath(self: Image, file_path: []const u8, encoder_options: EncoderOptions) WriteError!void {
+ var file = try std.fs.cwd().createFile(file_path, .{});
+ defer file.close();
+
+ try self.writeToFile(file, encoder_options);
+}
+
+
+pub fn writeToFile(self: Image, file: std.fs.File, encoder_options: EncoderOptions) WriteError!void {
+ var stream_source = std.io.StreamSource{ .file = file };
+
+ try self.internalWrite(&stream_source, encoder_options);
+}
+
+
+
+pub fn writeToMemory(self: Image, write_buffer: []u8, encoder_options: EncoderOptions) WriteError![]u8 {
+ var stream_source = std.io.StreamSource{ .buffer = std.io.fixedBufferStream(write_buffer) };
+
+ try self.internalWrite(&stream_source, encoder_options);
+
+ return stream_source.buffer.getWritten();
+}
+
+
+
+
+
+
+pub fn iterator(self: *const Image) color.PixelStorageIterator {
+ return color.PixelStorageIterator.init(&self.pixels);
+}
+
+fn internalRead(allocator: std.mem.Allocator, stream: *Stream) !Image {
+ const format_interface = try findImageInterfaceFromStream(stream);
+
+ try stream.seekTo(0);
+
+ return try format_interface.readImage(allocator, stream);
+}
+
+fn internalWrite(self: Image, stream: *Stream, encoder_options: EncoderOptions) WriteError!void {
+ const image_format = std.meta.activeTag(encoder_options);
+
+ var format_interface = try findImageInterfaceFromImageFormat(image_format);
+
+ try format_interface.writeImage(self.allocator, stream, self, encoder_options);
+}
+
+fn findImageInterfaceFromStream(stream: *Stream) !FormatInterface {
+ for (all_interface_funcs) |intefaceFn| {
+ const formatInterface = intefaceFn();
+
+ try stream.seekTo(0);
+ const found = try formatInterface.formatDetect(stream);
+ if (found) {
+ return formatInterface;
+ }
+ }
+
+ return Error.Unsupported;
+}
+
+fn findImageInterfaceFromImageFormat(image_format: Format) !FormatInterface {
+ for (all_interface_funcs) |interface_fn| {
+ const format_interface = interface_fn();
+
+ if (format_interface.format() == image_format) {
+ return format_interface;
+ }
+ }
+
+ return Error.Unsupported;
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/buffered_stream_source.zig.html b/docs/src/zigimg/src/buffered_stream_source.zig.html
new file mode 100644
index 0000000..b6492ed
--- /dev/null
+++ b/docs/src/zigimg/src/buffered_stream_source.zig.html
@@ -0,0 +1,372 @@
+
+
+
+
+
src/buffered_stream_source.zig - source view
+
+
+
+
+
+
const std = @import("std");
+
+const DefaultBufferSize = 8 * 1024;
+
+pub const DefaultBufferedStreamSourceReader = BufferedStreamSourceReader(DefaultBufferSize);
+pub const DefaultBufferedStreamSourceWriter = BufferedStreamSourceWriter(DefaultBufferSize);
+
+
+
+pub fn BufferedStreamSourceReader(comptime BufferSize: usize) type {
+ return struct {
+ buffered_reader: std.io.BufferedReader(BufferSize, std.io.StreamSource.Reader),
+
+ pub const ReadError = std.io.StreamSource.ReadError;
+ pub const SeekError = std.io.StreamSource.SeekError;
+ pub const GetSeekPosError = std.io.StreamSource.GetSeekPosError;
+
+ const Self = @This();
+
+ pub const Reader = std.io.Reader(*Self, ReadError, read);
+ pub const SeekableStream = std.io.SeekableStream(
+ *Self,
+ SeekError,
+ GetSeekPosError,
+ seekTo,
+ seekBy,
+ getPos,
+ getEndPos,
+ );
+
+ pub fn read(self: *Self, dest: []u8) ReadError!usize {
+ return switch (self.buffered_reader.unbuffered_reader.context.*) {
+ .buffer => |*actual_reader| actual_reader.read(dest),
+ .const_buffer => |*actual_reader| actual_reader.read(dest),
+ .file => self.buffered_reader.read(dest),
+ };
+ }
+
+ pub fn seekTo(self: *Self, pos: u64) SeekError!void {
+ switch (self.buffered_reader.unbuffered_reader.context.*) {
+ .buffer => |*actual_reader| {
+ return actual_reader.seekTo(pos);
+ },
+ .const_buffer => |*actual_reader| {
+ return actual_reader.seekTo(pos);
+ },
+ .file => {
+ try self.buffered_reader.unbuffered_reader.context.seekTo(pos);
+ self.resetBufferedReader();
+ },
+ }
+ }
+
+ pub fn seekBy(self: *Self, amt: i64) SeekError!void {
+ switch (self.buffered_reader.unbuffered_reader.context.*) {
+ .buffer => |*actual_reader| {
+ return actual_reader.seekBy(amt);
+ },
+ .const_buffer => |*actual_reader| {
+ return actual_reader.seekBy(amt);
+ },
+ .file => {
+ const bytes_availables = self.buffered_reader.end - self.buffered_reader.start;
+ if (amt > 0) {
+ if (amt <= bytes_availables) {
+ self.buffered_reader.start += @intCast(amt);
+ } else {
+ try self.buffered_reader.unbuffered_reader.context.seekBy(amt - @as(i64, @intCast(bytes_availables)));
+ self.resetBufferedReader();
+ }
+ } else if (amt < 0) {
+ const absolute_amt = @abs(amt);
+ if (absolute_amt <= self.buffered_reader.start) {
+ self.buffered_reader.start -%= absolute_amt;
+ } else {
+ try self.buffered_reader.unbuffered_reader.context.seekBy(amt - @as(i64, @intCast(bytes_availables)));
+ self.resetBufferedReader();
+ }
+ }
+ },
+ }
+ }
+
+ pub fn getEndPos(self: *Self) GetSeekPosError!u64 {
+ return self.buffered_reader.unbuffered_reader.context.getEndPos();
+ }
+
+ pub fn getPos(self: *Self) GetSeekPosError!u64 {
+ switch (self.buffered_reader.unbuffered_reader.context.*) {
+ .buffer => |*actual_reader| {
+ return actual_reader.getPos();
+ },
+ .const_buffer => |*actual_reader| {
+ return actual_reader.getPos();
+ },
+ .file => {
+ if (self.buffered_reader.unbuffered_reader.context.getPos()) |position| {
+ return position - (self.buffered_reader.end - self.buffered_reader.start);
+ } else |err| {
+ return err;
+ }
+ },
+ }
+ }
+
+ pub fn reader(self: *Self) Reader {
+ return .{ .context = self };
+ }
+
+ pub fn seekableStream(self: *Self) SeekableStream {
+ return .{ .context = self };
+ }
+
+ fn resetBufferedReader(self: *Self) void {
+ self.buffered_reader.start = 0;
+ self.buffered_reader.end = 0;
+ }
+ };
+}
+
+pub fn bufferedStreamSourceReader(stream: *std.io.StreamSource) BufferedStreamSourceReader(DefaultBufferSize) {
+ return .{ .buffered_reader = .{ .unbuffered_reader = stream.reader() } };
+}
+
+pub fn bufferedStreamSourceReaderWithSize(comptime buffer_size: usize, stream: *std.io.StreamSource) BufferedStreamSourceReader(buffer_size) {
+ return .{ .buffered_reader = .{ .unbuffered_reader = stream.reader() } };
+}
+
+
+
+pub fn BufferedStreamSourceWriter(comptime BufferSize: usize) type {
+ return struct {
+ buffered_writer: std.io.BufferedWriter(BufferSize, std.io.StreamSource.Writer),
+
+ pub const WriteError = std.io.StreamSource.WriteError;
+ pub const SeekError = std.io.StreamSource.SeekError;
+ pub const GetSeekPosError = std.io.StreamSource.GetSeekPosError;
+
+ const Self = @This();
+
+ pub const Writer = std.io.Writer(*Self, WriteError, write);
+ pub const SeekableStream = std.io.SeekableStream(
+ *Self,
+ SeekError,
+ GetSeekPosError,
+ seekTo,
+ seekBy,
+ getPos,
+ getEndPos,
+ );
+
+ pub fn write(self: *Self, bytes: []const u8) WriteError!usize {
+ return switch (self.buffered_writer.unbuffered_writer.context.*) {
+ .buffer => |*actual_writer| actual_writer.write(bytes),
+ .const_buffer => error.AccessDenied,
+ .file => self.buffered_writer.write(bytes),
+ };
+ }
+
+ pub fn seekTo(self: *Self, pos: u64) SeekError!void {
+ switch (self.buffered_writer.unbuffered_writer.context.*) {
+ .buffer => |*actual_writer| {
+ return actual_writer.seekTo(pos);
+ },
+ .const_buffer => |*actual_writer| {
+ return actual_writer.seekTo(pos);
+ },
+ .file => {
+ try self.buffered_writer.flush();
+ try self.buffered_writer.buffered_writer.context.seekTo(pos);
+ },
+ }
+ }
+
+ pub fn seekBy(self: *Self, amt: i64) SeekError!void {
+ switch (self.buffered_writer.unbuffered_writer.context.*) {
+ .buffer => |*actual_writer| {
+ return actual_writer.seekBy(amt);
+ },
+ .const_buffer => |*actual_writer| {
+ return actual_writer.seekBy(amt);
+ },
+ .file => {
+ if (amt < 0) {
+ const abs_amt = @abs(amt);
+ if (abs_amt <= self.buffered_writer.end) {
+ self.buffered_writer.end -= abs_amt;
+ } else {
+ self.buffered_writer.flush() catch {
+ return error.Unseekable;
+ };
+ try self.buffered_writer.unbuffered_writer.context.seekBy(amt);
+ }
+ } else {
+ const amt_usize: usize = @intCast(amt);
+
+ if (self.buffered_writer.end + amt_usize < self.buffered_writer.buf.len) {
+ self.buffered_writer.end += amt_usize;
+ } else {
+ self.buffered_writer.flush() catch {
+ return error.Unseekable;
+ };
+ try self.buffered_writer.unbuffered_writer.context.seekBy(amt);
+ }
+ }
+ },
+ }
+ }
+
+ pub fn getEndPos(self: *Self) GetSeekPosError!u64 {
+ return self.buffered_writer.unbuffered_writer.context.getEndPos();
+ }
+
+ pub fn getPos(self: *Self) GetSeekPosError!u64 {
+ switch (self.buffered_writer.unbuffered_writer.context.*) {
+ .buffer => |*actual_writer| {
+ return actual_writer.getPos();
+ },
+ .const_buffer => |*actual_writer| {
+ return actual_writer.getPos();
+ },
+ .file => {
+ if (self.buffered_writer.unbuffered_writer.context.getPos()) |position| {
+ return position + self.buffered_writer.end;
+ } else |err| {
+ return err;
+ }
+ },
+ }
+ }
+
+ pub fn writer(self: *Self) Writer {
+ return .{ .context = self };
+ }
+
+ pub fn seekableStream(self: *Self) SeekableStream {
+ return .{ .context = self };
+ }
+
+ pub fn flush(self: *Self) WriteError!void {
+ return switch (self.buffered_writer.unbuffered_writer.context.*) {
+ .file => self.buffered_writer.flush(),
+ else => {},
+ };
+ }
+ };
+}
+
+pub fn bufferedStreamSourceWriter(stream: *std.io.StreamSource) BufferedStreamSourceWriter(DefaultBufferSize) {
+ return .{ .buffered_writer = .{ .unbuffered_writer = stream.writer() } };
+}
+
+pub fn bufferedStreamSourceWriterWithSize(comptime buffer_size: usize, stream: *std.io.StreamSource) BufferedStreamSourceWriter(buffer_size) {
+ return .{ .buffered_writer = .{ .unbuffered_writer = stream.writer() } };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/color.zig.html b/docs/src/zigimg/src/color.zig.html
new file mode 100644
index 0000000..4a49e30
--- /dev/null
+++ b/docs/src/zigimg/src/color.zig.html
@@ -0,0 +1,1060 @@
+
+
+
+
+
src/color.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const math = std.math;
+const Allocator = std.mem.Allocator;
+const PixelFormat = @import("pixel_format.zig").PixelFormat;
+const TypeInfo = std.builtin.TypeInfo;
+
+pub inline fn toIntColor(comptime T: type, value: f32) T {
+ const float_value = @round(value * @as(f32, @floatFromInt(math.maxInt(T))));
+ return @as(T, @intFromFloat(math.clamp(float_value, math.minInt(T), math.maxInt(T))));
+}
+
+pub inline fn scaleToIntColor(comptime T: type, value: anytype) T {
+ const ValueT = @TypeOf(value);
+ if (ValueT == comptime_int) return @as(T, value);
+ const ValueTypeInfo = @typeInfo(ValueT);
+ if (ValueTypeInfo != .Int or ValueTypeInfo.Int.signedness != .unsigned) {
+ @compileError("scaleToInColor only accepts unsigned integers as values. Got " ++ @typeName(ValueT) ++ ".");
+ }
+ const cur_value_bits = @bitSizeOf(ValueT);
+ const new_value_bits = @bitSizeOf(T);
+ if (cur_value_bits > new_value_bits) {
+ return @as(T, @truncate(value >> (cur_value_bits - new_value_bits)));
+ } else if (cur_value_bits < new_value_bits) {
+ const cur_value_max = math.maxInt(ValueT);
+ const new_value_max = math.maxInt(T);
+ return @as(T, @truncate((@as(u32, value) * new_value_max + cur_value_max / 2) / cur_value_max));
+ } else return @as(T, value);
+}
+
+pub inline fn toF32Color(value: anytype) f32 {
+ return @as(f32, @floatFromInt(value)) / @as(f32, @floatFromInt(math.maxInt(@TypeOf(value))));
+}
+
+pub const Colorf32 = extern struct {
+ r: f32 align(1),
+ g: f32 align(1),
+ b: f32 align(1),
+ a: f32 align(1) = 1.0,
+
+ const Self = @This();
+
+ pub fn initRgb(r: f32, g: f32, b: f32) Self {
+ return Self{
+ .r = r,
+ .g = g,
+ .b = b,
+ };
+ }
+
+ pub fn initRgba(r: f32, g: f32, b: f32, a: f32) Self {
+ return Self{
+ .r = r,
+ .g = g,
+ .b = b,
+ .a = a,
+ };
+ }
+
+ pub fn fromU32Rgba(value: u32) Self {
+ return Self{
+ .r = toF32Color(@as(u8, @truncate(value >> 24))),
+ .g = toF32Color(@as(u8, @truncate(value >> 16))),
+ .b = toF32Color(@as(u8, @truncate(value >> 8))),
+ .a = toF32Color(@as(u8, @truncate(value))),
+ };
+ }
+
+ pub fn toU32Rgba(self: Self) u32 {
+ return @as(u32, toIntColor(u8, self.r)) << 24 |
+ @as(u32, toIntColor(u8, self.g)) << 16 |
+ @as(u32, toIntColor(u8, self.b)) << 8 |
+ @as(u32, toIntColor(u8, self.a));
+ }
+
+ pub fn fromU64Rgba(value: u64) Self {
+ return Self{
+ .r = toF32Color(@as(u16, @truncate(value >> 48))),
+ .g = toF32Color(@as(u16, @truncate(value >> 32))),
+ .b = toF32Color(@as(u16, @truncate(value >> 16))),
+ .a = toF32Color(@as(u16, @truncate(value))),
+ };
+ }
+
+ pub fn toU64Rgba(self: Self) u64 {
+ return @as(u64, toIntColor(u16, self.r)) << 48 |
+ @as(u64, toIntColor(u16, self.g)) << 32 |
+ @as(u64, toIntColor(u16, self.b)) << 16 |
+ @as(u64, toIntColor(u16, self.a));
+ }
+
+ pub fn toPremultipliedAlpha(self: Self) Self {
+ return Self{
+ .r = self.r * self.a,
+ .g = self.g * self.a,
+ .b = self.b * self.a,
+ .a = self.a,
+ };
+ }
+
+ pub fn toRgba(self: Self, comptime T: type) RgbaColor(T) {
+ return .{
+ .r = toIntColor(T, self.r),
+ .g = toIntColor(T, self.g),
+ .b = toIntColor(T, self.b),
+ .a = toIntColor(T, self.a),
+ };
+ }
+
+ pub fn toRgba32(self: Self) Rgba32 {
+ return self.toRgba(u8);
+ }
+
+ pub fn toRgba64(self: Self) Rgba64 {
+ return self.toRgba(u16);
+ }
+
+ pub fn toArray(self: Self) [4]f32 {
+ return @bitCast(self);
+ }
+
+ pub fn fromArray(value: [4]f32) Self {
+ return @bitCast(value);
+ }
+};
+
+fn isAll8BitColor(comptime red_type: type, comptime green_type: type, comptime blue_type: type, comptime alpha_type: type) bool {
+ return red_type == u8 and green_type == u8 and blue_type == u8 and (alpha_type == u8 or alpha_type == void);
+}
+
+
+
+fn RgbMethods(
+ comptime Self: type,
+ comptime RedT: type,
+ comptime GreenT: type,
+ comptime BlueT: type,
+ comptime AlphaT: type,
+) type {
+ const has_alpha_type = @hasField(Self, "a");
+
+ return struct {
+ pub fn initRgb(r: RedT, g: GreenT, b: BlueT) Self {
+ return Self{
+ .r = r,
+ .g = g,
+ .b = b,
+ };
+ }
+
+ pub fn toColorf32(self: Self) Colorf32 {
+ return Colorf32{
+ .r = toF32Color(self.r),
+ .g = toF32Color(self.g),
+ .b = toF32Color(self.b),
+ .a = if (has_alpha_type) toF32Color(self.a) else 1.0,
+ };
+ }
+
+ pub fn fromU32Rgba(value: u32) Self {
+ var res = Self{
+ .r = scaleToIntColor(RedT, @as(u8, @truncate(value >> 24))),
+ .g = scaleToIntColor(GreenT, @as(u8, @truncate(value >> 16))),
+ .b = scaleToIntColor(BlueT, @as(u8, @truncate(value >> 8))),
+ };
+ if (has_alpha_type) {
+ res.a = scaleToIntColor(AlphaT, @as(u8, @truncate(value)));
+ }
+ return res;
+ }
+
+ pub fn fromU32Rgb(value: u32) Self {
+ return Self{
+ .r = scaleToIntColor(RedT, @as(u8, @truncate(value >> 16))),
+ .g = scaleToIntColor(GreenT, @as(u8, @truncate(value >> 8))),
+ .b = scaleToIntColor(BlueT, @as(u8, @truncate(value))),
+ };
+ }
+
+ pub fn fromU64Rgba(value: u64) Self {
+ var res = Self{
+ .r = scaleToIntColor(RedT, @as(u16, @truncate(value >> 48))),
+ .g = scaleToIntColor(GreenT, @as(u16, @truncate(value >> 32))),
+ .b = scaleToIntColor(BlueT, @as(u16, @truncate(value >> 16))),
+ };
+ if (has_alpha_type) {
+ res.a = scaleToIntColor(AlphaT, @as(u16, @truncate(value)));
+ }
+ return res;
+ }
+
+ pub fn fromU64Rgb(value: u64) Self {
+ return Self{
+ .r = scaleToIntColor(RedT, @as(u16, @truncate(value >> 32))),
+ .g = scaleToIntColor(GreenT, @as(u16, @truncate(value >> 16))),
+ .b = scaleToIntColor(BlueT, @as(u16, @truncate(value))),
+ };
+ }
+
+
+
+ pub usingnamespace if (isAll8BitColor(RedT, GreenT, BlueT, AlphaT))
+ struct {
+ pub fn fromHtmlHex(hex_string: []const u8) !Self {
+ if (hex_string.len == 0) {
+ return error.InvalidHtmlHexString;
+ }
+
+ if (hex_string[0] != '#') {
+ return error.InvalidHtmlHexString;
+ }
+
+ if (has_alpha_type) {
+ if (hex_string.len != 4 and hex_string.len != 7 and hex_string.len != 5 and hex_string.len != 9) {
+ return error.InvalidHtmlHexString;
+ }
+ } else {
+ if (hex_string.len != 4 and hex_string.len != 7) {
+ return error.InvalidHtmlHexString;
+ }
+ }
+
+ if (hex_string.len == 7) {
+ var storage: [3]u8 = undefined;
+ const output = std.fmt.hexToBytes(storage[0..], hex_string[1..]) catch {
+ return error.InvalidHtmlHexString;
+ };
+
+ return Self{
+ .r = output[0],
+ .g = output[1],
+ .b = output[2],
+ };
+ } else if (has_alpha_type and hex_string.len == 9) {
+ var storage: [4]u8 = undefined;
+ const output = std.fmt.hexToBytes(storage[0..], hex_string[1..]) catch {
+ return error.InvalidHtmlHexString;
+ };
+
+ return Self{
+ .r = output[0],
+ .g = output[1],
+ .b = output[2],
+ .a = output[3],
+ };
+ } else if (hex_string.len == 4) {
+ const red_digit = std.fmt.charToDigit(hex_string[1], 16) catch {
+ return error.InvalidHtmlHexString;
+ };
+ const green_digit = std.fmt.charToDigit(hex_string[2], 16) catch {
+ return error.InvalidHtmlHexString;
+ };
+ const blue_digit = std.fmt.charToDigit(hex_string[3], 16) catch {
+ return error.InvalidHtmlHexString;
+ };
+
+ return Self{
+ .r = red_digit | (red_digit << 4),
+ .g = green_digit | (green_digit << 4),
+ .b = blue_digit | (blue_digit << 4),
+ };
+ } else if (has_alpha_type and hex_string.len == 5) {
+ const red_digit = std.fmt.charToDigit(hex_string[1], 16) catch {
+ return error.InvalidHtmlHexString;
+ };
+ const green_digit = std.fmt.charToDigit(hex_string[2], 16) catch {
+ return error.InvalidHtmlHexString;
+ };
+ const blue_digit = std.fmt.charToDigit(hex_string[3], 16) catch {
+ return error.InvalidHtmlHexString;
+ };
+ const alpha_digit = std.fmt.charToDigit(hex_string[4], 16) catch {
+ return error.InvalidHtmlHexString;
+ };
+
+ return Self{
+ .r = red_digit | (red_digit << 4),
+ .g = green_digit | (green_digit << 4),
+ .b = blue_digit | (blue_digit << 4),
+ .a = alpha_digit | (alpha_digit << 4),
+ };
+ } else {
+ return error.InvalidHtmlHexString;
+ }
+ }
+ }
+ else
+ struct {};
+
+ pub fn toU32Rgba(self: Self) u32 {
+ return @as(u32, scaleToIntColor(u8, self.r)) << 24 |
+ @as(u32, scaleToIntColor(u8, self.g)) << 16 |
+ @as(u32, scaleToIntColor(u8, self.b)) << 8 |
+ if (@hasField(Self, "a")) scaleToIntColor(u8, self.a) else 0xff;
+ }
+
+ pub fn toU32Rgb(self: Self) u32 {
+ return @as(u32, scaleToIntColor(u8, self.r)) << 16 |
+ @as(u32, scaleToIntColor(u8, self.g)) << 8 |
+ scaleToIntColor(u8, self.b);
+ }
+
+ pub fn toU64Rgba(self: Self) u64 {
+ return @as(u64, scaleToIntColor(u16, self.r)) << 48 |
+ @as(u64, scaleToIntColor(u16, self.g)) << 32 |
+ @as(u64, scaleToIntColor(u16, self.b)) << 16 |
+ if (@hasField(Self, "a")) scaleToIntColor(u16, self.a) else 0xffff;
+ }
+
+ pub fn toU64Rgb(self: Self) u64 {
+ return @as(u64, scaleToIntColor(u16, self.r)) << 32 |
+ @as(u64, scaleToIntColor(u16, self.g)) << 16 |
+ scaleToIntColor(u16, self.b);
+ }
+ };
+}
+
+fn RgbaMethods(comptime Self: type) type {
+ return struct {
+ const T = std.meta.fieldInfo(Self, .r).type;
+ const comp_bits = @typeInfo(T).Int.bits;
+
+ pub fn initRgba(r: T, g: T, b: T, a: T) Self {
+ return Self{
+ .r = r,
+ .g = g,
+ .b = b,
+ .a = a,
+ };
+ }
+
+ pub fn toPremultipliedAlpha(self: Self) Self {
+ const max = math.maxInt(T);
+ return Self{
+ .r = @as(T, @truncate((@as(u32, self.r) * self.a + max / 2) / max)),
+ .g = @as(T, @truncate((@as(u32, self.g) * self.a + max / 2) / max)),
+ .b = @as(T, @truncate((@as(u32, self.b) * self.a + max / 2) / max)),
+ .a = self.a,
+ };
+ }
+ };
+}
+
+fn RgbColor(comptime T: type) type {
+ return extern struct {
+ r: T align(1),
+ g: T align(1),
+ b: T align(1),
+
+ pub usingnamespace RgbMethods(@This(), T, T, T, void);
+ };
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+pub const Bgr555 = packed struct {
+ r: u5 = 0,
+ g: u5 = 0,
+ b: u5 = 0,
+
+ pub usingnamespace RgbMethods(@This(), u5, u5, u5, void);
+};
+
+
+
+
+
+
+
+
+
+pub const Rgb555 = packed struct {
+ b: u5,
+ g: u5,
+ r: u5,
+
+ pub usingnamespace RgbMethods(@This(), u5, u5, u5, void);
+};
+
+
+
+
+
+
+
+
+
+pub const Rgb565 = packed struct {
+ b: u5,
+ g: u6,
+ r: u5,
+
+ pub usingnamespace RgbMethods(@This(), u5, u6, u5, void);
+};
+
+fn RgbaColor(comptime T: type) type {
+ return extern struct {
+ r: T align(1),
+ g: T align(1),
+ b: T align(1),
+ a: T align(1) = math.maxInt(T),
+
+ pub usingnamespace RgbMethods(@This(), T, T, T, T);
+ pub usingnamespace RgbaMethods(@This());
+ };
+}
+
+
+
+
+
+
+
+
+
+pub const Rgb24 = RgbColor(u8);
+
+
+
+
+
+
+
+
+
+pub const Rgba32 = RgbaColor(u8);
+
+
+
+
+
+
+
+
+
+pub const Rgb48 = RgbColor(u16);
+
+
+
+
+
+
+
+
+
+pub const Rgba64 = RgbaColor(u16);
+
+fn BgrColor(comptime T: type) type {
+ return extern struct {
+ b: T align(1),
+ g: T align(1),
+ r: T align(1),
+
+ pub usingnamespace RgbMethods(@This(), T, T, T, void);
+ };
+}
+
+fn BgraColor(comptime T: type) type {
+ return extern struct {
+ b: T align(1),
+ g: T align(1),
+ r: T align(1),
+ a: T = math.maxInt(T),
+
+ pub usingnamespace RgbMethods(@This(), T, T, T, T);
+ pub usingnamespace RgbaMethods(@This());
+ };
+}
+
+
+
+
+
+
+
+
+
+pub const Bgr24 = BgrColor(u8);
+
+
+
+
+
+
+
+
+
+pub const Bgra32 = BgraColor(u8);
+
+pub fn IndexedStorage(comptime T: type) type {
+ return struct {
+ palette: []Rgba32,
+ indices: []T,
+
+ pub const PaletteSize = 1 << @bitSizeOf(T);
+
+ const Self = @This();
+
+ pub fn init(allocator: Allocator, pixel_count: usize) !Self {
+ const result = Self{
+ .indices = try allocator.alloc(T, pixel_count),
+ .palette = try allocator.alloc(Rgba32, PaletteSize),
+ };
+
+
+
+
+
+ @memset(result.palette, Rgba32.initRgba(0, 0, 0, 0));
+ return result;
+ }
+
+ pub fn deinit(self: Self, allocator: Allocator) void {
+ allocator.free(self.palette);
+ allocator.free(self.indices);
+ }
+ };
+}
+
+pub const IndexedStorage1 = IndexedStorage(u1);
+pub const IndexedStorage2 = IndexedStorage(u2);
+pub const IndexedStorage4 = IndexedStorage(u4);
+pub const IndexedStorage8 = IndexedStorage(u8);
+pub const IndexedStorage16 = IndexedStorage(u16);
+
+pub fn Grayscale(comptime T: type) type {
+ return struct {
+ value: T,
+
+ const Self = @This();
+
+ pub fn toColorf32(self: Self) Colorf32 {
+ const gray = toF32Color(self.value);
+ return Colorf32{
+ .r = gray,
+ .g = gray,
+ .b = gray,
+ .a = 1.0,
+ };
+ }
+ };
+}
+
+pub fn GrayscaleAlpha(comptime T: type) type {
+ return struct {
+ value: T,
+ alpha: T = math.maxInt(T),
+
+ const Self = @This();
+
+ pub fn toColorf32(self: Self) Colorf32 {
+ const gray = toF32Color(self.value);
+ return Colorf32{
+ .r = gray,
+ .g = gray,
+ .b = gray,
+ .a = toF32Color(self.alpha),
+ };
+ }
+ };
+}
+
+pub const Grayscale1 = Grayscale(u1);
+pub const Grayscale2 = Grayscale(u2);
+pub const Grayscale4 = Grayscale(u4);
+pub const Grayscale8 = Grayscale(u8);
+pub const Grayscale16 = Grayscale(u16);
+pub const Grayscale8Alpha = GrayscaleAlpha(u8);
+pub const Grayscale16Alpha = GrayscaleAlpha(u16);
+
+pub const PixelStorage = union(PixelFormat) {
+ invalid: void,
+ indexed1: IndexedStorage1,
+ indexed2: IndexedStorage2,
+ indexed4: IndexedStorage4,
+ indexed8: IndexedStorage8,
+ indexed16: IndexedStorage16,
+ grayscale1: []Grayscale1,
+ grayscale2: []Grayscale2,
+ grayscale4: []Grayscale4,
+ grayscale8: []Grayscale8,
+ grayscale16: []Grayscale16,
+ grayscale8Alpha: []Grayscale8Alpha,
+ grayscale16Alpha: []Grayscale16Alpha,
+ rgb555: []Rgb555,
+ rgb565: []Rgb565,
+ rgb24: []Rgb24,
+ rgba32: []Rgba32,
+ bgr555: []Bgr555,
+ bgr24: []Bgr24,
+ bgra32: []Bgra32,
+ rgb48: []Rgb48,
+ rgba64: []Rgba64,
+ float32: []Colorf32,
+
+ const Self = @This();
+
+ pub fn init(allocator: Allocator, format: PixelFormat, pixel_count: usize) !Self {
+ return switch (format) {
+ .invalid => {
+ return Self{
+ .invalid = void{},
+ };
+ },
+ .indexed1 => {
+ return Self{
+ .indexed1 = try IndexedStorage(u1).init(allocator, pixel_count),
+ };
+ },
+ .indexed2 => {
+ return Self{
+ .indexed2 = try IndexedStorage(u2).init(allocator, pixel_count),
+ };
+ },
+ .indexed4 => {
+ return Self{
+ .indexed4 = try IndexedStorage(u4).init(allocator, pixel_count),
+ };
+ },
+ .indexed8 => {
+ return Self{
+ .indexed8 = try IndexedStorage(u8).init(allocator, pixel_count),
+ };
+ },
+ .indexed16 => {
+ return Self{
+ .indexed16 = try IndexedStorage(u16).init(allocator, pixel_count),
+ };
+ },
+ .grayscale1 => {
+ return Self{
+ .grayscale1 = try allocator.alloc(Grayscale1, pixel_count),
+ };
+ },
+ .grayscale2 => {
+ return Self{
+ .grayscale2 = try allocator.alloc(Grayscale2, pixel_count),
+ };
+ },
+ .grayscale4 => {
+ return Self{
+ .grayscale4 = try allocator.alloc(Grayscale4, pixel_count),
+ };
+ },
+ .grayscale8 => {
+ return Self{
+ .grayscale8 = try allocator.alloc(Grayscale8, pixel_count),
+ };
+ },
+ .grayscale8Alpha => {
+ return Self{
+ .grayscale8Alpha = try allocator.alloc(Grayscale8Alpha, pixel_count),
+ };
+ },
+ .grayscale16 => {
+ return Self{
+ .grayscale16 = try allocator.alloc(Grayscale16, pixel_count),
+ };
+ },
+ .grayscale16Alpha => {
+ return Self{
+ .grayscale16Alpha = try allocator.alloc(Grayscale16Alpha, pixel_count),
+ };
+ },
+ .rgb24 => {
+ return Self{
+ .rgb24 = try allocator.alloc(Rgb24, pixel_count),
+ };
+ },
+ .rgba32 => {
+ return Self{
+ .rgba32 = try allocator.alloc(Rgba32, pixel_count),
+ };
+ },
+ .rgb565 => {
+ return Self{
+ .rgb565 = try allocator.alloc(Rgb565, pixel_count),
+ };
+ },
+ .rgb555 => {
+ return Self{
+ .rgb555 = try allocator.alloc(Rgb555, pixel_count),
+ };
+ },
+ .bgr555 => {
+ return Self{
+ .bgr555 = try allocator.alloc(Bgr555, pixel_count),
+ };
+ },
+ .bgr24 => {
+ return Self{
+ .bgr24 = try allocator.alloc(Bgr24, pixel_count),
+ };
+ },
+ .bgra32 => {
+ return Self{
+ .bgra32 = try allocator.alloc(Bgra32, pixel_count),
+ };
+ },
+ .rgb48 => {
+ return Self{
+ .rgb48 = try allocator.alloc(Rgb48, pixel_count),
+ };
+ },
+ .rgba64 => {
+ return Self{
+ .rgba64 = try allocator.alloc(Rgba64, pixel_count),
+ };
+ },
+ .float32 => {
+ return Self{
+ .float32 = try allocator.alloc(Colorf32, pixel_count),
+ };
+ },
+ };
+ }
+
+ pub fn deinit(self: Self, allocator: Allocator) void {
+ switch (self) {
+ .invalid => {},
+ .indexed1 => |data| data.deinit(allocator),
+ .indexed2 => |data| data.deinit(allocator),
+ .indexed4 => |data| data.deinit(allocator),
+ .indexed8 => |data| data.deinit(allocator),
+ .indexed16 => |data| data.deinit(allocator),
+ .grayscale1 => |data| allocator.free(data),
+ .grayscale2 => |data| allocator.free(data),
+ .grayscale4 => |data| allocator.free(data),
+ .grayscale8 => |data| allocator.free(data),
+ .grayscale8Alpha => |data| allocator.free(data),
+ .grayscale16 => |data| allocator.free(data),
+ .grayscale16Alpha => |data| allocator.free(data),
+ .rgb24 => |data| allocator.free(data),
+ .rgba32 => |data| allocator.free(data),
+ .rgb565 => |data| allocator.free(data),
+ .rgb555 => |data| allocator.free(data),
+ .bgr555 => |data| allocator.free(data),
+ .bgr24 => |data| allocator.free(data),
+ .bgra32 => |data| allocator.free(data),
+ .rgb48 => |data| allocator.free(data),
+ .rgba64 => |data| allocator.free(data),
+ .float32 => |data| allocator.free(data),
+ }
+ }
+
+ pub fn len(self: Self) usize {
+ return switch (self) {
+ .invalid => 0,
+ .indexed1 => |data| data.indices.len,
+ .indexed2 => |data| data.indices.len,
+ .indexed4 => |data| data.indices.len,
+ .indexed8 => |data| data.indices.len,
+ .indexed16 => |data| data.indices.len,
+ .grayscale1 => |data| data.len,
+ .grayscale2 => |data| data.len,
+ .grayscale4 => |data| data.len,
+ .grayscale8 => |data| data.len,
+ .grayscale8Alpha => |data| data.len,
+ .grayscale16 => |data| data.len,
+ .grayscale16Alpha => |data| data.len,
+ .rgb24 => |data| data.len,
+ .rgba32 => |data| data.len,
+ .rgb565 => |data| data.len,
+ .rgb555 => |data| data.len,
+ .bgr555 => |data| data.len,
+ .bgr24 => |data| data.len,
+ .bgra32 => |data| data.len,
+ .rgb48 => |data| data.len,
+ .rgba64 => |data| data.len,
+ .float32 => |data| data.len,
+ };
+ }
+
+ pub fn isIndexed(self: Self) bool {
+ return switch (self) {
+ .indexed1 => true,
+ .indexed2 => true,
+ .indexed4 => true,
+ .indexed8 => true,
+ .indexed16 => true,
+ else => false,
+ };
+ }
+
+ pub fn getPalette(self: Self) ?[]Rgba32 {
+ return switch (self) {
+ .indexed1 => |data| data.palette,
+ .indexed2 => |data| data.palette,
+ .indexed4 => |data| data.palette,
+ .indexed8 => |data| data.palette,
+ .indexed16 => |data| data.palette,
+ else => null,
+ };
+ }
+
+
+ pub fn asBytes(self: Self) []u8 {
+ return switch (self) {
+ .invalid => &[_]u8{},
+ .indexed1 => |data| std.mem.sliceAsBytes(data.indices),
+ .indexed2 => |data| std.mem.sliceAsBytes(data.indices),
+ .indexed4 => |data| std.mem.sliceAsBytes(data.indices),
+ .indexed8 => |data| std.mem.sliceAsBytes(data.indices),
+ .indexed16 => |data| std.mem.sliceAsBytes(data.indices),
+ .grayscale1 => |data| std.mem.sliceAsBytes(data),
+ .grayscale2 => |data| std.mem.sliceAsBytes(data),
+ .grayscale4 => |data| std.mem.sliceAsBytes(data),
+ .grayscale8 => |data| std.mem.sliceAsBytes(data),
+ .grayscale8Alpha => |data| std.mem.sliceAsBytes(data),
+ .grayscale16 => |data| std.mem.sliceAsBytes(data),
+ .grayscale16Alpha => |data| std.mem.sliceAsBytes(data),
+ .rgb24 => |data| std.mem.sliceAsBytes(data),
+ .rgba32 => |data| std.mem.sliceAsBytes(data),
+ .rgb565 => |data| std.mem.sliceAsBytes(data),
+ .rgb555 => |data| std.mem.sliceAsBytes(data),
+ .bgr555 => |data| std.mem.sliceAsBytes(data),
+ .bgr24 => |data| std.mem.sliceAsBytes(data),
+ .bgra32 => |data| std.mem.sliceAsBytes(data),
+ .rgb48 => |data| std.mem.sliceAsBytes(data),
+ .rgba64 => |data| std.mem.sliceAsBytes(data),
+ .float32 => |data| std.mem.sliceAsBytes(data),
+ };
+ }
+
+ pub fn asConstBytes(self: Self) []const u8 {
+ return switch (self) {
+ .invalid => &[_]u8{},
+ .indexed1 => |data| std.mem.sliceAsBytes(data.indices),
+ .indexed2 => |data| std.mem.sliceAsBytes(data.indices),
+ .indexed4 => |data| std.mem.sliceAsBytes(data.indices),
+ .indexed8 => |data| std.mem.sliceAsBytes(data.indices),
+ .indexed16 => |data| std.mem.sliceAsBytes(data.indices),
+ .grayscale1 => |data| std.mem.sliceAsBytes(data),
+ .grayscale2 => |data| std.mem.sliceAsBytes(data),
+ .grayscale4 => |data| std.mem.sliceAsBytes(data),
+ .grayscale8 => |data| std.mem.sliceAsBytes(data),
+ .grayscale8Alpha => |data| std.mem.sliceAsBytes(data),
+ .grayscale16 => |data| std.mem.sliceAsBytes(data),
+ .grayscale16Alpha => |data| std.mem.sliceAsBytes(data),
+ .rgb24 => |data| std.mem.sliceAsBytes(data),
+ .rgba32 => |data| std.mem.sliceAsBytes(data),
+ .rgb565 => |data| std.mem.sliceAsBytes(data),
+ .rgb555 => |data| std.mem.sliceAsBytes(data),
+ .bgr555 => |data| std.mem.sliceAsBytes(data),
+ .bgr24 => |data| std.mem.sliceAsBytes(data),
+ .bgra32 => |data| std.mem.sliceAsBytes(data),
+ .rgb48 => |data| std.mem.sliceAsBytes(data),
+ .rgba64 => |data| std.mem.sliceAsBytes(data),
+ .float32 => |data| std.mem.sliceAsBytes(data),
+ };
+ }
+
+
+ pub fn slice(self: Self, begin: usize, end: usize) Self {
+ return switch (self) {
+ .invalid => .invalid,
+ .indexed1 => |data| .{ .indexed1 = .{ .palette = data.palette, .indices = data.indices[begin..end] } },
+ .indexed2 => |data| .{ .indexed2 = .{ .palette = data.palette, .indices = data.indices[begin..end] } },
+ .indexed4 => |data| .{ .indexed4 = .{ .palette = data.palette, .indices = data.indices[begin..end] } },
+ .indexed8 => |data| .{ .indexed8 = .{ .palette = data.palette, .indices = data.indices[begin..end] } },
+ .indexed16 => |data| .{ .indexed16 = .{ .palette = data.palette, .indices = data.indices[begin..end] } },
+ .grayscale1 => |data| .{ .grayscale1 = data[begin..end] },
+ .grayscale2 => |data| .{ .grayscale2 = data[begin..end] },
+ .grayscale4 => |data| .{ .grayscale4 = data[begin..end] },
+ .grayscale8 => |data| .{ .grayscale8 = data[begin..end] },
+ .grayscale8Alpha => |data| .{ .grayscale8Alpha = data[begin..end] },
+ .grayscale16 => |data| .{ .grayscale16 = data[begin..end] },
+ .grayscale16Alpha => |data| .{ .grayscale16Alpha = data[begin..end] },
+ .rgb24 => |data| .{ .rgb24 = data[begin..end] },
+ .rgba32 => |data| .{ .rgba32 = data[begin..end] },
+ .rgb565 => |data| .{ .rgb565 = data[begin..end] },
+ .rgb555 => |data| .{ .rgb555 = data[begin..end] },
+ .bgr555 => |data| .{ .bgr555 = data[begin..end] },
+ .bgr24 => |data| .{ .bgr24 = data[begin..end] },
+ .bgra32 => |data| .{ .bgra32 = data[begin..end] },
+ .rgb48 => |data| .{ .rgb48 = data[begin..end] },
+ .rgba64 => |data| .{ .rgba64 = data[begin..end] },
+ .float32 => |data| .{ .float32 = data[begin..end] },
+ };
+ }
+};
+
+pub const PixelStorageIterator = struct {
+ pixels: *const PixelStorage = undefined,
+ current_index: usize = 0,
+ end: usize = 0,
+
+ const Self = @This();
+
+ pub fn init(pixels: *const PixelStorage) Self {
+ return Self{
+ .pixels = pixels,
+ .end = pixels.len(),
+ };
+ }
+
+ pub fn next(self: *Self) ?Colorf32 {
+ if (self.current_index >= self.end) {
+ return null;
+ }
+
+ const result: ?Colorf32 = switch (self.pixels.*) {
+ .invalid => Colorf32.initRgb(0.0, 0.0, 0.0),
+ .indexed1 => |data| data.palette[data.indices[self.current_index]].toColorf32(),
+ .indexed2 => |data| data.palette[data.indices[self.current_index]].toColorf32(),
+ .indexed4 => |data| data.palette[data.indices[self.current_index]].toColorf32(),
+ .indexed8 => |data| data.palette[data.indices[self.current_index]].toColorf32(),
+ .indexed16 => |data| data.palette[data.indices[self.current_index]].toColorf32(),
+ .grayscale1 => |data| data[self.current_index].toColorf32(),
+ .grayscale2 => |data| data[self.current_index].toColorf32(),
+ .grayscale4 => |data| data[self.current_index].toColorf32(),
+ .grayscale8 => |data| data[self.current_index].toColorf32(),
+ .grayscale8Alpha => |data| data[self.current_index].toColorf32(),
+ .grayscale16 => |data| data[self.current_index].toColorf32(),
+ .grayscale16Alpha => |data| data[self.current_index].toColorf32(),
+ .rgb24 => |data| data[self.current_index].toColorf32(),
+ .rgba32 => |data| data[self.current_index].toColorf32(),
+ .rgb565 => |data| data[self.current_index].toColorf32(),
+ .rgb555 => |data| data[self.current_index].toColorf32(),
+ .bgr555 => |data| data[self.current_index].toColorf32(),
+ .bgr24 => |data| data[self.current_index].toColorf32(),
+ .bgra32 => |data| data[self.current_index].toColorf32(),
+ .rgb48 => |data| data[self.current_index].toColorf32(),
+ .rgba64 => |data| data[self.current_index].toColorf32(),
+ .float32 => |data| data[self.current_index],
+ };
+
+ self.current_index += 1;
+ return result;
+ }
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/compressions/lzw.zig.html b/docs/src/zigimg/src/compressions/lzw.zig.html
new file mode 100644
index 0000000..f8b302e
--- /dev/null
+++ b/docs/src/zigimg/src/compressions/lzw.zig.html
@@ -0,0 +1,295 @@
+
+
+
+
+
src/compressions/lzw.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const Image = @import("../Image.zig");
+
+
+
+pub fn Decoder(comptime endian: std.builtin.Endian) type {
+ return struct {
+ area_allocator: std.heap.ArenaAllocator,
+ code_size: u8 = 0,
+ clear_code: u13 = 0,
+ initial_code_size: u8 = 0,
+ end_information_code: u13 = 0,
+ next_code: u13 = 0,
+ previous_code: ?u13 = null,
+ dictionary: std.AutoArrayHashMap(u13, []const u8),
+
+ remaining_data: ?u13 = null,
+ remaining_bits: u4 = 0,
+
+ const MaxCodeSize = 12;
+
+ const Self = @This();
+
+ pub fn init(allocator: std.mem.Allocator, initial_code_size: u8) !Self {
+ var result = Self{
+ .area_allocator = std.heap.ArenaAllocator.init(allocator),
+ .code_size = initial_code_size,
+ .dictionary = std.AutoArrayHashMap(u13, []const u8).init(allocator),
+ .initial_code_size = initial_code_size,
+ .clear_code = @as(u13, 1) << @intCast(initial_code_size),
+ .end_information_code = (@as(u13, 1) << @intCast(initial_code_size)) + 1,
+ .next_code = (@as(u13, 1) << @intCast(initial_code_size)) + 2,
+ };
+
+
+
+ try result.resetDictionary();
+
+ return result;
+ }
+
+ pub fn deinit(self: *Self) void {
+ self.area_allocator.deinit();
+ self.dictionary.deinit();
+ }
+
+ pub fn decode(self: *Self, reader: Image.Stream.Reader, writer: anytype) !void {
+ var bit_reader = std.io.bitReader(endian, reader);
+
+ var bits_to_read = self.code_size + 1;
+
+ var read_size: usize = 0;
+ var read_code: u13 = 0;
+
+ if (self.remaining_data) |remaining_data| {
+ const rest_of_data = try bit_reader.readBits(u13, self.remaining_bits, &read_size);
+ if (read_size > 0) {
+ switch (endian) {
+ .little => {
+ read_code = remaining_data | (rest_of_data << @as(u4, @intCast(bits_to_read - self.remaining_bits)));
+ },
+ .big => {
+ read_code = (remaining_data << self.remaining_bits) | rest_of_data;
+ },
+ }
+ }
+ self.remaining_data = null;
+ } else {
+ read_code = try bit_reader.readBits(u13, bits_to_read, &read_size);
+ }
+
+ var allocator = self.area_allocator.allocator();
+
+ while (read_size > 0) {
+ if (self.dictionary.get(read_code)) |value| {
+ _ = try writer.write(value);
+
+ if (self.previous_code) |previous_code| {
+ if (self.dictionary.get(previous_code)) |previous_value| {
+ var new_value = try allocator.alloc(u8, previous_value.len + 1);
+ std.mem.copyForwards(u8, new_value, previous_value);
+ new_value[previous_value.len] = value[0];
+ try self.dictionary.put(self.next_code, new_value);
+
+ self.next_code += 1;
+
+ const max_code = @as(u13, 1) << @intCast(self.code_size + 1);
+ if (self.next_code == max_code and (self.code_size + 1) < MaxCodeSize) {
+ self.code_size += 1;
+ bits_to_read += 1;
+ }
+ }
+ }
+ } else {
+ if (read_code == self.clear_code) {
+ try self.resetDictionary();
+ bits_to_read = self.code_size + 1;
+ self.previous_code = read_code;
+ } else if (read_code == self.end_information_code) {
+ return;
+ } else {
+ if (self.previous_code) |previous_code| {
+ if (self.dictionary.get(previous_code)) |previous_value| {
+ var new_value = try allocator.alloc(u8, previous_value.len + 1);
+ std.mem.copyForwards(u8, new_value, previous_value);
+ new_value[previous_value.len] = previous_value[0];
+ try self.dictionary.put(self.next_code, new_value);
+
+ _ = try writer.write(new_value);
+
+ self.next_code += 1;
+
+ const max_code = @as(u13, 1) << @intCast(self.code_size + 1);
+ if (self.next_code == max_code and (self.code_size + 1) < MaxCodeSize) {
+ self.code_size += 1;
+ bits_to_read += 1;
+ }
+ }
+ }
+ }
+ }
+
+ self.previous_code = read_code;
+
+ read_code = try bit_reader.readBits(u13, bits_to_read, &read_size);
+ if (read_size != bits_to_read) {
+ self.remaining_data = read_code;
+ self.remaining_bits = @intCast(bits_to_read - read_size);
+ return;
+ }
+ }
+ }
+
+ fn resetDictionary(self: *Self) !void {
+ self.dictionary.clearRetainingCapacity();
+ self.area_allocator.deinit();
+
+ self.code_size = self.initial_code_size;
+ self.next_code = (@as(u13, 1) << @intCast(self.initial_code_size)) + 2;
+
+ self.area_allocator = std.heap.ArenaAllocator.init(self.area_allocator.child_allocator);
+ var allocator = self.area_allocator.allocator();
+
+ const roots_size = @as(usize, 1) << @intCast(self.code_size);
+
+ var index: u13 = 0;
+
+ while (index < roots_size) : (index += 1) {
+ var data = try allocator.alloc(u8, 1);
+ data[0] = @as(u8, @truncate(index));
+
+ try self.dictionary.put(index, data);
+ }
+ }
+ };
+}
+
+test "Should decode a simple LZW little-endian stream" {
+ const initial_code_size = 2;
+ const test_data = [_]u8{ 0x4c, 0x01 };
+
+ var reader = Image.Stream{
+ .const_buffer = std.io.fixedBufferStream(&test_data),
+ };
+
+ var out_data_storage: [256]u8 = undefined;
+ var out_data_buffer = Image.Stream{
+ .buffer = std.io.fixedBufferStream(&out_data_storage),
+ };
+
+ var lzw = try Decoder(.little).init(std.testing.allocator, initial_code_size);
+ defer lzw.deinit();
+
+ try lzw.decode(reader.reader(), out_data_buffer.writer());
+
+ try std.testing.expectEqual(@as(usize, 1), out_data_buffer.buffer.pos);
+ try std.testing.expectEqual(@as(u8, 1), out_data_storage[0]);
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/all.zig.html b/docs/src/zigimg/src/formats/all.zig.html
new file mode 100644
index 0000000..737c72b
--- /dev/null
+++ b/docs/src/zigimg/src/formats/all.zig.html
@@ -0,0 +1,142 @@
+
+
+
+
+
src/formats/all.zig - source view
+
+
+
+
+
+
pub const BMP = @import("bmp.zig").BMP;
+pub const GIF = @import("gif.zig").GIF;
+pub const JPEG = @import("jpeg.zig").JPEG;
+pub const PBM = @import("netpbm.zig").PBM;
+pub const PCX = @import("pcx.zig").PCX;
+pub const PGM = @import("netpbm.zig").PGM;
+pub const PNG = @import("png.zig").PNG;
+pub const PPM = @import("netpbm.zig").PPM;
+pub const QOI = @import("qoi.zig").QOI;
+pub const TGA = @import("tga.zig").TGA;
+pub const PAM = @import("pam.zig").PAM;
+
+pub const ImageEncoderOptions = union(@import("../Image.zig").Format) {
+ bmp: BMP.EncoderOptions,
+ gif: void,
+ jpg: void,
+ pbm: PBM.EncoderOptions,
+ pcx: PCX.EncoderOptions,
+ pgm: PGM.EncoderOptions,
+ png: PNG.EncoderOptions,
+ ppm: PPM.EncoderOptions,
+ qoi: QOI.EncoderOptions,
+ tga: TGA.EncoderOptions,
+ pam: PAM.EncoderOptions,
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/bmp.zig.html b/docs/src/zigimg/src/formats/bmp.zig.html
new file mode 100644
index 0000000..5e5b841
--- /dev/null
+++ b/docs/src/zigimg/src/formats/bmp.zig.html
@@ -0,0 +1,544 @@
+
+
+
+
+
src/formats/bmp.zig - source view
+
+
+
+
+
+
const buffered_stream_source = @import("../buffered_stream_source.zig");
+const color = @import("../color.zig");
+const FormatInterface = @import("../FormatInterface.zig");
+const Image = @import("../Image.zig");
+const PixelFormat = @import("../pixel_format.zig").PixelFormat;
+const std = @import("std");
+const utils = @import("../utils.zig");
+
+const BitmapMagicHeader = [_]u8{ 'B', 'M' };
+
+pub const BitmapFileHeader = extern struct {
+ magic_header: [2]u8 = BitmapMagicHeader,
+ size: u32 align(1) = 0,
+ reserved: u32 align(1) = 0,
+ pixel_offset: u32 align(1) = 0,
+};
+
+pub const CompressionMethod = enum(u32) {
+ none = 0,
+ rle8 = 1,
+ rle4 = 2,
+ bitfields = 3,
+ jpg = 4,
+ png = 5,
+ alpha_bit_fields = 6,
+ cmyk = 11,
+ cmyk_rle8 = 12,
+ cmyk_rle4 = 13,
+};
+
+pub const BitmapColorSpace = enum(u32) {
+ calibrated_rgb = 0,
+ srgb = utils.toMagicNumber("sRGB", .big),
+ windows_color_space = utils.toMagicNumber("Win ", .big),
+ profile_linked = utils.toMagicNumber("LINK", .big),
+ profile_embedded = utils.toMagicNumber("MBED", .big),
+};
+
+pub const BitmapIntent = enum(u32) {
+ business = 1,
+ graphics = 2,
+ images = 4,
+ absolute_colorimetric = 8,
+};
+
+pub const CieXyz = extern struct {
+ x: u32 = 0,
+
+ y: u32 = 0,
+ z: u32 = 0,
+};
+
+pub const CieXyzTriple = extern struct {
+ red: CieXyz = CieXyz{},
+ green: CieXyz = CieXyz{},
+ blue: CieXyz = CieXyz{},
+};
+
+pub const BitmapInfoHeaderWindows31 = extern struct {
+ header_size: u32 = 0,
+ width: i32 = 0,
+ height: i32 = 0,
+ color_plane: u16 = 0,
+ bit_count: u16 = 0,
+ compression_method: CompressionMethod = .none,
+ image_raw_size: u32 = 0,
+ horizontal_resolution: u32 = 0,
+ vertical_resolution: u32 = 0,
+ palette_size: u32 = 0,
+ important_colors: u32 = 0,
+
+ pub const HeaderSize = @sizeOf(BitmapInfoHeaderWindows31);
+};
+
+pub const BitmapInfoHeaderV4 = extern struct {
+ header_size: u32 = 0,
+ width: i32 = 0,
+ height: i32 = 0,
+ color_plane: u16 align(1) = 0,
+ bit_count: u16 align(1) = 0,
+ compression_method: CompressionMethod = .none,
+ image_raw_size: u32 = 0,
+ horizontal_resolution: u32 = 0,
+ vertical_resolution: u32 = 0,
+ palette_size: u32 = 0,
+ important_colors: u32 = 0,
+ red_mask: u32 = 0,
+ green_mask: u32 = 0,
+ blue_mask: u32 = 0,
+ alpha_mask: u32 = 0,
+ color_space: BitmapColorSpace = .srgb,
+ cie_end_points: CieXyzTriple = .{},
+ gamma_red: u32 = 0,
+ gamma_green: u32 = 0,
+ gamma_blue: u32 = 0,
+
+ pub const HeaderSize = @sizeOf(BitmapInfoHeaderV4);
+};
+
+pub const BitmapInfoHeaderV5 = extern struct {
+ header_size: u32 = 0,
+ width: i32 = 0,
+ height: i32 = 0,
+ color_plane: u16 align(1) = 0,
+ bit_count: u16 align(1) = 0,
+ compression_method: CompressionMethod = .none,
+ image_raw_size: u32 = 0,
+ horizontal_resolution: u32 = 0,
+ vertical_resolution: u32 = 0,
+ palette_size: u32 = 0,
+ important_colors: u32 = 0,
+ red_mask: u32 = 0,
+ green_mask: u32 = 0,
+ blue_mask: u32 = 0,
+ alpha_mask: u32 = 0,
+ color_space: BitmapColorSpace = .srgb,
+ cie_end_points: CieXyzTriple = .{},
+ gamma_red: u32 = 0,
+ gamma_green: u32 = 0,
+ gamma_blue: u32 = 0,
+ intent: BitmapIntent = .graphics,
+ profile_data: u32 = 0,
+ profile_size: u32 = 0,
+ reserved: u32 = 0,
+
+ pub const HeaderSize = @sizeOf(BitmapInfoHeaderV5);
+};
+
+pub const BitmapInfoHeader = union(enum) {
+ windows31: BitmapInfoHeaderWindows31,
+ v4: BitmapInfoHeaderV4,
+ v5: BitmapInfoHeaderV5,
+};
+
+
+
+
+
+const PixelsPerMeterResolution = 2835;
+
+pub const BMP = struct {
+ file_header: BitmapFileHeader = undefined,
+ info_header: BitmapInfoHeader = undefined,
+
+ pub const EncoderOptions = struct {};
+
+ pub fn formatInterface() FormatInterface {
+ return FormatInterface{
+ .format = format,
+ .formatDetect = formatDetect,
+ .readImage = readImage,
+ .writeImage = writeImage,
+ };
+ }
+
+ pub fn format() Image.Format {
+ return Image.Format.bmp;
+ }
+
+ pub fn formatDetect(stream: *Image.Stream) Image.Stream.ReadError!bool {
+ var magic_number_buffer: [2]u8 = undefined;
+ _ = try stream.read(magic_number_buffer[0..]);
+ if (std.mem.eql(u8, magic_number_buffer[0..], BitmapMagicHeader[0..])) {
+ return true;
+ }
+
+ return false;
+ }
+
+ pub fn readImage(allocator: std.mem.Allocator, stream: *Image.Stream) Image.ReadError!Image {
+ var result = Image.init(allocator);
+ errdefer result.deinit();
+
+ var bmp = BMP{};
+ const pixels = try bmp.read(allocator, stream);
+
+ result.width = @intCast(bmp.width());
+ result.height = @intCast(bmp.height());
+ result.pixels = pixels;
+
+ return result;
+ }
+
+ pub fn writeImage(allocator: std.mem.Allocator, stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) Image.WriteError!void {
+ var bmp = BMP{};
+
+
+
+ switch (image.pixels) {
+ .bgr24 => {
+ bmp.file_header = .{
+ .size = @intCast(image.width * image.height * 3 + @sizeOf(BitmapFileHeader) + BitmapInfoHeaderV4.HeaderSize),
+ .pixel_offset = @sizeOf(BitmapFileHeader) + BitmapInfoHeaderV4.HeaderSize,
+ };
+
+ bmp.info_header = .{
+ .v4 = .{
+ .header_size = BitmapInfoHeaderV4.HeaderSize,
+ .width = @intCast(image.width),
+ .height = @intCast(image.height),
+ .color_plane = 1,
+ .bit_count = 24,
+ .compression_method = .none,
+ .image_raw_size = @intCast(image.width * image.height * 3),
+ .horizontal_resolution = PixelsPerMeterResolution,
+ .vertical_resolution = PixelsPerMeterResolution,
+ .color_space = .srgb,
+ },
+ };
+ },
+ .bgra32 => {
+ bmp.file_header = .{
+ .size = @intCast(image.width * image.height * 4 + @sizeOf(BitmapFileHeader) + BitmapInfoHeaderV5.HeaderSize),
+ .pixel_offset = @sizeOf(BitmapFileHeader) + BitmapInfoHeaderV5.HeaderSize,
+ };
+
+ bmp.info_header = .{
+ .v5 = .{
+ .header_size = BitmapInfoHeaderV5.HeaderSize,
+ .width = @intCast(image.width),
+ .height = @intCast(image.height),
+ .color_plane = 1,
+ .bit_count = 32,
+ .compression_method = .bitfields,
+
+ .image_raw_size = @intCast(image.width * image.height * 4),
+ .horizontal_resolution = PixelsPerMeterResolution,
+ .vertical_resolution = PixelsPerMeterResolution,
+ .color_space = .srgb,
+ .red_mask = 0x0000FF00,
+ .green_mask = 0x00FF0000,
+ .blue_mask = 0xFF000000,
+ .alpha_mask = 0x000000FF,
+ },
+ };
+ },
+ else => {
+ return Image.WriteError.InvalidData;
+ },
+ }
+
+ try bmp.write(stream, image.pixels);
+
+ _ = allocator;
+ _ = encoder_options;
+ }
+
+ pub fn width(self: BMP) i32 {
+ return switch (self.info_header) {
+ .windows31 => |win31| {
+ return win31.width;
+ },
+ .v4 => |v4Header| {
+ return v4Header.width;
+ },
+ .v5 => |v5Header| {
+ return v5Header.width;
+ },
+ };
+ }
+
+ pub fn height(self: BMP) i32 {
+ return switch (self.info_header) {
+ .windows31 => |win31| {
+ return win31.height;
+ },
+ .v4 => |v4Header| {
+ return v4Header.height;
+ },
+ .v5 => |v5Header| {
+ return v5Header.height;
+ },
+ };
+ }
+
+ pub fn pixelFormat(self: BMP) Image.ReadError!PixelFormat {
+ return switch (self.info_header) {
+ .v4 => |v4Header| try findPixelFormat(v4Header.bit_count, v4Header.compression_method),
+ .v5 => |v5Header| try findPixelFormat(v5Header.bit_count, v5Header.compression_method),
+ else => return Image.Error.Unsupported,
+ };
+ }
+
+ pub fn read(self: *BMP, allocator: std.mem.Allocator, stream: *Image.Stream) Image.ReadError!color.PixelStorage {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);
+
+
+
+ const reader = buffered_stream.reader();
+ self.file_header = try utils.readStruct(reader, BitmapFileHeader, .little);
+ if (!std.mem.eql(u8, self.file_header.magic_header[0..], BitmapMagicHeader[0..])) {
+ return Image.ReadError.InvalidData;
+ }
+
+ const header_size = try reader.readInt(u32, .little);
+ try buffered_stream.seekBy(-@sizeOf(u32));
+
+
+
+ self.info_header = switch (header_size) {
+ BitmapInfoHeaderWindows31.HeaderSize => BitmapInfoHeader{ .windows31 = try utils.readStruct(reader, BitmapInfoHeaderWindows31, .little) },
+ BitmapInfoHeaderV4.HeaderSize => BitmapInfoHeader{ .v4 = try utils.readStruct(reader, BitmapInfoHeaderV4, .little) },
+ BitmapInfoHeaderV5.HeaderSize => BitmapInfoHeader{ .v5 = try utils.readStruct(reader, BitmapInfoHeaderV5, .little) },
+ else => return Image.Error.Unsupported,
+ };
+
+ var pixels: color.PixelStorage = undefined;
+
+
+
+ _ = switch (self.info_header) {
+ .v4 => |v4Header| {
+ const pixel_width = v4Header.width;
+ const pixel_height = v4Header.height;
+ const pixel_format = try findPixelFormat(v4Header.bit_count, v4Header.compression_method);
+
+ pixels = try color.PixelStorage.init(allocator, pixel_format, @intCast(pixel_width * pixel_height));
+ errdefer pixels.deinit(allocator);
+
+ try readPixels(reader, pixel_width, pixel_height, &pixels);
+ },
+ .v5 => |v5Header| {
+ const pixel_width = v5Header.width;
+ const pixel_height = v5Header.height;
+ const pixel_format = try findPixelFormat(v5Header.bit_count, v5Header.compression_method);
+
+ pixels = try color.PixelStorage.init(allocator, pixel_format, @intCast(pixel_width * pixel_height));
+ errdefer pixels.deinit(allocator);
+
+ try readPixels(reader, pixel_width, pixel_height, &pixels);
+ },
+ else => return Image.Error.Unsupported,
+ };
+
+ return pixels;
+ }
+
+ pub fn write(self: BMP, stream: *Image.Stream, pixels: color.PixelStorage) Image.WriteError!void {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceWriter(stream);
+
+ const writer = buffered_stream.writer();
+
+ try utils.writeStruct(writer, self.file_header, .little);
+
+ switch (self.info_header) {
+ .v4 => |v4| {
+ try utils.writeStruct(writer, v4, .little);
+ },
+ .v5 => |v5| {
+ try utils.writeStruct(writer, v5, .little);
+ },
+ else => {
+ return Image.WriteError.InvalidData;
+ },
+ }
+
+ try writePixels(writer, pixels, self.width(), self.height());
+
+ try buffered_stream.flush();
+ }
+
+ fn findPixelFormat(bit_count: u32, compression: CompressionMethod) Image.Error!PixelFormat {
+ if (bit_count == 32 and compression == CompressionMethod.bitfields) {
+ return PixelFormat.bgra32;
+ } else if (bit_count == 24 and compression == CompressionMethod.none) {
+ return PixelFormat.bgr24;
+ } else {
+ return Image.Error.Unsupported;
+ }
+ }
+
+ fn readPixels(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader, pixel_width: i32, pixel_height: i32, pixels: *color.PixelStorage) Image.ReadError!void {
+ return switch (pixels.*) {
+ .bgr24 => {
+ return readPixelsInternal(pixels.bgr24, reader, pixel_width, pixel_height);
+ },
+ .bgra32 => {
+ return readPixelsInternal(pixels.bgra32, reader, pixel_width, pixel_height);
+ },
+ else => {
+ return Image.Error.Unsupported;
+ },
+ };
+ }
+
+ fn readPixelsInternal(pixels: anytype, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader, pixel_width: i32, pixel_height: i32) Image.ReadError!void {
+ const ColorBufferType = @typeInfo(@TypeOf(pixels)).Pointer.child;
+
+ var x: i32 = 0;
+ var y: i32 = pixel_height - 1;
+ while (y >= 0) : (y -= 1) {
+ const scanline = y * pixel_width;
+
+ x = 0;
+ while (x < pixel_width) : (x += 1) {
+ pixels[@intCast(scanline + x)] = try utils.readStruct(reader, ColorBufferType, .little);
+ }
+ }
+ }
+
+ fn writePixels(writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, pixels: color.PixelStorage, pixel_width: i32, pixel_height: i32) Image.WriteError!void {
+ return switch (pixels) {
+ .bgr24 => {
+ return writePixelsInternal(pixels.bgr24, writer, pixel_width, pixel_height);
+ },
+ .bgra32 => {
+ return writePixelsInternal(pixels.bgra32, writer, pixel_width, pixel_height);
+ },
+ else => {
+ return Image.WriteError.InvalidData;
+ },
+ };
+ }
+
+ fn writePixelsInternal(pixels: anytype, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, pixel_width: i32, pixel_height: i32) Image.WriteError!void {
+ var x: i32 = 0;
+ var y: i32 = pixel_height - 1;
+ while (y >= 0) : (y -= 1) {
+ const scanline = y * pixel_width;
+
+ x = 0;
+ while (x < pixel_width) : (x += 1) {
+ try utils.writeStruct(writer, pixels[@intCast(scanline + x)], .little);
+ }
+ }
+ }
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/gif.zig.html b/docs/src/zigimg/src/formats/gif.zig.html
new file mode 100644
index 0000000..29e0735
--- /dev/null
+++ b/docs/src/zigimg/src/formats/gif.zig.html
@@ -0,0 +1,1150 @@
+
+
+
+
+
src/formats/gif.zig - source view
+
+
+
+
+
+
const buffered_stream_source = @import("../buffered_stream_source.zig");
+const color = @import("../color.zig");
+const FormatInterface = @import("../FormatInterface.zig");
+const Image = @import("../Image.zig");
+const lzw = @import("../compressions/lzw.zig");
+const PixelFormat = @import("../pixel_format.zig").PixelFormat;
+const std = @import("std");
+const utils = @import("../utils.zig");
+
+pub const HeaderFlags = packed struct {
+ global_color_table_size: u3 = 0,
+ sorted: bool = false,
+ color_resolution: u3 = 0,
+ use_global_color_table: bool = false,
+};
+
+pub const Header = extern struct {
+ magic: [3]u8 align(1) = undefined,
+ version: [3]u8 align(1) = undefined,
+ width: u16 align(1) = 0,
+ height: u16 align(1) = 0,
+ flags: HeaderFlags align(1) = .{},
+ background_color_index: u8 align(1) = 0,
+ pixel_aspect_ratio: u8 align(1) = 0,
+};
+
+pub const ImageDescriptorFlags = packed struct(u8) {
+ local_color_table_size: u3 = 0,
+ reserved: u2 = 0,
+ sort: bool = false,
+ is_interlaced: bool = false,
+ has_local_color_table: bool = false,
+};
+
+pub const ImageDescriptor = extern struct {
+ left_position: u16 align(1) = 0,
+ top_position: u16 align(1) = 0,
+ width: u16 align(1) = 0,
+ height: u16 align(1) = 0,
+ flags: ImageDescriptorFlags align(1) = .{},
+};
+
+pub const DisposeMethod = enum(u3) {
+ none = 0,
+ do_not_dispose = 1,
+ restore_background_color = 2,
+ restore_to_previous = 3,
+ _,
+};
+
+pub const GraphicControlExtensionFlags = packed struct(u8) {
+ has_transparent_color: bool = false,
+ user_input: bool = false,
+ disposal_method: DisposeMethod = .none,
+ reserved: u3 = 0,
+};
+
+pub const GraphicControlExtension = extern struct {
+ flags: GraphicControlExtensionFlags align(1) = .{},
+ delay_time: u16 align(1) = 0,
+ transparent_color_index: u8 align(1) = 0,
+};
+
+pub const CommentExtension = struct {
+ comment: []u8,
+
+ pub fn deinit(self: CommentExtension, allocator: std.mem.Allocator) void {
+ allocator.free(self.comment);
+ }
+};
+
+pub const ApplicationExtension = struct {
+ application_identifier: [8]u8,
+ authentification_code: [3]u8,
+ data: []u8,
+
+ pub fn deinit(self: ApplicationExtension, allocator: std.mem.Allocator) void {
+ allocator.free(self.data);
+ }
+};
+
+const DataBlockKind = enum((u8)) {
+ image_descriptor = 0x2c,
+ extension = 0x21,
+ end_of_file = 0x3b,
+};
+
+const ExtensionKind = enum(u8) {
+ graphic_control = 0xf9,
+ comment = 0xfe,
+ plain_text = 0x01,
+ application_extension = 0xff,
+};
+
+const Magic = "GIF";
+
+const Versions = [_][]const u8{
+ "87a",
+ "89a",
+};
+
+const ApplicationExtensions = struct {
+ identifier: []const u8,
+ code: []const u8,
+};
+const AnimationApplicationExtensions = [_]ApplicationExtensions{
+ .{
+ .identifier = "NETSCAPE",
+ .code = "2.0",
+ },
+ .{
+ .identifier = "ANIMEXTS",
+ .code = "1.0",
+ },
+};
+
+const ExtensionBlockTerminator = 0x00;
+
+const InterlacePasses = [_]struct { start: usize, step: usize }{
+ .{ .start = 0, .step = 8 },
+ .{ .start = 4, .step = 8 },
+ .{ .start = 2, .step = 4 },
+ .{ .start = 1, .step = 2 },
+};
+
+pub const GIF = struct {
+ header: Header = .{},
+ global_color_table: utils.FixedStorage(color.Rgb24, 256) = .{},
+ frames: std.ArrayListUnmanaged(FrameData) = .{},
+ comments: std.ArrayListUnmanaged(CommentExtension) = .{},
+ application_infos: std.ArrayListUnmanaged(ApplicationExtension) = .{},
+ allocator: std.mem.Allocator = undefined,
+
+ pub const SubImage = struct {
+ local_color_table: utils.FixedStorage(color.Rgb24, 256) = .{},
+ image_descriptor: ImageDescriptor = .{},
+ pixels: []u8 = &.{},
+
+ pub fn deinit(self: SubImage, allocator: std.mem.Allocator) void {
+ allocator.free(self.pixels);
+ }
+ };
+
+ pub const FrameData = struct {
+ graphics_control: ?GraphicControlExtension = null,
+ sub_images: std.ArrayListUnmanaged(SubImage) = .{},
+
+ pub fn deinit(self: *FrameData, allocator: std.mem.Allocator) void {
+ for (self.sub_images.items) |sub_image| {
+ sub_image.deinit(allocator);
+ }
+
+ self.sub_images.deinit(allocator);
+ }
+
+ pub fn allocNewSubImage(self: *FrameData, allocator: std.mem.Allocator) !*SubImage {
+ const new_sub_image = try self.sub_images.addOne(allocator);
+ new_sub_image.* = SubImage{};
+ return new_sub_image;
+ }
+ };
+
+ const ReaderContext = struct {
+ reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader = undefined,
+ current_frame_data: ?*FrameData = null,
+ has_animation_application_extension: bool = false,
+ };
+
+ pub fn init(allocator: std.mem.Allocator) GIF {
+ return .{
+ .allocator = allocator,
+ };
+ }
+
+ pub fn deinit(self: *GIF) void {
+ for (self.frames.items) |*frame| {
+ frame.deinit(self.allocator);
+ }
+
+ for (self.application_infos.items) |application_info| {
+ application_info.deinit(self.allocator);
+ }
+
+ for (self.comments.items) |comment| {
+ comment.deinit(self.allocator);
+ }
+
+ self.frames.deinit(self.allocator);
+ self.comments.deinit(self.allocator);
+ self.application_infos.deinit(self.allocator);
+ }
+
+ pub fn formatInterface() FormatInterface {
+ return FormatInterface{
+ .format = format,
+ .formatDetect = formatDetect,
+ .readImage = readImage,
+ .writeImage = writeImage,
+ };
+ }
+
+ pub fn format() Image.Format {
+ return Image.Format.gif;
+ }
+
+ pub fn formatDetect(stream: *Image.Stream) !bool {
+ var header_buffer: [6]u8 = undefined;
+ const read_bytes = try stream.read(header_buffer[0..]);
+ if (read_bytes < 6) {
+ return false;
+ }
+
+ for (Versions) |version| {
+ if (std.mem.eql(u8, header_buffer[0..Magic.len], Magic) and std.mem.eql(u8, header_buffer[Magic.len..], version)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ pub fn readImage(allocator: std.mem.Allocator, stream: *Image.Stream) Image.ReadError!Image {
+ var result = Image.init(allocator);
+ errdefer result.deinit();
+
+ var gif = GIF.init(allocator);
+ defer gif.deinit();
+
+ const frames = try gif.read(stream);
+ if (frames.items.len == 0) {
+ return Image.ReadError.InvalidData;
+ }
+
+ result.width = gif.header.width;
+ result.height = gif.header.height;
+ result.pixels = frames.items[0].pixels;
+ result.animation.frames = frames;
+ result.animation.loop_count = gif.loopCount();
+ return result;
+ }
+
+ pub fn writeImage(allocator: std.mem.Allocator, write_stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) Image.Stream.WriteError!void {
+ _ = allocator;
+ _ = write_stream;
+ _ = image;
+ _ = encoder_options;
+ }
+
+ pub fn loopCount(self: GIF) i32 {
+ for (self.application_infos.items) |application_info| {
+ for (AnimationApplicationExtensions) |anim_extension| {
+ if (std.mem.eql(u8, application_info.application_identifier[0..], anim_extension.identifier) and std.mem.eql(u8, application_info.authentification_code[0..], anim_extension.code)) {
+ const loop_count = std.mem.readPackedInt(u16, application_info.data[1..], 0, .little);
+ if (loop_count == 0) {
+ return Image.AnimationLoopInfinite;
+ }
+ return loop_count;
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ pub fn read(self: *GIF, stream: *Image.Stream) Image.ReadError!Image.Animation.FrameList {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);
+ var context = ReaderContext{
+ .reader = buffered_stream.reader(),
+ };
+
+ self.header = try utils.readStruct(context.reader, Header, .little);
+
+ if (!std.mem.eql(u8, self.header.magic[0..], Magic)) {
+ return Image.ReadError.InvalidData;
+ }
+
+ var valid_version = false;
+
+ for (Versions) |version| {
+ if (std.mem.eql(u8, self.header.version[0..], version)) {
+ valid_version = true;
+ break;
+ }
+ }
+
+ if (!valid_version) {
+ return Image.ReadError.InvalidData;
+ }
+
+ const global_color_table_size = @as(usize, 1) << (@as(u6, @intCast(self.header.flags.global_color_table_size)) + 1);
+
+ self.global_color_table.resize(global_color_table_size);
+
+ if (self.header.flags.use_global_color_table) {
+ var index: usize = 0;
+
+ while (index < global_color_table_size) : (index += 1) {
+ self.global_color_table.data[index] = try utils.readStruct(context.reader, color.Rgb24, .little);
+ }
+ }
+
+ try self.readData(&context);
+
+ return try self.render();
+ }
+
+
+
+ fn readData(self: *GIF, context: *ReaderContext) Image.ReadError!void {
+ var current_block = context.reader.readEnum(DataBlockKind, .little) catch {
+ return Image.ReadError.InvalidData;
+ };
+
+ while (current_block != .end_of_file) {
+ var is_graphic_block = false;
+ var extension_kind_opt: ?ExtensionKind = null;
+
+ switch (current_block) {
+ .image_descriptor => {
+ is_graphic_block = true;
+ },
+ .extension => {
+ extension_kind_opt = context.reader.readEnum(ExtensionKind, .little) catch blk: {
+ var dummy_byte = try context.reader.readByte();
+ while (dummy_byte != ExtensionBlockTerminator) {
+ dummy_byte = try context.reader.readByte();
+ }
+ break :blk null;
+ };
+
+ if (extension_kind_opt) |extension_kind| {
+ switch (extension_kind) {
+ .graphic_control => {
+ is_graphic_block = true;
+ },
+ .plain_text => {
+ is_graphic_block = true;
+ },
+ else => {},
+ }
+ } else {
+ current_block = context.reader.readEnum(DataBlockKind, .little) catch {
+ return Image.ReadError.InvalidData;
+ };
+ continue;
+ }
+ },
+ .end_of_file => {
+ return;
+ },
+ }
+
+ if (is_graphic_block) {
+ try self.readGraphicBlock(context, current_block, extension_kind_opt);
+ } else {
+ try self.readSpecialPurposeBlock(context, extension_kind_opt.?);
+ }
+
+ current_block = context.reader.readEnum(DataBlockKind, .little) catch {
+ return Image.ReadError.InvalidData;
+ };
+ }
+ }
+
+
+
+ fn readGraphicBlock(self: *GIF, context: *ReaderContext, block_kind: DataBlockKind, extension_kind_opt: ?ExtensionKind) Image.ReadError!void {
+ if (extension_kind_opt) |extension_kind| {
+ if (extension_kind == .graphic_control) {
+
+
+ context.current_frame_data = try self.allocNewFrame();
+
+ context.current_frame_data.?.graphics_control = blk: {
+ var graphics_control: GraphicControlExtension = undefined;
+
+
+
+ _ = try context.reader.readByte();
+
+ graphics_control.flags = try utils.readStruct(context.reader, GraphicControlExtensionFlags, .little);
+ graphics_control.delay_time = try context.reader.readInt(u16, .little);
+
+ if (graphics_control.flags.has_transparent_color) {
+ graphics_control.transparent_color_index = try context.reader.readByte();
+ } else {
+
+
+ _ = try context.reader.readByte();
+
+ graphics_control.transparent_color_index = 0;
+ }
+
+
+
+ _ = try context.reader.readByte();
+
+ break :blk graphics_control;
+ };
+
+ const new_block_kind = context.reader.readEnum(DataBlockKind, .little) catch {
+ return Image.ReadError.InvalidData;
+ };
+
+
+
+ try self.readGraphicRenderingBlock(context, new_block_kind, null);
+ } else if (extension_kind == .plain_text) {
+ try self.readGraphicRenderingBlock(context, block_kind, extension_kind_opt);
+ }
+ } else {
+ if (context.current_frame_data == null) {
+ context.current_frame_data = try self.allocNewFrame();
+ } else if (context.has_animation_application_extension) {
+ context.current_frame_data = try self.allocNewFrame();
+ }
+
+ try self.readGraphicRenderingBlock(context, block_kind, extension_kind_opt);
+ }
+ }
+
+
+
+ fn readGraphicRenderingBlock(self: *GIF, context: *ReaderContext, block_kind: DataBlockKind, extension_kind_opt: ?ExtensionKind) Image.ReadError!void {
+ switch (block_kind) {
+ .image_descriptor => {
+ try self.readImageDescriptorAndData(context);
+ },
+ .extension => {
+ var extension_kind: ExtensionKind = undefined;
+ if (extension_kind_opt) |value| {
+ extension_kind = value;
+ } else {
+ extension_kind = context.reader.readEnum(ExtensionKind, .little) catch {
+ return Image.ReadError.InvalidData;
+ };
+ }
+
+ switch (extension_kind) {
+ .plain_text => {
+
+
+ const block_size = try context.reader.readByte();
+ try context.reader.skipBytes(block_size, .{});
+
+ const sub_data_size = try context.reader.readByte();
+ try context.reader.skipBytes(sub_data_size + 1, .{});
+ },
+ else => {
+ return Image.ReadError.InvalidData;
+ },
+ }
+ },
+ .end_of_file => {
+ return;
+ },
+ }
+ }
+
+
+
+ fn readSpecialPurposeBlock(self: *GIF, context: *ReaderContext, extension_kind: ExtensionKind) Image.ReadError!void {
+ switch (extension_kind) {
+ .comment => {
+ var new_comment_entry = try self.comments.addOne(self.allocator);
+
+ var comment_list = try std.ArrayListUnmanaged(u8).initCapacity(self.allocator, 256);
+ defer comment_list.deinit(self.allocator);
+
+ var data_block_size = try context.reader.readByte();
+
+ while (data_block_size > 0) {
+ var data_block = utils.FixedStorage(u8, 256){};
+ data_block.resize(data_block_size);
+
+ _ = try context.reader.read(data_block.data[0..]);
+
+ try comment_list.appendSlice(self.allocator, data_block.data);
+
+ data_block_size = try context.reader.readByte();
+ }
+
+ new_comment_entry.comment = try self.allocator.dupe(u8, comment_list.items);
+ },
+ .application_extension => {
+ const new_application_info = blk: {
+ var application_info: ApplicationExtension = undefined;
+
+
+
+ _ = try context.reader.readByte();
+
+ _ = try context.reader.read(application_info.application_identifier[0..]);
+ _ = try context.reader.read(application_info.authentification_code[0..]);
+
+ var data_list = try std.ArrayListUnmanaged(u8).initCapacity(self.allocator, 256);
+ defer data_list.deinit(self.allocator);
+
+ var data_block_size = try context.reader.readByte();
+
+ while (data_block_size > 0) {
+ var data_block = utils.FixedStorage(u8, 256){};
+ data_block.resize(data_block_size);
+
+ _ = try context.reader.read(data_block.data[0..]);
+
+ try data_list.appendSlice(self.allocator, data_block.data);
+
+ data_block_size = try context.reader.readByte();
+ }
+
+ application_info.data = try self.allocator.dupe(u8, data_list.items);
+
+ break :blk application_info;
+ };
+
+ for (AnimationApplicationExtensions) |anim_extension| {
+ if (std.mem.eql(u8, new_application_info.application_identifier[0..], anim_extension.identifier) and std.mem.eql(u8, new_application_info.authentification_code[0..], anim_extension.code)) {
+ context.has_animation_application_extension = true;
+ break;
+ }
+ }
+
+ try self.application_infos.append(self.allocator, new_application_info);
+ },
+ else => {
+ return Image.ReadError.InvalidData;
+ },
+ }
+ }
+
+
+
+ fn readImageDescriptorAndData(self: *GIF, context: *ReaderContext) Image.ReadError!void {
+ if (context.current_frame_data) |current_frame_data| {
+ var sub_image = try current_frame_data.allocNewSubImage(self.allocator);
+ sub_image.image_descriptor = try utils.readStruct(context.reader, ImageDescriptor, .little);
+
+
+
+ if (sub_image.image_descriptor.width == 0 or sub_image.image_descriptor.height == 0) {
+ return;
+ }
+
+ const local_color_table_size = @as(usize, 1) << (@as(u6, @intCast(sub_image.image_descriptor.flags.local_color_table_size)) + 1);
+
+ sub_image.local_color_table.resize(local_color_table_size);
+
+ if (sub_image.image_descriptor.flags.has_local_color_table) {
+ var index: usize = 0;
+
+ while (index < local_color_table_size) : (index += 1) {
+ sub_image.local_color_table.data[index] = try utils.readStruct(context.reader, color.Rgb24, .little);
+ }
+ }
+
+ sub_image.pixels = try self.allocator.alloc(u8, @as(usize, sub_image.image_descriptor.height) * @as(usize, sub_image.image_descriptor.width));
+ var pixels_buffer = std.io.fixedBufferStream(sub_image.pixels);
+
+ const lzw_minimum_code_size = try context.reader.readByte();
+
+ if (lzw_minimum_code_size == @intFromEnum(DataBlockKind.end_of_file)) {
+ return Image.ReadError.InvalidData;
+ }
+
+ var lzw_decoder = try lzw.Decoder(.little).init(self.allocator, lzw_minimum_code_size);
+ defer lzw_decoder.deinit();
+
+ var data_block_size = try context.reader.readByte();
+
+ while (data_block_size > 0) {
+ var data_block = utils.FixedStorage(u8, 256){};
+ data_block.resize(data_block_size);
+
+ _ = try context.reader.read(data_block.data[0..]);
+
+ var data_block_reader = Image.Stream{
+ .buffer = std.io.fixedBufferStream(data_block.data),
+ };
+
+ lzw_decoder.decode(data_block_reader.reader(), pixels_buffer.writer()) catch |err| {
+ if (err != error.NoSpaceLeft) {
+ return Image.ReadError.InvalidData;
+ }
+ };
+
+ data_block_size = try context.reader.readByte();
+ }
+ }
+ }
+
+ fn render(self: *GIF) Image.ReadError!Image.Animation.FrameList {
+ const final_pixel_format = self.findBestPixelFormat();
+
+ var frame_list = Image.Animation.FrameList{};
+
+ if (self.frames.items.len == 0) {
+ var current_animation_frame = try self.createNewAnimationFrame(final_pixel_format);
+ fillPalette(¤t_animation_frame, self.global_color_table.data, null);
+ fillWithBackgroundColor(¤t_animation_frame, self.global_color_table.data, self.header.background_color_index);
+ try frame_list.append(self.allocator, current_animation_frame);
+ return frame_list;
+ }
+
+ var canvas = try self.createNewAnimationFrame(final_pixel_format);
+ defer canvas.deinit(self.allocator);
+
+ var previous_canvas = try self.createNewAnimationFrame(final_pixel_format);
+ defer previous_canvas.deinit(self.allocator);
+
+ if (self.header.flags.use_global_color_table) {
+ fillPalette(&canvas, self.global_color_table.data, null);
+ fillWithBackgroundColor(&canvas, self.global_color_table.data, self.header.background_color_index);
+
+ copyFrame(&canvas, &previous_canvas);
+ }
+
+ var has_graphic_control = false;
+ for (self.frames.items) |frame| {
+ if (frame.graphics_control != null) {
+ has_graphic_control = true;
+ break;
+ }
+ }
+
+ for (self.frames.items) |frame| {
+ var current_animation_frame = try self.createNewAnimationFrame(final_pixel_format);
+
+ var transparency_index_opt: ?u8 = null;
+
+ var dispose_method: DisposeMethod = .none;
+
+ if (frame.graphics_control) |graphics_control| {
+ current_animation_frame.duration = @as(f32, @floatFromInt(graphics_control.delay_time)) * (1.0 / 100.0);
+ if (graphics_control.flags.has_transparent_color) {
+ transparency_index_opt = graphics_control.transparent_color_index;
+ }
+
+ dispose_method = graphics_control.flags.disposal_method;
+ }
+
+ if (self.header.flags.use_global_color_table) {
+ fillPalette(¤t_animation_frame, self.global_color_table.data, transparency_index_opt);
+ }
+
+ for (frame.sub_images.items) |sub_image| {
+ const effective_color_table = if (sub_image.image_descriptor.flags.has_local_color_table) sub_image.local_color_table.data else self.global_color_table.data;
+
+ if (sub_image.image_descriptor.flags.has_local_color_table) {
+ fillPalette(¤t_animation_frame, effective_color_table, transparency_index_opt);
+ }
+
+ self.renderSubImage(&sub_image, &canvas, effective_color_table, transparency_index_opt);
+ }
+
+ copyFrame(&canvas, ¤t_animation_frame);
+
+ if (!has_graphic_control or (has_graphic_control and frame.graphics_control != null)) {
+ try frame_list.append(self.allocator, current_animation_frame);
+ } else {
+ current_animation_frame.deinit(self.allocator);
+ }
+
+ switch (dispose_method) {
+ .restore_to_previous => {
+ copyFrame(&previous_canvas, &canvas);
+ },
+ .restore_background_color => {
+ for (frame.sub_images.items) |sub_image| {
+ const effective_color_table = if (sub_image.image_descriptor.flags.has_local_color_table) sub_image.local_color_table.data else self.global_color_table.data;
+
+ self.replaceWithBackground(&sub_image, &canvas, effective_color_table, transparency_index_opt);
+ }
+
+ copyFrame(&canvas, &previous_canvas);
+ },
+ else => {
+ copyFrame(&canvas, &previous_canvas);
+ },
+ }
+ }
+
+ return frame_list;
+ }
+
+ fn fillPalette(current_frame: *Image.AnimationFrame, effective_color_table: []const color.Rgb24, transparency_index_opt: ?u8) void {
+
+
+ _ = transparency_index_opt;
+
+ switch (current_frame.pixels) {
+ .indexed1 => |pixels| {
+ for (0..@min(effective_color_table.len, pixels.palette.len)) |index| {
+ pixels.palette[index] = color.Rgba32.fromU32Rgb(effective_color_table[index].toU32Rgb());
+ }
+ },
+ .indexed2 => |pixels| {
+ for (0..@min(effective_color_table.len, pixels.palette.len)) |index| {
+ pixels.palette[index] = color.Rgba32.fromU32Rgb(effective_color_table[index].toU32Rgb());
+ }
+ },
+ .indexed4 => |pixels| {
+ for (0..@min(effective_color_table.len, pixels.palette.len)) |index| {
+ pixels.palette[index] = color.Rgba32.fromU32Rgb(effective_color_table[index].toU32Rgb());
+ }
+ },
+ .indexed8 => |pixels| {
+ for (0..@min(effective_color_table.len, pixels.palette.len)) |index| {
+ pixels.palette[index] = color.Rgba32.fromU32Rgb(effective_color_table[index].toU32Rgb());
+ }
+ },
+ else => {},
+ }
+ }
+
+ fn fillWithBackgroundColor(current_frame: *Image.AnimationFrame, effective_color_table: []const color.Rgb24, background_color_index: u8) void {
+ if (background_color_index >= effective_color_table.len) {
+ return;
+ }
+
+ switch (current_frame.pixels) {
+ .indexed1 => |pixels| @memset(pixels.indices, @intCast(background_color_index)),
+ .indexed2 => |pixels| @memset(pixels.indices, @intCast(background_color_index)),
+ .indexed4 => |pixels| @memset(pixels.indices, @intCast(background_color_index)),
+ .indexed8 => |pixels| @memset(pixels.indices, background_color_index),
+ .rgb24 => |pixels| @memset(pixels, effective_color_table[background_color_index]),
+ .rgba32 => |pixels| @memset(pixels, color.Rgba32.fromU32Rgba(effective_color_table[background_color_index].toU32Rgb())),
+ else => std.debug.panic("Pixel format {s} not supported", .{@tagName(current_frame.pixels)}),
+ }
+ }
+
+ fn copyFrame(source: *Image.AnimationFrame, target: *Image.AnimationFrame) void {
+ switch (target.pixels) {
+ .indexed1 => |pixels| @memcpy(pixels.indices, source.pixels.indexed1.indices),
+ .indexed2 => |pixels| @memcpy(pixels.indices, source.pixels.indexed2.indices),
+ .indexed4 => |pixels| @memcpy(pixels.indices, source.pixels.indexed4.indices),
+ .indexed8 => |pixels| @memcpy(pixels.indices, source.pixels.indexed8.indices),
+ .rgb24 => |pixels| @memcpy(pixels, source.pixels.rgb24),
+ .rgba32 => |pixels| @memcpy(pixels, source.pixels.rgba32),
+ else => std.debug.panic("Pixel format {s} not supported", .{@tagName(target.pixels)}),
+ }
+ }
+
+ fn replaceWithBackground(self: *const GIF, sub_image: *const SubImage, canvas: *Image.AnimationFrame, effective_color_table: []const color.Rgb24, transparency_index_opt: ?u8) void {
+ const background_color_index = if (transparency_index_opt != null) transparency_index_opt.? else self.header.background_color_index;
+
+ for (0..sub_image.image_descriptor.height) |source_y| {
+ const target_y = source_y + sub_image.image_descriptor.top_position;
+
+ const source_stride = source_y * sub_image.image_descriptor.width;
+ const target_stride = target_y * self.header.width;
+
+ for (0..sub_image.image_descriptor.width) |source_x| {
+ const target_x = source_x + sub_image.image_descriptor.left_position;
+
+ const source_index = source_stride + source_x;
+ const target_index = target_stride + target_x;
+
+ if (source_index >= sub_image.pixels.len) {
+ continue;
+ }
+
+ switch (canvas.pixels) {
+ .indexed1 => |pixels| {
+ if (target_index >= pixels.indices.len) {
+ return;
+ }
+
+ pixels.indices[target_index] = @intCast(background_color_index);
+ },
+ .indexed2 => |pixels| {
+ if (target_index >= pixels.indices.len) {
+ return;
+ }
+
+ pixels.indices[target_index] = @intCast(background_color_index);
+ },
+ .indexed4 => |pixels| {
+ if (target_index >= pixels.indices.len) {
+ return;
+ }
+
+ pixels.indices[target_index] = @intCast(background_color_index);
+ },
+ .indexed8 => |pixels| {
+ if (target_index >= pixels.indices.len) {
+ return;
+ }
+
+ pixels.indices[target_index] = background_color_index;
+ },
+ .rgb24 => |pixels| {
+ if (target_index >= pixels.len) {
+ return;
+ }
+
+ if (background_color_index < effective_color_table.len) {
+ pixels[target_index] = effective_color_table[background_color_index];
+ }
+ },
+ .rgba32 => |pixels| {
+ if (target_index >= pixels.len) {
+ return;
+ }
+
+ if (background_color_index < effective_color_table.len) {
+ pixels[target_index] = color.Rgba32.fromU32Rgba(effective_color_table[background_color_index].toU32Rgba());
+ }
+ },
+ else => {
+ std.debug.panic("Pixel format {s} not supported", .{@tagName(canvas.pixels)});
+ },
+ }
+ }
+ }
+ }
+
+ fn renderSubImage(self: *const GIF, sub_image: *const SubImage, current_frame: *Image.AnimationFrame, effective_color_table: []const color.Rgb24, transparency_index_opt: ?u8) void {
+ if (sub_image.image_descriptor.flags.is_interlaced) {
+ var source_y: usize = 0;
+
+ for (InterlacePasses) |pass| {
+ var target_y = pass.start + sub_image.image_descriptor.top_position;
+
+ while (target_y < self.header.height) {
+ const source_stride = source_y * sub_image.image_descriptor.width;
+ const target_stride = target_y * self.header.width;
+
+ for (0..sub_image.image_descriptor.width) |source_x| {
+ const target_x = source_x + sub_image.image_descriptor.left_position;
+
+ const source_index = source_stride + source_x;
+ const target_index = target_stride + target_x;
+
+ plotPixel(sub_image, current_frame, effective_color_table, transparency_index_opt, source_index, target_index);
+ }
+
+ target_y += pass.step;
+ source_y += 1;
+ }
+ }
+ } else {
+ for (0..sub_image.image_descriptor.height) |source_y| {
+ const target_y = source_y + sub_image.image_descriptor.top_position;
+
+ const source_stride = source_y * sub_image.image_descriptor.width;
+ const target_stride = target_y * self.header.width;
+
+ for (0..sub_image.image_descriptor.width) |source_x| {
+ const target_x = source_x + sub_image.image_descriptor.left_position;
+
+ const source_index = source_stride + source_x;
+ const target_index = target_stride + target_x;
+
+ plotPixel(sub_image, current_frame, effective_color_table, transparency_index_opt, source_index, target_index);
+ }
+ }
+ }
+ }
+
+ fn plotPixel(sub_image: *const SubImage, current_frame: *Image.AnimationFrame, effective_color_table: []const color.Rgb24, transparency_index_opt: ?u8, source_index: usize, target_index: usize) void {
+ if (source_index >= sub_image.pixels.len) {
+ return;
+ }
+
+ switch (current_frame.pixels) {
+ .indexed1 => |pixels| {
+ if (target_index >= pixels.indices.len) {
+ return;
+ }
+
+ if (transparency_index_opt) |transparency_index| {
+ if (sub_image.pixels[source_index] == transparency_index) {
+ return;
+ }
+ }
+
+ pixels.indices[target_index] = @truncate(sub_image.pixels[source_index]);
+ },
+ .indexed2 => |pixels| {
+ if (target_index >= pixels.indices.len) {
+ return;
+ }
+
+ if (transparency_index_opt) |transparency_index| {
+ if (sub_image.pixels[source_index] == transparency_index) {
+ return;
+ }
+ }
+
+ pixels.indices[target_index] = @truncate(sub_image.pixels[source_index]);
+ },
+ .indexed4 => |pixels| {
+ if (target_index >= pixels.indices.len) {
+ return;
+ }
+
+ if (transparency_index_opt) |transparency_index| {
+ if (sub_image.pixels[source_index] == transparency_index) {
+ return;
+ }
+ }
+
+ pixels.indices[target_index] = @truncate(sub_image.pixels[source_index]);
+ },
+ .indexed8 => |pixels| {
+ if (target_index >= pixels.indices.len) {
+ return;
+ }
+
+ if (transparency_index_opt) |transparency_index| {
+ if (sub_image.pixels[source_index] == transparency_index) {
+ return;
+ }
+ }
+
+ pixels.indices[target_index] = @intCast(sub_image.pixels[source_index]);
+ },
+ .rgb24 => |pixels| {
+ if (target_index >= pixels.len) {
+ return;
+ }
+
+ if (transparency_index_opt) |transparency_index| {
+ if (sub_image.pixels[source_index] == transparency_index) {
+ return;
+ }
+ }
+
+ const pixel_index = sub_image.pixels[source_index];
+ if (pixel_index < effective_color_table.len) {
+ pixels[target_index] = effective_color_table[pixel_index];
+ }
+ },
+ .rgba32 => |pixels| {
+ if (target_index >= pixels.len) {
+ return;
+ }
+
+ if (transparency_index_opt) |transparency_index| {
+ if (sub_image.pixels[source_index] == transparency_index) {
+ return;
+ }
+ }
+
+ const pixel_index = sub_image.pixels[source_index];
+ if (pixel_index < effective_color_table.len) {
+ pixels[target_index] = color.Rgba32.fromU32Rgba(effective_color_table[pixel_index].toU32Rgba());
+ }
+ },
+ else => {
+ std.debug.panic("Pixel format {s} not supported", .{@tagName(current_frame.pixels)});
+ },
+ }
+ }
+
+ fn allocNewFrame(self: *GIF) !*FrameData {
+ const new_frame = try self.frames.addOne(self.allocator);
+ new_frame.* = FrameData{};
+ return new_frame;
+ }
+
+ fn createNewAnimationFrame(self: *const GIF, pixel_format: PixelFormat) !Image.AnimationFrame {
+ const new_frame = Image.AnimationFrame{
+ .pixels = try color.PixelStorage.init(self.allocator, pixel_format, @as(usize, @intCast(self.header.width)) * @as(usize, @intCast(self.header.height))),
+ .duration = 0.0,
+ };
+
+
+
+ switch (new_frame.pixels) {
+ .indexed1 => |pixels| @memset(pixels.indices, 0),
+ .indexed2 => |pixels| @memset(pixels.indices, 0),
+ .indexed4 => |pixels| @memset(pixels.indices, 0),
+ .indexed8 => |pixels| @memset(pixels.indices, 0),
+ .rgb24 => |pixels| @memset(pixels, color.Rgb24.fromU32Rgb(0)),
+ .rgba32 => |pixels| @memset(pixels, color.Rgba32.fromU32Rgba(0)),
+ else => std.debug.panic("Pixel format {} not supported", .{pixel_format}),
+ }
+
+ return new_frame;
+ }
+
+ fn findBestPixelFormat(self: *const GIF) PixelFormat {
+ var total_color_count: usize = 0;
+
+ if (self.header.flags.use_global_color_table) {
+ total_color_count = @as(usize, 1) << (@as(u6, @intCast(self.header.flags.global_color_table_size)) + 1);
+ }
+
+ var use_transparency: bool = false;
+
+ var max_color_per_frame: usize = 0;
+
+ for (self.frames.items) |frame| {
+ if (frame.graphics_control) |graphic_control| {
+ if (graphic_control.flags.has_transparent_color) {
+ use_transparency = true;
+ }
+ }
+
+ var color_per_frame: usize = 0;
+
+ for (frame.sub_images.items) |sub_image| {
+ if (sub_image.image_descriptor.flags.has_local_color_table) {
+ color_per_frame += @as(usize, 1) << (@as(u6, @intCast(sub_image.image_descriptor.flags.local_color_table_size)) + 1);
+ }
+ }
+
+ max_color_per_frame = @max(max_color_per_frame, color_per_frame);
+ }
+
+ total_color_count += max_color_per_frame;
+
+
+
+ if (total_color_count <= (1 << 1)) {
+ return .indexed1;
+ } else if (total_color_count <= (1 << 2)) {
+ return .indexed2;
+ } else if (total_color_count <= (1 << 4)) {
+ return .indexed4;
+ } else if (total_color_count <= (1 << 8)) {
+ return .indexed8;
+ }
+
+ if (use_transparency) {
+ return .rgba32;
+ }
+
+ return .rgb24;
+ }
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/jpeg.zig.html b/docs/src/zigimg/src/formats/jpeg.zig.html
new file mode 100644
index 0000000..0b955c1
--- /dev/null
+++ b/docs/src/zigimg/src/formats/jpeg.zig.html
@@ -0,0 +1,366 @@
+
+
+
+
+
src/formats/jpeg.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const buffered_stream_source = @import("../buffered_stream_source.zig");
+
+const Allocator = std.mem.Allocator;
+
+const ImageError = Image.Error;
+const ImageReadError = Image.ReadError;
+const ImageWriteError = Image.WriteError;
+const Image = @import("../Image.zig");
+const FormatInterface = @import("../FormatInterface.zig");
+const color = @import("../color.zig");
+const PixelFormat = @import("../pixel_format.zig").PixelFormat;
+
+const FrameHeader = @import("./jpeg/FrameHeader.zig");
+const JFIFHeader = @import("./jpeg/JFIFHeader.zig");
+
+const Markers = @import("./jpeg/utils.zig").Markers;
+const ZigzagOffsets = @import("./jpeg/utils.zig").ZigzagOffsets;
+const IDCTMultipliers = @import("./jpeg/utils.zig").IDCTMultipliers;
+const QuantizationTable = @import("./jpeg/quantization.zig").Table;
+
+const HuffmanReader = @import("./jpeg/huffman.zig").Reader;
+const HuffmanTable = @import("./jpeg/huffman.zig").Table;
+const Frame = @import("./jpeg/Frame.zig");
+const Scan = @import("./jpeg/Scan.zig");
+
+
+
+
+
+
+
+
+
+
+
+
+
+const JPEG_DEBUG = false;
+
+pub const JPEG = struct {
+ frame: ?Frame = null,
+ allocator: Allocator,
+ quantization_tables: [4]?QuantizationTable,
+
+ pub fn init(allocator: Allocator) JPEG {
+ return .{
+ .allocator = allocator,
+ .quantization_tables = [_]?QuantizationTable{null} ** 4,
+ };
+ }
+
+ pub fn deinit(self: *JPEG) void {
+ if (self.frame) |*frame| {
+ frame.deinit();
+ }
+ }
+
+ fn parseDefineQuantizationTables(self: *JPEG, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!void {
+ var segment_size = try reader.readInt(u16, .big);
+ if (JPEG_DEBUG) std.debug.print("DefineQuantizationTables: segment size = 0x{X}\n", .{segment_size});
+ segment_size -= 2;
+
+ while (segment_size > 0) {
+ const precision_and_destination = try reader.readByte();
+ const table_precision = precision_and_destination >> 4;
+ const table_destination = precision_and_destination & 0b11;
+
+ const quantization_table = try QuantizationTable.read(table_precision, reader);
+ switch (quantization_table) {
+ .q8 => segment_size -= 64 + 1,
+ .q16 => segment_size -= 128 + 1,
+ }
+
+ self.quantization_tables[table_destination] = quantization_table;
+ if (JPEG_DEBUG) std.debug.print(" Table with precision {} installed at {}\n", .{ table_precision, table_destination });
+ }
+ }
+
+ fn parseScan(self: *JPEG, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader, pixels_opt: *?color.PixelStorage) ImageReadError!void {
+ if (self.frame) |frame| {
+ try Scan.performScan(&frame, reader, pixels_opt);
+ } else return ImageReadError.InvalidData;
+ }
+
+ fn initializePixels(self: *JPEG, pixels_opt: *?color.PixelStorage) ImageReadError!void {
+ if (self.frame) |frame| {
+ var pixel_format: PixelFormat = undefined;
+ switch (frame.frame_header.components.len) {
+ 1 => pixel_format = .grayscale8,
+ 3 => pixel_format = .rgb24,
+ else => unreachable,
+ }
+
+ const pixel_count = @as(usize, @intCast(frame.frame_header.samples_per_row)) * @as(usize, @intCast(frame.frame_header.row_count));
+ pixels_opt.* = try color.PixelStorage.init(self.allocator, pixel_format, pixel_count);
+ } else return ImageReadError.InvalidData;
+ }
+
+ pub fn read(self: *JPEG, stream: *Image.Stream, pixels_opt: *?color.PixelStorage) ImageReadError!Frame {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);
+
+ const jfif_header = JFIFHeader.read(&buffered_stream) catch |err| switch (err) {
+ error.App0MarkerDoesNotExist, error.JfifIdentifierNotSet, error.ThumbnailImagesUnsupported, error.ExtraneousApplicationMarker => return ImageReadError.InvalidData,
+ else => |e| return e,
+ };
+ _ = jfif_header;
+
+ errdefer {
+ if (pixels_opt.*) |pixels| {
+ pixels.deinit(self.allocator);
+ pixels_opt.* = null;
+ }
+ }
+
+ const reader = buffered_stream.reader();
+ var marker = try reader.readInt(u16, .big);
+ while (marker != @intFromEnum(Markers.end_of_image)) : (marker = try reader.readInt(u16, .big)) {
+ if (JPEG_DEBUG) std.debug.print("Parsing marker value: 0x{X}\n", .{marker});
+
+ if (marker >= @intFromEnum(Markers.application0) and marker < @intFromEnum(Markers.application0) + 16) {
+ if (JPEG_DEBUG) std.debug.print("Skipping application data segment\n", .{});
+ const application_data_length = try reader.readInt(u16, .big);
+ try buffered_stream.seekBy(application_data_length - 2);
+ continue;
+ }
+
+ switch (@as(Markers, @enumFromInt(marker))) {
+
+
+
+
+
+
+ .sof0 => {
+
+ if (self.frame != null) {
+ return ImageError.Unsupported;
+ }
+
+ self.frame = try Frame.read(self.allocator, &self.quantization_tables, &buffered_stream);
+ },
+
+ .sof1 => return ImageError.Unsupported,
+
+ .sof2 => return ImageError.Unsupported,
+
+ .sof3 => return ImageError.Unsupported,
+
+ .sof5 => return ImageError.Unsupported,
+ .sof6 => return ImageError.Unsupported,
+ .sof7 => return ImageError.Unsupported,
+ .sof9 => return ImageError.Unsupported,
+
+ .sof10 => return ImageError.Unsupported,
+
+ .sof11 => return ImageError.Unsupported,
+
+ .sof13 => return ImageError.Unsupported,
+ .sof14 => return ImageError.Unsupported,
+ .sof15 => return ImageError.Unsupported,
+
+ .start_of_scan => {
+ try self.initializePixels(pixels_opt);
+ try self.parseScan(reader, pixels_opt);
+ },
+
+ .define_quantization_tables => {
+ try self.parseDefineQuantizationTables(reader);
+ },
+
+ .comment => {
+ if (JPEG_DEBUG) std.debug.print("Skipping comment segment\n", .{});
+
+ const comment_length = try reader.readInt(u16, .big);
+ try buffered_stream.seekBy(comment_length - 2);
+ },
+
+ else => {
+
+
+ return ImageReadError.InvalidData;
+ },
+ }
+ }
+
+ return if (self.frame) |frame| frame else ImageReadError.InvalidData;
+ }
+
+
+
+ pub fn formatInterface() FormatInterface {
+ return FormatInterface{
+ .format = format,
+ .formatDetect = formatDetect,
+ .readImage = readImage,
+ .writeImage = writeImage,
+ };
+ }
+
+ fn format() Image.Format {
+ return Image.Format.jpg;
+ }
+
+ fn formatDetect(stream: *Image.Stream) ImageReadError!bool {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);
+
+ const reader = buffered_stream.reader();
+ const maybe_start_of_image = try reader.readInt(u16, .big);
+ if (maybe_start_of_image != @intFromEnum(Markers.start_of_image)) {
+ return false;
+ }
+
+ try buffered_stream.seekTo(6);
+ var identifier_buffer: [4]u8 = undefined;
+ _ = try buffered_stream.read(identifier_buffer[0..]);
+
+ return std.mem.eql(u8, identifier_buffer[0..], "JFIF");
+ }
+
+ fn readImage(allocator: Allocator, stream: *Image.Stream) ImageReadError!Image {
+ var result = Image.init(allocator);
+ errdefer result.deinit();
+ var jpeg = JPEG.init(allocator);
+ defer jpeg.deinit();
+
+ var pixels_opt: ?color.PixelStorage = null;
+
+ const frame = try jpeg.read(stream, &pixels_opt);
+
+ result.width = frame.frame_header.samples_per_row;
+ result.height = frame.frame_header.row_count;
+
+ if (pixels_opt) |pixels| {
+ result.pixels = pixels;
+ } else {
+ return ImageReadError.InvalidData;
+ }
+
+ return result;
+ }
+
+ fn writeImage(allocator: Allocator, write_stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) ImageWriteError!void {
+ _ = allocator;
+ _ = write_stream;
+ _ = image;
+ _ = encoder_options;
+ }
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/jpeg/Frame.zig.html b/docs/src/zigimg/src/formats/jpeg/Frame.zig.html
new file mode 100644
index 0000000..1c7ccd0
--- /dev/null
+++ b/docs/src/zigimg/src/formats/jpeg/Frame.zig.html
@@ -0,0 +1,375 @@
+
+
+
+
+
src/formats/jpeg/Frame.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const Allocator = std.mem.Allocator;
+
+const buffered_stream_source = @import("../../buffered_stream_source.zig");
+const Image = @import("../../Image.zig");
+const ImageReadError = Image.ReadError;
+
+const Markers = @import("utils.zig").Markers;
+const FrameHeader = @import("FrameHeader.zig");
+const QuantizationTable = @import("quantization.zig").Table;
+const HuffmanTable = @import("huffman.zig").Table;
+const color = @import("../../color.zig");
+
+const IDCTMultipliers = @import("utils.zig").IDCTMultipliers;
+const MAX_COMPONENTS = @import("utils.zig").MAX_COMPONENTS;
+const MAX_BLOCKS = @import("utils.zig").MAX_BLOCKS;
+const MCU = @import("utils.zig").MCU;
+
+const Self = @This();
+allocator: Allocator,
+frame_header: FrameHeader,
+quantization_tables: *[4]?QuantizationTable,
+dc_huffman_tables: [2]?HuffmanTable,
+ac_huffman_tables: [2]?HuffmanTable,
+
+const JPEG_DEBUG = false;
+
+pub fn read(allocator: Allocator, quantization_tables: *[4]?QuantizationTable, buffered_stream: *buffered_stream_source.DefaultBufferedStreamSourceReader) ImageReadError!Self {
+ const reader = buffered_stream.reader();
+ const frame_header = try FrameHeader.read(allocator, reader);
+
+ var self = Self{
+ .allocator = allocator,
+ .frame_header = frame_header,
+ .quantization_tables = quantization_tables,
+ .dc_huffman_tables = [_]?HuffmanTable{null} ** 2,
+ .ac_huffman_tables = [_]?HuffmanTable{null} ** 2,
+ };
+ errdefer self.deinit();
+
+ var marker = try reader.readInt(u16, .big);
+ while (marker != @intFromEnum(Markers.start_of_scan)) : (marker = try reader.readInt(u16, .big)) {
+ if (JPEG_DEBUG) std.debug.print("Frame: Parsing marker value: 0x{X}\n", .{marker});
+
+ switch (@as(Markers, @enumFromInt(marker))) {
+ .define_huffman_tables => {
+ try self.parseDefineHuffmanTables(reader);
+ },
+ else => {
+ return ImageReadError.InvalidData;
+ },
+ }
+ }
+
+
+
+ try buffered_stream.seekBy(-2);
+
+ return self;
+}
+
+pub fn deinit(self: *Self) void {
+ for (&self.dc_huffman_tables) |*maybe_huffman_table| {
+ if (maybe_huffman_table.*) |*huffman_table| {
+ huffman_table.deinit();
+ }
+ }
+
+ for (&self.ac_huffman_tables) |*maybe_huffman_table| {
+ if (maybe_huffman_table.*) |*huffman_table| {
+ huffman_table.deinit();
+ }
+ }
+
+ self.frame_header.deinit();
+}
+
+fn parseDefineHuffmanTables(self: *Self, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!void {
+ var segment_size = try reader.readInt(u16, .big);
+ if (JPEG_DEBUG) std.debug.print("DefineHuffmanTables: segment size = 0x{X}\n", .{segment_size});
+ segment_size -= 2;
+
+ while (segment_size > 0) {
+ const class_and_destination = try reader.readByte();
+ const table_class = class_and_destination >> 4;
+ const table_destination = class_and_destination & 0b1;
+
+ const huffman_table = try HuffmanTable.read(self.allocator, table_class, reader);
+
+ if (table_class == 0) {
+ if (self.dc_huffman_tables[table_destination]) |*old_huffman_table| {
+ old_huffman_table.deinit();
+ }
+ self.dc_huffman_tables[table_destination] = huffman_table;
+ } else {
+ if (self.ac_huffman_tables[table_destination]) |*old_huffman_table| {
+ old_huffman_table.deinit();
+ }
+ self.ac_huffman_tables[table_destination] = huffman_table;
+ }
+
+ if (JPEG_DEBUG) std.debug.print(" Table with class {} installed at {}\n", .{ table_class, table_destination });
+
+
+
+ segment_size -= 1 + 16 + @as(u16, @intCast(huffman_table.code_map.count()));
+ }
+}
+
+pub fn renderToPixels(self: *const Self, mcu_storage: *[MAX_COMPONENTS][MAX_BLOCKS]MCU, mcu_id: usize, pixels: *color.PixelStorage) ImageReadError!void {
+ switch (self.frame_header.components.len) {
+ 1 => try self.renderToPixelsGrayscale(&mcu_storage[0][0], mcu_id, pixels.grayscale8),
+
+ 3 => try self.renderToPixelsRgb(mcu_storage, mcu_id, pixels.rgb24),
+ else => unreachable,
+ }
+}
+
+fn renderToPixelsGrayscale(self: *const Self, mcu_storage: *MCU, mcu_id: usize, pixels: []color.Grayscale8) ImageReadError!void {
+ const mcu_width = 8;
+ const mcu_height = 8;
+ const width = self.frame_header.samples_per_row;
+ const height = pixels.len / width;
+ const mcus_per_row = (width + mcu_width - 1) / mcu_width;
+ const mcu_origin_x = (mcu_id % mcus_per_row) * mcu_width;
+ const mcu_origin_y = (mcu_id / mcus_per_row) * mcu_height;
+
+ for (0..mcu_height) |mcu_y| {
+ const y = mcu_origin_y + mcu_y;
+ if (y >= height) continue;
+
+
+
+ const block_y = mcu_y % 8;
+
+ const stride = y * width;
+
+ for (0..mcu_width) |mcu_x| {
+ const x = mcu_origin_x + mcu_x;
+ if (x >= width) continue;
+
+
+
+ const block_x = mcu_x % 8;
+
+ const reconstructed_Y = idct(mcu_storage, @as(u3, @intCast(block_x)), @as(u3, @intCast(block_y)), mcu_id, 0);
+ const Y: f32 = @floatFromInt(reconstructed_Y);
+ pixels[stride + x] = .{
+ .value = @as(u8, @intFromFloat(std.math.clamp(Y + 128.0, 0.0, 255.0))),
+ };
+ }
+ }
+}
+
+fn renderToPixelsRgb(self: *const Self, mcu_storage: *[MAX_COMPONENTS][MAX_BLOCKS]MCU, mcu_id: usize, pixels: []color.Rgb24) ImageReadError!void {
+ const max_horizontal_sampling_factor = self.frame_header.getMaxHorizontalSamplingFactor();
+ const max_vertical_sampling_factor = self.frame_header.getMaxVerticalSamplingFactor();
+ const mcu_width = 8 * max_horizontal_sampling_factor;
+ const mcu_height = 8 * max_vertical_sampling_factor;
+ const width = self.frame_header.samples_per_row;
+ const height = pixels.len / width;
+ const mcus_per_row = (width + mcu_width - 1) / mcu_width;
+
+ const mcu_origin_x = (mcu_id % mcus_per_row) * mcu_width;
+ const mcu_origin_y = (mcu_id / mcus_per_row) * mcu_height;
+
+ for (0..mcu_height) |mcu_y| {
+ const y = mcu_origin_y + mcu_y;
+ if (y >= height) continue;
+
+
+
+ const y_sampled_y = (mcu_y * self.frame_header.components[0].vertical_sampling_factor) / max_vertical_sampling_factor;
+ const cb_sampled_y = (mcu_y * self.frame_header.components[1].vertical_sampling_factor) / max_vertical_sampling_factor;
+ const cr_sampled_y = (mcu_y * self.frame_header.components[2].vertical_sampling_factor) / max_vertical_sampling_factor;
+
+
+
+ const y_block_y = y_sampled_y % 8;
+ const cb_block_y = cb_sampled_y % 8;
+ const cr_block_y = cr_sampled_y % 8;
+
+ const stride = y * width;
+
+ for (0..mcu_width) |mcu_x| {
+ const x = mcu_origin_x + mcu_x;
+ if (x >= width) continue;
+
+
+
+ const y_sampled_x = (mcu_x * self.frame_header.components[0].horizontal_sampling_factor) / max_horizontal_sampling_factor;
+ const cb_sampled_x = (mcu_x * self.frame_header.components[1].horizontal_sampling_factor) / max_horizontal_sampling_factor;
+ const cr_sampled_x = (mcu_x * self.frame_header.components[2].horizontal_sampling_factor) / max_horizontal_sampling_factor;
+
+
+
+ const y_block_x = y_sampled_x % 8;
+ const cb_block_x = cb_sampled_x % 8;
+ const cr_block_x = cr_sampled_x % 8;
+
+ const y_block_ind = (y_sampled_y / 8) * self.frame_header.components[0].horizontal_sampling_factor + (y_sampled_x / 8);
+ const cb_block_ind = (cb_sampled_y / 8) * self.frame_header.components[1].horizontal_sampling_factor + (cb_sampled_x / 8);
+ const cr_block_ind = (cr_sampled_y / 8) * self.frame_header.components[2].horizontal_sampling_factor + (cr_sampled_x / 8);
+
+ const mcu_Y = &mcu_storage[0][y_block_ind];
+ const mcu_Cb = &mcu_storage[1][cb_block_ind];
+ const mcu_Cr = &mcu_storage[2][cr_block_ind];
+
+ const reconstructed_Y = idct(mcu_Y, @as(u3, @intCast(y_block_x)), @as(u3, @intCast(y_block_y)), mcu_id, 0);
+ const reconstructed_Cb = idct(mcu_Cb, @as(u3, @intCast(cb_block_x)), @as(u3, @intCast(cb_block_y)), mcu_id, 1);
+ const reconstructed_Cr = idct(mcu_Cr, @as(u3, @intCast(cr_block_x)), @as(u3, @intCast(cr_block_y)), mcu_id, 2);
+
+ const Y: f32 = @floatFromInt(reconstructed_Y);
+ const Cb: f32 = @floatFromInt(reconstructed_Cb);
+ const Cr: f32 = @floatFromInt(reconstructed_Cr);
+
+ const Co_red = 0.299;
+ const Co_green = 0.587;
+ const Co_blue = 0.114;
+
+ const r = Cr * (2 - 2 * Co_red) + Y;
+ const b = Cb * (2 - 2 * Co_blue) + Y;
+ const g = (Y - Co_blue * b - Co_red * r) / Co_green;
+
+ pixels[stride + x] = .{
+ .r = @intFromFloat(std.math.clamp(r + 128.0, 0.0, 255.0)),
+ .g = @intFromFloat(std.math.clamp(g + 128.0, 0.0, 255.0)),
+ .b = @intFromFloat(std.math.clamp(b + 128.0, 0.0, 255.0)),
+ };
+ }
+ }
+}
+
+fn idct(mcu: *const MCU, x: u3, y: u3, mcu_id: usize, component_id: usize) i8 {
+
+
+
+
+ var reconstructed_pixel: f32 = 0.0;
+
+ var u: usize = 0;
+ while (u < 8) : (u += 1) {
+ var v: usize = 0;
+ while (v < 8) : (v += 1) {
+ const mcu_value = mcu[v * 8 + u];
+ reconstructed_pixel += IDCTMultipliers[y][x][u][v] * @as(f32, @floatFromInt(mcu_value));
+ }
+ }
+
+ const scaled_pixel = @round(reconstructed_pixel / 4.0);
+ if (JPEG_DEBUG) {
+ if (scaled_pixel < -128.0 or scaled_pixel > 127.0) {
+ std.debug.print("Pixel at mcu={} x={} y={} component_id={} is out of bounds with DCT: {d}!\n", .{ mcu_id, x, y, component_id, scaled_pixel });
+ }
+ }
+
+ return @intFromFloat(std.math.clamp(scaled_pixel, -128.0, 127.0));
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/jpeg/FrameHeader.zig.html b/docs/src/zigimg/src/formats/jpeg/FrameHeader.zig.html
new file mode 100644
index 0000000..33ef3ef
--- /dev/null
+++ b/docs/src/zigimg/src/formats/jpeg/FrameHeader.zig.html
@@ -0,0 +1,267 @@
+
+
+
+
+
src/formats/jpeg/FrameHeader.zig - source view
+
+
+
+
+
+
+
+
+const std = @import("std");
+
+const buffered_stream_source = @import("../../buffered_stream_source.zig");
+const Image = @import("../../Image.zig");
+const ImageReadError = Image.ReadError;
+
+const Allocator = std.mem.Allocator;
+
+const JPEG_DEBUG = false;
+
+const Component = struct {
+ id: u8,
+ horizontal_sampling_factor: u4,
+ vertical_sampling_factor: u4,
+ quantization_table_id: u8,
+
+ pub fn read(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Component {
+ const component_id = try reader.readByte();
+ const sampling_factors = try reader.readByte();
+ const quantization_table_id = try reader.readByte();
+
+ const horizontal_sampling_factor: u4 = @intCast(sampling_factors >> 4);
+ const vertical_sampling_factor: u4 = @intCast(sampling_factors & 0xF);
+
+ if (horizontal_sampling_factor < 1 or horizontal_sampling_factor > 4) {
+
+
+ return ImageReadError.InvalidData;
+ }
+
+ if (vertical_sampling_factor < 1 or vertical_sampling_factor > 4) {
+
+
+ return ImageReadError.InvalidData;
+ }
+
+ if (quantization_table_id > 3) {
+
+
+ return ImageReadError.InvalidData;
+ }
+
+ return Component{
+ .id = component_id,
+ .horizontal_sampling_factor = horizontal_sampling_factor,
+ .vertical_sampling_factor = vertical_sampling_factor,
+ .quantization_table_id = quantization_table_id,
+ };
+ }
+};
+
+const Self = @This();
+
+allocator: Allocator,
+sample_precision: u8,
+row_count: u16,
+samples_per_row: u16,
+components: []Component,
+
+pub fn read(allocator: Allocator, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Self {
+ const segment_size = try reader.readInt(u16, .big);
+ if (JPEG_DEBUG) std.debug.print("StartOfFrame: frame size = 0x{X}\n", .{segment_size});
+
+ const sample_precision = try reader.readByte();
+ const row_count = try reader.readInt(u16, .big);
+ const samples_per_row = try reader.readInt(u16, .big);
+
+ const component_count = try reader.readByte();
+
+ if (component_count != 1 and component_count != 3) {
+
+
+ return ImageReadError.InvalidData;
+ }
+
+ if (JPEG_DEBUG) std.debug.print(" {}x{}, precision={}, {} components\n", .{ samples_per_row, row_count, sample_precision, component_count });
+
+ var components = try allocator.alloc(Component, component_count);
+ errdefer allocator.free(components);
+
+ var i: usize = 0;
+ while (i < component_count) : (i += 1) {
+ components[i] = try Component.read(reader);
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+
+
+ std.debug.assert(segment_size == 8 + 3 * component_count);
+
+ return Self{
+ .allocator = allocator,
+ .sample_precision = sample_precision,
+ .row_count = row_count,
+ .samples_per_row = samples_per_row,
+ .components = components,
+ };
+}
+
+pub fn deinit(self: *Self) void {
+ self.allocator.free(self.components);
+}
+
+pub fn getMaxHorizontalSamplingFactor(self: Self) usize {
+ var ret: u4 = 0;
+ for (self.components) |component| {
+ if (ret < component.horizontal_sampling_factor) {
+ ret = component.horizontal_sampling_factor;
+ }
+ }
+
+ return ret;
+}
+
+pub fn getMaxVerticalSamplingFactor(self: Self) usize {
+ var ret: u4 = 0;
+ for (self.components) |component| {
+ if (ret < component.vertical_sampling_factor) {
+ ret = component.vertical_sampling_factor;
+ }
+ }
+
+ return ret;
+}
+
+pub fn getBlockCount(self: Self, component_id: usize) usize {
+
+
+ if (self.components.len == 1) {
+ return 1;
+ }
+
+ const horizontal_block_count = self.components[component_id].horizontal_sampling_factor;
+ const vertical_block_count = self.components[component_id].vertical_sampling_factor;
+ return horizontal_block_count * vertical_block_count;
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/jpeg/JFIFHeader.zig.html b/docs/src/zigimg/src/formats/jpeg/JFIFHeader.zig.html
new file mode 100644
index 0000000..ed30962
--- /dev/null
+++ b/docs/src/zigimg/src/formats/jpeg/JFIFHeader.zig.html
@@ -0,0 +1,202 @@
+
+
+
+
+
src/formats/jpeg/JFIFHeader.zig - source view
+
+
+
+
+
+
+
+
+
+const std = @import("std");
+
+const buffered_stream_source = @import("../../buffered_stream_source.zig");
+const Image = @import("../../Image.zig");
+const Markers = @import("./utils.zig").Markers;
+
+const Self = @This();
+
+
+
+pub const DensityUnit = enum(u8) {
+ pixels = 0,
+ dots_per_inch = 1,
+ dots_per_cm = 2,
+};
+
+jfif_revision: u16,
+density_unit: DensityUnit,
+x_density: u16,
+y_density: u16,
+
+pub fn read(buffered_stream: *buffered_stream_source.DefaultBufferedStreamSourceReader) !Self {
+
+
+ const reader = buffered_stream.reader();
+ try buffered_stream.seekTo(2);
+ const maybe_app0_marker = try reader.readInt(u16, .big);
+ if (maybe_app0_marker != @intFromEnum(Markers.application0)) {
+ return error.App0MarkerDoesNotExist;
+ }
+
+
+
+ _ = try reader.readInt(u16, .big);
+
+ var identifier_buffer: [4]u8 = undefined;
+ _ = try reader.read(identifier_buffer[0..]);
+
+ if (!std.mem.eql(u8, identifier_buffer[0..], "JFIF")) {
+ return error.JfifIdentifierNotSet;
+ }
+
+
+
+ _ = try reader.readByte();
+
+ const jfif_revision = try reader.readInt(u16, .big);
+ const density_unit: DensityUnit = @enumFromInt(try reader.readByte());
+ const x_density = try reader.readInt(u16, .big);
+ const y_density = try reader.readInt(u16, .big);
+
+ const thumbnailWidth = try reader.readByte();
+ const thumbnailHeight = try reader.readByte();
+
+ if (thumbnailWidth != 0 or thumbnailHeight != 0) {
+
+
+ return error.ThumbnailImagesUnsupported;
+ }
+
+
+
+
+
+
+
+
+
+ if (((try reader.readInt(u16, .big)) & 0xFFF0) == @intFromEnum(Markers.application0)) {
+ return error.ExtraneousApplicationMarker;
+ }
+
+ try buffered_stream.seekBy(-2);
+
+ return Self{
+ .jfif_revision = jfif_revision,
+ .density_unit = density_unit,
+ .x_density = x_density,
+ .y_density = y_density,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/jpeg/Scan.zig.html b/docs/src/zigimg/src/formats/jpeg/Scan.zig.html
new file mode 100644
index 0000000..444785b
--- /dev/null
+++ b/docs/src/zigimg/src/formats/jpeg/Scan.zig.html
@@ -0,0 +1,393 @@
+
+
+
+
+
src/formats/jpeg/Scan.zig - source view
+
+
+
+
+
+
const std = @import("std");
+
+const buffered_stream_source = @import("../../buffered_stream_source.zig");
+const color = @import("../../color.zig");
+const Image = @import("../../Image.zig");
+const ImageReadError = Image.ReadError;
+
+const FrameHeader = @import("FrameHeader.zig");
+const Frame = @import("Frame.zig");
+const HuffmanReader = @import("huffman.zig").Reader;
+
+const MAX_COMPONENTS = @import("utils.zig").MAX_COMPONENTS;
+const MAX_BLOCKS = @import("utils.zig").MAX_BLOCKS;
+const MCU = @import("utils.zig").MCU;
+const ZigzagOffsets = @import("utils.zig").ZigzagOffsets;
+
+const Self = @This();
+
+const JPEG_DEBUG = false;
+const JPEG_VERY_DEBUG = false;
+
+frame: *const Frame,
+reader: HuffmanReader,
+scan_header: ScanHeader,
+mcu_storage: [MAX_COMPONENTS][MAX_BLOCKS]MCU,
+prediction_values: [3]i12,
+
+pub fn init(frame: *const Frame, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Self {
+ const scan_header = try ScanHeader.read(reader);
+ return Self{
+ .frame = frame,
+ .reader = HuffmanReader.init(reader),
+ .scan_header = scan_header,
+ .mcu_storage = undefined,
+ .prediction_values = [3]i12{ 0, 0, 0 },
+ };
+}
+
+
+
+
+pub fn performScan(frame: *const Frame, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader, pixels_opt: *?color.PixelStorage) ImageReadError!void {
+ var self = try Self.init(frame, reader);
+
+ const mcu_count = Self.calculateMCUCountInFrame(&frame.frame_header);
+ for (0..mcu_count) |mcu_id| {
+ try self.decodeMCU();
+ try self.dequantize();
+ try frame.renderToPixels(&self.mcu_storage, mcu_id, &pixels_opt.*.?);
+ }
+}
+
+fn dequantize(self: *Self) !void {
+ for (self.frame.frame_header.components, 0..) |component, component_id| {
+ const block_count = self.frame.frame_header.getBlockCount(component_id);
+ for (0..block_count) |i| {
+ const block = &self.mcu_storage[component_id][i];
+
+ if (self.frame.quantization_tables[component.quantization_table_id]) |quantization_table| {
+ var sample_id: usize = 0;
+ while (sample_id < 64) : (sample_id += 1) {
+ block[sample_id] = block[sample_id] * quantization_table.q8[sample_id];
+ }
+ } else return ImageReadError.InvalidData;
+ }
+ }
+}
+
+fn calculateMCUCountInFrame(frame_header: *const FrameHeader) usize {
+
+
+
+
+ const horizontal_block_count = if (1 < frame_header.components.len) frame_header.getMaxHorizontalSamplingFactor() else 1;
+ const vertical_block_count = if (1 < frame_header.components.len) frame_header.getMaxVerticalSamplingFactor() else 1;
+ const mcu_width = 8 * horizontal_block_count;
+ const mcu_height = 8 * vertical_block_count;
+ const mcu_count_per_row = (frame_header.samples_per_row + mcu_width - 1) / mcu_width;
+ const mcu_count_per_column = (frame_header.row_count + mcu_height - 1) / mcu_height;
+ return mcu_count_per_row * mcu_count_per_column;
+}
+
+fn decodeMCU(self: *Self) ImageReadError!void {
+ for (self.scan_header.components, 0..) |maybe_component, component_id| {
+ _ = component_id;
+ if (maybe_component == null)
+ break;
+
+ try self.decodeMCUComponent(maybe_component.?);
+ }
+}
+
+fn decodeMCUComponent(self: *Self, component: ScanComponentSpec) ImageReadError!void {
+
+
+
+
+
+
+ const component_destination: usize = blk: {
+ for (self.frame.frame_header.components, 0..) |frame_component, i| {
+ if (frame_component.id == component.component_selector) {
+ break :blk i;
+ }
+ }
+
+ return ImageReadError.InvalidData;
+ };
+
+ const block_count = self.frame.frame_header.getBlockCount(component_destination);
+ for (0..block_count) |i| {
+ const mcu = &self.mcu_storage[component_destination][i];
+
+
+
+ if (self.frame.dc_huffman_tables[component.dc_table_selector] == null) return ImageReadError.InvalidData;
+
+ self.reader.setHuffmanTable(&self.frame.dc_huffman_tables[component.dc_table_selector].?);
+
+ const dc_coefficient = try self.decodeDCCoefficient(component_destination);
+ mcu[0] = dc_coefficient;
+
+
+
+ if (self.frame.ac_huffman_tables[component.ac_table_selector] == null)
+ return ImageReadError.InvalidData;
+
+ self.reader.setHuffmanTable(&self.frame.ac_huffman_tables[component.ac_table_selector].?);
+
+ try self.decodeACCoefficients(mcu);
+ }
+}
+
+fn decodeDCCoefficient(self: *Self, component_destination: usize) ImageReadError!i12 {
+ const maybe_magnitude = try self.reader.readCode();
+ if (maybe_magnitude > 11) return ImageReadError.InvalidData;
+ const magnitude: u4 = @intCast(maybe_magnitude);
+
+ const diff: i12 = @intCast(try self.reader.readMagnitudeCoded(magnitude));
+
+
+ const dc_coefficient = diff + self.prediction_values[component_destination];
+ self.prediction_values[component_destination] = dc_coefficient;
+
+ return dc_coefficient;
+}
+
+fn decodeACCoefficients(self: *Self, mcu: *MCU) ImageReadError!void {
+ var ac: usize = 1;
+ var did_see_eob = false;
+ while (ac < 64) : (ac += 1) {
+ if (did_see_eob) {
+ mcu[ZigzagOffsets[ac]] = 0;
+ continue;
+ }
+
+ const zero_run_length_and_magnitude = try self.reader.readCode();
+
+
+ if (zero_run_length_and_magnitude == 0x00) {
+ did_see_eob = true;
+ mcu[ZigzagOffsets[ac]] = 0;
+ continue;
+ }
+
+ const zero_run_length = zero_run_length_and_magnitude >> 4;
+
+ const maybe_magnitude = zero_run_length_and_magnitude & 0xF;
+ if (maybe_magnitude > 10) return ImageReadError.InvalidData;
+ const magnitude: u4 = @intCast(maybe_magnitude);
+
+ const ac_coefficient: i11 = @intCast(try self.reader.readMagnitudeCoded(magnitude));
+
+ var i: usize = 0;
+ while (i < zero_run_length) : (i += 1) {
+ mcu[ZigzagOffsets[ac]] = 0;
+ ac += 1;
+ }
+
+ mcu[ZigzagOffsets[ac]] = ac_coefficient;
+ }
+}
+
+pub const ScanComponentSpec = struct {
+ component_selector: u8,
+ dc_table_selector: u4,
+ ac_table_selector: u4,
+
+ pub fn read(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!ScanComponentSpec {
+ const component_selector = try reader.readByte();
+ const entropy_coding_selectors = try reader.readByte();
+
+ const dc_table_selector: u4 = @intCast(entropy_coding_selectors >> 4);
+ const ac_table_selector: u4 = @intCast(entropy_coding_selectors & 0b11);
+
+ if (JPEG_VERY_DEBUG) {
+ std.debug.print(" Component spec: selector={}, DC table ID={}, AC table ID={}\n", .{ component_selector, dc_table_selector, ac_table_selector });
+ }
+
+ return ScanComponentSpec{
+ .component_selector = component_selector,
+ .dc_table_selector = dc_table_selector,
+ .ac_table_selector = ac_table_selector,
+ };
+ }
+};
+
+pub const Header = struct {
+ components: [4]?ScanComponentSpec,
+
+
+ start_of_spectral_selection: u8,
+
+
+
+
+ end_of_spectral_selection: u8,
+ approximation_high: u4,
+ approximation_low: u4,
+
+ pub fn read(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Header {
+ const segment_size = try reader.readInt(u16, .big);
+ if (JPEG_DEBUG) std.debug.print("StartOfScan: segment size = 0x{X}\n", .{segment_size});
+
+ const component_count = try reader.readByte();
+ if (component_count < 1 or component_count > 4) {
+ return ImageReadError.InvalidData;
+ }
+
+ if (JPEG_DEBUG) std.debug.print(" Component count: {}\n", .{component_count});
+
+ var components = [_]?ScanComponentSpec{null} ** 4;
+
+ if (JPEG_VERY_DEBUG) std.debug.print(" Components:\n", .{});
+ var i: usize = 0;
+ while (i < component_count) : (i += 1) {
+ components[i] = try ScanComponentSpec.read(reader);
+ }
+
+ const start_of_spectral_selection = try reader.readByte();
+ const end_of_spectral_selection = try reader.readByte();
+
+ if (start_of_spectral_selection > 63) {
+ return ImageReadError.InvalidData;
+ }
+
+ if (end_of_spectral_selection < start_of_spectral_selection or end_of_spectral_selection > 63) {
+ return ImageReadError.InvalidData;
+ }
+
+
+
+ if (start_of_spectral_selection == 0 and end_of_spectral_selection != 63) {
+ return ImageReadError.InvalidData;
+ }
+
+ if (JPEG_VERY_DEBUG) std.debug.print(" Spectral selection: {}-{}\n", .{ start_of_spectral_selection, end_of_spectral_selection });
+
+ const approximation_bits = try reader.readByte();
+ const approximation_high: u4 = @intCast(approximation_bits >> 4);
+ const approximation_low: u4 = @intCast(approximation_bits & 0b1111);
+ if (JPEG_VERY_DEBUG) std.debug.print(" Approximation bit position: high={} low={}\n", .{ approximation_high, approximation_low });
+
+ std.debug.assert(segment_size == 2 * component_count + 1 + 2 + 1 + 2);
+
+ return Header{
+ .components = components,
+ .start_of_spectral_selection = start_of_spectral_selection,
+ .end_of_spectral_selection = end_of_spectral_selection,
+ .approximation_high = approximation_high,
+ .approximation_low = approximation_low,
+ };
+ }
+};
+
+const ScanHeader = Header;
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/jpeg/huffman.zig.html b/docs/src/zigimg/src/formats/jpeg/huffman.zig.html
new file mode 100644
index 0000000..c79ec7a
--- /dev/null
+++ b/docs/src/zigimg/src/formats/jpeg/huffman.zig.html
@@ -0,0 +1,302 @@
+
+
+
+
+
src/formats/jpeg/huffman.zig - source view
+
+
+
+
+
+
+
+
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+
+const buffered_stream_source = @import("../../buffered_stream_source.zig");
+const Image = @import("../../Image.zig");
+const ImageReadError = Image.ReadError;
+
+const HuffmanCode = struct { length_minus_one: u4, code: u16 };
+const HuffmanCodeMap = std.AutoArrayHashMap(HuffmanCode, u8);
+
+const JPEG_DEBUG = false;
+const JPEG_VERY_DEBUG = false;
+
+pub const Table = struct {
+ const Self = @This();
+
+ allocator: Allocator,
+
+ code_counts: [16]u8,
+ code_map: HuffmanCodeMap,
+
+ table_class: u8,
+
+ pub fn read(allocator: Allocator, table_class: u8, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Self {
+ if (table_class & 1 != table_class)
+ return ImageReadError.InvalidData;
+
+ var code_counts: [16]u8 = undefined;
+ if ((try reader.read(code_counts[0..])) < 16) {
+ return ImageReadError.InvalidData;
+ }
+
+ if (JPEG_DEBUG) std.debug.print(" Code counts: {any}\n", .{code_counts});
+
+ var total_huffman_codes: usize = 0;
+ for (code_counts) |count| total_huffman_codes += count;
+
+ var huffman_code_map = HuffmanCodeMap.init(allocator);
+ errdefer huffman_code_map.deinit();
+
+ if (JPEG_VERY_DEBUG) std.debug.print(" Decoded huffman codes map:\n", .{});
+
+ var code: u16 = 0;
+ for (code_counts, 0..) |count, i| {
+ if (JPEG_VERY_DEBUG) {
+ std.debug.print(" Length {}: ", .{i + 1});
+ if (count == 0) {
+ std.debug.print("(none)\n", .{});
+ } else {
+ std.debug.print("\n", .{});
+ }
+ }
+
+ var j: usize = 0;
+ while (j < count) : (j += 1) {
+
+
+ if (code == (@as(u17, @intCast(1)) << (@as(u5, @intCast(i)) + 1)) - 1) {
+ return ImageReadError.InvalidData;
+ }
+
+ const byte = try reader.readByte();
+ try huffman_code_map.put(.{ .length_minus_one = @as(u4, @intCast(i)), .code = code }, byte);
+
+ if (JPEG_VERY_DEBUG) std.debug.print(" {b} => 0x{X}\n", .{ code, byte });
+ code += 1;
+ }
+
+ code <<= 1;
+ }
+
+ return Self{
+ .allocator = allocator,
+ .code_counts = code_counts,
+ .code_map = huffman_code_map,
+ .table_class = table_class,
+ };
+ }
+
+ pub fn deinit(self: *Self) void {
+ self.code_map.deinit();
+ }
+};
+
+pub const Reader = struct {
+ const Self = @This();
+
+ table: ?*const Table = null,
+ reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader,
+ byte_buffer: u8 = 0,
+ bits_left: u4 = 0,
+ last_byte_was_ff: bool = false,
+
+ pub fn init(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) Self {
+ return .{
+ .reader = reader,
+ };
+ }
+
+ pub fn setHuffmanTable(self: *Self, table: *const Table) void {
+ self.table = table;
+ }
+
+ fn readBit(self: *Self) ImageReadError!u1 {
+ if (self.bits_left == 0) {
+ self.byte_buffer = try self.reader.readByte();
+
+ if (self.byte_buffer == 0 and self.last_byte_was_ff) {
+
+
+ self.byte_buffer = try self.reader.readByte();
+ }
+ self.last_byte_was_ff = self.byte_buffer == 0xFF;
+ self.bits_left = 8;
+ }
+
+ const bit: u1 = @intCast(self.byte_buffer >> 7);
+ self.byte_buffer <<= 1;
+ self.bits_left -= 1;
+
+ return bit;
+ }
+
+ pub fn readCode(self: *Self) ImageReadError!u8 {
+ var code: u16 = 0;
+
+ var i: u5 = 0;
+ while (i < 16) : (i += 1) {
+
+
+
+
+ code = (code << 1) | (try self.readBit());
+ if (self.table.?.code_map.get(.{ .length_minus_one = @intCast(i), .code = code })) |value| {
+ return value;
+ }
+ }
+
+ if (JPEG_DEBUG) std.debug.print("found unknown code: {x}\n", .{code});
+ return ImageReadError.InvalidData;
+ }
+
+ pub fn readLiteralBits(self: *Self, bitsNeeded: u8) ImageReadError!u32 {
+ var bits: u32 = 0;
+
+ var i: usize = 0;
+ while (i < bitsNeeded) : (i += 1) {
+ bits = (bits << 1) | (try self.readBit());
+ }
+
+ return bits;
+ }
+
+
+ pub fn readMagnitudeCoded(self: *Self, magnitude: u5) ImageReadError!i32 {
+ if (magnitude == 0)
+ return 0;
+
+ const bits = try self.readLiteralBits(magnitude);
+
+
+
+ const bits_sign = (bits >> (magnitude - 1)) & 1;
+
+
+ const bits_mask = (@as(u32, 1) << (magnitude - 1)) - 1;
+
+
+ const unsigned_bits = bits & bits_mask;
+
+
+
+
+
+ const base = if (bits_sign == 0)
+ -(@as(i32, 1) << magnitude) + 1
+ else
+ (@as(i32, 1) << (magnitude - 1));
+
+ return base + @as(i32, @bitCast(unsigned_bits));
+ }
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/jpeg/quantization.zig.html b/docs/src/zigimg/src/formats/jpeg/quantization.zig.html
new file mode 100644
index 0000000..8f11a37
--- /dev/null
+++ b/docs/src/zigimg/src/formats/jpeg/quantization.zig.html
@@ -0,0 +1,213 @@
+
+
+
+
+
src/formats/jpeg/quantization.zig - source view
+
+
+
+
+
+
+
+const std = @import("std");
+
+const buffered_stream_source = @import("../../buffered_stream_source.zig");
+const Image = @import("../../Image.zig");
+const ImageReadError = Image.ReadError;
+
+const ZigzagOffsets = @import("./utils.zig").ZigzagOffsets;
+
+const JPEG_DEBUG = false;
+
+pub const Header = struct {
+
+
+ const Self = @This();
+
+
+
+
+
+ table_precision: u4,
+
+
+
+ table_destination: u4,
+
+ table: Table,
+
+ pub fn read(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Self {
+ _ = try reader.readInt(u16, .big);
+
+
+ const precision_and_destination = try reader.readByte();
+ const table_precision = precision_and_destination >> 4;
+ const table_destination = precision_and_destination & 0b11;
+
+ const table = try Table.read(table_precision, reader);
+
+
+
+
+ return Self{
+ .table_precision = table_precision,
+ .table_destination = table_destination,
+ .table = table,
+ };
+ }
+};
+
+pub const Table = union(enum) {
+ const Self = @This();
+ q8: [64]u8,
+ q16: [64]u16,
+
+ pub fn read(precision: u8, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Self {
+
+
+ switch (precision) {
+ 0 => {
+ var table = Self{ .q8 = undefined };
+
+ var offset: usize = 0;
+ while (offset < 64) : (offset += 1) {
+ const value = try reader.readByte();
+ table.q8[ZigzagOffsets[offset]] = value;
+ }
+
+ if (JPEG_DEBUG) {
+ var i: usize = 0;
+ while (i < 8) : (i += 1) {
+ var j: usize = 0;
+ while (j < 8) : (j += 1) {
+ std.debug.print("{d:4} ", .{table.q8[i * 8 + j]});
+ }
+ std.debug.print("\n", .{});
+ }
+ }
+
+ return table;
+ },
+ 1 => {
+ var table = Self{ .q16 = undefined };
+
+ var offset: usize = 0;
+ while (offset < 64) : (offset += 1) {
+ const value = try reader.readInt(u16, .big);
+ table.q16[ZigzagOffsets[offset]] = value;
+ }
+
+ return table;
+ },
+ else => return ImageReadError.InvalidData,
+ }
+ }
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/jpeg/utils.zig.html b/docs/src/zigimg/src/formats/jpeg/utils.zig.html
new file mode 100644
index 0000000..46d844e
--- /dev/null
+++ b/docs/src/zigimg/src/formats/jpeg/utils.zig.html
@@ -0,0 +1,282 @@
+
+
+
+
+
src/formats/jpeg/utils.zig - source view
+
+
+
+
+
+
+const std = @import("std");
+
+
+
+pub const ZigzagOffsets = blk: {
+ var offsets: [64]usize = undefined;
+ offsets[0] = 0;
+
+ var current_offset: usize = 0;
+ var direction: enum { north_east, south_west } = .north_east;
+ var i: usize = 1;
+ while (i < 64) : (i += 1) {
+ switch (direction) {
+ .north_east => {
+ if (current_offset < 8) {
+
+
+ current_offset += 1;
+ direction = .south_west;
+ } else if (current_offset % 8 == 7) {
+
+
+ current_offset += 8;
+ direction = .south_west;
+ } else {
+ current_offset -= 7;
+ }
+ },
+ .south_west => {
+ if (current_offset >= 56) {
+
+
+ current_offset += 1;
+ direction = .north_east;
+ } else if (current_offset % 8 == 0) {
+
+
+ current_offset += 8;
+ direction = .north_east;
+ } else {
+ current_offset += 7;
+ }
+ },
+ }
+
+ if (current_offset >= 64) {
+ @compileError(std.fmt.comptimePrint("ZigzagOffsets: Hit offset {} (>= 64) at index {}!\n", .{ current_offset, i }));
+ }
+
+ offsets[i] = current_offset;
+ }
+
+ break :blk offsets;
+};
+
+
+
+
+pub const IDCTMultipliers = blk: {
+ var multipliers: [8][8][8][8]f32 = undefined;
+ @setEvalBranchQuota(4700);
+
+ var y: usize = 0;
+ while (y < 8) : (y += 1) {
+ var x: usize = 0;
+ while (x < 8) : (x += 1) {
+ var u: usize = 0;
+ while (u < 8) : (u += 1) {
+ var v: usize = 0;
+ while (v < 8) : (v += 1) {
+ const C_u: f32 = if (u == 0) 1.0 / @sqrt(2.0) else 1.0;
+ const C_v: f32 = if (v == 0) 1.0 / @sqrt(2.0) else 1.0;
+
+ const x_cosine = @cos(((2 * @as(f32, @floatFromInt(x)) + 1) * @as(f32, @floatFromInt(u)) * std.math.pi) / 16.0);
+ const y_cosine = @cos(((2 * @as(f32, @floatFromInt(y)) + 1) * @as(f32, @floatFromInt(v)) * std.math.pi) / 16.0);
+ const uv_value = C_u * C_v * x_cosine * y_cosine;
+ multipliers[y][x][u][v] = uv_value;
+ }
+ }
+ }
+ }
+
+ break :blk multipliers;
+};
+
+
+pub const Markers = enum(u16) {
+
+
+ sof0 = 0xFFC0,
+
+ sof1 = 0xFFC1,
+
+ sof2 = 0xFFC2,
+
+ sof3 = 0xFFC3,
+
+
+
+
+ sof5 = 0xFFC5,
+
+ sof6 = 0xFFC6,
+
+ sof7 = 0xFFC7,
+
+
+
+
+ sof9 = 0xFFC9,
+
+ sof10 = 0xFFCA,
+
+ sof11 = 0xFFCB,
+
+
+
+
+ sof13 = 0xFFCD,
+
+ sof14 = 0xFFCE,
+
+ sof15 = 0xFFCF,
+
+
+ define_huffman_tables = 0xFFC4,
+ define_arithmetic_coding = 0xFFCC,
+
+
+
+ restart0 = 0xFFD0,
+ restart1 = 0xFFD1,
+ restart2 = 0xFFD2,
+ restart3 = 0xFFD3,
+ restart4 = 0xFFD4,
+ restart5 = 0xFFD5,
+ restart6 = 0xFFD6,
+ restart7 = 0xFFD7,
+
+ start_of_image = 0xFFD8,
+ end_of_image = 0xFFD9,
+ start_of_scan = 0xFFDA,
+ define_quantization_tables = 0xFFDB,
+ define_number_of_lines = 0xFFDC,
+ define_restart_interval = 0xFFDD,
+ define_hierarchical_progression = 0xFFDE,
+ expand_reference_components = 0xFFDF,
+
+
+
+ application0 = 0xFFE0,
+
+
+
+ jpeg_extension0 = 0xFFF0,
+ comment = 0xFFFE,
+
+
+
+};
+
+pub const MAX_COMPONENTS = 3;
+pub const MAX_BLOCKS = 8;
+pub const MCU = [64]i32;
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/netpbm.zig.html b/docs/src/zigimg/src/formats/netpbm.zig.html
new file mode 100644
index 0000000..63a79e1
--- /dev/null
+++ b/docs/src/zigimg/src/formats/netpbm.zig.html
@@ -0,0 +1,635 @@
+
+
+
+
+
src/formats/netpbm.zig - source view
+
+
+
+
+
+
+
+
+
+const Allocator = std.mem.Allocator;
+const buffered_stream_source = @import("../buffered_stream_source.zig");
+const color = @import("../color.zig");
+const FormatInterface = @import("../FormatInterface.zig");
+const Image = @import("../Image.zig");
+const ImageError = Image.Error;
+const ImageReadError = Image.ReadError;
+const ImageWriteError = Image.WriteError;
+const PixelFormat = @import("../pixel_format.zig").PixelFormat;
+const std = @import("std");
+const utils = @import("../utils.zig");
+
+
+
+
+
+
+
+
+
+
+
+pub const Format = enum {
+
+ bitmap,
+
+
+ grayscale,
+
+
+ rgb,
+};
+
+pub const Header = struct {
+ format: Format,
+ binary: bool,
+ width: usize,
+ height: usize,
+ max_value: usize,
+};
+
+fn parseHeader(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Header {
+ var header: Header = undefined;
+
+ var magic: [2]u8 = undefined;
+ _ = try reader.read(magic[0..]);
+
+ if (std.mem.eql(u8, &magic, "P1")) {
+ header.binary = false;
+ header.format = .bitmap;
+ header.max_value = 1;
+ } else if (std.mem.eql(u8, &magic, "P2")) {
+ header.binary = false;
+ header.format = .grayscale;
+ } else if (std.mem.eql(u8, &magic, "P3")) {
+ header.binary = false;
+ header.format = .rgb;
+ } else if (std.mem.eql(u8, &magic, "P4")) {
+ header.binary = true;
+ header.format = .bitmap;
+ header.max_value = 1;
+ } else if (std.mem.eql(u8, &magic, "P5")) {
+ header.binary = true;
+ header.format = .grayscale;
+ } else if (std.mem.eql(u8, &magic, "P6")) {
+ header.binary = true;
+ header.format = .rgb;
+ } else {
+ return ImageReadError.InvalidData;
+ }
+
+ var read_buffer: [16]u8 = undefined;
+
+ header.width = try parseNumber(reader, read_buffer[0..]);
+ header.height = try parseNumber(reader, read_buffer[0..]);
+ if (header.format != .bitmap) {
+ header.max_value = try parseNumber(reader, read_buffer[0..]);
+ }
+
+ return header;
+}
+
+fn isWhitespace(b: u8) bool {
+ return switch (b) {
+
+
+ '\n', '\r', ' ', '\t' => true,
+ else => false,
+ };
+}
+
+fn readNextByte(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!u8 {
+ while (true) {
+ const b = try reader.readByte();
+ switch (b) {
+
+
+
+
+
+
+
+
+
+
+
+
+ '#' => {
+
+
+ while (true) {
+ const c = try reader.readByte();
+ switch (c) {
+ '\r', '\n' => break,
+ else => {},
+ }
+ }
+ },
+ else => return b,
+ }
+ }
+}
+
+
+
+fn parseNumber(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader, buffer: []u8) ImageReadError!usize {
+ var input_length: usize = 0;
+ while (true) {
+ const b = try readNextByte(reader);
+ if (isWhitespace(b)) {
+ if (input_length > 0) {
+ return std.fmt.parseInt(usize, buffer[0..input_length], 10) catch return ImageReadError.InvalidData;
+ } else {
+ continue;
+ }
+ } else {
+ if (input_length >= buffer.len)
+ return error.OutOfMemory;
+ buffer[input_length] = b;
+ input_length += 1;
+ }
+ }
+}
+
+fn loadBinaryBitmap(header: Header, data: []color.Grayscale1, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!void {
+ var bit_reader = std.io.bitReader(.big, reader);
+
+ for (0..header.height) |row_index| {
+ for (data[row_index * header.width ..][0..header.width]) |*sample| {
+ sample.value = ~(try bit_reader.readBitsNoEof(u1, 1));
+ }
+ bit_reader.alignToByte();
+ }
+}
+
+fn loadAsciiBitmap(header: Header, data: []color.Grayscale1, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!void {
+ var data_index: usize = 0;
+ const data_end = header.width * header.height;
+
+ while (data_index < data_end) {
+ const b = try reader.readByte();
+ if (isWhitespace(b)) {
+ continue;
+ }
+
+
+
+
+
+ const pixel = if (b == '0') @as(u1, 1) else @as(u1, 0);
+ data[data_index] = color.Grayscale1{ .value = pixel };
+
+ data_index += 1;
+ }
+}
+
+fn readLinearizedValue(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader, max_value: usize) ImageReadError!u8 {
+ return if (max_value > 255)
+ @truncate(255 * @as(usize, try reader.readInt(u16, .big)) / max_value)
+ else
+ @truncate(255 * @as(usize, try reader.readByte()) / max_value);
+}
+
+fn loadBinaryGraymap(header: Header, pixels: *color.PixelStorage, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!void {
+ var data_index: usize = 0;
+ const data_end = header.width * header.height;
+ if (header.max_value <= 255) {
+ while (data_index < data_end) : (data_index += 1) {
+ pixels.grayscale8[data_index] = color.Grayscale8{ .value = try readLinearizedValue(reader, header.max_value) };
+ }
+ } else {
+ while (data_index < data_end) : (data_index += 1) {
+ pixels.grayscale16[data_index] = color.Grayscale16{ .value = try reader.readInt(u16, .big) };
+ }
+ }
+}
+
+fn loadAsciiGraymap(header: Header, pixels: *color.PixelStorage, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!void {
+ var read_buffer: [16]u8 = undefined;
+
+ var data_index: usize = 0;
+ const data_end = header.width * header.height;
+
+ if (header.max_value <= 255) {
+ while (data_index < data_end) : (data_index += 1) {
+ pixels.grayscale8[data_index] = color.Grayscale8{ .value = @truncate(try parseNumber(reader, read_buffer[0..])) };
+ }
+ } else {
+ while (data_index < data_end) : (data_index += 1) {
+ pixels.grayscale16[data_index] = color.Grayscale16{ .value = @truncate(try parseNumber(reader, read_buffer[0..])) };
+ }
+ }
+}
+
+fn loadBinaryRgbmap(header: Header, data: []color.Rgb24, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!void {
+ var data_index: usize = 0;
+ const data_end = header.width * header.height;
+
+ while (data_index < data_end) : (data_index += 1) {
+ data[data_index] = color.Rgb24{
+ .r = try readLinearizedValue(reader, header.max_value),
+ .g = try readLinearizedValue(reader, header.max_value),
+ .b = try readLinearizedValue(reader, header.max_value),
+ };
+ }
+}
+
+fn loadAsciiRgbmap(header: Header, data: []color.Rgb24, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!void {
+ var read_buffer: [16]u8 = undefined;
+
+ var data_index: usize = 0;
+ const data_end = header.width * header.height;
+
+ while (data_index < data_end) : (data_index += 1) {
+ const r = try parseNumber(reader, read_buffer[0..]);
+ const g = try parseNumber(reader, read_buffer[0..]);
+ const b = try parseNumber(reader, read_buffer[0..]);
+
+ data[data_index] = color.Rgb24{
+ .r = @truncate(255 * r / header.max_value),
+ .g = @truncate(255 * g / header.max_value),
+ .b = @truncate(255 * b / header.max_value),
+ };
+ }
+}
+
+fn Netpbm(comptime image_format: Image.Format, comptime header_numbers: []const u8) type {
+ return struct {
+ header: Header = undefined,
+
+ const Self = @This();
+
+ pub const EncoderOptions = struct {
+ binary: bool = true,
+ };
+
+ pub fn formatInterface() FormatInterface {
+ return FormatInterface{
+ .format = format,
+ .formatDetect = formatDetect,
+ .readImage = readImage,
+ .writeImage = writeImage,
+ };
+ }
+
+ pub fn format() Image.Format {
+ return image_format;
+ }
+
+ pub fn formatDetect(stream: *Image.Stream) ImageReadError!bool {
+ var magic_number_buffer: [2]u8 = undefined;
+ _ = try stream.read(magic_number_buffer[0..]);
+
+ if (magic_number_buffer[0] != 'P') {
+ return false;
+ }
+
+ var found = false;
+
+ for (header_numbers) |number| {
+ if (magic_number_buffer[1] == number) {
+ found = true;
+ break;
+ }
+ }
+
+ return found;
+ }
+
+ pub fn readImage(allocator: Allocator, stream: *Image.Stream) ImageReadError!Image {
+ var result = Image.init(allocator);
+ errdefer result.deinit();
+ var netpbm_file = Self{};
+
+ const pixels = try netpbm_file.read(allocator, stream);
+
+ result.width = netpbm_file.header.width;
+ result.height = netpbm_file.header.height;
+ result.pixels = pixels;
+
+ return result;
+ }
+
+ pub fn writeImage(allocator: Allocator, write_stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) ImageWriteError!void {
+ _ = allocator;
+
+ var netpbm_file = Self{};
+ netpbm_file.header.binary = switch (encoder_options) {
+ .pbm => |options| options.binary,
+ .pgm => |options| options.binary,
+ .ppm => |options| options.binary,
+ else => false,
+ };
+
+ netpbm_file.header.width = image.width;
+ netpbm_file.header.height = image.height;
+ netpbm_file.header.format = switch (image.pixels) {
+ .grayscale1 => Format.bitmap,
+ .grayscale8, .grayscale16 => Format.grayscale,
+ .rgb24 => Format.rgb,
+ else => return ImageError.Unsupported,
+ };
+
+ netpbm_file.header.max_value = switch (image.pixels) {
+ .grayscale16 => std.math.maxInt(u16),
+ .grayscale1 => 1,
+ else => std.math.maxInt(u8),
+ };
+
+ try netpbm_file.write(write_stream, image.pixels);
+ }
+
+ pub fn pixelFormat(self: Self) ImageReadError!PixelFormat {
+ return switch (self.header.format) {
+ .bitmap => PixelFormat.grayscale1,
+ .grayscale => switch (self.header.max_value) {
+ 0...255 => PixelFormat.grayscale8,
+ else => PixelFormat.grayscale16,
+ },
+ .rgb => PixelFormat.rgb24,
+ };
+ }
+
+ pub fn read(self: *Self, allocator: Allocator, stream: *Image.Stream) ImageReadError!color.PixelStorage {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);
+ const reader = buffered_stream.reader();
+ self.header = try parseHeader(reader);
+
+ const pixel_format = try self.pixelFormat();
+
+ var pixels = try color.PixelStorage.init(allocator, pixel_format, self.header.width * self.header.height);
+ errdefer pixels.deinit(allocator);
+
+ switch (self.header.format) {
+ .bitmap => {
+ if (self.header.binary) {
+ try loadBinaryBitmap(self.header, pixels.grayscale1, reader);
+ } else {
+ try loadAsciiBitmap(self.header, pixels.grayscale1, reader);
+ }
+ },
+ .grayscale => {
+ if (self.header.binary) {
+ try loadBinaryGraymap(self.header, &pixels, reader);
+ } else {
+ try loadAsciiGraymap(self.header, &pixels, reader);
+ }
+ },
+ .rgb => {
+ if (self.header.binary) {
+ try loadBinaryRgbmap(self.header, pixels.rgb24, reader);
+ } else {
+ try loadAsciiRgbmap(self.header, pixels.rgb24, reader);
+ }
+ },
+ }
+
+ return pixels;
+ }
+
+ pub fn write(self: *Self, write_stream: *Image.Stream, pixels: color.PixelStorage) ImageWriteError!void {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceWriter(write_stream);
+
+ const image_type = if (self.header.binary) header_numbers[1] else header_numbers[0];
+ const writer = buffered_stream.writer();
+ try writer.print("P{c}\n", .{image_type});
+ _ = try writer.write("# Created by zigimg\n");
+
+ try writer.print("{} {}\n", .{ self.header.width, self.header.height });
+
+ if (self.header.format != .bitmap) {
+ try writer.print("{}\n", .{self.header.max_value});
+ }
+
+ if (self.header.binary) {
+ switch (self.header.format) {
+ .bitmap => {
+ switch (pixels) {
+ .grayscale1 => |samples| {
+ var bit_writer = std.io.bitWriter(.big, writer);
+
+ for (0..self.header.height) |row_index| {
+ for (samples[row_index * self.header.width ..][0..self.header.width]) |sample| {
+ try bit_writer.writeBits(~sample.value, 1);
+ }
+ try bit_writer.flushBits();
+ }
+ },
+ else => {
+ return ImageError.Unsupported;
+ },
+ }
+ },
+ .grayscale => {
+ switch (pixels) {
+ .grayscale16 => {
+ for (pixels.grayscale16) |entry| {
+
+
+ try writer.writeInt(u16, entry.value, .big);
+ }
+ },
+ .grayscale8 => {
+ for (pixels.grayscale8) |entry| {
+ try writer.writeInt(u8, entry.value, .little);
+ }
+ },
+ else => {
+ return ImageError.Unsupported;
+ },
+ }
+ },
+ .rgb => {
+ switch (pixels) {
+ .rgb24 => {
+ for (pixels.rgb24) |entry| {
+ try writer.writeByte(entry.r);
+ try writer.writeByte(entry.g);
+ try writer.writeByte(entry.b);
+ }
+ },
+ else => {
+ return ImageError.Unsupported;
+ },
+ }
+ },
+ }
+ } else {
+ switch (self.header.format) {
+ .bitmap => {
+ switch (pixels) {
+ .grayscale1 => {
+ for (pixels.grayscale1) |entry| {
+ try writer.print("{}", .{~entry.value});
+ }
+ _ = try writer.write("\n");
+ },
+ else => {
+ return ImageError.Unsupported;
+ },
+ }
+ },
+ .grayscale => {
+ switch (pixels) {
+ .grayscale16 => {
+ const pixels_len = pixels.len();
+ for (pixels.grayscale16, 0..) |entry, index| {
+ try writer.print("{}", .{entry.value});
+
+ if (index != (pixels_len - 1)) {
+ _ = try writer.write(" ");
+ }
+ }
+ _ = try writer.write("\n");
+ },
+ .grayscale8 => {
+ const pixels_len = pixels.len();
+ for (pixels.grayscale8, 0..) |entry, index| {
+ try writer.print("{}", .{entry.value});
+
+ if (index != (pixels_len - 1)) {
+ _ = try writer.write(" ");
+ }
+ }
+ _ = try writer.write("\n");
+ },
+ else => {
+ return ImageError.Unsupported;
+ },
+ }
+ },
+ .rgb => {
+ switch (pixels) {
+ .rgb24 => {
+ for (pixels.rgb24) |entry| {
+ try writer.print("{} {} {}\n", .{ entry.r, entry.g, entry.b });
+ }
+ },
+ else => {
+ return ImageError.Unsupported;
+ },
+ }
+ },
+ }
+ }
+
+ try buffered_stream.flush();
+ }
+ };
+}
+
+pub const PBM = Netpbm(Image.Format.pbm, &[_]u8{ '1', '4' });
+pub const PGM = Netpbm(Image.Format.pgm, &[_]u8{ '2', '5' });
+pub const PPM = Netpbm(Image.Format.ppm, &[_]u8{ '3', '6' });
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/pam.zig.html b/docs/src/zigimg/src/formats/pam.zig.html
new file mode 100644
index 0000000..c4d524d
--- /dev/null
+++ b/docs/src/zigimg/src/formats/pam.zig.html
@@ -0,0 +1,694 @@
+
+
+
+
+
src/formats/pam.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const io = std.io;
+const mem = std.mem;
+const math = std.math;
+const ascii = std.ascii;
+const fmt = std.fmt;
+const meta = std.meta;
+const Allocator = std.mem.Allocator;
+const buffered_stream_source = @import("../buffered_stream_source.zig");
+const color = @import("../color.zig");
+const FormatInterface = @import("../FormatInterface.zig");
+const PixelStorage = color.PixelStorage;
+const PixelFormat = @import("../pixel_format.zig").PixelFormat;
+const Image = @import("../Image.zig");
+const ImageError = Image.Error;
+const ImageReadError = Image.ReadError;
+const ImageWriteError = Image.WriteError;
+const utils = @import("../utils.zig");
+
+
+const TupleType = enum {
+ mono,
+ mono_a,
+ gray,
+ gray_a,
+ rgb,
+ rgb_a,
+
+
+
+ fn fromString(string: []const u8) error{Unsupported}!TupleType {
+
+
+ return if(mem.eql(u8, string, "BLACKANDWHITE")) .mono
+ else if(mem.eql(u8, string, "BLACKANDWHITE_ALPHA")) .mono_a
+ else if(mem.eql(u8, string, "GRAYSCALE")) .gray
+ else if(mem.eql(u8, string, "GRAYSCALE_ALPHA")) .gray_a
+ else if(mem.eql(u8, string, "RGB")) .rgb
+ else if(mem.eql(u8, string, "RGB_ALPHA")) .rgb_a
+ else error.Unsupported;
+
+
+
+ }
+
+
+ fn toString(tuple_type: TupleType) []const u8 {
+ return switch (tuple_type) {
+ .mono => "BLACKANDWHITE",
+ .mono_a => "BLACKANDWHITE_ALPHA",
+ .gray => "GRAYSCALE",
+ .gray_a => "GRAYSCALE_ALPHA",
+ .rgb => "RGB",
+ .rgb_a => "RGB_ALPHA",
+ };
+ }
+};
+
+
+const Header = struct {
+
+ width: usize,
+
+ height: usize,
+
+ depth: usize,
+
+ maxval: u16,
+
+ tuple_type: TupleType,
+
+
+ comments: []const []const u8,
+
+
+
+
+
+
+
+ fn read(allocator: Allocator, reader: anytype) (error{ InvalidData, Unsupported, OutOfMemory, EndOfStream, StreamTooLong } || @TypeOf(reader).Error)!Header {
+ var maybe_width: ?usize = null;
+ var maybe_height: ?usize = null;
+ var maybe_depth: ?usize = null;
+ var maybe_maxval: ?u16 = null;
+ var maybe_tuple_type: ?TupleType = null;
+ var comments = std.ArrayListUnmanaged([]const u8){};
+ defer {
+ for (comments.items) |comment| allocator.free(comment);
+ comments.deinit(allocator);
+ }
+
+ {
+ var buf = try std.ArrayList(u8).initCapacity(allocator, 32);
+ defer buf.deinit();
+
+ while (true) {
+
+
+ try reader.readUntilDelimiterArrayList(&buf, '\n', math.maxInt(usize));
+ const line = buf.items;
+
+ if (line.len == 0) continue;
+ if (line[0] == '#') {
+
+ try comments.append(allocator, try allocator.dupe(u8, line[1..]));
+ continue;
+ }
+
+ var tok_iter = mem.tokenize(u8, line, &ascii.whitespace);
+ const first_token = tok_iter.next() orelse continue;
+
+
+ if (first_token.len > 8) return error.InvalidData;
+
+
+ if (mem.eql(u8, first_token, "ENDHDR")) break;
+
+ if (mem.eql(u8, first_token, "TUPLTYPE")) {
+ maybe_tuple_type = try TupleType.fromString(tok_iter.rest());
+ continue;
+ }
+
+ const second_token = tok_iter.next() orelse return error.InvalidData;
+
+
+ if (mem.eql(u8, first_token, "WIDTH")) {
+ maybe_width = fmt.parseUnsigned(usize, second_token, 10) catch return error.InvalidData;
+
+ } else if (mem.eql(u8, first_token, "HEIGHT")) {
+ maybe_height = fmt.parseUnsigned(usize, second_token, 10) catch return error.InvalidData;
+
+ } else if (mem.eql(u8, first_token, "DEPTH")) {
+ maybe_depth = fmt.parseUnsigned(usize, second_token, 10) catch return error.InvalidData;
+
+ } else if (mem.eql(u8, first_token, "MAXVAL")) {
+ maybe_maxval = fmt.parseUnsigned(u16, second_token, 10) catch return error.InvalidData;
+
+ } else return error.InvalidData;
+
+ }
+ }
+
+ if (maybe_height == null or maybe_width == null or maybe_maxval == null or maybe_depth == null) return error.InvalidData;
+
+ if (maybe_height.? < 1 or maybe_width.? < 1 or maybe_maxval.? < 1) return error.InvalidData;
+
+ if (maybe_tuple_type == null) {
+
+ const depth = maybe_depth.?;
+ const maxval = maybe_maxval.?;
+ maybe_tuple_type = switch (depth) {
+ 1 => if (maxval == 1) TupleType.mono else TupleType.gray,
+ 2 => if (maxval == 1) TupleType.mono_a else TupleType.gray_a,
+ 3 => TupleType.rgb,
+ 4 => TupleType.rgb_a,
+ else => return error.Unsupported,
+
+ };
+ }
+
+ const tuple_type_matches = if (maybe_depth) |depth| if (maybe_maxval) |maxval| switch (maybe_tuple_type.?) {
+ .mono => depth == 1 and maxval == 1,
+ .mono_a => depth == 2 and maxval == 1,
+ .gray => depth == 1,
+ .gray_a => depth == 2,
+ .rgb => depth == 3,
+ .rgb_a => depth == 4,
+ } else unreachable else unreachable;
+
+ if (!tuple_type_matches) return error.InvalidData;
+
+
+ return Header{
+ .width = maybe_width.?,
+ .height = maybe_height.?,
+ .maxval = maybe_maxval.?,
+ .depth = maybe_depth.?,
+ .tuple_type = maybe_tuple_type.?,
+ .comments = try comments.toOwnedSlice(allocator),
+ };
+ }
+
+
+
+ fn write(header: Header, writer: anytype) @TypeOf(writer).Error!void {
+ try writer.writeAll("P7\n");
+
+ for (header.comments) |comment|
+ try writer.print("#{s}\n", .{comment});
+
+ const fmtstr =
+ \\WIDTH {d}
+
+ \\HEIGHT {d}
+
+ \\DEPTH {d}
+
+ \\MAXVAL {d}
+
+ \\TUPLTYPE {s}
+
+ \\ENDHDR
+
+ \\
+
+ ;
+ try writer.print(fmtstr, .{ header.width, header.height, header.depth, header.maxval, header.tuple_type.toString() });
+ }
+
+
+ fn deinit(header: *Header, allocator: Allocator) void {
+ for (header.comments) |comment| {
+ allocator.free(comment);
+ }
+ allocator.free(header.comments);
+ header.* = undefined;
+ }
+
+ fn hasTwoBytesPerComponent(header: Header) bool {
+ return header.maxval > math.maxInt(u8);
+ }
+
+ fn getPixelFormat(header: Header) PixelFormat {
+ return switch (header.tuple_type) {
+ .mono => .grayscale1,
+
+
+ .mono_a => .grayscale1,
+ .gray => if (header.hasTwoBytesPerComponent()) .grayscale16 else .grayscale8,
+ .gray_a => if (header.hasTwoBytesPerComponent()) .grayscale16Alpha else .grayscale8Alpha,
+ .rgb => if (header.hasTwoBytesPerComponent()) .rgb48 else .rgb24,
+ .rgb_a => if (header.hasTwoBytesPerComponent()) .rgba64 else .rgba32,
+ };
+ }
+
+
+
+ fn initImage(header: Header, allocator: Allocator) error{OutOfMemory}!Image {
+ var image = Image.init(allocator);
+ image.width = header.width;
+ image.height = header.height;
+ image.pixels = try PixelStorage.init(allocator, header.getPixelFormat(), header.width * header.height);
+ return image;
+ }
+
+
+
+
+ fn fromImage(image: Image) error{Unsupported}!Header {
+ var header: Header = undefined;
+ switch (image.pixelFormat()) {
+ .invalid,
+ .indexed1,
+ .indexed2,
+ .indexed4,
+ .indexed8,
+ .indexed16,
+ .float32,
+ .rgb565,
+ => return error.Unsupported,
+
+
+ .grayscale1 => {
+ header.depth = 1;
+ header.maxval = 1;
+ header.tuple_type = .mono;
+ },
+ .grayscale2 => {
+ header.depth = 1;
+ header.maxval = math.maxInt(u2);
+ header.tuple_type = .gray;
+ },
+ .grayscale4 => {
+ header.depth = 1;
+ header.maxval = math.maxInt(u4);
+ header.tuple_type = .gray;
+ },
+ .grayscale8 => {
+ header.depth = 1;
+ header.maxval = math.maxInt(u8);
+ header.tuple_type = .gray;
+ },
+ .grayscale8Alpha => {
+ header.depth = 2;
+ header.maxval = math.maxInt(u8);
+ header.tuple_type = .gray_a;
+ },
+ .grayscale16 => {
+ header.depth = 1;
+ header.maxval = math.maxInt(u16);
+ header.tuple_type = .gray;
+ },
+ .grayscale16Alpha => {
+ header.depth = 2;
+ header.maxval = math.maxInt(u16);
+ header.tuple_type = .gray_a;
+ },
+ .rgb555, .bgr555 => {
+ header.depth = 3;
+ header.maxval = math.maxInt(u5);
+ header.tuple_type = .rgb;
+ },
+ .rgb24, .bgr24 => {
+ header.depth = 3;
+ header.maxval = math.maxInt(u8);
+ header.tuple_type = .rgb;
+ },
+ .rgba32, .bgra32 => {
+ header.depth = 4;
+ header.maxval = math.maxInt(u8);
+ header.tuple_type = .rgb_a;
+ },
+ .rgb48 => {
+ header.depth = 3;
+ header.maxval = math.maxInt(u16);
+ header.tuple_type = .rgb;
+ },
+ .rgba64 => {
+ header.depth = 4;
+ header.maxval = math.maxInt(u16);
+ header.tuple_type = .rgb_a;
+ },
+ }
+ header.comments = &.{};
+ header.width = image.width;
+ header.height = image.height;
+ return header;
+ }
+};
+
+pub const PAM = struct {
+
+
+
+
+
+
+
+
+
+
+ pub const EncoderOptions = struct {
+
+ comments: []const []const u8 = &.{},
+
+
+ add_duration_as_comment: bool = false,
+ };
+
+ pub fn formatInterface() FormatInterface {
+ return FormatInterface{
+ .format = format,
+ .formatDetect = formatDetect,
+ .readImage = readImage,
+ .writeImage = writeImage,
+ };
+ }
+
+ pub fn format() Image.Format {
+ return Image.Format.pam;
+ }
+
+
+
+ pub fn formatDetect(stream: *Image.Stream) ImageReadError!bool {
+ const magic = try stream.reader().readBytesNoEof(3);
+ return mem.eql(u8, &magic, "P7\n");
+
+ }
+
+ pub fn readImage(allocator: Allocator, stream: *Image.Stream) ImageReadError!Image {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);
+ const reader = buffered_stream.reader();
+ var image: Image = try readFrame(allocator, reader) orelse return ImageReadError.InvalidData;
+
+ errdefer image.deinit();
+
+ while (try readFrame(allocator, reader)) |frame| {
+ if (frame.width != image.width or frame.height != image.height or meta.activeTag(frame.pixels) != meta.activeTag(image.pixels)) {
+ return ImageReadError.Unsupported;
+
+ }
+ try image.animation.frames.append(allocator, Image.AnimationFrame{ .pixels = frame.pixels, .duration = 0 });
+ }
+ return image;
+ }
+
+
+
+
+
+ fn mapValue(comptime T: type, val: T, src_maxval: T, dst_maxval: T) error{InvalidData}!T {
+ if (val > src_maxval) return error.InvalidData;
+
+
+ if (src_maxval == dst_maxval) return val;
+
+ const W = meta.Int(.unsigned, @bitSizeOf(T) * 2);
+ return @intCast(@min(math.maxInt(T), @as(W, dst_maxval) * @as(W, val) / @as(W, src_maxval)));
+ }
+
+ fn readFrame(allocator: Allocator, reader: anytype) ImageReadError!?Image {
+
+
+
+
+
+
+ const magic = reader.readBytesNoEof(3) catch |e| return if (e == error.EndOfStream) null else e;
+ const is_pam = mem.eql(u8, &magic, "P7\n");
+ if (!is_pam) return ImageReadError.InvalidData;
+
+
+ var header = try Header.read(allocator, reader);
+ defer header.deinit(allocator);
+
+ var image: Image = try header.initImage(allocator);
+ errdefer image.deinit();
+
+ for (0..image.height) |row| {
+ const offset = row * image.width;
+ for (0..image.width) |column| {
+ switch (image.pixels) {
+ .grayscale1 => |g| g[offset + column].value = @intCast(if (header.tuple_type == .mono) try mapValue(u8, try reader.readByte(), 1, 1) else try mapValue(u8, try reader.readByte(), 1, 1) & try mapValue(u8, try reader.readByte(), 1, 1)),
+ .grayscale8 => |g| g[offset + column].value = try mapValue(u8, try reader.readByte(), @as(u8, @intCast(header.maxval)), math.maxInt(u8)),
+ .grayscale8Alpha => |g| g[offset + column] = .{
+ .value = try mapValue(u8, try reader.readByte(), @as(u8, @intCast(header.maxval)), math.maxInt(u8)),
+ .alpha = try mapValue(u8, try reader.readByte(), @as(u8, @intCast(header.maxval)), math.maxInt(u8)),
+ },
+ .grayscale16 => |g| g[offset + column].value = try mapValue(u16, try reader.readInt(u16, .little), header.maxval, math.maxInt(u16)),
+ .grayscale16Alpha => |g| g[offset + column] = .{
+ .value = try mapValue(u16, try reader.readInt(u16, .little), header.maxval, math.maxInt(u16)),
+ .alpha = try mapValue(u16, try reader.readInt(u16, .little), header.maxval, math.maxInt(u16)),
+ },
+ .rgb24 => |x| x[offset + column] = .{
+ .r = try mapValue(u8, try reader.readByte(), @as(u8, @intCast(header.maxval)), math.maxInt(u8)),
+ .g = try mapValue(u8, try reader.readByte(), @as(u8, @intCast(header.maxval)), math.maxInt(u8)),
+ .b = try mapValue(u8, try reader.readByte(), @as(u8, @intCast(header.maxval)), math.maxInt(u8)),
+ },
+ .rgba32 => |x| x[offset + column] = .{
+ .r = try mapValue(u8, try reader.readByte(), @as(u8, @intCast(header.maxval)), math.maxInt(u8)),
+ .g = try mapValue(u8, try reader.readByte(), @as(u8, @intCast(header.maxval)), math.maxInt(u8)),
+ .b = try mapValue(u8, try reader.readByte(), @as(u8, @intCast(header.maxval)), math.maxInt(u8)),
+ .a = try mapValue(u8, try reader.readByte(), @as(u8, @intCast(header.maxval)), math.maxInt(u8)),
+ },
+ .rgb48 => |x| x[offset + column] = .{
+ .r = try mapValue(u16, try reader.readInt(u16, .little), header.maxval, math.maxInt(u16)),
+ .g = try mapValue(u16, try reader.readInt(u16, .little), header.maxval, math.maxInt(u16)),
+ .b = try mapValue(u16, try reader.readInt(u16, .little), header.maxval, math.maxInt(u16)),
+ },
+ .rgba64 => |x| x[offset + column] = .{
+ .r = try mapValue(u16, try reader.readInt(u16, .little), header.maxval, math.maxInt(u16)),
+ .g = try mapValue(u16, try reader.readInt(u16, .little), header.maxval, math.maxInt(u16)),
+ .b = try mapValue(u16, try reader.readInt(u16, .little), header.maxval, math.maxInt(u16)),
+ .a = try mapValue(u16, try reader.readInt(u16, .little), header.maxval, math.maxInt(u16)),
+ },
+ else => unreachable,
+ }
+ }
+ }
+ return image;
+ }
+
+ pub fn writeImage(allocator: Allocator, stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) ImageWriteError!void {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceWriter(stream);
+ const writer = buffered_stream.writer();
+
+ var comments = std.ArrayList([]const u8).init(allocator);
+ defer comments.deinit();
+ try comments.appendSlice(switch (encoder_options) {
+ .pam => |p| p.comments,
+ else => &.{},
+ });
+
+ var duration_buffer: [128]u8 = undefined;
+ const add_duration_as_comment = switch (encoder_options) {
+ .pam => |p| p.add_duration_as_comment,
+ else => false,
+ };
+
+ {
+ if (add_duration_as_comment and image.isAnimation()) {
+ try comments.append(try fmt.bufPrint(&duration_buffer, "loop count: {d}", .{image.animation.loop_count}));
+ }
+ defer {
+ if (add_duration_as_comment and image.isAnimation()) _ = comments.pop();
+ }
+
+ try writeFrame(writer, image, .{ .pam = .{ .comments = comments.items } });
+ }
+
+ for (image.animation.frames.items) |frame| {
+ if (add_duration_as_comment)
+ try comments.append(try fmt.bufPrint(&duration_buffer, "duration: {d}", .{frame.duration}));
+ defer {
+ if (add_duration_as_comment) _ = comments.pop();
+ }
+
+ const frame_img = Image{ .pixels = frame.pixels, .width = image.width, .height = image.height, .allocator = image.allocator };
+
+ try writeFrame(writer, frame_img, .{ .pam = .{ .comments = comments.items } });
+ }
+
+ try buffered_stream.flush();
+ }
+
+ pub fn writeFrame(writer: anytype, frame: Image, encoder_options: Image.EncoderOptions) ImageWriteError!void {
+ var header = try Header.fromImage(frame);
+ header.comments = encoder_options.pam.comments;
+ try header.write(writer);
+ for (0..frame.height) |row| {
+ const offset = row * frame.width;
+ for (0..frame.width) |column| {
+ switch (frame.pixels) {
+ .grayscale1 => |x| try writer.writeByte(x[offset + column].value),
+ .grayscale4 => |x| try writer.writeByte(x[offset + column].value),
+ .grayscale8 => |x| try writer.writeByte(x[offset + column].value),
+ .grayscale16 => |x| try writer.writeInt(u16, x[offset + column].value, .little),
+ .grayscale8Alpha => |x| {
+ try writer.writeByte(x[offset + column].value);
+ try writer.writeByte(x[offset + column].alpha);
+ },
+ .grayscale16Alpha => |x| {
+ try writer.writeInt(u16, x[offset + column].value, .little);
+ try writer.writeInt(u16, x[offset + column].alpha, .little);
+ },
+ .bgr555 => |x| {
+ try writer.writeByte(x[offset + column].r);
+ try writer.writeByte(x[offset + column].g);
+ try writer.writeByte(x[offset + column].b);
+ },
+ .rgb555 => |x| {
+ try writer.writeByte(x[offset + column].r);
+ try writer.writeByte(x[offset + column].g);
+ try writer.writeByte(x[offset + column].b);
+ },
+ .rgb24 => |x| {
+ try writer.writeByte(x[offset + column].r);
+ try writer.writeByte(x[offset + column].g);
+ try writer.writeByte(x[offset + column].b);
+ },
+ .rgba32 => |x| {
+ try writer.writeByte(x[offset + column].r);
+ try writer.writeByte(x[offset + column].g);
+ try writer.writeByte(x[offset + column].b);
+ try writer.writeByte(x[offset + column].a);
+ },
+ .bgr24 => |x| {
+ try writer.writeByte(x[offset + column].r);
+ try writer.writeByte(x[offset + column].g);
+ try writer.writeByte(x[offset + column].b);
+ },
+ .bgra32 => |x| {
+ try writer.writeByte(x[offset + column].r);
+ try writer.writeByte(x[offset + column].g);
+ try writer.writeByte(x[offset + column].b);
+ try writer.writeByte(x[offset + column].a);
+ },
+ .rgb48 => |x| {
+ try writer.writeInt(u16, x[offset + column].r, .little);
+ try writer.writeInt(u16, x[offset + column].g, .little);
+ try writer.writeInt(u16, x[offset + column].b, .little);
+ },
+ .rgba64 => |x| {
+ try writer.writeInt(u16, x[offset + column].r, .little);
+ try writer.writeInt(u16, x[offset + column].g, .little);
+ try writer.writeInt(u16, x[offset + column].b, .little);
+ try writer.writeInt(u16, x[offset + column].a, .little);
+ },
+ else => unreachable,
+
+ }
+ }
+ }
+ }
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/pcx.zig.html b/docs/src/zigimg/src/formats/pcx.zig.html
new file mode 100644
index 0000000..094acb2
--- /dev/null
+++ b/docs/src/zigimg/src/formats/pcx.zig.html
@@ -0,0 +1,862 @@
+
+
+
+
+
src/formats/pcx.zig - source view
+
+
+
+
+
+
+
+
+
+const Allocator = std.mem.Allocator;
+const buffered_stream_source = @import("../buffered_stream_source.zig");
+const color = @import("../color.zig");
+const FormatInterface = @import("../FormatInterface.zig");
+const Image = @import("../Image.zig");
+const ImageError = Image.Error;
+const ImageReadError = Image.ReadError;
+const ImageWriteError = Image.WriteError;
+const PixelFormat = @import("../pixel_format.zig").PixelFormat;
+const std = @import("std");
+const utils = @import("../utils.zig");
+const simd = @import("../simd.zig");
+
+const MagicHeader: u8 = 0x0A;
+const Version: u8 = 5;
+const VGAPaletteIdentifier: u8 = 0x0C;
+
+pub const Compression = enum(u8) {
+ none,
+ rle,
+};
+
+pub const PaletteInfo = enum(u16) {
+ color = 1,
+ grayscale = 2,
+ _,
+};
+
+pub const PCXHeader = extern struct {
+ id: u8 = MagicHeader,
+ version: u8 = Version,
+ compression: Compression = .rle,
+ bpp: u8 = 0,
+ xmin: u16 align(1) = 0,
+ ymin: u16 align(1) = 0,
+ xmax: u16 align(1) = 0,
+ ymax: u16 align(1) = 0,
+ horizontal_dpi: u16 align(1) = 320,
+
+ vertical_dpi: u16 align(1) = 200,
+
+ builtin_palette: [16]color.Rgb24 = [_]color.Rgb24{.{ .r = 0, .g = 0, .b = 0 }} ** 16,
+ _reserved0: u8 = 0,
+ planes: u8 = 0,
+ stride: u16 align(1) = 0,
+ palette_information: PaletteInfo align(1) = .color,
+ screen_width: u16 align(1) = 0,
+ screen_height: u16 align(1) = 0,
+ padding: [54]u8 = [_]u8{0} ** 54,
+
+ comptime {
+ std.debug.assert(@sizeOf(PCXHeader) == 128);
+ }
+};
+
+const RLEPairMask = 0xC0;
+const RLELengthMask = 0xFF - RLEPairMask;
+
+const RLEDecoder = struct {
+ const Run = struct {
+ value: u8,
+ remaining: usize,
+ };
+
+ reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader,
+ current_run: ?Run,
+
+ fn init(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) RLEDecoder {
+ return RLEDecoder{
+ .reader = reader,
+ .current_run = null,
+ };
+ }
+
+ fn readByte(self: *RLEDecoder) ImageReadError!u8 {
+ if (self.current_run) |*run| {
+ const result = run.value;
+ run.remaining -= 1;
+ if (run.remaining == 0) {
+ self.current_run = null;
+ }
+ return result;
+ } else {
+ while (true) {
+ const byte = try self.reader.readByte();
+ if (byte == RLEPairMask)
+
+ continue;
+ if ((byte & RLEPairMask) == RLEPairMask) {
+ const len = byte & RLELengthMask;
+ std.debug.assert(len > 0);
+ const result = try self.reader.readByte();
+ if (len > 1) {
+
+
+ self.current_run = .{
+ .value = result,
+ .remaining = len - 1,
+ };
+ }
+ return result;
+ } else {
+ return byte;
+ }
+ }
+ }
+ }
+
+ fn finish(decoder: RLEDecoder) ImageReadError!void {
+ if (decoder.current_run != null) {
+ return ImageReadError.InvalidData;
+ }
+ }
+};
+
+const RLEPair = packed struct(u8) {
+ length: u6 = 0,
+ identifier: u2 = (1 << 2) - 1,
+};
+
+const RLEMinLength = 2;
+const RLEMaxLength = (1 << 6) - 1;
+
+fn flushRLE(writer: anytype, value: u8, count: usize) !void {
+ var current_count = count;
+ while (current_count > 0) {
+ const length_to_write = @min(current_count, RLEMaxLength);
+
+ if (length_to_write >= RLEMinLength) {
+ try flushRlePair(writer, value, length_to_write);
+ } else {
+ try flushRawBytes(writer, value, length_to_write);
+ }
+
+ current_count -= length_to_write;
+ }
+}
+
+inline fn flushRlePair(writer: anytype, value: u8, count: usize) !void {
+ const rle_pair = RLEPair{
+ .length = @truncate(count),
+ };
+ try writer.writeByte(@bitCast(rle_pair));
+ try writer.writeByte(value);
+}
+
+inline fn flushRawBytes(writer: anytype, value: u8, count: usize) !void {
+
+
+ if ((value & RLEPairMask) == RLEPairMask) {
+ for (0..count) |_| {
+ try flushRlePair(writer, value, 1);
+ }
+ } else {
+ for (0..count) |_| {
+ try writer.writeByte(value);
+ }
+ }
+}
+
+const RLEFastEncoder = struct {
+ const LengthToCheck = 16;
+ const VectorType = @Vector(LengthToCheck, u8);
+
+ pub fn encode(source_data: []const u8, writer: anytype) !void {
+ if (source_data.len == 0) {
+ return;
+ }
+
+ var index: usize = 0;
+
+ var total_similar_count: usize = 0;
+
+ var current_byte: u8 = 0;
+
+ while (index < source_data.len and (index + LengthToCheck) <= source_data.len) {
+
+
+ current_byte = source_data[index];
+
+ const current_byte_splatted: VectorType = @splat(current_byte);
+ const compare_chunk = simd.load(source_data[index..], VectorType, 0);
+
+ const compare_mask = (current_byte_splatted == compare_chunk);
+ const inverted_mask = ~@as(u16, @bitCast(compare_mask));
+ const current_similar_count = @ctz(inverted_mask);
+
+ if (current_similar_count == LengthToCheck) {
+ total_similar_count += current_similar_count;
+ index += current_similar_count;
+ } else {
+ total_similar_count += current_similar_count;
+
+ try flushRLE(writer, current_byte, total_similar_count);
+
+ total_similar_count = 0;
+
+ index += current_similar_count;
+ }
+ }
+
+ try flushRLE(writer, current_byte, total_similar_count);
+
+
+
+ total_similar_count = 0;
+ if (index < source_data.len) {
+ current_byte = source_data[index];
+
+ while (index < source_data.len) {
+ const read_byte = source_data[index];
+ if (read_byte == current_byte) {
+ total_similar_count += 1;
+ } else {
+ try flushRLE(writer, current_byte, total_similar_count);
+
+ current_byte = read_byte;
+ total_similar_count = 1;
+ }
+
+ index += 1;
+ }
+
+ try flushRLE(writer, current_byte, total_similar_count);
+ }
+ }
+};
+
+test "PCX RLE Fast encoder" {
+ const uncompressed_data = [_]u8{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 64, 64, 2, 2, 2, 2, 2, 215, 215, 215, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 200, 200, 200, 200, 210, 210 };
+ const compressed_data = [_]u8{ 0xC9, 0x01, 0xC2, 0x40, 0xC5, 0x02, 0xC3, 0xD7, 0xCA, 0x03, 0xC4, 0xC8, 0xC2, 0xD2 };
+
+ var result_list = std.ArrayList(u8).init(std.testing.allocator);
+ defer result_list.deinit();
+
+ const writer = result_list.writer();
+
+ try RLEFastEncoder.encode(uncompressed_data[0..], writer);
+
+ try std.testing.expectEqualSlices(u8, compressed_data[0..], result_list.items);
+}
+
+test "PCX RLE Fast encoder should encore more than 63 bytes similar" {
+ const first_uncompressed_part = [_]u8{0x45} ** 65;
+ const second_uncompresse_part = [_]u8{ 0x1, 0x1, 0x1, 0x1 };
+ const uncompressed_data = first_uncompressed_part ++ second_uncompresse_part;
+
+ const compressed_data = [_]u8{ 0xFF, 0x45, 0x45, 0x45, 0xC4, 0x1 };
+
+ var result_list = std.ArrayList(u8).init(std.testing.allocator);
+ defer result_list.deinit();
+
+ const writer = result_list.writer();
+
+ try RLEFastEncoder.encode(uncompressed_data[0..], writer);
+
+ try std.testing.expectEqualSlices(u8, compressed_data[0..], result_list.items);
+}
+
+const RLEStreamEncoder = struct {
+ rle_byte: ?u8 = null,
+ length: usize = 0,
+
+ pub fn encode(self: *RLEStreamEncoder, writer: anytype, bytes: []const u8) !void {
+ for (bytes) |byte| {
+ try self.encodeByte(writer, byte);
+ }
+ }
+
+ pub fn encodeByte(self: *RLEStreamEncoder, writer: anytype, byte: u8) !void {
+ if (self.rle_byte == null) {
+ self.rle_byte = byte;
+ self.length = 1;
+ return;
+ }
+
+ if (self.rle_byte) |rle_byte| {
+ if (rle_byte == byte) {
+ self.length += 1;
+ } else {
+ try flushRLE(writer, rle_byte, self.length);
+
+ self.length = 1;
+ self.rle_byte = byte;
+ }
+ }
+ }
+
+ pub fn flush(self: *RLEStreamEncoder, writer: anytype) !void {
+ if (self.length == 0) {
+ return;
+ }
+
+ if (self.rle_byte) |check_byte| {
+ try flushRLE(writer, check_byte, self.length);
+ }
+ }
+};
+
+pub const PCX = struct {
+ header: PCXHeader = .{},
+
+ pub const EncoderOptions = struct {};
+
+ pub fn formatInterface() FormatInterface {
+ return FormatInterface{
+ .format = format,
+ .formatDetect = formatDetect,
+ .readImage = readImage,
+ .writeImage = writeImage,
+ };
+ }
+
+ pub fn format() Image.Format {
+ return Image.Format.pcx;
+ }
+
+ pub fn formatDetect(stream: *Image.Stream) ImageReadError!bool {
+ var magic_number_bufffer: [2]u8 = undefined;
+ _ = try stream.read(magic_number_bufffer[0..]);
+
+ if (magic_number_bufffer[0] != MagicHeader) {
+ return false;
+ }
+
+ if (magic_number_bufffer[1] > Version) {
+ return false;
+ }
+
+ return true;
+ }
+
+ pub fn readImage(allocator: Allocator, stream: *Image.Stream) ImageReadError!Image {
+ var result = Image.init(allocator);
+ errdefer result.deinit();
+ var pcx = PCX{};
+
+ const pixels = try pcx.read(allocator, stream);
+
+ result.width = pcx.width();
+ result.height = pcx.height();
+ result.pixels = pixels;
+
+ return result;
+ }
+
+ pub fn writeImage(allocator: Allocator, stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) ImageWriteError!void {
+ _ = allocator;
+ _ = encoder_options;
+
+ var pcx = PCX{};
+
+ if (image.width > std.math.maxInt(u16) or image.height > std.math.maxInt(u16)) {
+ return ImageWriteError.Unsupported;
+ }
+
+ pcx.header.xmax = @truncate(image.width - 1);
+ pcx.header.ymax = @truncate(image.height - 1);
+
+
+
+ switch (image.pixels) {
+ .indexed1 => |pixels| {
+ pcx.header.bpp = 1;
+ pcx.header.planes = 1;
+
+ pcx.fillPalette(pixels.palette);
+ },
+ .indexed4 => |pixels| {
+ pcx.header.bpp = 4;
+ pcx.header.planes = 1;
+
+ pcx.fillPalette(pixels.palette);
+ },
+ .indexed8 => {
+ pcx.header.bpp = 8;
+ pcx.header.planes = 1;
+ },
+ .rgb24 => {
+ pcx.header.bpp = 8;
+ pcx.header.planes = 3;
+ },
+ else => {
+ return ImageWriteError.Unsupported;
+ },
+ }
+
+ pcx.header.stride = @as(u16, @intFromFloat((@as(f32, @floatFromInt(image.width)) / 8.0) * @as(f32, @floatFromInt(pcx.header.bpp))));
+
+
+ pcx.header.stride += (pcx.header.stride & 0x1);
+
+ try pcx.write(stream, image.pixels);
+ }
+
+ pub fn pixelFormat(self: PCX) ImageReadError!PixelFormat {
+ if (self.header.planes == 1) {
+ switch (self.header.bpp) {
+ 1 => return PixelFormat.indexed1,
+ 4 => return PixelFormat.indexed4,
+ 8 => return PixelFormat.indexed8,
+ else => return ImageError.Unsupported,
+ }
+ } else if (self.header.planes == 3) {
+ switch (self.header.bpp) {
+ 8 => return PixelFormat.rgb24,
+ else => return ImageError.Unsupported,
+ }
+ } else {
+ return ImageError.Unsupported;
+ }
+ }
+
+ pub fn width(self: PCX) usize {
+ return self.header.xmax - self.header.xmin + 1;
+ }
+
+ pub fn height(self: PCX) usize {
+ return self.header.ymax - self.header.ymin + 1;
+ }
+
+ pub fn read(self: *PCX, allocator: Allocator, stream: *Image.Stream) ImageReadError!color.PixelStorage {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);
+ const reader = buffered_stream.reader();
+ self.header = try utils.readStruct(reader, PCXHeader, .little);
+
+ if (self.header.id != 0x0A) {
+ return ImageReadError.InvalidData;
+ }
+
+ if (self.header.version > 0x05) {
+ return ImageReadError.InvalidData;
+ }
+
+ if (self.header.planes > 3) {
+ return ImageError.Unsupported;
+ }
+
+ const pixel_format = try self.pixelFormat();
+
+ const image_width = self.width();
+ const image_height = self.height();
+
+ const has_dummy_byte = (@as(i16, @bitCast(self.header.stride)) - @as(isize, @bitCast(image_width))) == 1;
+ const actual_width = if (has_dummy_byte) image_width + 1 else image_width;
+
+ var pixels = try color.PixelStorage.init(allocator, pixel_format, image_width * image_height);
+ errdefer pixels.deinit(allocator);
+
+ var decoder = RLEDecoder.init(reader);
+
+ const scanline_length = (self.header.stride * self.header.planes);
+
+ var y: usize = 0;
+ while (y < image_height) : (y += 1) {
+ var offset: usize = 0;
+ var x: usize = 0;
+
+ const y_stride = y * image_width;
+
+
+
+ while (offset < scanline_length and x < image_width) : (offset += 1) {
+ const byte = try decoder.readByte();
+ switch (pixels) {
+ .indexed1 => |storage| {
+ var i: usize = 0;
+ while (i < 8) : (i += 1) {
+ if (x < image_width) {
+ storage.indices[y_stride + x] = @intCast((byte >> (7 - @as(u3, @intCast(i)))) & 0x01);
+ x += 1;
+ }
+ }
+ },
+ .indexed4 => |storage| {
+ storage.indices[y_stride + x] = @truncate(byte >> 4);
+ x += 1;
+ if (x < image_width) {
+ storage.indices[y_stride + x] = @truncate(byte);
+ x += 1;
+ }
+ },
+ .indexed8 => |storage| {
+ storage.indices[y_stride + x] = byte;
+ x += 1;
+ },
+ .rgb24 => |storage| {
+ if (has_dummy_byte and byte == 0x00) {
+ continue;
+ }
+ const pixel_x = offset % (actual_width);
+ const current_color = offset / (actual_width);
+ switch (current_color) {
+ 0 => {
+ storage[y_stride + pixel_x].r = byte;
+ },
+ 1 => {
+ storage[y_stride + pixel_x].g = byte;
+ },
+ 2 => {
+ storage[y_stride + pixel_x].b = byte;
+ },
+ else => {},
+ }
+
+ if (pixel_x > 0 and (pixel_x % self.header.planes) == 0) {
+ x += 1;
+ }
+ },
+ else => return ImageError.Unsupported,
+ }
+ }
+
+
+
+ while (offset < self.header.stride) : (offset += 1) {
+ _ = try decoder.readByte();
+ }
+ }
+
+ try decoder.finish();
+
+ if (pixel_format == .indexed1 or pixel_format == .indexed4 or pixel_format == .indexed8) {
+ var palette = switch (pixels) {
+ .indexed1 => |*storage| storage.palette[0..],
+ .indexed4 => |*storage| storage.palette[0..],
+ .indexed8 => |*storage| storage.palette[0..],
+ else => undefined,
+ };
+
+ const effective_len = @min(palette.len, self.header.builtin_palette.len);
+ for (0..effective_len) |index| {
+ palette[index].r = self.header.builtin_palette[index].r;
+ palette[index].g = self.header.builtin_palette[index].g;
+ palette[index].b = self.header.builtin_palette[index].b;
+ palette[index].a = 255;
+ }
+
+ if (pixels == .indexed8) {
+ const end_pos = try buffered_stream.getEndPos();
+ try buffered_stream.seekTo(end_pos - 769);
+
+ if ((try reader.readByte()) != VGAPaletteIdentifier) {
+ return ImageReadError.InvalidData;
+ }
+
+ for (palette) |*current_entry| {
+ current_entry.r = try reader.readByte();
+ current_entry.g = try reader.readByte();
+ current_entry.b = try reader.readByte();
+ current_entry.a = 255;
+ }
+ }
+ }
+
+ return pixels;
+ }
+
+ pub fn write(self: PCX, stream: *Image.Stream, pixels: color.PixelStorage) Image.WriteError!void {
+ switch (pixels) {
+ .indexed1,
+ .indexed4,
+ .indexed8,
+ .rgb24,
+ => {
+
+
+ },
+ else => {
+ return ImageWriteError.Unsupported;
+ },
+ }
+
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceWriter(stream);
+
+ const writer = buffered_stream.writer();
+
+ try utils.writeStruct(writer, self.header, .little);
+
+ const actual_width = self.width();
+ const is_even = ((actual_width & 0x1) == 0);
+
+ switch (pixels) {
+ .indexed1 => |indexed| {
+ try self.writeIndexed1(writer, indexed);
+ },
+ .indexed4 => |indexed| {
+ try self.writeIndexed4(writer, indexed);
+ },
+ .indexed8 => |indexed| {
+ if (is_even) {
+ try writeIndexed8Even(writer, indexed);
+ } else {
+ try self.writeIndexed8Odd(writer, indexed);
+ }
+
+
+
+ try writer.writeByte(VGAPaletteIdentifier);
+ for (pixels.indexed8.palette) |current_entry| {
+ const rgb24_color = color.Rgb24.fromU32Rgba(current_entry.toU32Rgba());
+ try utils.writeStruct(writer, rgb24_color, .little);
+ }
+ },
+ .rgb24 => |data| {
+ try self.writeRgb24(writer, data);
+ },
+ else => {
+ return ImageWriteError.Unsupported;
+ },
+ }
+
+ try buffered_stream.flush();
+ }
+
+ fn fillPalette(self: *PCX, palette: []const color.Rgba32) void {
+ const effective_len = @min(palette.len, self.header.builtin_palette.len);
+ for (0..effective_len) |index| {
+ self.header.builtin_palette[index].r = palette[index].r;
+ self.header.builtin_palette[index].g = palette[index].g;
+ self.header.builtin_palette[index].b = palette[index].b;
+ }
+ }
+
+ fn writeIndexed1(self: *const PCX, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, indexed: color.IndexedStorage1) Image.WriteError!void {
+ var rle_encoder = RLEStreamEncoder{};
+
+ const image_width = self.width();
+ const image_height = self.height();
+
+ const is_even = ((image_width & 0x1) == 0);
+
+ for (0..image_height) |y| {
+ const stride = y * image_width;
+
+ var current_byte: u8 = 0;
+
+ for (0..image_width) |x| {
+ const pixel = indexed.indices[stride + x];
+
+ const bit = @as(u3, @intCast(7 - (x % 8)));
+
+ current_byte |= @as(u8, pixel) << bit;
+ if (bit == 0) {
+ try rle_encoder.encodeByte(writer, current_byte);
+ current_byte = 0;
+ }
+ }
+
+ if (!is_even) {
+ try rle_encoder.encodeByte(writer, current_byte);
+ }
+ }
+
+ try rle_encoder.flush(writer);
+ }
+
+ fn writeIndexed4(self: *const PCX, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, indexed: color.IndexedStorage4) Image.WriteError!void {
+ var rle_encoder = RLEStreamEncoder{};
+
+ const image_width = self.width();
+ const image_height = self.height();
+
+ const is_even = ((image_width & 0x1) == 0);
+
+ var current_byte: u8 = 0;
+
+ for (0..image_height) |y| {
+ const stride = y * image_width;
+
+ for (0..image_width) |x| {
+ const pixel = indexed.indices[stride + x];
+
+ if ((x & 0x1) == 0x1) {
+ current_byte |= pixel;
+ try rle_encoder.encodeByte(writer, current_byte);
+ } else {
+ current_byte = @as(u8, pixel) << 4;
+ }
+ }
+
+ if (!is_even) {
+ try rle_encoder.encodeByte(writer, current_byte);
+ }
+ }
+
+ try rle_encoder.flush(writer);
+ }
+
+ fn writeIndexed8Even(writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, indexed: color.IndexedStorage8) Image.WriteError!void {
+ try RLEFastEncoder.encode(indexed.indices, writer);
+ }
+
+ fn writeIndexed8Odd(self: *const PCX, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, indexed: color.IndexedStorage8) Image.WriteError!void {
+ var rle_encoder = RLEStreamEncoder{};
+
+ const image_width = self.width();
+ const image_height = self.height();
+
+ for (0..image_height) |y| {
+ const y_stride = y * image_width;
+
+ const pixel_stride = indexed.indices[y_stride..(y_stride + image_width)];
+ try rle_encoder.encode(writer, pixel_stride);
+ try rle_encoder.encodeByte(writer, 0x00);
+ }
+
+ try rle_encoder.flush(writer);
+ }
+
+ fn writeRgb24(self: *const PCX, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, pixels: []const color.Rgb24) Image.WriteError!void {
+ var rle_encoder = RLEStreamEncoder{};
+
+ const image_width = self.width();
+ const image_height = self.height();
+
+ const is_even = ((image_width & 0x1) == 0);
+
+ for (0..image_height) |y| {
+ const stride = y * image_width;
+
+ for (0..3) |plane| {
+ for (0..image_width) |x| {
+ const current_color = pixels[stride + x];
+ switch (plane) {
+ 0 => try rle_encoder.encodeByte(writer, current_color.r),
+ 1 => try rle_encoder.encodeByte(writer, current_color.g),
+ 2 => try rle_encoder.encodeByte(writer, current_color.b),
+ else => {},
+ }
+ }
+
+ if (!is_even) {
+ try rle_encoder.encodeByte(writer, 0x00);
+ }
+ }
+ }
+
+ try rle_encoder.flush(writer);
+ }
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/png.zig.html b/docs/src/zigimg/src/formats/png.zig.html
new file mode 100644
index 0000000..abb79a7
--- /dev/null
+++ b/docs/src/zigimg/src/formats/png.zig.html
@@ -0,0 +1,351 @@
+
+
+
+
+
src/formats/png.zig - source view
+
+
+
+
+
+
+
+
+
+
+const Allocator = std.mem.Allocator;
+const chunk_writer = @import("png/chunk_writer.zig");
+const color = @import("../color.zig");
+const filter = @import("png/filtering.zig");
+const FormatInterface = @import("../FormatInterface.zig");
+const Image = @import("../Image.zig");
+const ImageReadError = Image.ReadError;
+const ImageWriteError = Image.WriteError;
+const PixelFormat = @import("../pixel_format.zig").PixelFormat;
+const reader = @import("png/reader.zig");
+const std = @import("std");
+const types = @import("png/types.zig");
+const ZlibCompressor = @import("png/zlib_compressor.zig").ZlibCompressor;
+
+pub const HeaderData = types.HeaderData;
+pub const ColorType = types.ColorType;
+pub const CompressionMethod = types.CompressionMethod;
+pub const FilterMethod = types.FilterMethod;
+pub const FilterType = types.FilterType;
+pub const InterlaceMethod = types.InterlaceMethod;
+pub const Chunks = types.Chunks;
+pub const isChunkCritical = reader.isChunkCritical;
+pub const load = reader.load;
+pub const loadHeader = reader.loadHeader;
+pub const loadWithHeader = reader.loadWithHeader;
+pub const ChunkProcessData = reader.ChunkProcessData;
+pub const PaletteProcessData = reader.PaletteProcessData;
+pub const RowProcessData = reader.RowProcessData;
+pub const ReaderProcessor = reader.ReaderProcessor;
+pub const TrnsProcessor = reader.TrnsProcessor;
+pub const PlteProcessor = reader.PlteProcessor;
+pub const ReaderOptions = reader.ReaderOptions;
+pub const DefaultProcessors = reader.DefaultProcessors;
+pub const DefaultOptions = reader.DefaultOptions;
+
+pub const PNG = struct {
+ const Self = @This();
+
+ pub const EncoderOptions = struct {
+
+
+ interlaced: bool = false,
+
+
+ filter_choice: filter.FilterChoice = .heuristic,
+ };
+
+ pub fn formatInterface() FormatInterface {
+ return FormatInterface{
+ .format = format,
+ .formatDetect = formatDetect,
+ .readImage = readImage,
+ .writeImage = writeImage,
+ };
+ }
+
+ pub fn format() Image.Format {
+ return Image.Format.png;
+ }
+
+ pub fn formatDetect(stream: *Image.Stream) ImageReadError!bool {
+ var magic_buffer: [types.magic_header.len]u8 = undefined;
+
+ _ = try stream.reader().readAll(magic_buffer[0..]);
+
+ return std.mem.eql(u8, magic_buffer[0..], types.magic_header[0..]);
+ }
+
+ pub fn readImage(allocator: Allocator, stream: *Image.Stream) ImageReadError!Image {
+ var default_options = DefaultOptions{};
+ return load(stream, allocator, default_options.get());
+ }
+
+ pub fn writeImage(allocator: Allocator, write_stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) ImageWriteError!void {
+ const options = encoder_options.png;
+
+ try ensureWritable(image);
+
+ const header = HeaderData{
+ .width = @truncate(image.width),
+ .height = @truncate(image.height),
+ .bit_depth = image.pixelFormat().bitsPerChannel(),
+ .color_type = try types.ColorType.fromPixelFormat(image.pixelFormat()),
+ .compression_method = .deflate,
+ .filter_method = .adaptive,
+ .interlace_method = if (options.interlaced) .adam7 else .none,
+ };
+
+ std.debug.assert(header.isValid());
+
+ try write(allocator, write_stream, image.pixels, header, options.filter_choice);
+ }
+
+ pub fn write(allocator: Allocator, write_stream: *Image.Stream, pixels: color.PixelStorage, header: HeaderData, filter_choice: filter.FilterChoice) ImageWriteError!void {
+ if (header.interlace_method != .none)
+ return ImageWriteError.Unsupported;
+ if (header.compression_method != .deflate)
+ return ImageWriteError.Unsupported;
+ if (header.filter_method != .adaptive)
+ return ImageWriteError.Unsupported;
+
+ const writer = write_stream.writer();
+
+ try writeSignature(writer);
+ try writeHeader(writer, header);
+ if (PixelFormat.isIndexed(pixels)) {
+ try writePalette(writer, pixels);
+ try writeTransparencyInfo(writer, pixels);
+
+ }
+ try writeData(allocator, writer, pixels, header, filter_choice);
+ try writeTrailer(writer);
+ }
+
+ pub fn ensureWritable(image: Image) !void {
+ if (image.width > std.math.maxInt(u31))
+ return error.Unsupported;
+ if (image.height > std.math.maxInt(u31))
+ return error.Unsupported;
+
+ switch (image.pixels) {
+ .rgb24, .rgb48, .rgba32, .rgba64, .grayscale8, .grayscale16, .grayscale8Alpha, .grayscale16Alpha, .indexed8 => {},
+
+ .grayscale1, .grayscale2, .grayscale4, .indexed1, .indexed2, .indexed4 => return error.Unsupported,
+
+
+
+
+
+ else => return error.Unsupported,
+ }
+ }
+
+ fn writeSignature(writer: anytype) !void {
+ try writer.writeAll(types.magic_header);
+ }
+
+
+
+ fn writeHeader(writer: anytype, header: HeaderData) ImageWriteError!void {
+ var chunk = chunk_writer.chunkWriter(writer, "IHDR");
+ var chunk_wr = chunk.writer();
+
+ try chunk_wr.writeInt(u32, header.width, .big);
+ try chunk_wr.writeInt(u32, header.height, .big);
+ try chunk_wr.writeInt(u8, header.bit_depth, .big);
+ try chunk_wr.writeInt(u8, @intFromEnum(header.color_type), .big);
+ try chunk_wr.writeInt(u8, @intFromEnum(header.compression_method), .big);
+ try chunk_wr.writeInt(u8, @intFromEnum(header.filter_method), .big);
+ try chunk_wr.writeInt(u8, @intFromEnum(header.interlace_method), .big);
+
+ try chunk.flush();
+ }
+
+
+
+ fn writeData(allocator: Allocator, writer: anytype, pixels: color.PixelStorage, header: HeaderData, filter_choice: filter.FilterChoice) ImageWriteError!void {
+
+
+
+
+ var chunks = chunk_writer.chunkWriter(writer, "IDAT");
+ const chunk_wr = chunks.writer();
+
+ var zlib: ZlibCompressor(@TypeOf(chunk_wr)) = undefined;
+ try zlib.init(allocator, chunk_wr);
+
+ try zlib.begin();
+ try filter.filter(zlib.writer(), pixels, filter_choice, header);
+ try zlib.end();
+
+ try chunks.flush();
+ }
+
+
+
+ fn writeTrailer(writer: anytype) ImageWriteError!void {
+ var chunk = chunk_writer.chunkWriter(writer, "IEND");
+ try chunk.flush();
+ }
+
+
+
+ fn writePalette(writer: anytype, pixels: color.PixelStorage) ImageWriteError!void {
+ var chunk = chunk_writer.chunkWriter(writer, "PLTE");
+ var chunk_wr = chunk.writer();
+
+ const palette = switch (pixels) {
+ .indexed1 => |d| d.palette,
+ .indexed2 => |d| d.palette,
+ .indexed4 => |d| d.palette,
+ .indexed8 => |d| d.palette,
+ .indexed16 => return ImageWriteError.Unsupported,
+ else => unreachable,
+ };
+
+ for (palette) |col| {
+ try chunk_wr.writeByte(col.r);
+ try chunk_wr.writeByte(col.g);
+ try chunk_wr.writeByte(col.b);
+ }
+
+ try chunk.flush();
+ }
+
+
+
+ fn writeTransparencyInfo(writer: anytype, pixels: color.PixelStorage) ImageWriteError!void {
+ var chunk = chunk_writer.chunkWriter(writer, "tRNS");
+ var chunk_wr = chunk.writer();
+
+ const palette = switch (pixels) {
+ .indexed1 => |d| d.palette,
+ .indexed2 => |d| d.palette,
+ .indexed4 => |d| d.palette,
+ .indexed8 => |d| d.palette,
+ .indexed16 => return ImageWriteError.Unsupported,
+
+
+ else => unreachable,
+ };
+
+ for (palette) |col| {
+ try chunk_wr.writeByte(col.a);
+ }
+
+ try chunk.flush();
+ }
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/png/chunk_writer.zig.html b/docs/src/zigimg/src/formats/png/chunk_writer.zig.html
new file mode 100644
index 0000000..a828505
--- /dev/null
+++ b/docs/src/zigimg/src/formats/png/chunk_writer.zig.html
@@ -0,0 +1,182 @@
+
+
+
+
+
src/formats/png/chunk_writer.zig - source view
+
+
+
+
+
+
const std = @import("std");
+
+const io = std.io;
+const mem = std.mem;
+
+const Crc = std.hash.crc.Crc32WithPoly(.IEEE);
+
+
+pub fn ChunkWriter(comptime buffer_size: usize, comptime WriterType: type) type {
+ return struct {
+ unbuffered_writer: WriterType,
+ buf: [buffer_size]u8 = undefined,
+ end: usize = 0,
+ section_id: [4]u8,
+
+ pub const Error = WriterType.Error;
+ pub const Writer = io.Writer(*Self, Error, write);
+
+ const Self = @This();
+
+ pub fn flush(self: *Self) !void {
+ try self.unbuffered_writer.writeInt(u32, @as(u32, @truncate(self.end)), .big);
+
+ var crc = Crc.init();
+
+ crc.update(&self.section_id);
+ try self.unbuffered_writer.writeAll(&self.section_id);
+ crc.update(self.buf[0..self.end]);
+ try self.unbuffered_writer.writeAll(self.buf[0..self.end]);
+
+ try self.unbuffered_writer.writeInt(u32, crc.final(), .big);
+
+ self.end = 0;
+ }
+
+ pub fn writer(self: *Self) Writer {
+ return .{ .context = self };
+ }
+
+ pub fn write(self: *Self, bytes: []const u8) Error!usize {
+ if (self.end + bytes.len > self.buf.len) {
+ try self.flush();
+ if (bytes.len > self.buf.len)
+ return self.unbuffered_writer.write(bytes);
+ }
+
+ @memcpy(self.buf[self.end..][0..bytes.len], bytes);
+ self.end += bytes.len;
+ return bytes.len;
+ }
+ };
+}
+
+const ChunkBufferSize = 1 << 14;
+
+
+pub fn chunkWriter(underlying_stream: anytype, comptime id: []const u8) ChunkWriter(ChunkBufferSize, @TypeOf(underlying_stream)) {
+ if (id.len != 4)
+ @compileError("PNG chunk id must be 4 characters");
+
+ return .{ .unbuffered_writer = underlying_stream, .section_id = std.mem.bytesToValue([4]u8, id[0..4]) };
+}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/png/filtering.zig.html b/docs/src/zigimg/src/formats/png/filtering.zig.html
new file mode 100644
index 0000000..96b7fce
--- /dev/null
+++ b/docs/src/zigimg/src/formats/png/filtering.zig.html
@@ -0,0 +1,320 @@
+
+
+
+
+
src/formats/png/filtering.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const color = @import("../../color.zig");
+const PixelFormat = @import("../../pixel_format.zig").PixelFormat;
+const Image = @import("../../Image.zig");
+const HeaderData = @import("types.zig").HeaderData;
+const builtin = @import("builtin");
+
+pub const FilterType = enum(u8) {
+ none = 0,
+ sub = 1,
+ up = 2,
+ average = 3,
+ paeth = 4,
+};
+
+pub const FilterChoiceStrategies = enum {
+ try_all,
+ heuristic,
+ specified,
+};
+
+pub const FilterChoice = union(FilterChoiceStrategies) {
+ try_all,
+ heuristic,
+ specified: FilterType,
+};
+
+pub fn filter(writer: anytype, pixels: color.PixelStorage, filter_choice: FilterChoice, header: HeaderData) Image.WriteError!void {
+ var scanline: color.PixelStorage = undefined;
+ var previous_scanline: ?color.PixelStorage = null;
+
+ const format: PixelFormat = pixels;
+
+ if (format.bitsPerChannel() < 8)
+ return Image.WriteError.Unsupported;
+
+ const pixel_len = format.pixelStride();
+
+ var y: usize = 0;
+ while (y < header.height) : (y += 1) {
+ scanline = pixels.slice(y * header.width, (y + 1) * header.width);
+
+ const filter_type: FilterType = switch (filter_choice) {
+ .try_all => @panic("Unimplemented"),
+ .heuristic => filterChoiceHeuristic(scanline, previous_scanline),
+ .specified => |f| f,
+ };
+
+ try writer.writeByte(@intFromEnum(filter_type));
+
+ for (0..scanline.asBytes().len) |byte_index| {
+ const i = if (builtin.target.cpu.arch.endian() == .little) pixelByteSwappedIndex(scanline, byte_index) else byte_index;
+
+ const sample = scanline.asBytes()[i];
+ const previous: u8 = if (byte_index >= pixel_len) scanline.asBytes()[i - pixel_len] else 0;
+ const above: u8 = if (previous_scanline) |b| b.asBytes()[i] else 0;
+ const above_previous = if (previous_scanline) |b| (if (byte_index >= pixel_len) b.asBytes()[i - pixel_len] else 0) else 0;
+
+ const byte: u8 = switch (filter_type) {
+ .none => sample,
+ .sub => sample -% previous,
+ .up => sample -% above,
+ .average => sample -% average(previous, above),
+ .paeth => sample -% paeth(previous, above, above_previous),
+ };
+
+ try writer.writeByte(byte);
+ }
+ previous_scanline = scanline;
+ }
+}
+
+
+
+fn pixelByteSwappedIndex(storage: color.PixelStorage, index: usize) usize {
+ return switch (storage) {
+ .invalid => index,
+ inline .indexed1, .indexed2, .indexed4, .indexed8, .indexed16 => |data| byteSwappedIndex(@typeInfo(@TypeOf(data.indices)).Pointer.child, index),
+ inline else => |data| byteSwappedIndex(@typeInfo(@TypeOf(data)).Pointer.child, index),
+ };
+}
+
+
+
+fn byteSwappedIndex(comptime T: type, byte_index: usize) usize {
+ const element_index = byte_index / @sizeOf(T);
+ const element_offset = element_index * @sizeOf(T);
+ const index = byte_index % @sizeOf(T);
+ switch (@typeInfo(T)) {
+ .Int => {
+ if (@sizeOf(T) == 1) return byte_index;
+ return element_offset + @sizeOf(T) - 1 - index;
+ },
+ .Struct => |info| {
+ inline for (info.fields) |field| {
+ if (index >= @offsetOf(T, field.name) or index <= @offsetOf(T, field.name) + @sizeOf(field.type)) {
+ if (@sizeOf(field.type) == 1) return byte_index;
+ return element_offset + @sizeOf(field.type) - 1 - index;
+ }
+ }
+ },
+ else => @compileError("type " ++ @typeName(T) ++ " not supported"),
+ }
+}
+
+fn filterChoiceHeuristic(scanline: color.PixelStorage, previous_scanline: ?color.PixelStorage) FilterType {
+ const pixel_len = @as(PixelFormat, scanline).pixelStride();
+
+ const filter_types = [_]FilterType{ .none, .sub, .up, .average, .paeth };
+
+ var previous_bytes: [filter_types.len]u8 = [_]u8{0} ** filter_types.len;
+ var combos: [filter_types.len]usize = [_]usize{0} ** filter_types.len;
+ var scores: [filter_types.len]usize = [_]usize{0} ** filter_types.len;
+
+ for (scanline.asBytes(), 0..) |sample, i| {
+ const previous: u8 = if (i >= pixel_len) scanline.asBytes()[i - pixel_len] else 0;
+ const above: u8 = if (previous_scanline) |b| b.asBytes()[i] else 0;
+ const above_previous = if (previous_scanline) |b| (if (i >= pixel_len) b.asBytes()[i - pixel_len] else 0) else 0;
+
+ inline for (filter_types, &previous_bytes, &combos, &scores) |filter_type, *previous_byte, *combo, *score| {
+ const byte: u8 = switch (filter_type) {
+ .none => sample,
+ .sub => sample -% previous,
+ .up => sample -% above,
+ .average => sample -% average(previous, above),
+ .paeth => sample -% paeth(previous, above, above_previous),
+ };
+
+ if (byte == previous_byte.*) {
+ combo.* += 1;
+ } else {
+ score.* += combo.* * combo.*;
+ combo.* = 0;
+ previous_byte.* = byte;
+ }
+ }
+ }
+
+ var best: FilterType = .none;
+ var max_score: usize = 0;
+ inline for (filter_types, scores) |filter_type, score| {
+ if (score > max_score) {
+ max_score = score;
+ best = filter_type;
+ }
+ }
+ return best;
+}
+
+fn average(a: u9, b: u9) u8 {
+ return @truncate((a + b) / 2);
+}
+
+fn paeth(b4: u8, up: u8, b4_up: u8) u8 {
+ const p: i16 = @as(i16, @intCast(b4)) + up - b4_up;
+ const pa = @abs(p - b4);
+ const pb = @abs(p - up);
+ const pc = @abs(p - b4_up);
+
+ if (pa <= pb and pa <= pc) {
+ return b4;
+ } else if (pb <= pc) {
+ return up;
+ } else {
+ return b4_up;
+ }
+}
+
+test "filtering 16-bit grayscale pixels uses correct endianess" {
+ var output_bytes = std.ArrayList(u8).init(std.testing.allocator);
+ defer output_bytes.deinit();
+
+ const pixels = try std.testing.allocator.dupe(color.Grayscale16, &.{
+ .{ .value = 0xF },
+ .{ .value = 0xFF },
+ .{ .value = 0xFFF },
+ .{ .value = 0xFFFF },
+ .{ .value = 0xF },
+ .{ .value = 0xFF },
+ .{ .value = 0xFFF },
+ .{ .value = 0xFFFF },
+ });
+ defer std.testing.allocator.free(pixels);
+
+
+
+ try filter(output_bytes.writer(), .{ .grayscale16 = pixels }, .{ .specified = .none }, .{
+ .width = 4,
+ .height = 2,
+ .bit_depth = 16,
+ .color_type = .grayscale,
+ .compression_method = .deflate,
+ .filter_method = .adaptive,
+ .interlace_method = .none,
+ });
+
+ try std.testing.expectEqualSlices(u8, &.{
+ 0x00, 0x00, 0x0F, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF,
+
+ 0x00, 0x00, 0x0F, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF,
+
+ }, output_bytes.items);
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/png/reader.zig.html b/docs/src/zigimg/src/formats/png/reader.zig.html
new file mode 100644
index 0000000..60fb29b
--- /dev/null
+++ b/docs/src/zigimg/src/formats/png/reader.zig.html
@@ -0,0 +1,1240 @@
+
+
+
+
+
src/formats/png/reader.zig - source view
+
+
+
+
+
+
const Allocator = std.mem.Allocator;
+const buffered_stream_source = @import("../../buffered_stream_source.zig");
+const color = @import("../../color.zig");
+const Crc32 = std.hash.Crc32;
+const File = std.fs.File;
+const Image = @import("../../Image.zig");
+const mem = std.mem;
+const PixelFormat = @import("../../pixel_format.zig").PixelFormat;
+const PixelStorage = color.PixelStorage;
+const png = @import("types.zig");
+const std = @import("std");
+const utils = @import("../../utils.zig");
+
+
+
+
+pub fn isChunkCritical(id: u32) bool {
+ return (id & 0x20000000) == 0;
+}
+
+fn callChunkProcessors(processors: []ReaderProcessor, chunk_process_data: *ChunkProcessData) Image.ReadError!void {
+ const id = chunk_process_data.chunk_id;
+
+
+ var processed = isChunkCritical(id);
+ for (processors) |*processor| {
+ if (processor.id == id or processor.id == png.Chunks.Any.id) {
+ const new_format = try processor.processChunk(chunk_process_data);
+ std.debug.assert(new_format.pixelStride() >= chunk_process_data.current_format.pixelStride());
+ chunk_process_data.current_format = new_format;
+ if (!processed) {
+
+
+ processed = true;
+ break;
+ }
+ }
+ }
+
+
+
+ if (!processed) {
+ try chunk_process_data.stream.seekBy(@intCast(chunk_process_data.chunk_length + 4));
+ }
+}
+
+
+
+
+
+
+
+
+
+const IDatChunksReader = struct {
+ stream: *buffered_stream_source.DefaultBufferedStreamSourceReader,
+ buffer: [4096]u8 = undefined,
+ data: []u8,
+ processors: []ReaderProcessor,
+ chunk_process_data: *ChunkProcessData,
+ remaining_chunk_length: u32,
+ crc: Crc32,
+
+ const Self = @This();
+
+ fn init(
+ stream: *buffered_stream_source.DefaultBufferedStreamSourceReader,
+ processors: []ReaderProcessor,
+ chunk_process_data: *ChunkProcessData,
+ ) Self {
+ var crc = Crc32.init();
+ crc.update(png.Chunks.IDAT.name);
+ return .{
+ .stream = stream,
+ .data = &[_]u8{},
+ .processors = processors,
+ .chunk_process_data = chunk_process_data,
+ .remaining_chunk_length = chunk_process_data.chunk_length,
+ .crc = crc,
+ };
+ }
+
+ fn fillBuffer(self: *Self, to_read: usize) Image.ReadError!usize {
+ @memcpy(self.buffer[0..self.data.len], self.data);
+ const new_start = self.data.len;
+ var max = self.buffer.len;
+ if (max > self.remaining_chunk_length) {
+ max = self.remaining_chunk_length;
+ }
+ const len = try self.stream.read(self.buffer[new_start..max]);
+ self.data = self.buffer[0 .. new_start + len];
+ self.crc.update(self.data[new_start..]);
+ return if (len < to_read) len else to_read;
+ }
+
+ fn read(self: *Self, dest: []u8) Image.ReadError!usize {
+ if (self.remaining_chunk_length == 0) return 0;
+ const new_dest = dest;
+
+ var reader = self.stream.reader();
+ var to_read = new_dest.len;
+ if (to_read > self.remaining_chunk_length) {
+ to_read = self.remaining_chunk_length;
+ }
+ if (to_read > self.data.len) {
+ to_read = try self.fillBuffer(to_read);
+ }
+ @memcpy(new_dest[0..to_read], self.data[0..to_read]);
+ self.remaining_chunk_length -= @intCast(to_read);
+ self.data = self.data[to_read..];
+
+ if (self.remaining_chunk_length == 0) {
+
+
+ const expected_crc = try reader.readInt(u32, .big);
+ const actual_crc = self.crc.final();
+ if (actual_crc != expected_crc) {
+ return Image.ReadError.InvalidData;
+ }
+
+ try callChunkProcessors(self.processors, self.chunk_process_data);
+
+ self.crc = Crc32.init();
+ self.crc.update(png.Chunks.IDAT.name);
+
+
+
+ const chunk = try utils.readStruct(reader, png.ChunkHeader, .big);
+ if (chunk.type == png.Chunks.IDAT.id) {
+ self.remaining_chunk_length = chunk.length;
+ } else {
+
+
+ try self.stream.seekBy(-@sizeOf(png.ChunkHeader));
+ }
+ }
+
+ return to_read;
+ }
+};
+
+const IDATReader = std.io.Reader(*IDatChunksReader, Image.ReadError, IDatChunksReader.read);
+
+pub fn loadHeader(stream: *Image.Stream) Image.ReadError!png.HeaderData {
+ var reader = stream.reader();
+ var signature: [png.magic_header.len]u8 = undefined;
+ try reader.readNoEof(signature[0..]);
+ if (!mem.eql(u8, signature[0..], png.magic_header)) {
+ return Image.ReadError.InvalidData;
+ }
+
+ const chunk = try utils.readStruct(reader, png.ChunkHeader, .big);
+ if (chunk.type != png.Chunks.IHDR.id) return Image.ReadError.InvalidData;
+ if (chunk.length != @sizeOf(png.HeaderData)) return Image.ReadError.InvalidData;
+
+ var header_data: [@sizeOf(png.HeaderData)]u8 = undefined;
+ try reader.readNoEof(&header_data);
+
+ var struct_stream = std.io.fixedBufferStream(&header_data);
+
+ const header = try utils.readStruct(struct_stream.reader(), png.HeaderData, .big);
+ if (!header.isValid()) return Image.ReadError.InvalidData;
+
+ const expected_crc = try reader.readInt(u32, .big);
+ var crc = Crc32.init();
+ crc.update(png.Chunks.IHDR.name);
+ crc.update(&header_data);
+ const actual_crc = crc.final();
+ if (expected_crc != actual_crc) return Image.ReadError.InvalidData;
+
+ return header;
+}
+
+
+
+
+
+
+
+
+
+
+pub fn load(stream: *Image.Stream, allocator: Allocator, options: ReaderOptions) Image.ReadError!Image {
+ const header = try loadHeader(stream);
+ var result = Image.init(allocator);
+ errdefer result.deinit();
+
+ result.width = header.width;
+ result.height = header.height;
+ result.pixels = try loadWithHeader(stream, &header, allocator, options);
+
+ return result;
+}
+
+
+
+pub fn loadWithHeader(
+ stream: *Image.Stream,
+ header: *const png.HeaderData,
+ allocator: Allocator,
+ in_options: ReaderOptions,
+) Image.ReadError!PixelStorage {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);
+ var options = in_options;
+ var temp_allocator = options.temp_allocator;
+ if (temp_allocator.vtable == &NoopAllocator) {
+ temp_allocator = allocator;
+ }
+
+ var arena_allocator = std.heap.ArenaAllocator.init(temp_allocator);
+ defer arena_allocator.deinit();
+ options.temp_allocator = arena_allocator.allocator();
+
+ var palette: []color.Rgb24 = &[_]color.Rgb24{};
+ var data_found = false;
+ var result: PixelStorage = undefined;
+
+ var chunk_process_data = ChunkProcessData{
+ .stream = &buffered_stream,
+ .chunk_id = png.Chunks.IHDR.id,
+ .chunk_length = @sizeOf(png.HeaderData),
+ .current_format = header.getPixelFormat(),
+ .header = header,
+ .temp_allocator = options.temp_allocator,
+ };
+ try callChunkProcessors(options.processors, &chunk_process_data);
+
+ var reader = buffered_stream.reader();
+
+ while (true) {
+ const chunk = (try utils.readStruct(reader, png.ChunkHeader, .big));
+ chunk_process_data.chunk_id = chunk.type;
+ chunk_process_data.chunk_length = chunk.length;
+
+ switch (chunk.type) {
+ png.Chunks.IHDR.id => {
+ return Image.ReadError.InvalidData;
+
+ },
+ png.Chunks.IEND.id => {
+ if (!data_found) return Image.ReadError.InvalidData;
+ _ = try reader.readInt(u32, .big);
+
+ try callChunkProcessors(options.processors, &chunk_process_data);
+ return result;
+ },
+ png.Chunks.IDAT.id => {
+ if (data_found) return Image.ReadError.InvalidData;
+ if (header.color_type == .indexed and palette.len == 0) {
+ return Image.ReadError.InvalidData;
+ }
+ result = try readAllData(&buffered_stream, header, palette, allocator, &options, &chunk_process_data);
+ data_found = true;
+ },
+ png.Chunks.PLTE.id => {
+ if (!header.allowsPalette()) return Image.ReadError.InvalidData;
+ if (palette.len > 0) return Image.ReadError.InvalidData;
+
+
+ if (data_found) {
+
+
+ try buffered_stream.seekBy(chunk.length + @sizeOf(u32));
+ } else {
+ if (chunk.length % 3 != 0) return Image.ReadError.InvalidData;
+ const palette_entries = chunk.length / 3;
+ if (palette_entries > header.maxPaletteSize()) {
+ return Image.ReadError.InvalidData;
+ }
+ palette = try options.temp_allocator.alloc(color.Rgb24, palette_entries);
+ const palette_bytes = mem.sliceAsBytes(palette);
+ try reader.readNoEof(palette_bytes);
+
+ const expected_crc = try reader.readInt(u32, .big);
+ var crc = Crc32.init();
+ crc.update(png.Chunks.PLTE.name);
+ crc.update(palette_bytes);
+ const actual_crc = crc.final();
+ if (expected_crc != actual_crc) return Image.ReadError.InvalidData;
+ try callChunkProcessors(options.processors, &chunk_process_data);
+ }
+ },
+ else => {
+ try callChunkProcessors(options.processors, &chunk_process_data);
+ },
+ }
+ }
+}
+
+fn readAllData(
+ buffered_stream: *buffered_stream_source.DefaultBufferedStreamSourceReader,
+ header: *const png.HeaderData,
+ palette: []color.Rgb24,
+ allocator: Allocator,
+ options: *const ReaderOptions,
+ chunk_process_data: *ChunkProcessData,
+) Image.ReadError!PixelStorage {
+ const native_endian = comptime @import("builtin").cpu.arch.endian();
+ const is_little_endian = native_endian == .little;
+ const width = header.width;
+ const height = header.height;
+ const channel_count = header.channelCount();
+ const dest_format = chunk_process_data.current_format;
+ var result = try PixelStorage.init(allocator, dest_format, width * height);
+ errdefer result.deinit(allocator);
+ var idat_chunks_reader = IDatChunksReader.init(buffered_stream, options.processors, chunk_process_data);
+ const idat_reader: IDATReader = .{ .context = &idat_chunks_reader };
+ var decompress_stream = std.compress.zlib.decompressStream(options.temp_allocator, idat_reader) catch |err| switch (err) {
+ error.BadHeader, error.InvalidCompression, error.InvalidWindowSize => return Image.ReadError.InvalidData,
+ else => |leftover_err| return leftover_err,
+ };
+ defer decompress_stream.deinit();
+
+ if (palette.len > 0) {
+ var destination_palette = if (result.getPalette()) |result_palette|
+ result_palette
+ else
+ try options.temp_allocator.alloc(color.Rgba32, palette.len);
+ for (palette, 0..) |entry, n| {
+ destination_palette[n] = color.Rgba32.initRgb(entry.r, entry.g, entry.b);
+ }
+ try callPaletteProcessors(options, destination_palette);
+ }
+
+ var destination = result.asBytes();
+
+
+
+ const filter_stride = (header.bit_depth + 7) / 8 * channel_count;
+
+ const line_bytes = header.lineBytes();
+ const virtual_line_bytes = line_bytes + filter_stride;
+ const result_line_bytes: u32 = @intCast(destination.len / height);
+ var tmpbytes = 2 * virtual_line_bytes;
+
+
+ if (header.interlace_method == .adam7) {
+ tmpbytes += result_line_bytes;
+ }
+ var temp_allocator = if (tmpbytes < 128 * 1024) options.temp_allocator else allocator;
+ var tmp_buffer = try temp_allocator.alloc(u8, tmpbytes);
+ defer temp_allocator.free(tmp_buffer);
+ @memset(tmp_buffer, 0);
+ var prev_row = tmp_buffer[0..virtual_line_bytes];
+ var current_row = tmp_buffer[virtual_line_bytes .. 2 * virtual_line_bytes];
+ const pixel_stride: u8 = @intCast(result_line_bytes / width);
+ std.debug.assert(pixel_stride == dest_format.pixelStride());
+
+ var process_row_data = RowProcessData{
+ .dest_row = undefined,
+ .src_format = header.getPixelFormat(),
+ .dest_format = dest_format,
+ .header = header,
+ .temp_allocator = options.temp_allocator,
+ };
+
+ var decompress_reader = decompress_stream.reader();
+
+ if (header.interlace_method == .none) {
+ var i: u32 = 0;
+ while (i < height) : (i += 1) {
+ decompress_reader.readNoEof(current_row[filter_stride - 1 ..]) catch |err| switch (err) {
+ error.CorruptInput, error.BadInternalState, error.BadReaderState, error.UnexpectedEndOfStream, error.EndOfStreamWithNoError, error.WrongChecksum => return Image.ReadError.InvalidData,
+ else => |leftover_err| return leftover_err,
+ };
+ try defilter(current_row, prev_row, filter_stride);
+
+ process_row_data.dest_row = destination[0..result_line_bytes];
+ destination = destination[result_line_bytes..];
+
+
+
+ spreadRowData(
+ process_row_data.dest_row,
+ current_row[filter_stride..],
+ header.bit_depth,
+ channel_count,
+ pixel_stride,
+ is_little_endian,
+ );
+
+ const result_format = try callRowProcessors(options.processors, &process_row_data);
+ if (result_format != dest_format) return Image.ReadError.InvalidData;
+
+ const tmp = prev_row;
+ prev_row = current_row;
+ current_row = tmp;
+ }
+ } else {
+ const start_x = [7]u8{ 0, 4, 0, 2, 0, 1, 0 };
+ const start_y = [7]u8{ 0, 0, 4, 0, 2, 0, 1 };
+ const xinc = [7]u8{ 8, 8, 4, 4, 2, 2, 1 };
+ const yinc = [7]u8{ 8, 8, 8, 4, 4, 2, 2 };
+ const pass_width = [7]u32{
+ (width + 7) / 8,
+ (width + 3) / 8,
+ (width + 3) / 4,
+ (width + 1) / 4,
+ (width + 1) / 2,
+ width / 2,
+ width,
+ };
+ const pass_height = [7]u32{
+ (height + 7) / 8,
+ (height + 7) / 8,
+ (height + 3) / 8,
+ (height + 3) / 4,
+ (height + 1) / 4,
+ (height + 1) / 2,
+ height / 2,
+ };
+ const pixel_bits = header.pixelBits();
+ const deinterlace_bit_depth: u8 = if (header.bit_depth <= 8) 8 else 16;
+ var dest_row = tmp_buffer[virtual_line_bytes * 2 ..];
+
+ var pass: u32 = 0;
+ while (pass < 7) : (pass += 1) {
+ if (pass_width[pass] == 0 or pass_height[pass] == 0) {
+ continue;
+ }
+ const pass_bytes = (pixel_bits * pass_width[pass] + 7) / 8;
+ const pass_length = pass_bytes + filter_stride;
+ const result_pass_line_bytes = pixel_stride * pass_width[pass];
+ const deinterlace_stride = xinc[pass] * pixel_stride;
+ @memset(prev_row, 0);
+ const destx = start_x[pass] * pixel_stride;
+ var desty = start_y[pass];
+ var y: u32 = 0;
+ while (y < pass_height[pass]) : (y += 1) {
+ decompress_reader.readNoEof(current_row[filter_stride - 1 .. pass_length]) catch |err| switch (err) {
+ error.CorruptInput, error.BadInternalState, error.BadReaderState, error.UnexpectedEndOfStream, error.EndOfStreamWithNoError, error.WrongChecksum => return Image.ReadError.InvalidData,
+ else => |leftover_err| return leftover_err,
+ };
+ try defilter(current_row[0..pass_length], prev_row[0..pass_length], filter_stride);
+
+ process_row_data.dest_row = dest_row[0..result_pass_line_bytes];
+
+
+
+ spreadRowData(
+ process_row_data.dest_row,
+ current_row[filter_stride..],
+ header.bit_depth,
+ channel_count,
+ pixel_stride,
+ is_little_endian,
+ );
+
+ const result_format = try callRowProcessors(options.processors, &process_row_data);
+ if (result_format != dest_format) return Image.ReadError.InvalidData;
+
+ const line_start_index = desty * result_line_bytes;
+ const start_byte = line_start_index + destx;
+ const end_byte = line_start_index + result_line_bytes;
+
+
+ spreadRowData(
+ destination[start_byte..end_byte],
+ process_row_data.dest_row,
+ deinterlace_bit_depth,
+ result_format.channelCount(),
+ deinterlace_stride,
+ false,
+ );
+
+ desty += yinc[pass];
+
+ const tmp = prev_row;
+ prev_row = current_row;
+ current_row = tmp;
+ }
+ }
+ }
+
+
+
+ var buf: [8]u8 = undefined;
+ const shouldBeZero = decompress_stream.read(buf[0..]) catch |err| switch (err) {
+ error.CorruptInput, error.BadInternalState, error.BadReaderState, error.UnexpectedEndOfStream, error.EndOfStreamWithNoError, error.WrongChecksum => return Image.ReadError.InvalidData,
+ else => |leftover_err| return leftover_err,
+ };
+
+ std.debug.assert(shouldBeZero == 0);
+
+ return result;
+}
+
+fn callPaletteProcessors(options: *const ReaderOptions, palette: []color.Rgba32) Image.ReadError!void {
+ var process_data = PaletteProcessData{ .palette = palette, .temp_allocator = options.temp_allocator };
+ for (options.processors) |*processor| {
+ try processor.processPalette(&process_data);
+ }
+}
+
+fn defilter(current_row: []u8, prev_row: []u8, filter_stride: u8) Image.ReadError!void {
+ const filter_byte = current_row[filter_stride - 1];
+ if (filter_byte > @intFromEnum(png.FilterType.paeth)) {
+ return Image.ReadError.InvalidData;
+ }
+ const filter: png.FilterType = @enumFromInt(filter_byte);
+ current_row[filter_stride - 1] = 0;
+
+ var x: u32 = filter_stride;
+ switch (filter) {
+ .none => {},
+ .sub => while (x < current_row.len) : (x += 1) {
+ current_row[x] +%= current_row[x - filter_stride];
+ },
+ .up => while (x < current_row.len) : (x += 1) {
+ current_row[x] +%= prev_row[x];
+ },
+ .average => while (x < current_row.len) : (x += 1) {
+ current_row[x] +%= @truncate((@as(u32, @intCast(current_row[x - filter_stride])) + @as(u32, @intCast(prev_row[x]))) / 2);
+ },
+ .paeth => while (x < current_row.len) : (x += 1) {
+ const a = current_row[x - filter_stride];
+ const b = prev_row[x];
+ const c = prev_row[x - filter_stride];
+ var pa: i32 = @as(i32, @intCast(b)) - c;
+ var pb: i32 = @as(i32, @intCast(a)) - c;
+ var pc: i32 = pa + pb;
+ if (pa < 0) pa = -pa;
+ if (pb < 0) pb = -pb;
+ if (pc < 0) pc = -pc;
+
+
+ current_row[x] +%= if (pa <= pb and pa <= pc) a
+ else if (pb <= pc) b
+ else c;
+
+
+ },
+ }
+}
+
+fn spreadRowData(
+ dest_row: []u8,
+ current_row: []u8,
+ bit_depth: u8,
+ channel_count: u8,
+ pixel_stride: u8,
+ comptime byteswap: bool,
+) void {
+ var dest_index: u32 = 0;
+ var source_index: u32 = 0;
+ const result_line_bytes = dest_row.len;
+ switch (bit_depth) {
+ 1, 2, 4 => {
+ while (dest_index < result_line_bytes) {
+
+
+ var shift: i4 = @intCast(8 - bit_depth);
+ var mask = @as(u8, 0xff) << @intCast(shift);
+ while (shift >= 0 and dest_index < result_line_bytes) : (shift -= @as(i4, @intCast(bit_depth))) {
+ dest_row[dest_index] = (current_row[source_index] & mask) >> @as(u3, @intCast(shift));
+ dest_index += pixel_stride;
+ mask >>= @intCast(bit_depth);
+ }
+ source_index += 1;
+ }
+ },
+ 8 => {
+ while (dest_index < result_line_bytes) : (dest_index += pixel_stride) {
+ var c: u32 = 0;
+ while (c < channel_count) : (c += 1) {
+ dest_row[dest_index + c] = current_row[source_index + c];
+ }
+ source_index += channel_count;
+ }
+ },
+ 16 => {
+ const current_row16 = mem.bytesAsSlice(u16, current_row);
+ var dest_row16 = mem.bytesAsSlice(u16, dest_row);
+ const pixel_stride16 = pixel_stride / 2;
+ source_index /= 2;
+ while (dest_index < dest_row16.len) : (dest_index += pixel_stride16) {
+ var c: u32 = 0;
+ while (c < channel_count) : (c += 1) {
+
+
+ dest_row16[dest_index + c] = if (byteswap) @byteSwap(current_row16[source_index + c]) else current_row16[source_index + c];
+ }
+ source_index += channel_count;
+ }
+ },
+ else => unreachable,
+ }
+}
+
+fn callRowProcessors(processors: []ReaderProcessor, process_data: *RowProcessData) Image.ReadError!PixelFormat {
+ const starting_format = process_data.src_format;
+ var result_format = starting_format;
+ for (processors) |*processor| {
+ result_format = try processor.processDataRow(process_data);
+ process_data.src_format = result_format;
+ }
+ process_data.src_format = starting_format;
+ return result_format;
+}
+
+pub const ChunkProcessData = struct {
+ stream: *buffered_stream_source.DefaultBufferedStreamSourceReader,
+ chunk_id: u32,
+ chunk_length: u32,
+ current_format: PixelFormat,
+ header: *const png.HeaderData,
+ temp_allocator: Allocator,
+};
+
+pub const PaletteProcessData = struct {
+ palette: []color.Rgba32,
+ temp_allocator: Allocator,
+};
+
+pub const RowProcessData = struct {
+ dest_row: []u8,
+ src_format: PixelFormat,
+ dest_format: PixelFormat,
+ header: *const png.HeaderData,
+ temp_allocator: Allocator,
+};
+
+pub const ReaderProcessor = struct {
+ id: u32,
+ context: *anyopaque,
+ vtable: *const VTable,
+
+ const VTable = struct {
+ chunk_processor: ?*const fn (context: *anyopaque, data: *ChunkProcessData) Image.ReadError!PixelFormat,
+ palette_processor: ?*const fn (context: *anyopaque, data: *PaletteProcessData) Image.ReadError!void,
+ data_row_processor: ?*const fn (context: *anyopaque, data: *RowProcessData) Image.ReadError!PixelFormat,
+ };
+
+ const Self = @This();
+
+ pub inline fn processChunk(self: *Self, data: *ChunkProcessData) Image.ReadError!PixelFormat {
+ return if (self.vtable.chunk_processor) |cp| cp(self.context, data) else data.current_format;
+ }
+
+ pub inline fn processPalette(self: *Self, data: *PaletteProcessData) Image.ReadError!void {
+ if (self.vtable.palette_processor) |pp| try pp(self.context, data);
+ }
+
+ pub inline fn processDataRow(self: *Self, data: *RowProcessData) Image.ReadError!PixelFormat {
+ return if (self.vtable.data_row_processor) |drp| drp(self.context, data) else data.dest_format;
+ }
+
+ pub fn init(
+ id: u32,
+ context: anytype,
+ comptime chunkProcessorFn: ?fn (ptr: @TypeOf(context), data: *ChunkProcessData) Image.ReadError!PixelFormat,
+ comptime paletteProcessorFn: ?fn (ptr: @TypeOf(context), data: *PaletteProcessData) Image.ReadError!void,
+ comptime dataRowProcessorFn: ?fn (ptr: @TypeOf(context), data: *RowProcessData) Image.ReadError!PixelFormat,
+ ) Self {
+ const Ptr = @TypeOf(context);
+ const ptr_info = @typeInfo(Ptr);
+
+ std.debug.assert(ptr_info == .Pointer);
+
+ std.debug.assert(ptr_info.Pointer.size == .One);
+
+
+ const gen = struct {
+ fn chunkProcessor(ptr: *anyopaque, data: *ChunkProcessData) Image.ReadError!PixelFormat {
+ const self: Ptr = @ptrCast(@alignCast(ptr));
+ return @call(.always_inline, chunkProcessorFn.?, .{ self, data });
+ }
+ fn paletteProcessor(ptr: *anyopaque, data: *PaletteProcessData) Image.ReadError!void {
+ const self: Ptr = @ptrCast(@alignCast(ptr));
+ return @call(.always_inline, paletteProcessorFn.?, .{ self, data });
+ }
+ fn dataRowProcessor(ptr: *anyopaque, data: *RowProcessData) Image.ReadError!PixelFormat {
+ const self: Ptr = @ptrCast(@alignCast(ptr));
+ return @call(.always_inline, dataRowProcessorFn.?, .{ self, data });
+ }
+
+ const vtable = VTable{
+ .chunk_processor = if (chunkProcessorFn == null) null else chunkProcessor,
+ .palette_processor = if (paletteProcessorFn == null) null else paletteProcessor,
+ .data_row_processor = if (dataRowProcessorFn == null) null else dataRowProcessor,
+ };
+ };
+
+ return .{
+ .id = id,
+ .context = context,
+ .vtable = &gen.vtable,
+ };
+ }
+};
+
+pub const TrnsProcessor = struct {
+ const Self = @This();
+ const TRNSData = union(enum) { unset: void, gray: u16, rgb: color.Rgb48, index_alpha: []u8 };
+
+ trns_data: TRNSData = .unset,
+ processed: bool = false,
+
+ pub fn processor(self: *Self) ReaderProcessor {
+ return ReaderProcessor.init(
+ png.Chunks.tRNS.id,
+ self,
+ processChunk,
+ processPalette,
+ processDataRow,
+ );
+ }
+
+ pub fn processChunk(self: *Self, data: *ChunkProcessData) Image.ReadError!PixelFormat {
+
+
+
+
+ var result_format = data.current_format;
+ if (self.processed) {
+ try data.stream.seekBy(data.chunk_length + @sizeOf(u32));
+
+ return result_format;
+ }
+ var reader = data.stream.reader();
+ switch (data.header.getPixelFormat()) {
+ .grayscale1, .grayscale2, .grayscale4, .grayscale8, .grayscale16 => {
+ if (data.chunk_length == 2) {
+ self.trns_data = .{ .gray = try reader.readInt(u16, .big) };
+ result_format = if (result_format == .grayscale16) .grayscale16Alpha else .grayscale8Alpha;
+ } else {
+ try data.stream.seekBy(data.chunk_length);
+
+ }
+ },
+ .indexed1, .indexed2, .indexed4, .indexed8, .indexed16 => {
+ if (data.chunk_length <= data.header.maxPaletteSize()) {
+ self.trns_data = .{ .index_alpha = try data.temp_allocator.alloc(u8, data.chunk_length) };
+ try reader.readNoEof(self.trns_data.index_alpha);
+ } else {
+ try data.stream.seekBy(data.chunk_length);
+
+ }
+ },
+ .rgb24, .rgb48 => {
+ if (data.chunk_length == @sizeOf(color.Rgb48)) {
+ self.trns_data = .{ .rgb = try utils.readStruct(reader, color.Rgb48, .big) };
+ result_format = if (result_format == .rgb48) .rgba64 else .rgba32;
+ } else {
+ try data.stream.seekBy(data.chunk_length);
+
+ }
+ },
+ else => try data.stream.seekBy(data.chunk_length),
+
+ }
+
+
+ try data.stream.seekBy(@sizeOf(u32));
+ return result_format;
+ }
+
+ pub fn processPalette(self: *Self, data: *PaletteProcessData) Image.ReadError!void {
+ self.processed = true;
+ switch (self.trns_data) {
+ .index_alpha => |index_alpha| {
+ for (index_alpha, 0..) |alpha, i| {
+ data.palette[i].a = alpha;
+ }
+ },
+ .unset => return,
+ else => return Image.ReadError.InvalidData,
+ }
+ }
+
+ pub fn processDataRow(self: *Self, data: *RowProcessData) Image.ReadError!PixelFormat {
+ self.processed = true;
+ if (data.src_format.isIndexed() or self.trns_data == .unset) {
+ return data.src_format;
+ }
+ var pixel_stride: u8 = switch (data.dest_format) {
+ .grayscale8Alpha, .grayscale16Alpha => 2,
+ .rgba32, .bgra32 => 4,
+ .rgba64 => 8,
+ else => return data.src_format,
+ };
+ var pixel_pos: u32 = 0;
+
+
+ const isWasm = comptime @import("builtin").target.isWasm();
+ switch (self.trns_data) {
+ .gray => |gray_alpha| {
+ switch (data.src_format) {
+ .grayscale1, .grayscale2, .grayscale4, .grayscale8 => {
+ while (pixel_pos + 1 < data.dest_row.len) : (pixel_pos += pixel_stride) {
+ if (!isWasm) {
+ data.dest_row[pixel_pos + 1] = (data.dest_row[pixel_pos] ^ @as(u8, @truncate(gray_alpha))) *| 255;
+ } else {
+ data.dest_row[pixel_pos + 1] = (data.dest_row[pixel_pos] ^ @as(u8, @truncate(gray_alpha))) * 255;
+ }
+ }
+ return .grayscale8Alpha;
+ },
+ .grayscale16 => {
+ var destination = std.mem.bytesAsSlice(u16, data.dest_row);
+ while (pixel_pos + 1 < destination.len) : (pixel_pos += pixel_stride) {
+
+
+ if (!isWasm) {
+ destination[pixel_pos + 1] = (data.dest_row[pixel_pos] ^ gray_alpha) *| 65535;
+ } else {
+ destination[pixel_pos + 1] = (data.dest_row[pixel_pos] ^ gray_alpha) * 65535;
+ }
+ }
+ return .grayscale16Alpha;
+ },
+ else => unreachable,
+ }
+ },
+ .rgb => |tr_color| {
+ switch (data.src_format) {
+ .rgb24 => {
+ var destination = std.mem.bytesAsSlice(color.Rgba32, data.dest_row);
+ pixel_stride /= 4;
+ while (pixel_pos < destination.len) : (pixel_pos += pixel_stride) {
+ var val = destination[pixel_pos];
+ val.a = if (val.r == tr_color.r and val.g == tr_color.g and val.b == tr_color.b) 0 else 255;
+ destination[pixel_pos] = val;
+ }
+ return .rgba32;
+ },
+ .rgb48 => {
+ var destination = std.mem.bytesAsSlice(color.Rgba64, data.dest_row);
+ pixel_stride = 1;
+ while (pixel_pos < destination.len) : (pixel_pos += pixel_stride) {
+ var val = destination[pixel_pos];
+ val.a = if (val.r == tr_color.r and val.g == tr_color.g and val.b == tr_color.b) 0 else 65535;
+ destination[pixel_pos] = val;
+ }
+ return .rgba64;
+ },
+ else => unreachable,
+ }
+ },
+ else => unreachable,
+ }
+ return data.src_format;
+ }
+};
+
+pub const PlteProcessor = struct {
+ const Self = @This();
+
+ palette: []color.Rgba32 = undefined,
+ processed: bool = false,
+
+ pub fn processor(self: *Self) ReaderProcessor {
+ return ReaderProcessor.init(
+ png.Chunks.PLTE.id,
+ self,
+ processChunk,
+ processPalette,
+ processDataRow,
+ );
+ }
+
+ pub fn processChunk(self: *Self, data: *ChunkProcessData) Image.ReadError!PixelFormat {
+
+
+ var result_format = data.current_format;
+ if (self.processed or !result_format.isIndexed()) {
+ self.processed = true;
+ return result_format;
+ }
+
+ return .rgba32;
+ }
+
+ pub fn processPalette(self: *Self, data: *PaletteProcessData) Image.ReadError!void {
+ self.processed = true;
+ self.palette = data.palette;
+ }
+
+ pub fn processDataRow(self: *Self, data: *RowProcessData) Image.ReadError!PixelFormat {
+ self.processed = true;
+
+ if (!data.src_format.isIndexed() or self.palette.len == 0) {
+ return data.src_format;
+ }
+
+ const pixel_stride: u8 = switch (data.dest_format) {
+ .rgba32, .bgra32 => 4,
+ .rgba64 => 8,
+ else => return data.src_format,
+ };
+
+ var pixel_pos: u32 = 0;
+ switch (data.src_format) {
+ .indexed1, .indexed2, .indexed4, .indexed8 => {
+ while (pixel_pos + 3 < data.dest_row.len) : (pixel_pos += pixel_stride) {
+ const index = data.dest_row[pixel_pos];
+ const entry = self.palette[index];
+ data.dest_row[pixel_pos] = entry.r;
+ data.dest_row[pixel_pos + 1] = entry.g;
+ data.dest_row[pixel_pos + 2] = entry.b;
+ data.dest_row[pixel_pos + 3] = entry.a;
+ }
+ },
+ .indexed16 => {
+ while (pixel_pos + 3 < data.dest_row.len) : (pixel_pos += pixel_stride) {
+ const index = std.mem.bytesToValue(u16, &[2]u8{ data.dest_row[pixel_pos], data.dest_row[pixel_pos + 1] });
+ const entry = self.palette[index];
+ data.dest_row[pixel_pos] = entry.r;
+ data.dest_row[pixel_pos + 1] = entry.g;
+ data.dest_row[pixel_pos + 2] = entry.b;
+ data.dest_row[pixel_pos + 3] = entry.a;
+ }
+ },
+ else => unreachable,
+ }
+
+ return .rgba32;
+ }
+};
+
+
+
+
+
+
+
+
+pub const ReaderOptions = struct {
+
+
+
+
+ temp_allocator: Allocator,
+
+
+
+
+
+
+ processors: []ReaderProcessor = &[_]ReaderProcessor{},
+
+ pub fn init(temp_allocator: Allocator) ReaderOptions {
+ return .{ .temp_allocator = temp_allocator };
+ }
+
+ pub fn initWithProcessors(temp_allocator: Allocator, processors: []ReaderProcessor) ReaderOptions {
+ return .{ .temp_allocator = temp_allocator, .processors = processors };
+ }
+};
+
+const root = @import("root");
+
+
+pub const DefaultProcessors = if (@hasDecl(root, "DefPngProcessors"))
+ root.DefPngProcessors
+else
+ struct {
+ trns_processor: TrnsProcessor = .{},
+ plte_processor: PlteProcessor = .{},
+ processors_buffer: [2]ReaderProcessor = undefined,
+
+ const Self = @This();
+
+ pub fn get(self: *Self) []ReaderProcessor {
+ self.processors_buffer[0] = self.trns_processor.processor();
+ self.processors_buffer[1] = self.plte_processor.processor();
+ return self.processors_buffer[0..];
+ }
+ };
+
+pub const NoopAllocator = Allocator.VTable{ .alloc = undefined, .free = undefined, .resize = undefined };
+
+
+
+
+
+pub const DefaultOptions = if (@hasDecl(root, "DefaultPngOptions"))
+ root.DefaultPngOptions
+else
+ struct {
+ def_processors: DefaultProcessors = .{},
+
+ const Self = @This();
+
+ pub fn get(self: *Self) ReaderOptions {
+ return .{ .temp_allocator = .{ .ptr = undefined, .vtable = &NoopAllocator }, .processors = self.def_processors.get() };
+ }
+ };
+
+
+
+
+test "testDefilter" {
+ var buffer = [_]u8{ 0, 1, 2, 3, 0, 5, 6, 7 };
+
+
+ var current_row: []u8 = buffer[4..];
+ var prev_row: []u8 = buffer[0..4];
+ var filter_stride: u8 = 1;
+
+ try testFilter(png.FilterType.none, current_row, prev_row, filter_stride, &[_]u8{ 0, 5, 6, 7 });
+ try testFilter(png.FilterType.sub, current_row, prev_row, filter_stride, &[_]u8{ 0, 5, 11, 18 });
+ try testFilter(png.FilterType.up, current_row, prev_row, filter_stride, &[_]u8{ 0, 6, 13, 21 });
+ try testFilter(png.FilterType.average, current_row, prev_row, filter_stride, &[_]u8{ 0, 6, 17, 31 });
+ try testFilter(png.FilterType.paeth, current_row, prev_row, filter_stride, &[_]u8{ 0, 7, 24, 55 });
+
+ var buffer16 = [_]u8{ 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 8, 9, 10, 11, 12, 13, 14 };
+ current_row = buffer16[9..];
+ prev_row = buffer16[0..9];
+ filter_stride = 2;
+
+ try testFilter(png.FilterType.none, current_row, prev_row, filter_stride, &[_]u8{ 0, 0, 8, 9, 10, 11, 12, 13, 14 });
+ try testFilter(png.FilterType.sub, current_row, prev_row, filter_stride, &[_]u8{ 0, 0, 8, 9, 18, 20, 30, 33, 44 });
+ try testFilter(png.FilterType.up, current_row, prev_row, filter_stride, &[_]u8{ 0, 0, 9, 11, 21, 24, 35, 39, 51 });
+ try testFilter(png.FilterType.average, current_row, prev_row, filter_stride, &[_]u8{ 0, 0, 9, 12, 27, 32, 51, 58, 80 });
+ try testFilter(png.FilterType.paeth, current_row, prev_row, filter_stride, &[_]u8{ 0, 0, 10, 14, 37, 46, 88, 104, 168 });
+}
+
+fn testFilter(filter_type: png.FilterType, current_row: []u8, prev_row: []u8, filter_stride: u8, expected: []const u8) !void {
+ const expectEqualSlices = std.testing.expectEqualSlices;
+ current_row[filter_stride - 1] = @intFromEnum(filter_type);
+ try defilter(current_row, prev_row, filter_stride);
+ try expectEqualSlices(u8, expected, current_row);
+}
+
+test "spreadRowData" {
+ var channel_count: u8 = 1;
+ var bit_depth: u8 = 1;
+
+
+ var dest_buffer = [_]u8{0} ** 32;
+ var cur_buffer = [_]u8{ 0, 0, 0, 0, 0xa5, 0x7c, 0x39, 0xf2, 0x5b, 0x15, 0x78, 0xd1 };
+ var dest_row: []u8 = dest_buffer[0..16];
+ var current_row: []u8 = cur_buffer[3..6];
+ var filter_stride: u8 = 1;
+ var pixel_stride: u8 = 1;
+ const expectEqualSlices = std.testing.expectEqualSlices;
+
+ spreadRowData(dest_row, current_row[filter_stride..], bit_depth, channel_count, pixel_stride, false);
+ try expectEqualSlices(u8, &[_]u8{ 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0 }, dest_row);
+ dest_row = dest_buffer[0..32];
+ pixel_stride = 2;
+ @memset(dest_row, 0);
+ spreadRowData(dest_row, current_row[filter_stride..], bit_depth, channel_count, pixel_stride, false);
+ try expectEqualSlices(u8, &[_]u8{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0 }, dest_row);
+
+ bit_depth = 2;
+ pixel_stride = 1;
+ dest_row = dest_buffer[0..8];
+ spreadRowData(dest_row, current_row[filter_stride..], bit_depth, channel_count, pixel_stride, false);
+ try expectEqualSlices(u8, &[_]u8{ 2, 2, 1, 1, 1, 3, 3, 0 }, dest_row);
+ dest_row = dest_buffer[0..16];
+ pixel_stride = 2;
+ @memset(dest_row, 0);
+ spreadRowData(dest_row, current_row[filter_stride..], bit_depth, channel_count, pixel_stride, false);
+ try expectEqualSlices(u8, &[_]u8{ 2, 0, 2, 0, 1, 0, 1, 0, 1, 0, 3, 0, 3, 0, 0, 0 }, dest_row);
+
+ bit_depth = 4;
+ pixel_stride = 1;
+ dest_row = dest_buffer[0..4];
+ spreadRowData(dest_row, current_row[filter_stride..], bit_depth, channel_count, pixel_stride, false);
+ try expectEqualSlices(u8, &[_]u8{ 0xa, 0x5, 0x7, 0xc }, dest_row);
+ dest_row = dest_buffer[0..8];
+ pixel_stride = 2;
+ @memset(dest_row, 0);
+ spreadRowData(dest_row, current_row[filter_stride..], bit_depth, channel_count, pixel_stride, false);
+ try expectEqualSlices(u8, &[_]u8{ 0xa, 0, 0x5, 0, 0x7, 0, 0xc, 0 }, dest_row);
+
+ bit_depth = 8;
+ pixel_stride = 1;
+ dest_row = dest_buffer[0..2];
+ spreadRowData(dest_row, current_row[filter_stride..], bit_depth, channel_count, pixel_stride, false);
+ try expectEqualSlices(u8, &[_]u8{ 0xa5, 0x7c }, dest_row);
+ dest_row = dest_buffer[0..4];
+ pixel_stride = 2;
+ @memset(dest_row, 0);
+ spreadRowData(dest_row, current_row[filter_stride..], bit_depth, channel_count, pixel_stride, false);
+ try expectEqualSlices(u8, &[_]u8{ 0xa5, 0, 0x7c, 0 }, dest_row);
+
+ channel_count = 2;
+
+ bit_depth = 8;
+ current_row = cur_buffer[2..8];
+ dest_row = dest_buffer[0..4];
+ filter_stride = 2;
+ pixel_stride = 2;
+ spreadRowData(dest_row, current_row[filter_stride..], bit_depth, channel_count, pixel_stride, false);
+ try expectEqualSlices(u8, &[_]u8{ 0xa5, 0x7c, 0x39, 0xf2 }, dest_row);
+ dest_row = dest_buffer[0..8];
+ @memset(dest_row, 0);
+ pixel_stride = 4;
+ spreadRowData(dest_row, current_row[filter_stride..], bit_depth, channel_count, pixel_stride, false);
+ try expectEqualSlices(u8, &[_]u8{ 0xa5, 0x7c, 0, 0, 0x39, 0xf2, 0, 0 }, dest_row);
+
+ bit_depth = 16;
+ current_row = cur_buffer[0..12];
+ dest_row = dest_buffer[0..8];
+ filter_stride = 4;
+ pixel_stride = 4;
+ spreadRowData(dest_row, current_row[filter_stride..], bit_depth, channel_count, pixel_stride, true);
+ try expectEqualSlices(u8, &[_]u8{ 0x7c, 0xa5, 0xf2, 0x39, 0x15, 0x5b, 0xd1, 0x78 }, dest_row);
+
+ channel_count = 3;
+ bit_depth = 8;
+ current_row = cur_buffer[1..10];
+ dest_row = dest_buffer[0..8];
+ @memset(dest_row, 0);
+ filter_stride = 3;
+ pixel_stride = 4;
+ spreadRowData(dest_row, current_row[filter_stride..], bit_depth, channel_count, pixel_stride, false);
+ try expectEqualSlices(u8, &[_]u8{ 0xa5, 0x7c, 0x39, 0, 0xf2, 0x5b, 0x15, 0 }, dest_row);
+
+ channel_count = 4;
+ bit_depth = 16;
+ var cbuffer16 = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0xa5, 0x7c, 0x39, 0xf2, 0x5b, 0x15, 0x78, 0xd1 };
+ current_row = cbuffer16[0..];
+ dest_row = dest_buffer[0..8];
+ @memset(dest_row, 0);
+ filter_stride = 8;
+ pixel_stride = 8;
+ spreadRowData(dest_row, current_row[filter_stride..], bit_depth, channel_count, pixel_stride, true);
+ try expectEqualSlices(u8, &[_]u8{ 0x7c, 0xa5, 0xf2, 0x39, 0x15, 0x5b, 0xd1, 0x78 }, dest_row);
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/png/types.zig.html b/docs/src/zigimg/src/formats/png/types.zig.html
new file mode 100644
index 0000000..c57d97e
--- /dev/null
+++ b/docs/src/zigimg/src/formats/png/types.zig.html
@@ -0,0 +1,310 @@
+
+
+
+
+
src/formats/png/types.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const utils = @import("../../utils.zig");
+const color = @import("../../color.zig");
+const PixelFormat = @import("../../pixel_format.zig").PixelFormat;
+const Allocator = std.mem.Allocator;
+const Colorf32 = color.Colorf32;
+
+pub const magic_header = "\x89PNG\x0D\x0A\x1A\x0A";
+
+pub const Chunk = struct {
+ id: u32,
+ name: *const [4:0]u8,
+
+ pub fn init(name: *const [4:0]u8) Chunk {
+ return .{ .name = name, .id = std.mem.bigToNative(u32, std.mem.bytesToValue(u32, name)) };
+ }
+};
+
+pub const Chunks = struct {
+ pub const IHDR = Chunk.init("IHDR");
+ pub const PLTE = Chunk.init("PLTE");
+ pub const IDAT = Chunk.init("IDAT");
+ pub const IEND = Chunk.init("IEND");
+ pub const gAMA = Chunk.init("gAMA");
+ pub const sBIT = Chunk.init("sBIT");
+ pub const tEXt = Chunk.init("tEXt");
+ pub const zTXt = Chunk.init("zTXt");
+ pub const iTXt = Chunk.init("iTXt");
+ pub const cHRM = Chunk.init("cHRM");
+ pub const pHYs = Chunk.init("pHYs");
+ pub const tRNS = Chunk.init("tRNS");
+ pub const bKGD = Chunk.init("bKGD");
+ pub const tIME = Chunk.init("tIME");
+ pub const iCCP = Chunk.init("iCCP");
+ pub const sRGB = Chunk.init("sRGB");
+ pub const Any = Chunk.init("_ANY");
+};
+
+pub const ColorType = enum(u8) {
+ grayscale = 0,
+ rgb_color = 2,
+ indexed = 3,
+ grayscale_alpha = 4,
+ rgba_color = 6,
+
+ const Self = @This();
+
+ pub fn channelCount(self: Self) u8 {
+ return switch (self) {
+ .grayscale => 1,
+ .rgb_color => 3,
+ .indexed => 1,
+ .grayscale_alpha => 2,
+ .rgba_color => 4,
+ };
+ }
+
+ pub fn fromPixelFormat(pixel_format: PixelFormat) !Self {
+ return switch (pixel_format) {
+ .rgb24, .rgb48 => .rgb_color,
+
+ .rgba32, .rgba64 => .rgba_color,
+
+ .grayscale1, .grayscale2, .grayscale4, .grayscale8, .grayscale16 => .grayscale,
+
+ .grayscale8Alpha, .grayscale16Alpha => .grayscale_alpha,
+
+ .indexed1, .indexed2, .indexed4, .indexed8 => .indexed,
+
+ else => return error.Unsupported,
+ };
+ }
+};
+
+pub const FilterType = enum(u8) {
+ none = 0,
+ sub = 1,
+ up = 2,
+ average = 3,
+ paeth = 4,
+};
+
+pub const InterlaceMethod = enum(u8) {
+ none = 0,
+ adam7 = 1,
+};
+
+
+pub const CompressionMethod = enum(u8) { deflate = 0, _ };
+
+
+pub const FilterMethod = enum(u8) { adaptive = 0, _ };
+
+pub const ChunkHeader = extern struct {
+ length: u32 align(1),
+ type: u32 align(1),
+
+ const Self = @This();
+
+ pub fn name(self: *Self) []const u8 {
+ return std.mem.asBytes(&self.type);
+ }
+};
+
+pub const HeaderData = extern struct {
+ width: u32 align(1),
+ height: u32 align(1),
+ bit_depth: u8,
+ color_type: ColorType,
+ compression_method: CompressionMethod,
+ filter_method: FilterMethod,
+ interlace_method: InterlaceMethod,
+
+ const Self = @This();
+
+ pub fn isValid(self: *const Self) bool {
+ const max_dim = std.math.maxInt(u32) >> 1;
+ const w = self.width;
+ const h = self.height;
+ if (w == 0 or w > max_dim) return false;
+ if (h == 0 or h > max_dim) return false;
+
+ const bd = self.bit_depth;
+ return switch (self.color_type) {
+ .grayscale => bd == 1 or bd == 2 or bd == 4 or bd == 8 or bd == 16,
+ .indexed => bd == 1 or bd == 2 or bd == 4 or bd == 8,
+ else => bd == 8 or bd == 16,
+ };
+ }
+
+ pub fn allowsPalette(self: *const Self) bool {
+ return self.color_type == .indexed or
+ self.color_type == .rgb_color or
+ self.color_type == .rgba_color;
+ }
+
+ pub fn maxPaletteSize(self: *const Self) u16 {
+ return if (self.bit_depth > 8) 256 else @as(u16, 1) << @truncate(self.bit_depth);
+ }
+
+ pub fn channelCount(self: *const Self) u8 {
+ return switch (self.color_type) {
+ .grayscale => 1,
+ .rgb_color => 3,
+ .indexed => 1,
+ .grayscale_alpha => 2,
+ .rgba_color => 4,
+ };
+ }
+
+ pub fn pixelBits(self: *const Self) u8 {
+ return self.bit_depth * self.channelCount();
+ }
+
+ pub fn lineBytes(self: *const Self) u32 {
+ return (self.pixelBits() * self.width + 7) / 8;
+ }
+
+ pub fn getPixelFormat(self: *const Self) PixelFormat {
+ return switch (self.color_type) {
+ .grayscale => switch (self.bit_depth) {
+ 1 => PixelFormat.grayscale1,
+ 2 => PixelFormat.grayscale2,
+ 4 => PixelFormat.grayscale4,
+ 8 => PixelFormat.grayscale8,
+ 16 => PixelFormat.grayscale16,
+ else => unreachable,
+ },
+ .rgb_color => switch (self.bit_depth) {
+ 8 => PixelFormat.rgb24,
+ 16 => PixelFormat.rgb48,
+ else => unreachable,
+ },
+ .indexed => switch (self.bit_depth) {
+ 1 => PixelFormat.indexed1,
+ 2 => PixelFormat.indexed2,
+ 4 => PixelFormat.indexed4,
+ 8 => PixelFormat.indexed8,
+ else => unreachable,
+ },
+ .grayscale_alpha => switch (self.bit_depth) {
+ 8 => PixelFormat.grayscale8Alpha,
+ 16 => PixelFormat.grayscale16Alpha,
+ else => unreachable,
+ },
+ .rgba_color => switch (self.bit_depth) {
+ 8 => PixelFormat.rgba32,
+ 16 => PixelFormat.rgba64,
+ else => unreachable,
+ },
+ };
+ }
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/png/zlib_compressor.zig.html b/docs/src/zigimg/src/formats/png/zlib_compressor.zig.html
new file mode 100644
index 0000000..deb6101
--- /dev/null
+++ b/docs/src/zigimg/src/formats/png/zlib_compressor.zig.html
@@ -0,0 +1,186 @@
+
+
+
+
+
src/formats/png/zlib_compressor.zig - source view
+
+
+
+
+
+
const std = @import("std");
+const io = std.io;
+const deflate = std.compress.deflate;
+
+
+pub fn ZlibCompressor(comptime WriterType: type) type {
+ return struct {
+ raw_writer: WriterType,
+ compressor: deflate.Compressor(WriterType),
+ adler: std.hash.Adler32,
+
+ const Self = @This();
+
+
+
+
+
+ pub fn init(self: *Self, alloc: std.mem.Allocator, stream: WriterType) !void {
+ self.raw_writer = stream;
+ self.compressor = try deflate.compressor(alloc, self.raw_writer, .{});
+ self.adler = std.hash.Adler32.init();
+ }
+
+
+ pub fn begin(self: *Self) !void {
+
+
+ const compression_method = 0x78;
+
+ const compression_flags = blk: {
+ var ret: u8 = 0b10000000;
+
+ const rem: u8 = @truncate(((@as(usize, @intCast(compression_method)) << 8) + ret) % 31);
+ ret += 31 - @as(u8, @truncate(rem));
+ break :blk ret;
+ };
+
+
+
+
+
+ var wr = self.raw_writer;
+ try wr.writeByte(compression_method);
+ try wr.writeByte(compression_flags);
+ }
+
+ pub const Error = WriterType.Error;
+ pub const Writer = std.io.Writer(*Self, Error, write);
+
+ pub fn writer(self: *Self) Writer {
+ return .{ .context = self };
+ }
+
+ pub fn write(self: *Self, bytes: []const u8) Error!usize {
+ const amount = try self.compressor.writer().write(bytes);
+ self.adler.update(bytes[0..amount]);
+ return amount;
+ }
+
+
+ pub fn end(self: *Self) !void {
+ try self.compressor.close();
+ self.compressor.deinit();
+
+
+ try self.raw_writer.writeInt(u32, self.adler.final(), .big);
+ }
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/qoi.zig.html b/docs/src/zigimg/src/formats/qoi.zig.html
new file mode 100644
index 0000000..a11720c
--- /dev/null
+++ b/docs/src/zigimg/src/formats/qoi.zig.html
@@ -0,0 +1,568 @@
+
+
+
+
+
src/formats/qoi.zig - source view
+
+
+
+
+
+
+
+
+
+const Allocator = std.mem.Allocator;
+const buffered_stream_source = @import("../buffered_stream_source.zig");
+const color = @import("../color.zig");
+const FormatInterface = @import("../FormatInterface.zig");
+const fs = std.fs;
+const Image = @import("../Image.zig");
+const ImageError = Image.Error;
+const ImageReadError = Image.ReadError;
+const ImageWriteError = Image.WriteError;
+const io = std.io;
+const mem = std.mem;
+const path = std.fs.path;
+const PixelFormat = @import("../pixel_format.zig").PixelFormat;
+const std = @import("std");
+const utils = @import("../utils.zig");
+
+pub const QoiColor = extern struct {
+ r: u8 align(1),
+ g: u8 align(1),
+ b: u8 align(1),
+ a: u8 align(1) = 0xFF,
+
+ fn hash(c: QoiColor) u6 {
+ return @truncate(c.r *% 3 +% c.g *% 5 +% c.b *% 7 +% c.a *% 11);
+ }
+
+ pub fn eql(a: QoiColor, b: QoiColor) bool {
+ return std.meta.eql(a, b);
+ }
+
+ pub fn toRgb24(self: QoiColor) color.Rgb24 {
+ return color.Rgb24{
+ .r = self.r,
+ .g = self.g,
+ .b = self.b,
+ };
+ }
+
+ pub fn toRgba32(self: QoiColor) color.Rgba32 {
+ return color.Rgba32{
+ .r = self.r,
+ .g = self.g,
+ .b = self.b,
+ .a = self.a,
+ };
+ }
+
+ pub fn from(pixel: anytype) QoiColor {
+ if (@TypeOf(pixel) == color.Rgb24) {
+ return QoiColor{
+ .r = pixel.r,
+ .g = pixel.g,
+ .b = pixel.b,
+ };
+ } else if (@TypeOf(pixel) == color.Rgba32) {
+ return QoiColor{
+ .r = pixel.r,
+ .g = pixel.g,
+ .b = pixel.b,
+ .a = pixel.a,
+ };
+ } else {
+ unreachable;
+ }
+ }
+};
+
+pub const Colorspace = enum(u8) {
+
+ srgb = 0,
+
+
+ linear = 1,
+};
+
+pub const Format = enum(u8) {
+ rgb = 3,
+ rgba = 4,
+};
+
+pub const Header = extern struct {
+ const size = 14;
+ const correct_magic = [4]u8{ 'q', 'o', 'i', 'f' };
+
+ width: u32 align(1),
+ height: u32 align(1),
+ format: Format align(1),
+ colorspace: Colorspace align(1),
+
+ fn encode(header: Header) [size]u8 {
+ var result: [size]u8 = undefined;
+ @memcpy(result[0..4], &correct_magic);
+ std.mem.writeInt(u32, result[4..8], header.width, .big);
+ std.mem.writeInt(u32, result[8..12], header.height, .big);
+ result[12] = @intFromEnum(header.format);
+ result[13] = @intFromEnum(header.colorspace);
+ return result;
+ }
+
+ comptime {
+ std.debug.assert((@sizeOf(Header) + Header.correct_magic.len) == Header.size);
+ }
+};
+
+pub const QOI = struct {
+ header: Header = undefined,
+
+ pub const EncoderOptions = struct {
+ colorspace: Colorspace = .srgb,
+ };
+
+ const Self = @This();
+
+ pub fn formatInterface() FormatInterface {
+ return FormatInterface{
+ .format = format,
+ .formatDetect = formatDetect,
+ .readImage = readImage,
+ .writeImage = writeImage,
+ };
+ }
+
+ pub fn format() Image.Format {
+ return Image.Format.qoi;
+ }
+
+ pub fn formatDetect(stream: *Image.Stream) ImageReadError!bool {
+ var magic_buffer: [Header.correct_magic.len]u8 = undefined;
+
+ _ = try stream.read(magic_buffer[0..]);
+
+ return std.mem.eql(u8, magic_buffer[0..], Header.correct_magic[0..]);
+ }
+
+ pub fn readImage(allocator: Allocator, stream: *Image.Stream) ImageReadError!Image {
+ var result = Image.init(allocator);
+ errdefer result.deinit();
+ var qoi = Self{};
+
+ const pixels = try qoi.read(allocator, stream);
+
+ result.width = qoi.width();
+ result.height = qoi.height();
+ result.pixels = pixels;
+
+ return result;
+ }
+
+ pub fn writeImage(allocator: Allocator, write_stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) ImageWriteError!void {
+ _ = allocator;
+
+ var qoi = Self{};
+ qoi.header.width = @truncate(image.width);
+ qoi.header.height = @truncate(image.height);
+ qoi.header.format = switch (image.pixels) {
+ .rgb24 => Format.rgb,
+ .rgba32 => Format.rgba,
+ else => return ImageError.Unsupported,
+ };
+ switch (encoder_options) {
+ .qoi => |qoi_encode_options| {
+ qoi.header.colorspace = qoi_encode_options.colorspace;
+ },
+ else => {
+ qoi.header.colorspace = .srgb;
+ },
+ }
+
+ try qoi.write(write_stream, image.pixels);
+ }
+
+ pub fn width(self: Self) usize {
+ return self.header.width;
+ }
+
+ pub fn height(self: Self) usize {
+ return self.header.height;
+ }
+
+ pub fn pixelFormat(self: Self) !PixelFormat {
+ return switch (self.header.format) {
+ .rgb => PixelFormat.rgb24,
+ .rgba => PixelFormat.rgba32,
+ };
+ }
+
+ pub fn read(self: *Self, allocator: Allocator, stream: *Image.Stream) ImageReadError!color.PixelStorage {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);
+
+ var magic_buffer: [Header.correct_magic.len]u8 = undefined;
+
+ const reader = buffered_stream.reader();
+
+ _ = try buffered_stream.read(magic_buffer[0..]);
+
+ if (!std.mem.eql(u8, magic_buffer[0..], Header.correct_magic[0..])) {
+ return ImageReadError.InvalidData;
+ }
+
+ self.header = utils.readStruct(reader, Header, .big) catch return ImageReadError.InvalidData;
+
+ const pixel_format = try self.pixelFormat();
+
+ var pixels = try color.PixelStorage.init(allocator, pixel_format, self.width() * self.height());
+ errdefer pixels.deinit(allocator);
+
+ var current_color = QoiColor{ .r = 0, .g = 0, .b = 0, .a = 0xFF };
+ var color_lut = std.mem.zeroes([64]QoiColor);
+
+ var index: usize = 0;
+ const pixels_size: usize = @as(usize, self.header.width) * @as(usize, self.header.height);
+
+ while (index < pixels_size) {
+ const byte = try reader.readByte();
+
+ var new_color = current_color;
+ var count: usize = 1;
+
+ if (byte == 0b11111110) {
+
+ new_color.r = try reader.readByte();
+ new_color.g = try reader.readByte();
+ new_color.b = try reader.readByte();
+ } else if (byte == 0b11111111) {
+
+ new_color.r = try reader.readByte();
+ new_color.g = try reader.readByte();
+ new_color.b = try reader.readByte();
+ new_color.a = try reader.readByte();
+ } else if (hasPrefix(byte, u2, 0b00)) {
+
+ const color_index: u6 = @truncate(byte);
+ new_color = color_lut[color_index];
+ } else if (hasPrefix(byte, u2, 0b01)) {
+
+ const diff_r = unmapRange2(byte >> 4);
+ const diff_g = unmapRange2(byte >> 2);
+ const diff_b = unmapRange2(byte >> 0);
+
+ add8(&new_color.r, diff_r);
+ add8(&new_color.g, diff_g);
+ add8(&new_color.b, diff_b);
+ } else if (hasPrefix(byte, u2, 0b10)) {
+
+ const diff_g = unmapRange6(byte);
+
+ const diff_rg_rb = try reader.readByte();
+
+ const diff_rg = unmapRange4(diff_rg_rb >> 4);
+ const diff_rb = unmapRange4(diff_rg_rb >> 0);
+
+ const diff_r = @as(i8, diff_g) + diff_rg;
+ const diff_b = @as(i8, diff_g) + diff_rb;
+
+ add8(&new_color.r, diff_r);
+ add8(&new_color.g, diff_g);
+ add8(&new_color.b, diff_b);
+ } else if (hasPrefix(byte, u2, 0b11)) {
+
+ count = @as(usize, @as(u6, @truncate(byte))) + 1;
+ std.debug.assert(count >= 1 and count <= 62);
+ } else {
+
+
+ unreachable;
+ }
+
+
+
+
+
+ if (index + count > pixels_size) {
+ return ImageReadError.InvalidData;
+ }
+
+ while (count > 0) {
+ count -= 1;
+ switch (pixels) {
+ .rgb24 => |data| {
+ data[index] = new_color.toRgb24();
+ },
+ .rgba32 => |data| {
+ data[index] = new_color.toRgba32();
+ },
+ else => {},
+ }
+ index += 1;
+ }
+
+ color_lut[new_color.hash()] = new_color;
+ current_color = new_color;
+ }
+
+ return pixels;
+ }
+
+ pub fn write(self: Self, stream: *Image.Stream, pixels: color.PixelStorage) ImageWriteError!void {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceWriter(stream);
+ const writer = buffered_stream.writer();
+ try writer.writeAll(&self.header.encode());
+
+ switch (pixels) {
+ .rgb24 => |data| {
+ try writeData(writer, data);
+ },
+ .rgba32 => |data| {
+ try writeData(writer, data);
+ },
+ else => {
+ return ImageError.Unsupported;
+ },
+ }
+
+ try writer.writeAll(&[8]u8{
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x01,
+ });
+
+ try buffered_stream.flush();
+ }
+
+ fn writeData(writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, pixels_data: anytype) ImageWriteError!void {
+ var color_lut = std.mem.zeroes([64]QoiColor);
+
+ var previous_pixel = QoiColor{ .r = 0, .g = 0, .b = 0, .a = 0xFF };
+ var run_length: usize = 0;
+
+ for (pixels_data, 0..) |current_color, i| {
+ const pixel = QoiColor.from(current_color);
+
+ defer previous_pixel = pixel;
+
+ const same_pixel = pixel.eql(previous_pixel);
+
+ if (same_pixel) {
+ run_length += 1;
+ }
+
+ if (run_length > 0 and (run_length == 62 or !same_pixel or (i == (pixels_data.len - 1)))) {
+
+
+ std.debug.assert(run_length >= 1 and run_length <= 62);
+ try writer.writeByte(0b1100_0000 | @as(u8, @truncate(run_length - 1)));
+ run_length = 0;
+ }
+
+ if (!same_pixel) {
+ const hash = pixel.hash();
+ if (color_lut[hash].eql(pixel)) {
+
+
+ try writer.writeByte(0b0000_0000 | hash);
+ } else {
+ color_lut[hash] = pixel;
+
+ const diff_r = @as(i16, pixel.r) - @as(i16, previous_pixel.r);
+ const diff_g = @as(i16, pixel.g) - @as(i16, previous_pixel.g);
+ const diff_b = @as(i16, pixel.b) - @as(i16, previous_pixel.b);
+ const diff_a = @as(i16, pixel.a) - @as(i16, previous_pixel.a);
+
+ const diff_rg = diff_r - diff_g;
+ const diff_rb = diff_b - diff_g;
+
+ if (diff_a == 0 and inRange2(diff_r) and inRange2(diff_g) and inRange2(diff_b)) {
+
+
+ const byte = 0b0100_0000 |
+ (mapRange2(diff_r) << 4) |
+ (mapRange2(diff_g) << 2) |
+ (mapRange2(diff_b) << 0);
+ try writer.writeByte(byte);
+ } else if (diff_a == 0 and inRange6(diff_g) and inRange4(diff_rg) and inRange4(diff_rb)) {
+
+
+ try writer.writeAll(&[2]u8{
+ 0b1000_0000 | mapRange6(diff_g),
+ (mapRange4(diff_rg) << 4) | (mapRange4(diff_rb) << 0),
+ });
+ } else if (diff_a == 0) {
+
+
+ try writer.writeAll(&[4]u8{
+ 0b1111_1110,
+ pixel.r,
+ pixel.g,
+ pixel.b,
+ });
+ } else {
+
+
+ try writer.writeAll(&[5]u8{
+ 0b1111_1111,
+ pixel.r,
+ pixel.g,
+ pixel.b,
+ pixel.a,
+ });
+ }
+ }
+ }
+ }
+ }
+
+ fn mapRange2(val: i16) u8 {
+ return @as(u2, @intCast(val + 2));
+ }
+ fn mapRange4(val: i16) u8 {
+ return @as(u4, @intCast(val + 8));
+ }
+ fn mapRange6(val: i16) u8 {
+ return @as(u6, @intCast(val + 32));
+ }
+
+ fn unmapRange2(val: u32) i2 {
+ return @as(i2, @intCast(@as(i8, @as(u2, @truncate(val))) - 2));
+ }
+ fn unmapRange4(val: u32) i4 {
+ return @as(i4, @intCast(@as(i8, @as(u4, @truncate(val))) - 8));
+ }
+ fn unmapRange6(val: u32) i6 {
+ return @as(i6, @intCast(@as(i8, @as(u6, @truncate(val))) - 32));
+ }
+
+ fn inRange2(val: i16) bool {
+ return (val >= -2) and (val <= 1);
+ }
+ fn inRange4(val: i16) bool {
+ return (val >= -8) and (val <= 7);
+ }
+ fn inRange6(val: i16) bool {
+ return (val >= -32) and (val <= 31);
+ }
+
+ fn add8(dst: *u8, diff: i8) void {
+ dst.* +%= @bitCast(diff);
+ }
+
+ fn hasPrefix(value: u8, comptime T: type, prefix: T) bool {
+ return (@as(T, @truncate(value >> (8 - @bitSizeOf(T)))) == prefix);
+ }
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/formats/tga.zig.html b/docs/src/zigimg/src/formats/tga.zig.html
new file mode 100644
index 0000000..f0e34ca
--- /dev/null
+++ b/docs/src/zigimg/src/formats/tga.zig.html
@@ -0,0 +1,1491 @@
+
+
+
+
+
src/formats/tga.zig - source view
+
+
+
+
+
+
const FormatInterface = @import("../FormatInterface.zig");
+const PixelFormat = @import("../pixel_format.zig").PixelFormat;
+const buffered_stream_source = @import("../buffered_stream_source.zig");
+const color = @import("../color.zig");
+const Image = @import("../Image.zig");
+const std = @import("std");
+const simd = @import("../simd.zig");
+const utils = @import("../utils.zig");
+
+pub const TGAImageType = packed struct(u8) {
+ indexed: bool = false,
+ truecolor: bool = false,
+ pad0: bool = false,
+ run_length: bool = false,
+ pad1: u4 = 0,
+};
+
+pub const TGAColorMapSpec = extern struct {
+ first_entry_index: u16 align(1) = 0,
+ length: u16 align(1) = 0,
+ bit_depth: u8 align(1) = 0,
+};
+
+pub const TGADescriptor = packed struct(u8) {
+ num_attributes_bit: u4 = 0,
+ right_to_left: bool = false,
+ top_to_bottom: bool = false,
+ pad: u2 = 0,
+};
+
+pub const TGAImageSpec = extern struct {
+ origin_x: u16 align(1) = 0,
+ origin_y: u16 align(1) = 0,
+ width: u16 align(1) = 0,
+ height: u16 align(1) = 0,
+ bit_per_pixel: u8 align(1) = 0,
+ descriptor: TGADescriptor align(1) = .{},
+};
+
+pub const TGAHeader = extern struct {
+ id_length: u8 align(1) = 0,
+ has_color_map: u8 align(1) = 0,
+ image_type: TGAImageType align(1) = .{},
+ color_map_spec: TGAColorMapSpec align(1) = .{},
+ image_spec: TGAImageSpec align(1) = .{},
+
+ pub fn isValid(self: TGAHeader) bool {
+ if (self.has_color_map != 0 and self.has_color_map != 1) {
+ return false;
+ }
+
+ if (self.image_type.pad0) {
+ return false;
+ }
+
+ if (self.image_type.pad1 != 0) {
+ return false;
+ }
+
+ switch (self.color_map_spec.bit_depth) {
+ 0, 15, 16, 24, 32 => {},
+ else => {
+ return false;
+ },
+ }
+
+ return true;
+ }
+};
+
+pub const TGAExtensionComment = extern struct {
+ lines: [4][80:0]u8 = [_][80:0]u8{[_:0]u8{0} ** 80} ** 4,
+};
+
+pub const TGAExtensionSoftwareVersion = extern struct {
+ number: u16 align(1) = 0,
+ letter: u8 align(1) = ' ',
+};
+
+pub const TGAExtensionTimestamp = extern struct {
+ month: u16 align(1) = 0,
+ day: u16 align(1) = 0,
+ year: u16 align(1) = 0,
+ hour: u16 align(1) = 0,
+ minute: u16 align(1) = 0,
+ second: u16 align(1) = 0,
+};
+
+pub const TGAExtensionJobTime = extern struct {
+ hours: u16 align(1) = 0,
+ minutes: u16 align(1) = 0,
+ seconds: u16 align(1) = 0,
+};
+
+pub const TGAExtensionRatio = extern struct {
+ numerator: u16 align(1) = 0,
+ denominator: u16 align(1) = 0,
+};
+
+pub const TGAAttributeType = enum(u8) {
+ no_alpha = 0,
+ undefined_alpha_ignore = 1,
+ undefined_alpha_retained = 2,
+ useful_alpha_channel = 3,
+ premultipled_alpha = 4,
+};
+
+pub const TGAExtension = extern struct {
+ extension_size: u16 align(1) = @sizeOf(TGAExtension),
+ author_name: [40:0]u8 align(1) = [_:0]u8{0} ** 40,
+ author_comment: TGAExtensionComment align(1) = .{},
+ timestamp: TGAExtensionTimestamp align(1) = .{},
+ job_id: [40:0]u8 align(1) = [_:0]u8{0} ** 40,
+ job_time: TGAExtensionJobTime align(1) = .{},
+ software_id: [40:0]u8 align(1) = [_:0]u8{0} ** 40,
+ software_version: TGAExtensionSoftwareVersion align(1) = .{},
+ key_color: color.Bgra32 align(1) = .{ .r = 0, .g = 0, .b = 0, .a = 0 },
+ pixel_aspect: TGAExtensionRatio align(1) = .{},
+ gamma_value: TGAExtensionRatio align(1) = .{},
+ color_correction_offset: u32 align(1) = 0,
+ postage_stamp_offset: u32 align(1) = 0,
+ scanline_offset: u32 align(1) = 0,
+ attributes: TGAAttributeType align(1) = .no_alpha,
+};
+
+pub const TGAFooter = extern struct {
+ extension_offset: u32 align(1) = 0,
+ dev_area_offset: u32 align(1) = 0,
+ signature: [16]u8 align(1) = undefined,
+ dot: u8 align(1) = '.',
+ null_value: u8 align(1) = 0,
+};
+
+pub const TGASignature = "TRUEVISION-XFILE";
+
+comptime {
+ std.debug.assert(@sizeOf(TGAHeader) == 18);
+ std.debug.assert(@sizeOf(TGAExtension) == 495);
+}
+
+const RLEPacketType = enum(u1) {
+ raw = 0,
+ repeated = 1,
+};
+
+const RLEPacketHeader = packed struct {
+ count: u7,
+ packet_type: RLEPacketType,
+};
+
+const TargaRLEDecoder = struct {
+ source_reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader,
+ allocator: std.mem.Allocator,
+ bytes_per_pixel: usize,
+
+ state: State = .read_header,
+ repeat_count: usize = 0,
+ repeat_data: []u8 = undefined,
+ data_stream: std.io.FixedBufferStream([]u8) = undefined,
+
+ pub const Reader = std.io.Reader(*TargaRLEDecoder, Image.ReadError, read);
+
+ const State = enum {
+ read_header,
+ repeated,
+ raw,
+ };
+
+ pub fn init(allocator: std.mem.Allocator, source_reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader, bytes_per_pixels: usize) !TargaRLEDecoder {
+ var result = TargaRLEDecoder{
+ .allocator = allocator,
+ .source_reader = source_reader,
+ .bytes_per_pixel = bytes_per_pixels,
+ };
+
+ result.repeat_data = try allocator.alloc(u8, bytes_per_pixels);
+ result.data_stream = std.io.fixedBufferStream(result.repeat_data);
+ return result;
+ }
+
+ pub fn deinit(self: TargaRLEDecoder) void {
+ self.allocator.free(self.repeat_data);
+ }
+
+ pub fn read(self: *TargaRLEDecoder, dest: []u8) Image.ReadError!usize {
+ var read_count: usize = 0;
+
+ if (self.state == .read_header) {
+ const packet_header = try utils.readStruct(self.source_reader, RLEPacketHeader, .little);
+
+ if (packet_header.packet_type == .repeated) {
+ self.state = .repeated;
+
+ self.repeat_count = @as(usize, @intCast(packet_header.count)) + 1;
+
+ _ = try self.source_reader.read(self.repeat_data);
+
+ self.data_stream.reset();
+ } else if (packet_header.packet_type == .raw) {
+ self.state = .raw;
+
+ self.repeat_count = (@as(usize, @intCast(packet_header.count)) + 1) * self.bytes_per_pixel;
+ }
+ }
+
+ switch (self.state) {
+ .repeated => {
+ _ = try self.data_stream.read(dest);
+
+ const end_pos = try self.data_stream.getEndPos();
+ if (self.data_stream.pos >= end_pos) {
+ self.data_stream.reset();
+
+ self.repeat_count -= 1;
+ }
+
+ read_count = dest.len;
+ },
+ .raw => {
+ const read_bytes = try self.source_reader.read(dest);
+
+ self.repeat_count -= read_bytes;
+
+ read_count = read_bytes;
+ },
+ else => {
+ return Image.ReadError.InvalidData;
+ },
+ }
+
+ if (self.repeat_count == 0) {
+ self.state = .read_header;
+ }
+
+ return read_count;
+ }
+
+ pub fn reader(self: *TargaRLEDecoder) Reader {
+ return .{ .context = self };
+ }
+};
+
+pub const TargaStream = union(enum) {
+ image: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader,
+ rle: TargaRLEDecoder,
+
+ pub const Reader = std.io.Reader(*TargaStream, Image.ReadError, read);
+
+ pub fn read(self: *TargaStream, dest: []u8) Image.ReadError!usize {
+ switch (self.*) {
+ .image => |*x| return x.read(dest),
+ .rle => |*x| return x.read(dest),
+ }
+ }
+
+ pub fn reader(self: *TargaStream) Reader {
+ return .{ .context = self };
+ }
+};
+
+const RLEPacketMask = 1 << 7;
+const RLEMinLength = 2;
+const RLEMaxLength = RLEPacketMask;
+
+const RunLengthEncoderCommon = struct {
+ pub fn flush(comptime IntType: type, writer: anytype, value: IntType, count: usize) !void {
+ var current_count = count;
+ while (current_count > 0) {
+ const length_to_write = @min(current_count, RLEMaxLength);
+
+ if (length_to_write >= RLEMinLength) {
+ try flushRLE(IntType, writer, value, length_to_write);
+ } else {
+ try flushRaw(IntType, writer, value, length_to_write);
+ }
+
+ current_count -= length_to_write;
+ }
+ }
+
+ pub inline fn flushRLE(comptime IntType: type, writer: anytype, value: IntType, count: usize) !void {
+ const rle_packet_header = RLEPacketHeader{
+ .count = @truncate(count - 1),
+ .packet_type = .repeated,
+ };
+ try writer.writeByte(@bitCast(rle_packet_header));
+ try writer.writeInt(IntType, value, .little);
+ }
+
+ pub inline fn flushRaw(comptime IntType: type, writer: anytype, value: IntType, count: usize) !void {
+ const rle_packet_header = RLEPacketHeader{
+ .count = @truncate(count - 1),
+ .packet_type = .raw,
+ };
+ try writer.writeByte(@bitCast(rle_packet_header));
+
+ for (0..count) |_| {
+ try writer.writeInt(IntType, value, .little);
+ }
+ }
+};
+
+fn RunLengthSimpleEncoder(comptime IntType: type) type {
+ return struct {
+ pub fn encode(source_data: []const u8, writer: anytype) !void {
+ if (source_data.len == 0) {
+ return;
+ }
+
+ var fixed_stream = std.io.fixedBufferStream(source_data);
+ const reader = fixed_stream.reader();
+
+ var total_similar_count: usize = 0;
+ var compared_value = try reader.readInt(IntType, .little);
+ total_similar_count = 1;
+
+ while ((try fixed_stream.getPos()) < (try fixed_stream.getEndPos())) {
+ const read_value = try reader.readInt(IntType, .little);
+ if (read_value == compared_value) {
+ total_similar_count += 1;
+ } else {
+ try RunLengthEncoderCommon.flush(IntType, writer, compared_value, total_similar_count);
+
+ compared_value = read_value;
+ total_similar_count = 1;
+ }
+ }
+
+ try RunLengthEncoderCommon.flush(IntType, writer, compared_value, total_similar_count);
+ }
+ };
+}
+
+fn RunLengthSIMDEncoder(comptime IntType: type) type {
+ return struct {
+ const VectorLength = std.simd.suggestVectorLength(IntType) orelse 4;
+ const VectorType = @Vector(VectorLength, IntType);
+ const BytesPerPixels = (@typeInfo(IntType).Int.bits + 7) / 8;
+ const IndexStep = VectorLength * BytesPerPixels;
+ const MaskType = std.meta.Int(.unsigned, VectorLength);
+
+ comptime {
+ if (!std.math.isPowerOfTwo(@typeInfo(IntType).Int.bits)) {
+ @compileError("Only power of two integers are supported by the run-length SIMD encoder");
+ }
+ }
+
+ pub fn encode(source_data: []const u8, writer: anytype) !void {
+ if (source_data.len == 0) {
+ return;
+ }
+
+ var index: usize = 0;
+
+ var total_similar_count: usize = 0;
+
+ var fixed_stream = std.io.fixedBufferStream(source_data);
+ const reader = fixed_stream.reader();
+
+ var compared_value = try reader.readInt(IntType, .little);
+ try fixed_stream.seekTo(0);
+
+ while (index < source_data.len and ((index + IndexStep) <= source_data.len)) {
+ const read_value = try reader.readInt(IntType, .little);
+
+ const current_byte_splatted: VectorType = @splat(read_value);
+ const compare_chunk = simd.load(source_data[index..], VectorType, 0);
+
+ const compare_mask = (current_byte_splatted == compare_chunk);
+ const inverted_mask = ~@as(MaskType, @bitCast(compare_mask));
+ const current_similar_count = @ctz(inverted_mask);
+
+ if (current_similar_count == VectorLength) {
+ total_similar_count += current_similar_count;
+ index += current_similar_count * BytesPerPixels;
+
+ try reader.skipBytes((current_similar_count - 1) * BytesPerPixels, .{});
+
+ compared_value = read_value;
+ } else {
+ if (compared_value == read_value) {
+ total_similar_count += current_similar_count;
+ try RunLengthEncoderCommon.flush(IntType, writer, compared_value, total_similar_count);
+
+ compared_value = read_value;
+ total_similar_count = 0;
+ } else {
+ try RunLengthEncoderCommon.flush(IntType, writer, compared_value, total_similar_count);
+
+ compared_value = read_value;
+ total_similar_count = current_similar_count;
+ }
+
+ index += current_similar_count * BytesPerPixels;
+
+ try reader.skipBytes((current_similar_count - 1) * BytesPerPixels, .{});
+ }
+ }
+
+ try RunLengthEncoderCommon.flush(IntType, writer, compared_value, total_similar_count);
+
+
+
+ if (index < source_data.len) {
+ try RunLengthSimpleEncoder(IntType).encode(source_data[index..], writer);
+ }
+ }
+ };
+}
+
+fn RLEStreamEncoder(comptime ColorType: type) type {
+ return struct {
+ rle_value: ?ColorType = null,
+ length: usize = 0,
+
+ const IntType = switch (ColorType) {
+ color.Bgr24 => u24,
+ color.Bgra32 => u32,
+ else => @compileError("Not supported color format"),
+ };
+
+ pub fn encode(self: *@This(), writer: anytype, value: ColorType) !void {
+ if (self.rle_value == null) {
+ self.rle_value = value;
+ self.length = 1;
+ return;
+ }
+
+ if (self.rle_value) |rle_value| {
+ if (std.mem.eql(u8, std.mem.asBytes(&rle_value), std.mem.asBytes(&value))) {
+ self.length += 1;
+ } else {
+ try RunLengthEncoderCommon.flush(IntType, writer, @as(IntType, @bitCast(rle_value)), self.length);
+
+ self.length = 1;
+ self.rle_value = value;
+ }
+ }
+ }
+
+ pub fn flush(self: *@This(), writer: anytype) !void {
+ if (self.length == 0) {
+ return;
+ }
+
+ if (self.rle_value) |rle_value| {
+ try RunLengthEncoderCommon.flush(IntType, writer, @as(IntType, @bitCast(rle_value)), self.length);
+ }
+ }
+ };
+}
+
+test "TGA RLE SIMD u8 (bytes) encoder" {
+ const uncompressed_data = [_]u8{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 64, 64, 2, 2, 2, 2, 2, 215, 215, 215, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 200, 200, 200, 200, 210, 210 };
+ const compressed_data = [_]u8{ 0x88, 0x01, 0x81, 0x40, 0x84, 0x02, 0x82, 0xD7, 0x89, 0x03, 0x83, 0xC8, 0x81, 0xD2 };
+
+ var result_list = std.ArrayList(u8).init(std.testing.allocator);
+ defer result_list.deinit();
+
+ const writer = result_list.writer();
+
+ try RunLengthSIMDEncoder(u8).encode(uncompressed_data[0..], writer);
+
+ try std.testing.expectEqualSlices(u8, compressed_data[0..], result_list.items);
+}
+
+test "TGA RLE SIMD u8 (bytes) encoder should encore more than 128 bytes similar" {
+ const first_uncompressed_part = [_]u8{0x45} ** 135;
+ const second_uncompresse_part = [_]u8{ 0x1, 0x1, 0x1, 0x1 };
+ const uncompressed_data = first_uncompressed_part ++ second_uncompresse_part;
+
+ const compressed_data = [_]u8{ 0xFF, 0x45, 0x86, 0x45, 0x83, 0x1 };
+
+ var result_list = std.ArrayList(u8).init(std.testing.allocator);
+ defer result_list.deinit();
+
+ const writer = result_list.writer();
+
+ try RunLengthSIMDEncoder(u8).encode(uncompressed_data[0..], writer);
+
+ try std.testing.expectEqualSlices(u8, compressed_data[0..], result_list.items);
+}
+
+test "TGA RLE SIMD u16 encoder" {
+ const uncompressed_source = [_]u16{ 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x301, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 };
+ const uncompressed_data = std.mem.sliceAsBytes(uncompressed_source[0..]);
+
+ const compressed_data = [_]u8{ 0x87, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00 };
+
+ var result_list = std.ArrayList(u8).init(std.testing.allocator);
+ defer result_list.deinit();
+
+ const writer = result_list.writer();
+
+ try RunLengthSIMDEncoder(u16).encode(uncompressed_data[0..], writer);
+
+ try std.testing.expectEqualSlices(u8, compressed_data[0..], result_list.items);
+}
+
+test "TGA RLE SIMD u32 encoder" {
+ const uncompressed_source = [_]u32{ 0xFFABCDEF, 0xFFABCDEF, 0xFFABCDEF, 0xFFABCDEF, 0xFFABCDEF, 0xFFABCDEF, 0xFFABCDEF, 0xFFABCDEF, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 };
+ const uncompressed_data = std.mem.sliceAsBytes(uncompressed_source[0..]);
+
+ const compressed_data = [_]u8{ 0x87, 0xEF, 0xCD, 0xAB, 0xFF, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 };
+
+ var result_list = std.ArrayList(u8).init(std.testing.allocator);
+ defer result_list.deinit();
+
+ const writer = result_list.writer();
+
+ try RunLengthSIMDEncoder(u32).encode(uncompressed_data[0..], writer);
+
+ try std.testing.expectEqualSlices(u8, compressed_data[0..], result_list.items);
+}
+
+test "TGA RLE simple u24 encoder" {
+ const uncompressed_source = [_]color.Rgb24{
+ .{ .r = 0xEF, .g = 0xCD, .b = 0xAB },
+ .{ .r = 0xEF, .g = 0xCD, .b = 0xAB },
+ .{ .r = 0xEF, .g = 0xCD, .b = 0xAB },
+ .{ .r = 0xEF, .g = 0xCD, .b = 0xAB },
+ .{ .r = 0xEF, .g = 0xCD, .b = 0xAB },
+ .{ .r = 0xEF, .g = 0xCD, .b = 0xAB },
+ .{ .r = 0xEF, .g = 0xCD, .b = 0xAB },
+ .{ .r = 0xEF, .g = 0xCD, .b = 0xAB },
+ .{ .r = 0x1, .g = 0x2, .b = 0x3 },
+ .{ .r = 0x4, .g = 0x5, .b = 0x6 },
+ .{ .r = 0x7, .g = 0x8, .b = 0x9 },
+ };
+ const uncompressed_data = std.mem.sliceAsBytes(uncompressed_source[0..]);
+
+ const compressed_data = [_]u8{
+ 0x87, 0xEF, 0xCD, 0xAB,
+ 0x00, 0x01, 0x02, 0x03,
+ 0x00, 0x04, 0x05, 0x06,
+ 0x00, 0x07, 0x08, 0x09,
+ };
+
+ var result_list = std.ArrayList(u8).init(std.testing.allocator);
+ defer result_list.deinit();
+
+ const writer = result_list.writer();
+
+ try RunLengthSimpleEncoder(u24).encode(uncompressed_data[0..], writer);
+
+ try std.testing.expectEqualSlices(u8, compressed_data[0..], result_list.items);
+}
+
+pub const TGA = struct {
+ header: TGAHeader = .{},
+ id: utils.FixedStorage(u8, 256) = .{},
+ extension: ?TGAExtension = null,
+
+ pub const EncoderOptions = struct {
+ rle_compressed: bool = true,
+ top_to_bottom_image: bool = true,
+ color_map_depth: u8 = 24,
+ image_id: []const u8 = &.{},
+ author_name: [:0]const u8 = &.{},
+ author_comment: TGAExtensionComment = .{},
+ timestamp: TGAExtensionTimestamp = .{},
+ job_id: [:0]const u8 = &.{},
+ job_time: TGAExtensionJobTime = .{},
+ software_id: [:0]const u8 = &.{},
+ software_version: TGAExtensionSoftwareVersion = .{},
+ };
+
+ pub fn formatInterface() FormatInterface {
+ return FormatInterface{
+ .format = format,
+ .formatDetect = formatDetect,
+ .readImage = readImage,
+ .writeImage = writeImage,
+ };
+ }
+
+ pub fn format() Image.Format {
+ return Image.Format.tga;
+ }
+
+ pub fn formatDetect(stream: *Image.Stream) Image.ReadError!bool {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);
+
+ const end_pos = try buffered_stream.getEndPos();
+
+ const is_valid_tga_v2: bool = blk: {
+ if (@sizeOf(TGAFooter) < end_pos) {
+ const footer_position = end_pos - @sizeOf(TGAFooter);
+
+ try buffered_stream.seekTo(footer_position);
+ const footer = try utils.readStruct(buffered_stream.reader(), TGAFooter, .little);
+
+ if (footer.dot != '.') {
+ break :blk false;
+ }
+
+ if (footer.null_value != 0) {
+ break :blk false;
+ }
+
+ if (std.mem.eql(u8, footer.signature[0..], TGASignature[0..])) {
+ break :blk true;
+ }
+ }
+
+ break :blk false;
+ };
+
+
+
+ const is_valid_tga_v1: bool = blk: {
+ if (!is_valid_tga_v2 and @sizeOf(TGAHeader) < end_pos) {
+ try buffered_stream.seekTo(0);
+
+ const header = try utils.readStruct(buffered_stream.reader(), TGAHeader, .little);
+ break :blk header.isValid();
+ }
+
+ break :blk false;
+ };
+
+ return is_valid_tga_v2 or is_valid_tga_v1;
+ }
+
+ pub fn readImage(allocator: std.mem.Allocator, stream: *Image.Stream) Image.ReadError!Image {
+ var result = Image.init(allocator);
+ errdefer result.deinit();
+ var tga = TGA{};
+
+ const pixels = try tga.read(allocator, stream);
+
+ result.width = tga.width();
+ result.height = tga.height();
+ result.pixels = pixels;
+
+ return result;
+ }
+
+ pub fn writeImage(allocator: std.mem.Allocator, write_stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) Image.WriteError!void {
+ _ = allocator;
+
+ const tga_encoder_options = encoder_options.tga;
+
+ const image_width = image.width;
+ const image_height = image.height;
+
+ if (image_width > std.math.maxInt(u16)) {
+ return Image.WriteError.Unsupported;
+ }
+
+ if (image_height > std.math.maxInt(u16)) {
+ return Image.WriteError.Unsupported;
+ }
+
+ if (!(tga_encoder_options.color_map_depth == 16 or tga_encoder_options.color_map_depth == 24)) {
+ return Image.WriteError.Unsupported;
+ }
+
+ var tga = TGA{};
+ tga.header.image_spec.width = @truncate(image_width);
+ tga.header.image_spec.height = @truncate(image_height);
+ tga.extension = TGAExtension{};
+
+ if (tga_encoder_options.rle_compressed) {
+ tga.header.image_type.run_length = true;
+ }
+ if (tga_encoder_options.top_to_bottom_image) {
+ tga.header.image_spec.descriptor.top_to_bottom = true;
+ }
+
+ if (tga_encoder_options.image_id.len > 0) {
+ if (tga_encoder_options.image_id.len > tga.id.storage.len) {
+ return Image.WriteError.Unsupported;
+ }
+
+ tga.header.id_length = @truncate(tga_encoder_options.image_id.len);
+ tga.id.resize(tga_encoder_options.image_id.len);
+
+ @memcpy(tga.id.data[0..], tga_encoder_options.image_id[0..]);
+ }
+
+ if (tga.extension) |*extension| {
+ if (tga_encoder_options.author_name.len >= extension.author_name.len) {
+ return Image.WriteError.Unsupported;
+ }
+ if (tga_encoder_options.job_id.len >= extension.job_id.len) {
+ return Image.WriteError.Unsupported;
+ }
+ if (tga_encoder_options.software_id.len >= extension.software_id.len) {
+ return Image.WriteError.Unsupported;
+ }
+
+ std.mem.copyForwards(u8, extension.author_name[0..], tga_encoder_options.author_name[0..]);
+ extension.author_comment = tga_encoder_options.author_comment;
+
+ extension.timestamp = tga_encoder_options.timestamp;
+
+ std.mem.copyForwards(u8, extension.job_id[0..], tga_encoder_options.job_id[0..]);
+ extension.job_time = tga_encoder_options.job_time;
+
+ std.mem.copyForwards(u8, extension.software_id[0..], tga_encoder_options.software_id[0..]);
+ extension.software_version = tga_encoder_options.software_version;
+ }
+
+ switch (image.pixels) {
+ .grayscale8 => {
+ tga.header.image_type.indexed = true;
+ tga.header.image_type.truecolor = true;
+
+ tga.header.image_spec.bit_per_pixel = 8;
+ },
+ .indexed8 => |indexed| {
+ tga.header.image_type.indexed = true;
+
+ tga.header.image_spec.bit_per_pixel = 8;
+
+ tga.header.color_map_spec.bit_depth = tga_encoder_options.color_map_depth;
+ tga.header.color_map_spec.first_entry_index = 0;
+ tga.header.color_map_spec.length = @truncate(indexed.palette.len);
+
+ tga.header.has_color_map = 1;
+ },
+ .rgb555 => {
+ tga.header.image_type.indexed = false;
+ tga.header.image_type.truecolor = true;
+ tga.header.image_spec.bit_per_pixel = 16;
+ },
+ .rgb24, .bgr24 => {
+ tga.header.image_type.indexed = false;
+ tga.header.image_type.truecolor = true;
+
+ tga.header.image_spec.bit_per_pixel = 24;
+ },
+ .rgba32, .bgra32 => {
+ tga.header.image_type.indexed = false;
+ tga.header.image_type.truecolor = true;
+
+ tga.header.image_spec.bit_per_pixel = 32;
+
+ tga.header.image_spec.descriptor.num_attributes_bit = 8;
+
+ tga.extension.?.attributes = .useful_alpha_channel;
+ },
+ else => {
+ return Image.WriteError.Unsupported;
+ },
+ }
+
+ try tga.write(write_stream, image.pixels);
+ }
+
+ pub fn width(self: TGA) usize {
+ return self.header.image_spec.width;
+ }
+
+ pub fn height(self: TGA) usize {
+ return self.header.image_spec.height;
+ }
+
+ pub fn pixelFormat(self: TGA) Image.ReadError!PixelFormat {
+ if (self.header.image_type.indexed) {
+ if (self.header.image_type.truecolor) {
+ return PixelFormat.grayscale8;
+ }
+
+ return PixelFormat.indexed8;
+ } else if (self.header.image_type.truecolor) {
+ switch (self.header.image_spec.bit_per_pixel) {
+ 16 => return PixelFormat.rgb555,
+ 24 => return PixelFormat.bgr24,
+ 32 => return PixelFormat.bgra32,
+ else => {},
+ }
+ }
+
+ return Image.Error.Unsupported;
+ }
+
+ pub fn read(self: *TGA, allocator: std.mem.Allocator, stream: *Image.Stream) !color.PixelStorage {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);
+
+
+
+ const end_pos = try buffered_stream.getEndPos();
+
+ if (@sizeOf(TGAFooter) > end_pos) {
+ return Image.ReadError.InvalidData;
+ }
+
+ const reader = buffered_stream.reader();
+ try buffered_stream.seekTo(end_pos - @sizeOf(TGAFooter));
+ const footer = try utils.readStruct(reader, TGAFooter, .little);
+
+ var is_tga_version2 = true;
+
+ if (!std.mem.eql(u8, footer.signature[0..], TGASignature[0..])) {
+ is_tga_version2 = false;
+ }
+
+
+
+ if (is_tga_version2 and footer.extension_offset > 0) {
+ const extension_pos: u64 = @intCast(footer.extension_offset);
+ try buffered_stream.seekTo(extension_pos);
+ self.extension = try utils.readStruct(reader, TGAExtension, .little);
+ }
+
+
+
+ try buffered_stream.seekTo(0);
+ self.header = try utils.readStruct(reader, TGAHeader, .little);
+
+ if (!self.header.isValid()) {
+ return Image.ReadError.InvalidData;
+ }
+
+
+
+ if (self.header.id_length > 0) {
+ self.id.resize(self.header.id_length);
+
+ const read_id_size = try buffered_stream.read(self.id.data[0..]);
+
+ if (read_id_size != self.header.id_length) {
+ return Image.ReadError.InvalidData;
+ }
+ }
+
+ const pixel_format = try self.pixelFormat();
+
+ var pixels = try color.PixelStorage.init(allocator, pixel_format, self.width() * self.height());
+ errdefer pixels.deinit(allocator);
+
+ const is_compressed = self.header.image_type.run_length;
+
+ var targa_stream: TargaStream = TargaStream{ .image = reader };
+ var rle_decoder: ?TargaRLEDecoder = null;
+
+ defer {
+ if (rle_decoder) |rle| {
+ rle.deinit();
+ }
+ }
+
+ if (is_compressed) {
+ const bytes_per_pixel = (self.header.image_spec.bit_per_pixel + 7) / 8;
+
+ rle_decoder = try TargaRLEDecoder.init(allocator, reader, bytes_per_pixel);
+ if (rle_decoder) |rle| {
+ targa_stream = TargaStream{ .rle = rle };
+ }
+ }
+
+ const top_to_bottom_image = self.header.image_spec.descriptor.top_to_bottom;
+
+ switch (pixel_format) {
+ .grayscale8 => {
+ if (top_to_bottom_image) {
+ try self.readGrayscale8TopToBottom(pixels.grayscale8, targa_stream.reader());
+ } else {
+ try self.readGrayscale8BottomToTop(pixels.grayscale8, targa_stream.reader());
+ }
+ },
+ .indexed8 => {
+
+
+ switch (self.header.color_map_spec.bit_depth) {
+ 15, 16 => {
+ try self.readColorMap16(pixels.indexed8, reader);
+ },
+ 24 => {
+ try self.readColorMap24(pixels.indexed8, reader);
+ },
+ else => {
+ return Image.Error.Unsupported;
+ },
+ }
+
+
+
+ if (top_to_bottom_image) {
+ try self.readIndexed8TopToBottom(pixels.indexed8, targa_stream.reader());
+ } else {
+ try self.readIndexed8BottomToTop(pixels.indexed8, targa_stream.reader());
+ }
+ },
+ .rgb555 => {
+ if (top_to_bottom_image) {
+ try self.readTruecolor16TopToBottom(pixels.rgb555, targa_stream.reader());
+ } else {
+ try self.readTruecolor16BottomToTop(pixels.rgb555, targa_stream.reader());
+ }
+ },
+ .bgr24 => {
+ if (top_to_bottom_image) {
+ try self.readTruecolor24TopToBottom(pixels.bgr24, targa_stream.reader());
+ } else {
+ try self.readTruecolor24BottomTopTop(pixels.bgr24, targa_stream.reader());
+ }
+ },
+ .bgra32 => {
+ if (top_to_bottom_image) {
+ try self.readTruecolor32TopToBottom(pixels.bgra32, targa_stream.reader());
+ } else {
+ try self.readTruecolor32BottomToTop(pixels.bgra32, targa_stream.reader());
+ }
+ },
+ else => {
+ return Image.Error.Unsupported;
+ },
+ }
+
+ return pixels;
+ }
+
+ fn readGrayscale8TopToBottom(self: *TGA, data: []color.Grayscale8, stream: TargaStream.Reader) Image.ReadError!void {
+ var data_index: usize = 0;
+ const data_end: usize = self.width() * self.height();
+
+ while (data_index < data_end) : (data_index += 1) {
+ data[data_index] = color.Grayscale8{ .value = try stream.readByte() };
+ }
+ }
+
+ fn readGrayscale8BottomToTop(self: *TGA, data: []color.Grayscale8, stream: TargaStream.Reader) Image.ReadError!void {
+ for (0..self.height()) |y| {
+ const inverted_y = self.height() - y - 1;
+
+ const stride = inverted_y * self.width();
+
+ for (0..self.width()) |x| {
+ const data_index = stride + x;
+ data[data_index] = color.Grayscale8{ .value = try stream.readByte() };
+ }
+ }
+ }
+
+ fn readIndexed8TopToBottom(self: *TGA, data: color.IndexedStorage8, stream: TargaStream.Reader) Image.ReadError!void {
+ var data_index: usize = 0;
+ const data_end: usize = self.width() * self.height();
+
+ while (data_index < data_end) : (data_index += 1) {
+ data.indices[data_index] = try stream.readByte();
+ }
+ }
+
+ fn readIndexed8BottomToTop(self: *TGA, data: color.IndexedStorage8, stream: TargaStream.Reader) Image.ReadError!void {
+ for (0..self.height()) |y| {
+ const inverted_y = self.height() - y - 1;
+
+ const stride = inverted_y * self.width();
+
+ for (0..self.width()) |x| {
+ const data_index = stride + x;
+ data.indices[data_index] = try stream.readByte();
+ }
+ }
+ }
+
+ fn readColorMap16(self: *TGA, data: color.IndexedStorage8, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) Image.ReadError!void {
+ var data_index: usize = self.header.color_map_spec.first_entry_index;
+ const data_end: usize = self.header.color_map_spec.first_entry_index + self.header.color_map_spec.length;
+
+ while (data_index < data_end) : (data_index += 1) {
+ const read_color = try utils.readStruct(reader, color.Rgb555, .little);
+
+ data.palette[data_index].r = color.scaleToIntColor(u8, read_color.r);
+ data.palette[data_index].g = color.scaleToIntColor(u8, read_color.g);
+ data.palette[data_index].b = color.scaleToIntColor(u8, read_color.b);
+ data.palette[data_index].a = 255;
+ }
+ }
+
+ fn readColorMap24(self: *TGA, data: color.IndexedStorage8, stream: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) Image.ReadError!void {
+ var data_index: usize = self.header.color_map_spec.first_entry_index;
+ const data_end: usize = self.header.color_map_spec.first_entry_index + self.header.color_map_spec.length;
+
+ while (data_index < data_end) : (data_index += 1) {
+ data.palette[data_index].b = try stream.readByte();
+ data.palette[data_index].g = try stream.readByte();
+ data.palette[data_index].r = try stream.readByte();
+ data.palette[data_index].a = 255;
+ }
+ }
+
+ fn readTruecolor16TopToBottom(self: *TGA, data: []color.Rgb555, stream: TargaStream.Reader) Image.ReadError!void {
+ var data_index: usize = 0;
+ const data_end: usize = self.width() * self.height();
+
+ while (data_index < data_end) : (data_index += 1) {
+ const raw_color = try stream.readInt(u16, .little);
+
+ data[data_index].r = @truncate(raw_color >> 10);
+ data[data_index].g = @truncate(raw_color >> 5);
+ data[data_index].b = @truncate(raw_color);
+ }
+ }
+
+ fn readTruecolor16BottomToTop(self: *TGA, data: []color.Rgb555, stream: TargaStream.Reader) Image.ReadError!void {
+ for (0..self.height()) |y| {
+ const inverted_y = self.height() - y - 1;
+
+ const stride = inverted_y * self.width();
+
+ for (0..self.width()) |x| {
+ const data_index = stride + x;
+
+ const raw_color = try stream.readInt(u16, .little);
+
+ data[data_index].r = @truncate(raw_color >> (5 * 2));
+ data[data_index].g = @truncate(raw_color >> 5);
+ data[data_index].b = @truncate(raw_color);
+ }
+ }
+ }
+
+ fn readTruecolor24TopToBottom(self: *TGA, data: []color.Bgr24, stream: TargaStream.Reader) Image.ReadError!void {
+ var data_index: usize = 0;
+ const data_end: usize = self.width() * self.height();
+
+ while (data_index < data_end) : (data_index += 1) {
+ data[data_index].b = try stream.readByte();
+ data[data_index].g = try stream.readByte();
+ data[data_index].r = try stream.readByte();
+ }
+ }
+
+ fn readTruecolor24BottomTopTop(self: *TGA, data: []color.Bgr24, stream: TargaStream.Reader) Image.ReadError!void {
+ for (0..self.height()) |y| {
+ const inverted_y = self.height() - y - 1;
+
+ const stride = inverted_y * self.width();
+
+ for (0..self.width()) |x| {
+ const data_index = stride + x;
+ data[data_index].b = try stream.readByte();
+ data[data_index].g = try stream.readByte();
+ data[data_index].r = try stream.readByte();
+ }
+ }
+ }
+
+ fn readTruecolor32TopToBottom(self: *TGA, data: []color.Bgra32, stream: TargaStream.Reader) Image.ReadError!void {
+ var data_index: usize = 0;
+ const data_end: usize = self.width() * self.height();
+
+ while (data_index < data_end) : (data_index += 1) {
+ data[data_index].b = try stream.readByte();
+ data[data_index].g = try stream.readByte();
+ data[data_index].r = try stream.readByte();
+ data[data_index].a = try stream.readByte();
+
+ if (self.extension) |extended_info| {
+ if (extended_info.attributes != TGAAttributeType.useful_alpha_channel) {
+ data[data_index].a = 0xFF;
+ }
+ }
+ }
+ }
+
+ fn readTruecolor32BottomToTop(self: *TGA, data: []color.Bgra32, stream: TargaStream.Reader) Image.ReadError!void {
+ for (0..self.height()) |y| {
+ const inverted_y = self.height() - y - 1;
+
+ const stride = inverted_y * self.width();
+
+ for (0..self.width()) |x| {
+ const data_index = stride + x;
+
+ data[data_index].b = try stream.readByte();
+ data[data_index].g = try stream.readByte();
+ data[data_index].r = try stream.readByte();
+ data[data_index].a = try stream.readByte();
+
+ if (self.extension) |extended_info| {
+ if (extended_info.attributes != TGAAttributeType.useful_alpha_channel) {
+ data[data_index].a = 0xFF;
+ }
+ }
+ }
+ }
+ }
+
+ pub fn write(self: TGA, stream: *Image.Stream, pixels: color.PixelStorage) Image.WriteError!void {
+ var buffered_stream = buffered_stream_source.bufferedStreamSourceWriter(stream);
+ const writer = buffered_stream.writer();
+
+ try utils.writeStruct(writer, self.header, .little);
+
+ if (self.header.id_length > 0) {
+ if (self.id.data.len != self.header.id_length) {
+ return Image.WriteError.Unsupported;
+ }
+
+ _ = try writer.write(self.id.data);
+ }
+
+ switch (pixels) {
+ .indexed8 => {
+ try self.writeIndexed8(writer, pixels);
+ },
+ .grayscale8,
+ .rgb555,
+ .bgr24,
+ .bgra32,
+ => {
+ try self.writePixels(writer, pixels);
+ },
+ .rgb24 => {
+ try self.writeRgb24(writer, pixels);
+ },
+ .rgba32 => {
+ try self.writeRgba32(writer, pixels);
+ },
+ else => {
+ return Image.WriteError.Unsupported;
+ },
+ }
+
+ var extension_offset: u32 = 0;
+ if (self.extension) |extension| {
+ extension_offset = @truncate(try buffered_stream.getPos());
+
+ try utils.writeStruct(writer, extension, .little);
+ }
+
+ var footer = TGAFooter{};
+ footer.extension_offset = extension_offset;
+ std.mem.copyForwards(u8, footer.signature[0..], TGASignature[0..]);
+ try utils.writeStruct(writer, footer, .little);
+
+ try buffered_stream.flush();
+ }
+
+ fn writePixels(self: TGA, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, pixels: color.PixelStorage) Image.WriteError!void {
+ const bytes = pixels.asConstBytes();
+
+ const effective_height = self.height();
+ const effective_width = self.width();
+ const bytes_per_pixel = std.meta.activeTag(pixels).pixelStride();
+ const pixel_stride = effective_width * bytes_per_pixel;
+
+ if (self.header.image_type.run_length) {
+
+
+ inline for (1..(4 + 1)) |bpp| {
+ const IntType = std.meta.Int(.unsigned, bpp * 8);
+
+ if (bytes_per_pixel == bpp) {
+ if (comptime std.math.isPowerOfTwo(bpp)) {
+ if (self.header.image_spec.descriptor.top_to_bottom) {
+ for (0..effective_height) |y| {
+ const current_scanline = y * pixel_stride;
+
+ try RunLengthSIMDEncoder(IntType).encode(bytes[current_scanline..(current_scanline + pixel_stride)], writer);
+ }
+ } else {
+ for (0..effective_height) |y| {
+ const flipped_y = effective_height - y - 1;
+ const current_scanline = flipped_y * pixel_stride;
+
+ try RunLengthSIMDEncoder(IntType).encode(bytes[current_scanline..(current_scanline + pixel_stride)], writer);
+ }
+ }
+ } else {
+ if (self.header.image_spec.descriptor.top_to_bottom) {
+ for (0..effective_height) |y| {
+ const current_scanline = y * pixel_stride;
+
+ try RunLengthSimpleEncoder(IntType).encode(bytes[current_scanline..(current_scanline + pixel_stride)], writer);
+ }
+ } else {
+ for (0..effective_height) |y| {
+ const flipped_y = effective_height - y - 1;
+ const current_scanline = flipped_y * pixel_stride;
+
+ try RunLengthSimpleEncoder(IntType).encode(bytes[current_scanline..(current_scanline + pixel_stride)], writer);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ if (self.header.image_spec.descriptor.top_to_bottom) {
+ _ = try writer.write(bytes);
+ } else {
+ for (0..effective_height) |y| {
+ const flipped_y = effective_height - y - 1;
+ const current_scanline = flipped_y * pixel_stride;
+
+ _ = try writer.write(bytes[current_scanline..(current_scanline + pixel_stride)]);
+ }
+ }
+ }
+ }
+
+ fn writeRgb24(self: TGA, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, pixels: color.PixelStorage) Image.WriteError!void {
+ const image_width = self.width();
+ const image_height = self.height();
+
+ if (self.header.image_type.run_length) {
+ var rle_encoder = RLEStreamEncoder(color.Bgr24){};
+
+ if (self.header.image_spec.descriptor.top_to_bottom) {
+ for (0..image_height) |y| {
+ const stride = y * image_width;
+
+ for (0..image_width) |x| {
+ const current_color = pixels.rgb24[stride + x];
+
+ const bgr_color = color.Bgr24{ .r = current_color.r, .g = current_color.g, .b = current_color.b };
+
+ try rle_encoder.encode(writer, bgr_color);
+ }
+ }
+ } else {
+ for (0..image_height) |y| {
+ const flipped_y = image_height - y - 1;
+ const stride = flipped_y * image_width;
+
+ for (0..image_width) |x| {
+ const current_color = pixels.rgb24[stride + x];
+
+ const bgr_color = color.Bgr24{ .r = current_color.r, .g = current_color.g, .b = current_color.b };
+
+ try rle_encoder.encode(writer, bgr_color);
+ }
+ }
+ }
+
+ try rle_encoder.flush(writer);
+ } else {
+ if (self.header.image_spec.descriptor.top_to_bottom) {
+ for (0..image_height) |y| {
+ const stride = y * image_width;
+
+ for (0..image_width) |x| {
+ const current_color = pixels.rgb24[stride + x];
+ try writer.writeByte(current_color.b);
+ try writer.writeByte(current_color.g);
+ try writer.writeByte(current_color.r);
+ }
+ }
+ } else {
+ for (0..image_height) |y| {
+ const flipped_y = image_height - y - 1;
+ const stride = flipped_y * image_width;
+
+ for (0..image_width) |x| {
+ const current_color = pixels.rgb24[stride + x];
+ try writer.writeByte(current_color.b);
+ try writer.writeByte(current_color.g);
+ try writer.writeByte(current_color.r);
+ }
+ }
+ }
+ }
+ }
+
+ fn writeRgba32(self: TGA, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, pixels: color.PixelStorage) Image.WriteError!void {
+ const image_width = self.width();
+ const image_height = self.height();
+
+ if (self.header.image_type.run_length) {
+ var rle_encoder = RLEStreamEncoder(color.Bgra32){};
+
+ if (self.header.image_spec.descriptor.top_to_bottom) {
+ for (0..image_height) |y| {
+ const stride = y * image_width;
+
+ for (0..image_width) |x| {
+ const current_color = pixels.rgba32[stride + x];
+
+ const bgra_color = color.Bgra32{ .r = current_color.r, .g = current_color.g, .b = current_color.b, .a = current_color.a };
+
+ try rle_encoder.encode(writer, bgra_color);
+ }
+ }
+ } else {
+ for (0..image_height) |y| {
+ const flipped_y = image_height - y - 1;
+ const stride = flipped_y * image_width;
+
+ for (0..image_width) |x| {
+ const current_color = pixels.rgba32[stride + x];
+
+ const bgra_color = color.Bgra32{ .r = current_color.r, .g = current_color.g, .b = current_color.b, .a = current_color.a };
+
+ try rle_encoder.encode(writer, bgra_color);
+ }
+ }
+ }
+
+ try rle_encoder.flush(writer);
+ } else {
+ if (self.header.image_spec.descriptor.top_to_bottom) {
+ for (0..image_height) |y| {
+ const stride = y * image_width;
+
+ for (0..image_width) |x| {
+ const current_color = pixels.rgba32[stride + x];
+ try writer.writeByte(current_color.b);
+ try writer.writeByte(current_color.g);
+ try writer.writeByte(current_color.r);
+ try writer.writeByte(current_color.a);
+ }
+ }
+ } else {
+ for (0..image_height) |y| {
+ const flipped_y = image_height - y - 1;
+ const stride = flipped_y * image_width;
+
+ for (0..image_width) |x| {
+ const current_color = pixels.rgba32[stride + x];
+ try writer.writeByte(current_color.b);
+ try writer.writeByte(current_color.g);
+ try writer.writeByte(current_color.r);
+ try writer.writeByte(current_color.a);
+ }
+ }
+ }
+ }
+ }
+
+ fn writeIndexed8(self: TGA, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, pixels: color.PixelStorage) Image.WriteError!void {
+
+
+ switch (self.header.color_map_spec.bit_depth) {
+ 15, 16 => {
+ try self.writeColorMap16(writer, pixels.indexed8);
+ },
+ 24 => {
+ try self.writeColorMap24(writer, pixels.indexed8);
+ },
+ else => {
+ return Image.Error.Unsupported;
+ },
+ }
+
+
+
+ try self.writePixels(writer, pixels);
+ }
+
+ fn writeColorMap16(self: TGA, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, indexed: color.IndexedStorage8) Image.WriteError!void {
+ var data_index: usize = self.header.color_map_spec.first_entry_index;
+ const data_end: usize = self.header.color_map_spec.first_entry_index + self.header.color_map_spec.length;
+
+ while (data_index < data_end) : (data_index += 1) {
+ const converted_color = color.Rgb555{
+ .r = color.scaleToIntColor(u5, indexed.palette[data_index].r),
+ .g = color.scaleToIntColor(u5, indexed.palette[data_index].g),
+ .b = color.scaleToIntColor(u5, indexed.palette[data_index].b),
+ };
+
+ try writer.writeInt(u16, @as(u15, @bitCast(converted_color)), .little);
+ }
+ }
+
+ fn writeColorMap24(self: TGA, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, indexed: color.IndexedStorage8) Image.WriteError!void {
+ var data_index: usize = self.header.color_map_spec.first_entry_index;
+ const data_end: usize = self.header.color_map_spec.first_entry_index + self.header.color_map_spec.length;
+
+ while (data_index < data_end) : (data_index += 1) {
+ const converted_color = color.Bgr24{
+ .r = indexed.palette[data_index].r,
+ .g = indexed.palette[data_index].g,
+ .b = indexed.palette[data_index].b,
+ };
+
+ try utils.writeStruct(writer, converted_color, .little);
+ }
+ }
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/octree_quantizer.zig.html b/docs/src/zigimg/src/octree_quantizer.zig.html
new file mode 100644
index 0000000..e9f09e3
--- /dev/null
+++ b/docs/src/zigimg/src/octree_quantizer.zig.html
@@ -0,0 +1,335 @@
+
+
+
+
+
src/octree_quantizer.zig - source view
+
+
+
+
+
+
const Allocator = @import("std").mem.Allocator;
+const ArenaAllocator = @import("std").heap.ArenaAllocator;
+const ArrayList = @import("std").ArrayList;
+const Rgba32 = @import("color.zig").Rgba32;
+
+const MaxDepth = 8;
+
+pub const OctTreeQuantizer = struct {
+ rootNode: OctTreeQuantizerNode,
+ levels: [MaxDepth]NodeArrayList,
+ arenaAllocator: ArenaAllocator,
+
+ const NodeArrayList = ArrayList(*OctTreeQuantizerNode);
+ const Self = @This();
+
+ pub fn init(allocator: Allocator) Self {
+ var result = Self{
+ .rootNode = OctTreeQuantizerNode{},
+ .arenaAllocator = ArenaAllocator.init(allocator),
+ .levels = undefined,
+ };
+ var i: usize = 0;
+ while (i < result.levels.len) : (i += 1) {
+ result.levels[i] = NodeArrayList.init(allocator);
+ }
+ result.rootNode.init(0, &result) catch unreachable;
+ return result;
+ }
+
+ pub fn deinit(self: *Self) void {
+ self.arenaAllocator.deinit();
+ var i: usize = 0;
+ while (i < self.levels.len) : (i += 1) {
+ self.levels[i].deinit();
+ }
+ }
+
+ pub fn allocateNode(self: *Self) !*OctTreeQuantizerNode {
+ return try self.arenaAllocator.allocator().create(OctTreeQuantizerNode);
+ }
+
+ pub fn addLevelNode(self: *Self, level: i32, node: *OctTreeQuantizerNode) !void {
+ try self.levels[@intCast(level)].append(node);
+ }
+
+ pub fn addColor(self: *Self, color: Rgba32) !void {
+ try self.rootNode.addColor(color, 0, self);
+ }
+
+ pub fn getPaletteIndex(self: Self, color: Rgba32) !usize {
+ return try self.rootNode.getPaletteIndex(color, 0);
+ }
+
+ pub fn makePalette(self: *Self, colorCount: usize, palette: []Rgba32) anyerror![]Rgba32 {
+ var paletteIndex: usize = 0;
+
+ var rootLeafNodes = try self.rootNode.getLeafNodes(self.arenaAllocator.child_allocator);
+ defer rootLeafNodes.deinit();
+ var leafCount = rootLeafNodes.items.len;
+
+ var level: usize = MaxDepth - 1;
+ while (level >= 0) : (level -= 1) {
+ for (self.levels[level].items) |node| {
+ leafCount -= @intCast(node.removeLeaves());
+ if (leafCount <= colorCount) {
+ break;
+ }
+ }
+ if (leafCount <= colorCount) {
+ break;
+ }
+ try self.levels[level].resize(0);
+ }
+
+ var processedRoofLeafNodes = try self.rootNode.getLeafNodes(self.arenaAllocator.child_allocator);
+ defer processedRoofLeafNodes.deinit();
+
+ for (processedRoofLeafNodes.items) |node| {
+ if (paletteIndex >= colorCount) {
+ break;
+ }
+ if (node.isLeaf()) {
+ palette[paletteIndex] = node.getColor();
+ node.paletteIndex = paletteIndex;
+ paletteIndex += 1;
+ }
+ }
+
+ return palette[0..paletteIndex];
+ }
+};
+
+const OctTreeQuantizerNode = struct {
+ red: u32 = 0,
+ green: u32 = 0,
+ blue: u32 = 0,
+ referenceCount: usize = 0,
+ paletteIndex: usize = 0,
+ children: [8]?*Self = undefined,
+
+ const Self = @This();
+ const NodeArrayList = ArrayList(*Self);
+
+ pub fn init(self: *Self, level: i32, parent: *OctTreeQuantizer) !void {
+ self.red = 0;
+ self.green = 0;
+ self.blue = 0;
+ self.referenceCount = 0;
+ self.paletteIndex = 0;
+
+ var i: usize = 0;
+ while (i < self.children.len) : (i += 1) {
+ self.children[i] = null;
+ }
+
+ if (level < (MaxDepth - 1)) {
+ try parent.addLevelNode(level, self);
+ }
+ }
+
+ pub fn isLeaf(self: Self) bool {
+ return self.referenceCount > 0;
+ }
+
+ pub fn getColor(self: Self) Rgba32 {
+ return Rgba32.initRgb(@intCast(self.red / self.referenceCount), @intCast(self.green / self.referenceCount), @intCast(self.blue / self.referenceCount));
+ }
+
+ pub fn addColor(self: *Self, color: Rgba32, level: i32, parent: *OctTreeQuantizer) anyerror!void {
+ if (level >= MaxDepth) {
+ self.red += color.r;
+ self.green += color.g;
+ self.blue += color.b;
+ self.referenceCount += 1;
+ return;
+ }
+ const index = getColorIndex(color, level);
+ if (index >= self.children.len) {
+ return error.InvalidColorIndex;
+ }
+ if (self.children[index]) |child| {
+ try child.addColor(color, level + 1, parent);
+ } else {
+ var newNode = try parent.allocateNode();
+ try newNode.init(level, parent);
+ try newNode.addColor(color, level + 1, parent);
+ self.children[index] = newNode;
+ }
+ }
+
+ pub fn getPaletteIndex(self: Self, color: Rgba32, level: i32) anyerror!usize {
+ if (self.isLeaf()) {
+ return self.paletteIndex;
+ }
+ const index = getColorIndex(color, level);
+ if (self.children[index]) |child| {
+ return try child.getPaletteIndex(color, level + 1);
+ } else {
+ for (self.children) |childOptional| {
+ if (childOptional) |child| {
+ return try child.getPaletteIndex(color, level + 1);
+ }
+ }
+ }
+
+ return error.ColorNotFound;
+ }
+
+ pub fn getLeafNodes(self: Self, allocator: Allocator) anyerror!NodeArrayList {
+ var leafNodes = NodeArrayList.init(allocator);
+
+ for (self.children) |childOptional| {
+ if (childOptional) |child| {
+ if (child.isLeaf()) {
+ try leafNodes.append(child);
+ } else {
+ var childNodes = try child.getLeafNodes(allocator);
+ defer childNodes.deinit();
+ for (childNodes.items) |childNode| {
+ try leafNodes.append(childNode);
+ }
+ }
+ }
+ }
+
+ return leafNodes;
+ }
+
+ pub fn removeLeaves(self: *Self) i32 {
+ var result: i32 = 0;
+ for (self.children, 0..) |childOptional, i| {
+ if (childOptional) |child| {
+ self.red += child.red;
+ self.green += child.green;
+ self.blue += child.blue;
+ self.referenceCount += child.referenceCount;
+ result += 1;
+ self.children[i] = null;
+ }
+ }
+ return result - 1;
+ }
+
+ inline fn getColorIndex(color: Rgba32, level: i32) usize {
+ var index: usize = 0;
+ const mask = @as(u8, 0b10000000) >> @intCast(level);
+ if (color.r & mask != 0) {
+ index |= 0b100;
+ }
+ if (color.g & mask != 0) {
+ index |= 0b010;
+ }
+ if (color.b & mask != 0) {
+ index |= 0b001;
+ }
+ return index;
+ }
+};
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/pixel_format.zig.html b/docs/src/zigimg/src/pixel_format.zig.html
new file mode 100644
index 0000000..1a35c54
--- /dev/null
+++ b/docs/src/zigimg/src/pixel_format.zig.html
@@ -0,0 +1,235 @@
+
+
+
+
+
src/pixel_format.zig - source view
+
+
+
+
+
+
pub const PixelFormatVariant = enum(u4) {
+ none = 0,
+ bgr = 1,
+ float = 2,
+ rgb565 = 3,
+ _,
+};
+
+
+
+
+
+
+pub const PixelFormatInfo = packed struct {
+ bits_per_channel: u8 = 0,
+ channel_count: u4 = 0,
+ variant: PixelFormatVariant = .none,
+ padding: u16 = 0,
+};
+
+pub inline fn toPixelFormatValue(comptime pixel_format: PixelFormatInfo) u32 {
+ return @bitCast(pixel_format);
+}
+
+pub const PixelFormat = enum(u32) {
+ invalid = 0,
+ indexed1 = toPixelFormatValue(.{ .bits_per_channel = 1 }),
+ indexed2 = toPixelFormatValue(.{ .bits_per_channel = 2 }),
+ indexed4 = toPixelFormatValue(.{ .bits_per_channel = 4 }),
+ indexed8 = toPixelFormatValue(.{ .bits_per_channel = 8 }),
+ indexed16 = toPixelFormatValue(.{ .bits_per_channel = 16 }),
+ grayscale1 = toPixelFormatValue(.{ .channel_count = 1, .bits_per_channel = 1 }),
+ grayscale2 = toPixelFormatValue(.{ .channel_count = 1, .bits_per_channel = 2 }),
+ grayscale4 = toPixelFormatValue(.{ .channel_count = 1, .bits_per_channel = 4 }),
+ grayscale8 = toPixelFormatValue(.{ .channel_count = 1, .bits_per_channel = 8 }),
+ grayscale16 = toPixelFormatValue(.{ .channel_count = 1, .bits_per_channel = 16 }),
+ grayscale8Alpha = toPixelFormatValue(.{ .channel_count = 2, .bits_per_channel = 8 }),
+ grayscale16Alpha = toPixelFormatValue(.{ .channel_count = 2, .bits_per_channel = 16 }),
+ rgb555 = toPixelFormatValue(.{ .channel_count = 3, .bits_per_channel = 5 }),
+ rgb565 = toPixelFormatValue(.{ .variant = .rgb565, .channel_count = 3, .bits_per_channel = 5 }),
+ rgb24 = toPixelFormatValue(.{ .channel_count = 3, .bits_per_channel = 8 }),
+ rgba32 = toPixelFormatValue(.{ .channel_count = 4, .bits_per_channel = 8 }),
+ bgr555 = toPixelFormatValue(.{ .variant = .bgr, .channel_count = 3, .bits_per_channel = 5 }),
+ bgr24 = toPixelFormatValue(.{ .variant = .bgr, .channel_count = 3, .bits_per_channel = 8 }),
+ bgra32 = toPixelFormatValue(.{ .variant = .bgr, .channel_count = 4, .bits_per_channel = 8 }),
+ rgb48 = toPixelFormatValue(.{ .channel_count = 3, .bits_per_channel = 16 }),
+ rgba64 = toPixelFormatValue(.{ .channel_count = 4, .bits_per_channel = 16 }),
+ float32 = toPixelFormatValue(.{ .variant = .float, .channel_count = 4, .bits_per_channel = 32 }),
+
+ pub inline fn info(self: PixelFormat) PixelFormatInfo {
+ return @as(PixelFormatInfo, @bitCast(@intFromEnum(self)));
+ }
+
+ pub fn isGrayscale(self: PixelFormat) bool {
+ return switch (self) {
+ .grayscale1, .grayscale2, .grayscale4, .grayscale8, .grayscale16, .grayscale8Alpha, .grayscale16Alpha => true,
+ else => false,
+ };
+ }
+
+ pub fn isIndexed(self: PixelFormat) bool {
+ return info(self).channel_count == 0;
+ }
+
+ pub fn isStandardRgb(self: PixelFormat) bool {
+ return self == .rgb24 or self == .rgb48;
+ }
+
+ pub fn isRgba(self: PixelFormat) bool {
+ return self == .rgba32 or self == .rgba64;
+ }
+
+ pub fn is16Bit(self: PixelFormat) bool {
+ return info(self).bits_per_channel == 16;
+ }
+
+ pub fn pixelStride(self: PixelFormat) u8 {
+ if (self.isIndexed()) {
+ return (info(self).bits_per_channel + 7) / 8;
+ }
+
+ return switch (self) {
+ inline else => |value| (info(value).channel_count * info(value).bits_per_channel + 7) / 8,
+ };
+ }
+
+ pub fn bitsPerChannel(self: PixelFormat) u8 {
+ return switch (self) {
+ .rgb565 => unreachable,
+
+ inline else => |value| info(value).bits_per_channel,
+ };
+ }
+
+ pub fn channelCount(self: PixelFormat) u8 {
+ if (self.isIndexed()) {
+ return 1;
+ }
+
+ return switch (self) {
+ inline else => |value| info(value).channel_count,
+ };
+ }
+};
+
+comptime {
+ const std = @import("std");
+
+ std.debug.assert(@intFromEnum(PixelFormat.grayscale1) == 0x101);
+ std.debug.assert(@intFromEnum(PixelFormat.grayscale16) == 0x110);
+ std.debug.assert(@intFromEnum(PixelFormat.grayscale8Alpha) == 0x208);
+ std.debug.assert(@intFromEnum(PixelFormat.rgb555) == 0x305);
+ std.debug.assert(@intFromEnum(PixelFormat.rgb565) == 0x3305);
+ std.debug.assert(@intFromEnum(PixelFormat.rgba32) == 0x408);
+ std.debug.assert(@intFromEnum(PixelFormat.bgr24) == 0x1308);
+ std.debug.assert(@intFromEnum(PixelFormat.bgra32) == 0x1408);
+ std.debug.assert(@intFromEnum(PixelFormat.float32) == 0x2420);
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/simd.zig.html b/docs/src/zigimg/src/simd.zig.html
new file mode 100644
index 0000000..ee4daf7
--- /dev/null
+++ b/docs/src/zigimg/src/simd.zig.html
@@ -0,0 +1,145 @@
+
+
+
+
+
src/simd.zig - source view
+
+
+
+
+
+
const std = @import("std");
+
+pub fn load(bytes: []const u8, comptime T: type, comptime len: u32) T {
+ const mem = std.mem.bytesAsSlice(vectorInnerType(T), bytes);
+ var result: T = @splat(@as(vectorInnerType(T), 0));
+ const vector_len = if (len == 0) vectorLength(T) else len;
+ comptime var i: u32 = 0;
+ inline while (i < vector_len) : (i += 1) {
+ result[i] = mem[i];
+ }
+ return result;
+}
+
+fn vectorLength(comptime VectorType: type) comptime_int {
+ return switch (@typeInfo(VectorType)) {
+ .Vector => |info| info.len,
+ .Array => |info| info.len,
+ else => @compileError("Invalid type " ++ @typeName(VectorType)),
+ };
+}
+
+fn vectorInnerType(comptime VectorType: type) type {
+ return switch (@typeInfo(VectorType)) {
+ .Vector => |info| info.child,
+ .Array => |info| info.child,
+ else => @compileError("Invalid type " ++ @typeName(VectorType)),
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/src/utils.zig.html b/docs/src/zigimg/src/utils.zig.html
new file mode 100644
index 0000000..5c7af25
--- /dev/null
+++ b/docs/src/zigimg/src/utils.zig.html
@@ -0,0 +1,295 @@
+
+
+
+
+
src/utils.zig - source view
+
+
+
+
+
+
const builtin = @import("builtin");
+const std = @import("std");
+
+const native_endian = builtin.target.cpu.arch.endian();
+
+pub const StructReadError = error{ EndOfStream, InvalidData } || std.io.StreamSource.ReadError;
+pub const StructWriteError = std.io.StreamSource.WriteError;
+
+pub fn FixedStorage(comptime T: type, comptime storage_size: usize) type {
+ return struct {
+ data: []T = &.{},
+ storage: [storage_size]T = undefined,
+
+ const Self = @This();
+
+ pub fn resize(self: *Self, size: usize) void {
+ self.data = self.storage[0..size];
+ }
+ };
+}
+
+pub fn toMagicNumberNative(magic: []const u8) u32 {
+ var result: u32 = 0;
+ for (magic, 0..) |character, index| {
+ result |= (@as(u32, character) << @intCast((index * 8)));
+ }
+ return result;
+}
+
+pub fn toMagicNumberForeign(magic: []const u8) u32 {
+ var result: u32 = 0;
+ for (magic, 0..) |character, index| {
+ result |= (@as(u32, character) << @intCast((magic.len - 1 - index) * 8));
+ }
+ return result;
+}
+
+pub inline fn toMagicNumber(magic: []const u8, comptime wanted_endian: std.builtin.Endian) u32 {
+ return switch (native_endian) {
+ .little => {
+ return switch (wanted_endian) {
+ .little => toMagicNumberNative(magic),
+ .big => toMagicNumberForeign(magic),
+ };
+ },
+ .big => {
+ return switch (wanted_endian) {
+ .little => toMagicNumberForeign(magic),
+ .big => toMagicNumberNative(magic),
+ };
+ },
+ };
+}
+
+fn checkEnumFields(data: anytype) StructReadError!void {
+ const T = @typeInfo(@TypeOf(data)).Pointer.child;
+ inline for (std.meta.fields(T)) |entry| {
+ switch (@typeInfo(entry.type)) {
+ .Enum => {
+ const value = @intFromEnum(@field(data, entry.name));
+ _ = std.meta.intToEnum(entry.type, value) catch return StructReadError.InvalidData;
+ },
+ .Struct => {
+ try checkEnumFields(&@field(data, entry.name));
+ },
+ else => {},
+ }
+ }
+}
+
+pub fn readStructNative(reader: anytype, comptime T: type) StructReadError!T {
+ var result: T = try reader.readStruct(T);
+ try checkEnumFields(&result);
+ return result;
+}
+
+pub fn writeStructNative(writer: anytype, value: anytype) StructWriteError!void {
+ try writer.writeStruct(value);
+}
+
+pub fn writeStructForeign(writer: anytype, value: anytype) StructWriteError!void {
+ const T = @typeInfo(@TypeOf(value));
+ inline for (std.meta.fields(T)) |field| {
+ switch (@typeInfo(field.type)) {
+ .Int => {
+ try writer.writeIntForeign(field.type, @field(value, field.name));
+ },
+ .Struct => {
+ try writeStructForeign(writer, @field(value, field.name));
+ },
+ .Enum => {
+ const enum_value = @intFromEnum(@field(value, field.name));
+ try writer.writeIntForeign(field.type, enum_value);
+ },
+ .Bool => {
+ try writer.writeByte(@intFromBool(@field(value, field.name)));
+ },
+ else => {
+ @compileError("Add support for type " ++ @typeName(T) ++ "." ++ @typeName(field.type) ++ " in writeStructForeign()");
+ },
+ }
+ }
+}
+
+
+
+fn swapFieldBytes(data: anytype) StructReadError!void {
+ const T = @typeInfo(@TypeOf(data)).Pointer.child;
+ inline for (std.meta.fields(T)) |entry| {
+ switch (@typeInfo(entry.type)) {
+ .Int => |int| {
+ if (int.bits > 8) {
+ @field(data, entry.name) = @byteSwap(@field(data, entry.name));
+ }
+ },
+ .Struct => {
+ try swapFieldBytes(&@field(data, entry.name));
+ },
+ .Enum => {
+ const value = @intFromEnum(@field(data, entry.name));
+ if (@bitSizeOf(@TypeOf(value)) > 8) {
+ @field(data, entry.name) = try std.meta.intToEnum(entry.type, @byteSwap(value));
+ } else {
+ _ = std.meta.intToEnum(entry.type, value) catch return StructReadError.InvalidData;
+ }
+ },
+ .Array => |array| {
+ if (array.child != u8) {
+ @compileError("Add support for type " ++ @typeName(T) ++ "." ++ @typeName(entry.type) ++ " in swapFieldBytes");
+ }
+ },
+ .Bool => {},
+ else => {
+ @compileError("Add support for type " ++ @typeName(T) ++ "." ++ @typeName(entry.type) ++ " in swapFieldBytes");
+ },
+ }
+ }
+}
+
+pub fn readStructForeign(reader: anytype, comptime T: type) StructReadError!T {
+ var result: T = try reader.readStruct(T);
+ try swapFieldBytes(&result);
+ return result;
+}
+
+pub inline fn readStruct(reader: anytype, comptime T: type, comptime wanted_endian: std.builtin.Endian) StructReadError!T {
+ return switch (native_endian) {
+ .little => {
+ return switch (wanted_endian) {
+ .little => readStructNative(reader, T),
+ .big => readStructForeign(reader, T),
+ };
+ },
+ .big => {
+ return switch (wanted_endian) {
+ .little => readStructForeign(reader, T),
+ .big => readStructNative(reader, T),
+ };
+ },
+ };
+}
+
+pub inline fn writeStruct(writer: anytype, value: anytype, comptime wanted_endian: std.builtin.Endian) StructWriteError!void {
+ return switch (native_endian) {
+ .little => {
+ return switch (wanted_endian) {
+ .little => writeStructNative(writer, value),
+ .big => writeStructForeign(writer, value),
+ };
+ },
+ .big => {
+ return switch (wanted_endian) {
+ .little => writeStructForeign(writer, value),
+ .big => writeStructNative(writer, value),
+ };
+ },
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/zigimg/zigimg.zig.html b/docs/src/zigimg/zigimg.zig.html
new file mode 100644
index 0000000..44a3281
--- /dev/null
+++ b/docs/src/zigimg/zigimg.zig.html
@@ -0,0 +1,156 @@
+
+
+
+
+
zigimg.zig - source view
+
+
+
+
+
+
pub const AllFormats = @import("src/formats/all.zig");
+pub const bmp = @import("src/formats/bmp.zig");
+pub const color = @import("src/color.zig");
+pub const FormatInterface = @import("src/FormatInterface.zig");
+pub const Image = @import("src/Image.zig");
+pub const gif = @import("src/formats/gif.zig");
+pub const netpbm = @import("src/formats/netpbm.zig");
+pub const OctTreeQuantizer = @import("src/octree_quantizer.zig").OctTreeQuantizer;
+pub const pcx = @import("src/formats/pcx.zig");
+pub const PixelFormat = @import("src/pixel_format.zig").PixelFormat;
+pub const jpeg = @import("src/formats/jpeg.zig");
+pub const png = @import("src/formats/png.zig");
+pub const qoi = @import("src/formats/qoi.zig");
+pub const tga = @import("src/formats/tga.zig");
+pub const pam = @import("src/formats/pam.zig");
+
+test {
+ const std = @import("std");
+ std.testing.refAllDecls(@This());
+
+ inline for (.{
+ @import("src/compressions/lzw.zig"),
+ @import("src/formats/png/reader.zig"),
+ @import("tests/buffered_stream_source_test.zig"),
+ @import("tests/color_test.zig"),
+ @import("tests/formats/bmp_test.zig"),
+ @import("tests/formats/gif_test.zig"),
+ @import("tests/formats/jpeg_test.zig"),
+ @import("tests/formats/netpbm_test.zig"),
+ @import("tests/formats/pam_test.zig"),
+ @import("tests/formats/pcx_test.zig"),
+ @import("tests/formats/png_test.zig"),
+ @import("tests/formats/qoi_test.zig"),
+ @import("tests/formats/tga_test.zig"),
+ @import("tests/image_test.zig"),
+ @import("tests/octree_quantizer_test.zig"),
+ @import("tests/pixel_format_test.zig"),
+ }) |source_file| std.testing.refAllDeclsRecursive(source_file);
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/blocks.zig.html b/docs/src/ziglyph/autogen/blocks.zig.html
new file mode 100644
index 0000000..7de2dbd
--- /dev/null
+++ b/docs/src/ziglyph/autogen/blocks.zig.html
@@ -0,0 +1,3062 @@
+
+
+
+
+
autogen/blocks.zig - source view
+
+
+
+
+
+
+
+
+pub fn isBasicLatin(cp: u21) bool {
+ if (cp > 0x7f) return false;
+
+ return switch (cp) {
+ 0x0...0x7f => true,
+ else => false,
+ };
+}
+
+pub fn isLatin1Supplement(cp: u21) bool {
+ if (cp < 0x80 or cp > 0xff) return false;
+
+ return switch (cp) {
+ 0x80...0xff => true,
+ else => false,
+ };
+}
+
+pub fn isLatinExtendedA(cp: u21) bool {
+ if (cp < 0x100 or cp > 0x17f) return false;
+
+ return switch (cp) {
+ 0x100...0x17f => true,
+ else => false,
+ };
+}
+
+pub fn isLatinExtendedB(cp: u21) bool {
+ if (cp < 0x180 or cp > 0x24f) return false;
+
+ return switch (cp) {
+ 0x180...0x24f => true,
+ else => false,
+ };
+}
+
+pub fn isIpaExtensions(cp: u21) bool {
+ if (cp < 0x250 or cp > 0x2af) return false;
+
+ return switch (cp) {
+ 0x250...0x2af => true,
+ else => false,
+ };
+}
+
+pub fn isSpacingModifierLetters(cp: u21) bool {
+ if (cp < 0x2b0 or cp > 0x2ff) return false;
+
+ return switch (cp) {
+ 0x2b0...0x2ff => true,
+ else => false,
+ };
+}
+
+pub fn isCombiningDiacriticalMarks(cp: u21) bool {
+ if (cp < 0x300 or cp > 0x36f) return false;
+
+ return switch (cp) {
+ 0x300...0x36f => true,
+ else => false,
+ };
+}
+
+pub fn isGreekAndCoptic(cp: u21) bool {
+ if (cp < 0x370 or cp > 0x3ff) return false;
+
+ return switch (cp) {
+ 0x370...0x3ff => true,
+ else => false,
+ };
+}
+
+pub fn isCyrillic(cp: u21) bool {
+ if (cp < 0x400 or cp > 0x4ff) return false;
+
+ return switch (cp) {
+ 0x400...0x4ff => true,
+ else => false,
+ };
+}
+
+pub fn isCyrillicSupplement(cp: u21) bool {
+ if (cp < 0x500 or cp > 0x52f) return false;
+
+ return switch (cp) {
+ 0x500...0x52f => true,
+ else => false,
+ };
+}
+
+pub fn isArmenian(cp: u21) bool {
+ if (cp < 0x530 or cp > 0x58f) return false;
+
+ return switch (cp) {
+ 0x530...0x58f => true,
+ else => false,
+ };
+}
+
+pub fn isHebrew(cp: u21) bool {
+ if (cp < 0x590 or cp > 0x5ff) return false;
+
+ return switch (cp) {
+ 0x590...0x5ff => true,
+ else => false,
+ };
+}
+
+pub fn isArabic(cp: u21) bool {
+ if (cp < 0x600 or cp > 0x6ff) return false;
+
+ return switch (cp) {
+ 0x600...0x6ff => true,
+ else => false,
+ };
+}
+
+pub fn isSyriac(cp: u21) bool {
+ if (cp < 0x700 or cp > 0x74f) return false;
+
+ return switch (cp) {
+ 0x700...0x74f => true,
+ else => false,
+ };
+}
+
+pub fn isArabicSupplement(cp: u21) bool {
+ if (cp < 0x750 or cp > 0x77f) return false;
+
+ return switch (cp) {
+ 0x750...0x77f => true,
+ else => false,
+ };
+}
+
+pub fn isThaana(cp: u21) bool {
+ if (cp < 0x780 or cp > 0x7bf) return false;
+
+ return switch (cp) {
+ 0x780...0x7bf => true,
+ else => false,
+ };
+}
+
+pub fn isNko(cp: u21) bool {
+ if (cp < 0x7c0 or cp > 0x7ff) return false;
+
+ return switch (cp) {
+ 0x7c0...0x7ff => true,
+ else => false,
+ };
+}
+
+pub fn isSamaritan(cp: u21) bool {
+ if (cp < 0x800 or cp > 0x83f) return false;
+
+ return switch (cp) {
+ 0x800...0x83f => true,
+ else => false,
+ };
+}
+
+pub fn isMandaic(cp: u21) bool {
+ if (cp < 0x840 or cp > 0x85f) return false;
+
+ return switch (cp) {
+ 0x840...0x85f => true,
+ else => false,
+ };
+}
+
+pub fn isSyriacSupplement(cp: u21) bool {
+ if (cp < 0x860 or cp > 0x86f) return false;
+
+ return switch (cp) {
+ 0x860...0x86f => true,
+ else => false,
+ };
+}
+
+pub fn isArabicExtendedB(cp: u21) bool {
+ if (cp < 0x870 or cp > 0x89f) return false;
+
+ return switch (cp) {
+ 0x870...0x89f => true,
+ else => false,
+ };
+}
+
+pub fn isArabicExtendedA(cp: u21) bool {
+ if (cp < 0x8a0 or cp > 0x8ff) return false;
+
+ return switch (cp) {
+ 0x8a0...0x8ff => true,
+ else => false,
+ };
+}
+
+pub fn isDevanagari(cp: u21) bool {
+ if (cp < 0x900 or cp > 0x97f) return false;
+
+ return switch (cp) {
+ 0x900...0x97f => true,
+ else => false,
+ };
+}
+
+pub fn isBengali(cp: u21) bool {
+ if (cp < 0x980 or cp > 0x9ff) return false;
+
+ return switch (cp) {
+ 0x980...0x9ff => true,
+ else => false,
+ };
+}
+
+pub fn isGurmukhi(cp: u21) bool {
+ if (cp < 0xa00 or cp > 0xa7f) return false;
+
+ return switch (cp) {
+ 0xa00...0xa7f => true,
+ else => false,
+ };
+}
+
+pub fn isGujarati(cp: u21) bool {
+ if (cp < 0xa80 or cp > 0xaff) return false;
+
+ return switch (cp) {
+ 0xa80...0xaff => true,
+ else => false,
+ };
+}
+
+pub fn isOriya(cp: u21) bool {
+ if (cp < 0xb00 or cp > 0xb7f) return false;
+
+ return switch (cp) {
+ 0xb00...0xb7f => true,
+ else => false,
+ };
+}
+
+pub fn isTamil(cp: u21) bool {
+ if (cp < 0xb80 or cp > 0xbff) return false;
+
+ return switch (cp) {
+ 0xb80...0xbff => true,
+ else => false,
+ };
+}
+
+pub fn isTelugu(cp: u21) bool {
+ if (cp < 0xc00 or cp > 0xc7f) return false;
+
+ return switch (cp) {
+ 0xc00...0xc7f => true,
+ else => false,
+ };
+}
+
+pub fn isKannada(cp: u21) bool {
+ if (cp < 0xc80 or cp > 0xcff) return false;
+
+ return switch (cp) {
+ 0xc80...0xcff => true,
+ else => false,
+ };
+}
+
+pub fn isMalayalam(cp: u21) bool {
+ if (cp < 0xd00 or cp > 0xd7f) return false;
+
+ return switch (cp) {
+ 0xd00...0xd7f => true,
+ else => false,
+ };
+}
+
+pub fn isSinhala(cp: u21) bool {
+ if (cp < 0xd80 or cp > 0xdff) return false;
+
+ return switch (cp) {
+ 0xd80...0xdff => true,
+ else => false,
+ };
+}
+
+pub fn isThai(cp: u21) bool {
+ if (cp < 0xe00 or cp > 0xe7f) return false;
+
+ return switch (cp) {
+ 0xe00...0xe7f => true,
+ else => false,
+ };
+}
+
+pub fn isLao(cp: u21) bool {
+ if (cp < 0xe80 or cp > 0xeff) return false;
+
+ return switch (cp) {
+ 0xe80...0xeff => true,
+ else => false,
+ };
+}
+
+pub fn isTibetan(cp: u21) bool {
+ if (cp < 0xf00 or cp > 0xfff) return false;
+
+ return switch (cp) {
+ 0xf00...0xfff => true,
+ else => false,
+ };
+}
+
+pub fn isMyanmar(cp: u21) bool {
+ if (cp < 0x1000 or cp > 0x109f) return false;
+
+ return switch (cp) {
+ 0x1000...0x109f => true,
+ else => false,
+ };
+}
+
+pub fn isGeorgian(cp: u21) bool {
+ if (cp < 0x10a0 or cp > 0x10ff) return false;
+
+ return switch (cp) {
+ 0x10a0...0x10ff => true,
+ else => false,
+ };
+}
+
+pub fn isHangulJamo(cp: u21) bool {
+ if (cp < 0x1100 or cp > 0x11ff) return false;
+
+ return switch (cp) {
+ 0x1100...0x11ff => true,
+ else => false,
+ };
+}
+
+pub fn isEthiopic(cp: u21) bool {
+ if (cp < 0x1200 or cp > 0x137f) return false;
+
+ return switch (cp) {
+ 0x1200...0x137f => true,
+ else => false,
+ };
+}
+
+pub fn isEthiopicSupplement(cp: u21) bool {
+ if (cp < 0x1380 or cp > 0x139f) return false;
+
+ return switch (cp) {
+ 0x1380...0x139f => true,
+ else => false,
+ };
+}
+
+pub fn isCherokee(cp: u21) bool {
+ if (cp < 0x13a0 or cp > 0x13ff) return false;
+
+ return switch (cp) {
+ 0x13a0...0x13ff => true,
+ else => false,
+ };
+}
+
+pub fn isUnifiedCanadianAboriginalSyllabics(cp: u21) bool {
+ if (cp < 0x1400 or cp > 0x167f) return false;
+
+ return switch (cp) {
+ 0x1400...0x167f => true,
+ else => false,
+ };
+}
+
+pub fn isOgham(cp: u21) bool {
+ if (cp < 0x1680 or cp > 0x169f) return false;
+
+ return switch (cp) {
+ 0x1680...0x169f => true,
+ else => false,
+ };
+}
+
+pub fn isRunic(cp: u21) bool {
+ if (cp < 0x16a0 or cp > 0x16ff) return false;
+
+ return switch (cp) {
+ 0x16a0...0x16ff => true,
+ else => false,
+ };
+}
+
+pub fn isTagalog(cp: u21) bool {
+ if (cp < 0x1700 or cp > 0x171f) return false;
+
+ return switch (cp) {
+ 0x1700...0x171f => true,
+ else => false,
+ };
+}
+
+pub fn isHanunoo(cp: u21) bool {
+ if (cp < 0x1720 or cp > 0x173f) return false;
+
+ return switch (cp) {
+ 0x1720...0x173f => true,
+ else => false,
+ };
+}
+
+pub fn isBuhid(cp: u21) bool {
+ if (cp < 0x1740 or cp > 0x175f) return false;
+
+ return switch (cp) {
+ 0x1740...0x175f => true,
+ else => false,
+ };
+}
+
+pub fn isTagbanwa(cp: u21) bool {
+ if (cp < 0x1760 or cp > 0x177f) return false;
+
+ return switch (cp) {
+ 0x1760...0x177f => true,
+ else => false,
+ };
+}
+
+pub fn isKhmer(cp: u21) bool {
+ if (cp < 0x1780 or cp > 0x17ff) return false;
+
+ return switch (cp) {
+ 0x1780...0x17ff => true,
+ else => false,
+ };
+}
+
+pub fn isMongolian(cp: u21) bool {
+ if (cp < 0x1800 or cp > 0x18af) return false;
+
+ return switch (cp) {
+ 0x1800...0x18af => true,
+ else => false,
+ };
+}
+
+pub fn isUnifiedCanadianAboriginalSyllabicsExtended(cp: u21) bool {
+ if (cp < 0x18b0 or cp > 0x18ff) return false;
+
+ return switch (cp) {
+ 0x18b0...0x18ff => true,
+ else => false,
+ };
+}
+
+pub fn isLimbu(cp: u21) bool {
+ if (cp < 0x1900 or cp > 0x194f) return false;
+
+ return switch (cp) {
+ 0x1900...0x194f => true,
+ else => false,
+ };
+}
+
+pub fn isTaiLe(cp: u21) bool {
+ if (cp < 0x1950 or cp > 0x197f) return false;
+
+ return switch (cp) {
+ 0x1950...0x197f => true,
+ else => false,
+ };
+}
+
+pub fn isNewTaiLue(cp: u21) bool {
+ if (cp < 0x1980 or cp > 0x19df) return false;
+
+ return switch (cp) {
+ 0x1980...0x19df => true,
+ else => false,
+ };
+}
+
+pub fn isKhmerSymbols(cp: u21) bool {
+ if (cp < 0x19e0 or cp > 0x19ff) return false;
+
+ return switch (cp) {
+ 0x19e0...0x19ff => true,
+ else => false,
+ };
+}
+
+pub fn isBuginese(cp: u21) bool {
+ if (cp < 0x1a00 or cp > 0x1a1f) return false;
+
+ return switch (cp) {
+ 0x1a00...0x1a1f => true,
+ else => false,
+ };
+}
+
+pub fn isTaiTham(cp: u21) bool {
+ if (cp < 0x1a20 or cp > 0x1aaf) return false;
+
+ return switch (cp) {
+ 0x1a20...0x1aaf => true,
+ else => false,
+ };
+}
+
+pub fn isCombiningDiacriticalMarksExtended(cp: u21) bool {
+ if (cp < 0x1ab0 or cp > 0x1aff) return false;
+
+ return switch (cp) {
+ 0x1ab0...0x1aff => true,
+ else => false,
+ };
+}
+
+pub fn isBalinese(cp: u21) bool {
+ if (cp < 0x1b00 or cp > 0x1b7f) return false;
+
+ return switch (cp) {
+ 0x1b00...0x1b7f => true,
+ else => false,
+ };
+}
+
+pub fn isSundanese(cp: u21) bool {
+ if (cp < 0x1b80 or cp > 0x1bbf) return false;
+
+ return switch (cp) {
+ 0x1b80...0x1bbf => true,
+ else => false,
+ };
+}
+
+pub fn isBatak(cp: u21) bool {
+ if (cp < 0x1bc0 or cp > 0x1bff) return false;
+
+ return switch (cp) {
+ 0x1bc0...0x1bff => true,
+ else => false,
+ };
+}
+
+pub fn isLepcha(cp: u21) bool {
+ if (cp < 0x1c00 or cp > 0x1c4f) return false;
+
+ return switch (cp) {
+ 0x1c00...0x1c4f => true,
+ else => false,
+ };
+}
+
+pub fn isOlChiki(cp: u21) bool {
+ if (cp < 0x1c50 or cp > 0x1c7f) return false;
+
+ return switch (cp) {
+ 0x1c50...0x1c7f => true,
+ else => false,
+ };
+}
+
+pub fn isCyrillicExtendedC(cp: u21) bool {
+ if (cp < 0x1c80 or cp > 0x1c8f) return false;
+
+ return switch (cp) {
+ 0x1c80...0x1c8f => true,
+ else => false,
+ };
+}
+
+pub fn isGeorgianExtended(cp: u21) bool {
+ if (cp < 0x1c90 or cp > 0x1cbf) return false;
+
+ return switch (cp) {
+ 0x1c90...0x1cbf => true,
+ else => false,
+ };
+}
+
+pub fn isSundaneseSupplement(cp: u21) bool {
+ if (cp < 0x1cc0 or cp > 0x1ccf) return false;
+
+ return switch (cp) {
+ 0x1cc0...0x1ccf => true,
+ else => false,
+ };
+}
+
+pub fn isVedicExtensions(cp: u21) bool {
+ if (cp < 0x1cd0 or cp > 0x1cff) return false;
+
+ return switch (cp) {
+ 0x1cd0...0x1cff => true,
+ else => false,
+ };
+}
+
+pub fn isPhoneticExtensions(cp: u21) bool {
+ if (cp < 0x1d00 or cp > 0x1d7f) return false;
+
+ return switch (cp) {
+ 0x1d00...0x1d7f => true,
+ else => false,
+ };
+}
+
+pub fn isPhoneticExtensionsSupplement(cp: u21) bool {
+ if (cp < 0x1d80 or cp > 0x1dbf) return false;
+
+ return switch (cp) {
+ 0x1d80...0x1dbf => true,
+ else => false,
+ };
+}
+
+pub fn isCombiningDiacriticalMarksSupplement(cp: u21) bool {
+ if (cp < 0x1dc0 or cp > 0x1dff) return false;
+
+ return switch (cp) {
+ 0x1dc0...0x1dff => true,
+ else => false,
+ };
+}
+
+pub fn isLatinExtendedAdditional(cp: u21) bool {
+ if (cp < 0x1e00 or cp > 0x1eff) return false;
+
+ return switch (cp) {
+ 0x1e00...0x1eff => true,
+ else => false,
+ };
+}
+
+pub fn isGreekExtended(cp: u21) bool {
+ if (cp < 0x1f00 or cp > 0x1fff) return false;
+
+ return switch (cp) {
+ 0x1f00...0x1fff => true,
+ else => false,
+ };
+}
+
+pub fn isGeneralPunctuation(cp: u21) bool {
+ if (cp < 0x2000 or cp > 0x206f) return false;
+
+ return switch (cp) {
+ 0x2000...0x206f => true,
+ else => false,
+ };
+}
+
+pub fn isSuperscriptsAndSubscripts(cp: u21) bool {
+ if (cp < 0x2070 or cp > 0x209f) return false;
+
+ return switch (cp) {
+ 0x2070...0x209f => true,
+ else => false,
+ };
+}
+
+pub fn isCurrencySymbols(cp: u21) bool {
+ if (cp < 0x20a0 or cp > 0x20cf) return false;
+
+ return switch (cp) {
+ 0x20a0...0x20cf => true,
+ else => false,
+ };
+}
+
+pub fn isCombiningDiacriticalMarksForSymbols(cp: u21) bool {
+ if (cp < 0x20d0 or cp > 0x20ff) return false;
+
+ return switch (cp) {
+ 0x20d0...0x20ff => true,
+ else => false,
+ };
+}
+
+pub fn isLetterlikeSymbols(cp: u21) bool {
+ if (cp < 0x2100 or cp > 0x214f) return false;
+
+ return switch (cp) {
+ 0x2100...0x214f => true,
+ else => false,
+ };
+}
+
+pub fn isNumberForms(cp: u21) bool {
+ if (cp < 0x2150 or cp > 0x218f) return false;
+
+ return switch (cp) {
+ 0x2150...0x218f => true,
+ else => false,
+ };
+}
+
+pub fn isArrows(cp: u21) bool {
+ if (cp < 0x2190 or cp > 0x21ff) return false;
+
+ return switch (cp) {
+ 0x2190...0x21ff => true,
+ else => false,
+ };
+}
+
+pub fn isMathematicalOperators(cp: u21) bool {
+ if (cp < 0x2200 or cp > 0x22ff) return false;
+
+ return switch (cp) {
+ 0x2200...0x22ff => true,
+ else => false,
+ };
+}
+
+pub fn isMiscellaneousTechnical(cp: u21) bool {
+ if (cp < 0x2300 or cp > 0x23ff) return false;
+
+ return switch (cp) {
+ 0x2300...0x23ff => true,
+ else => false,
+ };
+}
+
+pub fn isControlPictures(cp: u21) bool {
+ if (cp < 0x2400 or cp > 0x243f) return false;
+
+ return switch (cp) {
+ 0x2400...0x243f => true,
+ else => false,
+ };
+}
+
+pub fn isOpticalCharacterRecognition(cp: u21) bool {
+ if (cp < 0x2440 or cp > 0x245f) return false;
+
+ return switch (cp) {
+ 0x2440...0x245f => true,
+ else => false,
+ };
+}
+
+pub fn isEnclosedAlphanumerics(cp: u21) bool {
+ if (cp < 0x2460 or cp > 0x24ff) return false;
+
+ return switch (cp) {
+ 0x2460...0x24ff => true,
+ else => false,
+ };
+}
+
+pub fn isBoxDrawing(cp: u21) bool {
+ if (cp < 0x2500 or cp > 0x257f) return false;
+
+ return switch (cp) {
+ 0x2500...0x257f => true,
+ else => false,
+ };
+}
+
+pub fn isBlockElements(cp: u21) bool {
+ if (cp < 0x2580 or cp > 0x259f) return false;
+
+ return switch (cp) {
+ 0x2580...0x259f => true,
+ else => false,
+ };
+}
+
+pub fn isGeometricShapes(cp: u21) bool {
+ if (cp < 0x25a0 or cp > 0x25ff) return false;
+
+ return switch (cp) {
+ 0x25a0...0x25ff => true,
+ else => false,
+ };
+}
+
+pub fn isMiscellaneousSymbols(cp: u21) bool {
+ if (cp < 0x2600 or cp > 0x26ff) return false;
+
+ return switch (cp) {
+ 0x2600...0x26ff => true,
+ else => false,
+ };
+}
+
+pub fn isDingbats(cp: u21) bool {
+ if (cp < 0x2700 or cp > 0x27bf) return false;
+
+ return switch (cp) {
+ 0x2700...0x27bf => true,
+ else => false,
+ };
+}
+
+pub fn isMiscellaneousMathematicalSymbolsA(cp: u21) bool {
+ if (cp < 0x27c0 or cp > 0x27ef) return false;
+
+ return switch (cp) {
+ 0x27c0...0x27ef => true,
+ else => false,
+ };
+}
+
+pub fn isSupplementalArrowsA(cp: u21) bool {
+ if (cp < 0x27f0 or cp > 0x27ff) return false;
+
+ return switch (cp) {
+ 0x27f0...0x27ff => true,
+ else => false,
+ };
+}
+
+pub fn isBraillePatterns(cp: u21) bool {
+ if (cp < 0x2800 or cp > 0x28ff) return false;
+
+ return switch (cp) {
+ 0x2800...0x28ff => true,
+ else => false,
+ };
+}
+
+pub fn isSupplementalArrowsB(cp: u21) bool {
+ if (cp < 0x2900 or cp > 0x297f) return false;
+
+ return switch (cp) {
+ 0x2900...0x297f => true,
+ else => false,
+ };
+}
+
+pub fn isMiscellaneousMathematicalSymbolsB(cp: u21) bool {
+ if (cp < 0x2980 or cp > 0x29ff) return false;
+
+ return switch (cp) {
+ 0x2980...0x29ff => true,
+ else => false,
+ };
+}
+
+pub fn isSupplementalMathematicalOperators(cp: u21) bool {
+ if (cp < 0x2a00 or cp > 0x2aff) return false;
+
+ return switch (cp) {
+ 0x2a00...0x2aff => true,
+ else => false,
+ };
+}
+
+pub fn isMiscellaneousSymbolsAndArrows(cp: u21) bool {
+ if (cp < 0x2b00 or cp > 0x2bff) return false;
+
+ return switch (cp) {
+ 0x2b00...0x2bff => true,
+ else => false,
+ };
+}
+
+pub fn isGlagolitic(cp: u21) bool {
+ if (cp < 0x2c00 or cp > 0x2c5f) return false;
+
+ return switch (cp) {
+ 0x2c00...0x2c5f => true,
+ else => false,
+ };
+}
+
+pub fn isLatinExtendedC(cp: u21) bool {
+ if (cp < 0x2c60 or cp > 0x2c7f) return false;
+
+ return switch (cp) {
+ 0x2c60...0x2c7f => true,
+ else => false,
+ };
+}
+
+pub fn isCoptic(cp: u21) bool {
+ if (cp < 0x2c80 or cp > 0x2cff) return false;
+
+ return switch (cp) {
+ 0x2c80...0x2cff => true,
+ else => false,
+ };
+}
+
+pub fn isGeorgianSupplement(cp: u21) bool {
+ if (cp < 0x2d00 or cp > 0x2d2f) return false;
+
+ return switch (cp) {
+ 0x2d00...0x2d2f => true,
+ else => false,
+ };
+}
+
+pub fn isTifinagh(cp: u21) bool {
+ if (cp < 0x2d30 or cp > 0x2d7f) return false;
+
+ return switch (cp) {
+ 0x2d30...0x2d7f => true,
+ else => false,
+ };
+}
+
+pub fn isEthiopicExtended(cp: u21) bool {
+ if (cp < 0x2d80 or cp > 0x2ddf) return false;
+
+ return switch (cp) {
+ 0x2d80...0x2ddf => true,
+ else => false,
+ };
+}
+
+pub fn isCyrillicExtendedA(cp: u21) bool {
+ if (cp < 0x2de0 or cp > 0x2dff) return false;
+
+ return switch (cp) {
+ 0x2de0...0x2dff => true,
+ else => false,
+ };
+}
+
+pub fn isSupplementalPunctuation(cp: u21) bool {
+ if (cp < 0x2e00 or cp > 0x2e7f) return false;
+
+ return switch (cp) {
+ 0x2e00...0x2e7f => true,
+ else => false,
+ };
+}
+
+pub fn isCjkRadicalsSupplement(cp: u21) bool {
+ if (cp < 0x2e80 or cp > 0x2eff) return false;
+
+ return switch (cp) {
+ 0x2e80...0x2eff => true,
+ else => false,
+ };
+}
+
+pub fn isKangxiRadicals(cp: u21) bool {
+ if (cp < 0x2f00 or cp > 0x2fdf) return false;
+
+ return switch (cp) {
+ 0x2f00...0x2fdf => true,
+ else => false,
+ };
+}
+
+pub fn isIdeographicDescriptionCharacters(cp: u21) bool {
+ if (cp < 0x2ff0 or cp > 0x2fff) return false;
+
+ return switch (cp) {
+ 0x2ff0...0x2fff => true,
+ else => false,
+ };
+}
+
+pub fn isCjkSymbolsAndPunctuation(cp: u21) bool {
+ if (cp < 0x3000 or cp > 0x303f) return false;
+
+ return switch (cp) {
+ 0x3000...0x303f => true,
+ else => false,
+ };
+}
+
+pub fn isHiragana(cp: u21) bool {
+ if (cp < 0x3040 or cp > 0x309f) return false;
+
+ return switch (cp) {
+ 0x3040...0x309f => true,
+ else => false,
+ };
+}
+
+pub fn isKatakana(cp: u21) bool {
+ if (cp < 0x30a0 or cp > 0x30ff) return false;
+
+ return switch (cp) {
+ 0x30a0...0x30ff => true,
+ else => false,
+ };
+}
+
+pub fn isBopomofo(cp: u21) bool {
+ if (cp < 0x3100 or cp > 0x312f) return false;
+
+ return switch (cp) {
+ 0x3100...0x312f => true,
+ else => false,
+ };
+}
+
+pub fn isHangulCompatibilityJamo(cp: u21) bool {
+ if (cp < 0x3130 or cp > 0x318f) return false;
+
+ return switch (cp) {
+ 0x3130...0x318f => true,
+ else => false,
+ };
+}
+
+pub fn isKanbun(cp: u21) bool {
+ if (cp < 0x3190 or cp > 0x319f) return false;
+
+ return switch (cp) {
+ 0x3190...0x319f => true,
+ else => false,
+ };
+}
+
+pub fn isBopomofoExtended(cp: u21) bool {
+ if (cp < 0x31a0 or cp > 0x31bf) return false;
+
+ return switch (cp) {
+ 0x31a0...0x31bf => true,
+ else => false,
+ };
+}
+
+pub fn isCjkStrokes(cp: u21) bool {
+ if (cp < 0x31c0 or cp > 0x31ef) return false;
+
+ return switch (cp) {
+ 0x31c0...0x31ef => true,
+ else => false,
+ };
+}
+
+pub fn isKatakanaPhoneticExtensions(cp: u21) bool {
+ if (cp < 0x31f0 or cp > 0x31ff) return false;
+
+ return switch (cp) {
+ 0x31f0...0x31ff => true,
+ else => false,
+ };
+}
+
+pub fn isEnclosedCjkLettersAndMonths(cp: u21) bool {
+ if (cp < 0x3200 or cp > 0x32ff) return false;
+
+ return switch (cp) {
+ 0x3200...0x32ff => true,
+ else => false,
+ };
+}
+
+pub fn isCjkCompatibility(cp: u21) bool {
+ if (cp < 0x3300 or cp > 0x33ff) return false;
+
+ return switch (cp) {
+ 0x3300...0x33ff => true,
+ else => false,
+ };
+}
+
+pub fn isCjkUnifiedIdeographsExtensionA(cp: u21) bool {
+ if (cp < 0x3400 or cp > 0x4dbf) return false;
+
+ return switch (cp) {
+ 0x3400...0x4dbf => true,
+ else => false,
+ };
+}
+
+pub fn isYijingHexagramSymbols(cp: u21) bool {
+ if (cp < 0x4dc0 or cp > 0x4dff) return false;
+
+ return switch (cp) {
+ 0x4dc0...0x4dff => true,
+ else => false,
+ };
+}
+
+pub fn isCjkUnifiedIdeographs(cp: u21) bool {
+ if (cp < 0x4e00 or cp > 0x9fff) return false;
+
+ return switch (cp) {
+ 0x4e00...0x9fff => true,
+ else => false,
+ };
+}
+
+pub fn isYiSyllables(cp: u21) bool {
+ if (cp < 0xa000 or cp > 0xa48f) return false;
+
+ return switch (cp) {
+ 0xa000...0xa48f => true,
+ else => false,
+ };
+}
+
+pub fn isYiRadicals(cp: u21) bool {
+ if (cp < 0xa490 or cp > 0xa4cf) return false;
+
+ return switch (cp) {
+ 0xa490...0xa4cf => true,
+ else => false,
+ };
+}
+
+pub fn isLisu(cp: u21) bool {
+ if (cp < 0xa4d0 or cp > 0xa4ff) return false;
+
+ return switch (cp) {
+ 0xa4d0...0xa4ff => true,
+ else => false,
+ };
+}
+
+pub fn isVai(cp: u21) bool {
+ if (cp < 0xa500 or cp > 0xa63f) return false;
+
+ return switch (cp) {
+ 0xa500...0xa63f => true,
+ else => false,
+ };
+}
+
+pub fn isCyrillicExtendedB(cp: u21) bool {
+ if (cp < 0xa640 or cp > 0xa69f) return false;
+
+ return switch (cp) {
+ 0xa640...0xa69f => true,
+ else => false,
+ };
+}
+
+pub fn isBamum(cp: u21) bool {
+ if (cp < 0xa6a0 or cp > 0xa6ff) return false;
+
+ return switch (cp) {
+ 0xa6a0...0xa6ff => true,
+ else => false,
+ };
+}
+
+pub fn isModifierToneLetters(cp: u21) bool {
+ if (cp < 0xa700 or cp > 0xa71f) return false;
+
+ return switch (cp) {
+ 0xa700...0xa71f => true,
+ else => false,
+ };
+}
+
+pub fn isLatinExtendedD(cp: u21) bool {
+ if (cp < 0xa720 or cp > 0xa7ff) return false;
+
+ return switch (cp) {
+ 0xa720...0xa7ff => true,
+ else => false,
+ };
+}
+
+pub fn isSylotiNagri(cp: u21) bool {
+ if (cp < 0xa800 or cp > 0xa82f) return false;
+
+ return switch (cp) {
+ 0xa800...0xa82f => true,
+ else => false,
+ };
+}
+
+pub fn isCommonIndicNumberForms(cp: u21) bool {
+ if (cp < 0xa830 or cp > 0xa83f) return false;
+
+ return switch (cp) {
+ 0xa830...0xa83f => true,
+ else => false,
+ };
+}
+
+pub fn isPhagsPa(cp: u21) bool {
+ if (cp < 0xa840 or cp > 0xa87f) return false;
+
+ return switch (cp) {
+ 0xa840...0xa87f => true,
+ else => false,
+ };
+}
+
+pub fn isSaurashtra(cp: u21) bool {
+ if (cp < 0xa880 or cp > 0xa8df) return false;
+
+ return switch (cp) {
+ 0xa880...0xa8df => true,
+ else => false,
+ };
+}
+
+pub fn isDevanagariExtended(cp: u21) bool {
+ if (cp < 0xa8e0 or cp > 0xa8ff) return false;
+
+ return switch (cp) {
+ 0xa8e0...0xa8ff => true,
+ else => false,
+ };
+}
+
+pub fn isKayahLi(cp: u21) bool {
+ if (cp < 0xa900 or cp > 0xa92f) return false;
+
+ return switch (cp) {
+ 0xa900...0xa92f => true,
+ else => false,
+ };
+}
+
+pub fn isRejang(cp: u21) bool {
+ if (cp < 0xa930 or cp > 0xa95f) return false;
+
+ return switch (cp) {
+ 0xa930...0xa95f => true,
+ else => false,
+ };
+}
+
+pub fn isHangulJamoExtendedA(cp: u21) bool {
+ if (cp < 0xa960 or cp > 0xa97f) return false;
+
+ return switch (cp) {
+ 0xa960...0xa97f => true,
+ else => false,
+ };
+}
+
+pub fn isJavanese(cp: u21) bool {
+ if (cp < 0xa980 or cp > 0xa9df) return false;
+
+ return switch (cp) {
+ 0xa980...0xa9df => true,
+ else => false,
+ };
+}
+
+pub fn isMyanmarExtendedB(cp: u21) bool {
+ if (cp < 0xa9e0 or cp > 0xa9ff) return false;
+
+ return switch (cp) {
+ 0xa9e0...0xa9ff => true,
+ else => false,
+ };
+}
+
+pub fn isCham(cp: u21) bool {
+ if (cp < 0xaa00 or cp > 0xaa5f) return false;
+
+ return switch (cp) {
+ 0xaa00...0xaa5f => true,
+ else => false,
+ };
+}
+
+pub fn isMyanmarExtendedA(cp: u21) bool {
+ if (cp < 0xaa60 or cp > 0xaa7f) return false;
+
+ return switch (cp) {
+ 0xaa60...0xaa7f => true,
+ else => false,
+ };
+}
+
+pub fn isTaiViet(cp: u21) bool {
+ if (cp < 0xaa80 or cp > 0xaadf) return false;
+
+ return switch (cp) {
+ 0xaa80...0xaadf => true,
+ else => false,
+ };
+}
+
+pub fn isMeeteiMayekExtensions(cp: u21) bool {
+ if (cp < 0xaae0 or cp > 0xaaff) return false;
+
+ return switch (cp) {
+ 0xaae0...0xaaff => true,
+ else => false,
+ };
+}
+
+pub fn isEthiopicExtendedA(cp: u21) bool {
+ if (cp < 0xab00 or cp > 0xab2f) return false;
+
+ return switch (cp) {
+ 0xab00...0xab2f => true,
+ else => false,
+ };
+}
+
+pub fn isLatinExtendedE(cp: u21) bool {
+ if (cp < 0xab30 or cp > 0xab6f) return false;
+
+ return switch (cp) {
+ 0xab30...0xab6f => true,
+ else => false,
+ };
+}
+
+pub fn isCherokeeSupplement(cp: u21) bool {
+ if (cp < 0xab70 or cp > 0xabbf) return false;
+
+ return switch (cp) {
+ 0xab70...0xabbf => true,
+ else => false,
+ };
+}
+
+pub fn isMeeteiMayek(cp: u21) bool {
+ if (cp < 0xabc0 or cp > 0xabff) return false;
+
+ return switch (cp) {
+ 0xabc0...0xabff => true,
+ else => false,
+ };
+}
+
+pub fn isHangulSyllables(cp: u21) bool {
+ if (cp < 0xac00 or cp > 0xd7af) return false;
+
+ return switch (cp) {
+ 0xac00...0xd7af => true,
+ else => false,
+ };
+}
+
+pub fn isHangulJamoExtendedB(cp: u21) bool {
+ if (cp < 0xd7b0 or cp > 0xd7ff) return false;
+
+ return switch (cp) {
+ 0xd7b0...0xd7ff => true,
+ else => false,
+ };
+}
+
+pub fn isHighSurrogates(cp: u21) bool {
+ if (cp < 0xd800 or cp > 0xdb7f) return false;
+
+ return switch (cp) {
+ 0xd800...0xdb7f => true,
+ else => false,
+ };
+}
+
+pub fn isHighPrivateUseSurrogates(cp: u21) bool {
+ if (cp < 0xdb80 or cp > 0xdbff) return false;
+
+ return switch (cp) {
+ 0xdb80...0xdbff => true,
+ else => false,
+ };
+}
+
+pub fn isLowSurrogates(cp: u21) bool {
+ if (cp < 0xdc00 or cp > 0xdfff) return false;
+
+ return switch (cp) {
+ 0xdc00...0xdfff => true,
+ else => false,
+ };
+}
+
+pub fn isPrivateUseArea(cp: u21) bool {
+ if (cp < 0xe000 or cp > 0xf8ff) return false;
+
+ return switch (cp) {
+ 0xe000...0xf8ff => true,
+ else => false,
+ };
+}
+
+pub fn isCjkCompatibilityIdeographs(cp: u21) bool {
+ if (cp < 0xf900 or cp > 0xfaff) return false;
+
+ return switch (cp) {
+ 0xf900...0xfaff => true,
+ else => false,
+ };
+}
+
+pub fn isAlphabeticPresentationForms(cp: u21) bool {
+ if (cp < 0xfb00 or cp > 0xfb4f) return false;
+
+ return switch (cp) {
+ 0xfb00...0xfb4f => true,
+ else => false,
+ };
+}
+
+pub fn isArabicPresentationFormsA(cp: u21) bool {
+ if (cp < 0xfb50 or cp > 0xfdff) return false;
+
+ return switch (cp) {
+ 0xfb50...0xfdff => true,
+ else => false,
+ };
+}
+
+pub fn isVariationSelectors(cp: u21) bool {
+ if (cp < 0xfe00 or cp > 0xfe0f) return false;
+
+ return switch (cp) {
+ 0xfe00...0xfe0f => true,
+ else => false,
+ };
+}
+
+pub fn isVerticalForms(cp: u21) bool {
+ if (cp < 0xfe10 or cp > 0xfe1f) return false;
+
+ return switch (cp) {
+ 0xfe10...0xfe1f => true,
+ else => false,
+ };
+}
+
+pub fn isCombiningHalfMarks(cp: u21) bool {
+ if (cp < 0xfe20 or cp > 0xfe2f) return false;
+
+ return switch (cp) {
+ 0xfe20...0xfe2f => true,
+ else => false,
+ };
+}
+
+pub fn isCjkCompatibilityForms(cp: u21) bool {
+ if (cp < 0xfe30 or cp > 0xfe4f) return false;
+
+ return switch (cp) {
+ 0xfe30...0xfe4f => true,
+ else => false,
+ };
+}
+
+pub fn isSmallFormVariants(cp: u21) bool {
+ if (cp < 0xfe50 or cp > 0xfe6f) return false;
+
+ return switch (cp) {
+ 0xfe50...0xfe6f => true,
+ else => false,
+ };
+}
+
+pub fn isArabicPresentationFormsB(cp: u21) bool {
+ if (cp < 0xfe70 or cp > 0xfeff) return false;
+
+ return switch (cp) {
+ 0xfe70...0xfeff => true,
+ else => false,
+ };
+}
+
+pub fn isHalfwidthAndFullwidthForms(cp: u21) bool {
+ if (cp < 0xff00 or cp > 0xffef) return false;
+
+ return switch (cp) {
+ 0xff00...0xffef => true,
+ else => false,
+ };
+}
+
+pub fn isSpecials(cp: u21) bool {
+ if (cp < 0xfff0 or cp > 0xffff) return false;
+
+ return switch (cp) {
+ 0xfff0...0xffff => true,
+ else => false,
+ };
+}
+
+pub fn isLinearBSyllabary(cp: u21) bool {
+ if (cp < 0x10000 or cp > 0x1007f) return false;
+
+ return switch (cp) {
+ 0x10000...0x1007f => true,
+ else => false,
+ };
+}
+
+pub fn isLinearBIdeograms(cp: u21) bool {
+ if (cp < 0x10080 or cp > 0x100ff) return false;
+
+ return switch (cp) {
+ 0x10080...0x100ff => true,
+ else => false,
+ };
+}
+
+pub fn isAegeanNumbers(cp: u21) bool {
+ if (cp < 0x10100 or cp > 0x1013f) return false;
+
+ return switch (cp) {
+ 0x10100...0x1013f => true,
+ else => false,
+ };
+}
+
+pub fn isAncientGreekNumbers(cp: u21) bool {
+ if (cp < 0x10140 or cp > 0x1018f) return false;
+
+ return switch (cp) {
+ 0x10140...0x1018f => true,
+ else => false,
+ };
+}
+
+pub fn isAncientSymbols(cp: u21) bool {
+ if (cp < 0x10190 or cp > 0x101cf) return false;
+
+ return switch (cp) {
+ 0x10190...0x101cf => true,
+ else => false,
+ };
+}
+
+pub fn isPhaistosDisc(cp: u21) bool {
+ if (cp < 0x101d0 or cp > 0x101ff) return false;
+
+ return switch (cp) {
+ 0x101d0...0x101ff => true,
+ else => false,
+ };
+}
+
+pub fn isLycian(cp: u21) bool {
+ if (cp < 0x10280 or cp > 0x1029f) return false;
+
+ return switch (cp) {
+ 0x10280...0x1029f => true,
+ else => false,
+ };
+}
+
+pub fn isCarian(cp: u21) bool {
+ if (cp < 0x102a0 or cp > 0x102df) return false;
+
+ return switch (cp) {
+ 0x102a0...0x102df => true,
+ else => false,
+ };
+}
+
+pub fn isCopticEpactNumbers(cp: u21) bool {
+ if (cp < 0x102e0 or cp > 0x102ff) return false;
+
+ return switch (cp) {
+ 0x102e0...0x102ff => true,
+ else => false,
+ };
+}
+
+pub fn isOldItalic(cp: u21) bool {
+ if (cp < 0x10300 or cp > 0x1032f) return false;
+
+ return switch (cp) {
+ 0x10300...0x1032f => true,
+ else => false,
+ };
+}
+
+pub fn isGothic(cp: u21) bool {
+ if (cp < 0x10330 or cp > 0x1034f) return false;
+
+ return switch (cp) {
+ 0x10330...0x1034f => true,
+ else => false,
+ };
+}
+
+pub fn isOldPermic(cp: u21) bool {
+ if (cp < 0x10350 or cp > 0x1037f) return false;
+
+ return switch (cp) {
+ 0x10350...0x1037f => true,
+ else => false,
+ };
+}
+
+pub fn isUgaritic(cp: u21) bool {
+ if (cp < 0x10380 or cp > 0x1039f) return false;
+
+ return switch (cp) {
+ 0x10380...0x1039f => true,
+ else => false,
+ };
+}
+
+pub fn isOldPersian(cp: u21) bool {
+ if (cp < 0x103a0 or cp > 0x103df) return false;
+
+ return switch (cp) {
+ 0x103a0...0x103df => true,
+ else => false,
+ };
+}
+
+pub fn isDeseret(cp: u21) bool {
+ if (cp < 0x10400 or cp > 0x1044f) return false;
+
+ return switch (cp) {
+ 0x10400...0x1044f => true,
+ else => false,
+ };
+}
+
+pub fn isShavian(cp: u21) bool {
+ if (cp < 0x10450 or cp > 0x1047f) return false;
+
+ return switch (cp) {
+ 0x10450...0x1047f => true,
+ else => false,
+ };
+}
+
+pub fn isOsmanya(cp: u21) bool {
+ if (cp < 0x10480 or cp > 0x104af) return false;
+
+ return switch (cp) {
+ 0x10480...0x104af => true,
+ else => false,
+ };
+}
+
+pub fn isOsage(cp: u21) bool {
+ if (cp < 0x104b0 or cp > 0x104ff) return false;
+
+ return switch (cp) {
+ 0x104b0...0x104ff => true,
+ else => false,
+ };
+}
+
+pub fn isElbasan(cp: u21) bool {
+ if (cp < 0x10500 or cp > 0x1052f) return false;
+
+ return switch (cp) {
+ 0x10500...0x1052f => true,
+ else => false,
+ };
+}
+
+pub fn isCaucasianAlbanian(cp: u21) bool {
+ if (cp < 0x10530 or cp > 0x1056f) return false;
+
+ return switch (cp) {
+ 0x10530...0x1056f => true,
+ else => false,
+ };
+}
+
+pub fn isVithkuqi(cp: u21) bool {
+ if (cp < 0x10570 or cp > 0x105bf) return false;
+
+ return switch (cp) {
+ 0x10570...0x105bf => true,
+ else => false,
+ };
+}
+
+pub fn isLinearA(cp: u21) bool {
+ if (cp < 0x10600 or cp > 0x1077f) return false;
+
+ return switch (cp) {
+ 0x10600...0x1077f => true,
+ else => false,
+ };
+}
+
+pub fn isLatinExtendedF(cp: u21) bool {
+ if (cp < 0x10780 or cp > 0x107bf) return false;
+
+ return switch (cp) {
+ 0x10780...0x107bf => true,
+ else => false,
+ };
+}
+
+pub fn isCypriotSyllabary(cp: u21) bool {
+ if (cp < 0x10800 or cp > 0x1083f) return false;
+
+ return switch (cp) {
+ 0x10800...0x1083f => true,
+ else => false,
+ };
+}
+
+pub fn isImperialAramaic(cp: u21) bool {
+ if (cp < 0x10840 or cp > 0x1085f) return false;
+
+ return switch (cp) {
+ 0x10840...0x1085f => true,
+ else => false,
+ };
+}
+
+pub fn isPalmyrene(cp: u21) bool {
+ if (cp < 0x10860 or cp > 0x1087f) return false;
+
+ return switch (cp) {
+ 0x10860...0x1087f => true,
+ else => false,
+ };
+}
+
+pub fn isNabataean(cp: u21) bool {
+ if (cp < 0x10880 or cp > 0x108af) return false;
+
+ return switch (cp) {
+ 0x10880...0x108af => true,
+ else => false,
+ };
+}
+
+pub fn isHatran(cp: u21) bool {
+ if (cp < 0x108e0 or cp > 0x108ff) return false;
+
+ return switch (cp) {
+ 0x108e0...0x108ff => true,
+ else => false,
+ };
+}
+
+pub fn isPhoenician(cp: u21) bool {
+ if (cp < 0x10900 or cp > 0x1091f) return false;
+
+ return switch (cp) {
+ 0x10900...0x1091f => true,
+ else => false,
+ };
+}
+
+pub fn isLydian(cp: u21) bool {
+ if (cp < 0x10920 or cp > 0x1093f) return false;
+
+ return switch (cp) {
+ 0x10920...0x1093f => true,
+ else => false,
+ };
+}
+
+pub fn isMeroiticHieroglyphs(cp: u21) bool {
+ if (cp < 0x10980 or cp > 0x1099f) return false;
+
+ return switch (cp) {
+ 0x10980...0x1099f => true,
+ else => false,
+ };
+}
+
+pub fn isMeroiticCursive(cp: u21) bool {
+ if (cp < 0x109a0 or cp > 0x109ff) return false;
+
+ return switch (cp) {
+ 0x109a0...0x109ff => true,
+ else => false,
+ };
+}
+
+pub fn isKharoshthi(cp: u21) bool {
+ if (cp < 0x10a00 or cp > 0x10a5f) return false;
+
+ return switch (cp) {
+ 0x10a00...0x10a5f => true,
+ else => false,
+ };
+}
+
+pub fn isOldSouthArabian(cp: u21) bool {
+ if (cp < 0x10a60 or cp > 0x10a7f) return false;
+
+ return switch (cp) {
+ 0x10a60...0x10a7f => true,
+ else => false,
+ };
+}
+
+pub fn isOldNorthArabian(cp: u21) bool {
+ if (cp < 0x10a80 or cp > 0x10a9f) return false;
+
+ return switch (cp) {
+ 0x10a80...0x10a9f => true,
+ else => false,
+ };
+}
+
+pub fn isManichaean(cp: u21) bool {
+ if (cp < 0x10ac0 or cp > 0x10aff) return false;
+
+ return switch (cp) {
+ 0x10ac0...0x10aff => true,
+ else => false,
+ };
+}
+
+pub fn isAvestan(cp: u21) bool {
+ if (cp < 0x10b00 or cp > 0x10b3f) return false;
+
+ return switch (cp) {
+ 0x10b00...0x10b3f => true,
+ else => false,
+ };
+}
+
+pub fn isInscriptionalParthian(cp: u21) bool {
+ if (cp < 0x10b40 or cp > 0x10b5f) return false;
+
+ return switch (cp) {
+ 0x10b40...0x10b5f => true,
+ else => false,
+ };
+}
+
+pub fn isInscriptionalPahlavi(cp: u21) bool {
+ if (cp < 0x10b60 or cp > 0x10b7f) return false;
+
+ return switch (cp) {
+ 0x10b60...0x10b7f => true,
+ else => false,
+ };
+}
+
+pub fn isPsalterPahlavi(cp: u21) bool {
+ if (cp < 0x10b80 or cp > 0x10baf) return false;
+
+ return switch (cp) {
+ 0x10b80...0x10baf => true,
+ else => false,
+ };
+}
+
+pub fn isOldTurkic(cp: u21) bool {
+ if (cp < 0x10c00 or cp > 0x10c4f) return false;
+
+ return switch (cp) {
+ 0x10c00...0x10c4f => true,
+ else => false,
+ };
+}
+
+pub fn isOldHungarian(cp: u21) bool {
+ if (cp < 0x10c80 or cp > 0x10cff) return false;
+
+ return switch (cp) {
+ 0x10c80...0x10cff => true,
+ else => false,
+ };
+}
+
+pub fn isHanifiRohingya(cp: u21) bool {
+ if (cp < 0x10d00 or cp > 0x10d3f) return false;
+
+ return switch (cp) {
+ 0x10d00...0x10d3f => true,
+ else => false,
+ };
+}
+
+pub fn isRumiNumeralSymbols(cp: u21) bool {
+ if (cp < 0x10e60 or cp > 0x10e7f) return false;
+
+ return switch (cp) {
+ 0x10e60...0x10e7f => true,
+ else => false,
+ };
+}
+
+pub fn isYezidi(cp: u21) bool {
+ if (cp < 0x10e80 or cp > 0x10ebf) return false;
+
+ return switch (cp) {
+ 0x10e80...0x10ebf => true,
+ else => false,
+ };
+}
+
+pub fn isArabicExtendedC(cp: u21) bool {
+ if (cp < 0x10ec0 or cp > 0x10eff) return false;
+
+ return switch (cp) {
+ 0x10ec0...0x10eff => true,
+ else => false,
+ };
+}
+
+pub fn isOldSogdian(cp: u21) bool {
+ if (cp < 0x10f00 or cp > 0x10f2f) return false;
+
+ return switch (cp) {
+ 0x10f00...0x10f2f => true,
+ else => false,
+ };
+}
+
+pub fn isSogdian(cp: u21) bool {
+ if (cp < 0x10f30 or cp > 0x10f6f) return false;
+
+ return switch (cp) {
+ 0x10f30...0x10f6f => true,
+ else => false,
+ };
+}
+
+pub fn isOldUyghur(cp: u21) bool {
+ if (cp < 0x10f70 or cp > 0x10faf) return false;
+
+ return switch (cp) {
+ 0x10f70...0x10faf => true,
+ else => false,
+ };
+}
+
+pub fn isChorasmian(cp: u21) bool {
+ if (cp < 0x10fb0 or cp > 0x10fdf) return false;
+
+ return switch (cp) {
+ 0x10fb0...0x10fdf => true,
+ else => false,
+ };
+}
+
+pub fn isElymaic(cp: u21) bool {
+ if (cp < 0x10fe0 or cp > 0x10fff) return false;
+
+ return switch (cp) {
+ 0x10fe0...0x10fff => true,
+ else => false,
+ };
+}
+
+pub fn isBrahmi(cp: u21) bool {
+ if (cp < 0x11000 or cp > 0x1107f) return false;
+
+ return switch (cp) {
+ 0x11000...0x1107f => true,
+ else => false,
+ };
+}
+
+pub fn isKaithi(cp: u21) bool {
+ if (cp < 0x11080 or cp > 0x110cf) return false;
+
+ return switch (cp) {
+ 0x11080...0x110cf => true,
+ else => false,
+ };
+}
+
+pub fn isSoraSompeng(cp: u21) bool {
+ if (cp < 0x110d0 or cp > 0x110ff) return false;
+
+ return switch (cp) {
+ 0x110d0...0x110ff => true,
+ else => false,
+ };
+}
+
+pub fn isChakma(cp: u21) bool {
+ if (cp < 0x11100 or cp > 0x1114f) return false;
+
+ return switch (cp) {
+ 0x11100...0x1114f => true,
+ else => false,
+ };
+}
+
+pub fn isMahajani(cp: u21) bool {
+ if (cp < 0x11150 or cp > 0x1117f) return false;
+
+ return switch (cp) {
+ 0x11150...0x1117f => true,
+ else => false,
+ };
+}
+
+pub fn isSharada(cp: u21) bool {
+ if (cp < 0x11180 or cp > 0x111df) return false;
+
+ return switch (cp) {
+ 0x11180...0x111df => true,
+ else => false,
+ };
+}
+
+pub fn isSinhalaArchaicNumbers(cp: u21) bool {
+ if (cp < 0x111e0 or cp > 0x111ff) return false;
+
+ return switch (cp) {
+ 0x111e0...0x111ff => true,
+ else => false,
+ };
+}
+
+pub fn isKhojki(cp: u21) bool {
+ if (cp < 0x11200 or cp > 0x1124f) return false;
+
+ return switch (cp) {
+ 0x11200...0x1124f => true,
+ else => false,
+ };
+}
+
+pub fn isMultani(cp: u21) bool {
+ if (cp < 0x11280 or cp > 0x112af) return false;
+
+ return switch (cp) {
+ 0x11280...0x112af => true,
+ else => false,
+ };
+}
+
+pub fn isKhudawadi(cp: u21) bool {
+ if (cp < 0x112b0 or cp > 0x112ff) return false;
+
+ return switch (cp) {
+ 0x112b0...0x112ff => true,
+ else => false,
+ };
+}
+
+pub fn isGrantha(cp: u21) bool {
+ if (cp < 0x11300 or cp > 0x1137f) return false;
+
+ return switch (cp) {
+ 0x11300...0x1137f => true,
+ else => false,
+ };
+}
+
+pub fn isNewa(cp: u21) bool {
+ if (cp < 0x11400 or cp > 0x1147f) return false;
+
+ return switch (cp) {
+ 0x11400...0x1147f => true,
+ else => false,
+ };
+}
+
+pub fn isTirhuta(cp: u21) bool {
+ if (cp < 0x11480 or cp > 0x114df) return false;
+
+ return switch (cp) {
+ 0x11480...0x114df => true,
+ else => false,
+ };
+}
+
+pub fn isSiddham(cp: u21) bool {
+ if (cp < 0x11580 or cp > 0x115ff) return false;
+
+ return switch (cp) {
+ 0x11580...0x115ff => true,
+ else => false,
+ };
+}
+
+pub fn isModi(cp: u21) bool {
+ if (cp < 0x11600 or cp > 0x1165f) return false;
+
+ return switch (cp) {
+ 0x11600...0x1165f => true,
+ else => false,
+ };
+}
+
+pub fn isMongolianSupplement(cp: u21) bool {
+ if (cp < 0x11660 or cp > 0x1167f) return false;
+
+ return switch (cp) {
+ 0x11660...0x1167f => true,
+ else => false,
+ };
+}
+
+pub fn isTakri(cp: u21) bool {
+ if (cp < 0x11680 or cp > 0x116cf) return false;
+
+ return switch (cp) {
+ 0x11680...0x116cf => true,
+ else => false,
+ };
+}
+
+pub fn isAhom(cp: u21) bool {
+ if (cp < 0x11700 or cp > 0x1174f) return false;
+
+ return switch (cp) {
+ 0x11700...0x1174f => true,
+ else => false,
+ };
+}
+
+pub fn isDogra(cp: u21) bool {
+ if (cp < 0x11800 or cp > 0x1184f) return false;
+
+ return switch (cp) {
+ 0x11800...0x1184f => true,
+ else => false,
+ };
+}
+
+pub fn isWarangCiti(cp: u21) bool {
+ if (cp < 0x118a0 or cp > 0x118ff) return false;
+
+ return switch (cp) {
+ 0x118a0...0x118ff => true,
+ else => false,
+ };
+}
+
+pub fn isDivesAkuru(cp: u21) bool {
+ if (cp < 0x11900 or cp > 0x1195f) return false;
+
+ return switch (cp) {
+ 0x11900...0x1195f => true,
+ else => false,
+ };
+}
+
+pub fn isNandinagari(cp: u21) bool {
+ if (cp < 0x119a0 or cp > 0x119ff) return false;
+
+ return switch (cp) {
+ 0x119a0...0x119ff => true,
+ else => false,
+ };
+}
+
+pub fn isZanabazarSquare(cp: u21) bool {
+ if (cp < 0x11a00 or cp > 0x11a4f) return false;
+
+ return switch (cp) {
+ 0x11a00...0x11a4f => true,
+ else => false,
+ };
+}
+
+pub fn isSoyombo(cp: u21) bool {
+ if (cp < 0x11a50 or cp > 0x11aaf) return false;
+
+ return switch (cp) {
+ 0x11a50...0x11aaf => true,
+ else => false,
+ };
+}
+
+pub fn isUnifiedCanadianAboriginalSyllabicsExtendedA(cp: u21) bool {
+ if (cp < 0x11ab0 or cp > 0x11abf) return false;
+
+ return switch (cp) {
+ 0x11ab0...0x11abf => true,
+ else => false,
+ };
+}
+
+pub fn isPauCinHau(cp: u21) bool {
+ if (cp < 0x11ac0 or cp > 0x11aff) return false;
+
+ return switch (cp) {
+ 0x11ac0...0x11aff => true,
+ else => false,
+ };
+}
+
+pub fn isDevanagariExtendedA(cp: u21) bool {
+ if (cp < 0x11b00 or cp > 0x11b5f) return false;
+
+ return switch (cp) {
+ 0x11b00...0x11b5f => true,
+ else => false,
+ };
+}
+
+pub fn isBhaiksuki(cp: u21) bool {
+ if (cp < 0x11c00 or cp > 0x11c6f) return false;
+
+ return switch (cp) {
+ 0x11c00...0x11c6f => true,
+ else => false,
+ };
+}
+
+pub fn isMarchen(cp: u21) bool {
+ if (cp < 0x11c70 or cp > 0x11cbf) return false;
+
+ return switch (cp) {
+ 0x11c70...0x11cbf => true,
+ else => false,
+ };
+}
+
+pub fn isMasaramGondi(cp: u21) bool {
+ if (cp < 0x11d00 or cp > 0x11d5f) return false;
+
+ return switch (cp) {
+ 0x11d00...0x11d5f => true,
+ else => false,
+ };
+}
+
+pub fn isGunjalaGondi(cp: u21) bool {
+ if (cp < 0x11d60 or cp > 0x11daf) return false;
+
+ return switch (cp) {
+ 0x11d60...0x11daf => true,
+ else => false,
+ };
+}
+
+pub fn isMakasar(cp: u21) bool {
+ if (cp < 0x11ee0 or cp > 0x11eff) return false;
+
+ return switch (cp) {
+ 0x11ee0...0x11eff => true,
+ else => false,
+ };
+}
+
+pub fn isKawi(cp: u21) bool {
+ if (cp < 0x11f00 or cp > 0x11f5f) return false;
+
+ return switch (cp) {
+ 0x11f00...0x11f5f => true,
+ else => false,
+ };
+}
+
+pub fn isLisuSupplement(cp: u21) bool {
+ if (cp < 0x11fb0 or cp > 0x11fbf) return false;
+
+ return switch (cp) {
+ 0x11fb0...0x11fbf => true,
+ else => false,
+ };
+}
+
+pub fn isTamilSupplement(cp: u21) bool {
+ if (cp < 0x11fc0 or cp > 0x11fff) return false;
+
+ return switch (cp) {
+ 0x11fc0...0x11fff => true,
+ else => false,
+ };
+}
+
+pub fn isCuneiform(cp: u21) bool {
+ if (cp < 0x12000 or cp > 0x123ff) return false;
+
+ return switch (cp) {
+ 0x12000...0x123ff => true,
+ else => false,
+ };
+}
+
+pub fn isCuneiformNumbersAndPunctuation(cp: u21) bool {
+ if (cp < 0x12400 or cp > 0x1247f) return false;
+
+ return switch (cp) {
+ 0x12400...0x1247f => true,
+ else => false,
+ };
+}
+
+pub fn isEarlyDynasticCuneiform(cp: u21) bool {
+ if (cp < 0x12480 or cp > 0x1254f) return false;
+
+ return switch (cp) {
+ 0x12480...0x1254f => true,
+ else => false,
+ };
+}
+
+pub fn isCyproMinoan(cp: u21) bool {
+ if (cp < 0x12f90 or cp > 0x12fff) return false;
+
+ return switch (cp) {
+ 0x12f90...0x12fff => true,
+ else => false,
+ };
+}
+
+pub fn isEgyptianHieroglyphs(cp: u21) bool {
+ if (cp < 0x13000 or cp > 0x1342f) return false;
+
+ return switch (cp) {
+ 0x13000...0x1342f => true,
+ else => false,
+ };
+}
+
+pub fn isEgyptianHieroglyphFormatControls(cp: u21) bool {
+ if (cp < 0x13430 or cp > 0x1345f) return false;
+
+ return switch (cp) {
+ 0x13430...0x1345f => true,
+ else => false,
+ };
+}
+
+pub fn isAnatolianHieroglyphs(cp: u21) bool {
+ if (cp < 0x14400 or cp > 0x1467f) return false;
+
+ return switch (cp) {
+ 0x14400...0x1467f => true,
+ else => false,
+ };
+}
+
+pub fn isBamumSupplement(cp: u21) bool {
+ if (cp < 0x16800 or cp > 0x16a3f) return false;
+
+ return switch (cp) {
+ 0x16800...0x16a3f => true,
+ else => false,
+ };
+}
+
+pub fn isMro(cp: u21) bool {
+ if (cp < 0x16a40 or cp > 0x16a6f) return false;
+
+ return switch (cp) {
+ 0x16a40...0x16a6f => true,
+ else => false,
+ };
+}
+
+pub fn isTangsa(cp: u21) bool {
+ if (cp < 0x16a70 or cp > 0x16acf) return false;
+
+ return switch (cp) {
+ 0x16a70...0x16acf => true,
+ else => false,
+ };
+}
+
+pub fn isBassaVah(cp: u21) bool {
+ if (cp < 0x16ad0 or cp > 0x16aff) return false;
+
+ return switch (cp) {
+ 0x16ad0...0x16aff => true,
+ else => false,
+ };
+}
+
+pub fn isPahawhHmong(cp: u21) bool {
+ if (cp < 0x16b00 or cp > 0x16b8f) return false;
+
+ return switch (cp) {
+ 0x16b00...0x16b8f => true,
+ else => false,
+ };
+}
+
+pub fn isMedefaidrin(cp: u21) bool {
+ if (cp < 0x16e40 or cp > 0x16e9f) return false;
+
+ return switch (cp) {
+ 0x16e40...0x16e9f => true,
+ else => false,
+ };
+}
+
+pub fn isMiao(cp: u21) bool {
+ if (cp < 0x16f00 or cp > 0x16f9f) return false;
+
+ return switch (cp) {
+ 0x16f00...0x16f9f => true,
+ else => false,
+ };
+}
+
+pub fn isIdeographicSymbolsAndPunctuation(cp: u21) bool {
+ if (cp < 0x16fe0 or cp > 0x16fff) return false;
+
+ return switch (cp) {
+ 0x16fe0...0x16fff => true,
+ else => false,
+ };
+}
+
+pub fn isTangut(cp: u21) bool {
+ if (cp < 0x17000 or cp > 0x187ff) return false;
+
+ return switch (cp) {
+ 0x17000...0x187ff => true,
+ else => false,
+ };
+}
+
+pub fn isTangutComponents(cp: u21) bool {
+ if (cp < 0x18800 or cp > 0x18aff) return false;
+
+ return switch (cp) {
+ 0x18800...0x18aff => true,
+ else => false,
+ };
+}
+
+pub fn isKhitanSmallScript(cp: u21) bool {
+ if (cp < 0x18b00 or cp > 0x18cff) return false;
+
+ return switch (cp) {
+ 0x18b00...0x18cff => true,
+ else => false,
+ };
+}
+
+pub fn isTangutSupplement(cp: u21) bool {
+ if (cp < 0x18d00 or cp > 0x18d7f) return false;
+
+ return switch (cp) {
+ 0x18d00...0x18d7f => true,
+ else => false,
+ };
+}
+
+pub fn isKanaExtendedB(cp: u21) bool {
+ if (cp < 0x1aff0 or cp > 0x1afff) return false;
+
+ return switch (cp) {
+ 0x1aff0...0x1afff => true,
+ else => false,
+ };
+}
+
+pub fn isKanaSupplement(cp: u21) bool {
+ if (cp < 0x1b000 or cp > 0x1b0ff) return false;
+
+ return switch (cp) {
+ 0x1b000...0x1b0ff => true,
+ else => false,
+ };
+}
+
+pub fn isKanaExtendedA(cp: u21) bool {
+ if (cp < 0x1b100 or cp > 0x1b12f) return false;
+
+ return switch (cp) {
+ 0x1b100...0x1b12f => true,
+ else => false,
+ };
+}
+
+pub fn isSmallKanaExtension(cp: u21) bool {
+ if (cp < 0x1b130 or cp > 0x1b16f) return false;
+
+ return switch (cp) {
+ 0x1b130...0x1b16f => true,
+ else => false,
+ };
+}
+
+pub fn isNushu(cp: u21) bool {
+ if (cp < 0x1b170 or cp > 0x1b2ff) return false;
+
+ return switch (cp) {
+ 0x1b170...0x1b2ff => true,
+ else => false,
+ };
+}
+
+pub fn isDuployan(cp: u21) bool {
+ if (cp < 0x1bc00 or cp > 0x1bc9f) return false;
+
+ return switch (cp) {
+ 0x1bc00...0x1bc9f => true,
+ else => false,
+ };
+}
+
+pub fn isShorthandFormatControls(cp: u21) bool {
+ if (cp < 0x1bca0 or cp > 0x1bcaf) return false;
+
+ return switch (cp) {
+ 0x1bca0...0x1bcaf => true,
+ else => false,
+ };
+}
+
+pub fn isZnamennyMusicalNotation(cp: u21) bool {
+ if (cp < 0x1cf00 or cp > 0x1cfcf) return false;
+
+ return switch (cp) {
+ 0x1cf00...0x1cfcf => true,
+ else => false,
+ };
+}
+
+pub fn isByzantineMusicalSymbols(cp: u21) bool {
+ if (cp < 0x1d000 or cp > 0x1d0ff) return false;
+
+ return switch (cp) {
+ 0x1d000...0x1d0ff => true,
+ else => false,
+ };
+}
+
+pub fn isMusicalSymbols(cp: u21) bool {
+ if (cp < 0x1d100 or cp > 0x1d1ff) return false;
+
+ return switch (cp) {
+ 0x1d100...0x1d1ff => true,
+ else => false,
+ };
+}
+
+pub fn isAncientGreekMusicalNotation(cp: u21) bool {
+ if (cp < 0x1d200 or cp > 0x1d24f) return false;
+
+ return switch (cp) {
+ 0x1d200...0x1d24f => true,
+ else => false,
+ };
+}
+
+pub fn isKaktovikNumerals(cp: u21) bool {
+ if (cp < 0x1d2c0 or cp > 0x1d2df) return false;
+
+ return switch (cp) {
+ 0x1d2c0...0x1d2df => true,
+ else => false,
+ };
+}
+
+pub fn isMayanNumerals(cp: u21) bool {
+ if (cp < 0x1d2e0 or cp > 0x1d2ff) return false;
+
+ return switch (cp) {
+ 0x1d2e0...0x1d2ff => true,
+ else => false,
+ };
+}
+
+pub fn isTaiXuanJingSymbols(cp: u21) bool {
+ if (cp < 0x1d300 or cp > 0x1d35f) return false;
+
+ return switch (cp) {
+ 0x1d300...0x1d35f => true,
+ else => false,
+ };
+}
+
+pub fn isCountingRodNumerals(cp: u21) bool {
+ if (cp < 0x1d360 or cp > 0x1d37f) return false;
+
+ return switch (cp) {
+ 0x1d360...0x1d37f => true,
+ else => false,
+ };
+}
+
+pub fn isMathematicalAlphanumericSymbols(cp: u21) bool {
+ if (cp < 0x1d400 or cp > 0x1d7ff) return false;
+
+ return switch (cp) {
+ 0x1d400...0x1d7ff => true,
+ else => false,
+ };
+}
+
+pub fn isSuttonSignwriting(cp: u21) bool {
+ if (cp < 0x1d800 or cp > 0x1daaf) return false;
+
+ return switch (cp) {
+ 0x1d800...0x1daaf => true,
+ else => false,
+ };
+}
+
+pub fn isLatinExtendedG(cp: u21) bool {
+ if (cp < 0x1df00 or cp > 0x1dfff) return false;
+
+ return switch (cp) {
+ 0x1df00...0x1dfff => true,
+ else => false,
+ };
+}
+
+pub fn isGlagoliticSupplement(cp: u21) bool {
+ if (cp < 0x1e000 or cp > 0x1e02f) return false;
+
+ return switch (cp) {
+ 0x1e000...0x1e02f => true,
+ else => false,
+ };
+}
+
+pub fn isCyrillicExtendedD(cp: u21) bool {
+ if (cp < 0x1e030 or cp > 0x1e08f) return false;
+
+ return switch (cp) {
+ 0x1e030...0x1e08f => true,
+ else => false,
+ };
+}
+
+pub fn isNyiakengPuachueHmong(cp: u21) bool {
+ if (cp < 0x1e100 or cp > 0x1e14f) return false;
+
+ return switch (cp) {
+ 0x1e100...0x1e14f => true,
+ else => false,
+ };
+}
+
+pub fn isToto(cp: u21) bool {
+ if (cp < 0x1e290 or cp > 0x1e2bf) return false;
+
+ return switch (cp) {
+ 0x1e290...0x1e2bf => true,
+ else => false,
+ };
+}
+
+pub fn isWancho(cp: u21) bool {
+ if (cp < 0x1e2c0 or cp > 0x1e2ff) return false;
+
+ return switch (cp) {
+ 0x1e2c0...0x1e2ff => true,
+ else => false,
+ };
+}
+
+pub fn isNagMundari(cp: u21) bool {
+ if (cp < 0x1e4d0 or cp > 0x1e4ff) return false;
+
+ return switch (cp) {
+ 0x1e4d0...0x1e4ff => true,
+ else => false,
+ };
+}
+
+pub fn isEthiopicExtendedB(cp: u21) bool {
+ if (cp < 0x1e7e0 or cp > 0x1e7ff) return false;
+
+ return switch (cp) {
+ 0x1e7e0...0x1e7ff => true,
+ else => false,
+ };
+}
+
+pub fn isMendeKikakui(cp: u21) bool {
+ if (cp < 0x1e800 or cp > 0x1e8df) return false;
+
+ return switch (cp) {
+ 0x1e800...0x1e8df => true,
+ else => false,
+ };
+}
+
+pub fn isAdlam(cp: u21) bool {
+ if (cp < 0x1e900 or cp > 0x1e95f) return false;
+
+ return switch (cp) {
+ 0x1e900...0x1e95f => true,
+ else => false,
+ };
+}
+
+pub fn isIndicSiyaqNumbers(cp: u21) bool {
+ if (cp < 0x1ec70 or cp > 0x1ecbf) return false;
+
+ return switch (cp) {
+ 0x1ec70...0x1ecbf => true,
+ else => false,
+ };
+}
+
+pub fn isOttomanSiyaqNumbers(cp: u21) bool {
+ if (cp < 0x1ed00 or cp > 0x1ed4f) return false;
+
+ return switch (cp) {
+ 0x1ed00...0x1ed4f => true,
+ else => false,
+ };
+}
+
+pub fn isArabicMathematicalAlphabeticSymbols(cp: u21) bool {
+ if (cp < 0x1ee00 or cp > 0x1eeff) return false;
+
+ return switch (cp) {
+ 0x1ee00...0x1eeff => true,
+ else => false,
+ };
+}
+
+pub fn isMahjongTiles(cp: u21) bool {
+ if (cp < 0x1f000 or cp > 0x1f02f) return false;
+
+ return switch (cp) {
+ 0x1f000...0x1f02f => true,
+ else => false,
+ };
+}
+
+pub fn isDominoTiles(cp: u21) bool {
+ if (cp < 0x1f030 or cp > 0x1f09f) return false;
+
+ return switch (cp) {
+ 0x1f030...0x1f09f => true,
+ else => false,
+ };
+}
+
+pub fn isPlayingCards(cp: u21) bool {
+ if (cp < 0x1f0a0 or cp > 0x1f0ff) return false;
+
+ return switch (cp) {
+ 0x1f0a0...0x1f0ff => true,
+ else => false,
+ };
+}
+
+pub fn isEnclosedAlphanumericSupplement(cp: u21) bool {
+ if (cp < 0x1f100 or cp > 0x1f1ff) return false;
+
+ return switch (cp) {
+ 0x1f100...0x1f1ff => true,
+ else => false,
+ };
+}
+
+pub fn isEnclosedIdeographicSupplement(cp: u21) bool {
+ if (cp < 0x1f200 or cp > 0x1f2ff) return false;
+
+ return switch (cp) {
+ 0x1f200...0x1f2ff => true,
+ else => false,
+ };
+}
+
+pub fn isMiscellaneousSymbolsAndPictographs(cp: u21) bool {
+ if (cp < 0x1f300 or cp > 0x1f5ff) return false;
+
+ return switch (cp) {
+ 0x1f300...0x1f5ff => true,
+ else => false,
+ };
+}
+
+pub fn isEmoticons(cp: u21) bool {
+ if (cp < 0x1f600 or cp > 0x1f64f) return false;
+
+ return switch (cp) {
+ 0x1f600...0x1f64f => true,
+ else => false,
+ };
+}
+
+pub fn isOrnamentalDingbats(cp: u21) bool {
+ if (cp < 0x1f650 or cp > 0x1f67f) return false;
+
+ return switch (cp) {
+ 0x1f650...0x1f67f => true,
+ else => false,
+ };
+}
+
+pub fn isTransportAndMapSymbols(cp: u21) bool {
+ if (cp < 0x1f680 or cp > 0x1f6ff) return false;
+
+ return switch (cp) {
+ 0x1f680...0x1f6ff => true,
+ else => false,
+ };
+}
+
+pub fn isAlchemicalSymbols(cp: u21) bool {
+ if (cp < 0x1f700 or cp > 0x1f77f) return false;
+
+ return switch (cp) {
+ 0x1f700...0x1f77f => true,
+ else => false,
+ };
+}
+
+pub fn isGeometricShapesExtended(cp: u21) bool {
+ if (cp < 0x1f780 or cp > 0x1f7ff) return false;
+
+ return switch (cp) {
+ 0x1f780...0x1f7ff => true,
+ else => false,
+ };
+}
+
+pub fn isSupplementalArrowsC(cp: u21) bool {
+ if (cp < 0x1f800 or cp > 0x1f8ff) return false;
+
+ return switch (cp) {
+ 0x1f800...0x1f8ff => true,
+ else => false,
+ };
+}
+
+pub fn isSupplementalSymbolsAndPictographs(cp: u21) bool {
+ if (cp < 0x1f900 or cp > 0x1f9ff) return false;
+
+ return switch (cp) {
+ 0x1f900...0x1f9ff => true,
+ else => false,
+ };
+}
+
+pub fn isChessSymbols(cp: u21) bool {
+ if (cp < 0x1fa00 or cp > 0x1fa6f) return false;
+
+ return switch (cp) {
+ 0x1fa00...0x1fa6f => true,
+ else => false,
+ };
+}
+
+pub fn isSymbolsAndPictographsExtendedA(cp: u21) bool {
+ if (cp < 0x1fa70 or cp > 0x1faff) return false;
+
+ return switch (cp) {
+ 0x1fa70...0x1faff => true,
+ else => false,
+ };
+}
+
+pub fn isSymbolsForLegacyComputing(cp: u21) bool {
+ if (cp < 0x1fb00 or cp > 0x1fbff) return false;
+
+ return switch (cp) {
+ 0x1fb00...0x1fbff => true,
+ else => false,
+ };
+}
+
+pub fn isCjkUnifiedIdeographsExtensionB(cp: u21) bool {
+ if (cp < 0x20000 or cp > 0x2a6df) return false;
+
+ return switch (cp) {
+ 0x20000...0x2a6df => true,
+ else => false,
+ };
+}
+
+pub fn isCjkUnifiedIdeographsExtensionC(cp: u21) bool {
+ if (cp < 0x2a700 or cp > 0x2b73f) return false;
+
+ return switch (cp) {
+ 0x2a700...0x2b73f => true,
+ else => false,
+ };
+}
+
+pub fn isCjkUnifiedIdeographsExtensionD(cp: u21) bool {
+ if (cp < 0x2b740 or cp > 0x2b81f) return false;
+
+ return switch (cp) {
+ 0x2b740...0x2b81f => true,
+ else => false,
+ };
+}
+
+pub fn isCjkUnifiedIdeographsExtensionE(cp: u21) bool {
+ if (cp < 0x2b820 or cp > 0x2ceaf) return false;
+
+ return switch (cp) {
+ 0x2b820...0x2ceaf => true,
+ else => false,
+ };
+}
+
+pub fn isCjkUnifiedIdeographsExtensionF(cp: u21) bool {
+ if (cp < 0x2ceb0 or cp > 0x2ebef) return false;
+
+ return switch (cp) {
+ 0x2ceb0...0x2ebef => true,
+ else => false,
+ };
+}
+
+pub fn isCjkCompatibilityIdeographsSupplement(cp: u21) bool {
+ if (cp < 0x2f800 or cp > 0x2fa1f) return false;
+
+ return switch (cp) {
+ 0x2f800...0x2fa1f => true,
+ else => false,
+ };
+}
+
+pub fn isCjkUnifiedIdeographsExtensionG(cp: u21) bool {
+ if (cp < 0x30000 or cp > 0x3134f) return false;
+
+ return switch (cp) {
+ 0x30000...0x3134f => true,
+ else => false,
+ };
+}
+
+pub fn isCjkUnifiedIdeographsExtensionH(cp: u21) bool {
+ if (cp < 0x31350 or cp > 0x323af) return false;
+
+ return switch (cp) {
+ 0x31350...0x323af => true,
+ else => false,
+ };
+}
+
+pub fn isTags(cp: u21) bool {
+ if (cp < 0xe0000 or cp > 0xe007f) return false;
+
+ return switch (cp) {
+ 0xe0000...0xe007f => true,
+ else => false,
+ };
+}
+
+pub fn isVariationSelectorsSupplement(cp: u21) bool {
+ if (cp < 0xe0100 or cp > 0xe01ef) return false;
+
+ return switch (cp) {
+ 0xe0100...0xe01ef => true,
+ else => false,
+ };
+}
+
+pub fn isSupplementaryPrivateUseAreaA(cp: u21) bool {
+ if (cp < 0xf0000 or cp > 0xfffff) return false;
+
+ return switch (cp) {
+ 0xf0000...0xfffff => true,
+ else => false,
+ };
+}
+
+pub fn isSupplementaryPrivateUseAreaB(cp: u21) bool {
+ if (cp < 0x100000 or cp > 0x10ffff) return false;
+
+ return switch (cp) {
+ 0x100000...0x10ffff => true,
+ else => false,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/case_folding.zig.html b/docs/src/ziglyph/autogen/case_folding.zig.html
new file mode 100644
index 0000000..d2f44ae
--- /dev/null
+++ b/docs/src/ziglyph/autogen/case_folding.zig.html
@@ -0,0 +1,1697 @@
+
+
+
+
+
autogen/case_folding.zig - source view
+
+
+
+
+
+
+
+
+const std = @import("std");
+const unicode = std.unicode;
+
+const CodePointIterator = @import("../segmenter/CodePoint.zig").CodePointIterator;
+
+
+
+pub fn caseFoldStr(allocator: std.mem.Allocator, str: []const u8) ![]u8 {
+ var result = std.ArrayList(u8).init(allocator);
+ defer result.deinit();
+ var code_points = std.ArrayList(u21).init(allocator);
+ defer code_points.deinit();
+
+
+
+ var iter = CodePointIterator{ .bytes = str };
+ while (iter.next()) |cp| {
+ for (toCaseFold(cp.code)) |fcp| {
+ if (fcp == 0) break;
+ try code_points.append(fcp);
+ }
+ }
+
+
+
+ var buf: [4]u8 = undefined;
+ for (code_points.items) |dcp| {
+ const len = try unicode.utf8Encode(dcp, &buf);
+ try result.appendSlice(buf[0..len]);
+ }
+
+ return try result.toOwnedSlice();
+}
+
+
+
+
+pub fn toCaseFold(cp: u21) [3]u21 {
+ const slice: []const u21 = switch (cp) {
+ 0x41 => &.{0x61},
+ 0x42 => &.{0x62},
+ 0x43 => &.{0x63},
+ 0x44 => &.{0x64},
+ 0x45 => &.{0x65},
+ 0x46 => &.{0x66},
+ 0x47 => &.{0x67},
+ 0x48 => &.{0x68},
+ 0x49 => &.{0x69},
+ 0x4A => &.{0x6A},
+ 0x4B => &.{0x6B},
+ 0x4C => &.{0x6C},
+ 0x4D => &.{0x6D},
+ 0x4E => &.{0x6E},
+ 0x4F => &.{0x6F},
+ 0x50 => &.{0x70},
+ 0x51 => &.{0x71},
+ 0x52 => &.{0x72},
+ 0x53 => &.{0x73},
+ 0x54 => &.{0x74},
+ 0x55 => &.{0x75},
+ 0x56 => &.{0x76},
+ 0x57 => &.{0x77},
+ 0x58 => &.{0x78},
+ 0x59 => &.{0x79},
+ 0x5A => &.{0x7A},
+ 0xB5 => &.{0x3BC},
+ 0xC0 => &.{0xE0},
+ 0xC1 => &.{0xE1},
+ 0xC2 => &.{0xE2},
+ 0xC3 => &.{0xE3},
+ 0xC4 => &.{0xE4},
+ 0xC5 => &.{0xE5},
+ 0xC6 => &.{0xE6},
+ 0xC7 => &.{0xE7},
+ 0xC8 => &.{0xE8},
+ 0xC9 => &.{0xE9},
+ 0xCA => &.{0xEA},
+ 0xCB => &.{0xEB},
+ 0xCC => &.{0xEC},
+ 0xCD => &.{0xED},
+ 0xCE => &.{0xEE},
+ 0xCF => &.{0xEF},
+ 0xD0 => &.{0xF0},
+ 0xD1 => &.{0xF1},
+ 0xD2 => &.{0xF2},
+ 0xD3 => &.{0xF3},
+ 0xD4 => &.{0xF4},
+ 0xD5 => &.{0xF5},
+ 0xD6 => &.{0xF6},
+ 0xD8 => &.{0xF8},
+ 0xD9 => &.{0xF9},
+ 0xDA => &.{0xFA},
+ 0xDB => &.{0xFB},
+ 0xDC => &.{0xFC},
+ 0xDD => &.{0xFD},
+ 0xDE => &.{0xFE},
+ 0xDF => &.{ 0x73, 0x73 },
+ 0x100 => &.{0x101},
+ 0x102 => &.{0x103},
+ 0x104 => &.{0x105},
+ 0x106 => &.{0x107},
+ 0x108 => &.{0x109},
+ 0x10A => &.{0x10B},
+ 0x10C => &.{0x10D},
+ 0x10E => &.{0x10F},
+ 0x110 => &.{0x111},
+ 0x112 => &.{0x113},
+ 0x114 => &.{0x115},
+ 0x116 => &.{0x117},
+ 0x118 => &.{0x119},
+ 0x11A => &.{0x11B},
+ 0x11C => &.{0x11D},
+ 0x11E => &.{0x11F},
+ 0x120 => &.{0x121},
+ 0x122 => &.{0x123},
+ 0x124 => &.{0x125},
+ 0x126 => &.{0x127},
+ 0x128 => &.{0x129},
+ 0x12A => &.{0x12B},
+ 0x12C => &.{0x12D},
+ 0x12E => &.{0x12F},
+ 0x130 => &.{ 0x69, 0x307 },
+ 0x132 => &.{0x133},
+ 0x134 => &.{0x135},
+ 0x136 => &.{0x137},
+ 0x139 => &.{0x13A},
+ 0x13B => &.{0x13C},
+ 0x13D => &.{0x13E},
+ 0x13F => &.{0x140},
+ 0x141 => &.{0x142},
+ 0x143 => &.{0x144},
+ 0x145 => &.{0x146},
+ 0x147 => &.{0x148},
+ 0x149 => &.{ 0x2BC, 0x6E },
+ 0x14A => &.{0x14B},
+ 0x14C => &.{0x14D},
+ 0x14E => &.{0x14F},
+ 0x150 => &.{0x151},
+ 0x152 => &.{0x153},
+ 0x154 => &.{0x155},
+ 0x156 => &.{0x157},
+ 0x158 => &.{0x159},
+ 0x15A => &.{0x15B},
+ 0x15C => &.{0x15D},
+ 0x15E => &.{0x15F},
+ 0x160 => &.{0x161},
+ 0x162 => &.{0x163},
+ 0x164 => &.{0x165},
+ 0x166 => &.{0x167},
+ 0x168 => &.{0x169},
+ 0x16A => &.{0x16B},
+ 0x16C => &.{0x16D},
+ 0x16E => &.{0x16F},
+ 0x170 => &.{0x171},
+ 0x172 => &.{0x173},
+ 0x174 => &.{0x175},
+ 0x176 => &.{0x177},
+ 0x178 => &.{0xFF},
+ 0x179 => &.{0x17A},
+ 0x17B => &.{0x17C},
+ 0x17D => &.{0x17E},
+ 0x17F => &.{0x73},
+ 0x181 => &.{0x253},
+ 0x182 => &.{0x183},
+ 0x184 => &.{0x185},
+ 0x186 => &.{0x254},
+ 0x187 => &.{0x188},
+ 0x189 => &.{0x256},
+ 0x18A => &.{0x257},
+ 0x18B => &.{0x18C},
+ 0x18E => &.{0x1DD},
+ 0x18F => &.{0x259},
+ 0x190 => &.{0x25B},
+ 0x191 => &.{0x192},
+ 0x193 => &.{0x260},
+ 0x194 => &.{0x263},
+ 0x196 => &.{0x269},
+ 0x197 => &.{0x268},
+ 0x198 => &.{0x199},
+ 0x19C => &.{0x26F},
+ 0x19D => &.{0x272},
+ 0x19F => &.{0x275},
+ 0x1A0 => &.{0x1A1},
+ 0x1A2 => &.{0x1A3},
+ 0x1A4 => &.{0x1A5},
+ 0x1A6 => &.{0x280},
+ 0x1A7 => &.{0x1A8},
+ 0x1A9 => &.{0x283},
+ 0x1AC => &.{0x1AD},
+ 0x1AE => &.{0x288},
+ 0x1AF => &.{0x1B0},
+ 0x1B1 => &.{0x28A},
+ 0x1B2 => &.{0x28B},
+ 0x1B3 => &.{0x1B4},
+ 0x1B5 => &.{0x1B6},
+ 0x1B7 => &.{0x292},
+ 0x1B8 => &.{0x1B9},
+ 0x1BC => &.{0x1BD},
+ 0x1C4 => &.{0x1C6},
+ 0x1C5 => &.{0x1C6},
+ 0x1C7 => &.{0x1C9},
+ 0x1C8 => &.{0x1C9},
+ 0x1CA => &.{0x1CC},
+ 0x1CB => &.{0x1CC},
+ 0x1CD => &.{0x1CE},
+ 0x1CF => &.{0x1D0},
+ 0x1D1 => &.{0x1D2},
+ 0x1D3 => &.{0x1D4},
+ 0x1D5 => &.{0x1D6},
+ 0x1D7 => &.{0x1D8},
+ 0x1D9 => &.{0x1DA},
+ 0x1DB => &.{0x1DC},
+ 0x1DE => &.{0x1DF},
+ 0x1E0 => &.{0x1E1},
+ 0x1E2 => &.{0x1E3},
+ 0x1E4 => &.{0x1E5},
+ 0x1E6 => &.{0x1E7},
+ 0x1E8 => &.{0x1E9},
+ 0x1EA => &.{0x1EB},
+ 0x1EC => &.{0x1ED},
+ 0x1EE => &.{0x1EF},
+ 0x1F0 => &.{ 0x6A, 0x30C },
+ 0x1F1 => &.{0x1F3},
+ 0x1F2 => &.{0x1F3},
+ 0x1F4 => &.{0x1F5},
+ 0x1F6 => &.{0x195},
+ 0x1F7 => &.{0x1BF},
+ 0x1F8 => &.{0x1F9},
+ 0x1FA => &.{0x1FB},
+ 0x1FC => &.{0x1FD},
+ 0x1FE => &.{0x1FF},
+ 0x200 => &.{0x201},
+ 0x202 => &.{0x203},
+ 0x204 => &.{0x205},
+ 0x206 => &.{0x207},
+ 0x208 => &.{0x209},
+ 0x20A => &.{0x20B},
+ 0x20C => &.{0x20D},
+ 0x20E => &.{0x20F},
+ 0x210 => &.{0x211},
+ 0x212 => &.{0x213},
+ 0x214 => &.{0x215},
+ 0x216 => &.{0x217},
+ 0x218 => &.{0x219},
+ 0x21A => &.{0x21B},
+ 0x21C => &.{0x21D},
+ 0x21E => &.{0x21F},
+ 0x220 => &.{0x19E},
+ 0x222 => &.{0x223},
+ 0x224 => &.{0x225},
+ 0x226 => &.{0x227},
+ 0x228 => &.{0x229},
+ 0x22A => &.{0x22B},
+ 0x22C => &.{0x22D},
+ 0x22E => &.{0x22F},
+ 0x230 => &.{0x231},
+ 0x232 => &.{0x233},
+ 0x23A => &.{0x2C65},
+ 0x23B => &.{0x23C},
+ 0x23D => &.{0x19A},
+ 0x23E => &.{0x2C66},
+ 0x241 => &.{0x242},
+ 0x243 => &.{0x180},
+ 0x244 => &.{0x289},
+ 0x245 => &.{0x28C},
+ 0x246 => &.{0x247},
+ 0x248 => &.{0x249},
+ 0x24A => &.{0x24B},
+ 0x24C => &.{0x24D},
+ 0x24E => &.{0x24F},
+ 0x345 => &.{0x3B9},
+ 0x370 => &.{0x371},
+ 0x372 => &.{0x373},
+ 0x376 => &.{0x377},
+ 0x37F => &.{0x3F3},
+ 0x386 => &.{0x3AC},
+ 0x388 => &.{0x3AD},
+ 0x389 => &.{0x3AE},
+ 0x38A => &.{0x3AF},
+ 0x38C => &.{0x3CC},
+ 0x38E => &.{0x3CD},
+ 0x38F => &.{0x3CE},
+ 0x390 => &.{ 0x3B9, 0x308, 0x301 },
+ 0x391 => &.{0x3B1},
+ 0x392 => &.{0x3B2},
+ 0x393 => &.{0x3B3},
+ 0x394 => &.{0x3B4},
+ 0x395 => &.{0x3B5},
+ 0x396 => &.{0x3B6},
+ 0x397 => &.{0x3B7},
+ 0x398 => &.{0x3B8},
+ 0x399 => &.{0x3B9},
+ 0x39A => &.{0x3BA},
+ 0x39B => &.{0x3BB},
+ 0x39C => &.{0x3BC},
+ 0x39D => &.{0x3BD},
+ 0x39E => &.{0x3BE},
+ 0x39F => &.{0x3BF},
+ 0x3A0 => &.{0x3C0},
+ 0x3A1 => &.{0x3C1},
+ 0x3A3 => &.{0x3C3},
+ 0x3A4 => &.{0x3C4},
+ 0x3A5 => &.{0x3C5},
+ 0x3A6 => &.{0x3C6},
+ 0x3A7 => &.{0x3C7},
+ 0x3A8 => &.{0x3C8},
+ 0x3A9 => &.{0x3C9},
+ 0x3AA => &.{0x3CA},
+ 0x3AB => &.{0x3CB},
+ 0x3B0 => &.{ 0x3C5, 0x308, 0x301 },
+ 0x3C2 => &.{0x3C3},
+ 0x3CF => &.{0x3D7},
+ 0x3D0 => &.{0x3B2},
+ 0x3D1 => &.{0x3B8},
+ 0x3D5 => &.{0x3C6},
+ 0x3D6 => &.{0x3C0},
+ 0x3D8 => &.{0x3D9},
+ 0x3DA => &.{0x3DB},
+ 0x3DC => &.{0x3DD},
+ 0x3DE => &.{0x3DF},
+ 0x3E0 => &.{0x3E1},
+ 0x3E2 => &.{0x3E3},
+ 0x3E4 => &.{0x3E5},
+ 0x3E6 => &.{0x3E7},
+ 0x3E8 => &.{0x3E9},
+ 0x3EA => &.{0x3EB},
+ 0x3EC => &.{0x3ED},
+ 0x3EE => &.{0x3EF},
+ 0x3F0 => &.{0x3BA},
+ 0x3F1 => &.{0x3C1},
+ 0x3F4 => &.{0x3B8},
+ 0x3F5 => &.{0x3B5},
+ 0x3F7 => &.{0x3F8},
+ 0x3F9 => &.{0x3F2},
+ 0x3FA => &.{0x3FB},
+ 0x3FD => &.{0x37B},
+ 0x3FE => &.{0x37C},
+ 0x3FF => &.{0x37D},
+ 0x400 => &.{0x450},
+ 0x401 => &.{0x451},
+ 0x402 => &.{0x452},
+ 0x403 => &.{0x453},
+ 0x404 => &.{0x454},
+ 0x405 => &.{0x455},
+ 0x406 => &.{0x456},
+ 0x407 => &.{0x457},
+ 0x408 => &.{0x458},
+ 0x409 => &.{0x459},
+ 0x40A => &.{0x45A},
+ 0x40B => &.{0x45B},
+ 0x40C => &.{0x45C},
+ 0x40D => &.{0x45D},
+ 0x40E => &.{0x45E},
+ 0x40F => &.{0x45F},
+ 0x410 => &.{0x430},
+ 0x411 => &.{0x431},
+ 0x412 => &.{0x432},
+ 0x413 => &.{0x433},
+ 0x414 => &.{0x434},
+ 0x415 => &.{0x435},
+ 0x416 => &.{0x436},
+ 0x417 => &.{0x437},
+ 0x418 => &.{0x438},
+ 0x419 => &.{0x439},
+ 0x41A => &.{0x43A},
+ 0x41B => &.{0x43B},
+ 0x41C => &.{0x43C},
+ 0x41D => &.{0x43D},
+ 0x41E => &.{0x43E},
+ 0x41F => &.{0x43F},
+ 0x420 => &.{0x440},
+ 0x421 => &.{0x441},
+ 0x422 => &.{0x442},
+ 0x423 => &.{0x443},
+ 0x424 => &.{0x444},
+ 0x425 => &.{0x445},
+ 0x426 => &.{0x446},
+ 0x427 => &.{0x447},
+ 0x428 => &.{0x448},
+ 0x429 => &.{0x449},
+ 0x42A => &.{0x44A},
+ 0x42B => &.{0x44B},
+ 0x42C => &.{0x44C},
+ 0x42D => &.{0x44D},
+ 0x42E => &.{0x44E},
+ 0x42F => &.{0x44F},
+ 0x460 => &.{0x461},
+ 0x462 => &.{0x463},
+ 0x464 => &.{0x465},
+ 0x466 => &.{0x467},
+ 0x468 => &.{0x469},
+ 0x46A => &.{0x46B},
+ 0x46C => &.{0x46D},
+ 0x46E => &.{0x46F},
+ 0x470 => &.{0x471},
+ 0x472 => &.{0x473},
+ 0x474 => &.{0x475},
+ 0x476 => &.{0x477},
+ 0x478 => &.{0x479},
+ 0x47A => &.{0x47B},
+ 0x47C => &.{0x47D},
+ 0x47E => &.{0x47F},
+ 0x480 => &.{0x481},
+ 0x48A => &.{0x48B},
+ 0x48C => &.{0x48D},
+ 0x48E => &.{0x48F},
+ 0x490 => &.{0x491},
+ 0x492 => &.{0x493},
+ 0x494 => &.{0x495},
+ 0x496 => &.{0x497},
+ 0x498 => &.{0x499},
+ 0x49A => &.{0x49B},
+ 0x49C => &.{0x49D},
+ 0x49E => &.{0x49F},
+ 0x4A0 => &.{0x4A1},
+ 0x4A2 => &.{0x4A3},
+ 0x4A4 => &.{0x4A5},
+ 0x4A6 => &.{0x4A7},
+ 0x4A8 => &.{0x4A9},
+ 0x4AA => &.{0x4AB},
+ 0x4AC => &.{0x4AD},
+ 0x4AE => &.{0x4AF},
+ 0x4B0 => &.{0x4B1},
+ 0x4B2 => &.{0x4B3},
+ 0x4B4 => &.{0x4B5},
+ 0x4B6 => &.{0x4B7},
+ 0x4B8 => &.{0x4B9},
+ 0x4BA => &.{0x4BB},
+ 0x4BC => &.{0x4BD},
+ 0x4BE => &.{0x4BF},
+ 0x4C0 => &.{0x4CF},
+ 0x4C1 => &.{0x4C2},
+ 0x4C3 => &.{0x4C4},
+ 0x4C5 => &.{0x4C6},
+ 0x4C7 => &.{0x4C8},
+ 0x4C9 => &.{0x4CA},
+ 0x4CB => &.{0x4CC},
+ 0x4CD => &.{0x4CE},
+ 0x4D0 => &.{0x4D1},
+ 0x4D2 => &.{0x4D3},
+ 0x4D4 => &.{0x4D5},
+ 0x4D6 => &.{0x4D7},
+ 0x4D8 => &.{0x4D9},
+ 0x4DA => &.{0x4DB},
+ 0x4DC => &.{0x4DD},
+ 0x4DE => &.{0x4DF},
+ 0x4E0 => &.{0x4E1},
+ 0x4E2 => &.{0x4E3},
+ 0x4E4 => &.{0x4E5},
+ 0x4E6 => &.{0x4E7},
+ 0x4E8 => &.{0x4E9},
+ 0x4EA => &.{0x4EB},
+ 0x4EC => &.{0x4ED},
+ 0x4EE => &.{0x4EF},
+ 0x4F0 => &.{0x4F1},
+ 0x4F2 => &.{0x4F3},
+ 0x4F4 => &.{0x4F5},
+ 0x4F6 => &.{0x4F7},
+ 0x4F8 => &.{0x4F9},
+ 0x4FA => &.{0x4FB},
+ 0x4FC => &.{0x4FD},
+ 0x4FE => &.{0x4FF},
+ 0x500 => &.{0x501},
+ 0x502 => &.{0x503},
+ 0x504 => &.{0x505},
+ 0x506 => &.{0x507},
+ 0x508 => &.{0x509},
+ 0x50A => &.{0x50B},
+ 0x50C => &.{0x50D},
+ 0x50E => &.{0x50F},
+ 0x510 => &.{0x511},
+ 0x512 => &.{0x513},
+ 0x514 => &.{0x515},
+ 0x516 => &.{0x517},
+ 0x518 => &.{0x519},
+ 0x51A => &.{0x51B},
+ 0x51C => &.{0x51D},
+ 0x51E => &.{0x51F},
+ 0x520 => &.{0x521},
+ 0x522 => &.{0x523},
+ 0x524 => &.{0x525},
+ 0x526 => &.{0x527},
+ 0x528 => &.{0x529},
+ 0x52A => &.{0x52B},
+ 0x52C => &.{0x52D},
+ 0x52E => &.{0x52F},
+ 0x531 => &.{0x561},
+ 0x532 => &.{0x562},
+ 0x533 => &.{0x563},
+ 0x534 => &.{0x564},
+ 0x535 => &.{0x565},
+ 0x536 => &.{0x566},
+ 0x537 => &.{0x567},
+ 0x538 => &.{0x568},
+ 0x539 => &.{0x569},
+ 0x53A => &.{0x56A},
+ 0x53B => &.{0x56B},
+ 0x53C => &.{0x56C},
+ 0x53D => &.{0x56D},
+ 0x53E => &.{0x56E},
+ 0x53F => &.{0x56F},
+ 0x540 => &.{0x570},
+ 0x541 => &.{0x571},
+ 0x542 => &.{0x572},
+ 0x543 => &.{0x573},
+ 0x544 => &.{0x574},
+ 0x545 => &.{0x575},
+ 0x546 => &.{0x576},
+ 0x547 => &.{0x577},
+ 0x548 => &.{0x578},
+ 0x549 => &.{0x579},
+ 0x54A => &.{0x57A},
+ 0x54B => &.{0x57B},
+ 0x54C => &.{0x57C},
+ 0x54D => &.{0x57D},
+ 0x54E => &.{0x57E},
+ 0x54F => &.{0x57F},
+ 0x550 => &.{0x580},
+ 0x551 => &.{0x581},
+ 0x552 => &.{0x582},
+ 0x553 => &.{0x583},
+ 0x554 => &.{0x584},
+ 0x555 => &.{0x585},
+ 0x556 => &.{0x586},
+ 0x587 => &.{ 0x565, 0x582 },
+ 0x10A0 => &.{0x2D00},
+ 0x10A1 => &.{0x2D01},
+ 0x10A2 => &.{0x2D02},
+ 0x10A3 => &.{0x2D03},
+ 0x10A4 => &.{0x2D04},
+ 0x10A5 => &.{0x2D05},
+ 0x10A6 => &.{0x2D06},
+ 0x10A7 => &.{0x2D07},
+ 0x10A8 => &.{0x2D08},
+ 0x10A9 => &.{0x2D09},
+ 0x10AA => &.{0x2D0A},
+ 0x10AB => &.{0x2D0B},
+ 0x10AC => &.{0x2D0C},
+ 0x10AD => &.{0x2D0D},
+ 0x10AE => &.{0x2D0E},
+ 0x10AF => &.{0x2D0F},
+ 0x10B0 => &.{0x2D10},
+ 0x10B1 => &.{0x2D11},
+ 0x10B2 => &.{0x2D12},
+ 0x10B3 => &.{0x2D13},
+ 0x10B4 => &.{0x2D14},
+ 0x10B5 => &.{0x2D15},
+ 0x10B6 => &.{0x2D16},
+ 0x10B7 => &.{0x2D17},
+ 0x10B8 => &.{0x2D18},
+ 0x10B9 => &.{0x2D19},
+ 0x10BA => &.{0x2D1A},
+ 0x10BB => &.{0x2D1B},
+ 0x10BC => &.{0x2D1C},
+ 0x10BD => &.{0x2D1D},
+ 0x10BE => &.{0x2D1E},
+ 0x10BF => &.{0x2D1F},
+ 0x10C0 => &.{0x2D20},
+ 0x10C1 => &.{0x2D21},
+ 0x10C2 => &.{0x2D22},
+ 0x10C3 => &.{0x2D23},
+ 0x10C4 => &.{0x2D24},
+ 0x10C5 => &.{0x2D25},
+ 0x10C7 => &.{0x2D27},
+ 0x10CD => &.{0x2D2D},
+ 0x13F8 => &.{0x13F0},
+ 0x13F9 => &.{0x13F1},
+ 0x13FA => &.{0x13F2},
+ 0x13FB => &.{0x13F3},
+ 0x13FC => &.{0x13F4},
+ 0x13FD => &.{0x13F5},
+ 0x1C80 => &.{0x432},
+ 0x1C81 => &.{0x434},
+ 0x1C82 => &.{0x43E},
+ 0x1C83 => &.{0x441},
+ 0x1C84 => &.{0x442},
+ 0x1C85 => &.{0x442},
+ 0x1C86 => &.{0x44A},
+ 0x1C87 => &.{0x463},
+ 0x1C88 => &.{0xA64B},
+ 0x1C90 => &.{0x10D0},
+ 0x1C91 => &.{0x10D1},
+ 0x1C92 => &.{0x10D2},
+ 0x1C93 => &.{0x10D3},
+ 0x1C94 => &.{0x10D4},
+ 0x1C95 => &.{0x10D5},
+ 0x1C96 => &.{0x10D6},
+ 0x1C97 => &.{0x10D7},
+ 0x1C98 => &.{0x10D8},
+ 0x1C99 => &.{0x10D9},
+ 0x1C9A => &.{0x10DA},
+ 0x1C9B => &.{0x10DB},
+ 0x1C9C => &.{0x10DC},
+ 0x1C9D => &.{0x10DD},
+ 0x1C9E => &.{0x10DE},
+ 0x1C9F => &.{0x10DF},
+ 0x1CA0 => &.{0x10E0},
+ 0x1CA1 => &.{0x10E1},
+ 0x1CA2 => &.{0x10E2},
+ 0x1CA3 => &.{0x10E3},
+ 0x1CA4 => &.{0x10E4},
+ 0x1CA5 => &.{0x10E5},
+ 0x1CA6 => &.{0x10E6},
+ 0x1CA7 => &.{0x10E7},
+ 0x1CA8 => &.{0x10E8},
+ 0x1CA9 => &.{0x10E9},
+ 0x1CAA => &.{0x10EA},
+ 0x1CAB => &.{0x10EB},
+ 0x1CAC => &.{0x10EC},
+ 0x1CAD => &.{0x10ED},
+ 0x1CAE => &.{0x10EE},
+ 0x1CAF => &.{0x10EF},
+ 0x1CB0 => &.{0x10F0},
+ 0x1CB1 => &.{0x10F1},
+ 0x1CB2 => &.{0x10F2},
+ 0x1CB3 => &.{0x10F3},
+ 0x1CB4 => &.{0x10F4},
+ 0x1CB5 => &.{0x10F5},
+ 0x1CB6 => &.{0x10F6},
+ 0x1CB7 => &.{0x10F7},
+ 0x1CB8 => &.{0x10F8},
+ 0x1CB9 => &.{0x10F9},
+ 0x1CBA => &.{0x10FA},
+ 0x1CBD => &.{0x10FD},
+ 0x1CBE => &.{0x10FE},
+ 0x1CBF => &.{0x10FF},
+ 0x1E00 => &.{0x1E01},
+ 0x1E02 => &.{0x1E03},
+ 0x1E04 => &.{0x1E05},
+ 0x1E06 => &.{0x1E07},
+ 0x1E08 => &.{0x1E09},
+ 0x1E0A => &.{0x1E0B},
+ 0x1E0C => &.{0x1E0D},
+ 0x1E0E => &.{0x1E0F},
+ 0x1E10 => &.{0x1E11},
+ 0x1E12 => &.{0x1E13},
+ 0x1E14 => &.{0x1E15},
+ 0x1E16 => &.{0x1E17},
+ 0x1E18 => &.{0x1E19},
+ 0x1E1A => &.{0x1E1B},
+ 0x1E1C => &.{0x1E1D},
+ 0x1E1E => &.{0x1E1F},
+ 0x1E20 => &.{0x1E21},
+ 0x1E22 => &.{0x1E23},
+ 0x1E24 => &.{0x1E25},
+ 0x1E26 => &.{0x1E27},
+ 0x1E28 => &.{0x1E29},
+ 0x1E2A => &.{0x1E2B},
+ 0x1E2C => &.{0x1E2D},
+ 0x1E2E => &.{0x1E2F},
+ 0x1E30 => &.{0x1E31},
+ 0x1E32 => &.{0x1E33},
+ 0x1E34 => &.{0x1E35},
+ 0x1E36 => &.{0x1E37},
+ 0x1E38 => &.{0x1E39},
+ 0x1E3A => &.{0x1E3B},
+ 0x1E3C => &.{0x1E3D},
+ 0x1E3E => &.{0x1E3F},
+ 0x1E40 => &.{0x1E41},
+ 0x1E42 => &.{0x1E43},
+ 0x1E44 => &.{0x1E45},
+ 0x1E46 => &.{0x1E47},
+ 0x1E48 => &.{0x1E49},
+ 0x1E4A => &.{0x1E4B},
+ 0x1E4C => &.{0x1E4D},
+ 0x1E4E => &.{0x1E4F},
+ 0x1E50 => &.{0x1E51},
+ 0x1E52 => &.{0x1E53},
+ 0x1E54 => &.{0x1E55},
+ 0x1E56 => &.{0x1E57},
+ 0x1E58 => &.{0x1E59},
+ 0x1E5A => &.{0x1E5B},
+ 0x1E5C => &.{0x1E5D},
+ 0x1E5E => &.{0x1E5F},
+ 0x1E60 => &.{0x1E61},
+ 0x1E62 => &.{0x1E63},
+ 0x1E64 => &.{0x1E65},
+ 0x1E66 => &.{0x1E67},
+ 0x1E68 => &.{0x1E69},
+ 0x1E6A => &.{0x1E6B},
+ 0x1E6C => &.{0x1E6D},
+ 0x1E6E => &.{0x1E6F},
+ 0x1E70 => &.{0x1E71},
+ 0x1E72 => &.{0x1E73},
+ 0x1E74 => &.{0x1E75},
+ 0x1E76 => &.{0x1E77},
+ 0x1E78 => &.{0x1E79},
+ 0x1E7A => &.{0x1E7B},
+ 0x1E7C => &.{0x1E7D},
+ 0x1E7E => &.{0x1E7F},
+ 0x1E80 => &.{0x1E81},
+ 0x1E82 => &.{0x1E83},
+ 0x1E84 => &.{0x1E85},
+ 0x1E86 => &.{0x1E87},
+ 0x1E88 => &.{0x1E89},
+ 0x1E8A => &.{0x1E8B},
+ 0x1E8C => &.{0x1E8D},
+ 0x1E8E => &.{0x1E8F},
+ 0x1E90 => &.{0x1E91},
+ 0x1E92 => &.{0x1E93},
+ 0x1E94 => &.{0x1E95},
+ 0x1E96 => &.{ 0x68, 0x331 },
+ 0x1E97 => &.{ 0x74, 0x308 },
+ 0x1E98 => &.{ 0x77, 0x30A },
+ 0x1E99 => &.{ 0x79, 0x30A },
+ 0x1E9A => &.{ 0x61, 0x2BE },
+ 0x1E9B => &.{0x1E61},
+ 0x1E9E => &.{ 0x73, 0x73 },
+ 0x1EA0 => &.{0x1EA1},
+ 0x1EA2 => &.{0x1EA3},
+ 0x1EA4 => &.{0x1EA5},
+ 0x1EA6 => &.{0x1EA7},
+ 0x1EA8 => &.{0x1EA9},
+ 0x1EAA => &.{0x1EAB},
+ 0x1EAC => &.{0x1EAD},
+ 0x1EAE => &.{0x1EAF},
+ 0x1EB0 => &.{0x1EB1},
+ 0x1EB2 => &.{0x1EB3},
+ 0x1EB4 => &.{0x1EB5},
+ 0x1EB6 => &.{0x1EB7},
+ 0x1EB8 => &.{0x1EB9},
+ 0x1EBA => &.{0x1EBB},
+ 0x1EBC => &.{0x1EBD},
+ 0x1EBE => &.{0x1EBF},
+ 0x1EC0 => &.{0x1EC1},
+ 0x1EC2 => &.{0x1EC3},
+ 0x1EC4 => &.{0x1EC5},
+ 0x1EC6 => &.{0x1EC7},
+ 0x1EC8 => &.{0x1EC9},
+ 0x1ECA => &.{0x1ECB},
+ 0x1ECC => &.{0x1ECD},
+ 0x1ECE => &.{0x1ECF},
+ 0x1ED0 => &.{0x1ED1},
+ 0x1ED2 => &.{0x1ED3},
+ 0x1ED4 => &.{0x1ED5},
+ 0x1ED6 => &.{0x1ED7},
+ 0x1ED8 => &.{0x1ED9},
+ 0x1EDA => &.{0x1EDB},
+ 0x1EDC => &.{0x1EDD},
+ 0x1EDE => &.{0x1EDF},
+ 0x1EE0 => &.{0x1EE1},
+ 0x1EE2 => &.{0x1EE3},
+ 0x1EE4 => &.{0x1EE5},
+ 0x1EE6 => &.{0x1EE7},
+ 0x1EE8 => &.{0x1EE9},
+ 0x1EEA => &.{0x1EEB},
+ 0x1EEC => &.{0x1EED},
+ 0x1EEE => &.{0x1EEF},
+ 0x1EF0 => &.{0x1EF1},
+ 0x1EF2 => &.{0x1EF3},
+ 0x1EF4 => &.{0x1EF5},
+ 0x1EF6 => &.{0x1EF7},
+ 0x1EF8 => &.{0x1EF9},
+ 0x1EFA => &.{0x1EFB},
+ 0x1EFC => &.{0x1EFD},
+ 0x1EFE => &.{0x1EFF},
+ 0x1F08 => &.{0x1F00},
+ 0x1F09 => &.{0x1F01},
+ 0x1F0A => &.{0x1F02},
+ 0x1F0B => &.{0x1F03},
+ 0x1F0C => &.{0x1F04},
+ 0x1F0D => &.{0x1F05},
+ 0x1F0E => &.{0x1F06},
+ 0x1F0F => &.{0x1F07},
+ 0x1F18 => &.{0x1F10},
+ 0x1F19 => &.{0x1F11},
+ 0x1F1A => &.{0x1F12},
+ 0x1F1B => &.{0x1F13},
+ 0x1F1C => &.{0x1F14},
+ 0x1F1D => &.{0x1F15},
+ 0x1F28 => &.{0x1F20},
+ 0x1F29 => &.{0x1F21},
+ 0x1F2A => &.{0x1F22},
+ 0x1F2B => &.{0x1F23},
+ 0x1F2C => &.{0x1F24},
+ 0x1F2D => &.{0x1F25},
+ 0x1F2E => &.{0x1F26},
+ 0x1F2F => &.{0x1F27},
+ 0x1F38 => &.{0x1F30},
+ 0x1F39 => &.{0x1F31},
+ 0x1F3A => &.{0x1F32},
+ 0x1F3B => &.{0x1F33},
+ 0x1F3C => &.{0x1F34},
+ 0x1F3D => &.{0x1F35},
+ 0x1F3E => &.{0x1F36},
+ 0x1F3F => &.{0x1F37},
+ 0x1F48 => &.{0x1F40},
+ 0x1F49 => &.{0x1F41},
+ 0x1F4A => &.{0x1F42},
+ 0x1F4B => &.{0x1F43},
+ 0x1F4C => &.{0x1F44},
+ 0x1F4D => &.{0x1F45},
+ 0x1F50 => &.{ 0x3C5, 0x313 },
+ 0x1F52 => &.{ 0x3C5, 0x313, 0x300 },
+ 0x1F54 => &.{ 0x3C5, 0x313, 0x301 },
+ 0x1F56 => &.{ 0x3C5, 0x313, 0x342 },
+ 0x1F59 => &.{0x1F51},
+ 0x1F5B => &.{0x1F53},
+ 0x1F5D => &.{0x1F55},
+ 0x1F5F => &.{0x1F57},
+ 0x1F68 => &.{0x1F60},
+ 0x1F69 => &.{0x1F61},
+ 0x1F6A => &.{0x1F62},
+ 0x1F6B => &.{0x1F63},
+ 0x1F6C => &.{0x1F64},
+ 0x1F6D => &.{0x1F65},
+ 0x1F6E => &.{0x1F66},
+ 0x1F6F => &.{0x1F67},
+ 0x1F80 => &.{ 0x1F00, 0x3B9 },
+ 0x1F81 => &.{ 0x1F01, 0x3B9 },
+ 0x1F82 => &.{ 0x1F02, 0x3B9 },
+ 0x1F83 => &.{ 0x1F03, 0x3B9 },
+ 0x1F84 => &.{ 0x1F04, 0x3B9 },
+ 0x1F85 => &.{ 0x1F05, 0x3B9 },
+ 0x1F86 => &.{ 0x1F06, 0x3B9 },
+ 0x1F87 => &.{ 0x1F07, 0x3B9 },
+ 0x1F88 => &.{ 0x1F00, 0x3B9 },
+ 0x1F89 => &.{ 0x1F01, 0x3B9 },
+ 0x1F8A => &.{ 0x1F02, 0x3B9 },
+ 0x1F8B => &.{ 0x1F03, 0x3B9 },
+ 0x1F8C => &.{ 0x1F04, 0x3B9 },
+ 0x1F8D => &.{ 0x1F05, 0x3B9 },
+ 0x1F8E => &.{ 0x1F06, 0x3B9 },
+ 0x1F8F => &.{ 0x1F07, 0x3B9 },
+ 0x1F90 => &.{ 0x1F20, 0x3B9 },
+ 0x1F91 => &.{ 0x1F21, 0x3B9 },
+ 0x1F92 => &.{ 0x1F22, 0x3B9 },
+ 0x1F93 => &.{ 0x1F23, 0x3B9 },
+ 0x1F94 => &.{ 0x1F24, 0x3B9 },
+ 0x1F95 => &.{ 0x1F25, 0x3B9 },
+ 0x1F96 => &.{ 0x1F26, 0x3B9 },
+ 0x1F97 => &.{ 0x1F27, 0x3B9 },
+ 0x1F98 => &.{ 0x1F20, 0x3B9 },
+ 0x1F99 => &.{ 0x1F21, 0x3B9 },
+ 0x1F9A => &.{ 0x1F22, 0x3B9 },
+ 0x1F9B => &.{ 0x1F23, 0x3B9 },
+ 0x1F9C => &.{ 0x1F24, 0x3B9 },
+ 0x1F9D => &.{ 0x1F25, 0x3B9 },
+ 0x1F9E => &.{ 0x1F26, 0x3B9 },
+ 0x1F9F => &.{ 0x1F27, 0x3B9 },
+ 0x1FA0 => &.{ 0x1F60, 0x3B9 },
+ 0x1FA1 => &.{ 0x1F61, 0x3B9 },
+ 0x1FA2 => &.{ 0x1F62, 0x3B9 },
+ 0x1FA3 => &.{ 0x1F63, 0x3B9 },
+ 0x1FA4 => &.{ 0x1F64, 0x3B9 },
+ 0x1FA5 => &.{ 0x1F65, 0x3B9 },
+ 0x1FA6 => &.{ 0x1F66, 0x3B9 },
+ 0x1FA7 => &.{ 0x1F67, 0x3B9 },
+ 0x1FA8 => &.{ 0x1F60, 0x3B9 },
+ 0x1FA9 => &.{ 0x1F61, 0x3B9 },
+ 0x1FAA => &.{ 0x1F62, 0x3B9 },
+ 0x1FAB => &.{ 0x1F63, 0x3B9 },
+ 0x1FAC => &.{ 0x1F64, 0x3B9 },
+ 0x1FAD => &.{ 0x1F65, 0x3B9 },
+ 0x1FAE => &.{ 0x1F66, 0x3B9 },
+ 0x1FAF => &.{ 0x1F67, 0x3B9 },
+ 0x1FB2 => &.{ 0x1F70, 0x3B9 },
+ 0x1FB3 => &.{ 0x3B1, 0x3B9 },
+ 0x1FB4 => &.{ 0x3AC, 0x3B9 },
+ 0x1FB6 => &.{ 0x3B1, 0x342 },
+ 0x1FB7 => &.{ 0x3B1, 0x342, 0x3B9 },
+ 0x1FB8 => &.{0x1FB0},
+ 0x1FB9 => &.{0x1FB1},
+ 0x1FBA => &.{0x1F70},
+ 0x1FBB => &.{0x1F71},
+ 0x1FBC => &.{ 0x3B1, 0x3B9 },
+ 0x1FBE => &.{0x3B9},
+ 0x1FC2 => &.{ 0x1F74, 0x3B9 },
+ 0x1FC3 => &.{ 0x3B7, 0x3B9 },
+ 0x1FC4 => &.{ 0x3AE, 0x3B9 },
+ 0x1FC6 => &.{ 0x3B7, 0x342 },
+ 0x1FC7 => &.{ 0x3B7, 0x342, 0x3B9 },
+ 0x1FC8 => &.{0x1F72},
+ 0x1FC9 => &.{0x1F73},
+ 0x1FCA => &.{0x1F74},
+ 0x1FCB => &.{0x1F75},
+ 0x1FCC => &.{ 0x3B7, 0x3B9 },
+ 0x1FD2 => &.{ 0x3B9, 0x308, 0x300 },
+ 0x1FD3 => &.{ 0x3B9, 0x308, 0x301 },
+ 0x1FD6 => &.{ 0x3B9, 0x342 },
+ 0x1FD7 => &.{ 0x3B9, 0x308, 0x342 },
+ 0x1FD8 => &.{0x1FD0},
+ 0x1FD9 => &.{0x1FD1},
+ 0x1FDA => &.{0x1F76},
+ 0x1FDB => &.{0x1F77},
+ 0x1FE2 => &.{ 0x3C5, 0x308, 0x300 },
+ 0x1FE3 => &.{ 0x3C5, 0x308, 0x301 },
+ 0x1FE4 => &.{ 0x3C1, 0x313 },
+ 0x1FE6 => &.{ 0x3C5, 0x342 },
+ 0x1FE7 => &.{ 0x3C5, 0x308, 0x342 },
+ 0x1FE8 => &.{0x1FE0},
+ 0x1FE9 => &.{0x1FE1},
+ 0x1FEA => &.{0x1F7A},
+ 0x1FEB => &.{0x1F7B},
+ 0x1FEC => &.{0x1FE5},
+ 0x1FF2 => &.{ 0x1F7C, 0x3B9 },
+ 0x1FF3 => &.{ 0x3C9, 0x3B9 },
+ 0x1FF4 => &.{ 0x3CE, 0x3B9 },
+ 0x1FF6 => &.{ 0x3C9, 0x342 },
+ 0x1FF7 => &.{ 0x3C9, 0x342, 0x3B9 },
+ 0x1FF8 => &.{0x1F78},
+ 0x1FF9 => &.{0x1F79},
+ 0x1FFA => &.{0x1F7C},
+ 0x1FFB => &.{0x1F7D},
+ 0x1FFC => &.{ 0x3C9, 0x3B9 },
+ 0x2126 => &.{0x3C9},
+ 0x212A => &.{0x6B},
+ 0x212B => &.{0xE5},
+ 0x2132 => &.{0x214E},
+ 0x2160 => &.{0x2170},
+ 0x2161 => &.{0x2171},
+ 0x2162 => &.{0x2172},
+ 0x2163 => &.{0x2173},
+ 0x2164 => &.{0x2174},
+ 0x2165 => &.{0x2175},
+ 0x2166 => &.{0x2176},
+ 0x2167 => &.{0x2177},
+ 0x2168 => &.{0x2178},
+ 0x2169 => &.{0x2179},
+ 0x216A => &.{0x217A},
+ 0x216B => &.{0x217B},
+ 0x216C => &.{0x217C},
+ 0x216D => &.{0x217D},
+ 0x216E => &.{0x217E},
+ 0x216F => &.{0x217F},
+ 0x2183 => &.{0x2184},
+ 0x24B6 => &.{0x24D0},
+ 0x24B7 => &.{0x24D1},
+ 0x24B8 => &.{0x24D2},
+ 0x24B9 => &.{0x24D3},
+ 0x24BA => &.{0x24D4},
+ 0x24BB => &.{0x24D5},
+ 0x24BC => &.{0x24D6},
+ 0x24BD => &.{0x24D7},
+ 0x24BE => &.{0x24D8},
+ 0x24BF => &.{0x24D9},
+ 0x24C0 => &.{0x24DA},
+ 0x24C1 => &.{0x24DB},
+ 0x24C2 => &.{0x24DC},
+ 0x24C3 => &.{0x24DD},
+ 0x24C4 => &.{0x24DE},
+ 0x24C5 => &.{0x24DF},
+ 0x24C6 => &.{0x24E0},
+ 0x24C7 => &.{0x24E1},
+ 0x24C8 => &.{0x24E2},
+ 0x24C9 => &.{0x24E3},
+ 0x24CA => &.{0x24E4},
+ 0x24CB => &.{0x24E5},
+ 0x24CC => &.{0x24E6},
+ 0x24CD => &.{0x24E7},
+ 0x24CE => &.{0x24E8},
+ 0x24CF => &.{0x24E9},
+ 0x2C00 => &.{0x2C30},
+ 0x2C01 => &.{0x2C31},
+ 0x2C02 => &.{0x2C32},
+ 0x2C03 => &.{0x2C33},
+ 0x2C04 => &.{0x2C34},
+ 0x2C05 => &.{0x2C35},
+ 0x2C06 => &.{0x2C36},
+ 0x2C07 => &.{0x2C37},
+ 0x2C08 => &.{0x2C38},
+ 0x2C09 => &.{0x2C39},
+ 0x2C0A => &.{0x2C3A},
+ 0x2C0B => &.{0x2C3B},
+ 0x2C0C => &.{0x2C3C},
+ 0x2C0D => &.{0x2C3D},
+ 0x2C0E => &.{0x2C3E},
+ 0x2C0F => &.{0x2C3F},
+ 0x2C10 => &.{0x2C40},
+ 0x2C11 => &.{0x2C41},
+ 0x2C12 => &.{0x2C42},
+ 0x2C13 => &.{0x2C43},
+ 0x2C14 => &.{0x2C44},
+ 0x2C15 => &.{0x2C45},
+ 0x2C16 => &.{0x2C46},
+ 0x2C17 => &.{0x2C47},
+ 0x2C18 => &.{0x2C48},
+ 0x2C19 => &.{0x2C49},
+ 0x2C1A => &.{0x2C4A},
+ 0x2C1B => &.{0x2C4B},
+ 0x2C1C => &.{0x2C4C},
+ 0x2C1D => &.{0x2C4D},
+ 0x2C1E => &.{0x2C4E},
+ 0x2C1F => &.{0x2C4F},
+ 0x2C20 => &.{0x2C50},
+ 0x2C21 => &.{0x2C51},
+ 0x2C22 => &.{0x2C52},
+ 0x2C23 => &.{0x2C53},
+ 0x2C24 => &.{0x2C54},
+ 0x2C25 => &.{0x2C55},
+ 0x2C26 => &.{0x2C56},
+ 0x2C27 => &.{0x2C57},
+ 0x2C28 => &.{0x2C58},
+ 0x2C29 => &.{0x2C59},
+ 0x2C2A => &.{0x2C5A},
+ 0x2C2B => &.{0x2C5B},
+ 0x2C2C => &.{0x2C5C},
+ 0x2C2D => &.{0x2C5D},
+ 0x2C2E => &.{0x2C5E},
+ 0x2C2F => &.{0x2C5F},
+ 0x2C60 => &.{0x2C61},
+ 0x2C62 => &.{0x26B},
+ 0x2C63 => &.{0x1D7D},
+ 0x2C64 => &.{0x27D},
+ 0x2C67 => &.{0x2C68},
+ 0x2C69 => &.{0x2C6A},
+ 0x2C6B => &.{0x2C6C},
+ 0x2C6D => &.{0x251},
+ 0x2C6E => &.{0x271},
+ 0x2C6F => &.{0x250},
+ 0x2C70 => &.{0x252},
+ 0x2C72 => &.{0x2C73},
+ 0x2C75 => &.{0x2C76},
+ 0x2C7E => &.{0x23F},
+ 0x2C7F => &.{0x240},
+ 0x2C80 => &.{0x2C81},
+ 0x2C82 => &.{0x2C83},
+ 0x2C84 => &.{0x2C85},
+ 0x2C86 => &.{0x2C87},
+ 0x2C88 => &.{0x2C89},
+ 0x2C8A => &.{0x2C8B},
+ 0x2C8C => &.{0x2C8D},
+ 0x2C8E => &.{0x2C8F},
+ 0x2C90 => &.{0x2C91},
+ 0x2C92 => &.{0x2C93},
+ 0x2C94 => &.{0x2C95},
+ 0x2C96 => &.{0x2C97},
+ 0x2C98 => &.{0x2C99},
+ 0x2C9A => &.{0x2C9B},
+ 0x2C9C => &.{0x2C9D},
+ 0x2C9E => &.{0x2C9F},
+ 0x2CA0 => &.{0x2CA1},
+ 0x2CA2 => &.{0x2CA3},
+ 0x2CA4 => &.{0x2CA5},
+ 0x2CA6 => &.{0x2CA7},
+ 0x2CA8 => &.{0x2CA9},
+ 0x2CAA => &.{0x2CAB},
+ 0x2CAC => &.{0x2CAD},
+ 0x2CAE => &.{0x2CAF},
+ 0x2CB0 => &.{0x2CB1},
+ 0x2CB2 => &.{0x2CB3},
+ 0x2CB4 => &.{0x2CB5},
+ 0x2CB6 => &.{0x2CB7},
+ 0x2CB8 => &.{0x2CB9},
+ 0x2CBA => &.{0x2CBB},
+ 0x2CBC => &.{0x2CBD},
+ 0x2CBE => &.{0x2CBF},
+ 0x2CC0 => &.{0x2CC1},
+ 0x2CC2 => &.{0x2CC3},
+ 0x2CC4 => &.{0x2CC5},
+ 0x2CC6 => &.{0x2CC7},
+ 0x2CC8 => &.{0x2CC9},
+ 0x2CCA => &.{0x2CCB},
+ 0x2CCC => &.{0x2CCD},
+ 0x2CCE => &.{0x2CCF},
+ 0x2CD0 => &.{0x2CD1},
+ 0x2CD2 => &.{0x2CD3},
+ 0x2CD4 => &.{0x2CD5},
+ 0x2CD6 => &.{0x2CD7},
+ 0x2CD8 => &.{0x2CD9},
+ 0x2CDA => &.{0x2CDB},
+ 0x2CDC => &.{0x2CDD},
+ 0x2CDE => &.{0x2CDF},
+ 0x2CE0 => &.{0x2CE1},
+ 0x2CE2 => &.{0x2CE3},
+ 0x2CEB => &.{0x2CEC},
+ 0x2CED => &.{0x2CEE},
+ 0x2CF2 => &.{0x2CF3},
+ 0xA640 => &.{0xA641},
+ 0xA642 => &.{0xA643},
+ 0xA644 => &.{0xA645},
+ 0xA646 => &.{0xA647},
+ 0xA648 => &.{0xA649},
+ 0xA64A => &.{0xA64B},
+ 0xA64C => &.{0xA64D},
+ 0xA64E => &.{0xA64F},
+ 0xA650 => &.{0xA651},
+ 0xA652 => &.{0xA653},
+ 0xA654 => &.{0xA655},
+ 0xA656 => &.{0xA657},
+ 0xA658 => &.{0xA659},
+ 0xA65A => &.{0xA65B},
+ 0xA65C => &.{0xA65D},
+ 0xA65E => &.{0xA65F},
+ 0xA660 => &.{0xA661},
+ 0xA662 => &.{0xA663},
+ 0xA664 => &.{0xA665},
+ 0xA666 => &.{0xA667},
+ 0xA668 => &.{0xA669},
+ 0xA66A => &.{0xA66B},
+ 0xA66C => &.{0xA66D},
+ 0xA680 => &.{0xA681},
+ 0xA682 => &.{0xA683},
+ 0xA684 => &.{0xA685},
+ 0xA686 => &.{0xA687},
+ 0xA688 => &.{0xA689},
+ 0xA68A => &.{0xA68B},
+ 0xA68C => &.{0xA68D},
+ 0xA68E => &.{0xA68F},
+ 0xA690 => &.{0xA691},
+ 0xA692 => &.{0xA693},
+ 0xA694 => &.{0xA695},
+ 0xA696 => &.{0xA697},
+ 0xA698 => &.{0xA699},
+ 0xA69A => &.{0xA69B},
+ 0xA722 => &.{0xA723},
+ 0xA724 => &.{0xA725},
+ 0xA726 => &.{0xA727},
+ 0xA728 => &.{0xA729},
+ 0xA72A => &.{0xA72B},
+ 0xA72C => &.{0xA72D},
+ 0xA72E => &.{0xA72F},
+ 0xA732 => &.{0xA733},
+ 0xA734 => &.{0xA735},
+ 0xA736 => &.{0xA737},
+ 0xA738 => &.{0xA739},
+ 0xA73A => &.{0xA73B},
+ 0xA73C => &.{0xA73D},
+ 0xA73E => &.{0xA73F},
+ 0xA740 => &.{0xA741},
+ 0xA742 => &.{0xA743},
+ 0xA744 => &.{0xA745},
+ 0xA746 => &.{0xA747},
+ 0xA748 => &.{0xA749},
+ 0xA74A => &.{0xA74B},
+ 0xA74C => &.{0xA74D},
+ 0xA74E => &.{0xA74F},
+ 0xA750 => &.{0xA751},
+ 0xA752 => &.{0xA753},
+ 0xA754 => &.{0xA755},
+ 0xA756 => &.{0xA757},
+ 0xA758 => &.{0xA759},
+ 0xA75A => &.{0xA75B},
+ 0xA75C => &.{0xA75D},
+ 0xA75E => &.{0xA75F},
+ 0xA760 => &.{0xA761},
+ 0xA762 => &.{0xA763},
+ 0xA764 => &.{0xA765},
+ 0xA766 => &.{0xA767},
+ 0xA768 => &.{0xA769},
+ 0xA76A => &.{0xA76B},
+ 0xA76C => &.{0xA76D},
+ 0xA76E => &.{0xA76F},
+ 0xA779 => &.{0xA77A},
+ 0xA77B => &.{0xA77C},
+ 0xA77D => &.{0x1D79},
+ 0xA77E => &.{0xA77F},
+ 0xA780 => &.{0xA781},
+ 0xA782 => &.{0xA783},
+ 0xA784 => &.{0xA785},
+ 0xA786 => &.{0xA787},
+ 0xA78B => &.{0xA78C},
+ 0xA78D => &.{0x265},
+ 0xA790 => &.{0xA791},
+ 0xA792 => &.{0xA793},
+ 0xA796 => &.{0xA797},
+ 0xA798 => &.{0xA799},
+ 0xA79A => &.{0xA79B},
+ 0xA79C => &.{0xA79D},
+ 0xA79E => &.{0xA79F},
+ 0xA7A0 => &.{0xA7A1},
+ 0xA7A2 => &.{0xA7A3},
+ 0xA7A4 => &.{0xA7A5},
+ 0xA7A6 => &.{0xA7A7},
+ 0xA7A8 => &.{0xA7A9},
+ 0xA7AA => &.{0x266},
+ 0xA7AB => &.{0x25C},
+ 0xA7AC => &.{0x261},
+ 0xA7AD => &.{0x26C},
+ 0xA7AE => &.{0x26A},
+ 0xA7B0 => &.{0x29E},
+ 0xA7B1 => &.{0x287},
+ 0xA7B2 => &.{0x29D},
+ 0xA7B3 => &.{0xAB53},
+ 0xA7B4 => &.{0xA7B5},
+ 0xA7B6 => &.{0xA7B7},
+ 0xA7B8 => &.{0xA7B9},
+ 0xA7BA => &.{0xA7BB},
+ 0xA7BC => &.{0xA7BD},
+ 0xA7BE => &.{0xA7BF},
+ 0xA7C0 => &.{0xA7C1},
+ 0xA7C2 => &.{0xA7C3},
+ 0xA7C4 => &.{0xA794},
+ 0xA7C5 => &.{0x282},
+ 0xA7C6 => &.{0x1D8E},
+ 0xA7C7 => &.{0xA7C8},
+ 0xA7C9 => &.{0xA7CA},
+ 0xA7D0 => &.{0xA7D1},
+ 0xA7D6 => &.{0xA7D7},
+ 0xA7D8 => &.{0xA7D9},
+ 0xA7F5 => &.{0xA7F6},
+ 0xAB70 => &.{0x13A0},
+ 0xAB71 => &.{0x13A1},
+ 0xAB72 => &.{0x13A2},
+ 0xAB73 => &.{0x13A3},
+ 0xAB74 => &.{0x13A4},
+ 0xAB75 => &.{0x13A5},
+ 0xAB76 => &.{0x13A6},
+ 0xAB77 => &.{0x13A7},
+ 0xAB78 => &.{0x13A8},
+ 0xAB79 => &.{0x13A9},
+ 0xAB7A => &.{0x13AA},
+ 0xAB7B => &.{0x13AB},
+ 0xAB7C => &.{0x13AC},
+ 0xAB7D => &.{0x13AD},
+ 0xAB7E => &.{0x13AE},
+ 0xAB7F => &.{0x13AF},
+ 0xAB80 => &.{0x13B0},
+ 0xAB81 => &.{0x13B1},
+ 0xAB82 => &.{0x13B2},
+ 0xAB83 => &.{0x13B3},
+ 0xAB84 => &.{0x13B4},
+ 0xAB85 => &.{0x13B5},
+ 0xAB86 => &.{0x13B6},
+ 0xAB87 => &.{0x13B7},
+ 0xAB88 => &.{0x13B8},
+ 0xAB89 => &.{0x13B9},
+ 0xAB8A => &.{0x13BA},
+ 0xAB8B => &.{0x13BB},
+ 0xAB8C => &.{0x13BC},
+ 0xAB8D => &.{0x13BD},
+ 0xAB8E => &.{0x13BE},
+ 0xAB8F => &.{0x13BF},
+ 0xAB90 => &.{0x13C0},
+ 0xAB91 => &.{0x13C1},
+ 0xAB92 => &.{0x13C2},
+ 0xAB93 => &.{0x13C3},
+ 0xAB94 => &.{0x13C4},
+ 0xAB95 => &.{0x13C5},
+ 0xAB96 => &.{0x13C6},
+ 0xAB97 => &.{0x13C7},
+ 0xAB98 => &.{0x13C8},
+ 0xAB99 => &.{0x13C9},
+ 0xAB9A => &.{0x13CA},
+ 0xAB9B => &.{0x13CB},
+ 0xAB9C => &.{0x13CC},
+ 0xAB9D => &.{0x13CD},
+ 0xAB9E => &.{0x13CE},
+ 0xAB9F => &.{0x13CF},
+ 0xABA0 => &.{0x13D0},
+ 0xABA1 => &.{0x13D1},
+ 0xABA2 => &.{0x13D2},
+ 0xABA3 => &.{0x13D3},
+ 0xABA4 => &.{0x13D4},
+ 0xABA5 => &.{0x13D5},
+ 0xABA6 => &.{0x13D6},
+ 0xABA7 => &.{0x13D7},
+ 0xABA8 => &.{0x13D8},
+ 0xABA9 => &.{0x13D9},
+ 0xABAA => &.{0x13DA},
+ 0xABAB => &.{0x13DB},
+ 0xABAC => &.{0x13DC},
+ 0xABAD => &.{0x13DD},
+ 0xABAE => &.{0x13DE},
+ 0xABAF => &.{0x13DF},
+ 0xABB0 => &.{0x13E0},
+ 0xABB1 => &.{0x13E1},
+ 0xABB2 => &.{0x13E2},
+ 0xABB3 => &.{0x13E3},
+ 0xABB4 => &.{0x13E4},
+ 0xABB5 => &.{0x13E5},
+ 0xABB6 => &.{0x13E6},
+ 0xABB7 => &.{0x13E7},
+ 0xABB8 => &.{0x13E8},
+ 0xABB9 => &.{0x13E9},
+ 0xABBA => &.{0x13EA},
+ 0xABBB => &.{0x13EB},
+ 0xABBC => &.{0x13EC},
+ 0xABBD => &.{0x13ED},
+ 0xABBE => &.{0x13EE},
+ 0xABBF => &.{0x13EF},
+ 0xFB00 => &.{ 0x66, 0x66 },
+ 0xFB01 => &.{ 0x66, 0x69 },
+ 0xFB02 => &.{ 0x66, 0x6C },
+ 0xFB03 => &.{ 0x66, 0x66, 0x69 },
+ 0xFB04 => &.{ 0x66, 0x66, 0x6C },
+ 0xFB05 => &.{ 0x73, 0x74 },
+ 0xFB06 => &.{ 0x73, 0x74 },
+ 0xFB13 => &.{ 0x574, 0x576 },
+ 0xFB14 => &.{ 0x574, 0x565 },
+ 0xFB15 => &.{ 0x574, 0x56B },
+ 0xFB16 => &.{ 0x57E, 0x576 },
+ 0xFB17 => &.{ 0x574, 0x56D },
+ 0xFF21 => &.{0xFF41},
+ 0xFF22 => &.{0xFF42},
+ 0xFF23 => &.{0xFF43},
+ 0xFF24 => &.{0xFF44},
+ 0xFF25 => &.{0xFF45},
+ 0xFF26 => &.{0xFF46},
+ 0xFF27 => &.{0xFF47},
+ 0xFF28 => &.{0xFF48},
+ 0xFF29 => &.{0xFF49},
+ 0xFF2A => &.{0xFF4A},
+ 0xFF2B => &.{0xFF4B},
+ 0xFF2C => &.{0xFF4C},
+ 0xFF2D => &.{0xFF4D},
+ 0xFF2E => &.{0xFF4E},
+ 0xFF2F => &.{0xFF4F},
+ 0xFF30 => &.{0xFF50},
+ 0xFF31 => &.{0xFF51},
+ 0xFF32 => &.{0xFF52},
+ 0xFF33 => &.{0xFF53},
+ 0xFF34 => &.{0xFF54},
+ 0xFF35 => &.{0xFF55},
+ 0xFF36 => &.{0xFF56},
+ 0xFF37 => &.{0xFF57},
+ 0xFF38 => &.{0xFF58},
+ 0xFF39 => &.{0xFF59},
+ 0xFF3A => &.{0xFF5A},
+ 0x10400 => &.{0x10428},
+ 0x10401 => &.{0x10429},
+ 0x10402 => &.{0x1042A},
+ 0x10403 => &.{0x1042B},
+ 0x10404 => &.{0x1042C},
+ 0x10405 => &.{0x1042D},
+ 0x10406 => &.{0x1042E},
+ 0x10407 => &.{0x1042F},
+ 0x10408 => &.{0x10430},
+ 0x10409 => &.{0x10431},
+ 0x1040A => &.{0x10432},
+ 0x1040B => &.{0x10433},
+ 0x1040C => &.{0x10434},
+ 0x1040D => &.{0x10435},
+ 0x1040E => &.{0x10436},
+ 0x1040F => &.{0x10437},
+ 0x10410 => &.{0x10438},
+ 0x10411 => &.{0x10439},
+ 0x10412 => &.{0x1043A},
+ 0x10413 => &.{0x1043B},
+ 0x10414 => &.{0x1043C},
+ 0x10415 => &.{0x1043D},
+ 0x10416 => &.{0x1043E},
+ 0x10417 => &.{0x1043F},
+ 0x10418 => &.{0x10440},
+ 0x10419 => &.{0x10441},
+ 0x1041A => &.{0x10442},
+ 0x1041B => &.{0x10443},
+ 0x1041C => &.{0x10444},
+ 0x1041D => &.{0x10445},
+ 0x1041E => &.{0x10446},
+ 0x1041F => &.{0x10447},
+ 0x10420 => &.{0x10448},
+ 0x10421 => &.{0x10449},
+ 0x10422 => &.{0x1044A},
+ 0x10423 => &.{0x1044B},
+ 0x10424 => &.{0x1044C},
+ 0x10425 => &.{0x1044D},
+ 0x10426 => &.{0x1044E},
+ 0x10427 => &.{0x1044F},
+ 0x104B0 => &.{0x104D8},
+ 0x104B1 => &.{0x104D9},
+ 0x104B2 => &.{0x104DA},
+ 0x104B3 => &.{0x104DB},
+ 0x104B4 => &.{0x104DC},
+ 0x104B5 => &.{0x104DD},
+ 0x104B6 => &.{0x104DE},
+ 0x104B7 => &.{0x104DF},
+ 0x104B8 => &.{0x104E0},
+ 0x104B9 => &.{0x104E1},
+ 0x104BA => &.{0x104E2},
+ 0x104BB => &.{0x104E3},
+ 0x104BC => &.{0x104E4},
+ 0x104BD => &.{0x104E5},
+ 0x104BE => &.{0x104E6},
+ 0x104BF => &.{0x104E7},
+ 0x104C0 => &.{0x104E8},
+ 0x104C1 => &.{0x104E9},
+ 0x104C2 => &.{0x104EA},
+ 0x104C3 => &.{0x104EB},
+ 0x104C4 => &.{0x104EC},
+ 0x104C5 => &.{0x104ED},
+ 0x104C6 => &.{0x104EE},
+ 0x104C7 => &.{0x104EF},
+ 0x104C8 => &.{0x104F0},
+ 0x104C9 => &.{0x104F1},
+ 0x104CA => &.{0x104F2},
+ 0x104CB => &.{0x104F3},
+ 0x104CC => &.{0x104F4},
+ 0x104CD => &.{0x104F5},
+ 0x104CE => &.{0x104F6},
+ 0x104CF => &.{0x104F7},
+ 0x104D0 => &.{0x104F8},
+ 0x104D1 => &.{0x104F9},
+ 0x104D2 => &.{0x104FA},
+ 0x104D3 => &.{0x104FB},
+ 0x10570 => &.{0x10597},
+ 0x10571 => &.{0x10598},
+ 0x10572 => &.{0x10599},
+ 0x10573 => &.{0x1059A},
+ 0x10574 => &.{0x1059B},
+ 0x10575 => &.{0x1059C},
+ 0x10576 => &.{0x1059D},
+ 0x10577 => &.{0x1059E},
+ 0x10578 => &.{0x1059F},
+ 0x10579 => &.{0x105A0},
+ 0x1057A => &.{0x105A1},
+ 0x1057C => &.{0x105A3},
+ 0x1057D => &.{0x105A4},
+ 0x1057E => &.{0x105A5},
+ 0x1057F => &.{0x105A6},
+ 0x10580 => &.{0x105A7},
+ 0x10581 => &.{0x105A8},
+ 0x10582 => &.{0x105A9},
+ 0x10583 => &.{0x105AA},
+ 0x10584 => &.{0x105AB},
+ 0x10585 => &.{0x105AC},
+ 0x10586 => &.{0x105AD},
+ 0x10587 => &.{0x105AE},
+ 0x10588 => &.{0x105AF},
+ 0x10589 => &.{0x105B0},
+ 0x1058A => &.{0x105B1},
+ 0x1058C => &.{0x105B3},
+ 0x1058D => &.{0x105B4},
+ 0x1058E => &.{0x105B5},
+ 0x1058F => &.{0x105B6},
+ 0x10590 => &.{0x105B7},
+ 0x10591 => &.{0x105B8},
+ 0x10592 => &.{0x105B9},
+ 0x10594 => &.{0x105BB},
+ 0x10595 => &.{0x105BC},
+ 0x10C80 => &.{0x10CC0},
+ 0x10C81 => &.{0x10CC1},
+ 0x10C82 => &.{0x10CC2},
+ 0x10C83 => &.{0x10CC3},
+ 0x10C84 => &.{0x10CC4},
+ 0x10C85 => &.{0x10CC5},
+ 0x10C86 => &.{0x10CC6},
+ 0x10C87 => &.{0x10CC7},
+ 0x10C88 => &.{0x10CC8},
+ 0x10C89 => &.{0x10CC9},
+ 0x10C8A => &.{0x10CCA},
+ 0x10C8B => &.{0x10CCB},
+ 0x10C8C => &.{0x10CCC},
+ 0x10C8D => &.{0x10CCD},
+ 0x10C8E => &.{0x10CCE},
+ 0x10C8F => &.{0x10CCF},
+ 0x10C90 => &.{0x10CD0},
+ 0x10C91 => &.{0x10CD1},
+ 0x10C92 => &.{0x10CD2},
+ 0x10C93 => &.{0x10CD3},
+ 0x10C94 => &.{0x10CD4},
+ 0x10C95 => &.{0x10CD5},
+ 0x10C96 => &.{0x10CD6},
+ 0x10C97 => &.{0x10CD7},
+ 0x10C98 => &.{0x10CD8},
+ 0x10C99 => &.{0x10CD9},
+ 0x10C9A => &.{0x10CDA},
+ 0x10C9B => &.{0x10CDB},
+ 0x10C9C => &.{0x10CDC},
+ 0x10C9D => &.{0x10CDD},
+ 0x10C9E => &.{0x10CDE},
+ 0x10C9F => &.{0x10CDF},
+ 0x10CA0 => &.{0x10CE0},
+ 0x10CA1 => &.{0x10CE1},
+ 0x10CA2 => &.{0x10CE2},
+ 0x10CA3 => &.{0x10CE3},
+ 0x10CA4 => &.{0x10CE4},
+ 0x10CA5 => &.{0x10CE5},
+ 0x10CA6 => &.{0x10CE6},
+ 0x10CA7 => &.{0x10CE7},
+ 0x10CA8 => &.{0x10CE8},
+ 0x10CA9 => &.{0x10CE9},
+ 0x10CAA => &.{0x10CEA},
+ 0x10CAB => &.{0x10CEB},
+ 0x10CAC => &.{0x10CEC},
+ 0x10CAD => &.{0x10CED},
+ 0x10CAE => &.{0x10CEE},
+ 0x10CAF => &.{0x10CEF},
+ 0x10CB0 => &.{0x10CF0},
+ 0x10CB1 => &.{0x10CF1},
+ 0x10CB2 => &.{0x10CF2},
+ 0x118A0 => &.{0x118C0},
+ 0x118A1 => &.{0x118C1},
+ 0x118A2 => &.{0x118C2},
+ 0x118A3 => &.{0x118C3},
+ 0x118A4 => &.{0x118C4},
+ 0x118A5 => &.{0x118C5},
+ 0x118A6 => &.{0x118C6},
+ 0x118A7 => &.{0x118C7},
+ 0x118A8 => &.{0x118C8},
+ 0x118A9 => &.{0x118C9},
+ 0x118AA => &.{0x118CA},
+ 0x118AB => &.{0x118CB},
+ 0x118AC => &.{0x118CC},
+ 0x118AD => &.{0x118CD},
+ 0x118AE => &.{0x118CE},
+ 0x118AF => &.{0x118CF},
+ 0x118B0 => &.{0x118D0},
+ 0x118B1 => &.{0x118D1},
+ 0x118B2 => &.{0x118D2},
+ 0x118B3 => &.{0x118D3},
+ 0x118B4 => &.{0x118D4},
+ 0x118B5 => &.{0x118D5},
+ 0x118B6 => &.{0x118D6},
+ 0x118B7 => &.{0x118D7},
+ 0x118B8 => &.{0x118D8},
+ 0x118B9 => &.{0x118D9},
+ 0x118BA => &.{0x118DA},
+ 0x118BB => &.{0x118DB},
+ 0x118BC => &.{0x118DC},
+ 0x118BD => &.{0x118DD},
+ 0x118BE => &.{0x118DE},
+ 0x118BF => &.{0x118DF},
+ 0x16E40 => &.{0x16E60},
+ 0x16E41 => &.{0x16E61},
+ 0x16E42 => &.{0x16E62},
+ 0x16E43 => &.{0x16E63},
+ 0x16E44 => &.{0x16E64},
+ 0x16E45 => &.{0x16E65},
+ 0x16E46 => &.{0x16E66},
+ 0x16E47 => &.{0x16E67},
+ 0x16E48 => &.{0x16E68},
+ 0x16E49 => &.{0x16E69},
+ 0x16E4A => &.{0x16E6A},
+ 0x16E4B => &.{0x16E6B},
+ 0x16E4C => &.{0x16E6C},
+ 0x16E4D => &.{0x16E6D},
+ 0x16E4E => &.{0x16E6E},
+ 0x16E4F => &.{0x16E6F},
+ 0x16E50 => &.{0x16E70},
+ 0x16E51 => &.{0x16E71},
+ 0x16E52 => &.{0x16E72},
+ 0x16E53 => &.{0x16E73},
+ 0x16E54 => &.{0x16E74},
+ 0x16E55 => &.{0x16E75},
+ 0x16E56 => &.{0x16E76},
+ 0x16E57 => &.{0x16E77},
+ 0x16E58 => &.{0x16E78},
+ 0x16E59 => &.{0x16E79},
+ 0x16E5A => &.{0x16E7A},
+ 0x16E5B => &.{0x16E7B},
+ 0x16E5C => &.{0x16E7C},
+ 0x16E5D => &.{0x16E7D},
+ 0x16E5E => &.{0x16E7E},
+ 0x16E5F => &.{0x16E7F},
+ 0x1E900 => &.{0x1E922},
+ 0x1E901 => &.{0x1E923},
+ 0x1E902 => &.{0x1E924},
+ 0x1E903 => &.{0x1E925},
+ 0x1E904 => &.{0x1E926},
+ 0x1E905 => &.{0x1E927},
+ 0x1E906 => &.{0x1E928},
+ 0x1E907 => &.{0x1E929},
+ 0x1E908 => &.{0x1E92A},
+ 0x1E909 => &.{0x1E92B},
+ 0x1E90A => &.{0x1E92C},
+ 0x1E90B => &.{0x1E92D},
+ 0x1E90C => &.{0x1E92E},
+ 0x1E90D => &.{0x1E92F},
+ 0x1E90E => &.{0x1E930},
+ 0x1E90F => &.{0x1E931},
+ 0x1E910 => &.{0x1E932},
+ 0x1E911 => &.{0x1E933},
+ 0x1E912 => &.{0x1E934},
+ 0x1E913 => &.{0x1E935},
+ 0x1E914 => &.{0x1E936},
+ 0x1E915 => &.{0x1E937},
+ 0x1E916 => &.{0x1E938},
+ 0x1E917 => &.{0x1E939},
+ 0x1E918 => &.{0x1E93A},
+ 0x1E919 => &.{0x1E93B},
+ 0x1E91A => &.{0x1E93C},
+ 0x1E91B => &.{0x1E93D},
+ 0x1E91C => &.{0x1E93E},
+ 0x1E91D => &.{0x1E93F},
+ 0x1E91E => &.{0x1E940},
+ 0x1E91F => &.{0x1E941},
+ 0x1E920 => &.{0x1E942},
+ 0x1E921 => &.{0x1E943},
+ else => &.{cp},
+ };
+
+ var array = [_]u21{0} ** 3;
+ @memcpy(array[0..slice.len], slice);
+
+ return array;
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/derived_combining_class.zig.html b/docs/src/ziglyph/autogen/derived_combining_class.zig.html
new file mode 100644
index 0000000..e69a524
--- /dev/null
+++ b/docs/src/ziglyph/autogen/derived_combining_class.zig.html
@@ -0,0 +1,519 @@
+
+
+
+
+
autogen/derived_combining_class.zig - source view
+
+
+
+
+
+
+
+
+
+
+pub fn combiningClass(cp: u21) u8 {
+ return switch (cp) {
+ 0x334...0x338 => 1,
+ 0x1CD4 => 1,
+ 0x1CE2...0x1CE8 => 1,
+ 0x20D2...0x20D3 => 1,
+ 0x20D8...0x20DA => 1,
+ 0x20E5...0x20E6 => 1,
+ 0x20EA...0x20EB => 1,
+ 0x10A39 => 1,
+ 0x16AF0...0x16AF4 => 1,
+ 0x1BC9E => 1,
+ 0x1D167...0x1D169 => 1,
+ 0x16FF0...0x16FF1 => 6,
+ 0x93C => 7,
+ 0x9BC => 7,
+ 0xA3C => 7,
+ 0xABC => 7,
+ 0xB3C => 7,
+ 0xC3C => 7,
+ 0xCBC => 7,
+ 0x1037 => 7,
+ 0x1B34 => 7,
+ 0x1BE6 => 7,
+ 0x1C37 => 7,
+ 0xA9B3 => 7,
+ 0x110BA => 7,
+ 0x11173 => 7,
+ 0x111CA => 7,
+ 0x11236 => 7,
+ 0x112E9 => 7,
+ 0x1133B...0x1133C => 7,
+ 0x11446 => 7,
+ 0x114C3 => 7,
+ 0x115C0 => 7,
+ 0x116B7 => 7,
+ 0x1183A => 7,
+ 0x11943 => 7,
+ 0x11D42 => 7,
+ 0x1E94A => 7,
+ 0x3099...0x309A => 8,
+ 0x94D => 9,
+ 0x9CD => 9,
+ 0xA4D => 9,
+ 0xACD => 9,
+ 0xB4D => 9,
+ 0xBCD => 9,
+ 0xC4D => 9,
+ 0xCCD => 9,
+ 0xD3B...0xD3C => 9,
+ 0xD4D => 9,
+ 0xDCA => 9,
+ 0xE3A => 9,
+ 0xEBA => 9,
+ 0xF84 => 9,
+ 0x1039...0x103A => 9,
+ 0x1714 => 9,
+ 0x1715 => 9,
+ 0x1734 => 9,
+ 0x17D2 => 9,
+ 0x1A60 => 9,
+ 0x1B44 => 9,
+ 0x1BAA => 9,
+ 0x1BAB => 9,
+ 0x1BF2...0x1BF3 => 9,
+ 0x2D7F => 9,
+ 0xA806 => 9,
+ 0xA82C => 9,
+ 0xA8C4 => 9,
+ 0xA953 => 9,
+ 0xA9C0 => 9,
+ 0xAAF6 => 9,
+ 0xABED => 9,
+ 0x10A3F => 9,
+ 0x11046 => 9,
+ 0x11070 => 9,
+ 0x1107F => 9,
+ 0x110B9 => 9,
+ 0x11133...0x11134 => 9,
+ 0x111C0 => 9,
+ 0x11235 => 9,
+ 0x112EA => 9,
+ 0x1134D => 9,
+ 0x11442 => 9,
+ 0x114C2 => 9,
+ 0x115BF => 9,
+ 0x1163F => 9,
+ 0x116B6 => 9,
+ 0x1172B => 9,
+ 0x11839 => 9,
+ 0x1193D => 9,
+ 0x1193E => 9,
+ 0x119E0 => 9,
+ 0x11A34 => 9,
+ 0x11A47 => 9,
+ 0x11A99 => 9,
+ 0x11C3F => 9,
+ 0x11D44...0x11D45 => 9,
+ 0x11D97 => 9,
+ 0x11F41 => 9,
+ 0x11F42 => 9,
+ 0x5B0 => 10,
+ 0x5B1 => 11,
+ 0x5B2 => 12,
+ 0x5B3 => 13,
+ 0x5B4 => 14,
+ 0x5B5 => 15,
+ 0x5B6 => 16,
+ 0x5B7 => 17,
+ 0x5B8 => 18,
+ 0x5C7 => 18,
+ 0x5B9...0x5BA => 19,
+ 0x5BB => 20,
+ 0x5BC => 21,
+ 0x5BD => 22,
+ 0x5BF => 23,
+ 0x5C1 => 24,
+ 0x5C2 => 25,
+ 0xFB1E => 26,
+ 0x64B => 27,
+ 0x8F0 => 27,
+ 0x64C => 28,
+ 0x8F1 => 28,
+ 0x64D => 29,
+ 0x8F2 => 29,
+ 0x618 => 30,
+ 0x64E => 30,
+ 0x619 => 31,
+ 0x64F => 31,
+ 0x61A => 32,
+ 0x650 => 32,
+ 0x651 => 33,
+ 0x652 => 34,
+ 0x670 => 35,
+ 0x711 => 36,
+ 0xC55 => 84,
+ 0xC56 => 91,
+ 0xE38...0xE39 => 103,
+ 0xE48...0xE4B => 107,
+ 0xEB8...0xEB9 => 118,
+ 0xEC8...0xECB => 122,
+ 0xF71 => 129,
+ 0xF72 => 130,
+ 0xF7A...0xF7D => 130,
+ 0xF80 => 130,
+ 0xF74 => 132,
+ 0x321...0x322 => 202,
+ 0x327...0x328 => 202,
+ 0x1DD0 => 202,
+ 0x1DCE => 214,
+ 0x31B => 216,
+ 0xF39 => 216,
+ 0x1D165...0x1D166 => 216,
+ 0x1D16E...0x1D172 => 216,
+ 0x1DFA => 218,
+ 0x302A => 218,
+ 0x316...0x319 => 220,
+ 0x31C...0x320 => 220,
+ 0x323...0x326 => 220,
+ 0x329...0x333 => 220,
+ 0x339...0x33C => 220,
+ 0x347...0x349 => 220,
+ 0x34D...0x34E => 220,
+ 0x353...0x356 => 220,
+ 0x359...0x35A => 220,
+ 0x591 => 220,
+ 0x596 => 220,
+ 0x59B => 220,
+ 0x5A2...0x5A7 => 220,
+ 0x5AA => 220,
+ 0x5C5 => 220,
+ 0x655...0x656 => 220,
+ 0x65C => 220,
+ 0x65F => 220,
+ 0x6E3 => 220,
+ 0x6EA => 220,
+ 0x6ED => 220,
+ 0x731 => 220,
+ 0x734 => 220,
+ 0x737...0x739 => 220,
+ 0x73B...0x73C => 220,
+ 0x73E => 220,
+ 0x742 => 220,
+ 0x744 => 220,
+ 0x746 => 220,
+ 0x748 => 220,
+ 0x7F2 => 220,
+ 0x7FD => 220,
+ 0x859...0x85B => 220,
+ 0x899...0x89B => 220,
+ 0x8CF...0x8D3 => 220,
+ 0x8E3 => 220,
+ 0x8E6 => 220,
+ 0x8E9 => 220,
+ 0x8ED...0x8EF => 220,
+ 0x8F6 => 220,
+ 0x8F9...0x8FA => 220,
+ 0x952 => 220,
+ 0xF18...0xF19 => 220,
+ 0xF35 => 220,
+ 0xF37 => 220,
+ 0xFC6 => 220,
+ 0x108D => 220,
+ 0x193B => 220,
+ 0x1A18 => 220,
+ 0x1A7F => 220,
+ 0x1AB5...0x1ABA => 220,
+ 0x1ABD => 220,
+ 0x1ABF...0x1AC0 => 220,
+ 0x1AC3...0x1AC4 => 220,
+ 0x1ACA => 220,
+ 0x1B6C => 220,
+ 0x1CD5...0x1CD9 => 220,
+ 0x1CDC...0x1CDF => 220,
+ 0x1CED => 220,
+ 0x1DC2 => 220,
+ 0x1DCA => 220,
+ 0x1DCF => 220,
+ 0x1DF9 => 220,
+ 0x1DFD => 220,
+ 0x1DFF => 220,
+ 0x20E8 => 220,
+ 0x20EC...0x20EF => 220,
+ 0xA92B...0xA92D => 220,
+ 0xAAB4 => 220,
+ 0xFE27...0xFE2D => 220,
+ 0x101FD => 220,
+ 0x102E0 => 220,
+ 0x10A0D => 220,
+ 0x10A3A => 220,
+ 0x10AE6 => 220,
+ 0x10EFD...0x10EFF => 220,
+ 0x10F46...0x10F47 => 220,
+ 0x10F4B => 220,
+ 0x10F4D...0x10F50 => 220,
+ 0x10F83 => 220,
+ 0x10F85 => 220,
+ 0x1D17B...0x1D182 => 220,
+ 0x1D18A...0x1D18B => 220,
+ 0x1E4EE => 220,
+ 0x1E8D0...0x1E8D6 => 220,
+ 0x59A => 222,
+ 0x5AD => 222,
+ 0x1939 => 222,
+ 0x302D => 222,
+ 0x302E...0x302F => 224,
+ 0x1D16D => 226,
+ 0x5AE => 228,
+ 0x18A9 => 228,
+ 0x1DF7...0x1DF8 => 228,
+ 0x302B => 228,
+ 0x300...0x314 => 230,
+ 0x33D...0x344 => 230,
+ 0x346 => 230,
+ 0x34A...0x34C => 230,
+ 0x350...0x352 => 230,
+ 0x357 => 230,
+ 0x35B => 230,
+ 0x363...0x36F => 230,
+ 0x483...0x487 => 230,
+ 0x592...0x595 => 230,
+ 0x597...0x599 => 230,
+ 0x59C...0x5A1 => 230,
+ 0x5A8...0x5A9 => 230,
+ 0x5AB...0x5AC => 230,
+ 0x5AF => 230,
+ 0x5C4 => 230,
+ 0x610...0x617 => 230,
+ 0x653...0x654 => 230,
+ 0x657...0x65B => 230,
+ 0x65D...0x65E => 230,
+ 0x6D6...0x6DC => 230,
+ 0x6DF...0x6E2 => 230,
+ 0x6E4 => 230,
+ 0x6E7...0x6E8 => 230,
+ 0x6EB...0x6EC => 230,
+ 0x730 => 230,
+ 0x732...0x733 => 230,
+ 0x735...0x736 => 230,
+ 0x73A => 230,
+ 0x73D => 230,
+ 0x73F...0x741 => 230,
+ 0x743 => 230,
+ 0x745 => 230,
+ 0x747 => 230,
+ 0x749...0x74A => 230,
+ 0x7EB...0x7F1 => 230,
+ 0x7F3 => 230,
+ 0x816...0x819 => 230,
+ 0x81B...0x823 => 230,
+ 0x825...0x827 => 230,
+ 0x829...0x82D => 230,
+ 0x898 => 230,
+ 0x89C...0x89F => 230,
+ 0x8CA...0x8CE => 230,
+ 0x8D4...0x8E1 => 230,
+ 0x8E4...0x8E5 => 230,
+ 0x8E7...0x8E8 => 230,
+ 0x8EA...0x8EC => 230,
+ 0x8F3...0x8F5 => 230,
+ 0x8F7...0x8F8 => 230,
+ 0x8FB...0x8FF => 230,
+ 0x951 => 230,
+ 0x953...0x954 => 230,
+ 0x9FE => 230,
+ 0xF82...0xF83 => 230,
+ 0xF86...0xF87 => 230,
+ 0x135D...0x135F => 230,
+ 0x17DD => 230,
+ 0x193A => 230,
+ 0x1A17 => 230,
+ 0x1A75...0x1A7C => 230,
+ 0x1AB0...0x1AB4 => 230,
+ 0x1ABB...0x1ABC => 230,
+ 0x1AC1...0x1AC2 => 230,
+ 0x1AC5...0x1AC9 => 230,
+ 0x1ACB...0x1ACE => 230,
+ 0x1B6B => 230,
+ 0x1B6D...0x1B73 => 230,
+ 0x1CD0...0x1CD2 => 230,
+ 0x1CDA...0x1CDB => 230,
+ 0x1CE0 => 230,
+ 0x1CF4 => 230,
+ 0x1CF8...0x1CF9 => 230,
+ 0x1DC0...0x1DC1 => 230,
+ 0x1DC3...0x1DC9 => 230,
+ 0x1DCB...0x1DCC => 230,
+ 0x1DD1...0x1DF5 => 230,
+ 0x1DFB => 230,
+ 0x1DFE => 230,
+ 0x20D0...0x20D1 => 230,
+ 0x20D4...0x20D7 => 230,
+ 0x20DB...0x20DC => 230,
+ 0x20E1 => 230,
+ 0x20E7 => 230,
+ 0x20E9 => 230,
+ 0x20F0 => 230,
+ 0x2CEF...0x2CF1 => 230,
+ 0x2DE0...0x2DFF => 230,
+ 0xA66F => 230,
+ 0xA674...0xA67D => 230,
+ 0xA69E...0xA69F => 230,
+ 0xA6F0...0xA6F1 => 230,
+ 0xA8E0...0xA8F1 => 230,
+ 0xAAB0 => 230,
+ 0xAAB2...0xAAB3 => 230,
+ 0xAAB7...0xAAB8 => 230,
+ 0xAABE...0xAABF => 230,
+ 0xAAC1 => 230,
+ 0xFE20...0xFE26 => 230,
+ 0xFE2E...0xFE2F => 230,
+ 0x10376...0x1037A => 230,
+ 0x10A0F => 230,
+ 0x10A38 => 230,
+ 0x10AE5 => 230,
+ 0x10D24...0x10D27 => 230,
+ 0x10EAB...0x10EAC => 230,
+ 0x10F48...0x10F4A => 230,
+ 0x10F4C => 230,
+ 0x10F82 => 230,
+ 0x10F84 => 230,
+ 0x11100...0x11102 => 230,
+ 0x11366...0x1136C => 230,
+ 0x11370...0x11374 => 230,
+ 0x1145E => 230,
+ 0x16B30...0x16B36 => 230,
+ 0x1D185...0x1D189 => 230,
+ 0x1D1AA...0x1D1AD => 230,
+ 0x1D242...0x1D244 => 230,
+ 0x1E000...0x1E006 => 230,
+ 0x1E008...0x1E018 => 230,
+ 0x1E01B...0x1E021 => 230,
+ 0x1E023...0x1E024 => 230,
+ 0x1E026...0x1E02A => 230,
+ 0x1E08F => 230,
+ 0x1E130...0x1E136 => 230,
+ 0x1E2AE => 230,
+ 0x1E2EC...0x1E2EF => 230,
+ 0x1E4EF => 230,
+ 0x1E944...0x1E949 => 230,
+ 0x315 => 232,
+ 0x31A => 232,
+ 0x358 => 232,
+ 0x1DF6 => 232,
+ 0x302C => 232,
+ 0x1E4EC...0x1E4ED => 232,
+ 0x35C => 233,
+ 0x35F => 233,
+ 0x362 => 233,
+ 0x1DFC => 233,
+ 0x35D...0x35E => 234,
+ 0x360...0x361 => 234,
+ 0x1DCD => 234,
+ 0x345 => 240,
+ else => 0,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/derived_core_properties.zig.html b/docs/src/ziglyph/autogen/derived_core_properties.zig.html
new file mode 100644
index 0000000..bb63f84
--- /dev/null
+++ b/docs/src/ziglyph/autogen/derived_core_properties.zig.html
@@ -0,0 +1,12637 @@
+
+
+
+
+
autogen/derived_core_properties.zig - source view
+
+
+
+
+
+
+
+
+pub fn isMath(cp: u21) bool {
+ if (cp < 0x2b or cp > 0x1eef1) return false;
+
+ return switch (cp) {
+ 0x2b => true,
+ 0x3c...0x3e => true,
+ 0x5e => true,
+ 0x7c => true,
+ 0x7e => true,
+ 0xac => true,
+ 0xb1 => true,
+ 0xd7 => true,
+ 0xf7 => true,
+ 0x3d0...0x3d2 => true,
+ 0x3d5 => true,
+ 0x3f0...0x3f1 => true,
+ 0x3f4...0x3f5 => true,
+ 0x3f6 => true,
+ 0x606...0x608 => true,
+ 0x2016 => true,
+ 0x2032...0x2034 => true,
+ 0x2040 => true,
+ 0x2044 => true,
+ 0x2052 => true,
+ 0x2061...0x2064 => true,
+ 0x207a...0x207c => true,
+ 0x207d => true,
+ 0x207e => true,
+ 0x208a...0x208c => true,
+ 0x208d => true,
+ 0x208e => true,
+ 0x20d0...0x20dc => true,
+ 0x20e1 => true,
+ 0x20e5...0x20e6 => true,
+ 0x20eb...0x20ef => true,
+ 0x2102 => true,
+ 0x2107 => true,
+ 0x210a...0x2113 => true,
+ 0x2115 => true,
+ 0x2118 => true,
+ 0x2119...0x211d => true,
+ 0x2124 => true,
+ 0x2128 => true,
+ 0x2129 => true,
+ 0x212c...0x212d => true,
+ 0x212f...0x2131 => true,
+ 0x2133...0x2134 => true,
+ 0x2135...0x2138 => true,
+ 0x213c...0x213f => true,
+ 0x2140...0x2144 => true,
+ 0x2145...0x2149 => true,
+ 0x214b => true,
+ 0x2190...0x2194 => true,
+ 0x2195...0x2199 => true,
+ 0x219a...0x219b => true,
+ 0x219c...0x219f => true,
+ 0x21a0 => true,
+ 0x21a1...0x21a2 => true,
+ 0x21a3 => true,
+ 0x21a4...0x21a5 => true,
+ 0x21a6 => true,
+ 0x21a7 => true,
+ 0x21a9...0x21ad => true,
+ 0x21ae => true,
+ 0x21b0...0x21b1 => true,
+ 0x21b6...0x21b7 => true,
+ 0x21bc...0x21cd => true,
+ 0x21ce...0x21cf => true,
+ 0x21d0...0x21d1 => true,
+ 0x21d2 => true,
+ 0x21d3 => true,
+ 0x21d4 => true,
+ 0x21d5...0x21db => true,
+ 0x21dd => true,
+ 0x21e4...0x21e5 => true,
+ 0x21f4...0x22ff => true,
+ 0x2308 => true,
+ 0x2309 => true,
+ 0x230a => true,
+ 0x230b => true,
+ 0x2320...0x2321 => true,
+ 0x237c => true,
+ 0x239b...0x23b3 => true,
+ 0x23b4...0x23b5 => true,
+ 0x23b7 => true,
+ 0x23d0 => true,
+ 0x23dc...0x23e1 => true,
+ 0x23e2 => true,
+ 0x25a0...0x25a1 => true,
+ 0x25ae...0x25b6 => true,
+ 0x25b7 => true,
+ 0x25bc...0x25c0 => true,
+ 0x25c1 => true,
+ 0x25c6...0x25c7 => true,
+ 0x25ca...0x25cb => true,
+ 0x25cf...0x25d3 => true,
+ 0x25e2 => true,
+ 0x25e4 => true,
+ 0x25e7...0x25ec => true,
+ 0x25f8...0x25ff => true,
+ 0x2605...0x2606 => true,
+ 0x2640 => true,
+ 0x2642 => true,
+ 0x2660...0x2663 => true,
+ 0x266d...0x266e => true,
+ 0x266f => true,
+ 0x27c0...0x27c4 => true,
+ 0x27c5 => true,
+ 0x27c6 => true,
+ 0x27c7...0x27e5 => true,
+ 0x27e6 => true,
+ 0x27e7 => true,
+ 0x27e8 => true,
+ 0x27e9 => true,
+ 0x27ea => true,
+ 0x27eb => true,
+ 0x27ec => true,
+ 0x27ed => true,
+ 0x27ee => true,
+ 0x27ef => true,
+ 0x27f0...0x27ff => true,
+ 0x2900...0x2982 => true,
+ 0x2983 => true,
+ 0x2984 => true,
+ 0x2985 => true,
+ 0x2986 => true,
+ 0x2987 => true,
+ 0x2988 => true,
+ 0x2989 => true,
+ 0x298a => true,
+ 0x298b => true,
+ 0x298c => true,
+ 0x298d => true,
+ 0x298e => true,
+ 0x298f => true,
+ 0x2990 => true,
+ 0x2991 => true,
+ 0x2992 => true,
+ 0x2993 => true,
+ 0x2994 => true,
+ 0x2995 => true,
+ 0x2996 => true,
+ 0x2997 => true,
+ 0x2998 => true,
+ 0x2999...0x29d7 => true,
+ 0x29d8 => true,
+ 0x29d9 => true,
+ 0x29da => true,
+ 0x29db => true,
+ 0x29dc...0x29fb => true,
+ 0x29fc => true,
+ 0x29fd => true,
+ 0x29fe...0x2aff => true,
+ 0x2b30...0x2b44 => true,
+ 0x2b47...0x2b4c => true,
+ 0xfb29 => true,
+ 0xfe61 => true,
+ 0xfe62 => true,
+ 0xfe63 => true,
+ 0xfe64...0xfe66 => true,
+ 0xfe68 => true,
+ 0xff0b => true,
+ 0xff1c...0xff1e => true,
+ 0xff3c => true,
+ 0xff3e => true,
+ 0xff5c => true,
+ 0xff5e => true,
+ 0xffe2 => true,
+ 0xffe9...0xffec => true,
+ 0x1d400...0x1d454 => true,
+ 0x1d456...0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d51e...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d552...0x1d6a5 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6c1 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6db => true,
+ 0x1d6dc...0x1d6fa => true,
+ 0x1d6fb => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d715 => true,
+ 0x1d716...0x1d734 => true,
+ 0x1d735 => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d74f => true,
+ 0x1d750...0x1d76e => true,
+ 0x1d76f => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d789 => true,
+ 0x1d78a...0x1d7a8 => true,
+ 0x1d7a9 => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c3 => true,
+ 0x1d7c4...0x1d7cb => true,
+ 0x1d7ce...0x1d7ff => true,
+ 0x1ee00...0x1ee03 => true,
+ 0x1ee05...0x1ee1f => true,
+ 0x1ee21...0x1ee22 => true,
+ 0x1ee24 => true,
+ 0x1ee27 => true,
+ 0x1ee29...0x1ee32 => true,
+ 0x1ee34...0x1ee37 => true,
+ 0x1ee39 => true,
+ 0x1ee3b => true,
+ 0x1ee42 => true,
+ 0x1ee47 => true,
+ 0x1ee49 => true,
+ 0x1ee4b => true,
+ 0x1ee4d...0x1ee4f => true,
+ 0x1ee51...0x1ee52 => true,
+ 0x1ee54 => true,
+ 0x1ee57 => true,
+ 0x1ee59 => true,
+ 0x1ee5b => true,
+ 0x1ee5d => true,
+ 0x1ee5f => true,
+ 0x1ee61...0x1ee62 => true,
+ 0x1ee64 => true,
+ 0x1ee67...0x1ee6a => true,
+ 0x1ee6c...0x1ee72 => true,
+ 0x1ee74...0x1ee77 => true,
+ 0x1ee79...0x1ee7c => true,
+ 0x1ee7e => true,
+ 0x1ee80...0x1ee89 => true,
+ 0x1ee8b...0x1ee9b => true,
+ 0x1eea1...0x1eea3 => true,
+ 0x1eea5...0x1eea9 => true,
+ 0x1eeab...0x1eebb => true,
+ 0x1eef0...0x1eef1 => true,
+ else => false,
+ };
+}
+
+pub fn isAlphabetic(cp: u21) bool {
+ if (cp < 0x41 or cp > 0x323af) return false;
+
+ return switch (cp) {
+ 0x41...0x5a => true,
+ 0x61...0x7a => true,
+ 0xaa => true,
+ 0xb5 => true,
+ 0xba => true,
+ 0xc0...0xd6 => true,
+ 0xd8...0xf6 => true,
+ 0xf8...0x1ba => true,
+ 0x1bb => true,
+ 0x1bc...0x1bf => true,
+ 0x1c0...0x1c3 => true,
+ 0x1c4...0x293 => true,
+ 0x294 => true,
+ 0x295...0x2af => true,
+ 0x2b0...0x2c1 => true,
+ 0x2c6...0x2d1 => true,
+ 0x2e0...0x2e4 => true,
+ 0x2ec => true,
+ 0x2ee => true,
+ 0x345 => true,
+ 0x370...0x373 => true,
+ 0x374 => true,
+ 0x376...0x377 => true,
+ 0x37a => true,
+ 0x37b...0x37d => true,
+ 0x37f => true,
+ 0x386 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x3a1 => true,
+ 0x3a3...0x3f5 => true,
+ 0x3f7...0x481 => true,
+ 0x48a...0x52f => true,
+ 0x531...0x556 => true,
+ 0x559 => true,
+ 0x560...0x588 => true,
+ 0x5b0...0x5bd => true,
+ 0x5bf => true,
+ 0x5c1...0x5c2 => true,
+ 0x5c4...0x5c5 => true,
+ 0x5c7 => true,
+ 0x5d0...0x5ea => true,
+ 0x5ef...0x5f2 => true,
+ 0x610...0x61a => true,
+ 0x620...0x63f => true,
+ 0x640 => true,
+ 0x641...0x64a => true,
+ 0x64b...0x657 => true,
+ 0x659...0x65f => true,
+ 0x66e...0x66f => true,
+ 0x670 => true,
+ 0x671...0x6d3 => true,
+ 0x6d5 => true,
+ 0x6d6...0x6dc => true,
+ 0x6e1...0x6e4 => true,
+ 0x6e5...0x6e6 => true,
+ 0x6e7...0x6e8 => true,
+ 0x6ed => true,
+ 0x6ee...0x6ef => true,
+ 0x6fa...0x6fc => true,
+ 0x6ff => true,
+ 0x710 => true,
+ 0x711 => true,
+ 0x712...0x72f => true,
+ 0x730...0x73f => true,
+ 0x74d...0x7a5 => true,
+ 0x7a6...0x7b0 => true,
+ 0x7b1 => true,
+ 0x7ca...0x7ea => true,
+ 0x7f4...0x7f5 => true,
+ 0x7fa => true,
+ 0x800...0x815 => true,
+ 0x816...0x817 => true,
+ 0x81a => true,
+ 0x81b...0x823 => true,
+ 0x824 => true,
+ 0x825...0x827 => true,
+ 0x828 => true,
+ 0x829...0x82c => true,
+ 0x840...0x858 => true,
+ 0x860...0x86a => true,
+ 0x870...0x887 => true,
+ 0x889...0x88e => true,
+ 0x8a0...0x8c8 => true,
+ 0x8c9 => true,
+ 0x8d4...0x8df => true,
+ 0x8e3...0x8e9 => true,
+ 0x8f0...0x902 => true,
+ 0x903 => true,
+ 0x904...0x939 => true,
+ 0x93a => true,
+ 0x93b => true,
+ 0x93d => true,
+ 0x93e...0x940 => true,
+ 0x941...0x948 => true,
+ 0x949...0x94c => true,
+ 0x94e...0x94f => true,
+ 0x950 => true,
+ 0x955...0x957 => true,
+ 0x958...0x961 => true,
+ 0x962...0x963 => true,
+ 0x971 => true,
+ 0x972...0x980 => true,
+ 0x981 => true,
+ 0x982...0x983 => true,
+ 0x985...0x98c => true,
+ 0x98f...0x990 => true,
+ 0x993...0x9a8 => true,
+ 0x9aa...0x9b0 => true,
+ 0x9b2 => true,
+ 0x9b6...0x9b9 => true,
+ 0x9bd => true,
+ 0x9be...0x9c0 => true,
+ 0x9c1...0x9c4 => true,
+ 0x9c7...0x9c8 => true,
+ 0x9cb...0x9cc => true,
+ 0x9ce => true,
+ 0x9d7 => true,
+ 0x9dc...0x9dd => true,
+ 0x9df...0x9e1 => true,
+ 0x9e2...0x9e3 => true,
+ 0x9f0...0x9f1 => true,
+ 0x9fc => true,
+ 0xa01...0xa02 => true,
+ 0xa03 => true,
+ 0xa05...0xa0a => true,
+ 0xa0f...0xa10 => true,
+ 0xa13...0xa28 => true,
+ 0xa2a...0xa30 => true,
+ 0xa32...0xa33 => true,
+ 0xa35...0xa36 => true,
+ 0xa38...0xa39 => true,
+ 0xa3e...0xa40 => true,
+ 0xa41...0xa42 => true,
+ 0xa47...0xa48 => true,
+ 0xa4b...0xa4c => true,
+ 0xa51 => true,
+ 0xa59...0xa5c => true,
+ 0xa5e => true,
+ 0xa70...0xa71 => true,
+ 0xa72...0xa74 => true,
+ 0xa75 => true,
+ 0xa81...0xa82 => true,
+ 0xa83 => true,
+ 0xa85...0xa8d => true,
+ 0xa8f...0xa91 => true,
+ 0xa93...0xaa8 => true,
+ 0xaaa...0xab0 => true,
+ 0xab2...0xab3 => true,
+ 0xab5...0xab9 => true,
+ 0xabd => true,
+ 0xabe...0xac0 => true,
+ 0xac1...0xac5 => true,
+ 0xac7...0xac8 => true,
+ 0xac9 => true,
+ 0xacb...0xacc => true,
+ 0xad0 => true,
+ 0xae0...0xae1 => true,
+ 0xae2...0xae3 => true,
+ 0xaf9 => true,
+ 0xafa...0xafc => true,
+ 0xb01 => true,
+ 0xb02...0xb03 => true,
+ 0xb05...0xb0c => true,
+ 0xb0f...0xb10 => true,
+ 0xb13...0xb28 => true,
+ 0xb2a...0xb30 => true,
+ 0xb32...0xb33 => true,
+ 0xb35...0xb39 => true,
+ 0xb3d => true,
+ 0xb3e => true,
+ 0xb3f => true,
+ 0xb40 => true,
+ 0xb41...0xb44 => true,
+ 0xb47...0xb48 => true,
+ 0xb4b...0xb4c => true,
+ 0xb56 => true,
+ 0xb57 => true,
+ 0xb5c...0xb5d => true,
+ 0xb5f...0xb61 => true,
+ 0xb62...0xb63 => true,
+ 0xb71 => true,
+ 0xb82 => true,
+ 0xb83 => true,
+ 0xb85...0xb8a => true,
+ 0xb8e...0xb90 => true,
+ 0xb92...0xb95 => true,
+ 0xb99...0xb9a => true,
+ 0xb9c => true,
+ 0xb9e...0xb9f => true,
+ 0xba3...0xba4 => true,
+ 0xba8...0xbaa => true,
+ 0xbae...0xbb9 => true,
+ 0xbbe...0xbbf => true,
+ 0xbc0 => true,
+ 0xbc1...0xbc2 => true,
+ 0xbc6...0xbc8 => true,
+ 0xbca...0xbcc => true,
+ 0xbd0 => true,
+ 0xbd7 => true,
+ 0xc00 => true,
+ 0xc01...0xc03 => true,
+ 0xc04 => true,
+ 0xc05...0xc0c => true,
+ 0xc0e...0xc10 => true,
+ 0xc12...0xc28 => true,
+ 0xc2a...0xc39 => true,
+ 0xc3d => true,
+ 0xc3e...0xc40 => true,
+ 0xc41...0xc44 => true,
+ 0xc46...0xc48 => true,
+ 0xc4a...0xc4c => true,
+ 0xc55...0xc56 => true,
+ 0xc58...0xc5a => true,
+ 0xc5d => true,
+ 0xc60...0xc61 => true,
+ 0xc62...0xc63 => true,
+ 0xc80 => true,
+ 0xc81 => true,
+ 0xc82...0xc83 => true,
+ 0xc85...0xc8c => true,
+ 0xc8e...0xc90 => true,
+ 0xc92...0xca8 => true,
+ 0xcaa...0xcb3 => true,
+ 0xcb5...0xcb9 => true,
+ 0xcbd => true,
+ 0xcbe => true,
+ 0xcbf => true,
+ 0xcc0...0xcc4 => true,
+ 0xcc6 => true,
+ 0xcc7...0xcc8 => true,
+ 0xcca...0xccb => true,
+ 0xccc => true,
+ 0xcd5...0xcd6 => true,
+ 0xcdd...0xcde => true,
+ 0xce0...0xce1 => true,
+ 0xce2...0xce3 => true,
+ 0xcf1...0xcf2 => true,
+ 0xcf3 => true,
+ 0xd00...0xd01 => true,
+ 0xd02...0xd03 => true,
+ 0xd04...0xd0c => true,
+ 0xd0e...0xd10 => true,
+ 0xd12...0xd3a => true,
+ 0xd3d => true,
+ 0xd3e...0xd40 => true,
+ 0xd41...0xd44 => true,
+ 0xd46...0xd48 => true,
+ 0xd4a...0xd4c => true,
+ 0xd4e => true,
+ 0xd54...0xd56 => true,
+ 0xd57 => true,
+ 0xd5f...0xd61 => true,
+ 0xd62...0xd63 => true,
+ 0xd7a...0xd7f => true,
+ 0xd81 => true,
+ 0xd82...0xd83 => true,
+ 0xd85...0xd96 => true,
+ 0xd9a...0xdb1 => true,
+ 0xdb3...0xdbb => true,
+ 0xdbd => true,
+ 0xdc0...0xdc6 => true,
+ 0xdcf...0xdd1 => true,
+ 0xdd2...0xdd4 => true,
+ 0xdd6 => true,
+ 0xdd8...0xddf => true,
+ 0xdf2...0xdf3 => true,
+ 0xe01...0xe30 => true,
+ 0xe31 => true,
+ 0xe32...0xe33 => true,
+ 0xe34...0xe3a => true,
+ 0xe40...0xe45 => true,
+ 0xe46 => true,
+ 0xe4d => true,
+ 0xe81...0xe82 => true,
+ 0xe84 => true,
+ 0xe86...0xe8a => true,
+ 0xe8c...0xea3 => true,
+ 0xea5 => true,
+ 0xea7...0xeb0 => true,
+ 0xeb1 => true,
+ 0xeb2...0xeb3 => true,
+ 0xeb4...0xeb9 => true,
+ 0xebb...0xebc => true,
+ 0xebd => true,
+ 0xec0...0xec4 => true,
+ 0xec6 => true,
+ 0xecd => true,
+ 0xedc...0xedf => true,
+ 0xf00 => true,
+ 0xf40...0xf47 => true,
+ 0xf49...0xf6c => true,
+ 0xf71...0xf7e => true,
+ 0xf7f => true,
+ 0xf80...0xf83 => true,
+ 0xf88...0xf8c => true,
+ 0xf8d...0xf97 => true,
+ 0xf99...0xfbc => true,
+ 0x1000...0x102a => true,
+ 0x102b...0x102c => true,
+ 0x102d...0x1030 => true,
+ 0x1031 => true,
+ 0x1032...0x1036 => true,
+ 0x1038 => true,
+ 0x103b...0x103c => true,
+ 0x103d...0x103e => true,
+ 0x103f => true,
+ 0x1050...0x1055 => true,
+ 0x1056...0x1057 => true,
+ 0x1058...0x1059 => true,
+ 0x105a...0x105d => true,
+ 0x105e...0x1060 => true,
+ 0x1061 => true,
+ 0x1062...0x1064 => true,
+ 0x1065...0x1066 => true,
+ 0x1067...0x106d => true,
+ 0x106e...0x1070 => true,
+ 0x1071...0x1074 => true,
+ 0x1075...0x1081 => true,
+ 0x1082 => true,
+ 0x1083...0x1084 => true,
+ 0x1085...0x1086 => true,
+ 0x1087...0x108c => true,
+ 0x108d => true,
+ 0x108e => true,
+ 0x108f => true,
+ 0x109a...0x109c => true,
+ 0x109d => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x10d0...0x10fa => true,
+ 0x10fc => true,
+ 0x10fd...0x10ff => true,
+ 0x1100...0x1248 => true,
+ 0x124a...0x124d => true,
+ 0x1250...0x1256 => true,
+ 0x1258 => true,
+ 0x125a...0x125d => true,
+ 0x1260...0x1288 => true,
+ 0x128a...0x128d => true,
+ 0x1290...0x12b0 => true,
+ 0x12b2...0x12b5 => true,
+ 0x12b8...0x12be => true,
+ 0x12c0 => true,
+ 0x12c2...0x12c5 => true,
+ 0x12c8...0x12d6 => true,
+ 0x12d8...0x1310 => true,
+ 0x1312...0x1315 => true,
+ 0x1318...0x135a => true,
+ 0x1380...0x138f => true,
+ 0x13a0...0x13f5 => true,
+ 0x13f8...0x13fd => true,
+ 0x1401...0x166c => true,
+ 0x166f...0x167f => true,
+ 0x1681...0x169a => true,
+ 0x16a0...0x16ea => true,
+ 0x16ee...0x16f0 => true,
+ 0x16f1...0x16f8 => true,
+ 0x1700...0x1711 => true,
+ 0x1712...0x1713 => true,
+ 0x171f...0x1731 => true,
+ 0x1732...0x1733 => true,
+ 0x1740...0x1751 => true,
+ 0x1752...0x1753 => true,
+ 0x1760...0x176c => true,
+ 0x176e...0x1770 => true,
+ 0x1772...0x1773 => true,
+ 0x1780...0x17b3 => true,
+ 0x17b6 => true,
+ 0x17b7...0x17bd => true,
+ 0x17be...0x17c5 => true,
+ 0x17c6 => true,
+ 0x17c7...0x17c8 => true,
+ 0x17d7 => true,
+ 0x17dc => true,
+ 0x1820...0x1842 => true,
+ 0x1843 => true,
+ 0x1844...0x1878 => true,
+ 0x1880...0x1884 => true,
+ 0x1885...0x1886 => true,
+ 0x1887...0x18a8 => true,
+ 0x18a9 => true,
+ 0x18aa => true,
+ 0x18b0...0x18f5 => true,
+ 0x1900...0x191e => true,
+ 0x1920...0x1922 => true,
+ 0x1923...0x1926 => true,
+ 0x1927...0x1928 => true,
+ 0x1929...0x192b => true,
+ 0x1930...0x1931 => true,
+ 0x1932 => true,
+ 0x1933...0x1938 => true,
+ 0x1950...0x196d => true,
+ 0x1970...0x1974 => true,
+ 0x1980...0x19ab => true,
+ 0x19b0...0x19c9 => true,
+ 0x1a00...0x1a16 => true,
+ 0x1a17...0x1a18 => true,
+ 0x1a19...0x1a1a => true,
+ 0x1a1b => true,
+ 0x1a20...0x1a54 => true,
+ 0x1a55 => true,
+ 0x1a56 => true,
+ 0x1a57 => true,
+ 0x1a58...0x1a5e => true,
+ 0x1a61 => true,
+ 0x1a62 => true,
+ 0x1a63...0x1a64 => true,
+ 0x1a65...0x1a6c => true,
+ 0x1a6d...0x1a72 => true,
+ 0x1a73...0x1a74 => true,
+ 0x1aa7 => true,
+ 0x1abf...0x1ac0 => true,
+ 0x1acc...0x1ace => true,
+ 0x1b00...0x1b03 => true,
+ 0x1b04 => true,
+ 0x1b05...0x1b33 => true,
+ 0x1b35 => true,
+ 0x1b36...0x1b3a => true,
+ 0x1b3b => true,
+ 0x1b3c => true,
+ 0x1b3d...0x1b41 => true,
+ 0x1b42 => true,
+ 0x1b43 => true,
+ 0x1b45...0x1b4c => true,
+ 0x1b80...0x1b81 => true,
+ 0x1b82 => true,
+ 0x1b83...0x1ba0 => true,
+ 0x1ba1 => true,
+ 0x1ba2...0x1ba5 => true,
+ 0x1ba6...0x1ba7 => true,
+ 0x1ba8...0x1ba9 => true,
+ 0x1bac...0x1bad => true,
+ 0x1bae...0x1baf => true,
+ 0x1bba...0x1be5 => true,
+ 0x1be7 => true,
+ 0x1be8...0x1be9 => true,
+ 0x1bea...0x1bec => true,
+ 0x1bed => true,
+ 0x1bee => true,
+ 0x1bef...0x1bf1 => true,
+ 0x1c00...0x1c23 => true,
+ 0x1c24...0x1c2b => true,
+ 0x1c2c...0x1c33 => true,
+ 0x1c34...0x1c35 => true,
+ 0x1c36 => true,
+ 0x1c4d...0x1c4f => true,
+ 0x1c5a...0x1c77 => true,
+ 0x1c78...0x1c7d => true,
+ 0x1c80...0x1c88 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1ce9...0x1cec => true,
+ 0x1cee...0x1cf3 => true,
+ 0x1cf5...0x1cf6 => true,
+ 0x1cfa => true,
+ 0x1d00...0x1d2b => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d6b...0x1d77 => true,
+ 0x1d78 => true,
+ 0x1d79...0x1d9a => true,
+ 0x1d9b...0x1dbf => true,
+ 0x1de7...0x1df4 => true,
+ 0x1e00...0x1f15 => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f20...0x1f45 => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f...0x1f7d => true,
+ 0x1f80...0x1fb4 => true,
+ 0x1fb6...0x1fbc => true,
+ 0x1fbe => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fcc => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fdb => true,
+ 0x1fe0...0x1fec => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ffc => true,
+ 0x2071 => true,
+ 0x207f => true,
+ 0x2090...0x209c => true,
+ 0x2102 => true,
+ 0x2107 => true,
+ 0x210a...0x2113 => true,
+ 0x2115 => true,
+ 0x2119...0x211d => true,
+ 0x2124 => true,
+ 0x2126 => true,
+ 0x2128 => true,
+ 0x212a...0x212d => true,
+ 0x212f...0x2134 => true,
+ 0x2135...0x2138 => true,
+ 0x2139 => true,
+ 0x213c...0x213f => true,
+ 0x2145...0x2149 => true,
+ 0x214e => true,
+ 0x2160...0x2182 => true,
+ 0x2183...0x2184 => true,
+ 0x2185...0x2188 => true,
+ 0x24b6...0x24e9 => true,
+ 0x2c00...0x2c7b => true,
+ 0x2c7c...0x2c7d => true,
+ 0x2c7e...0x2ce4 => true,
+ 0x2ceb...0x2cee => true,
+ 0x2cf2...0x2cf3 => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0x2d30...0x2d67 => true,
+ 0x2d6f => true,
+ 0x2d80...0x2d96 => true,
+ 0x2da0...0x2da6 => true,
+ 0x2da8...0x2dae => true,
+ 0x2db0...0x2db6 => true,
+ 0x2db8...0x2dbe => true,
+ 0x2dc0...0x2dc6 => true,
+ 0x2dc8...0x2dce => true,
+ 0x2dd0...0x2dd6 => true,
+ 0x2dd8...0x2dde => true,
+ 0x2de0...0x2dff => true,
+ 0x2e2f => true,
+ 0x3005 => true,
+ 0x3006 => true,
+ 0x3007 => true,
+ 0x3021...0x3029 => true,
+ 0x3031...0x3035 => true,
+ 0x3038...0x303a => true,
+ 0x303b => true,
+ 0x303c => true,
+ 0x3041...0x3096 => true,
+ 0x309d...0x309e => true,
+ 0x309f => true,
+ 0x30a1...0x30fa => true,
+ 0x30fc...0x30fe => true,
+ 0x30ff => true,
+ 0x3105...0x312f => true,
+ 0x3131...0x318e => true,
+ 0x31a0...0x31bf => true,
+ 0x31f0...0x31ff => true,
+ 0x3400...0x4dbf => true,
+ 0x4e00...0xa014 => true,
+ 0xa015 => true,
+ 0xa016...0xa48c => true,
+ 0xa4d0...0xa4f7 => true,
+ 0xa4f8...0xa4fd => true,
+ 0xa500...0xa60b => true,
+ 0xa60c => true,
+ 0xa610...0xa61f => true,
+ 0xa62a...0xa62b => true,
+ 0xa640...0xa66d => true,
+ 0xa66e => true,
+ 0xa674...0xa67b => true,
+ 0xa67f => true,
+ 0xa680...0xa69b => true,
+ 0xa69c...0xa69d => true,
+ 0xa69e...0xa69f => true,
+ 0xa6a0...0xa6e5 => true,
+ 0xa6e6...0xa6ef => true,
+ 0xa717...0xa71f => true,
+ 0xa722...0xa76f => true,
+ 0xa770 => true,
+ 0xa771...0xa787 => true,
+ 0xa788 => true,
+ 0xa78b...0xa78e => true,
+ 0xa78f => true,
+ 0xa790...0xa7ca => true,
+ 0xa7d0...0xa7d1 => true,
+ 0xa7d3 => true,
+ 0xa7d5...0xa7d9 => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f5...0xa7f6 => true,
+ 0xa7f7 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa7fa => true,
+ 0xa7fb...0xa801 => true,
+ 0xa802 => true,
+ 0xa803...0xa805 => true,
+ 0xa807...0xa80a => true,
+ 0xa80b => true,
+ 0xa80c...0xa822 => true,
+ 0xa823...0xa824 => true,
+ 0xa825...0xa826 => true,
+ 0xa827 => true,
+ 0xa840...0xa873 => true,
+ 0xa880...0xa881 => true,
+ 0xa882...0xa8b3 => true,
+ 0xa8b4...0xa8c3 => true,
+ 0xa8c5 => true,
+ 0xa8f2...0xa8f7 => true,
+ 0xa8fb => true,
+ 0xa8fd...0xa8fe => true,
+ 0xa8ff => true,
+ 0xa90a...0xa925 => true,
+ 0xa926...0xa92a => true,
+ 0xa930...0xa946 => true,
+ 0xa947...0xa951 => true,
+ 0xa952 => true,
+ 0xa960...0xa97c => true,
+ 0xa980...0xa982 => true,
+ 0xa983 => true,
+ 0xa984...0xa9b2 => true,
+ 0xa9b4...0xa9b5 => true,
+ 0xa9b6...0xa9b9 => true,
+ 0xa9ba...0xa9bb => true,
+ 0xa9bc...0xa9bd => true,
+ 0xa9be...0xa9bf => true,
+ 0xa9cf => true,
+ 0xa9e0...0xa9e4 => true,
+ 0xa9e5 => true,
+ 0xa9e6 => true,
+ 0xa9e7...0xa9ef => true,
+ 0xa9fa...0xa9fe => true,
+ 0xaa00...0xaa28 => true,
+ 0xaa29...0xaa2e => true,
+ 0xaa2f...0xaa30 => true,
+ 0xaa31...0xaa32 => true,
+ 0xaa33...0xaa34 => true,
+ 0xaa35...0xaa36 => true,
+ 0xaa40...0xaa42 => true,
+ 0xaa43 => true,
+ 0xaa44...0xaa4b => true,
+ 0xaa4c => true,
+ 0xaa4d => true,
+ 0xaa60...0xaa6f => true,
+ 0xaa70 => true,
+ 0xaa71...0xaa76 => true,
+ 0xaa7a => true,
+ 0xaa7b => true,
+ 0xaa7c => true,
+ 0xaa7d => true,
+ 0xaa7e...0xaaaf => true,
+ 0xaab0 => true,
+ 0xaab1 => true,
+ 0xaab2...0xaab4 => true,
+ 0xaab5...0xaab6 => true,
+ 0xaab7...0xaab8 => true,
+ 0xaab9...0xaabd => true,
+ 0xaabe => true,
+ 0xaac0 => true,
+ 0xaac2 => true,
+ 0xaadb...0xaadc => true,
+ 0xaadd => true,
+ 0xaae0...0xaaea => true,
+ 0xaaeb => true,
+ 0xaaec...0xaaed => true,
+ 0xaaee...0xaaef => true,
+ 0xaaf2 => true,
+ 0xaaf3...0xaaf4 => true,
+ 0xaaf5 => true,
+ 0xab01...0xab06 => true,
+ 0xab09...0xab0e => true,
+ 0xab11...0xab16 => true,
+ 0xab20...0xab26 => true,
+ 0xab28...0xab2e => true,
+ 0xab30...0xab5a => true,
+ 0xab5c...0xab5f => true,
+ 0xab60...0xab68 => true,
+ 0xab69 => true,
+ 0xab70...0xabbf => true,
+ 0xabc0...0xabe2 => true,
+ 0xabe3...0xabe4 => true,
+ 0xabe5 => true,
+ 0xabe6...0xabe7 => true,
+ 0xabe8 => true,
+ 0xabe9...0xabea => true,
+ 0xac00...0xd7a3 => true,
+ 0xd7b0...0xd7c6 => true,
+ 0xd7cb...0xd7fb => true,
+ 0xf900...0xfa6d => true,
+ 0xfa70...0xfad9 => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xfb1d => true,
+ 0xfb1e => true,
+ 0xfb1f...0xfb28 => true,
+ 0xfb2a...0xfb36 => true,
+ 0xfb38...0xfb3c => true,
+ 0xfb3e => true,
+ 0xfb40...0xfb41 => true,
+ 0xfb43...0xfb44 => true,
+ 0xfb46...0xfbb1 => true,
+ 0xfbd3...0xfd3d => true,
+ 0xfd50...0xfd8f => true,
+ 0xfd92...0xfdc7 => true,
+ 0xfdf0...0xfdfb => true,
+ 0xfe70...0xfe74 => true,
+ 0xfe76...0xfefc => true,
+ 0xff21...0xff3a => true,
+ 0xff41...0xff5a => true,
+ 0xff66...0xff6f => true,
+ 0xff70 => true,
+ 0xff71...0xff9d => true,
+ 0xff9e...0xff9f => true,
+ 0xffa0...0xffbe => true,
+ 0xffc2...0xffc7 => true,
+ 0xffca...0xffcf => true,
+ 0xffd2...0xffd7 => true,
+ 0xffda...0xffdc => true,
+ 0x10000...0x1000b => true,
+ 0x1000d...0x10026 => true,
+ 0x10028...0x1003a => true,
+ 0x1003c...0x1003d => true,
+ 0x1003f...0x1004d => true,
+ 0x10050...0x1005d => true,
+ 0x10080...0x100fa => true,
+ 0x10140...0x10174 => true,
+ 0x10280...0x1029c => true,
+ 0x102a0...0x102d0 => true,
+ 0x10300...0x1031f => true,
+ 0x1032d...0x10340 => true,
+ 0x10341 => true,
+ 0x10342...0x10349 => true,
+ 0x1034a => true,
+ 0x10350...0x10375 => true,
+ 0x10376...0x1037a => true,
+ 0x10380...0x1039d => true,
+ 0x103a0...0x103c3 => true,
+ 0x103c8...0x103cf => true,
+ 0x103d1...0x103d5 => true,
+ 0x10400...0x1044f => true,
+ 0x10450...0x1049d => true,
+ 0x104b0...0x104d3 => true,
+ 0x104d8...0x104fb => true,
+ 0x10500...0x10527 => true,
+ 0x10530...0x10563 => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10600...0x10736 => true,
+ 0x10740...0x10755 => true,
+ 0x10760...0x10767 => true,
+ 0x10780...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x10800...0x10805 => true,
+ 0x10808 => true,
+ 0x1080a...0x10835 => true,
+ 0x10837...0x10838 => true,
+ 0x1083c => true,
+ 0x1083f...0x10855 => true,
+ 0x10860...0x10876 => true,
+ 0x10880...0x1089e => true,
+ 0x108e0...0x108f2 => true,
+ 0x108f4...0x108f5 => true,
+ 0x10900...0x10915 => true,
+ 0x10920...0x10939 => true,
+ 0x10980...0x109b7 => true,
+ 0x109be...0x109bf => true,
+ 0x10a00 => true,
+ 0x10a01...0x10a03 => true,
+ 0x10a05...0x10a06 => true,
+ 0x10a0c...0x10a0f => true,
+ 0x10a10...0x10a13 => true,
+ 0x10a15...0x10a17 => true,
+ 0x10a19...0x10a35 => true,
+ 0x10a60...0x10a7c => true,
+ 0x10a80...0x10a9c => true,
+ 0x10ac0...0x10ac7 => true,
+ 0x10ac9...0x10ae4 => true,
+ 0x10b00...0x10b35 => true,
+ 0x10b40...0x10b55 => true,
+ 0x10b60...0x10b72 => true,
+ 0x10b80...0x10b91 => true,
+ 0x10c00...0x10c48 => true,
+ 0x10c80...0x10cb2 => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x10d00...0x10d23 => true,
+ 0x10d24...0x10d27 => true,
+ 0x10e80...0x10ea9 => true,
+ 0x10eab...0x10eac => true,
+ 0x10eb0...0x10eb1 => true,
+ 0x10f00...0x10f1c => true,
+ 0x10f27 => true,
+ 0x10f30...0x10f45 => true,
+ 0x10f70...0x10f81 => true,
+ 0x10fb0...0x10fc4 => true,
+ 0x10fe0...0x10ff6 => true,
+ 0x11000 => true,
+ 0x11001 => true,
+ 0x11002 => true,
+ 0x11003...0x11037 => true,
+ 0x11038...0x11045 => true,
+ 0x11071...0x11072 => true,
+ 0x11073...0x11074 => true,
+ 0x11075 => true,
+ 0x11080...0x11081 => true,
+ 0x11082 => true,
+ 0x11083...0x110af => true,
+ 0x110b0...0x110b2 => true,
+ 0x110b3...0x110b6 => true,
+ 0x110b7...0x110b8 => true,
+ 0x110c2 => true,
+ 0x110d0...0x110e8 => true,
+ 0x11100...0x11102 => true,
+ 0x11103...0x11126 => true,
+ 0x11127...0x1112b => true,
+ 0x1112c => true,
+ 0x1112d...0x11132 => true,
+ 0x11144 => true,
+ 0x11145...0x11146 => true,
+ 0x11147 => true,
+ 0x11150...0x11172 => true,
+ 0x11176 => true,
+ 0x11180...0x11181 => true,
+ 0x11182 => true,
+ 0x11183...0x111b2 => true,
+ 0x111b3...0x111b5 => true,
+ 0x111b6...0x111be => true,
+ 0x111bf => true,
+ 0x111c1...0x111c4 => true,
+ 0x111ce => true,
+ 0x111cf => true,
+ 0x111da => true,
+ 0x111dc => true,
+ 0x11200...0x11211 => true,
+ 0x11213...0x1122b => true,
+ 0x1122c...0x1122e => true,
+ 0x1122f...0x11231 => true,
+ 0x11232...0x11233 => true,
+ 0x11234 => true,
+ 0x11237 => true,
+ 0x1123e => true,
+ 0x1123f...0x11240 => true,
+ 0x11241 => true,
+ 0x11280...0x11286 => true,
+ 0x11288 => true,
+ 0x1128a...0x1128d => true,
+ 0x1128f...0x1129d => true,
+ 0x1129f...0x112a8 => true,
+ 0x112b0...0x112de => true,
+ 0x112df => true,
+ 0x112e0...0x112e2 => true,
+ 0x112e3...0x112e8 => true,
+ 0x11300...0x11301 => true,
+ 0x11302...0x11303 => true,
+ 0x11305...0x1130c => true,
+ 0x1130f...0x11310 => true,
+ 0x11313...0x11328 => true,
+ 0x1132a...0x11330 => true,
+ 0x11332...0x11333 => true,
+ 0x11335...0x11339 => true,
+ 0x1133d => true,
+ 0x1133e...0x1133f => true,
+ 0x11340 => true,
+ 0x11341...0x11344 => true,
+ 0x11347...0x11348 => true,
+ 0x1134b...0x1134c => true,
+ 0x11350 => true,
+ 0x11357 => true,
+ 0x1135d...0x11361 => true,
+ 0x11362...0x11363 => true,
+ 0x11400...0x11434 => true,
+ 0x11435...0x11437 => true,
+ 0x11438...0x1143f => true,
+ 0x11440...0x11441 => true,
+ 0x11443...0x11444 => true,
+ 0x11445 => true,
+ 0x11447...0x1144a => true,
+ 0x1145f...0x11461 => true,
+ 0x11480...0x114af => true,
+ 0x114b0...0x114b2 => true,
+ 0x114b3...0x114b8 => true,
+ 0x114b9 => true,
+ 0x114ba => true,
+ 0x114bb...0x114be => true,
+ 0x114bf...0x114c0 => true,
+ 0x114c1 => true,
+ 0x114c4...0x114c5 => true,
+ 0x114c7 => true,
+ 0x11580...0x115ae => true,
+ 0x115af...0x115b1 => true,
+ 0x115b2...0x115b5 => true,
+ 0x115b8...0x115bb => true,
+ 0x115bc...0x115bd => true,
+ 0x115be => true,
+ 0x115d8...0x115db => true,
+ 0x115dc...0x115dd => true,
+ 0x11600...0x1162f => true,
+ 0x11630...0x11632 => true,
+ 0x11633...0x1163a => true,
+ 0x1163b...0x1163c => true,
+ 0x1163d => true,
+ 0x1163e => true,
+ 0x11640 => true,
+ 0x11644 => true,
+ 0x11680...0x116aa => true,
+ 0x116ab => true,
+ 0x116ac => true,
+ 0x116ad => true,
+ 0x116ae...0x116af => true,
+ 0x116b0...0x116b5 => true,
+ 0x116b8 => true,
+ 0x11700...0x1171a => true,
+ 0x1171d...0x1171f => true,
+ 0x11720...0x11721 => true,
+ 0x11722...0x11725 => true,
+ 0x11726 => true,
+ 0x11727...0x1172a => true,
+ 0x11740...0x11746 => true,
+ 0x11800...0x1182b => true,
+ 0x1182c...0x1182e => true,
+ 0x1182f...0x11837 => true,
+ 0x11838 => true,
+ 0x118a0...0x118df => true,
+ 0x118ff...0x11906 => true,
+ 0x11909 => true,
+ 0x1190c...0x11913 => true,
+ 0x11915...0x11916 => true,
+ 0x11918...0x1192f => true,
+ 0x11930...0x11935 => true,
+ 0x11937...0x11938 => true,
+ 0x1193b...0x1193c => true,
+ 0x1193f => true,
+ 0x11940 => true,
+ 0x11941 => true,
+ 0x11942 => true,
+ 0x119a0...0x119a7 => true,
+ 0x119aa...0x119d0 => true,
+ 0x119d1...0x119d3 => true,
+ 0x119d4...0x119d7 => true,
+ 0x119da...0x119db => true,
+ 0x119dc...0x119df => true,
+ 0x119e1 => true,
+ 0x119e3 => true,
+ 0x119e4 => true,
+ 0x11a00 => true,
+ 0x11a01...0x11a0a => true,
+ 0x11a0b...0x11a32 => true,
+ 0x11a35...0x11a38 => true,
+ 0x11a39 => true,
+ 0x11a3a => true,
+ 0x11a3b...0x11a3e => true,
+ 0x11a50 => true,
+ 0x11a51...0x11a56 => true,
+ 0x11a57...0x11a58 => true,
+ 0x11a59...0x11a5b => true,
+ 0x11a5c...0x11a89 => true,
+ 0x11a8a...0x11a96 => true,
+ 0x11a97 => true,
+ 0x11a9d => true,
+ 0x11ab0...0x11af8 => true,
+ 0x11c00...0x11c08 => true,
+ 0x11c0a...0x11c2e => true,
+ 0x11c2f => true,
+ 0x11c30...0x11c36 => true,
+ 0x11c38...0x11c3d => true,
+ 0x11c3e => true,
+ 0x11c40 => true,
+ 0x11c72...0x11c8f => true,
+ 0x11c92...0x11ca7 => true,
+ 0x11ca9 => true,
+ 0x11caa...0x11cb0 => true,
+ 0x11cb1 => true,
+ 0x11cb2...0x11cb3 => true,
+ 0x11cb4 => true,
+ 0x11cb5...0x11cb6 => true,
+ 0x11d00...0x11d06 => true,
+ 0x11d08...0x11d09 => true,
+ 0x11d0b...0x11d30 => true,
+ 0x11d31...0x11d36 => true,
+ 0x11d3a => true,
+ 0x11d3c...0x11d3d => true,
+ 0x11d3f...0x11d41 => true,
+ 0x11d43 => true,
+ 0x11d46 => true,
+ 0x11d47 => true,
+ 0x11d60...0x11d65 => true,
+ 0x11d67...0x11d68 => true,
+ 0x11d6a...0x11d89 => true,
+ 0x11d8a...0x11d8e => true,
+ 0x11d90...0x11d91 => true,
+ 0x11d93...0x11d94 => true,
+ 0x11d95 => true,
+ 0x11d96 => true,
+ 0x11d98 => true,
+ 0x11ee0...0x11ef2 => true,
+ 0x11ef3...0x11ef4 => true,
+ 0x11ef5...0x11ef6 => true,
+ 0x11f00...0x11f01 => true,
+ 0x11f02 => true,
+ 0x11f03 => true,
+ 0x11f04...0x11f10 => true,
+ 0x11f12...0x11f33 => true,
+ 0x11f34...0x11f35 => true,
+ 0x11f36...0x11f3a => true,
+ 0x11f3e...0x11f3f => true,
+ 0x11f40 => true,
+ 0x11fb0 => true,
+ 0x12000...0x12399 => true,
+ 0x12400...0x1246e => true,
+ 0x12480...0x12543 => true,
+ 0x12f90...0x12ff0 => true,
+ 0x13000...0x1342f => true,
+ 0x13441...0x13446 => true,
+ 0x14400...0x14646 => true,
+ 0x16800...0x16a38 => true,
+ 0x16a40...0x16a5e => true,
+ 0x16a70...0x16abe => true,
+ 0x16ad0...0x16aed => true,
+ 0x16b00...0x16b2f => true,
+ 0x16b40...0x16b43 => true,
+ 0x16b63...0x16b77 => true,
+ 0x16b7d...0x16b8f => true,
+ 0x16e40...0x16e7f => true,
+ 0x16f00...0x16f4a => true,
+ 0x16f4f => true,
+ 0x16f50 => true,
+ 0x16f51...0x16f87 => true,
+ 0x16f8f...0x16f92 => true,
+ 0x16f93...0x16f9f => true,
+ 0x16fe0...0x16fe1 => true,
+ 0x16fe3 => true,
+ 0x16ff0...0x16ff1 => true,
+ 0x17000...0x187f7 => true,
+ 0x18800...0x18cd5 => true,
+ 0x18d00...0x18d08 => true,
+ 0x1aff0...0x1aff3 => true,
+ 0x1aff5...0x1affb => true,
+ 0x1affd...0x1affe => true,
+ 0x1b000...0x1b122 => true,
+ 0x1b132 => true,
+ 0x1b150...0x1b152 => true,
+ 0x1b155 => true,
+ 0x1b164...0x1b167 => true,
+ 0x1b170...0x1b2fb => true,
+ 0x1bc00...0x1bc6a => true,
+ 0x1bc70...0x1bc7c => true,
+ 0x1bc80...0x1bc88 => true,
+ 0x1bc90...0x1bc99 => true,
+ 0x1bc9e => true,
+ 0x1d400...0x1d454 => true,
+ 0x1d456...0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d51e...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d552...0x1d6a5 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6dc...0x1d6fa => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d716...0x1d734 => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d750...0x1d76e => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d78a...0x1d7a8 => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c4...0x1d7cb => true,
+ 0x1df00...0x1df09 => true,
+ 0x1df0a => true,
+ 0x1df0b...0x1df1e => true,
+ 0x1df25...0x1df2a => true,
+ 0x1e000...0x1e006 => true,
+ 0x1e008...0x1e018 => true,
+ 0x1e01b...0x1e021 => true,
+ 0x1e023...0x1e024 => true,
+ 0x1e026...0x1e02a => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e08f => true,
+ 0x1e100...0x1e12c => true,
+ 0x1e137...0x1e13d => true,
+ 0x1e14e => true,
+ 0x1e290...0x1e2ad => true,
+ 0x1e2c0...0x1e2eb => true,
+ 0x1e4d0...0x1e4ea => true,
+ 0x1e4eb => true,
+ 0x1e7e0...0x1e7e6 => true,
+ 0x1e7e8...0x1e7eb => true,
+ 0x1e7ed...0x1e7ee => true,
+ 0x1e7f0...0x1e7fe => true,
+ 0x1e800...0x1e8c4 => true,
+ 0x1e900...0x1e943 => true,
+ 0x1e947 => true,
+ 0x1e94b => true,
+ 0x1ee00...0x1ee03 => true,
+ 0x1ee05...0x1ee1f => true,
+ 0x1ee21...0x1ee22 => true,
+ 0x1ee24 => true,
+ 0x1ee27 => true,
+ 0x1ee29...0x1ee32 => true,
+ 0x1ee34...0x1ee37 => true,
+ 0x1ee39 => true,
+ 0x1ee3b => true,
+ 0x1ee42 => true,
+ 0x1ee47 => true,
+ 0x1ee49 => true,
+ 0x1ee4b => true,
+ 0x1ee4d...0x1ee4f => true,
+ 0x1ee51...0x1ee52 => true,
+ 0x1ee54 => true,
+ 0x1ee57 => true,
+ 0x1ee59 => true,
+ 0x1ee5b => true,
+ 0x1ee5d => true,
+ 0x1ee5f => true,
+ 0x1ee61...0x1ee62 => true,
+ 0x1ee64 => true,
+ 0x1ee67...0x1ee6a => true,
+ 0x1ee6c...0x1ee72 => true,
+ 0x1ee74...0x1ee77 => true,
+ 0x1ee79...0x1ee7c => true,
+ 0x1ee7e => true,
+ 0x1ee80...0x1ee89 => true,
+ 0x1ee8b...0x1ee9b => true,
+ 0x1eea1...0x1eea3 => true,
+ 0x1eea5...0x1eea9 => true,
+ 0x1eeab...0x1eebb => true,
+ 0x1f130...0x1f149 => true,
+ 0x1f150...0x1f169 => true,
+ 0x1f170...0x1f189 => true,
+ 0x20000...0x2a6df => true,
+ 0x2a700...0x2b739 => true,
+ 0x2b740...0x2b81d => true,
+ 0x2b820...0x2cea1 => true,
+ 0x2ceb0...0x2ebe0 => true,
+ 0x2f800...0x2fa1d => true,
+ 0x30000...0x3134a => true,
+ 0x31350...0x323af => true,
+ else => false,
+ };
+}
+
+pub fn isLowercase(cp: u21) bool {
+ if (cp < 0x61 or cp > 0x1e943) return false;
+
+ return switch (cp) {
+ 0x61...0x7a => true,
+ 0xaa => true,
+ 0xb5 => true,
+ 0xba => true,
+ 0xdf...0xf6 => true,
+ 0xf8...0xff => true,
+ 0x101 => true,
+ 0x103 => true,
+ 0x105 => true,
+ 0x107 => true,
+ 0x109 => true,
+ 0x10b => true,
+ 0x10d => true,
+ 0x10f => true,
+ 0x111 => true,
+ 0x113 => true,
+ 0x115 => true,
+ 0x117 => true,
+ 0x119 => true,
+ 0x11b => true,
+ 0x11d => true,
+ 0x11f => true,
+ 0x121 => true,
+ 0x123 => true,
+ 0x125 => true,
+ 0x127 => true,
+ 0x129 => true,
+ 0x12b => true,
+ 0x12d => true,
+ 0x12f => true,
+ 0x131 => true,
+ 0x133 => true,
+ 0x135 => true,
+ 0x137...0x138 => true,
+ 0x13a => true,
+ 0x13c => true,
+ 0x13e => true,
+ 0x140 => true,
+ 0x142 => true,
+ 0x144 => true,
+ 0x146 => true,
+ 0x148...0x149 => true,
+ 0x14b => true,
+ 0x14d => true,
+ 0x14f => true,
+ 0x151 => true,
+ 0x153 => true,
+ 0x155 => true,
+ 0x157 => true,
+ 0x159 => true,
+ 0x15b => true,
+ 0x15d => true,
+ 0x15f => true,
+ 0x161 => true,
+ 0x163 => true,
+ 0x165 => true,
+ 0x167 => true,
+ 0x169 => true,
+ 0x16b => true,
+ 0x16d => true,
+ 0x16f => true,
+ 0x171 => true,
+ 0x173 => true,
+ 0x175 => true,
+ 0x177 => true,
+ 0x17a => true,
+ 0x17c => true,
+ 0x17e...0x180 => true,
+ 0x183 => true,
+ 0x185 => true,
+ 0x188 => true,
+ 0x18c...0x18d => true,
+ 0x192 => true,
+ 0x195 => true,
+ 0x199...0x19b => true,
+ 0x19e => true,
+ 0x1a1 => true,
+ 0x1a3 => true,
+ 0x1a5 => true,
+ 0x1a8 => true,
+ 0x1aa...0x1ab => true,
+ 0x1ad => true,
+ 0x1b0 => true,
+ 0x1b4 => true,
+ 0x1b6 => true,
+ 0x1b9...0x1ba => true,
+ 0x1bd...0x1bf => true,
+ 0x1c6 => true,
+ 0x1c9 => true,
+ 0x1cc => true,
+ 0x1ce => true,
+ 0x1d0 => true,
+ 0x1d2 => true,
+ 0x1d4 => true,
+ 0x1d6 => true,
+ 0x1d8 => true,
+ 0x1da => true,
+ 0x1dc...0x1dd => true,
+ 0x1df => true,
+ 0x1e1 => true,
+ 0x1e3 => true,
+ 0x1e5 => true,
+ 0x1e7 => true,
+ 0x1e9 => true,
+ 0x1eb => true,
+ 0x1ed => true,
+ 0x1ef...0x1f0 => true,
+ 0x1f3 => true,
+ 0x1f5 => true,
+ 0x1f9 => true,
+ 0x1fb => true,
+ 0x1fd => true,
+ 0x1ff => true,
+ 0x201 => true,
+ 0x203 => true,
+ 0x205 => true,
+ 0x207 => true,
+ 0x209 => true,
+ 0x20b => true,
+ 0x20d => true,
+ 0x20f => true,
+ 0x211 => true,
+ 0x213 => true,
+ 0x215 => true,
+ 0x217 => true,
+ 0x219 => true,
+ 0x21b => true,
+ 0x21d => true,
+ 0x21f => true,
+ 0x221 => true,
+ 0x223 => true,
+ 0x225 => true,
+ 0x227 => true,
+ 0x229 => true,
+ 0x22b => true,
+ 0x22d => true,
+ 0x22f => true,
+ 0x231 => true,
+ 0x233...0x239 => true,
+ 0x23c => true,
+ 0x23f...0x240 => true,
+ 0x242 => true,
+ 0x247 => true,
+ 0x249 => true,
+ 0x24b => true,
+ 0x24d => true,
+ 0x24f...0x293 => true,
+ 0x295...0x2af => true,
+ 0x2b0...0x2b8 => true,
+ 0x2c0...0x2c1 => true,
+ 0x2e0...0x2e4 => true,
+ 0x345 => true,
+ 0x371 => true,
+ 0x373 => true,
+ 0x377 => true,
+ 0x37a => true,
+ 0x37b...0x37d => true,
+ 0x390 => true,
+ 0x3ac...0x3ce => true,
+ 0x3d0...0x3d1 => true,
+ 0x3d5...0x3d7 => true,
+ 0x3d9 => true,
+ 0x3db => true,
+ 0x3dd => true,
+ 0x3df => true,
+ 0x3e1 => true,
+ 0x3e3 => true,
+ 0x3e5 => true,
+ 0x3e7 => true,
+ 0x3e9 => true,
+ 0x3eb => true,
+ 0x3ed => true,
+ 0x3ef...0x3f3 => true,
+ 0x3f5 => true,
+ 0x3f8 => true,
+ 0x3fb...0x3fc => true,
+ 0x430...0x45f => true,
+ 0x461 => true,
+ 0x463 => true,
+ 0x465 => true,
+ 0x467 => true,
+ 0x469 => true,
+ 0x46b => true,
+ 0x46d => true,
+ 0x46f => true,
+ 0x471 => true,
+ 0x473 => true,
+ 0x475 => true,
+ 0x477 => true,
+ 0x479 => true,
+ 0x47b => true,
+ 0x47d => true,
+ 0x47f => true,
+ 0x481 => true,
+ 0x48b => true,
+ 0x48d => true,
+ 0x48f => true,
+ 0x491 => true,
+ 0x493 => true,
+ 0x495 => true,
+ 0x497 => true,
+ 0x499 => true,
+ 0x49b => true,
+ 0x49d => true,
+ 0x49f => true,
+ 0x4a1 => true,
+ 0x4a3 => true,
+ 0x4a5 => true,
+ 0x4a7 => true,
+ 0x4a9 => true,
+ 0x4ab => true,
+ 0x4ad => true,
+ 0x4af => true,
+ 0x4b1 => true,
+ 0x4b3 => true,
+ 0x4b5 => true,
+ 0x4b7 => true,
+ 0x4b9 => true,
+ 0x4bb => true,
+ 0x4bd => true,
+ 0x4bf => true,
+ 0x4c2 => true,
+ 0x4c4 => true,
+ 0x4c6 => true,
+ 0x4c8 => true,
+ 0x4ca => true,
+ 0x4cc => true,
+ 0x4ce...0x4cf => true,
+ 0x4d1 => true,
+ 0x4d3 => true,
+ 0x4d5 => true,
+ 0x4d7 => true,
+ 0x4d9 => true,
+ 0x4db => true,
+ 0x4dd => true,
+ 0x4df => true,
+ 0x4e1 => true,
+ 0x4e3 => true,
+ 0x4e5 => true,
+ 0x4e7 => true,
+ 0x4e9 => true,
+ 0x4eb => true,
+ 0x4ed => true,
+ 0x4ef => true,
+ 0x4f1 => true,
+ 0x4f3 => true,
+ 0x4f5 => true,
+ 0x4f7 => true,
+ 0x4f9 => true,
+ 0x4fb => true,
+ 0x4fd => true,
+ 0x4ff => true,
+ 0x501 => true,
+ 0x503 => true,
+ 0x505 => true,
+ 0x507 => true,
+ 0x509 => true,
+ 0x50b => true,
+ 0x50d => true,
+ 0x50f => true,
+ 0x511 => true,
+ 0x513 => true,
+ 0x515 => true,
+ 0x517 => true,
+ 0x519 => true,
+ 0x51b => true,
+ 0x51d => true,
+ 0x51f => true,
+ 0x521 => true,
+ 0x523 => true,
+ 0x525 => true,
+ 0x527 => true,
+ 0x529 => true,
+ 0x52b => true,
+ 0x52d => true,
+ 0x52f => true,
+ 0x560...0x588 => true,
+ 0x10d0...0x10fa => true,
+ 0x10fc => true,
+ 0x10fd...0x10ff => true,
+ 0x13f8...0x13fd => true,
+ 0x1c80...0x1c88 => true,
+ 0x1d00...0x1d2b => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d6b...0x1d77 => true,
+ 0x1d78 => true,
+ 0x1d79...0x1d9a => true,
+ 0x1d9b...0x1dbf => true,
+ 0x1e01 => true,
+ 0x1e03 => true,
+ 0x1e05 => true,
+ 0x1e07 => true,
+ 0x1e09 => true,
+ 0x1e0b => true,
+ 0x1e0d => true,
+ 0x1e0f => true,
+ 0x1e11 => true,
+ 0x1e13 => true,
+ 0x1e15 => true,
+ 0x1e17 => true,
+ 0x1e19 => true,
+ 0x1e1b => true,
+ 0x1e1d => true,
+ 0x1e1f => true,
+ 0x1e21 => true,
+ 0x1e23 => true,
+ 0x1e25 => true,
+ 0x1e27 => true,
+ 0x1e29 => true,
+ 0x1e2b => true,
+ 0x1e2d => true,
+ 0x1e2f => true,
+ 0x1e31 => true,
+ 0x1e33 => true,
+ 0x1e35 => true,
+ 0x1e37 => true,
+ 0x1e39 => true,
+ 0x1e3b => true,
+ 0x1e3d => true,
+ 0x1e3f => true,
+ 0x1e41 => true,
+ 0x1e43 => true,
+ 0x1e45 => true,
+ 0x1e47 => true,
+ 0x1e49 => true,
+ 0x1e4b => true,
+ 0x1e4d => true,
+ 0x1e4f => true,
+ 0x1e51 => true,
+ 0x1e53 => true,
+ 0x1e55 => true,
+ 0x1e57 => true,
+ 0x1e59 => true,
+ 0x1e5b => true,
+ 0x1e5d => true,
+ 0x1e5f => true,
+ 0x1e61 => true,
+ 0x1e63 => true,
+ 0x1e65 => true,
+ 0x1e67 => true,
+ 0x1e69 => true,
+ 0x1e6b => true,
+ 0x1e6d => true,
+ 0x1e6f => true,
+ 0x1e71 => true,
+ 0x1e73 => true,
+ 0x1e75 => true,
+ 0x1e77 => true,
+ 0x1e79 => true,
+ 0x1e7b => true,
+ 0x1e7d => true,
+ 0x1e7f => true,
+ 0x1e81 => true,
+ 0x1e83 => true,
+ 0x1e85 => true,
+ 0x1e87 => true,
+ 0x1e89 => true,
+ 0x1e8b => true,
+ 0x1e8d => true,
+ 0x1e8f => true,
+ 0x1e91 => true,
+ 0x1e93 => true,
+ 0x1e95...0x1e9d => true,
+ 0x1e9f => true,
+ 0x1ea1 => true,
+ 0x1ea3 => true,
+ 0x1ea5 => true,
+ 0x1ea7 => true,
+ 0x1ea9 => true,
+ 0x1eab => true,
+ 0x1ead => true,
+ 0x1eaf => true,
+ 0x1eb1 => true,
+ 0x1eb3 => true,
+ 0x1eb5 => true,
+ 0x1eb7 => true,
+ 0x1eb9 => true,
+ 0x1ebb => true,
+ 0x1ebd => true,
+ 0x1ebf => true,
+ 0x1ec1 => true,
+ 0x1ec3 => true,
+ 0x1ec5 => true,
+ 0x1ec7 => true,
+ 0x1ec9 => true,
+ 0x1ecb => true,
+ 0x1ecd => true,
+ 0x1ecf => true,
+ 0x1ed1 => true,
+ 0x1ed3 => true,
+ 0x1ed5 => true,
+ 0x1ed7 => true,
+ 0x1ed9 => true,
+ 0x1edb => true,
+ 0x1edd => true,
+ 0x1edf => true,
+ 0x1ee1 => true,
+ 0x1ee3 => true,
+ 0x1ee5 => true,
+ 0x1ee7 => true,
+ 0x1ee9 => true,
+ 0x1eeb => true,
+ 0x1eed => true,
+ 0x1eef => true,
+ 0x1ef1 => true,
+ 0x1ef3 => true,
+ 0x1ef5 => true,
+ 0x1ef7 => true,
+ 0x1ef9 => true,
+ 0x1efb => true,
+ 0x1efd => true,
+ 0x1eff...0x1f07 => true,
+ 0x1f10...0x1f15 => true,
+ 0x1f20...0x1f27 => true,
+ 0x1f30...0x1f37 => true,
+ 0x1f40...0x1f45 => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f60...0x1f67 => true,
+ 0x1f70...0x1f7d => true,
+ 0x1f80...0x1f87 => true,
+ 0x1f90...0x1f97 => true,
+ 0x1fa0...0x1fa7 => true,
+ 0x1fb0...0x1fb4 => true,
+ 0x1fb6...0x1fb7 => true,
+ 0x1fbe => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fc7 => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fd7 => true,
+ 0x1fe0...0x1fe7 => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ff7 => true,
+ 0x2071 => true,
+ 0x207f => true,
+ 0x2090...0x209c => true,
+ 0x210a => true,
+ 0x210e...0x210f => true,
+ 0x2113 => true,
+ 0x212f => true,
+ 0x2134 => true,
+ 0x2139 => true,
+ 0x213c...0x213d => true,
+ 0x2146...0x2149 => true,
+ 0x214e => true,
+ 0x2170...0x217f => true,
+ 0x2184 => true,
+ 0x24d0...0x24e9 => true,
+ 0x2c30...0x2c5f => true,
+ 0x2c61 => true,
+ 0x2c65...0x2c66 => true,
+ 0x2c68 => true,
+ 0x2c6a => true,
+ 0x2c6c => true,
+ 0x2c71 => true,
+ 0x2c73...0x2c74 => true,
+ 0x2c76...0x2c7b => true,
+ 0x2c7c...0x2c7d => true,
+ 0x2c81 => true,
+ 0x2c83 => true,
+ 0x2c85 => true,
+ 0x2c87 => true,
+ 0x2c89 => true,
+ 0x2c8b => true,
+ 0x2c8d => true,
+ 0x2c8f => true,
+ 0x2c91 => true,
+ 0x2c93 => true,
+ 0x2c95 => true,
+ 0x2c97 => true,
+ 0x2c99 => true,
+ 0x2c9b => true,
+ 0x2c9d => true,
+ 0x2c9f => true,
+ 0x2ca1 => true,
+ 0x2ca3 => true,
+ 0x2ca5 => true,
+ 0x2ca7 => true,
+ 0x2ca9 => true,
+ 0x2cab => true,
+ 0x2cad => true,
+ 0x2caf => true,
+ 0x2cb1 => true,
+ 0x2cb3 => true,
+ 0x2cb5 => true,
+ 0x2cb7 => true,
+ 0x2cb9 => true,
+ 0x2cbb => true,
+ 0x2cbd => true,
+ 0x2cbf => true,
+ 0x2cc1 => true,
+ 0x2cc3 => true,
+ 0x2cc5 => true,
+ 0x2cc7 => true,
+ 0x2cc9 => true,
+ 0x2ccb => true,
+ 0x2ccd => true,
+ 0x2ccf => true,
+ 0x2cd1 => true,
+ 0x2cd3 => true,
+ 0x2cd5 => true,
+ 0x2cd7 => true,
+ 0x2cd9 => true,
+ 0x2cdb => true,
+ 0x2cdd => true,
+ 0x2cdf => true,
+ 0x2ce1 => true,
+ 0x2ce3...0x2ce4 => true,
+ 0x2cec => true,
+ 0x2cee => true,
+ 0x2cf3 => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0xa641 => true,
+ 0xa643 => true,
+ 0xa645 => true,
+ 0xa647 => true,
+ 0xa649 => true,
+ 0xa64b => true,
+ 0xa64d => true,
+ 0xa64f => true,
+ 0xa651 => true,
+ 0xa653 => true,
+ 0xa655 => true,
+ 0xa657 => true,
+ 0xa659 => true,
+ 0xa65b => true,
+ 0xa65d => true,
+ 0xa65f => true,
+ 0xa661 => true,
+ 0xa663 => true,
+ 0xa665 => true,
+ 0xa667 => true,
+ 0xa669 => true,
+ 0xa66b => true,
+ 0xa66d => true,
+ 0xa681 => true,
+ 0xa683 => true,
+ 0xa685 => true,
+ 0xa687 => true,
+ 0xa689 => true,
+ 0xa68b => true,
+ 0xa68d => true,
+ 0xa68f => true,
+ 0xa691 => true,
+ 0xa693 => true,
+ 0xa695 => true,
+ 0xa697 => true,
+ 0xa699 => true,
+ 0xa69b => true,
+ 0xa69c...0xa69d => true,
+ 0xa723 => true,
+ 0xa725 => true,
+ 0xa727 => true,
+ 0xa729 => true,
+ 0xa72b => true,
+ 0xa72d => true,
+ 0xa72f...0xa731 => true,
+ 0xa733 => true,
+ 0xa735 => true,
+ 0xa737 => true,
+ 0xa739 => true,
+ 0xa73b => true,
+ 0xa73d => true,
+ 0xa73f => true,
+ 0xa741 => true,
+ 0xa743 => true,
+ 0xa745 => true,
+ 0xa747 => true,
+ 0xa749 => true,
+ 0xa74b => true,
+ 0xa74d => true,
+ 0xa74f => true,
+ 0xa751 => true,
+ 0xa753 => true,
+ 0xa755 => true,
+ 0xa757 => true,
+ 0xa759 => true,
+ 0xa75b => true,
+ 0xa75d => true,
+ 0xa75f => true,
+ 0xa761 => true,
+ 0xa763 => true,
+ 0xa765 => true,
+ 0xa767 => true,
+ 0xa769 => true,
+ 0xa76b => true,
+ 0xa76d => true,
+ 0xa76f => true,
+ 0xa770 => true,
+ 0xa771...0xa778 => true,
+ 0xa77a => true,
+ 0xa77c => true,
+ 0xa77f => true,
+ 0xa781 => true,
+ 0xa783 => true,
+ 0xa785 => true,
+ 0xa787 => true,
+ 0xa78c => true,
+ 0xa78e => true,
+ 0xa791 => true,
+ 0xa793...0xa795 => true,
+ 0xa797 => true,
+ 0xa799 => true,
+ 0xa79b => true,
+ 0xa79d => true,
+ 0xa79f => true,
+ 0xa7a1 => true,
+ 0xa7a3 => true,
+ 0xa7a5 => true,
+ 0xa7a7 => true,
+ 0xa7a9 => true,
+ 0xa7af => true,
+ 0xa7b5 => true,
+ 0xa7b7 => true,
+ 0xa7b9 => true,
+ 0xa7bb => true,
+ 0xa7bd => true,
+ 0xa7bf => true,
+ 0xa7c1 => true,
+ 0xa7c3 => true,
+ 0xa7c8 => true,
+ 0xa7ca => true,
+ 0xa7d1 => true,
+ 0xa7d3 => true,
+ 0xa7d5 => true,
+ 0xa7d7 => true,
+ 0xa7d9 => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f6 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa7fa => true,
+ 0xab30...0xab5a => true,
+ 0xab5c...0xab5f => true,
+ 0xab60...0xab68 => true,
+ 0xab69 => true,
+ 0xab70...0xabbf => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xff41...0xff5a => true,
+ 0x10428...0x1044f => true,
+ 0x104d8...0x104fb => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10780 => true,
+ 0x10783...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x118c0...0x118df => true,
+ 0x16e60...0x16e7f => true,
+ 0x1d41a...0x1d433 => true,
+ 0x1d44e...0x1d454 => true,
+ 0x1d456...0x1d467 => true,
+ 0x1d482...0x1d49b => true,
+ 0x1d4b6...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d4cf => true,
+ 0x1d4ea...0x1d503 => true,
+ 0x1d51e...0x1d537 => true,
+ 0x1d552...0x1d56b => true,
+ 0x1d586...0x1d59f => true,
+ 0x1d5ba...0x1d5d3 => true,
+ 0x1d5ee...0x1d607 => true,
+ 0x1d622...0x1d63b => true,
+ 0x1d656...0x1d66f => true,
+ 0x1d68a...0x1d6a5 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6dc...0x1d6e1 => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d716...0x1d71b => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d750...0x1d755 => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d78a...0x1d78f => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c4...0x1d7c9 => true,
+ 0x1d7cb => true,
+ 0x1df00...0x1df09 => true,
+ 0x1df0b...0x1df1e => true,
+ 0x1df25...0x1df2a => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e922...0x1e943 => true,
+ else => false,
+ };
+}
+
+pub fn isUppercase(cp: u21) bool {
+ if (cp < 0x41 or cp > 0x1f189) return false;
+
+ return switch (cp) {
+ 0x41...0x5a => true,
+ 0xc0...0xd6 => true,
+ 0xd8...0xde => true,
+ 0x100 => true,
+ 0x102 => true,
+ 0x104 => true,
+ 0x106 => true,
+ 0x108 => true,
+ 0x10a => true,
+ 0x10c => true,
+ 0x10e => true,
+ 0x110 => true,
+ 0x112 => true,
+ 0x114 => true,
+ 0x116 => true,
+ 0x118 => true,
+ 0x11a => true,
+ 0x11c => true,
+ 0x11e => true,
+ 0x120 => true,
+ 0x122 => true,
+ 0x124 => true,
+ 0x126 => true,
+ 0x128 => true,
+ 0x12a => true,
+ 0x12c => true,
+ 0x12e => true,
+ 0x130 => true,
+ 0x132 => true,
+ 0x134 => true,
+ 0x136 => true,
+ 0x139 => true,
+ 0x13b => true,
+ 0x13d => true,
+ 0x13f => true,
+ 0x141 => true,
+ 0x143 => true,
+ 0x145 => true,
+ 0x147 => true,
+ 0x14a => true,
+ 0x14c => true,
+ 0x14e => true,
+ 0x150 => true,
+ 0x152 => true,
+ 0x154 => true,
+ 0x156 => true,
+ 0x158 => true,
+ 0x15a => true,
+ 0x15c => true,
+ 0x15e => true,
+ 0x160 => true,
+ 0x162 => true,
+ 0x164 => true,
+ 0x166 => true,
+ 0x168 => true,
+ 0x16a => true,
+ 0x16c => true,
+ 0x16e => true,
+ 0x170 => true,
+ 0x172 => true,
+ 0x174 => true,
+ 0x176 => true,
+ 0x178...0x179 => true,
+ 0x17b => true,
+ 0x17d => true,
+ 0x181...0x182 => true,
+ 0x184 => true,
+ 0x186...0x187 => true,
+ 0x189...0x18b => true,
+ 0x18e...0x191 => true,
+ 0x193...0x194 => true,
+ 0x196...0x198 => true,
+ 0x19c...0x19d => true,
+ 0x19f...0x1a0 => true,
+ 0x1a2 => true,
+ 0x1a4 => true,
+ 0x1a6...0x1a7 => true,
+ 0x1a9 => true,
+ 0x1ac => true,
+ 0x1ae...0x1af => true,
+ 0x1b1...0x1b3 => true,
+ 0x1b5 => true,
+ 0x1b7...0x1b8 => true,
+ 0x1bc => true,
+ 0x1c4 => true,
+ 0x1c7 => true,
+ 0x1ca => true,
+ 0x1cd => true,
+ 0x1cf => true,
+ 0x1d1 => true,
+ 0x1d3 => true,
+ 0x1d5 => true,
+ 0x1d7 => true,
+ 0x1d9 => true,
+ 0x1db => true,
+ 0x1de => true,
+ 0x1e0 => true,
+ 0x1e2 => true,
+ 0x1e4 => true,
+ 0x1e6 => true,
+ 0x1e8 => true,
+ 0x1ea => true,
+ 0x1ec => true,
+ 0x1ee => true,
+ 0x1f1 => true,
+ 0x1f4 => true,
+ 0x1f6...0x1f8 => true,
+ 0x1fa => true,
+ 0x1fc => true,
+ 0x1fe => true,
+ 0x200 => true,
+ 0x202 => true,
+ 0x204 => true,
+ 0x206 => true,
+ 0x208 => true,
+ 0x20a => true,
+ 0x20c => true,
+ 0x20e => true,
+ 0x210 => true,
+ 0x212 => true,
+ 0x214 => true,
+ 0x216 => true,
+ 0x218 => true,
+ 0x21a => true,
+ 0x21c => true,
+ 0x21e => true,
+ 0x220 => true,
+ 0x222 => true,
+ 0x224 => true,
+ 0x226 => true,
+ 0x228 => true,
+ 0x22a => true,
+ 0x22c => true,
+ 0x22e => true,
+ 0x230 => true,
+ 0x232 => true,
+ 0x23a...0x23b => true,
+ 0x23d...0x23e => true,
+ 0x241 => true,
+ 0x243...0x246 => true,
+ 0x248 => true,
+ 0x24a => true,
+ 0x24c => true,
+ 0x24e => true,
+ 0x370 => true,
+ 0x372 => true,
+ 0x376 => true,
+ 0x37f => true,
+ 0x386 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x38f => true,
+ 0x391...0x3a1 => true,
+ 0x3a3...0x3ab => true,
+ 0x3cf => true,
+ 0x3d2...0x3d4 => true,
+ 0x3d8 => true,
+ 0x3da => true,
+ 0x3dc => true,
+ 0x3de => true,
+ 0x3e0 => true,
+ 0x3e2 => true,
+ 0x3e4 => true,
+ 0x3e6 => true,
+ 0x3e8 => true,
+ 0x3ea => true,
+ 0x3ec => true,
+ 0x3ee => true,
+ 0x3f4 => true,
+ 0x3f7 => true,
+ 0x3f9...0x3fa => true,
+ 0x3fd...0x42f => true,
+ 0x460 => true,
+ 0x462 => true,
+ 0x464 => true,
+ 0x466 => true,
+ 0x468 => true,
+ 0x46a => true,
+ 0x46c => true,
+ 0x46e => true,
+ 0x470 => true,
+ 0x472 => true,
+ 0x474 => true,
+ 0x476 => true,
+ 0x478 => true,
+ 0x47a => true,
+ 0x47c => true,
+ 0x47e => true,
+ 0x480 => true,
+ 0x48a => true,
+ 0x48c => true,
+ 0x48e => true,
+ 0x490 => true,
+ 0x492 => true,
+ 0x494 => true,
+ 0x496 => true,
+ 0x498 => true,
+ 0x49a => true,
+ 0x49c => true,
+ 0x49e => true,
+ 0x4a0 => true,
+ 0x4a2 => true,
+ 0x4a4 => true,
+ 0x4a6 => true,
+ 0x4a8 => true,
+ 0x4aa => true,
+ 0x4ac => true,
+ 0x4ae => true,
+ 0x4b0 => true,
+ 0x4b2 => true,
+ 0x4b4 => true,
+ 0x4b6 => true,
+ 0x4b8 => true,
+ 0x4ba => true,
+ 0x4bc => true,
+ 0x4be => true,
+ 0x4c0...0x4c1 => true,
+ 0x4c3 => true,
+ 0x4c5 => true,
+ 0x4c7 => true,
+ 0x4c9 => true,
+ 0x4cb => true,
+ 0x4cd => true,
+ 0x4d0 => true,
+ 0x4d2 => true,
+ 0x4d4 => true,
+ 0x4d6 => true,
+ 0x4d8 => true,
+ 0x4da => true,
+ 0x4dc => true,
+ 0x4de => true,
+ 0x4e0 => true,
+ 0x4e2 => true,
+ 0x4e4 => true,
+ 0x4e6 => true,
+ 0x4e8 => true,
+ 0x4ea => true,
+ 0x4ec => true,
+ 0x4ee => true,
+ 0x4f0 => true,
+ 0x4f2 => true,
+ 0x4f4 => true,
+ 0x4f6 => true,
+ 0x4f8 => true,
+ 0x4fa => true,
+ 0x4fc => true,
+ 0x4fe => true,
+ 0x500 => true,
+ 0x502 => true,
+ 0x504 => true,
+ 0x506 => true,
+ 0x508 => true,
+ 0x50a => true,
+ 0x50c => true,
+ 0x50e => true,
+ 0x510 => true,
+ 0x512 => true,
+ 0x514 => true,
+ 0x516 => true,
+ 0x518 => true,
+ 0x51a => true,
+ 0x51c => true,
+ 0x51e => true,
+ 0x520 => true,
+ 0x522 => true,
+ 0x524 => true,
+ 0x526 => true,
+ 0x528 => true,
+ 0x52a => true,
+ 0x52c => true,
+ 0x52e => true,
+ 0x531...0x556 => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x13a0...0x13f5 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1e00 => true,
+ 0x1e02 => true,
+ 0x1e04 => true,
+ 0x1e06 => true,
+ 0x1e08 => true,
+ 0x1e0a => true,
+ 0x1e0c => true,
+ 0x1e0e => true,
+ 0x1e10 => true,
+ 0x1e12 => true,
+ 0x1e14 => true,
+ 0x1e16 => true,
+ 0x1e18 => true,
+ 0x1e1a => true,
+ 0x1e1c => true,
+ 0x1e1e => true,
+ 0x1e20 => true,
+ 0x1e22 => true,
+ 0x1e24 => true,
+ 0x1e26 => true,
+ 0x1e28 => true,
+ 0x1e2a => true,
+ 0x1e2c => true,
+ 0x1e2e => true,
+ 0x1e30 => true,
+ 0x1e32 => true,
+ 0x1e34 => true,
+ 0x1e36 => true,
+ 0x1e38 => true,
+ 0x1e3a => true,
+ 0x1e3c => true,
+ 0x1e3e => true,
+ 0x1e40 => true,
+ 0x1e42 => true,
+ 0x1e44 => true,
+ 0x1e46 => true,
+ 0x1e48 => true,
+ 0x1e4a => true,
+ 0x1e4c => true,
+ 0x1e4e => true,
+ 0x1e50 => true,
+ 0x1e52 => true,
+ 0x1e54 => true,
+ 0x1e56 => true,
+ 0x1e58 => true,
+ 0x1e5a => true,
+ 0x1e5c => true,
+ 0x1e5e => true,
+ 0x1e60 => true,
+ 0x1e62 => true,
+ 0x1e64 => true,
+ 0x1e66 => true,
+ 0x1e68 => true,
+ 0x1e6a => true,
+ 0x1e6c => true,
+ 0x1e6e => true,
+ 0x1e70 => true,
+ 0x1e72 => true,
+ 0x1e74 => true,
+ 0x1e76 => true,
+ 0x1e78 => true,
+ 0x1e7a => true,
+ 0x1e7c => true,
+ 0x1e7e => true,
+ 0x1e80 => true,
+ 0x1e82 => true,
+ 0x1e84 => true,
+ 0x1e86 => true,
+ 0x1e88 => true,
+ 0x1e8a => true,
+ 0x1e8c => true,
+ 0x1e8e => true,
+ 0x1e90 => true,
+ 0x1e92 => true,
+ 0x1e94 => true,
+ 0x1e9e => true,
+ 0x1ea0 => true,
+ 0x1ea2 => true,
+ 0x1ea4 => true,
+ 0x1ea6 => true,
+ 0x1ea8 => true,
+ 0x1eaa => true,
+ 0x1eac => true,
+ 0x1eae => true,
+ 0x1eb0 => true,
+ 0x1eb2 => true,
+ 0x1eb4 => true,
+ 0x1eb6 => true,
+ 0x1eb8 => true,
+ 0x1eba => true,
+ 0x1ebc => true,
+ 0x1ebe => true,
+ 0x1ec0 => true,
+ 0x1ec2 => true,
+ 0x1ec4 => true,
+ 0x1ec6 => true,
+ 0x1ec8 => true,
+ 0x1eca => true,
+ 0x1ecc => true,
+ 0x1ece => true,
+ 0x1ed0 => true,
+ 0x1ed2 => true,
+ 0x1ed4 => true,
+ 0x1ed6 => true,
+ 0x1ed8 => true,
+ 0x1eda => true,
+ 0x1edc => true,
+ 0x1ede => true,
+ 0x1ee0 => true,
+ 0x1ee2 => true,
+ 0x1ee4 => true,
+ 0x1ee6 => true,
+ 0x1ee8 => true,
+ 0x1eea => true,
+ 0x1eec => true,
+ 0x1eee => true,
+ 0x1ef0 => true,
+ 0x1ef2 => true,
+ 0x1ef4 => true,
+ 0x1ef6 => true,
+ 0x1ef8 => true,
+ 0x1efa => true,
+ 0x1efc => true,
+ 0x1efe => true,
+ 0x1f08...0x1f0f => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f28...0x1f2f => true,
+ 0x1f38...0x1f3f => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f => true,
+ 0x1f68...0x1f6f => true,
+ 0x1fb8...0x1fbb => true,
+ 0x1fc8...0x1fcb => true,
+ 0x1fd8...0x1fdb => true,
+ 0x1fe8...0x1fec => true,
+ 0x1ff8...0x1ffb => true,
+ 0x2102 => true,
+ 0x2107 => true,
+ 0x210b...0x210d => true,
+ 0x2110...0x2112 => true,
+ 0x2115 => true,
+ 0x2119...0x211d => true,
+ 0x2124 => true,
+ 0x2126 => true,
+ 0x2128 => true,
+ 0x212a...0x212d => true,
+ 0x2130...0x2133 => true,
+ 0x213e...0x213f => true,
+ 0x2145 => true,
+ 0x2160...0x216f => true,
+ 0x2183 => true,
+ 0x24b6...0x24cf => true,
+ 0x2c00...0x2c2f => true,
+ 0x2c60 => true,
+ 0x2c62...0x2c64 => true,
+ 0x2c67 => true,
+ 0x2c69 => true,
+ 0x2c6b => true,
+ 0x2c6d...0x2c70 => true,
+ 0x2c72 => true,
+ 0x2c75 => true,
+ 0x2c7e...0x2c80 => true,
+ 0x2c82 => true,
+ 0x2c84 => true,
+ 0x2c86 => true,
+ 0x2c88 => true,
+ 0x2c8a => true,
+ 0x2c8c => true,
+ 0x2c8e => true,
+ 0x2c90 => true,
+ 0x2c92 => true,
+ 0x2c94 => true,
+ 0x2c96 => true,
+ 0x2c98 => true,
+ 0x2c9a => true,
+ 0x2c9c => true,
+ 0x2c9e => true,
+ 0x2ca0 => true,
+ 0x2ca2 => true,
+ 0x2ca4 => true,
+ 0x2ca6 => true,
+ 0x2ca8 => true,
+ 0x2caa => true,
+ 0x2cac => true,
+ 0x2cae => true,
+ 0x2cb0 => true,
+ 0x2cb2 => true,
+ 0x2cb4 => true,
+ 0x2cb6 => true,
+ 0x2cb8 => true,
+ 0x2cba => true,
+ 0x2cbc => true,
+ 0x2cbe => true,
+ 0x2cc0 => true,
+ 0x2cc2 => true,
+ 0x2cc4 => true,
+ 0x2cc6 => true,
+ 0x2cc8 => true,
+ 0x2cca => true,
+ 0x2ccc => true,
+ 0x2cce => true,
+ 0x2cd0 => true,
+ 0x2cd2 => true,
+ 0x2cd4 => true,
+ 0x2cd6 => true,
+ 0x2cd8 => true,
+ 0x2cda => true,
+ 0x2cdc => true,
+ 0x2cde => true,
+ 0x2ce0 => true,
+ 0x2ce2 => true,
+ 0x2ceb => true,
+ 0x2ced => true,
+ 0x2cf2 => true,
+ 0xa640 => true,
+ 0xa642 => true,
+ 0xa644 => true,
+ 0xa646 => true,
+ 0xa648 => true,
+ 0xa64a => true,
+ 0xa64c => true,
+ 0xa64e => true,
+ 0xa650 => true,
+ 0xa652 => true,
+ 0xa654 => true,
+ 0xa656 => true,
+ 0xa658 => true,
+ 0xa65a => true,
+ 0xa65c => true,
+ 0xa65e => true,
+ 0xa660 => true,
+ 0xa662 => true,
+ 0xa664 => true,
+ 0xa666 => true,
+ 0xa668 => true,
+ 0xa66a => true,
+ 0xa66c => true,
+ 0xa680 => true,
+ 0xa682 => true,
+ 0xa684 => true,
+ 0xa686 => true,
+ 0xa688 => true,
+ 0xa68a => true,
+ 0xa68c => true,
+ 0xa68e => true,
+ 0xa690 => true,
+ 0xa692 => true,
+ 0xa694 => true,
+ 0xa696 => true,
+ 0xa698 => true,
+ 0xa69a => true,
+ 0xa722 => true,
+ 0xa724 => true,
+ 0xa726 => true,
+ 0xa728 => true,
+ 0xa72a => true,
+ 0xa72c => true,
+ 0xa72e => true,
+ 0xa732 => true,
+ 0xa734 => true,
+ 0xa736 => true,
+ 0xa738 => true,
+ 0xa73a => true,
+ 0xa73c => true,
+ 0xa73e => true,
+ 0xa740 => true,
+ 0xa742 => true,
+ 0xa744 => true,
+ 0xa746 => true,
+ 0xa748 => true,
+ 0xa74a => true,
+ 0xa74c => true,
+ 0xa74e => true,
+ 0xa750 => true,
+ 0xa752 => true,
+ 0xa754 => true,
+ 0xa756 => true,
+ 0xa758 => true,
+ 0xa75a => true,
+ 0xa75c => true,
+ 0xa75e => true,
+ 0xa760 => true,
+ 0xa762 => true,
+ 0xa764 => true,
+ 0xa766 => true,
+ 0xa768 => true,
+ 0xa76a => true,
+ 0xa76c => true,
+ 0xa76e => true,
+ 0xa779 => true,
+ 0xa77b => true,
+ 0xa77d...0xa77e => true,
+ 0xa780 => true,
+ 0xa782 => true,
+ 0xa784 => true,
+ 0xa786 => true,
+ 0xa78b => true,
+ 0xa78d => true,
+ 0xa790 => true,
+ 0xa792 => true,
+ 0xa796 => true,
+ 0xa798 => true,
+ 0xa79a => true,
+ 0xa79c => true,
+ 0xa79e => true,
+ 0xa7a0 => true,
+ 0xa7a2 => true,
+ 0xa7a4 => true,
+ 0xa7a6 => true,
+ 0xa7a8 => true,
+ 0xa7aa...0xa7ae => true,
+ 0xa7b0...0xa7b4 => true,
+ 0xa7b6 => true,
+ 0xa7b8 => true,
+ 0xa7ba => true,
+ 0xa7bc => true,
+ 0xa7be => true,
+ 0xa7c0 => true,
+ 0xa7c2 => true,
+ 0xa7c4...0xa7c7 => true,
+ 0xa7c9 => true,
+ 0xa7d0 => true,
+ 0xa7d6 => true,
+ 0xa7d8 => true,
+ 0xa7f5 => true,
+ 0xff21...0xff3a => true,
+ 0x10400...0x10427 => true,
+ 0x104b0...0x104d3 => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10c80...0x10cb2 => true,
+ 0x118a0...0x118bf => true,
+ 0x16e40...0x16e5f => true,
+ 0x1d400...0x1d419 => true,
+ 0x1d434...0x1d44d => true,
+ 0x1d468...0x1d481 => true,
+ 0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b5 => true,
+ 0x1d4d0...0x1d4e9 => true,
+ 0x1d504...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d538...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d56c...0x1d585 => true,
+ 0x1d5a0...0x1d5b9 => true,
+ 0x1d5d4...0x1d5ed => true,
+ 0x1d608...0x1d621 => true,
+ 0x1d63c...0x1d655 => true,
+ 0x1d670...0x1d689 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6e2...0x1d6fa => true,
+ 0x1d71c...0x1d734 => true,
+ 0x1d756...0x1d76e => true,
+ 0x1d790...0x1d7a8 => true,
+ 0x1d7ca => true,
+ 0x1e900...0x1e921 => true,
+ 0x1f130...0x1f149 => true,
+ 0x1f150...0x1f169 => true,
+ 0x1f170...0x1f189 => true,
+ else => false,
+ };
+}
+
+pub fn isCased(cp: u21) bool {
+ if (cp < 0x41 or cp > 0x1f189) return false;
+
+ return switch (cp) {
+ 0x41...0x5a => true,
+ 0x61...0x7a => true,
+ 0xaa => true,
+ 0xb5 => true,
+ 0xba => true,
+ 0xc0...0xd6 => true,
+ 0xd8...0xf6 => true,
+ 0xf8...0x1ba => true,
+ 0x1bc...0x1bf => true,
+ 0x1c4...0x293 => true,
+ 0x295...0x2af => true,
+ 0x2b0...0x2b8 => true,
+ 0x2c0...0x2c1 => true,
+ 0x2e0...0x2e4 => true,
+ 0x345 => true,
+ 0x370...0x373 => true,
+ 0x376...0x377 => true,
+ 0x37a => true,
+ 0x37b...0x37d => true,
+ 0x37f => true,
+ 0x386 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x3a1 => true,
+ 0x3a3...0x3f5 => true,
+ 0x3f7...0x481 => true,
+ 0x48a...0x52f => true,
+ 0x531...0x556 => true,
+ 0x560...0x588 => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x10d0...0x10fa => true,
+ 0x10fc => true,
+ 0x10fd...0x10ff => true,
+ 0x13a0...0x13f5 => true,
+ 0x13f8...0x13fd => true,
+ 0x1c80...0x1c88 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1d00...0x1d2b => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d6b...0x1d77 => true,
+ 0x1d78 => true,
+ 0x1d79...0x1d9a => true,
+ 0x1d9b...0x1dbf => true,
+ 0x1e00...0x1f15 => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f20...0x1f45 => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f...0x1f7d => true,
+ 0x1f80...0x1fb4 => true,
+ 0x1fb6...0x1fbc => true,
+ 0x1fbe => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fcc => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fdb => true,
+ 0x1fe0...0x1fec => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ffc => true,
+ 0x2071 => true,
+ 0x207f => true,
+ 0x2090...0x209c => true,
+ 0x2102 => true,
+ 0x2107 => true,
+ 0x210a...0x2113 => true,
+ 0x2115 => true,
+ 0x2119...0x211d => true,
+ 0x2124 => true,
+ 0x2126 => true,
+ 0x2128 => true,
+ 0x212a...0x212d => true,
+ 0x212f...0x2134 => true,
+ 0x2139 => true,
+ 0x213c...0x213f => true,
+ 0x2145...0x2149 => true,
+ 0x214e => true,
+ 0x2160...0x217f => true,
+ 0x2183...0x2184 => true,
+ 0x24b6...0x24e9 => true,
+ 0x2c00...0x2c7b => true,
+ 0x2c7c...0x2c7d => true,
+ 0x2c7e...0x2ce4 => true,
+ 0x2ceb...0x2cee => true,
+ 0x2cf2...0x2cf3 => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0xa640...0xa66d => true,
+ 0xa680...0xa69b => true,
+ 0xa69c...0xa69d => true,
+ 0xa722...0xa76f => true,
+ 0xa770 => true,
+ 0xa771...0xa787 => true,
+ 0xa78b...0xa78e => true,
+ 0xa790...0xa7ca => true,
+ 0xa7d0...0xa7d1 => true,
+ 0xa7d3 => true,
+ 0xa7d5...0xa7d9 => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f5...0xa7f6 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa7fa => true,
+ 0xab30...0xab5a => true,
+ 0xab5c...0xab5f => true,
+ 0xab60...0xab68 => true,
+ 0xab69 => true,
+ 0xab70...0xabbf => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xff21...0xff3a => true,
+ 0xff41...0xff5a => true,
+ 0x10400...0x1044f => true,
+ 0x104b0...0x104d3 => true,
+ 0x104d8...0x104fb => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10780 => true,
+ 0x10783...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x10c80...0x10cb2 => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x118a0...0x118df => true,
+ 0x16e40...0x16e7f => true,
+ 0x1d400...0x1d454 => true,
+ 0x1d456...0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d51e...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d552...0x1d6a5 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6dc...0x1d6fa => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d716...0x1d734 => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d750...0x1d76e => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d78a...0x1d7a8 => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c4...0x1d7cb => true,
+ 0x1df00...0x1df09 => true,
+ 0x1df0b...0x1df1e => true,
+ 0x1df25...0x1df2a => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e900...0x1e943 => true,
+ 0x1f130...0x1f149 => true,
+ 0x1f150...0x1f169 => true,
+ 0x1f170...0x1f189 => true,
+ else => false,
+ };
+}
+
+pub fn isCaseIgnorable(cp: u21) bool {
+ if (cp < 0x27 or cp > 0xe01ef) return false;
+
+ return switch (cp) {
+ 0x27 => true,
+ 0x2e => true,
+ 0x3a => true,
+ 0x5e => true,
+ 0x60 => true,
+ 0xa8 => true,
+ 0xad => true,
+ 0xaf => true,
+ 0xb4 => true,
+ 0xb7 => true,
+ 0xb8 => true,
+ 0x2b0...0x2c1 => true,
+ 0x2c2...0x2c5 => true,
+ 0x2c6...0x2d1 => true,
+ 0x2d2...0x2df => true,
+ 0x2e0...0x2e4 => true,
+ 0x2e5...0x2eb => true,
+ 0x2ec => true,
+ 0x2ed => true,
+ 0x2ee => true,
+ 0x2ef...0x2ff => true,
+ 0x300...0x36f => true,
+ 0x374 => true,
+ 0x375 => true,
+ 0x37a => true,
+ 0x384...0x385 => true,
+ 0x387 => true,
+ 0x483...0x487 => true,
+ 0x488...0x489 => true,
+ 0x559 => true,
+ 0x55f => true,
+ 0x591...0x5bd => true,
+ 0x5bf => true,
+ 0x5c1...0x5c2 => true,
+ 0x5c4...0x5c5 => true,
+ 0x5c7 => true,
+ 0x5f4 => true,
+ 0x600...0x605 => true,
+ 0x610...0x61a => true,
+ 0x61c => true,
+ 0x640 => true,
+ 0x64b...0x65f => true,
+ 0x670 => true,
+ 0x6d6...0x6dc => true,
+ 0x6dd => true,
+ 0x6df...0x6e4 => true,
+ 0x6e5...0x6e6 => true,
+ 0x6e7...0x6e8 => true,
+ 0x6ea...0x6ed => true,
+ 0x70f => true,
+ 0x711 => true,
+ 0x730...0x74a => true,
+ 0x7a6...0x7b0 => true,
+ 0x7eb...0x7f3 => true,
+ 0x7f4...0x7f5 => true,
+ 0x7fa => true,
+ 0x7fd => true,
+ 0x816...0x819 => true,
+ 0x81a => true,
+ 0x81b...0x823 => true,
+ 0x824 => true,
+ 0x825...0x827 => true,
+ 0x828 => true,
+ 0x829...0x82d => true,
+ 0x859...0x85b => true,
+ 0x888 => true,
+ 0x890...0x891 => true,
+ 0x898...0x89f => true,
+ 0x8c9 => true,
+ 0x8ca...0x8e1 => true,
+ 0x8e2 => true,
+ 0x8e3...0x902 => true,
+ 0x93a => true,
+ 0x93c => true,
+ 0x941...0x948 => true,
+ 0x94d => true,
+ 0x951...0x957 => true,
+ 0x962...0x963 => true,
+ 0x971 => true,
+ 0x981 => true,
+ 0x9bc => true,
+ 0x9c1...0x9c4 => true,
+ 0x9cd => true,
+ 0x9e2...0x9e3 => true,
+ 0x9fe => true,
+ 0xa01...0xa02 => true,
+ 0xa3c => true,
+ 0xa41...0xa42 => true,
+ 0xa47...0xa48 => true,
+ 0xa4b...0xa4d => true,
+ 0xa51 => true,
+ 0xa70...0xa71 => true,
+ 0xa75 => true,
+ 0xa81...0xa82 => true,
+ 0xabc => true,
+ 0xac1...0xac5 => true,
+ 0xac7...0xac8 => true,
+ 0xacd => true,
+ 0xae2...0xae3 => true,
+ 0xafa...0xaff => true,
+ 0xb01 => true,
+ 0xb3c => true,
+ 0xb3f => true,
+ 0xb41...0xb44 => true,
+ 0xb4d => true,
+ 0xb55...0xb56 => true,
+ 0xb62...0xb63 => true,
+ 0xb82 => true,
+ 0xbc0 => true,
+ 0xbcd => true,
+ 0xc00 => true,
+ 0xc04 => true,
+ 0xc3c => true,
+ 0xc3e...0xc40 => true,
+ 0xc46...0xc48 => true,
+ 0xc4a...0xc4d => true,
+ 0xc55...0xc56 => true,
+ 0xc62...0xc63 => true,
+ 0xc81 => true,
+ 0xcbc => true,
+ 0xcbf => true,
+ 0xcc6 => true,
+ 0xccc...0xccd => true,
+ 0xce2...0xce3 => true,
+ 0xd00...0xd01 => true,
+ 0xd3b...0xd3c => true,
+ 0xd41...0xd44 => true,
+ 0xd4d => true,
+ 0xd62...0xd63 => true,
+ 0xd81 => true,
+ 0xdca => true,
+ 0xdd2...0xdd4 => true,
+ 0xdd6 => true,
+ 0xe31 => true,
+ 0xe34...0xe3a => true,
+ 0xe46 => true,
+ 0xe47...0xe4e => true,
+ 0xeb1 => true,
+ 0xeb4...0xebc => true,
+ 0xec6 => true,
+ 0xec8...0xece => true,
+ 0xf18...0xf19 => true,
+ 0xf35 => true,
+ 0xf37 => true,
+ 0xf39 => true,
+ 0xf71...0xf7e => true,
+ 0xf80...0xf84 => true,
+ 0xf86...0xf87 => true,
+ 0xf8d...0xf97 => true,
+ 0xf99...0xfbc => true,
+ 0xfc6 => true,
+ 0x102d...0x1030 => true,
+ 0x1032...0x1037 => true,
+ 0x1039...0x103a => true,
+ 0x103d...0x103e => true,
+ 0x1058...0x1059 => true,
+ 0x105e...0x1060 => true,
+ 0x1071...0x1074 => true,
+ 0x1082 => true,
+ 0x1085...0x1086 => true,
+ 0x108d => true,
+ 0x109d => true,
+ 0x10fc => true,
+ 0x135d...0x135f => true,
+ 0x1712...0x1714 => true,
+ 0x1732...0x1733 => true,
+ 0x1752...0x1753 => true,
+ 0x1772...0x1773 => true,
+ 0x17b4...0x17b5 => true,
+ 0x17b7...0x17bd => true,
+ 0x17c6 => true,
+ 0x17c9...0x17d3 => true,
+ 0x17d7 => true,
+ 0x17dd => true,
+ 0x180b...0x180d => true,
+ 0x180e => true,
+ 0x180f => true,
+ 0x1843 => true,
+ 0x1885...0x1886 => true,
+ 0x18a9 => true,
+ 0x1920...0x1922 => true,
+ 0x1927...0x1928 => true,
+ 0x1932 => true,
+ 0x1939...0x193b => true,
+ 0x1a17...0x1a18 => true,
+ 0x1a1b => true,
+ 0x1a56 => true,
+ 0x1a58...0x1a5e => true,
+ 0x1a60 => true,
+ 0x1a62 => true,
+ 0x1a65...0x1a6c => true,
+ 0x1a73...0x1a7c => true,
+ 0x1a7f => true,
+ 0x1aa7 => true,
+ 0x1ab0...0x1abd => true,
+ 0x1abe => true,
+ 0x1abf...0x1ace => true,
+ 0x1b00...0x1b03 => true,
+ 0x1b34 => true,
+ 0x1b36...0x1b3a => true,
+ 0x1b3c => true,
+ 0x1b42 => true,
+ 0x1b6b...0x1b73 => true,
+ 0x1b80...0x1b81 => true,
+ 0x1ba2...0x1ba5 => true,
+ 0x1ba8...0x1ba9 => true,
+ 0x1bab...0x1bad => true,
+ 0x1be6 => true,
+ 0x1be8...0x1be9 => true,
+ 0x1bed => true,
+ 0x1bef...0x1bf1 => true,
+ 0x1c2c...0x1c33 => true,
+ 0x1c36...0x1c37 => true,
+ 0x1c78...0x1c7d => true,
+ 0x1cd0...0x1cd2 => true,
+ 0x1cd4...0x1ce0 => true,
+ 0x1ce2...0x1ce8 => true,
+ 0x1ced => true,
+ 0x1cf4 => true,
+ 0x1cf8...0x1cf9 => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d78 => true,
+ 0x1d9b...0x1dbf => true,
+ 0x1dc0...0x1dff => true,
+ 0x1fbd => true,
+ 0x1fbf...0x1fc1 => true,
+ 0x1fcd...0x1fcf => true,
+ 0x1fdd...0x1fdf => true,
+ 0x1fed...0x1fef => true,
+ 0x1ffd...0x1ffe => true,
+ 0x200b...0x200f => true,
+ 0x2018 => true,
+ 0x2019 => true,
+ 0x2024 => true,
+ 0x2027 => true,
+ 0x202a...0x202e => true,
+ 0x2060...0x2064 => true,
+ 0x2066...0x206f => true,
+ 0x2071 => true,
+ 0x207f => true,
+ 0x2090...0x209c => true,
+ 0x20d0...0x20dc => true,
+ 0x20dd...0x20e0 => true,
+ 0x20e1 => true,
+ 0x20e2...0x20e4 => true,
+ 0x20e5...0x20f0 => true,
+ 0x2c7c...0x2c7d => true,
+ 0x2cef...0x2cf1 => true,
+ 0x2d6f => true,
+ 0x2d7f => true,
+ 0x2de0...0x2dff => true,
+ 0x2e2f => true,
+ 0x3005 => true,
+ 0x302a...0x302d => true,
+ 0x3031...0x3035 => true,
+ 0x303b => true,
+ 0x3099...0x309a => true,
+ 0x309b...0x309c => true,
+ 0x309d...0x309e => true,
+ 0x30fc...0x30fe => true,
+ 0xa015 => true,
+ 0xa4f8...0xa4fd => true,
+ 0xa60c => true,
+ 0xa66f => true,
+ 0xa670...0xa672 => true,
+ 0xa674...0xa67d => true,
+ 0xa67f => true,
+ 0xa69c...0xa69d => true,
+ 0xa69e...0xa69f => true,
+ 0xa6f0...0xa6f1 => true,
+ 0xa700...0xa716 => true,
+ 0xa717...0xa71f => true,
+ 0xa720...0xa721 => true,
+ 0xa770 => true,
+ 0xa788 => true,
+ 0xa789...0xa78a => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa802 => true,
+ 0xa806 => true,
+ 0xa80b => true,
+ 0xa825...0xa826 => true,
+ 0xa82c => true,
+ 0xa8c4...0xa8c5 => true,
+ 0xa8e0...0xa8f1 => true,
+ 0xa8ff => true,
+ 0xa926...0xa92d => true,
+ 0xa947...0xa951 => true,
+ 0xa980...0xa982 => true,
+ 0xa9b3 => true,
+ 0xa9b6...0xa9b9 => true,
+ 0xa9bc...0xa9bd => true,
+ 0xa9cf => true,
+ 0xa9e5 => true,
+ 0xa9e6 => true,
+ 0xaa29...0xaa2e => true,
+ 0xaa31...0xaa32 => true,
+ 0xaa35...0xaa36 => true,
+ 0xaa43 => true,
+ 0xaa4c => true,
+ 0xaa70 => true,
+ 0xaa7c => true,
+ 0xaab0 => true,
+ 0xaab2...0xaab4 => true,
+ 0xaab7...0xaab8 => true,
+ 0xaabe...0xaabf => true,
+ 0xaac1 => true,
+ 0xaadd => true,
+ 0xaaec...0xaaed => true,
+ 0xaaf3...0xaaf4 => true,
+ 0xaaf6 => true,
+ 0xab5b => true,
+ 0xab5c...0xab5f => true,
+ 0xab69 => true,
+ 0xab6a...0xab6b => true,
+ 0xabe5 => true,
+ 0xabe8 => true,
+ 0xabed => true,
+ 0xfb1e => true,
+ 0xfbb2...0xfbc2 => true,
+ 0xfe00...0xfe0f => true,
+ 0xfe13 => true,
+ 0xfe20...0xfe2f => true,
+ 0xfe52 => true,
+ 0xfe55 => true,
+ 0xfeff => true,
+ 0xff07 => true,
+ 0xff0e => true,
+ 0xff1a => true,
+ 0xff3e => true,
+ 0xff40 => true,
+ 0xff70 => true,
+ 0xff9e...0xff9f => true,
+ 0xffe3 => true,
+ 0xfff9...0xfffb => true,
+ 0x101fd => true,
+ 0x102e0 => true,
+ 0x10376...0x1037a => true,
+ 0x10780...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x10a01...0x10a03 => true,
+ 0x10a05...0x10a06 => true,
+ 0x10a0c...0x10a0f => true,
+ 0x10a38...0x10a3a => true,
+ 0x10a3f => true,
+ 0x10ae5...0x10ae6 => true,
+ 0x10d24...0x10d27 => true,
+ 0x10eab...0x10eac => true,
+ 0x10efd...0x10eff => true,
+ 0x10f46...0x10f50 => true,
+ 0x10f82...0x10f85 => true,
+ 0x11001 => true,
+ 0x11038...0x11046 => true,
+ 0x11070 => true,
+ 0x11073...0x11074 => true,
+ 0x1107f...0x11081 => true,
+ 0x110b3...0x110b6 => true,
+ 0x110b9...0x110ba => true,
+ 0x110bd => true,
+ 0x110c2 => true,
+ 0x110cd => true,
+ 0x11100...0x11102 => true,
+ 0x11127...0x1112b => true,
+ 0x1112d...0x11134 => true,
+ 0x11173 => true,
+ 0x11180...0x11181 => true,
+ 0x111b6...0x111be => true,
+ 0x111c9...0x111cc => true,
+ 0x111cf => true,
+ 0x1122f...0x11231 => true,
+ 0x11234 => true,
+ 0x11236...0x11237 => true,
+ 0x1123e => true,
+ 0x11241 => true,
+ 0x112df => true,
+ 0x112e3...0x112ea => true,
+ 0x11300...0x11301 => true,
+ 0x1133b...0x1133c => true,
+ 0x11340 => true,
+ 0x11366...0x1136c => true,
+ 0x11370...0x11374 => true,
+ 0x11438...0x1143f => true,
+ 0x11442...0x11444 => true,
+ 0x11446 => true,
+ 0x1145e => true,
+ 0x114b3...0x114b8 => true,
+ 0x114ba => true,
+ 0x114bf...0x114c0 => true,
+ 0x114c2...0x114c3 => true,
+ 0x115b2...0x115b5 => true,
+ 0x115bc...0x115bd => true,
+ 0x115bf...0x115c0 => true,
+ 0x115dc...0x115dd => true,
+ 0x11633...0x1163a => true,
+ 0x1163d => true,
+ 0x1163f...0x11640 => true,
+ 0x116ab => true,
+ 0x116ad => true,
+ 0x116b0...0x116b5 => true,
+ 0x116b7 => true,
+ 0x1171d...0x1171f => true,
+ 0x11722...0x11725 => true,
+ 0x11727...0x1172b => true,
+ 0x1182f...0x11837 => true,
+ 0x11839...0x1183a => true,
+ 0x1193b...0x1193c => true,
+ 0x1193e => true,
+ 0x11943 => true,
+ 0x119d4...0x119d7 => true,
+ 0x119da...0x119db => true,
+ 0x119e0 => true,
+ 0x11a01...0x11a0a => true,
+ 0x11a33...0x11a38 => true,
+ 0x11a3b...0x11a3e => true,
+ 0x11a47 => true,
+ 0x11a51...0x11a56 => true,
+ 0x11a59...0x11a5b => true,
+ 0x11a8a...0x11a96 => true,
+ 0x11a98...0x11a99 => true,
+ 0x11c30...0x11c36 => true,
+ 0x11c38...0x11c3d => true,
+ 0x11c3f => true,
+ 0x11c92...0x11ca7 => true,
+ 0x11caa...0x11cb0 => true,
+ 0x11cb2...0x11cb3 => true,
+ 0x11cb5...0x11cb6 => true,
+ 0x11d31...0x11d36 => true,
+ 0x11d3a => true,
+ 0x11d3c...0x11d3d => true,
+ 0x11d3f...0x11d45 => true,
+ 0x11d47 => true,
+ 0x11d90...0x11d91 => true,
+ 0x11d95 => true,
+ 0x11d97 => true,
+ 0x11ef3...0x11ef4 => true,
+ 0x11f00...0x11f01 => true,
+ 0x11f36...0x11f3a => true,
+ 0x11f40 => true,
+ 0x11f42 => true,
+ 0x13430...0x1343f => true,
+ 0x13440 => true,
+ 0x13447...0x13455 => true,
+ 0x16af0...0x16af4 => true,
+ 0x16b30...0x16b36 => true,
+ 0x16b40...0x16b43 => true,
+ 0x16f4f => true,
+ 0x16f8f...0x16f92 => true,
+ 0x16f93...0x16f9f => true,
+ 0x16fe0...0x16fe1 => true,
+ 0x16fe3 => true,
+ 0x16fe4 => true,
+ 0x1aff0...0x1aff3 => true,
+ 0x1aff5...0x1affb => true,
+ 0x1affd...0x1affe => true,
+ 0x1bc9d...0x1bc9e => true,
+ 0x1bca0...0x1bca3 => true,
+ 0x1cf00...0x1cf2d => true,
+ 0x1cf30...0x1cf46 => true,
+ 0x1d167...0x1d169 => true,
+ 0x1d173...0x1d17a => true,
+ 0x1d17b...0x1d182 => true,
+ 0x1d185...0x1d18b => true,
+ 0x1d1aa...0x1d1ad => true,
+ 0x1d242...0x1d244 => true,
+ 0x1da00...0x1da36 => true,
+ 0x1da3b...0x1da6c => true,
+ 0x1da75 => true,
+ 0x1da84 => true,
+ 0x1da9b...0x1da9f => true,
+ 0x1daa1...0x1daaf => true,
+ 0x1e000...0x1e006 => true,
+ 0x1e008...0x1e018 => true,
+ 0x1e01b...0x1e021 => true,
+ 0x1e023...0x1e024 => true,
+ 0x1e026...0x1e02a => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e08f => true,
+ 0x1e130...0x1e136 => true,
+ 0x1e137...0x1e13d => true,
+ 0x1e2ae => true,
+ 0x1e2ec...0x1e2ef => true,
+ 0x1e4eb => true,
+ 0x1e4ec...0x1e4ef => true,
+ 0x1e8d0...0x1e8d6 => true,
+ 0x1e944...0x1e94a => true,
+ 0x1e94b => true,
+ 0x1f3fb...0x1f3ff => true,
+ 0xe0001 => true,
+ 0xe0020...0xe007f => true,
+ 0xe0100...0xe01ef => true,
+ else => false,
+ };
+}
+
+pub fn isChangesWhenLowercased(cp: u21) bool {
+ if (cp < 0x41 or cp > 0x1e921) return false;
+
+ return switch (cp) {
+ 0x41...0x5a => true,
+ 0xc0...0xd6 => true,
+ 0xd8...0xde => true,
+ 0x100 => true,
+ 0x102 => true,
+ 0x104 => true,
+ 0x106 => true,
+ 0x108 => true,
+ 0x10a => true,
+ 0x10c => true,
+ 0x10e => true,
+ 0x110 => true,
+ 0x112 => true,
+ 0x114 => true,
+ 0x116 => true,
+ 0x118 => true,
+ 0x11a => true,
+ 0x11c => true,
+ 0x11e => true,
+ 0x120 => true,
+ 0x122 => true,
+ 0x124 => true,
+ 0x126 => true,
+ 0x128 => true,
+ 0x12a => true,
+ 0x12c => true,
+ 0x12e => true,
+ 0x130 => true,
+ 0x132 => true,
+ 0x134 => true,
+ 0x136 => true,
+ 0x139 => true,
+ 0x13b => true,
+ 0x13d => true,
+ 0x13f => true,
+ 0x141 => true,
+ 0x143 => true,
+ 0x145 => true,
+ 0x147 => true,
+ 0x14a => true,
+ 0x14c => true,
+ 0x14e => true,
+ 0x150 => true,
+ 0x152 => true,
+ 0x154 => true,
+ 0x156 => true,
+ 0x158 => true,
+ 0x15a => true,
+ 0x15c => true,
+ 0x15e => true,
+ 0x160 => true,
+ 0x162 => true,
+ 0x164 => true,
+ 0x166 => true,
+ 0x168 => true,
+ 0x16a => true,
+ 0x16c => true,
+ 0x16e => true,
+ 0x170 => true,
+ 0x172 => true,
+ 0x174 => true,
+ 0x176 => true,
+ 0x178...0x179 => true,
+ 0x17b => true,
+ 0x17d => true,
+ 0x181...0x182 => true,
+ 0x184 => true,
+ 0x186...0x187 => true,
+ 0x189...0x18b => true,
+ 0x18e...0x191 => true,
+ 0x193...0x194 => true,
+ 0x196...0x198 => true,
+ 0x19c...0x19d => true,
+ 0x19f...0x1a0 => true,
+ 0x1a2 => true,
+ 0x1a4 => true,
+ 0x1a6...0x1a7 => true,
+ 0x1a9 => true,
+ 0x1ac => true,
+ 0x1ae...0x1af => true,
+ 0x1b1...0x1b3 => true,
+ 0x1b5 => true,
+ 0x1b7...0x1b8 => true,
+ 0x1bc => true,
+ 0x1c4...0x1c5 => true,
+ 0x1c7...0x1c8 => true,
+ 0x1ca...0x1cb => true,
+ 0x1cd => true,
+ 0x1cf => true,
+ 0x1d1 => true,
+ 0x1d3 => true,
+ 0x1d5 => true,
+ 0x1d7 => true,
+ 0x1d9 => true,
+ 0x1db => true,
+ 0x1de => true,
+ 0x1e0 => true,
+ 0x1e2 => true,
+ 0x1e4 => true,
+ 0x1e6 => true,
+ 0x1e8 => true,
+ 0x1ea => true,
+ 0x1ec => true,
+ 0x1ee => true,
+ 0x1f1...0x1f2 => true,
+ 0x1f4 => true,
+ 0x1f6...0x1f8 => true,
+ 0x1fa => true,
+ 0x1fc => true,
+ 0x1fe => true,
+ 0x200 => true,
+ 0x202 => true,
+ 0x204 => true,
+ 0x206 => true,
+ 0x208 => true,
+ 0x20a => true,
+ 0x20c => true,
+ 0x20e => true,
+ 0x210 => true,
+ 0x212 => true,
+ 0x214 => true,
+ 0x216 => true,
+ 0x218 => true,
+ 0x21a => true,
+ 0x21c => true,
+ 0x21e => true,
+ 0x220 => true,
+ 0x222 => true,
+ 0x224 => true,
+ 0x226 => true,
+ 0x228 => true,
+ 0x22a => true,
+ 0x22c => true,
+ 0x22e => true,
+ 0x230 => true,
+ 0x232 => true,
+ 0x23a...0x23b => true,
+ 0x23d...0x23e => true,
+ 0x241 => true,
+ 0x243...0x246 => true,
+ 0x248 => true,
+ 0x24a => true,
+ 0x24c => true,
+ 0x24e => true,
+ 0x370 => true,
+ 0x372 => true,
+ 0x376 => true,
+ 0x37f => true,
+ 0x386 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x38f => true,
+ 0x391...0x3a1 => true,
+ 0x3a3...0x3ab => true,
+ 0x3cf => true,
+ 0x3d8 => true,
+ 0x3da => true,
+ 0x3dc => true,
+ 0x3de => true,
+ 0x3e0 => true,
+ 0x3e2 => true,
+ 0x3e4 => true,
+ 0x3e6 => true,
+ 0x3e8 => true,
+ 0x3ea => true,
+ 0x3ec => true,
+ 0x3ee => true,
+ 0x3f4 => true,
+ 0x3f7 => true,
+ 0x3f9...0x3fa => true,
+ 0x3fd...0x42f => true,
+ 0x460 => true,
+ 0x462 => true,
+ 0x464 => true,
+ 0x466 => true,
+ 0x468 => true,
+ 0x46a => true,
+ 0x46c => true,
+ 0x46e => true,
+ 0x470 => true,
+ 0x472 => true,
+ 0x474 => true,
+ 0x476 => true,
+ 0x478 => true,
+ 0x47a => true,
+ 0x47c => true,
+ 0x47e => true,
+ 0x480 => true,
+ 0x48a => true,
+ 0x48c => true,
+ 0x48e => true,
+ 0x490 => true,
+ 0x492 => true,
+ 0x494 => true,
+ 0x496 => true,
+ 0x498 => true,
+ 0x49a => true,
+ 0x49c => true,
+ 0x49e => true,
+ 0x4a0 => true,
+ 0x4a2 => true,
+ 0x4a4 => true,
+ 0x4a6 => true,
+ 0x4a8 => true,
+ 0x4aa => true,
+ 0x4ac => true,
+ 0x4ae => true,
+ 0x4b0 => true,
+ 0x4b2 => true,
+ 0x4b4 => true,
+ 0x4b6 => true,
+ 0x4b8 => true,
+ 0x4ba => true,
+ 0x4bc => true,
+ 0x4be => true,
+ 0x4c0...0x4c1 => true,
+ 0x4c3 => true,
+ 0x4c5 => true,
+ 0x4c7 => true,
+ 0x4c9 => true,
+ 0x4cb => true,
+ 0x4cd => true,
+ 0x4d0 => true,
+ 0x4d2 => true,
+ 0x4d4 => true,
+ 0x4d6 => true,
+ 0x4d8 => true,
+ 0x4da => true,
+ 0x4dc => true,
+ 0x4de => true,
+ 0x4e0 => true,
+ 0x4e2 => true,
+ 0x4e4 => true,
+ 0x4e6 => true,
+ 0x4e8 => true,
+ 0x4ea => true,
+ 0x4ec => true,
+ 0x4ee => true,
+ 0x4f0 => true,
+ 0x4f2 => true,
+ 0x4f4 => true,
+ 0x4f6 => true,
+ 0x4f8 => true,
+ 0x4fa => true,
+ 0x4fc => true,
+ 0x4fe => true,
+ 0x500 => true,
+ 0x502 => true,
+ 0x504 => true,
+ 0x506 => true,
+ 0x508 => true,
+ 0x50a => true,
+ 0x50c => true,
+ 0x50e => true,
+ 0x510 => true,
+ 0x512 => true,
+ 0x514 => true,
+ 0x516 => true,
+ 0x518 => true,
+ 0x51a => true,
+ 0x51c => true,
+ 0x51e => true,
+ 0x520 => true,
+ 0x522 => true,
+ 0x524 => true,
+ 0x526 => true,
+ 0x528 => true,
+ 0x52a => true,
+ 0x52c => true,
+ 0x52e => true,
+ 0x531...0x556 => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x13a0...0x13f5 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1e00 => true,
+ 0x1e02 => true,
+ 0x1e04 => true,
+ 0x1e06 => true,
+ 0x1e08 => true,
+ 0x1e0a => true,
+ 0x1e0c => true,
+ 0x1e0e => true,
+ 0x1e10 => true,
+ 0x1e12 => true,
+ 0x1e14 => true,
+ 0x1e16 => true,
+ 0x1e18 => true,
+ 0x1e1a => true,
+ 0x1e1c => true,
+ 0x1e1e => true,
+ 0x1e20 => true,
+ 0x1e22 => true,
+ 0x1e24 => true,
+ 0x1e26 => true,
+ 0x1e28 => true,
+ 0x1e2a => true,
+ 0x1e2c => true,
+ 0x1e2e => true,
+ 0x1e30 => true,
+ 0x1e32 => true,
+ 0x1e34 => true,
+ 0x1e36 => true,
+ 0x1e38 => true,
+ 0x1e3a => true,
+ 0x1e3c => true,
+ 0x1e3e => true,
+ 0x1e40 => true,
+ 0x1e42 => true,
+ 0x1e44 => true,
+ 0x1e46 => true,
+ 0x1e48 => true,
+ 0x1e4a => true,
+ 0x1e4c => true,
+ 0x1e4e => true,
+ 0x1e50 => true,
+ 0x1e52 => true,
+ 0x1e54 => true,
+ 0x1e56 => true,
+ 0x1e58 => true,
+ 0x1e5a => true,
+ 0x1e5c => true,
+ 0x1e5e => true,
+ 0x1e60 => true,
+ 0x1e62 => true,
+ 0x1e64 => true,
+ 0x1e66 => true,
+ 0x1e68 => true,
+ 0x1e6a => true,
+ 0x1e6c => true,
+ 0x1e6e => true,
+ 0x1e70 => true,
+ 0x1e72 => true,
+ 0x1e74 => true,
+ 0x1e76 => true,
+ 0x1e78 => true,
+ 0x1e7a => true,
+ 0x1e7c => true,
+ 0x1e7e => true,
+ 0x1e80 => true,
+ 0x1e82 => true,
+ 0x1e84 => true,
+ 0x1e86 => true,
+ 0x1e88 => true,
+ 0x1e8a => true,
+ 0x1e8c => true,
+ 0x1e8e => true,
+ 0x1e90 => true,
+ 0x1e92 => true,
+ 0x1e94 => true,
+ 0x1e9e => true,
+ 0x1ea0 => true,
+ 0x1ea2 => true,
+ 0x1ea4 => true,
+ 0x1ea6 => true,
+ 0x1ea8 => true,
+ 0x1eaa => true,
+ 0x1eac => true,
+ 0x1eae => true,
+ 0x1eb0 => true,
+ 0x1eb2 => true,
+ 0x1eb4 => true,
+ 0x1eb6 => true,
+ 0x1eb8 => true,
+ 0x1eba => true,
+ 0x1ebc => true,
+ 0x1ebe => true,
+ 0x1ec0 => true,
+ 0x1ec2 => true,
+ 0x1ec4 => true,
+ 0x1ec6 => true,
+ 0x1ec8 => true,
+ 0x1eca => true,
+ 0x1ecc => true,
+ 0x1ece => true,
+ 0x1ed0 => true,
+ 0x1ed2 => true,
+ 0x1ed4 => true,
+ 0x1ed6 => true,
+ 0x1ed8 => true,
+ 0x1eda => true,
+ 0x1edc => true,
+ 0x1ede => true,
+ 0x1ee0 => true,
+ 0x1ee2 => true,
+ 0x1ee4 => true,
+ 0x1ee6 => true,
+ 0x1ee8 => true,
+ 0x1eea => true,
+ 0x1eec => true,
+ 0x1eee => true,
+ 0x1ef0 => true,
+ 0x1ef2 => true,
+ 0x1ef4 => true,
+ 0x1ef6 => true,
+ 0x1ef8 => true,
+ 0x1efa => true,
+ 0x1efc => true,
+ 0x1efe => true,
+ 0x1f08...0x1f0f => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f28...0x1f2f => true,
+ 0x1f38...0x1f3f => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f => true,
+ 0x1f68...0x1f6f => true,
+ 0x1f88...0x1f8f => true,
+ 0x1f98...0x1f9f => true,
+ 0x1fa8...0x1faf => true,
+ 0x1fb8...0x1fbc => true,
+ 0x1fc8...0x1fcc => true,
+ 0x1fd8...0x1fdb => true,
+ 0x1fe8...0x1fec => true,
+ 0x1ff8...0x1ffc => true,
+ 0x2126 => true,
+ 0x212a...0x212b => true,
+ 0x2132 => true,
+ 0x2160...0x216f => true,
+ 0x2183 => true,
+ 0x24b6...0x24cf => true,
+ 0x2c00...0x2c2f => true,
+ 0x2c60 => true,
+ 0x2c62...0x2c64 => true,
+ 0x2c67 => true,
+ 0x2c69 => true,
+ 0x2c6b => true,
+ 0x2c6d...0x2c70 => true,
+ 0x2c72 => true,
+ 0x2c75 => true,
+ 0x2c7e...0x2c80 => true,
+ 0x2c82 => true,
+ 0x2c84 => true,
+ 0x2c86 => true,
+ 0x2c88 => true,
+ 0x2c8a => true,
+ 0x2c8c => true,
+ 0x2c8e => true,
+ 0x2c90 => true,
+ 0x2c92 => true,
+ 0x2c94 => true,
+ 0x2c96 => true,
+ 0x2c98 => true,
+ 0x2c9a => true,
+ 0x2c9c => true,
+ 0x2c9e => true,
+ 0x2ca0 => true,
+ 0x2ca2 => true,
+ 0x2ca4 => true,
+ 0x2ca6 => true,
+ 0x2ca8 => true,
+ 0x2caa => true,
+ 0x2cac => true,
+ 0x2cae => true,
+ 0x2cb0 => true,
+ 0x2cb2 => true,
+ 0x2cb4 => true,
+ 0x2cb6 => true,
+ 0x2cb8 => true,
+ 0x2cba => true,
+ 0x2cbc => true,
+ 0x2cbe => true,
+ 0x2cc0 => true,
+ 0x2cc2 => true,
+ 0x2cc4 => true,
+ 0x2cc6 => true,
+ 0x2cc8 => true,
+ 0x2cca => true,
+ 0x2ccc => true,
+ 0x2cce => true,
+ 0x2cd0 => true,
+ 0x2cd2 => true,
+ 0x2cd4 => true,
+ 0x2cd6 => true,
+ 0x2cd8 => true,
+ 0x2cda => true,
+ 0x2cdc => true,
+ 0x2cde => true,
+ 0x2ce0 => true,
+ 0x2ce2 => true,
+ 0x2ceb => true,
+ 0x2ced => true,
+ 0x2cf2 => true,
+ 0xa640 => true,
+ 0xa642 => true,
+ 0xa644 => true,
+ 0xa646 => true,
+ 0xa648 => true,
+ 0xa64a => true,
+ 0xa64c => true,
+ 0xa64e => true,
+ 0xa650 => true,
+ 0xa652 => true,
+ 0xa654 => true,
+ 0xa656 => true,
+ 0xa658 => true,
+ 0xa65a => true,
+ 0xa65c => true,
+ 0xa65e => true,
+ 0xa660 => true,
+ 0xa662 => true,
+ 0xa664 => true,
+ 0xa666 => true,
+ 0xa668 => true,
+ 0xa66a => true,
+ 0xa66c => true,
+ 0xa680 => true,
+ 0xa682 => true,
+ 0xa684 => true,
+ 0xa686 => true,
+ 0xa688 => true,
+ 0xa68a => true,
+ 0xa68c => true,
+ 0xa68e => true,
+ 0xa690 => true,
+ 0xa692 => true,
+ 0xa694 => true,
+ 0xa696 => true,
+ 0xa698 => true,
+ 0xa69a => true,
+ 0xa722 => true,
+ 0xa724 => true,
+ 0xa726 => true,
+ 0xa728 => true,
+ 0xa72a => true,
+ 0xa72c => true,
+ 0xa72e => true,
+ 0xa732 => true,
+ 0xa734 => true,
+ 0xa736 => true,
+ 0xa738 => true,
+ 0xa73a => true,
+ 0xa73c => true,
+ 0xa73e => true,
+ 0xa740 => true,
+ 0xa742 => true,
+ 0xa744 => true,
+ 0xa746 => true,
+ 0xa748 => true,
+ 0xa74a => true,
+ 0xa74c => true,
+ 0xa74e => true,
+ 0xa750 => true,
+ 0xa752 => true,
+ 0xa754 => true,
+ 0xa756 => true,
+ 0xa758 => true,
+ 0xa75a => true,
+ 0xa75c => true,
+ 0xa75e => true,
+ 0xa760 => true,
+ 0xa762 => true,
+ 0xa764 => true,
+ 0xa766 => true,
+ 0xa768 => true,
+ 0xa76a => true,
+ 0xa76c => true,
+ 0xa76e => true,
+ 0xa779 => true,
+ 0xa77b => true,
+ 0xa77d...0xa77e => true,
+ 0xa780 => true,
+ 0xa782 => true,
+ 0xa784 => true,
+ 0xa786 => true,
+ 0xa78b => true,
+ 0xa78d => true,
+ 0xa790 => true,
+ 0xa792 => true,
+ 0xa796 => true,
+ 0xa798 => true,
+ 0xa79a => true,
+ 0xa79c => true,
+ 0xa79e => true,
+ 0xa7a0 => true,
+ 0xa7a2 => true,
+ 0xa7a4 => true,
+ 0xa7a6 => true,
+ 0xa7a8 => true,
+ 0xa7aa...0xa7ae => true,
+ 0xa7b0...0xa7b4 => true,
+ 0xa7b6 => true,
+ 0xa7b8 => true,
+ 0xa7ba => true,
+ 0xa7bc => true,
+ 0xa7be => true,
+ 0xa7c0 => true,
+ 0xa7c2 => true,
+ 0xa7c4...0xa7c7 => true,
+ 0xa7c9 => true,
+ 0xa7d0 => true,
+ 0xa7d6 => true,
+ 0xa7d8 => true,
+ 0xa7f5 => true,
+ 0xff21...0xff3a => true,
+ 0x10400...0x10427 => true,
+ 0x104b0...0x104d3 => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10c80...0x10cb2 => true,
+ 0x118a0...0x118bf => true,
+ 0x16e40...0x16e5f => true,
+ 0x1e900...0x1e921 => true,
+ else => false,
+ };
+}
+
+pub fn isChangesWhenUppercased(cp: u21) bool {
+ if (cp < 0x61 or cp > 0x1e943) return false;
+
+ return switch (cp) {
+ 0x61...0x7a => true,
+ 0xb5 => true,
+ 0xdf...0xf6 => true,
+ 0xf8...0xff => true,
+ 0x101 => true,
+ 0x103 => true,
+ 0x105 => true,
+ 0x107 => true,
+ 0x109 => true,
+ 0x10b => true,
+ 0x10d => true,
+ 0x10f => true,
+ 0x111 => true,
+ 0x113 => true,
+ 0x115 => true,
+ 0x117 => true,
+ 0x119 => true,
+ 0x11b => true,
+ 0x11d => true,
+ 0x11f => true,
+ 0x121 => true,
+ 0x123 => true,
+ 0x125 => true,
+ 0x127 => true,
+ 0x129 => true,
+ 0x12b => true,
+ 0x12d => true,
+ 0x12f => true,
+ 0x131 => true,
+ 0x133 => true,
+ 0x135 => true,
+ 0x137 => true,
+ 0x13a => true,
+ 0x13c => true,
+ 0x13e => true,
+ 0x140 => true,
+ 0x142 => true,
+ 0x144 => true,
+ 0x146 => true,
+ 0x148...0x149 => true,
+ 0x14b => true,
+ 0x14d => true,
+ 0x14f => true,
+ 0x151 => true,
+ 0x153 => true,
+ 0x155 => true,
+ 0x157 => true,
+ 0x159 => true,
+ 0x15b => true,
+ 0x15d => true,
+ 0x15f => true,
+ 0x161 => true,
+ 0x163 => true,
+ 0x165 => true,
+ 0x167 => true,
+ 0x169 => true,
+ 0x16b => true,
+ 0x16d => true,
+ 0x16f => true,
+ 0x171 => true,
+ 0x173 => true,
+ 0x175 => true,
+ 0x177 => true,
+ 0x17a => true,
+ 0x17c => true,
+ 0x17e...0x180 => true,
+ 0x183 => true,
+ 0x185 => true,
+ 0x188 => true,
+ 0x18c => true,
+ 0x192 => true,
+ 0x195 => true,
+ 0x199...0x19a => true,
+ 0x19e => true,
+ 0x1a1 => true,
+ 0x1a3 => true,
+ 0x1a5 => true,
+ 0x1a8 => true,
+ 0x1ad => true,
+ 0x1b0 => true,
+ 0x1b4 => true,
+ 0x1b6 => true,
+ 0x1b9 => true,
+ 0x1bd => true,
+ 0x1bf => true,
+ 0x1c5...0x1c6 => true,
+ 0x1c8...0x1c9 => true,
+ 0x1cb...0x1cc => true,
+ 0x1ce => true,
+ 0x1d0 => true,
+ 0x1d2 => true,
+ 0x1d4 => true,
+ 0x1d6 => true,
+ 0x1d8 => true,
+ 0x1da => true,
+ 0x1dc...0x1dd => true,
+ 0x1df => true,
+ 0x1e1 => true,
+ 0x1e3 => true,
+ 0x1e5 => true,
+ 0x1e7 => true,
+ 0x1e9 => true,
+ 0x1eb => true,
+ 0x1ed => true,
+ 0x1ef...0x1f0 => true,
+ 0x1f2...0x1f3 => true,
+ 0x1f5 => true,
+ 0x1f9 => true,
+ 0x1fb => true,
+ 0x1fd => true,
+ 0x1ff => true,
+ 0x201 => true,
+ 0x203 => true,
+ 0x205 => true,
+ 0x207 => true,
+ 0x209 => true,
+ 0x20b => true,
+ 0x20d => true,
+ 0x20f => true,
+ 0x211 => true,
+ 0x213 => true,
+ 0x215 => true,
+ 0x217 => true,
+ 0x219 => true,
+ 0x21b => true,
+ 0x21d => true,
+ 0x21f => true,
+ 0x223 => true,
+ 0x225 => true,
+ 0x227 => true,
+ 0x229 => true,
+ 0x22b => true,
+ 0x22d => true,
+ 0x22f => true,
+ 0x231 => true,
+ 0x233 => true,
+ 0x23c => true,
+ 0x23f...0x240 => true,
+ 0x242 => true,
+ 0x247 => true,
+ 0x249 => true,
+ 0x24b => true,
+ 0x24d => true,
+ 0x24f...0x254 => true,
+ 0x256...0x257 => true,
+ 0x259 => true,
+ 0x25b...0x25c => true,
+ 0x260...0x261 => true,
+ 0x263 => true,
+ 0x265...0x266 => true,
+ 0x268...0x26c => true,
+ 0x26f => true,
+ 0x271...0x272 => true,
+ 0x275 => true,
+ 0x27d => true,
+ 0x280 => true,
+ 0x282...0x283 => true,
+ 0x287...0x28c => true,
+ 0x292 => true,
+ 0x29d...0x29e => true,
+ 0x345 => true,
+ 0x371 => true,
+ 0x373 => true,
+ 0x377 => true,
+ 0x37b...0x37d => true,
+ 0x390 => true,
+ 0x3ac...0x3ce => true,
+ 0x3d0...0x3d1 => true,
+ 0x3d5...0x3d7 => true,
+ 0x3d9 => true,
+ 0x3db => true,
+ 0x3dd => true,
+ 0x3df => true,
+ 0x3e1 => true,
+ 0x3e3 => true,
+ 0x3e5 => true,
+ 0x3e7 => true,
+ 0x3e9 => true,
+ 0x3eb => true,
+ 0x3ed => true,
+ 0x3ef...0x3f3 => true,
+ 0x3f5 => true,
+ 0x3f8 => true,
+ 0x3fb => true,
+ 0x430...0x45f => true,
+ 0x461 => true,
+ 0x463 => true,
+ 0x465 => true,
+ 0x467 => true,
+ 0x469 => true,
+ 0x46b => true,
+ 0x46d => true,
+ 0x46f => true,
+ 0x471 => true,
+ 0x473 => true,
+ 0x475 => true,
+ 0x477 => true,
+ 0x479 => true,
+ 0x47b => true,
+ 0x47d => true,
+ 0x47f => true,
+ 0x481 => true,
+ 0x48b => true,
+ 0x48d => true,
+ 0x48f => true,
+ 0x491 => true,
+ 0x493 => true,
+ 0x495 => true,
+ 0x497 => true,
+ 0x499 => true,
+ 0x49b => true,
+ 0x49d => true,
+ 0x49f => true,
+ 0x4a1 => true,
+ 0x4a3 => true,
+ 0x4a5 => true,
+ 0x4a7 => true,
+ 0x4a9 => true,
+ 0x4ab => true,
+ 0x4ad => true,
+ 0x4af => true,
+ 0x4b1 => true,
+ 0x4b3 => true,
+ 0x4b5 => true,
+ 0x4b7 => true,
+ 0x4b9 => true,
+ 0x4bb => true,
+ 0x4bd => true,
+ 0x4bf => true,
+ 0x4c2 => true,
+ 0x4c4 => true,
+ 0x4c6 => true,
+ 0x4c8 => true,
+ 0x4ca => true,
+ 0x4cc => true,
+ 0x4ce...0x4cf => true,
+ 0x4d1 => true,
+ 0x4d3 => true,
+ 0x4d5 => true,
+ 0x4d7 => true,
+ 0x4d9 => true,
+ 0x4db => true,
+ 0x4dd => true,
+ 0x4df => true,
+ 0x4e1 => true,
+ 0x4e3 => true,
+ 0x4e5 => true,
+ 0x4e7 => true,
+ 0x4e9 => true,
+ 0x4eb => true,
+ 0x4ed => true,
+ 0x4ef => true,
+ 0x4f1 => true,
+ 0x4f3 => true,
+ 0x4f5 => true,
+ 0x4f7 => true,
+ 0x4f9 => true,
+ 0x4fb => true,
+ 0x4fd => true,
+ 0x4ff => true,
+ 0x501 => true,
+ 0x503 => true,
+ 0x505 => true,
+ 0x507 => true,
+ 0x509 => true,
+ 0x50b => true,
+ 0x50d => true,
+ 0x50f => true,
+ 0x511 => true,
+ 0x513 => true,
+ 0x515 => true,
+ 0x517 => true,
+ 0x519 => true,
+ 0x51b => true,
+ 0x51d => true,
+ 0x51f => true,
+ 0x521 => true,
+ 0x523 => true,
+ 0x525 => true,
+ 0x527 => true,
+ 0x529 => true,
+ 0x52b => true,
+ 0x52d => true,
+ 0x52f => true,
+ 0x561...0x587 => true,
+ 0x10d0...0x10fa => true,
+ 0x10fd...0x10ff => true,
+ 0x13f8...0x13fd => true,
+ 0x1c80...0x1c88 => true,
+ 0x1d79 => true,
+ 0x1d7d => true,
+ 0x1d8e => true,
+ 0x1e01 => true,
+ 0x1e03 => true,
+ 0x1e05 => true,
+ 0x1e07 => true,
+ 0x1e09 => true,
+ 0x1e0b => true,
+ 0x1e0d => true,
+ 0x1e0f => true,
+ 0x1e11 => true,
+ 0x1e13 => true,
+ 0x1e15 => true,
+ 0x1e17 => true,
+ 0x1e19 => true,
+ 0x1e1b => true,
+ 0x1e1d => true,
+ 0x1e1f => true,
+ 0x1e21 => true,
+ 0x1e23 => true,
+ 0x1e25 => true,
+ 0x1e27 => true,
+ 0x1e29 => true,
+ 0x1e2b => true,
+ 0x1e2d => true,
+ 0x1e2f => true,
+ 0x1e31 => true,
+ 0x1e33 => true,
+ 0x1e35 => true,
+ 0x1e37 => true,
+ 0x1e39 => true,
+ 0x1e3b => true,
+ 0x1e3d => true,
+ 0x1e3f => true,
+ 0x1e41 => true,
+ 0x1e43 => true,
+ 0x1e45 => true,
+ 0x1e47 => true,
+ 0x1e49 => true,
+ 0x1e4b => true,
+ 0x1e4d => true,
+ 0x1e4f => true,
+ 0x1e51 => true,
+ 0x1e53 => true,
+ 0x1e55 => true,
+ 0x1e57 => true,
+ 0x1e59 => true,
+ 0x1e5b => true,
+ 0x1e5d => true,
+ 0x1e5f => true,
+ 0x1e61 => true,
+ 0x1e63 => true,
+ 0x1e65 => true,
+ 0x1e67 => true,
+ 0x1e69 => true,
+ 0x1e6b => true,
+ 0x1e6d => true,
+ 0x1e6f => true,
+ 0x1e71 => true,
+ 0x1e73 => true,
+ 0x1e75 => true,
+ 0x1e77 => true,
+ 0x1e79 => true,
+ 0x1e7b => true,
+ 0x1e7d => true,
+ 0x1e7f => true,
+ 0x1e81 => true,
+ 0x1e83 => true,
+ 0x1e85 => true,
+ 0x1e87 => true,
+ 0x1e89 => true,
+ 0x1e8b => true,
+ 0x1e8d => true,
+ 0x1e8f => true,
+ 0x1e91 => true,
+ 0x1e93 => true,
+ 0x1e95...0x1e9b => true,
+ 0x1ea1 => true,
+ 0x1ea3 => true,
+ 0x1ea5 => true,
+ 0x1ea7 => true,
+ 0x1ea9 => true,
+ 0x1eab => true,
+ 0x1ead => true,
+ 0x1eaf => true,
+ 0x1eb1 => true,
+ 0x1eb3 => true,
+ 0x1eb5 => true,
+ 0x1eb7 => true,
+ 0x1eb9 => true,
+ 0x1ebb => true,
+ 0x1ebd => true,
+ 0x1ebf => true,
+ 0x1ec1 => true,
+ 0x1ec3 => true,
+ 0x1ec5 => true,
+ 0x1ec7 => true,
+ 0x1ec9 => true,
+ 0x1ecb => true,
+ 0x1ecd => true,
+ 0x1ecf => true,
+ 0x1ed1 => true,
+ 0x1ed3 => true,
+ 0x1ed5 => true,
+ 0x1ed7 => true,
+ 0x1ed9 => true,
+ 0x1edb => true,
+ 0x1edd => true,
+ 0x1edf => true,
+ 0x1ee1 => true,
+ 0x1ee3 => true,
+ 0x1ee5 => true,
+ 0x1ee7 => true,
+ 0x1ee9 => true,
+ 0x1eeb => true,
+ 0x1eed => true,
+ 0x1eef => true,
+ 0x1ef1 => true,
+ 0x1ef3 => true,
+ 0x1ef5 => true,
+ 0x1ef7 => true,
+ 0x1ef9 => true,
+ 0x1efb => true,
+ 0x1efd => true,
+ 0x1eff...0x1f07 => true,
+ 0x1f10...0x1f15 => true,
+ 0x1f20...0x1f27 => true,
+ 0x1f30...0x1f37 => true,
+ 0x1f40...0x1f45 => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f60...0x1f67 => true,
+ 0x1f70...0x1f7d => true,
+ 0x1f80...0x1fb4 => true,
+ 0x1fb6...0x1fb7 => true,
+ 0x1fbc => true,
+ 0x1fbe => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fc7 => true,
+ 0x1fcc => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fd7 => true,
+ 0x1fe0...0x1fe7 => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ff7 => true,
+ 0x1ffc => true,
+ 0x214e => true,
+ 0x2170...0x217f => true,
+ 0x2184 => true,
+ 0x24d0...0x24e9 => true,
+ 0x2c30...0x2c5f => true,
+ 0x2c61 => true,
+ 0x2c65...0x2c66 => true,
+ 0x2c68 => true,
+ 0x2c6a => true,
+ 0x2c6c => true,
+ 0x2c73 => true,
+ 0x2c76 => true,
+ 0x2c81 => true,
+ 0x2c83 => true,
+ 0x2c85 => true,
+ 0x2c87 => true,
+ 0x2c89 => true,
+ 0x2c8b => true,
+ 0x2c8d => true,
+ 0x2c8f => true,
+ 0x2c91 => true,
+ 0x2c93 => true,
+ 0x2c95 => true,
+ 0x2c97 => true,
+ 0x2c99 => true,
+ 0x2c9b => true,
+ 0x2c9d => true,
+ 0x2c9f => true,
+ 0x2ca1 => true,
+ 0x2ca3 => true,
+ 0x2ca5 => true,
+ 0x2ca7 => true,
+ 0x2ca9 => true,
+ 0x2cab => true,
+ 0x2cad => true,
+ 0x2caf => true,
+ 0x2cb1 => true,
+ 0x2cb3 => true,
+ 0x2cb5 => true,
+ 0x2cb7 => true,
+ 0x2cb9 => true,
+ 0x2cbb => true,
+ 0x2cbd => true,
+ 0x2cbf => true,
+ 0x2cc1 => true,
+ 0x2cc3 => true,
+ 0x2cc5 => true,
+ 0x2cc7 => true,
+ 0x2cc9 => true,
+ 0x2ccb => true,
+ 0x2ccd => true,
+ 0x2ccf => true,
+ 0x2cd1 => true,
+ 0x2cd3 => true,
+ 0x2cd5 => true,
+ 0x2cd7 => true,
+ 0x2cd9 => true,
+ 0x2cdb => true,
+ 0x2cdd => true,
+ 0x2cdf => true,
+ 0x2ce1 => true,
+ 0x2ce3 => true,
+ 0x2cec => true,
+ 0x2cee => true,
+ 0x2cf3 => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0xa641 => true,
+ 0xa643 => true,
+ 0xa645 => true,
+ 0xa647 => true,
+ 0xa649 => true,
+ 0xa64b => true,
+ 0xa64d => true,
+ 0xa64f => true,
+ 0xa651 => true,
+ 0xa653 => true,
+ 0xa655 => true,
+ 0xa657 => true,
+ 0xa659 => true,
+ 0xa65b => true,
+ 0xa65d => true,
+ 0xa65f => true,
+ 0xa661 => true,
+ 0xa663 => true,
+ 0xa665 => true,
+ 0xa667 => true,
+ 0xa669 => true,
+ 0xa66b => true,
+ 0xa66d => true,
+ 0xa681 => true,
+ 0xa683 => true,
+ 0xa685 => true,
+ 0xa687 => true,
+ 0xa689 => true,
+ 0xa68b => true,
+ 0xa68d => true,
+ 0xa68f => true,
+ 0xa691 => true,
+ 0xa693 => true,
+ 0xa695 => true,
+ 0xa697 => true,
+ 0xa699 => true,
+ 0xa69b => true,
+ 0xa723 => true,
+ 0xa725 => true,
+ 0xa727 => true,
+ 0xa729 => true,
+ 0xa72b => true,
+ 0xa72d => true,
+ 0xa72f => true,
+ 0xa733 => true,
+ 0xa735 => true,
+ 0xa737 => true,
+ 0xa739 => true,
+ 0xa73b => true,
+ 0xa73d => true,
+ 0xa73f => true,
+ 0xa741 => true,
+ 0xa743 => true,
+ 0xa745 => true,
+ 0xa747 => true,
+ 0xa749 => true,
+ 0xa74b => true,
+ 0xa74d => true,
+ 0xa74f => true,
+ 0xa751 => true,
+ 0xa753 => true,
+ 0xa755 => true,
+ 0xa757 => true,
+ 0xa759 => true,
+ 0xa75b => true,
+ 0xa75d => true,
+ 0xa75f => true,
+ 0xa761 => true,
+ 0xa763 => true,
+ 0xa765 => true,
+ 0xa767 => true,
+ 0xa769 => true,
+ 0xa76b => true,
+ 0xa76d => true,
+ 0xa76f => true,
+ 0xa77a => true,
+ 0xa77c => true,
+ 0xa77f => true,
+ 0xa781 => true,
+ 0xa783 => true,
+ 0xa785 => true,
+ 0xa787 => true,
+ 0xa78c => true,
+ 0xa791 => true,
+ 0xa793...0xa794 => true,
+ 0xa797 => true,
+ 0xa799 => true,
+ 0xa79b => true,
+ 0xa79d => true,
+ 0xa79f => true,
+ 0xa7a1 => true,
+ 0xa7a3 => true,
+ 0xa7a5 => true,
+ 0xa7a7 => true,
+ 0xa7a9 => true,
+ 0xa7b5 => true,
+ 0xa7b7 => true,
+ 0xa7b9 => true,
+ 0xa7bb => true,
+ 0xa7bd => true,
+ 0xa7bf => true,
+ 0xa7c1 => true,
+ 0xa7c3 => true,
+ 0xa7c8 => true,
+ 0xa7ca => true,
+ 0xa7d1 => true,
+ 0xa7d7 => true,
+ 0xa7d9 => true,
+ 0xa7f6 => true,
+ 0xab53 => true,
+ 0xab70...0xabbf => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xff41...0xff5a => true,
+ 0x10428...0x1044f => true,
+ 0x104d8...0x104fb => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x118c0...0x118df => true,
+ 0x16e60...0x16e7f => true,
+ 0x1e922...0x1e943 => true,
+ else => false,
+ };
+}
+
+pub fn isChangesWhenTitlecased(cp: u21) bool {
+ if (cp < 0x61 or cp > 0x1e943) return false;
+
+ return switch (cp) {
+ 0x61...0x7a => true,
+ 0xb5 => true,
+ 0xdf...0xf6 => true,
+ 0xf8...0xff => true,
+ 0x101 => true,
+ 0x103 => true,
+ 0x105 => true,
+ 0x107 => true,
+ 0x109 => true,
+ 0x10b => true,
+ 0x10d => true,
+ 0x10f => true,
+ 0x111 => true,
+ 0x113 => true,
+ 0x115 => true,
+ 0x117 => true,
+ 0x119 => true,
+ 0x11b => true,
+ 0x11d => true,
+ 0x11f => true,
+ 0x121 => true,
+ 0x123 => true,
+ 0x125 => true,
+ 0x127 => true,
+ 0x129 => true,
+ 0x12b => true,
+ 0x12d => true,
+ 0x12f => true,
+ 0x131 => true,
+ 0x133 => true,
+ 0x135 => true,
+ 0x137 => true,
+ 0x13a => true,
+ 0x13c => true,
+ 0x13e => true,
+ 0x140 => true,
+ 0x142 => true,
+ 0x144 => true,
+ 0x146 => true,
+ 0x148...0x149 => true,
+ 0x14b => true,
+ 0x14d => true,
+ 0x14f => true,
+ 0x151 => true,
+ 0x153 => true,
+ 0x155 => true,
+ 0x157 => true,
+ 0x159 => true,
+ 0x15b => true,
+ 0x15d => true,
+ 0x15f => true,
+ 0x161 => true,
+ 0x163 => true,
+ 0x165 => true,
+ 0x167 => true,
+ 0x169 => true,
+ 0x16b => true,
+ 0x16d => true,
+ 0x16f => true,
+ 0x171 => true,
+ 0x173 => true,
+ 0x175 => true,
+ 0x177 => true,
+ 0x17a => true,
+ 0x17c => true,
+ 0x17e...0x180 => true,
+ 0x183 => true,
+ 0x185 => true,
+ 0x188 => true,
+ 0x18c => true,
+ 0x192 => true,
+ 0x195 => true,
+ 0x199...0x19a => true,
+ 0x19e => true,
+ 0x1a1 => true,
+ 0x1a3 => true,
+ 0x1a5 => true,
+ 0x1a8 => true,
+ 0x1ad => true,
+ 0x1b0 => true,
+ 0x1b4 => true,
+ 0x1b6 => true,
+ 0x1b9 => true,
+ 0x1bd => true,
+ 0x1bf => true,
+ 0x1c4 => true,
+ 0x1c6...0x1c7 => true,
+ 0x1c9...0x1ca => true,
+ 0x1cc => true,
+ 0x1ce => true,
+ 0x1d0 => true,
+ 0x1d2 => true,
+ 0x1d4 => true,
+ 0x1d6 => true,
+ 0x1d8 => true,
+ 0x1da => true,
+ 0x1dc...0x1dd => true,
+ 0x1df => true,
+ 0x1e1 => true,
+ 0x1e3 => true,
+ 0x1e5 => true,
+ 0x1e7 => true,
+ 0x1e9 => true,
+ 0x1eb => true,
+ 0x1ed => true,
+ 0x1ef...0x1f1 => true,
+ 0x1f3 => true,
+ 0x1f5 => true,
+ 0x1f9 => true,
+ 0x1fb => true,
+ 0x1fd => true,
+ 0x1ff => true,
+ 0x201 => true,
+ 0x203 => true,
+ 0x205 => true,
+ 0x207 => true,
+ 0x209 => true,
+ 0x20b => true,
+ 0x20d => true,
+ 0x20f => true,
+ 0x211 => true,
+ 0x213 => true,
+ 0x215 => true,
+ 0x217 => true,
+ 0x219 => true,
+ 0x21b => true,
+ 0x21d => true,
+ 0x21f => true,
+ 0x223 => true,
+ 0x225 => true,
+ 0x227 => true,
+ 0x229 => true,
+ 0x22b => true,
+ 0x22d => true,
+ 0x22f => true,
+ 0x231 => true,
+ 0x233 => true,
+ 0x23c => true,
+ 0x23f...0x240 => true,
+ 0x242 => true,
+ 0x247 => true,
+ 0x249 => true,
+ 0x24b => true,
+ 0x24d => true,
+ 0x24f...0x254 => true,
+ 0x256...0x257 => true,
+ 0x259 => true,
+ 0x25b...0x25c => true,
+ 0x260...0x261 => true,
+ 0x263 => true,
+ 0x265...0x266 => true,
+ 0x268...0x26c => true,
+ 0x26f => true,
+ 0x271...0x272 => true,
+ 0x275 => true,
+ 0x27d => true,
+ 0x280 => true,
+ 0x282...0x283 => true,
+ 0x287...0x28c => true,
+ 0x292 => true,
+ 0x29d...0x29e => true,
+ 0x345 => true,
+ 0x371 => true,
+ 0x373 => true,
+ 0x377 => true,
+ 0x37b...0x37d => true,
+ 0x390 => true,
+ 0x3ac...0x3ce => true,
+ 0x3d0...0x3d1 => true,
+ 0x3d5...0x3d7 => true,
+ 0x3d9 => true,
+ 0x3db => true,
+ 0x3dd => true,
+ 0x3df => true,
+ 0x3e1 => true,
+ 0x3e3 => true,
+ 0x3e5 => true,
+ 0x3e7 => true,
+ 0x3e9 => true,
+ 0x3eb => true,
+ 0x3ed => true,
+ 0x3ef...0x3f3 => true,
+ 0x3f5 => true,
+ 0x3f8 => true,
+ 0x3fb => true,
+ 0x430...0x45f => true,
+ 0x461 => true,
+ 0x463 => true,
+ 0x465 => true,
+ 0x467 => true,
+ 0x469 => true,
+ 0x46b => true,
+ 0x46d => true,
+ 0x46f => true,
+ 0x471 => true,
+ 0x473 => true,
+ 0x475 => true,
+ 0x477 => true,
+ 0x479 => true,
+ 0x47b => true,
+ 0x47d => true,
+ 0x47f => true,
+ 0x481 => true,
+ 0x48b => true,
+ 0x48d => true,
+ 0x48f => true,
+ 0x491 => true,
+ 0x493 => true,
+ 0x495 => true,
+ 0x497 => true,
+ 0x499 => true,
+ 0x49b => true,
+ 0x49d => true,
+ 0x49f => true,
+ 0x4a1 => true,
+ 0x4a3 => true,
+ 0x4a5 => true,
+ 0x4a7 => true,
+ 0x4a9 => true,
+ 0x4ab => true,
+ 0x4ad => true,
+ 0x4af => true,
+ 0x4b1 => true,
+ 0x4b3 => true,
+ 0x4b5 => true,
+ 0x4b7 => true,
+ 0x4b9 => true,
+ 0x4bb => true,
+ 0x4bd => true,
+ 0x4bf => true,
+ 0x4c2 => true,
+ 0x4c4 => true,
+ 0x4c6 => true,
+ 0x4c8 => true,
+ 0x4ca => true,
+ 0x4cc => true,
+ 0x4ce...0x4cf => true,
+ 0x4d1 => true,
+ 0x4d3 => true,
+ 0x4d5 => true,
+ 0x4d7 => true,
+ 0x4d9 => true,
+ 0x4db => true,
+ 0x4dd => true,
+ 0x4df => true,
+ 0x4e1 => true,
+ 0x4e3 => true,
+ 0x4e5 => true,
+ 0x4e7 => true,
+ 0x4e9 => true,
+ 0x4eb => true,
+ 0x4ed => true,
+ 0x4ef => true,
+ 0x4f1 => true,
+ 0x4f3 => true,
+ 0x4f5 => true,
+ 0x4f7 => true,
+ 0x4f9 => true,
+ 0x4fb => true,
+ 0x4fd => true,
+ 0x4ff => true,
+ 0x501 => true,
+ 0x503 => true,
+ 0x505 => true,
+ 0x507 => true,
+ 0x509 => true,
+ 0x50b => true,
+ 0x50d => true,
+ 0x50f => true,
+ 0x511 => true,
+ 0x513 => true,
+ 0x515 => true,
+ 0x517 => true,
+ 0x519 => true,
+ 0x51b => true,
+ 0x51d => true,
+ 0x51f => true,
+ 0x521 => true,
+ 0x523 => true,
+ 0x525 => true,
+ 0x527 => true,
+ 0x529 => true,
+ 0x52b => true,
+ 0x52d => true,
+ 0x52f => true,
+ 0x561...0x587 => true,
+ 0x13f8...0x13fd => true,
+ 0x1c80...0x1c88 => true,
+ 0x1d79 => true,
+ 0x1d7d => true,
+ 0x1d8e => true,
+ 0x1e01 => true,
+ 0x1e03 => true,
+ 0x1e05 => true,
+ 0x1e07 => true,
+ 0x1e09 => true,
+ 0x1e0b => true,
+ 0x1e0d => true,
+ 0x1e0f => true,
+ 0x1e11 => true,
+ 0x1e13 => true,
+ 0x1e15 => true,
+ 0x1e17 => true,
+ 0x1e19 => true,
+ 0x1e1b => true,
+ 0x1e1d => true,
+ 0x1e1f => true,
+ 0x1e21 => true,
+ 0x1e23 => true,
+ 0x1e25 => true,
+ 0x1e27 => true,
+ 0x1e29 => true,
+ 0x1e2b => true,
+ 0x1e2d => true,
+ 0x1e2f => true,
+ 0x1e31 => true,
+ 0x1e33 => true,
+ 0x1e35 => true,
+ 0x1e37 => true,
+ 0x1e39 => true,
+ 0x1e3b => true,
+ 0x1e3d => true,
+ 0x1e3f => true,
+ 0x1e41 => true,
+ 0x1e43 => true,
+ 0x1e45 => true,
+ 0x1e47 => true,
+ 0x1e49 => true,
+ 0x1e4b => true,
+ 0x1e4d => true,
+ 0x1e4f => true,
+ 0x1e51 => true,
+ 0x1e53 => true,
+ 0x1e55 => true,
+ 0x1e57 => true,
+ 0x1e59 => true,
+ 0x1e5b => true,
+ 0x1e5d => true,
+ 0x1e5f => true,
+ 0x1e61 => true,
+ 0x1e63 => true,
+ 0x1e65 => true,
+ 0x1e67 => true,
+ 0x1e69 => true,
+ 0x1e6b => true,
+ 0x1e6d => true,
+ 0x1e6f => true,
+ 0x1e71 => true,
+ 0x1e73 => true,
+ 0x1e75 => true,
+ 0x1e77 => true,
+ 0x1e79 => true,
+ 0x1e7b => true,
+ 0x1e7d => true,
+ 0x1e7f => true,
+ 0x1e81 => true,
+ 0x1e83 => true,
+ 0x1e85 => true,
+ 0x1e87 => true,
+ 0x1e89 => true,
+ 0x1e8b => true,
+ 0x1e8d => true,
+ 0x1e8f => true,
+ 0x1e91 => true,
+ 0x1e93 => true,
+ 0x1e95...0x1e9b => true,
+ 0x1ea1 => true,
+ 0x1ea3 => true,
+ 0x1ea5 => true,
+ 0x1ea7 => true,
+ 0x1ea9 => true,
+ 0x1eab => true,
+ 0x1ead => true,
+ 0x1eaf => true,
+ 0x1eb1 => true,
+ 0x1eb3 => true,
+ 0x1eb5 => true,
+ 0x1eb7 => true,
+ 0x1eb9 => true,
+ 0x1ebb => true,
+ 0x1ebd => true,
+ 0x1ebf => true,
+ 0x1ec1 => true,
+ 0x1ec3 => true,
+ 0x1ec5 => true,
+ 0x1ec7 => true,
+ 0x1ec9 => true,
+ 0x1ecb => true,
+ 0x1ecd => true,
+ 0x1ecf => true,
+ 0x1ed1 => true,
+ 0x1ed3 => true,
+ 0x1ed5 => true,
+ 0x1ed7 => true,
+ 0x1ed9 => true,
+ 0x1edb => true,
+ 0x1edd => true,
+ 0x1edf => true,
+ 0x1ee1 => true,
+ 0x1ee3 => true,
+ 0x1ee5 => true,
+ 0x1ee7 => true,
+ 0x1ee9 => true,
+ 0x1eeb => true,
+ 0x1eed => true,
+ 0x1eef => true,
+ 0x1ef1 => true,
+ 0x1ef3 => true,
+ 0x1ef5 => true,
+ 0x1ef7 => true,
+ 0x1ef9 => true,
+ 0x1efb => true,
+ 0x1efd => true,
+ 0x1eff...0x1f07 => true,
+ 0x1f10...0x1f15 => true,
+ 0x1f20...0x1f27 => true,
+ 0x1f30...0x1f37 => true,
+ 0x1f40...0x1f45 => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f60...0x1f67 => true,
+ 0x1f70...0x1f7d => true,
+ 0x1f80...0x1f87 => true,
+ 0x1f90...0x1f97 => true,
+ 0x1fa0...0x1fa7 => true,
+ 0x1fb0...0x1fb4 => true,
+ 0x1fb6...0x1fb7 => true,
+ 0x1fbe => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fc7 => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fd7 => true,
+ 0x1fe0...0x1fe7 => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ff7 => true,
+ 0x214e => true,
+ 0x2170...0x217f => true,
+ 0x2184 => true,
+ 0x24d0...0x24e9 => true,
+ 0x2c30...0x2c5f => true,
+ 0x2c61 => true,
+ 0x2c65...0x2c66 => true,
+ 0x2c68 => true,
+ 0x2c6a => true,
+ 0x2c6c => true,
+ 0x2c73 => true,
+ 0x2c76 => true,
+ 0x2c81 => true,
+ 0x2c83 => true,
+ 0x2c85 => true,
+ 0x2c87 => true,
+ 0x2c89 => true,
+ 0x2c8b => true,
+ 0x2c8d => true,
+ 0x2c8f => true,
+ 0x2c91 => true,
+ 0x2c93 => true,
+ 0x2c95 => true,
+ 0x2c97 => true,
+ 0x2c99 => true,
+ 0x2c9b => true,
+ 0x2c9d => true,
+ 0x2c9f => true,
+ 0x2ca1 => true,
+ 0x2ca3 => true,
+ 0x2ca5 => true,
+ 0x2ca7 => true,
+ 0x2ca9 => true,
+ 0x2cab => true,
+ 0x2cad => true,
+ 0x2caf => true,
+ 0x2cb1 => true,
+ 0x2cb3 => true,
+ 0x2cb5 => true,
+ 0x2cb7 => true,
+ 0x2cb9 => true,
+ 0x2cbb => true,
+ 0x2cbd => true,
+ 0x2cbf => true,
+ 0x2cc1 => true,
+ 0x2cc3 => true,
+ 0x2cc5 => true,
+ 0x2cc7 => true,
+ 0x2cc9 => true,
+ 0x2ccb => true,
+ 0x2ccd => true,
+ 0x2ccf => true,
+ 0x2cd1 => true,
+ 0x2cd3 => true,
+ 0x2cd5 => true,
+ 0x2cd7 => true,
+ 0x2cd9 => true,
+ 0x2cdb => true,
+ 0x2cdd => true,
+ 0x2cdf => true,
+ 0x2ce1 => true,
+ 0x2ce3 => true,
+ 0x2cec => true,
+ 0x2cee => true,
+ 0x2cf3 => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0xa641 => true,
+ 0xa643 => true,
+ 0xa645 => true,
+ 0xa647 => true,
+ 0xa649 => true,
+ 0xa64b => true,
+ 0xa64d => true,
+ 0xa64f => true,
+ 0xa651 => true,
+ 0xa653 => true,
+ 0xa655 => true,
+ 0xa657 => true,
+ 0xa659 => true,
+ 0xa65b => true,
+ 0xa65d => true,
+ 0xa65f => true,
+ 0xa661 => true,
+ 0xa663 => true,
+ 0xa665 => true,
+ 0xa667 => true,
+ 0xa669 => true,
+ 0xa66b => true,
+ 0xa66d => true,
+ 0xa681 => true,
+ 0xa683 => true,
+ 0xa685 => true,
+ 0xa687 => true,
+ 0xa689 => true,
+ 0xa68b => true,
+ 0xa68d => true,
+ 0xa68f => true,
+ 0xa691 => true,
+ 0xa693 => true,
+ 0xa695 => true,
+ 0xa697 => true,
+ 0xa699 => true,
+ 0xa69b => true,
+ 0xa723 => true,
+ 0xa725 => true,
+ 0xa727 => true,
+ 0xa729 => true,
+ 0xa72b => true,
+ 0xa72d => true,
+ 0xa72f => true,
+ 0xa733 => true,
+ 0xa735 => true,
+ 0xa737 => true,
+ 0xa739 => true,
+ 0xa73b => true,
+ 0xa73d => true,
+ 0xa73f => true,
+ 0xa741 => true,
+ 0xa743 => true,
+ 0xa745 => true,
+ 0xa747 => true,
+ 0xa749 => true,
+ 0xa74b => true,
+ 0xa74d => true,
+ 0xa74f => true,
+ 0xa751 => true,
+ 0xa753 => true,
+ 0xa755 => true,
+ 0xa757 => true,
+ 0xa759 => true,
+ 0xa75b => true,
+ 0xa75d => true,
+ 0xa75f => true,
+ 0xa761 => true,
+ 0xa763 => true,
+ 0xa765 => true,
+ 0xa767 => true,
+ 0xa769 => true,
+ 0xa76b => true,
+ 0xa76d => true,
+ 0xa76f => true,
+ 0xa77a => true,
+ 0xa77c => true,
+ 0xa77f => true,
+ 0xa781 => true,
+ 0xa783 => true,
+ 0xa785 => true,
+ 0xa787 => true,
+ 0xa78c => true,
+ 0xa791 => true,
+ 0xa793...0xa794 => true,
+ 0xa797 => true,
+ 0xa799 => true,
+ 0xa79b => true,
+ 0xa79d => true,
+ 0xa79f => true,
+ 0xa7a1 => true,
+ 0xa7a3 => true,
+ 0xa7a5 => true,
+ 0xa7a7 => true,
+ 0xa7a9 => true,
+ 0xa7b5 => true,
+ 0xa7b7 => true,
+ 0xa7b9 => true,
+ 0xa7bb => true,
+ 0xa7bd => true,
+ 0xa7bf => true,
+ 0xa7c1 => true,
+ 0xa7c3 => true,
+ 0xa7c8 => true,
+ 0xa7ca => true,
+ 0xa7d1 => true,
+ 0xa7d7 => true,
+ 0xa7d9 => true,
+ 0xa7f6 => true,
+ 0xab53 => true,
+ 0xab70...0xabbf => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xff41...0xff5a => true,
+ 0x10428...0x1044f => true,
+ 0x104d8...0x104fb => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x118c0...0x118df => true,
+ 0x16e60...0x16e7f => true,
+ 0x1e922...0x1e943 => true,
+ else => false,
+ };
+}
+
+pub fn isChangesWhenCasefolded(cp: u21) bool {
+ if (cp < 0x41 or cp > 0x1e921) return false;
+
+ return switch (cp) {
+ 0x41...0x5a => true,
+ 0xb5 => true,
+ 0xc0...0xd6 => true,
+ 0xd8...0xdf => true,
+ 0x100 => true,
+ 0x102 => true,
+ 0x104 => true,
+ 0x106 => true,
+ 0x108 => true,
+ 0x10a => true,
+ 0x10c => true,
+ 0x10e => true,
+ 0x110 => true,
+ 0x112 => true,
+ 0x114 => true,
+ 0x116 => true,
+ 0x118 => true,
+ 0x11a => true,
+ 0x11c => true,
+ 0x11e => true,
+ 0x120 => true,
+ 0x122 => true,
+ 0x124 => true,
+ 0x126 => true,
+ 0x128 => true,
+ 0x12a => true,
+ 0x12c => true,
+ 0x12e => true,
+ 0x130 => true,
+ 0x132 => true,
+ 0x134 => true,
+ 0x136 => true,
+ 0x139 => true,
+ 0x13b => true,
+ 0x13d => true,
+ 0x13f => true,
+ 0x141 => true,
+ 0x143 => true,
+ 0x145 => true,
+ 0x147 => true,
+ 0x149...0x14a => true,
+ 0x14c => true,
+ 0x14e => true,
+ 0x150 => true,
+ 0x152 => true,
+ 0x154 => true,
+ 0x156 => true,
+ 0x158 => true,
+ 0x15a => true,
+ 0x15c => true,
+ 0x15e => true,
+ 0x160 => true,
+ 0x162 => true,
+ 0x164 => true,
+ 0x166 => true,
+ 0x168 => true,
+ 0x16a => true,
+ 0x16c => true,
+ 0x16e => true,
+ 0x170 => true,
+ 0x172 => true,
+ 0x174 => true,
+ 0x176 => true,
+ 0x178...0x179 => true,
+ 0x17b => true,
+ 0x17d => true,
+ 0x17f => true,
+ 0x181...0x182 => true,
+ 0x184 => true,
+ 0x186...0x187 => true,
+ 0x189...0x18b => true,
+ 0x18e...0x191 => true,
+ 0x193...0x194 => true,
+ 0x196...0x198 => true,
+ 0x19c...0x19d => true,
+ 0x19f...0x1a0 => true,
+ 0x1a2 => true,
+ 0x1a4 => true,
+ 0x1a6...0x1a7 => true,
+ 0x1a9 => true,
+ 0x1ac => true,
+ 0x1ae...0x1af => true,
+ 0x1b1...0x1b3 => true,
+ 0x1b5 => true,
+ 0x1b7...0x1b8 => true,
+ 0x1bc => true,
+ 0x1c4...0x1c5 => true,
+ 0x1c7...0x1c8 => true,
+ 0x1ca...0x1cb => true,
+ 0x1cd => true,
+ 0x1cf => true,
+ 0x1d1 => true,
+ 0x1d3 => true,
+ 0x1d5 => true,
+ 0x1d7 => true,
+ 0x1d9 => true,
+ 0x1db => true,
+ 0x1de => true,
+ 0x1e0 => true,
+ 0x1e2 => true,
+ 0x1e4 => true,
+ 0x1e6 => true,
+ 0x1e8 => true,
+ 0x1ea => true,
+ 0x1ec => true,
+ 0x1ee => true,
+ 0x1f1...0x1f2 => true,
+ 0x1f4 => true,
+ 0x1f6...0x1f8 => true,
+ 0x1fa => true,
+ 0x1fc => true,
+ 0x1fe => true,
+ 0x200 => true,
+ 0x202 => true,
+ 0x204 => true,
+ 0x206 => true,
+ 0x208 => true,
+ 0x20a => true,
+ 0x20c => true,
+ 0x20e => true,
+ 0x210 => true,
+ 0x212 => true,
+ 0x214 => true,
+ 0x216 => true,
+ 0x218 => true,
+ 0x21a => true,
+ 0x21c => true,
+ 0x21e => true,
+ 0x220 => true,
+ 0x222 => true,
+ 0x224 => true,
+ 0x226 => true,
+ 0x228 => true,
+ 0x22a => true,
+ 0x22c => true,
+ 0x22e => true,
+ 0x230 => true,
+ 0x232 => true,
+ 0x23a...0x23b => true,
+ 0x23d...0x23e => true,
+ 0x241 => true,
+ 0x243...0x246 => true,
+ 0x248 => true,
+ 0x24a => true,
+ 0x24c => true,
+ 0x24e => true,
+ 0x345 => true,
+ 0x370 => true,
+ 0x372 => true,
+ 0x376 => true,
+ 0x37f => true,
+ 0x386 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x38f => true,
+ 0x391...0x3a1 => true,
+ 0x3a3...0x3ab => true,
+ 0x3c2 => true,
+ 0x3cf...0x3d1 => true,
+ 0x3d5...0x3d6 => true,
+ 0x3d8 => true,
+ 0x3da => true,
+ 0x3dc => true,
+ 0x3de => true,
+ 0x3e0 => true,
+ 0x3e2 => true,
+ 0x3e4 => true,
+ 0x3e6 => true,
+ 0x3e8 => true,
+ 0x3ea => true,
+ 0x3ec => true,
+ 0x3ee => true,
+ 0x3f0...0x3f1 => true,
+ 0x3f4...0x3f5 => true,
+ 0x3f7 => true,
+ 0x3f9...0x3fa => true,
+ 0x3fd...0x42f => true,
+ 0x460 => true,
+ 0x462 => true,
+ 0x464 => true,
+ 0x466 => true,
+ 0x468 => true,
+ 0x46a => true,
+ 0x46c => true,
+ 0x46e => true,
+ 0x470 => true,
+ 0x472 => true,
+ 0x474 => true,
+ 0x476 => true,
+ 0x478 => true,
+ 0x47a => true,
+ 0x47c => true,
+ 0x47e => true,
+ 0x480 => true,
+ 0x48a => true,
+ 0x48c => true,
+ 0x48e => true,
+ 0x490 => true,
+ 0x492 => true,
+ 0x494 => true,
+ 0x496 => true,
+ 0x498 => true,
+ 0x49a => true,
+ 0x49c => true,
+ 0x49e => true,
+ 0x4a0 => true,
+ 0x4a2 => true,
+ 0x4a4 => true,
+ 0x4a6 => true,
+ 0x4a8 => true,
+ 0x4aa => true,
+ 0x4ac => true,
+ 0x4ae => true,
+ 0x4b0 => true,
+ 0x4b2 => true,
+ 0x4b4 => true,
+ 0x4b6 => true,
+ 0x4b8 => true,
+ 0x4ba => true,
+ 0x4bc => true,
+ 0x4be => true,
+ 0x4c0...0x4c1 => true,
+ 0x4c3 => true,
+ 0x4c5 => true,
+ 0x4c7 => true,
+ 0x4c9 => true,
+ 0x4cb => true,
+ 0x4cd => true,
+ 0x4d0 => true,
+ 0x4d2 => true,
+ 0x4d4 => true,
+ 0x4d6 => true,
+ 0x4d8 => true,
+ 0x4da => true,
+ 0x4dc => true,
+ 0x4de => true,
+ 0x4e0 => true,
+ 0x4e2 => true,
+ 0x4e4 => true,
+ 0x4e6 => true,
+ 0x4e8 => true,
+ 0x4ea => true,
+ 0x4ec => true,
+ 0x4ee => true,
+ 0x4f0 => true,
+ 0x4f2 => true,
+ 0x4f4 => true,
+ 0x4f6 => true,
+ 0x4f8 => true,
+ 0x4fa => true,
+ 0x4fc => true,
+ 0x4fe => true,
+ 0x500 => true,
+ 0x502 => true,
+ 0x504 => true,
+ 0x506 => true,
+ 0x508 => true,
+ 0x50a => true,
+ 0x50c => true,
+ 0x50e => true,
+ 0x510 => true,
+ 0x512 => true,
+ 0x514 => true,
+ 0x516 => true,
+ 0x518 => true,
+ 0x51a => true,
+ 0x51c => true,
+ 0x51e => true,
+ 0x520 => true,
+ 0x522 => true,
+ 0x524 => true,
+ 0x526 => true,
+ 0x528 => true,
+ 0x52a => true,
+ 0x52c => true,
+ 0x52e => true,
+ 0x531...0x556 => true,
+ 0x587 => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x13f8...0x13fd => true,
+ 0x1c80...0x1c88 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1e00 => true,
+ 0x1e02 => true,
+ 0x1e04 => true,
+ 0x1e06 => true,
+ 0x1e08 => true,
+ 0x1e0a => true,
+ 0x1e0c => true,
+ 0x1e0e => true,
+ 0x1e10 => true,
+ 0x1e12 => true,
+ 0x1e14 => true,
+ 0x1e16 => true,
+ 0x1e18 => true,
+ 0x1e1a => true,
+ 0x1e1c => true,
+ 0x1e1e => true,
+ 0x1e20 => true,
+ 0x1e22 => true,
+ 0x1e24 => true,
+ 0x1e26 => true,
+ 0x1e28 => true,
+ 0x1e2a => true,
+ 0x1e2c => true,
+ 0x1e2e => true,
+ 0x1e30 => true,
+ 0x1e32 => true,
+ 0x1e34 => true,
+ 0x1e36 => true,
+ 0x1e38 => true,
+ 0x1e3a => true,
+ 0x1e3c => true,
+ 0x1e3e => true,
+ 0x1e40 => true,
+ 0x1e42 => true,
+ 0x1e44 => true,
+ 0x1e46 => true,
+ 0x1e48 => true,
+ 0x1e4a => true,
+ 0x1e4c => true,
+ 0x1e4e => true,
+ 0x1e50 => true,
+ 0x1e52 => true,
+ 0x1e54 => true,
+ 0x1e56 => true,
+ 0x1e58 => true,
+ 0x1e5a => true,
+ 0x1e5c => true,
+ 0x1e5e => true,
+ 0x1e60 => true,
+ 0x1e62 => true,
+ 0x1e64 => true,
+ 0x1e66 => true,
+ 0x1e68 => true,
+ 0x1e6a => true,
+ 0x1e6c => true,
+ 0x1e6e => true,
+ 0x1e70 => true,
+ 0x1e72 => true,
+ 0x1e74 => true,
+ 0x1e76 => true,
+ 0x1e78 => true,
+ 0x1e7a => true,
+ 0x1e7c => true,
+ 0x1e7e => true,
+ 0x1e80 => true,
+ 0x1e82 => true,
+ 0x1e84 => true,
+ 0x1e86 => true,
+ 0x1e88 => true,
+ 0x1e8a => true,
+ 0x1e8c => true,
+ 0x1e8e => true,
+ 0x1e90 => true,
+ 0x1e92 => true,
+ 0x1e94 => true,
+ 0x1e9a...0x1e9b => true,
+ 0x1e9e => true,
+ 0x1ea0 => true,
+ 0x1ea2 => true,
+ 0x1ea4 => true,
+ 0x1ea6 => true,
+ 0x1ea8 => true,
+ 0x1eaa => true,
+ 0x1eac => true,
+ 0x1eae => true,
+ 0x1eb0 => true,
+ 0x1eb2 => true,
+ 0x1eb4 => true,
+ 0x1eb6 => true,
+ 0x1eb8 => true,
+ 0x1eba => true,
+ 0x1ebc => true,
+ 0x1ebe => true,
+ 0x1ec0 => true,
+ 0x1ec2 => true,
+ 0x1ec4 => true,
+ 0x1ec6 => true,
+ 0x1ec8 => true,
+ 0x1eca => true,
+ 0x1ecc => true,
+ 0x1ece => true,
+ 0x1ed0 => true,
+ 0x1ed2 => true,
+ 0x1ed4 => true,
+ 0x1ed6 => true,
+ 0x1ed8 => true,
+ 0x1eda => true,
+ 0x1edc => true,
+ 0x1ede => true,
+ 0x1ee0 => true,
+ 0x1ee2 => true,
+ 0x1ee4 => true,
+ 0x1ee6 => true,
+ 0x1ee8 => true,
+ 0x1eea => true,
+ 0x1eec => true,
+ 0x1eee => true,
+ 0x1ef0 => true,
+ 0x1ef2 => true,
+ 0x1ef4 => true,
+ 0x1ef6 => true,
+ 0x1ef8 => true,
+ 0x1efa => true,
+ 0x1efc => true,
+ 0x1efe => true,
+ 0x1f08...0x1f0f => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f28...0x1f2f => true,
+ 0x1f38...0x1f3f => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f => true,
+ 0x1f68...0x1f6f => true,
+ 0x1f80...0x1faf => true,
+ 0x1fb2...0x1fb4 => true,
+ 0x1fb7...0x1fbc => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc7...0x1fcc => true,
+ 0x1fd8...0x1fdb => true,
+ 0x1fe8...0x1fec => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff7...0x1ffc => true,
+ 0x2126 => true,
+ 0x212a...0x212b => true,
+ 0x2132 => true,
+ 0x2160...0x216f => true,
+ 0x2183 => true,
+ 0x24b6...0x24cf => true,
+ 0x2c00...0x2c2f => true,
+ 0x2c60 => true,
+ 0x2c62...0x2c64 => true,
+ 0x2c67 => true,
+ 0x2c69 => true,
+ 0x2c6b => true,
+ 0x2c6d...0x2c70 => true,
+ 0x2c72 => true,
+ 0x2c75 => true,
+ 0x2c7e...0x2c80 => true,
+ 0x2c82 => true,
+ 0x2c84 => true,
+ 0x2c86 => true,
+ 0x2c88 => true,
+ 0x2c8a => true,
+ 0x2c8c => true,
+ 0x2c8e => true,
+ 0x2c90 => true,
+ 0x2c92 => true,
+ 0x2c94 => true,
+ 0x2c96 => true,
+ 0x2c98 => true,
+ 0x2c9a => true,
+ 0x2c9c => true,
+ 0x2c9e => true,
+ 0x2ca0 => true,
+ 0x2ca2 => true,
+ 0x2ca4 => true,
+ 0x2ca6 => true,
+ 0x2ca8 => true,
+ 0x2caa => true,
+ 0x2cac => true,
+ 0x2cae => true,
+ 0x2cb0 => true,
+ 0x2cb2 => true,
+ 0x2cb4 => true,
+ 0x2cb6 => true,
+ 0x2cb8 => true,
+ 0x2cba => true,
+ 0x2cbc => true,
+ 0x2cbe => true,
+ 0x2cc0 => true,
+ 0x2cc2 => true,
+ 0x2cc4 => true,
+ 0x2cc6 => true,
+ 0x2cc8 => true,
+ 0x2cca => true,
+ 0x2ccc => true,
+ 0x2cce => true,
+ 0x2cd0 => true,
+ 0x2cd2 => true,
+ 0x2cd4 => true,
+ 0x2cd6 => true,
+ 0x2cd8 => true,
+ 0x2cda => true,
+ 0x2cdc => true,
+ 0x2cde => true,
+ 0x2ce0 => true,
+ 0x2ce2 => true,
+ 0x2ceb => true,
+ 0x2ced => true,
+ 0x2cf2 => true,
+ 0xa640 => true,
+ 0xa642 => true,
+ 0xa644 => true,
+ 0xa646 => true,
+ 0xa648 => true,
+ 0xa64a => true,
+ 0xa64c => true,
+ 0xa64e => true,
+ 0xa650 => true,
+ 0xa652 => true,
+ 0xa654 => true,
+ 0xa656 => true,
+ 0xa658 => true,
+ 0xa65a => true,
+ 0xa65c => true,
+ 0xa65e => true,
+ 0xa660 => true,
+ 0xa662 => true,
+ 0xa664 => true,
+ 0xa666 => true,
+ 0xa668 => true,
+ 0xa66a => true,
+ 0xa66c => true,
+ 0xa680 => true,
+ 0xa682 => true,
+ 0xa684 => true,
+ 0xa686 => true,
+ 0xa688 => true,
+ 0xa68a => true,
+ 0xa68c => true,
+ 0xa68e => true,
+ 0xa690 => true,
+ 0xa692 => true,
+ 0xa694 => true,
+ 0xa696 => true,
+ 0xa698 => true,
+ 0xa69a => true,
+ 0xa722 => true,
+ 0xa724 => true,
+ 0xa726 => true,
+ 0xa728 => true,
+ 0xa72a => true,
+ 0xa72c => true,
+ 0xa72e => true,
+ 0xa732 => true,
+ 0xa734 => true,
+ 0xa736 => true,
+ 0xa738 => true,
+ 0xa73a => true,
+ 0xa73c => true,
+ 0xa73e => true,
+ 0xa740 => true,
+ 0xa742 => true,
+ 0xa744 => true,
+ 0xa746 => true,
+ 0xa748 => true,
+ 0xa74a => true,
+ 0xa74c => true,
+ 0xa74e => true,
+ 0xa750 => true,
+ 0xa752 => true,
+ 0xa754 => true,
+ 0xa756 => true,
+ 0xa758 => true,
+ 0xa75a => true,
+ 0xa75c => true,
+ 0xa75e => true,
+ 0xa760 => true,
+ 0xa762 => true,
+ 0xa764 => true,
+ 0xa766 => true,
+ 0xa768 => true,
+ 0xa76a => true,
+ 0xa76c => true,
+ 0xa76e => true,
+ 0xa779 => true,
+ 0xa77b => true,
+ 0xa77d...0xa77e => true,
+ 0xa780 => true,
+ 0xa782 => true,
+ 0xa784 => true,
+ 0xa786 => true,
+ 0xa78b => true,
+ 0xa78d => true,
+ 0xa790 => true,
+ 0xa792 => true,
+ 0xa796 => true,
+ 0xa798 => true,
+ 0xa79a => true,
+ 0xa79c => true,
+ 0xa79e => true,
+ 0xa7a0 => true,
+ 0xa7a2 => true,
+ 0xa7a4 => true,
+ 0xa7a6 => true,
+ 0xa7a8 => true,
+ 0xa7aa...0xa7ae => true,
+ 0xa7b0...0xa7b4 => true,
+ 0xa7b6 => true,
+ 0xa7b8 => true,
+ 0xa7ba => true,
+ 0xa7bc => true,
+ 0xa7be => true,
+ 0xa7c0 => true,
+ 0xa7c2 => true,
+ 0xa7c4...0xa7c7 => true,
+ 0xa7c9 => true,
+ 0xa7d0 => true,
+ 0xa7d6 => true,
+ 0xa7d8 => true,
+ 0xa7f5 => true,
+ 0xab70...0xabbf => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xff21...0xff3a => true,
+ 0x10400...0x10427 => true,
+ 0x104b0...0x104d3 => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10c80...0x10cb2 => true,
+ 0x118a0...0x118bf => true,
+ 0x16e40...0x16e5f => true,
+ 0x1e900...0x1e921 => true,
+ else => false,
+ };
+}
+
+pub fn isChangesWhenCasemapped(cp: u21) bool {
+ if (cp < 0x41 or cp > 0x1e943) return false;
+
+ return switch (cp) {
+ 0x41...0x5a => true,
+ 0x61...0x7a => true,
+ 0xb5 => true,
+ 0xc0...0xd6 => true,
+ 0xd8...0xf6 => true,
+ 0xf8...0x137 => true,
+ 0x139...0x18c => true,
+ 0x18e...0x19a => true,
+ 0x19c...0x1a9 => true,
+ 0x1ac...0x1b9 => true,
+ 0x1bc...0x1bd => true,
+ 0x1bf => true,
+ 0x1c4...0x220 => true,
+ 0x222...0x233 => true,
+ 0x23a...0x254 => true,
+ 0x256...0x257 => true,
+ 0x259 => true,
+ 0x25b...0x25c => true,
+ 0x260...0x261 => true,
+ 0x263 => true,
+ 0x265...0x266 => true,
+ 0x268...0x26c => true,
+ 0x26f => true,
+ 0x271...0x272 => true,
+ 0x275 => true,
+ 0x27d => true,
+ 0x280 => true,
+ 0x282...0x283 => true,
+ 0x287...0x28c => true,
+ 0x292 => true,
+ 0x29d...0x29e => true,
+ 0x345 => true,
+ 0x370...0x373 => true,
+ 0x376...0x377 => true,
+ 0x37b...0x37d => true,
+ 0x37f => true,
+ 0x386 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x3a1 => true,
+ 0x3a3...0x3d1 => true,
+ 0x3d5...0x3f5 => true,
+ 0x3f7...0x3fb => true,
+ 0x3fd...0x481 => true,
+ 0x48a...0x52f => true,
+ 0x531...0x556 => true,
+ 0x561...0x587 => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x10d0...0x10fa => true,
+ 0x10fd...0x10ff => true,
+ 0x13a0...0x13f5 => true,
+ 0x13f8...0x13fd => true,
+ 0x1c80...0x1c88 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1d79 => true,
+ 0x1d7d => true,
+ 0x1d8e => true,
+ 0x1e00...0x1e9b => true,
+ 0x1e9e => true,
+ 0x1ea0...0x1f15 => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f20...0x1f45 => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f...0x1f7d => true,
+ 0x1f80...0x1fb4 => true,
+ 0x1fb6...0x1fbc => true,
+ 0x1fbe => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fcc => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fdb => true,
+ 0x1fe0...0x1fec => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ffc => true,
+ 0x2126 => true,
+ 0x212a...0x212b => true,
+ 0x2132 => true,
+ 0x214e => true,
+ 0x2160...0x217f => true,
+ 0x2183...0x2184 => true,
+ 0x24b6...0x24e9 => true,
+ 0x2c00...0x2c70 => true,
+ 0x2c72...0x2c73 => true,
+ 0x2c75...0x2c76 => true,
+ 0x2c7e...0x2ce3 => true,
+ 0x2ceb...0x2cee => true,
+ 0x2cf2...0x2cf3 => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0xa640...0xa66d => true,
+ 0xa680...0xa69b => true,
+ 0xa722...0xa72f => true,
+ 0xa732...0xa76f => true,
+ 0xa779...0xa787 => true,
+ 0xa78b...0xa78d => true,
+ 0xa790...0xa794 => true,
+ 0xa796...0xa7ae => true,
+ 0xa7b0...0xa7ca => true,
+ 0xa7d0...0xa7d1 => true,
+ 0xa7d6...0xa7d9 => true,
+ 0xa7f5...0xa7f6 => true,
+ 0xab53 => true,
+ 0xab70...0xabbf => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xff21...0xff3a => true,
+ 0xff41...0xff5a => true,
+ 0x10400...0x1044f => true,
+ 0x104b0...0x104d3 => true,
+ 0x104d8...0x104fb => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10c80...0x10cb2 => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x118a0...0x118df => true,
+ 0x16e40...0x16e7f => true,
+ 0x1e900...0x1e943 => true,
+ else => false,
+ };
+}
+
+pub fn isIdStart(cp: u21) bool {
+ if (cp < 0x41 or cp > 0x323af) return false;
+
+ return switch (cp) {
+ 0x41...0x5a => true,
+ 0x61...0x7a => true,
+ 0xaa => true,
+ 0xb5 => true,
+ 0xba => true,
+ 0xc0...0xd6 => true,
+ 0xd8...0xf6 => true,
+ 0xf8...0x1ba => true,
+ 0x1bb => true,
+ 0x1bc...0x1bf => true,
+ 0x1c0...0x1c3 => true,
+ 0x1c4...0x293 => true,
+ 0x294 => true,
+ 0x295...0x2af => true,
+ 0x2b0...0x2c1 => true,
+ 0x2c6...0x2d1 => true,
+ 0x2e0...0x2e4 => true,
+ 0x2ec => true,
+ 0x2ee => true,
+ 0x370...0x373 => true,
+ 0x374 => true,
+ 0x376...0x377 => true,
+ 0x37a => true,
+ 0x37b...0x37d => true,
+ 0x37f => true,
+ 0x386 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x3a1 => true,
+ 0x3a3...0x3f5 => true,
+ 0x3f7...0x481 => true,
+ 0x48a...0x52f => true,
+ 0x531...0x556 => true,
+ 0x559 => true,
+ 0x560...0x588 => true,
+ 0x5d0...0x5ea => true,
+ 0x5ef...0x5f2 => true,
+ 0x620...0x63f => true,
+ 0x640 => true,
+ 0x641...0x64a => true,
+ 0x66e...0x66f => true,
+ 0x671...0x6d3 => true,
+ 0x6d5 => true,
+ 0x6e5...0x6e6 => true,
+ 0x6ee...0x6ef => true,
+ 0x6fa...0x6fc => true,
+ 0x6ff => true,
+ 0x710 => true,
+ 0x712...0x72f => true,
+ 0x74d...0x7a5 => true,
+ 0x7b1 => true,
+ 0x7ca...0x7ea => true,
+ 0x7f4...0x7f5 => true,
+ 0x7fa => true,
+ 0x800...0x815 => true,
+ 0x81a => true,
+ 0x824 => true,
+ 0x828 => true,
+ 0x840...0x858 => true,
+ 0x860...0x86a => true,
+ 0x870...0x887 => true,
+ 0x889...0x88e => true,
+ 0x8a0...0x8c8 => true,
+ 0x8c9 => true,
+ 0x904...0x939 => true,
+ 0x93d => true,
+ 0x950 => true,
+ 0x958...0x961 => true,
+ 0x971 => true,
+ 0x972...0x980 => true,
+ 0x985...0x98c => true,
+ 0x98f...0x990 => true,
+ 0x993...0x9a8 => true,
+ 0x9aa...0x9b0 => true,
+ 0x9b2 => true,
+ 0x9b6...0x9b9 => true,
+ 0x9bd => true,
+ 0x9ce => true,
+ 0x9dc...0x9dd => true,
+ 0x9df...0x9e1 => true,
+ 0x9f0...0x9f1 => true,
+ 0x9fc => true,
+ 0xa05...0xa0a => true,
+ 0xa0f...0xa10 => true,
+ 0xa13...0xa28 => true,
+ 0xa2a...0xa30 => true,
+ 0xa32...0xa33 => true,
+ 0xa35...0xa36 => true,
+ 0xa38...0xa39 => true,
+ 0xa59...0xa5c => true,
+ 0xa5e => true,
+ 0xa72...0xa74 => true,
+ 0xa85...0xa8d => true,
+ 0xa8f...0xa91 => true,
+ 0xa93...0xaa8 => true,
+ 0xaaa...0xab0 => true,
+ 0xab2...0xab3 => true,
+ 0xab5...0xab9 => true,
+ 0xabd => true,
+ 0xad0 => true,
+ 0xae0...0xae1 => true,
+ 0xaf9 => true,
+ 0xb05...0xb0c => true,
+ 0xb0f...0xb10 => true,
+ 0xb13...0xb28 => true,
+ 0xb2a...0xb30 => true,
+ 0xb32...0xb33 => true,
+ 0xb35...0xb39 => true,
+ 0xb3d => true,
+ 0xb5c...0xb5d => true,
+ 0xb5f...0xb61 => true,
+ 0xb71 => true,
+ 0xb83 => true,
+ 0xb85...0xb8a => true,
+ 0xb8e...0xb90 => true,
+ 0xb92...0xb95 => true,
+ 0xb99...0xb9a => true,
+ 0xb9c => true,
+ 0xb9e...0xb9f => true,
+ 0xba3...0xba4 => true,
+ 0xba8...0xbaa => true,
+ 0xbae...0xbb9 => true,
+ 0xbd0 => true,
+ 0xc05...0xc0c => true,
+ 0xc0e...0xc10 => true,
+ 0xc12...0xc28 => true,
+ 0xc2a...0xc39 => true,
+ 0xc3d => true,
+ 0xc58...0xc5a => true,
+ 0xc5d => true,
+ 0xc60...0xc61 => true,
+ 0xc80 => true,
+ 0xc85...0xc8c => true,
+ 0xc8e...0xc90 => true,
+ 0xc92...0xca8 => true,
+ 0xcaa...0xcb3 => true,
+ 0xcb5...0xcb9 => true,
+ 0xcbd => true,
+ 0xcdd...0xcde => true,
+ 0xce0...0xce1 => true,
+ 0xcf1...0xcf2 => true,
+ 0xd04...0xd0c => true,
+ 0xd0e...0xd10 => true,
+ 0xd12...0xd3a => true,
+ 0xd3d => true,
+ 0xd4e => true,
+ 0xd54...0xd56 => true,
+ 0xd5f...0xd61 => true,
+ 0xd7a...0xd7f => true,
+ 0xd85...0xd96 => true,
+ 0xd9a...0xdb1 => true,
+ 0xdb3...0xdbb => true,
+ 0xdbd => true,
+ 0xdc0...0xdc6 => true,
+ 0xe01...0xe30 => true,
+ 0xe32...0xe33 => true,
+ 0xe40...0xe45 => true,
+ 0xe46 => true,
+ 0xe81...0xe82 => true,
+ 0xe84 => true,
+ 0xe86...0xe8a => true,
+ 0xe8c...0xea3 => true,
+ 0xea5 => true,
+ 0xea7...0xeb0 => true,
+ 0xeb2...0xeb3 => true,
+ 0xebd => true,
+ 0xec0...0xec4 => true,
+ 0xec6 => true,
+ 0xedc...0xedf => true,
+ 0xf00 => true,
+ 0xf40...0xf47 => true,
+ 0xf49...0xf6c => true,
+ 0xf88...0xf8c => true,
+ 0x1000...0x102a => true,
+ 0x103f => true,
+ 0x1050...0x1055 => true,
+ 0x105a...0x105d => true,
+ 0x1061 => true,
+ 0x1065...0x1066 => true,
+ 0x106e...0x1070 => true,
+ 0x1075...0x1081 => true,
+ 0x108e => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x10d0...0x10fa => true,
+ 0x10fc => true,
+ 0x10fd...0x10ff => true,
+ 0x1100...0x1248 => true,
+ 0x124a...0x124d => true,
+ 0x1250...0x1256 => true,
+ 0x1258 => true,
+ 0x125a...0x125d => true,
+ 0x1260...0x1288 => true,
+ 0x128a...0x128d => true,
+ 0x1290...0x12b0 => true,
+ 0x12b2...0x12b5 => true,
+ 0x12b8...0x12be => true,
+ 0x12c0 => true,
+ 0x12c2...0x12c5 => true,
+ 0x12c8...0x12d6 => true,
+ 0x12d8...0x1310 => true,
+ 0x1312...0x1315 => true,
+ 0x1318...0x135a => true,
+ 0x1380...0x138f => true,
+ 0x13a0...0x13f5 => true,
+ 0x13f8...0x13fd => true,
+ 0x1401...0x166c => true,
+ 0x166f...0x167f => true,
+ 0x1681...0x169a => true,
+ 0x16a0...0x16ea => true,
+ 0x16ee...0x16f0 => true,
+ 0x16f1...0x16f8 => true,
+ 0x1700...0x1711 => true,
+ 0x171f...0x1731 => true,
+ 0x1740...0x1751 => true,
+ 0x1760...0x176c => true,
+ 0x176e...0x1770 => true,
+ 0x1780...0x17b3 => true,
+ 0x17d7 => true,
+ 0x17dc => true,
+ 0x1820...0x1842 => true,
+ 0x1843 => true,
+ 0x1844...0x1878 => true,
+ 0x1880...0x1884 => true,
+ 0x1885...0x1886 => true,
+ 0x1887...0x18a8 => true,
+ 0x18aa => true,
+ 0x18b0...0x18f5 => true,
+ 0x1900...0x191e => true,
+ 0x1950...0x196d => true,
+ 0x1970...0x1974 => true,
+ 0x1980...0x19ab => true,
+ 0x19b0...0x19c9 => true,
+ 0x1a00...0x1a16 => true,
+ 0x1a20...0x1a54 => true,
+ 0x1aa7 => true,
+ 0x1b05...0x1b33 => true,
+ 0x1b45...0x1b4c => true,
+ 0x1b83...0x1ba0 => true,
+ 0x1bae...0x1baf => true,
+ 0x1bba...0x1be5 => true,
+ 0x1c00...0x1c23 => true,
+ 0x1c4d...0x1c4f => true,
+ 0x1c5a...0x1c77 => true,
+ 0x1c78...0x1c7d => true,
+ 0x1c80...0x1c88 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1ce9...0x1cec => true,
+ 0x1cee...0x1cf3 => true,
+ 0x1cf5...0x1cf6 => true,
+ 0x1cfa => true,
+ 0x1d00...0x1d2b => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d6b...0x1d77 => true,
+ 0x1d78 => true,
+ 0x1d79...0x1d9a => true,
+ 0x1d9b...0x1dbf => true,
+ 0x1e00...0x1f15 => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f20...0x1f45 => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f...0x1f7d => true,
+ 0x1f80...0x1fb4 => true,
+ 0x1fb6...0x1fbc => true,
+ 0x1fbe => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fcc => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fdb => true,
+ 0x1fe0...0x1fec => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ffc => true,
+ 0x2071 => true,
+ 0x207f => true,
+ 0x2090...0x209c => true,
+ 0x2102 => true,
+ 0x2107 => true,
+ 0x210a...0x2113 => true,
+ 0x2115 => true,
+ 0x2118 => true,
+ 0x2119...0x211d => true,
+ 0x2124 => true,
+ 0x2126 => true,
+ 0x2128 => true,
+ 0x212a...0x212d => true,
+ 0x212e => true,
+ 0x212f...0x2134 => true,
+ 0x2135...0x2138 => true,
+ 0x2139 => true,
+ 0x213c...0x213f => true,
+ 0x2145...0x2149 => true,
+ 0x214e => true,
+ 0x2160...0x2182 => true,
+ 0x2183...0x2184 => true,
+ 0x2185...0x2188 => true,
+ 0x2c00...0x2c7b => true,
+ 0x2c7c...0x2c7d => true,
+ 0x2c7e...0x2ce4 => true,
+ 0x2ceb...0x2cee => true,
+ 0x2cf2...0x2cf3 => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0x2d30...0x2d67 => true,
+ 0x2d6f => true,
+ 0x2d80...0x2d96 => true,
+ 0x2da0...0x2da6 => true,
+ 0x2da8...0x2dae => true,
+ 0x2db0...0x2db6 => true,
+ 0x2db8...0x2dbe => true,
+ 0x2dc0...0x2dc6 => true,
+ 0x2dc8...0x2dce => true,
+ 0x2dd0...0x2dd6 => true,
+ 0x2dd8...0x2dde => true,
+ 0x3005 => true,
+ 0x3006 => true,
+ 0x3007 => true,
+ 0x3021...0x3029 => true,
+ 0x3031...0x3035 => true,
+ 0x3038...0x303a => true,
+ 0x303b => true,
+ 0x303c => true,
+ 0x3041...0x3096 => true,
+ 0x309b...0x309c => true,
+ 0x309d...0x309e => true,
+ 0x309f => true,
+ 0x30a1...0x30fa => true,
+ 0x30fc...0x30fe => true,
+ 0x30ff => true,
+ 0x3105...0x312f => true,
+ 0x3131...0x318e => true,
+ 0x31a0...0x31bf => true,
+ 0x31f0...0x31ff => true,
+ 0x3400...0x4dbf => true,
+ 0x4e00...0xa014 => true,
+ 0xa015 => true,
+ 0xa016...0xa48c => true,
+ 0xa4d0...0xa4f7 => true,
+ 0xa4f8...0xa4fd => true,
+ 0xa500...0xa60b => true,
+ 0xa60c => true,
+ 0xa610...0xa61f => true,
+ 0xa62a...0xa62b => true,
+ 0xa640...0xa66d => true,
+ 0xa66e => true,
+ 0xa67f => true,
+ 0xa680...0xa69b => true,
+ 0xa69c...0xa69d => true,
+ 0xa6a0...0xa6e5 => true,
+ 0xa6e6...0xa6ef => true,
+ 0xa717...0xa71f => true,
+ 0xa722...0xa76f => true,
+ 0xa770 => true,
+ 0xa771...0xa787 => true,
+ 0xa788 => true,
+ 0xa78b...0xa78e => true,
+ 0xa78f => true,
+ 0xa790...0xa7ca => true,
+ 0xa7d0...0xa7d1 => true,
+ 0xa7d3 => true,
+ 0xa7d5...0xa7d9 => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f5...0xa7f6 => true,
+ 0xa7f7 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa7fa => true,
+ 0xa7fb...0xa801 => true,
+ 0xa803...0xa805 => true,
+ 0xa807...0xa80a => true,
+ 0xa80c...0xa822 => true,
+ 0xa840...0xa873 => true,
+ 0xa882...0xa8b3 => true,
+ 0xa8f2...0xa8f7 => true,
+ 0xa8fb => true,
+ 0xa8fd...0xa8fe => true,
+ 0xa90a...0xa925 => true,
+ 0xa930...0xa946 => true,
+ 0xa960...0xa97c => true,
+ 0xa984...0xa9b2 => true,
+ 0xa9cf => true,
+ 0xa9e0...0xa9e4 => true,
+ 0xa9e6 => true,
+ 0xa9e7...0xa9ef => true,
+ 0xa9fa...0xa9fe => true,
+ 0xaa00...0xaa28 => true,
+ 0xaa40...0xaa42 => true,
+ 0xaa44...0xaa4b => true,
+ 0xaa60...0xaa6f => true,
+ 0xaa70 => true,
+ 0xaa71...0xaa76 => true,
+ 0xaa7a => true,
+ 0xaa7e...0xaaaf => true,
+ 0xaab1 => true,
+ 0xaab5...0xaab6 => true,
+ 0xaab9...0xaabd => true,
+ 0xaac0 => true,
+ 0xaac2 => true,
+ 0xaadb...0xaadc => true,
+ 0xaadd => true,
+ 0xaae0...0xaaea => true,
+ 0xaaf2 => true,
+ 0xaaf3...0xaaf4 => true,
+ 0xab01...0xab06 => true,
+ 0xab09...0xab0e => true,
+ 0xab11...0xab16 => true,
+ 0xab20...0xab26 => true,
+ 0xab28...0xab2e => true,
+ 0xab30...0xab5a => true,
+ 0xab5c...0xab5f => true,
+ 0xab60...0xab68 => true,
+ 0xab69 => true,
+ 0xab70...0xabbf => true,
+ 0xabc0...0xabe2 => true,
+ 0xac00...0xd7a3 => true,
+ 0xd7b0...0xd7c6 => true,
+ 0xd7cb...0xd7fb => true,
+ 0xf900...0xfa6d => true,
+ 0xfa70...0xfad9 => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xfb1d => true,
+ 0xfb1f...0xfb28 => true,
+ 0xfb2a...0xfb36 => true,
+ 0xfb38...0xfb3c => true,
+ 0xfb3e => true,
+ 0xfb40...0xfb41 => true,
+ 0xfb43...0xfb44 => true,
+ 0xfb46...0xfbb1 => true,
+ 0xfbd3...0xfd3d => true,
+ 0xfd50...0xfd8f => true,
+ 0xfd92...0xfdc7 => true,
+ 0xfdf0...0xfdfb => true,
+ 0xfe70...0xfe74 => true,
+ 0xfe76...0xfefc => true,
+ 0xff21...0xff3a => true,
+ 0xff41...0xff5a => true,
+ 0xff66...0xff6f => true,
+ 0xff70 => true,
+ 0xff71...0xff9d => true,
+ 0xff9e...0xff9f => true,
+ 0xffa0...0xffbe => true,
+ 0xffc2...0xffc7 => true,
+ 0xffca...0xffcf => true,
+ 0xffd2...0xffd7 => true,
+ 0xffda...0xffdc => true,
+ 0x10000...0x1000b => true,
+ 0x1000d...0x10026 => true,
+ 0x10028...0x1003a => true,
+ 0x1003c...0x1003d => true,
+ 0x1003f...0x1004d => true,
+ 0x10050...0x1005d => true,
+ 0x10080...0x100fa => true,
+ 0x10140...0x10174 => true,
+ 0x10280...0x1029c => true,
+ 0x102a0...0x102d0 => true,
+ 0x10300...0x1031f => true,
+ 0x1032d...0x10340 => true,
+ 0x10341 => true,
+ 0x10342...0x10349 => true,
+ 0x1034a => true,
+ 0x10350...0x10375 => true,
+ 0x10380...0x1039d => true,
+ 0x103a0...0x103c3 => true,
+ 0x103c8...0x103cf => true,
+ 0x103d1...0x103d5 => true,
+ 0x10400...0x1044f => true,
+ 0x10450...0x1049d => true,
+ 0x104b0...0x104d3 => true,
+ 0x104d8...0x104fb => true,
+ 0x10500...0x10527 => true,
+ 0x10530...0x10563 => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10600...0x10736 => true,
+ 0x10740...0x10755 => true,
+ 0x10760...0x10767 => true,
+ 0x10780...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x10800...0x10805 => true,
+ 0x10808 => true,
+ 0x1080a...0x10835 => true,
+ 0x10837...0x10838 => true,
+ 0x1083c => true,
+ 0x1083f...0x10855 => true,
+ 0x10860...0x10876 => true,
+ 0x10880...0x1089e => true,
+ 0x108e0...0x108f2 => true,
+ 0x108f4...0x108f5 => true,
+ 0x10900...0x10915 => true,
+ 0x10920...0x10939 => true,
+ 0x10980...0x109b7 => true,
+ 0x109be...0x109bf => true,
+ 0x10a00 => true,
+ 0x10a10...0x10a13 => true,
+ 0x10a15...0x10a17 => true,
+ 0x10a19...0x10a35 => true,
+ 0x10a60...0x10a7c => true,
+ 0x10a80...0x10a9c => true,
+ 0x10ac0...0x10ac7 => true,
+ 0x10ac9...0x10ae4 => true,
+ 0x10b00...0x10b35 => true,
+ 0x10b40...0x10b55 => true,
+ 0x10b60...0x10b72 => true,
+ 0x10b80...0x10b91 => true,
+ 0x10c00...0x10c48 => true,
+ 0x10c80...0x10cb2 => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x10d00...0x10d23 => true,
+ 0x10e80...0x10ea9 => true,
+ 0x10eb0...0x10eb1 => true,
+ 0x10f00...0x10f1c => true,
+ 0x10f27 => true,
+ 0x10f30...0x10f45 => true,
+ 0x10f70...0x10f81 => true,
+ 0x10fb0...0x10fc4 => true,
+ 0x10fe0...0x10ff6 => true,
+ 0x11003...0x11037 => true,
+ 0x11071...0x11072 => true,
+ 0x11075 => true,
+ 0x11083...0x110af => true,
+ 0x110d0...0x110e8 => true,
+ 0x11103...0x11126 => true,
+ 0x11144 => true,
+ 0x11147 => true,
+ 0x11150...0x11172 => true,
+ 0x11176 => true,
+ 0x11183...0x111b2 => true,
+ 0x111c1...0x111c4 => true,
+ 0x111da => true,
+ 0x111dc => true,
+ 0x11200...0x11211 => true,
+ 0x11213...0x1122b => true,
+ 0x1123f...0x11240 => true,
+ 0x11280...0x11286 => true,
+ 0x11288 => true,
+ 0x1128a...0x1128d => true,
+ 0x1128f...0x1129d => true,
+ 0x1129f...0x112a8 => true,
+ 0x112b0...0x112de => true,
+ 0x11305...0x1130c => true,
+ 0x1130f...0x11310 => true,
+ 0x11313...0x11328 => true,
+ 0x1132a...0x11330 => true,
+ 0x11332...0x11333 => true,
+ 0x11335...0x11339 => true,
+ 0x1133d => true,
+ 0x11350 => true,
+ 0x1135d...0x11361 => true,
+ 0x11400...0x11434 => true,
+ 0x11447...0x1144a => true,
+ 0x1145f...0x11461 => true,
+ 0x11480...0x114af => true,
+ 0x114c4...0x114c5 => true,
+ 0x114c7 => true,
+ 0x11580...0x115ae => true,
+ 0x115d8...0x115db => true,
+ 0x11600...0x1162f => true,
+ 0x11644 => true,
+ 0x11680...0x116aa => true,
+ 0x116b8 => true,
+ 0x11700...0x1171a => true,
+ 0x11740...0x11746 => true,
+ 0x11800...0x1182b => true,
+ 0x118a0...0x118df => true,
+ 0x118ff...0x11906 => true,
+ 0x11909 => true,
+ 0x1190c...0x11913 => true,
+ 0x11915...0x11916 => true,
+ 0x11918...0x1192f => true,
+ 0x1193f => true,
+ 0x11941 => true,
+ 0x119a0...0x119a7 => true,
+ 0x119aa...0x119d0 => true,
+ 0x119e1 => true,
+ 0x119e3 => true,
+ 0x11a00 => true,
+ 0x11a0b...0x11a32 => true,
+ 0x11a3a => true,
+ 0x11a50 => true,
+ 0x11a5c...0x11a89 => true,
+ 0x11a9d => true,
+ 0x11ab0...0x11af8 => true,
+ 0x11c00...0x11c08 => true,
+ 0x11c0a...0x11c2e => true,
+ 0x11c40 => true,
+ 0x11c72...0x11c8f => true,
+ 0x11d00...0x11d06 => true,
+ 0x11d08...0x11d09 => true,
+ 0x11d0b...0x11d30 => true,
+ 0x11d46 => true,
+ 0x11d60...0x11d65 => true,
+ 0x11d67...0x11d68 => true,
+ 0x11d6a...0x11d89 => true,
+ 0x11d98 => true,
+ 0x11ee0...0x11ef2 => true,
+ 0x11f02 => true,
+ 0x11f04...0x11f10 => true,
+ 0x11f12...0x11f33 => true,
+ 0x11fb0 => true,
+ 0x12000...0x12399 => true,
+ 0x12400...0x1246e => true,
+ 0x12480...0x12543 => true,
+ 0x12f90...0x12ff0 => true,
+ 0x13000...0x1342f => true,
+ 0x13441...0x13446 => true,
+ 0x14400...0x14646 => true,
+ 0x16800...0x16a38 => true,
+ 0x16a40...0x16a5e => true,
+ 0x16a70...0x16abe => true,
+ 0x16ad0...0x16aed => true,
+ 0x16b00...0x16b2f => true,
+ 0x16b40...0x16b43 => true,
+ 0x16b63...0x16b77 => true,
+ 0x16b7d...0x16b8f => true,
+ 0x16e40...0x16e7f => true,
+ 0x16f00...0x16f4a => true,
+ 0x16f50 => true,
+ 0x16f93...0x16f9f => true,
+ 0x16fe0...0x16fe1 => true,
+ 0x16fe3 => true,
+ 0x17000...0x187f7 => true,
+ 0x18800...0x18cd5 => true,
+ 0x18d00...0x18d08 => true,
+ 0x1aff0...0x1aff3 => true,
+ 0x1aff5...0x1affb => true,
+ 0x1affd...0x1affe => true,
+ 0x1b000...0x1b122 => true,
+ 0x1b132 => true,
+ 0x1b150...0x1b152 => true,
+ 0x1b155 => true,
+ 0x1b164...0x1b167 => true,
+ 0x1b170...0x1b2fb => true,
+ 0x1bc00...0x1bc6a => true,
+ 0x1bc70...0x1bc7c => true,
+ 0x1bc80...0x1bc88 => true,
+ 0x1bc90...0x1bc99 => true,
+ 0x1d400...0x1d454 => true,
+ 0x1d456...0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d51e...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d552...0x1d6a5 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6dc...0x1d6fa => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d716...0x1d734 => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d750...0x1d76e => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d78a...0x1d7a8 => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c4...0x1d7cb => true,
+ 0x1df00...0x1df09 => true,
+ 0x1df0a => true,
+ 0x1df0b...0x1df1e => true,
+ 0x1df25...0x1df2a => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e100...0x1e12c => true,
+ 0x1e137...0x1e13d => true,
+ 0x1e14e => true,
+ 0x1e290...0x1e2ad => true,
+ 0x1e2c0...0x1e2eb => true,
+ 0x1e4d0...0x1e4ea => true,
+ 0x1e4eb => true,
+ 0x1e7e0...0x1e7e6 => true,
+ 0x1e7e8...0x1e7eb => true,
+ 0x1e7ed...0x1e7ee => true,
+ 0x1e7f0...0x1e7fe => true,
+ 0x1e800...0x1e8c4 => true,
+ 0x1e900...0x1e943 => true,
+ 0x1e94b => true,
+ 0x1ee00...0x1ee03 => true,
+ 0x1ee05...0x1ee1f => true,
+ 0x1ee21...0x1ee22 => true,
+ 0x1ee24 => true,
+ 0x1ee27 => true,
+ 0x1ee29...0x1ee32 => true,
+ 0x1ee34...0x1ee37 => true,
+ 0x1ee39 => true,
+ 0x1ee3b => true,
+ 0x1ee42 => true,
+ 0x1ee47 => true,
+ 0x1ee49 => true,
+ 0x1ee4b => true,
+ 0x1ee4d...0x1ee4f => true,
+ 0x1ee51...0x1ee52 => true,
+ 0x1ee54 => true,
+ 0x1ee57 => true,
+ 0x1ee59 => true,
+ 0x1ee5b => true,
+ 0x1ee5d => true,
+ 0x1ee5f => true,
+ 0x1ee61...0x1ee62 => true,
+ 0x1ee64 => true,
+ 0x1ee67...0x1ee6a => true,
+ 0x1ee6c...0x1ee72 => true,
+ 0x1ee74...0x1ee77 => true,
+ 0x1ee79...0x1ee7c => true,
+ 0x1ee7e => true,
+ 0x1ee80...0x1ee89 => true,
+ 0x1ee8b...0x1ee9b => true,
+ 0x1eea1...0x1eea3 => true,
+ 0x1eea5...0x1eea9 => true,
+ 0x1eeab...0x1eebb => true,
+ 0x20000...0x2a6df => true,
+ 0x2a700...0x2b739 => true,
+ 0x2b740...0x2b81d => true,
+ 0x2b820...0x2cea1 => true,
+ 0x2ceb0...0x2ebe0 => true,
+ 0x2f800...0x2fa1d => true,
+ 0x30000...0x3134a => true,
+ 0x31350...0x323af => true,
+ else => false,
+ };
+}
+
+pub fn isIdContinue(cp: u21) bool {
+ if (cp < 0x30 or cp > 0xe01ef) return false;
+
+ return switch (cp) {
+ 0x30...0x39 => true,
+ 0x41...0x5a => true,
+ 0x5f => true,
+ 0x61...0x7a => true,
+ 0xaa => true,
+ 0xb5 => true,
+ 0xb7 => true,
+ 0xba => true,
+ 0xc0...0xd6 => true,
+ 0xd8...0xf6 => true,
+ 0xf8...0x1ba => true,
+ 0x1bb => true,
+ 0x1bc...0x1bf => true,
+ 0x1c0...0x1c3 => true,
+ 0x1c4...0x293 => true,
+ 0x294 => true,
+ 0x295...0x2af => true,
+ 0x2b0...0x2c1 => true,
+ 0x2c6...0x2d1 => true,
+ 0x2e0...0x2e4 => true,
+ 0x2ec => true,
+ 0x2ee => true,
+ 0x300...0x36f => true,
+ 0x370...0x373 => true,
+ 0x374 => true,
+ 0x376...0x377 => true,
+ 0x37a => true,
+ 0x37b...0x37d => true,
+ 0x37f => true,
+ 0x386 => true,
+ 0x387 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x3a1 => true,
+ 0x3a3...0x3f5 => true,
+ 0x3f7...0x481 => true,
+ 0x483...0x487 => true,
+ 0x48a...0x52f => true,
+ 0x531...0x556 => true,
+ 0x559 => true,
+ 0x560...0x588 => true,
+ 0x591...0x5bd => true,
+ 0x5bf => true,
+ 0x5c1...0x5c2 => true,
+ 0x5c4...0x5c5 => true,
+ 0x5c7 => true,
+ 0x5d0...0x5ea => true,
+ 0x5ef...0x5f2 => true,
+ 0x610...0x61a => true,
+ 0x620...0x63f => true,
+ 0x640 => true,
+ 0x641...0x64a => true,
+ 0x64b...0x65f => true,
+ 0x660...0x669 => true,
+ 0x66e...0x66f => true,
+ 0x670 => true,
+ 0x671...0x6d3 => true,
+ 0x6d5 => true,
+ 0x6d6...0x6dc => true,
+ 0x6df...0x6e4 => true,
+ 0x6e5...0x6e6 => true,
+ 0x6e7...0x6e8 => true,
+ 0x6ea...0x6ed => true,
+ 0x6ee...0x6ef => true,
+ 0x6f0...0x6f9 => true,
+ 0x6fa...0x6fc => true,
+ 0x6ff => true,
+ 0x710 => true,
+ 0x711 => true,
+ 0x712...0x72f => true,
+ 0x730...0x74a => true,
+ 0x74d...0x7a5 => true,
+ 0x7a6...0x7b0 => true,
+ 0x7b1 => true,
+ 0x7c0...0x7c9 => true,
+ 0x7ca...0x7ea => true,
+ 0x7eb...0x7f3 => true,
+ 0x7f4...0x7f5 => true,
+ 0x7fa => true,
+ 0x7fd => true,
+ 0x800...0x815 => true,
+ 0x816...0x819 => true,
+ 0x81a => true,
+ 0x81b...0x823 => true,
+ 0x824 => true,
+ 0x825...0x827 => true,
+ 0x828 => true,
+ 0x829...0x82d => true,
+ 0x840...0x858 => true,
+ 0x859...0x85b => true,
+ 0x860...0x86a => true,
+ 0x870...0x887 => true,
+ 0x889...0x88e => true,
+ 0x898...0x89f => true,
+ 0x8a0...0x8c8 => true,
+ 0x8c9 => true,
+ 0x8ca...0x8e1 => true,
+ 0x8e3...0x902 => true,
+ 0x903 => true,
+ 0x904...0x939 => true,
+ 0x93a => true,
+ 0x93b => true,
+ 0x93c => true,
+ 0x93d => true,
+ 0x93e...0x940 => true,
+ 0x941...0x948 => true,
+ 0x949...0x94c => true,
+ 0x94d => true,
+ 0x94e...0x94f => true,
+ 0x950 => true,
+ 0x951...0x957 => true,
+ 0x958...0x961 => true,
+ 0x962...0x963 => true,
+ 0x966...0x96f => true,
+ 0x971 => true,
+ 0x972...0x980 => true,
+ 0x981 => true,
+ 0x982...0x983 => true,
+ 0x985...0x98c => true,
+ 0x98f...0x990 => true,
+ 0x993...0x9a8 => true,
+ 0x9aa...0x9b0 => true,
+ 0x9b2 => true,
+ 0x9b6...0x9b9 => true,
+ 0x9bc => true,
+ 0x9bd => true,
+ 0x9be...0x9c0 => true,
+ 0x9c1...0x9c4 => true,
+ 0x9c7...0x9c8 => true,
+ 0x9cb...0x9cc => true,
+ 0x9cd => true,
+ 0x9ce => true,
+ 0x9d7 => true,
+ 0x9dc...0x9dd => true,
+ 0x9df...0x9e1 => true,
+ 0x9e2...0x9e3 => true,
+ 0x9e6...0x9ef => true,
+ 0x9f0...0x9f1 => true,
+ 0x9fc => true,
+ 0x9fe => true,
+ 0xa01...0xa02 => true,
+ 0xa03 => true,
+ 0xa05...0xa0a => true,
+ 0xa0f...0xa10 => true,
+ 0xa13...0xa28 => true,
+ 0xa2a...0xa30 => true,
+ 0xa32...0xa33 => true,
+ 0xa35...0xa36 => true,
+ 0xa38...0xa39 => true,
+ 0xa3c => true,
+ 0xa3e...0xa40 => true,
+ 0xa41...0xa42 => true,
+ 0xa47...0xa48 => true,
+ 0xa4b...0xa4d => true,
+ 0xa51 => true,
+ 0xa59...0xa5c => true,
+ 0xa5e => true,
+ 0xa66...0xa6f => true,
+ 0xa70...0xa71 => true,
+ 0xa72...0xa74 => true,
+ 0xa75 => true,
+ 0xa81...0xa82 => true,
+ 0xa83 => true,
+ 0xa85...0xa8d => true,
+ 0xa8f...0xa91 => true,
+ 0xa93...0xaa8 => true,
+ 0xaaa...0xab0 => true,
+ 0xab2...0xab3 => true,
+ 0xab5...0xab9 => true,
+ 0xabc => true,
+ 0xabd => true,
+ 0xabe...0xac0 => true,
+ 0xac1...0xac5 => true,
+ 0xac7...0xac8 => true,
+ 0xac9 => true,
+ 0xacb...0xacc => true,
+ 0xacd => true,
+ 0xad0 => true,
+ 0xae0...0xae1 => true,
+ 0xae2...0xae3 => true,
+ 0xae6...0xaef => true,
+ 0xaf9 => true,
+ 0xafa...0xaff => true,
+ 0xb01 => true,
+ 0xb02...0xb03 => true,
+ 0xb05...0xb0c => true,
+ 0xb0f...0xb10 => true,
+ 0xb13...0xb28 => true,
+ 0xb2a...0xb30 => true,
+ 0xb32...0xb33 => true,
+ 0xb35...0xb39 => true,
+ 0xb3c => true,
+ 0xb3d => true,
+ 0xb3e => true,
+ 0xb3f => true,
+ 0xb40 => true,
+ 0xb41...0xb44 => true,
+ 0xb47...0xb48 => true,
+ 0xb4b...0xb4c => true,
+ 0xb4d => true,
+ 0xb55...0xb56 => true,
+ 0xb57 => true,
+ 0xb5c...0xb5d => true,
+ 0xb5f...0xb61 => true,
+ 0xb62...0xb63 => true,
+ 0xb66...0xb6f => true,
+ 0xb71 => true,
+ 0xb82 => true,
+ 0xb83 => true,
+ 0xb85...0xb8a => true,
+ 0xb8e...0xb90 => true,
+ 0xb92...0xb95 => true,
+ 0xb99...0xb9a => true,
+ 0xb9c => true,
+ 0xb9e...0xb9f => true,
+ 0xba3...0xba4 => true,
+ 0xba8...0xbaa => true,
+ 0xbae...0xbb9 => true,
+ 0xbbe...0xbbf => true,
+ 0xbc0 => true,
+ 0xbc1...0xbc2 => true,
+ 0xbc6...0xbc8 => true,
+ 0xbca...0xbcc => true,
+ 0xbcd => true,
+ 0xbd0 => true,
+ 0xbd7 => true,
+ 0xbe6...0xbef => true,
+ 0xc00 => true,
+ 0xc01...0xc03 => true,
+ 0xc04 => true,
+ 0xc05...0xc0c => true,
+ 0xc0e...0xc10 => true,
+ 0xc12...0xc28 => true,
+ 0xc2a...0xc39 => true,
+ 0xc3c => true,
+ 0xc3d => true,
+ 0xc3e...0xc40 => true,
+ 0xc41...0xc44 => true,
+ 0xc46...0xc48 => true,
+ 0xc4a...0xc4d => true,
+ 0xc55...0xc56 => true,
+ 0xc58...0xc5a => true,
+ 0xc5d => true,
+ 0xc60...0xc61 => true,
+ 0xc62...0xc63 => true,
+ 0xc66...0xc6f => true,
+ 0xc80 => true,
+ 0xc81 => true,
+ 0xc82...0xc83 => true,
+ 0xc85...0xc8c => true,
+ 0xc8e...0xc90 => true,
+ 0xc92...0xca8 => true,
+ 0xcaa...0xcb3 => true,
+ 0xcb5...0xcb9 => true,
+ 0xcbc => true,
+ 0xcbd => true,
+ 0xcbe => true,
+ 0xcbf => true,
+ 0xcc0...0xcc4 => true,
+ 0xcc6 => true,
+ 0xcc7...0xcc8 => true,
+ 0xcca...0xccb => true,
+ 0xccc...0xccd => true,
+ 0xcd5...0xcd6 => true,
+ 0xcdd...0xcde => true,
+ 0xce0...0xce1 => true,
+ 0xce2...0xce3 => true,
+ 0xce6...0xcef => true,
+ 0xcf1...0xcf2 => true,
+ 0xcf3 => true,
+ 0xd00...0xd01 => true,
+ 0xd02...0xd03 => true,
+ 0xd04...0xd0c => true,
+ 0xd0e...0xd10 => true,
+ 0xd12...0xd3a => true,
+ 0xd3b...0xd3c => true,
+ 0xd3d => true,
+ 0xd3e...0xd40 => true,
+ 0xd41...0xd44 => true,
+ 0xd46...0xd48 => true,
+ 0xd4a...0xd4c => true,
+ 0xd4d => true,
+ 0xd4e => true,
+ 0xd54...0xd56 => true,
+ 0xd57 => true,
+ 0xd5f...0xd61 => true,
+ 0xd62...0xd63 => true,
+ 0xd66...0xd6f => true,
+ 0xd7a...0xd7f => true,
+ 0xd81 => true,
+ 0xd82...0xd83 => true,
+ 0xd85...0xd96 => true,
+ 0xd9a...0xdb1 => true,
+ 0xdb3...0xdbb => true,
+ 0xdbd => true,
+ 0xdc0...0xdc6 => true,
+ 0xdca => true,
+ 0xdcf...0xdd1 => true,
+ 0xdd2...0xdd4 => true,
+ 0xdd6 => true,
+ 0xdd8...0xddf => true,
+ 0xde6...0xdef => true,
+ 0xdf2...0xdf3 => true,
+ 0xe01...0xe30 => true,
+ 0xe31 => true,
+ 0xe32...0xe33 => true,
+ 0xe34...0xe3a => true,
+ 0xe40...0xe45 => true,
+ 0xe46 => true,
+ 0xe47...0xe4e => true,
+ 0xe50...0xe59 => true,
+ 0xe81...0xe82 => true,
+ 0xe84 => true,
+ 0xe86...0xe8a => true,
+ 0xe8c...0xea3 => true,
+ 0xea5 => true,
+ 0xea7...0xeb0 => true,
+ 0xeb1 => true,
+ 0xeb2...0xeb3 => true,
+ 0xeb4...0xebc => true,
+ 0xebd => true,
+ 0xec0...0xec4 => true,
+ 0xec6 => true,
+ 0xec8...0xece => true,
+ 0xed0...0xed9 => true,
+ 0xedc...0xedf => true,
+ 0xf00 => true,
+ 0xf18...0xf19 => true,
+ 0xf20...0xf29 => true,
+ 0xf35 => true,
+ 0xf37 => true,
+ 0xf39 => true,
+ 0xf3e...0xf3f => true,
+ 0xf40...0xf47 => true,
+ 0xf49...0xf6c => true,
+ 0xf71...0xf7e => true,
+ 0xf7f => true,
+ 0xf80...0xf84 => true,
+ 0xf86...0xf87 => true,
+ 0xf88...0xf8c => true,
+ 0xf8d...0xf97 => true,
+ 0xf99...0xfbc => true,
+ 0xfc6 => true,
+ 0x1000...0x102a => true,
+ 0x102b...0x102c => true,
+ 0x102d...0x1030 => true,
+ 0x1031 => true,
+ 0x1032...0x1037 => true,
+ 0x1038 => true,
+ 0x1039...0x103a => true,
+ 0x103b...0x103c => true,
+ 0x103d...0x103e => true,
+ 0x103f => true,
+ 0x1040...0x1049 => true,
+ 0x1050...0x1055 => true,
+ 0x1056...0x1057 => true,
+ 0x1058...0x1059 => true,
+ 0x105a...0x105d => true,
+ 0x105e...0x1060 => true,
+ 0x1061 => true,
+ 0x1062...0x1064 => true,
+ 0x1065...0x1066 => true,
+ 0x1067...0x106d => true,
+ 0x106e...0x1070 => true,
+ 0x1071...0x1074 => true,
+ 0x1075...0x1081 => true,
+ 0x1082 => true,
+ 0x1083...0x1084 => true,
+ 0x1085...0x1086 => true,
+ 0x1087...0x108c => true,
+ 0x108d => true,
+ 0x108e => true,
+ 0x108f => true,
+ 0x1090...0x1099 => true,
+ 0x109a...0x109c => true,
+ 0x109d => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x10d0...0x10fa => true,
+ 0x10fc => true,
+ 0x10fd...0x10ff => true,
+ 0x1100...0x1248 => true,
+ 0x124a...0x124d => true,
+ 0x1250...0x1256 => true,
+ 0x1258 => true,
+ 0x125a...0x125d => true,
+ 0x1260...0x1288 => true,
+ 0x128a...0x128d => true,
+ 0x1290...0x12b0 => true,
+ 0x12b2...0x12b5 => true,
+ 0x12b8...0x12be => true,
+ 0x12c0 => true,
+ 0x12c2...0x12c5 => true,
+ 0x12c8...0x12d6 => true,
+ 0x12d8...0x1310 => true,
+ 0x1312...0x1315 => true,
+ 0x1318...0x135a => true,
+ 0x135d...0x135f => true,
+ 0x1369...0x1371 => true,
+ 0x1380...0x138f => true,
+ 0x13a0...0x13f5 => true,
+ 0x13f8...0x13fd => true,
+ 0x1401...0x166c => true,
+ 0x166f...0x167f => true,
+ 0x1681...0x169a => true,
+ 0x16a0...0x16ea => true,
+ 0x16ee...0x16f0 => true,
+ 0x16f1...0x16f8 => true,
+ 0x1700...0x1711 => true,
+ 0x1712...0x1714 => true,
+ 0x1715 => true,
+ 0x171f...0x1731 => true,
+ 0x1732...0x1733 => true,
+ 0x1734 => true,
+ 0x1740...0x1751 => true,
+ 0x1752...0x1753 => true,
+ 0x1760...0x176c => true,
+ 0x176e...0x1770 => true,
+ 0x1772...0x1773 => true,
+ 0x1780...0x17b3 => true,
+ 0x17b4...0x17b5 => true,
+ 0x17b6 => true,
+ 0x17b7...0x17bd => true,
+ 0x17be...0x17c5 => true,
+ 0x17c6 => true,
+ 0x17c7...0x17c8 => true,
+ 0x17c9...0x17d3 => true,
+ 0x17d7 => true,
+ 0x17dc => true,
+ 0x17dd => true,
+ 0x17e0...0x17e9 => true,
+ 0x180b...0x180d => true,
+ 0x180f => true,
+ 0x1810...0x1819 => true,
+ 0x1820...0x1842 => true,
+ 0x1843 => true,
+ 0x1844...0x1878 => true,
+ 0x1880...0x1884 => true,
+ 0x1885...0x1886 => true,
+ 0x1887...0x18a8 => true,
+ 0x18a9 => true,
+ 0x18aa => true,
+ 0x18b0...0x18f5 => true,
+ 0x1900...0x191e => true,
+ 0x1920...0x1922 => true,
+ 0x1923...0x1926 => true,
+ 0x1927...0x1928 => true,
+ 0x1929...0x192b => true,
+ 0x1930...0x1931 => true,
+ 0x1932 => true,
+ 0x1933...0x1938 => true,
+ 0x1939...0x193b => true,
+ 0x1946...0x194f => true,
+ 0x1950...0x196d => true,
+ 0x1970...0x1974 => true,
+ 0x1980...0x19ab => true,
+ 0x19b0...0x19c9 => true,
+ 0x19d0...0x19d9 => true,
+ 0x19da => true,
+ 0x1a00...0x1a16 => true,
+ 0x1a17...0x1a18 => true,
+ 0x1a19...0x1a1a => true,
+ 0x1a1b => true,
+ 0x1a20...0x1a54 => true,
+ 0x1a55 => true,
+ 0x1a56 => true,
+ 0x1a57 => true,
+ 0x1a58...0x1a5e => true,
+ 0x1a60 => true,
+ 0x1a61 => true,
+ 0x1a62 => true,
+ 0x1a63...0x1a64 => true,
+ 0x1a65...0x1a6c => true,
+ 0x1a6d...0x1a72 => true,
+ 0x1a73...0x1a7c => true,
+ 0x1a7f => true,
+ 0x1a80...0x1a89 => true,
+ 0x1a90...0x1a99 => true,
+ 0x1aa7 => true,
+ 0x1ab0...0x1abd => true,
+ 0x1abf...0x1ace => true,
+ 0x1b00...0x1b03 => true,
+ 0x1b04 => true,
+ 0x1b05...0x1b33 => true,
+ 0x1b34 => true,
+ 0x1b35 => true,
+ 0x1b36...0x1b3a => true,
+ 0x1b3b => true,
+ 0x1b3c => true,
+ 0x1b3d...0x1b41 => true,
+ 0x1b42 => true,
+ 0x1b43...0x1b44 => true,
+ 0x1b45...0x1b4c => true,
+ 0x1b50...0x1b59 => true,
+ 0x1b6b...0x1b73 => true,
+ 0x1b80...0x1b81 => true,
+ 0x1b82 => true,
+ 0x1b83...0x1ba0 => true,
+ 0x1ba1 => true,
+ 0x1ba2...0x1ba5 => true,
+ 0x1ba6...0x1ba7 => true,
+ 0x1ba8...0x1ba9 => true,
+ 0x1baa => true,
+ 0x1bab...0x1bad => true,
+ 0x1bae...0x1baf => true,
+ 0x1bb0...0x1bb9 => true,
+ 0x1bba...0x1be5 => true,
+ 0x1be6 => true,
+ 0x1be7 => true,
+ 0x1be8...0x1be9 => true,
+ 0x1bea...0x1bec => true,
+ 0x1bed => true,
+ 0x1bee => true,
+ 0x1bef...0x1bf1 => true,
+ 0x1bf2...0x1bf3 => true,
+ 0x1c00...0x1c23 => true,
+ 0x1c24...0x1c2b => true,
+ 0x1c2c...0x1c33 => true,
+ 0x1c34...0x1c35 => true,
+ 0x1c36...0x1c37 => true,
+ 0x1c40...0x1c49 => true,
+ 0x1c4d...0x1c4f => true,
+ 0x1c50...0x1c59 => true,
+ 0x1c5a...0x1c77 => true,
+ 0x1c78...0x1c7d => true,
+ 0x1c80...0x1c88 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1cd0...0x1cd2 => true,
+ 0x1cd4...0x1ce0 => true,
+ 0x1ce1 => true,
+ 0x1ce2...0x1ce8 => true,
+ 0x1ce9...0x1cec => true,
+ 0x1ced => true,
+ 0x1cee...0x1cf3 => true,
+ 0x1cf4 => true,
+ 0x1cf5...0x1cf6 => true,
+ 0x1cf7 => true,
+ 0x1cf8...0x1cf9 => true,
+ 0x1cfa => true,
+ 0x1d00...0x1d2b => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d6b...0x1d77 => true,
+ 0x1d78 => true,
+ 0x1d79...0x1d9a => true,
+ 0x1d9b...0x1dbf => true,
+ 0x1dc0...0x1dff => true,
+ 0x1e00...0x1f15 => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f20...0x1f45 => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f...0x1f7d => true,
+ 0x1f80...0x1fb4 => true,
+ 0x1fb6...0x1fbc => true,
+ 0x1fbe => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fcc => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fdb => true,
+ 0x1fe0...0x1fec => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ffc => true,
+ 0x203f...0x2040 => true,
+ 0x2054 => true,
+ 0x2071 => true,
+ 0x207f => true,
+ 0x2090...0x209c => true,
+ 0x20d0...0x20dc => true,
+ 0x20e1 => true,
+ 0x20e5...0x20f0 => true,
+ 0x2102 => true,
+ 0x2107 => true,
+ 0x210a...0x2113 => true,
+ 0x2115 => true,
+ 0x2118 => true,
+ 0x2119...0x211d => true,
+ 0x2124 => true,
+ 0x2126 => true,
+ 0x2128 => true,
+ 0x212a...0x212d => true,
+ 0x212e => true,
+ 0x212f...0x2134 => true,
+ 0x2135...0x2138 => true,
+ 0x2139 => true,
+ 0x213c...0x213f => true,
+ 0x2145...0x2149 => true,
+ 0x214e => true,
+ 0x2160...0x2182 => true,
+ 0x2183...0x2184 => true,
+ 0x2185...0x2188 => true,
+ 0x2c00...0x2c7b => true,
+ 0x2c7c...0x2c7d => true,
+ 0x2c7e...0x2ce4 => true,
+ 0x2ceb...0x2cee => true,
+ 0x2cef...0x2cf1 => true,
+ 0x2cf2...0x2cf3 => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0x2d30...0x2d67 => true,
+ 0x2d6f => true,
+ 0x2d7f => true,
+ 0x2d80...0x2d96 => true,
+ 0x2da0...0x2da6 => true,
+ 0x2da8...0x2dae => true,
+ 0x2db0...0x2db6 => true,
+ 0x2db8...0x2dbe => true,
+ 0x2dc0...0x2dc6 => true,
+ 0x2dc8...0x2dce => true,
+ 0x2dd0...0x2dd6 => true,
+ 0x2dd8...0x2dde => true,
+ 0x2de0...0x2dff => true,
+ 0x3005 => true,
+ 0x3006 => true,
+ 0x3007 => true,
+ 0x3021...0x3029 => true,
+ 0x302a...0x302d => true,
+ 0x302e...0x302f => true,
+ 0x3031...0x3035 => true,
+ 0x3038...0x303a => true,
+ 0x303b => true,
+ 0x303c => true,
+ 0x3041...0x3096 => true,
+ 0x3099...0x309a => true,
+ 0x309b...0x309c => true,
+ 0x309d...0x309e => true,
+ 0x309f => true,
+ 0x30a1...0x30fa => true,
+ 0x30fc...0x30fe => true,
+ 0x30ff => true,
+ 0x3105...0x312f => true,
+ 0x3131...0x318e => true,
+ 0x31a0...0x31bf => true,
+ 0x31f0...0x31ff => true,
+ 0x3400...0x4dbf => true,
+ 0x4e00...0xa014 => true,
+ 0xa015 => true,
+ 0xa016...0xa48c => true,
+ 0xa4d0...0xa4f7 => true,
+ 0xa4f8...0xa4fd => true,
+ 0xa500...0xa60b => true,
+ 0xa60c => true,
+ 0xa610...0xa61f => true,
+ 0xa620...0xa629 => true,
+ 0xa62a...0xa62b => true,
+ 0xa640...0xa66d => true,
+ 0xa66e => true,
+ 0xa66f => true,
+ 0xa674...0xa67d => true,
+ 0xa67f => true,
+ 0xa680...0xa69b => true,
+ 0xa69c...0xa69d => true,
+ 0xa69e...0xa69f => true,
+ 0xa6a0...0xa6e5 => true,
+ 0xa6e6...0xa6ef => true,
+ 0xa6f0...0xa6f1 => true,
+ 0xa717...0xa71f => true,
+ 0xa722...0xa76f => true,
+ 0xa770 => true,
+ 0xa771...0xa787 => true,
+ 0xa788 => true,
+ 0xa78b...0xa78e => true,
+ 0xa78f => true,
+ 0xa790...0xa7ca => true,
+ 0xa7d0...0xa7d1 => true,
+ 0xa7d3 => true,
+ 0xa7d5...0xa7d9 => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f5...0xa7f6 => true,
+ 0xa7f7 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa7fa => true,
+ 0xa7fb...0xa801 => true,
+ 0xa802 => true,
+ 0xa803...0xa805 => true,
+ 0xa806 => true,
+ 0xa807...0xa80a => true,
+ 0xa80b => true,
+ 0xa80c...0xa822 => true,
+ 0xa823...0xa824 => true,
+ 0xa825...0xa826 => true,
+ 0xa827 => true,
+ 0xa82c => true,
+ 0xa840...0xa873 => true,
+ 0xa880...0xa881 => true,
+ 0xa882...0xa8b3 => true,
+ 0xa8b4...0xa8c3 => true,
+ 0xa8c4...0xa8c5 => true,
+ 0xa8d0...0xa8d9 => true,
+ 0xa8e0...0xa8f1 => true,
+ 0xa8f2...0xa8f7 => true,
+ 0xa8fb => true,
+ 0xa8fd...0xa8fe => true,
+ 0xa8ff => true,
+ 0xa900...0xa909 => true,
+ 0xa90a...0xa925 => true,
+ 0xa926...0xa92d => true,
+ 0xa930...0xa946 => true,
+ 0xa947...0xa951 => true,
+ 0xa952...0xa953 => true,
+ 0xa960...0xa97c => true,
+ 0xa980...0xa982 => true,
+ 0xa983 => true,
+ 0xa984...0xa9b2 => true,
+ 0xa9b3 => true,
+ 0xa9b4...0xa9b5 => true,
+ 0xa9b6...0xa9b9 => true,
+ 0xa9ba...0xa9bb => true,
+ 0xa9bc...0xa9bd => true,
+ 0xa9be...0xa9c0 => true,
+ 0xa9cf => true,
+ 0xa9d0...0xa9d9 => true,
+ 0xa9e0...0xa9e4 => true,
+ 0xa9e5 => true,
+ 0xa9e6 => true,
+ 0xa9e7...0xa9ef => true,
+ 0xa9f0...0xa9f9 => true,
+ 0xa9fa...0xa9fe => true,
+ 0xaa00...0xaa28 => true,
+ 0xaa29...0xaa2e => true,
+ 0xaa2f...0xaa30 => true,
+ 0xaa31...0xaa32 => true,
+ 0xaa33...0xaa34 => true,
+ 0xaa35...0xaa36 => true,
+ 0xaa40...0xaa42 => true,
+ 0xaa43 => true,
+ 0xaa44...0xaa4b => true,
+ 0xaa4c => true,
+ 0xaa4d => true,
+ 0xaa50...0xaa59 => true,
+ 0xaa60...0xaa6f => true,
+ 0xaa70 => true,
+ 0xaa71...0xaa76 => true,
+ 0xaa7a => true,
+ 0xaa7b => true,
+ 0xaa7c => true,
+ 0xaa7d => true,
+ 0xaa7e...0xaaaf => true,
+ 0xaab0 => true,
+ 0xaab1 => true,
+ 0xaab2...0xaab4 => true,
+ 0xaab5...0xaab6 => true,
+ 0xaab7...0xaab8 => true,
+ 0xaab9...0xaabd => true,
+ 0xaabe...0xaabf => true,
+ 0xaac0 => true,
+ 0xaac1 => true,
+ 0xaac2 => true,
+ 0xaadb...0xaadc => true,
+ 0xaadd => true,
+ 0xaae0...0xaaea => true,
+ 0xaaeb => true,
+ 0xaaec...0xaaed => true,
+ 0xaaee...0xaaef => true,
+ 0xaaf2 => true,
+ 0xaaf3...0xaaf4 => true,
+ 0xaaf5 => true,
+ 0xaaf6 => true,
+ 0xab01...0xab06 => true,
+ 0xab09...0xab0e => true,
+ 0xab11...0xab16 => true,
+ 0xab20...0xab26 => true,
+ 0xab28...0xab2e => true,
+ 0xab30...0xab5a => true,
+ 0xab5c...0xab5f => true,
+ 0xab60...0xab68 => true,
+ 0xab69 => true,
+ 0xab70...0xabbf => true,
+ 0xabc0...0xabe2 => true,
+ 0xabe3...0xabe4 => true,
+ 0xabe5 => true,
+ 0xabe6...0xabe7 => true,
+ 0xabe8 => true,
+ 0xabe9...0xabea => true,
+ 0xabec => true,
+ 0xabed => true,
+ 0xabf0...0xabf9 => true,
+ 0xac00...0xd7a3 => true,
+ 0xd7b0...0xd7c6 => true,
+ 0xd7cb...0xd7fb => true,
+ 0xf900...0xfa6d => true,
+ 0xfa70...0xfad9 => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xfb1d => true,
+ 0xfb1e => true,
+ 0xfb1f...0xfb28 => true,
+ 0xfb2a...0xfb36 => true,
+ 0xfb38...0xfb3c => true,
+ 0xfb3e => true,
+ 0xfb40...0xfb41 => true,
+ 0xfb43...0xfb44 => true,
+ 0xfb46...0xfbb1 => true,
+ 0xfbd3...0xfd3d => true,
+ 0xfd50...0xfd8f => true,
+ 0xfd92...0xfdc7 => true,
+ 0xfdf0...0xfdfb => true,
+ 0xfe00...0xfe0f => true,
+ 0xfe20...0xfe2f => true,
+ 0xfe33...0xfe34 => true,
+ 0xfe4d...0xfe4f => true,
+ 0xfe70...0xfe74 => true,
+ 0xfe76...0xfefc => true,
+ 0xff10...0xff19 => true,
+ 0xff21...0xff3a => true,
+ 0xff3f => true,
+ 0xff41...0xff5a => true,
+ 0xff66...0xff6f => true,
+ 0xff70 => true,
+ 0xff71...0xff9d => true,
+ 0xff9e...0xff9f => true,
+ 0xffa0...0xffbe => true,
+ 0xffc2...0xffc7 => true,
+ 0xffca...0xffcf => true,
+ 0xffd2...0xffd7 => true,
+ 0xffda...0xffdc => true,
+ 0x10000...0x1000b => true,
+ 0x1000d...0x10026 => true,
+ 0x10028...0x1003a => true,
+ 0x1003c...0x1003d => true,
+ 0x1003f...0x1004d => true,
+ 0x10050...0x1005d => true,
+ 0x10080...0x100fa => true,
+ 0x10140...0x10174 => true,
+ 0x101fd => true,
+ 0x10280...0x1029c => true,
+ 0x102a0...0x102d0 => true,
+ 0x102e0 => true,
+ 0x10300...0x1031f => true,
+ 0x1032d...0x10340 => true,
+ 0x10341 => true,
+ 0x10342...0x10349 => true,
+ 0x1034a => true,
+ 0x10350...0x10375 => true,
+ 0x10376...0x1037a => true,
+ 0x10380...0x1039d => true,
+ 0x103a0...0x103c3 => true,
+ 0x103c8...0x103cf => true,
+ 0x103d1...0x103d5 => true,
+ 0x10400...0x1044f => true,
+ 0x10450...0x1049d => true,
+ 0x104a0...0x104a9 => true,
+ 0x104b0...0x104d3 => true,
+ 0x104d8...0x104fb => true,
+ 0x10500...0x10527 => true,
+ 0x10530...0x10563 => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10600...0x10736 => true,
+ 0x10740...0x10755 => true,
+ 0x10760...0x10767 => true,
+ 0x10780...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x10800...0x10805 => true,
+ 0x10808 => true,
+ 0x1080a...0x10835 => true,
+ 0x10837...0x10838 => true,
+ 0x1083c => true,
+ 0x1083f...0x10855 => true,
+ 0x10860...0x10876 => true,
+ 0x10880...0x1089e => true,
+ 0x108e0...0x108f2 => true,
+ 0x108f4...0x108f5 => true,
+ 0x10900...0x10915 => true,
+ 0x10920...0x10939 => true,
+ 0x10980...0x109b7 => true,
+ 0x109be...0x109bf => true,
+ 0x10a00 => true,
+ 0x10a01...0x10a03 => true,
+ 0x10a05...0x10a06 => true,
+ 0x10a0c...0x10a0f => true,
+ 0x10a10...0x10a13 => true,
+ 0x10a15...0x10a17 => true,
+ 0x10a19...0x10a35 => true,
+ 0x10a38...0x10a3a => true,
+ 0x10a3f => true,
+ 0x10a60...0x10a7c => true,
+ 0x10a80...0x10a9c => true,
+ 0x10ac0...0x10ac7 => true,
+ 0x10ac9...0x10ae4 => true,
+ 0x10ae5...0x10ae6 => true,
+ 0x10b00...0x10b35 => true,
+ 0x10b40...0x10b55 => true,
+ 0x10b60...0x10b72 => true,
+ 0x10b80...0x10b91 => true,
+ 0x10c00...0x10c48 => true,
+ 0x10c80...0x10cb2 => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x10d00...0x10d23 => true,
+ 0x10d24...0x10d27 => true,
+ 0x10d30...0x10d39 => true,
+ 0x10e80...0x10ea9 => true,
+ 0x10eab...0x10eac => true,
+ 0x10eb0...0x10eb1 => true,
+ 0x10efd...0x10eff => true,
+ 0x10f00...0x10f1c => true,
+ 0x10f27 => true,
+ 0x10f30...0x10f45 => true,
+ 0x10f46...0x10f50 => true,
+ 0x10f70...0x10f81 => true,
+ 0x10f82...0x10f85 => true,
+ 0x10fb0...0x10fc4 => true,
+ 0x10fe0...0x10ff6 => true,
+ 0x11000 => true,
+ 0x11001 => true,
+ 0x11002 => true,
+ 0x11003...0x11037 => true,
+ 0x11038...0x11046 => true,
+ 0x11066...0x1106f => true,
+ 0x11070 => true,
+ 0x11071...0x11072 => true,
+ 0x11073...0x11074 => true,
+ 0x11075 => true,
+ 0x1107f...0x11081 => true,
+ 0x11082 => true,
+ 0x11083...0x110af => true,
+ 0x110b0...0x110b2 => true,
+ 0x110b3...0x110b6 => true,
+ 0x110b7...0x110b8 => true,
+ 0x110b9...0x110ba => true,
+ 0x110c2 => true,
+ 0x110d0...0x110e8 => true,
+ 0x110f0...0x110f9 => true,
+ 0x11100...0x11102 => true,
+ 0x11103...0x11126 => true,
+ 0x11127...0x1112b => true,
+ 0x1112c => true,
+ 0x1112d...0x11134 => true,
+ 0x11136...0x1113f => true,
+ 0x11144 => true,
+ 0x11145...0x11146 => true,
+ 0x11147 => true,
+ 0x11150...0x11172 => true,
+ 0x11173 => true,
+ 0x11176 => true,
+ 0x11180...0x11181 => true,
+ 0x11182 => true,
+ 0x11183...0x111b2 => true,
+ 0x111b3...0x111b5 => true,
+ 0x111b6...0x111be => true,
+ 0x111bf...0x111c0 => true,
+ 0x111c1...0x111c4 => true,
+ 0x111c9...0x111cc => true,
+ 0x111ce => true,
+ 0x111cf => true,
+ 0x111d0...0x111d9 => true,
+ 0x111da => true,
+ 0x111dc => true,
+ 0x11200...0x11211 => true,
+ 0x11213...0x1122b => true,
+ 0x1122c...0x1122e => true,
+ 0x1122f...0x11231 => true,
+ 0x11232...0x11233 => true,
+ 0x11234 => true,
+ 0x11235 => true,
+ 0x11236...0x11237 => true,
+ 0x1123e => true,
+ 0x1123f...0x11240 => true,
+ 0x11241 => true,
+ 0x11280...0x11286 => true,
+ 0x11288 => true,
+ 0x1128a...0x1128d => true,
+ 0x1128f...0x1129d => true,
+ 0x1129f...0x112a8 => true,
+ 0x112b0...0x112de => true,
+ 0x112df => true,
+ 0x112e0...0x112e2 => true,
+ 0x112e3...0x112ea => true,
+ 0x112f0...0x112f9 => true,
+ 0x11300...0x11301 => true,
+ 0x11302...0x11303 => true,
+ 0x11305...0x1130c => true,
+ 0x1130f...0x11310 => true,
+ 0x11313...0x11328 => true,
+ 0x1132a...0x11330 => true,
+ 0x11332...0x11333 => true,
+ 0x11335...0x11339 => true,
+ 0x1133b...0x1133c => true,
+ 0x1133d => true,
+ 0x1133e...0x1133f => true,
+ 0x11340 => true,
+ 0x11341...0x11344 => true,
+ 0x11347...0x11348 => true,
+ 0x1134b...0x1134d => true,
+ 0x11350 => true,
+ 0x11357 => true,
+ 0x1135d...0x11361 => true,
+ 0x11362...0x11363 => true,
+ 0x11366...0x1136c => true,
+ 0x11370...0x11374 => true,
+ 0x11400...0x11434 => true,
+ 0x11435...0x11437 => true,
+ 0x11438...0x1143f => true,
+ 0x11440...0x11441 => true,
+ 0x11442...0x11444 => true,
+ 0x11445 => true,
+ 0x11446 => true,
+ 0x11447...0x1144a => true,
+ 0x11450...0x11459 => true,
+ 0x1145e => true,
+ 0x1145f...0x11461 => true,
+ 0x11480...0x114af => true,
+ 0x114b0...0x114b2 => true,
+ 0x114b3...0x114b8 => true,
+ 0x114b9 => true,
+ 0x114ba => true,
+ 0x114bb...0x114be => true,
+ 0x114bf...0x114c0 => true,
+ 0x114c1 => true,
+ 0x114c2...0x114c3 => true,
+ 0x114c4...0x114c5 => true,
+ 0x114c7 => true,
+ 0x114d0...0x114d9 => true,
+ 0x11580...0x115ae => true,
+ 0x115af...0x115b1 => true,
+ 0x115b2...0x115b5 => true,
+ 0x115b8...0x115bb => true,
+ 0x115bc...0x115bd => true,
+ 0x115be => true,
+ 0x115bf...0x115c0 => true,
+ 0x115d8...0x115db => true,
+ 0x115dc...0x115dd => true,
+ 0x11600...0x1162f => true,
+ 0x11630...0x11632 => true,
+ 0x11633...0x1163a => true,
+ 0x1163b...0x1163c => true,
+ 0x1163d => true,
+ 0x1163e => true,
+ 0x1163f...0x11640 => true,
+ 0x11644 => true,
+ 0x11650...0x11659 => true,
+ 0x11680...0x116aa => true,
+ 0x116ab => true,
+ 0x116ac => true,
+ 0x116ad => true,
+ 0x116ae...0x116af => true,
+ 0x116b0...0x116b5 => true,
+ 0x116b6 => true,
+ 0x116b7 => true,
+ 0x116b8 => true,
+ 0x116c0...0x116c9 => true,
+ 0x11700...0x1171a => true,
+ 0x1171d...0x1171f => true,
+ 0x11720...0x11721 => true,
+ 0x11722...0x11725 => true,
+ 0x11726 => true,
+ 0x11727...0x1172b => true,
+ 0x11730...0x11739 => true,
+ 0x11740...0x11746 => true,
+ 0x11800...0x1182b => true,
+ 0x1182c...0x1182e => true,
+ 0x1182f...0x11837 => true,
+ 0x11838 => true,
+ 0x11839...0x1183a => true,
+ 0x118a0...0x118df => true,
+ 0x118e0...0x118e9 => true,
+ 0x118ff...0x11906 => true,
+ 0x11909 => true,
+ 0x1190c...0x11913 => true,
+ 0x11915...0x11916 => true,
+ 0x11918...0x1192f => true,
+ 0x11930...0x11935 => true,
+ 0x11937...0x11938 => true,
+ 0x1193b...0x1193c => true,
+ 0x1193d => true,
+ 0x1193e => true,
+ 0x1193f => true,
+ 0x11940 => true,
+ 0x11941 => true,
+ 0x11942 => true,
+ 0x11943 => true,
+ 0x11950...0x11959 => true,
+ 0x119a0...0x119a7 => true,
+ 0x119aa...0x119d0 => true,
+ 0x119d1...0x119d3 => true,
+ 0x119d4...0x119d7 => true,
+ 0x119da...0x119db => true,
+ 0x119dc...0x119df => true,
+ 0x119e0 => true,
+ 0x119e1 => true,
+ 0x119e3 => true,
+ 0x119e4 => true,
+ 0x11a00 => true,
+ 0x11a01...0x11a0a => true,
+ 0x11a0b...0x11a32 => true,
+ 0x11a33...0x11a38 => true,
+ 0x11a39 => true,
+ 0x11a3a => true,
+ 0x11a3b...0x11a3e => true,
+ 0x11a47 => true,
+ 0x11a50 => true,
+ 0x11a51...0x11a56 => true,
+ 0x11a57...0x11a58 => true,
+ 0x11a59...0x11a5b => true,
+ 0x11a5c...0x11a89 => true,
+ 0x11a8a...0x11a96 => true,
+ 0x11a97 => true,
+ 0x11a98...0x11a99 => true,
+ 0x11a9d => true,
+ 0x11ab0...0x11af8 => true,
+ 0x11c00...0x11c08 => true,
+ 0x11c0a...0x11c2e => true,
+ 0x11c2f => true,
+ 0x11c30...0x11c36 => true,
+ 0x11c38...0x11c3d => true,
+ 0x11c3e => true,
+ 0x11c3f => true,
+ 0x11c40 => true,
+ 0x11c50...0x11c59 => true,
+ 0x11c72...0x11c8f => true,
+ 0x11c92...0x11ca7 => true,
+ 0x11ca9 => true,
+ 0x11caa...0x11cb0 => true,
+ 0x11cb1 => true,
+ 0x11cb2...0x11cb3 => true,
+ 0x11cb4 => true,
+ 0x11cb5...0x11cb6 => true,
+ 0x11d00...0x11d06 => true,
+ 0x11d08...0x11d09 => true,
+ 0x11d0b...0x11d30 => true,
+ 0x11d31...0x11d36 => true,
+ 0x11d3a => true,
+ 0x11d3c...0x11d3d => true,
+ 0x11d3f...0x11d45 => true,
+ 0x11d46 => true,
+ 0x11d47 => true,
+ 0x11d50...0x11d59 => true,
+ 0x11d60...0x11d65 => true,
+ 0x11d67...0x11d68 => true,
+ 0x11d6a...0x11d89 => true,
+ 0x11d8a...0x11d8e => true,
+ 0x11d90...0x11d91 => true,
+ 0x11d93...0x11d94 => true,
+ 0x11d95 => true,
+ 0x11d96 => true,
+ 0x11d97 => true,
+ 0x11d98 => true,
+ 0x11da0...0x11da9 => true,
+ 0x11ee0...0x11ef2 => true,
+ 0x11ef3...0x11ef4 => true,
+ 0x11ef5...0x11ef6 => true,
+ 0x11f00...0x11f01 => true,
+ 0x11f02 => true,
+ 0x11f03 => true,
+ 0x11f04...0x11f10 => true,
+ 0x11f12...0x11f33 => true,
+ 0x11f34...0x11f35 => true,
+ 0x11f36...0x11f3a => true,
+ 0x11f3e...0x11f3f => true,
+ 0x11f40 => true,
+ 0x11f41 => true,
+ 0x11f42 => true,
+ 0x11f50...0x11f59 => true,
+ 0x11fb0 => true,
+ 0x12000...0x12399 => true,
+ 0x12400...0x1246e => true,
+ 0x12480...0x12543 => true,
+ 0x12f90...0x12ff0 => true,
+ 0x13000...0x1342f => true,
+ 0x13440 => true,
+ 0x13441...0x13446 => true,
+ 0x13447...0x13455 => true,
+ 0x14400...0x14646 => true,
+ 0x16800...0x16a38 => true,
+ 0x16a40...0x16a5e => true,
+ 0x16a60...0x16a69 => true,
+ 0x16a70...0x16abe => true,
+ 0x16ac0...0x16ac9 => true,
+ 0x16ad0...0x16aed => true,
+ 0x16af0...0x16af4 => true,
+ 0x16b00...0x16b2f => true,
+ 0x16b30...0x16b36 => true,
+ 0x16b40...0x16b43 => true,
+ 0x16b50...0x16b59 => true,
+ 0x16b63...0x16b77 => true,
+ 0x16b7d...0x16b8f => true,
+ 0x16e40...0x16e7f => true,
+ 0x16f00...0x16f4a => true,
+ 0x16f4f => true,
+ 0x16f50 => true,
+ 0x16f51...0x16f87 => true,
+ 0x16f8f...0x16f92 => true,
+ 0x16f93...0x16f9f => true,
+ 0x16fe0...0x16fe1 => true,
+ 0x16fe3 => true,
+ 0x16fe4 => true,
+ 0x16ff0...0x16ff1 => true,
+ 0x17000...0x187f7 => true,
+ 0x18800...0x18cd5 => true,
+ 0x18d00...0x18d08 => true,
+ 0x1aff0...0x1aff3 => true,
+ 0x1aff5...0x1affb => true,
+ 0x1affd...0x1affe => true,
+ 0x1b000...0x1b122 => true,
+ 0x1b132 => true,
+ 0x1b150...0x1b152 => true,
+ 0x1b155 => true,
+ 0x1b164...0x1b167 => true,
+ 0x1b170...0x1b2fb => true,
+ 0x1bc00...0x1bc6a => true,
+ 0x1bc70...0x1bc7c => true,
+ 0x1bc80...0x1bc88 => true,
+ 0x1bc90...0x1bc99 => true,
+ 0x1bc9d...0x1bc9e => true,
+ 0x1cf00...0x1cf2d => true,
+ 0x1cf30...0x1cf46 => true,
+ 0x1d165...0x1d166 => true,
+ 0x1d167...0x1d169 => true,
+ 0x1d16d...0x1d172 => true,
+ 0x1d17b...0x1d182 => true,
+ 0x1d185...0x1d18b => true,
+ 0x1d1aa...0x1d1ad => true,
+ 0x1d242...0x1d244 => true,
+ 0x1d400...0x1d454 => true,
+ 0x1d456...0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d51e...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d552...0x1d6a5 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6dc...0x1d6fa => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d716...0x1d734 => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d750...0x1d76e => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d78a...0x1d7a8 => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c4...0x1d7cb => true,
+ 0x1d7ce...0x1d7ff => true,
+ 0x1da00...0x1da36 => true,
+ 0x1da3b...0x1da6c => true,
+ 0x1da75 => true,
+ 0x1da84 => true,
+ 0x1da9b...0x1da9f => true,
+ 0x1daa1...0x1daaf => true,
+ 0x1df00...0x1df09 => true,
+ 0x1df0a => true,
+ 0x1df0b...0x1df1e => true,
+ 0x1df25...0x1df2a => true,
+ 0x1e000...0x1e006 => true,
+ 0x1e008...0x1e018 => true,
+ 0x1e01b...0x1e021 => true,
+ 0x1e023...0x1e024 => true,
+ 0x1e026...0x1e02a => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e08f => true,
+ 0x1e100...0x1e12c => true,
+ 0x1e130...0x1e136 => true,
+ 0x1e137...0x1e13d => true,
+ 0x1e140...0x1e149 => true,
+ 0x1e14e => true,
+ 0x1e290...0x1e2ad => true,
+ 0x1e2ae => true,
+ 0x1e2c0...0x1e2eb => true,
+ 0x1e2ec...0x1e2ef => true,
+ 0x1e2f0...0x1e2f9 => true,
+ 0x1e4d0...0x1e4ea => true,
+ 0x1e4eb => true,
+ 0x1e4ec...0x1e4ef => true,
+ 0x1e4f0...0x1e4f9 => true,
+ 0x1e7e0...0x1e7e6 => true,
+ 0x1e7e8...0x1e7eb => true,
+ 0x1e7ed...0x1e7ee => true,
+ 0x1e7f0...0x1e7fe => true,
+ 0x1e800...0x1e8c4 => true,
+ 0x1e8d0...0x1e8d6 => true,
+ 0x1e900...0x1e943 => true,
+ 0x1e944...0x1e94a => true,
+ 0x1e94b => true,
+ 0x1e950...0x1e959 => true,
+ 0x1ee00...0x1ee03 => true,
+ 0x1ee05...0x1ee1f => true,
+ 0x1ee21...0x1ee22 => true,
+ 0x1ee24 => true,
+ 0x1ee27 => true,
+ 0x1ee29...0x1ee32 => true,
+ 0x1ee34...0x1ee37 => true,
+ 0x1ee39 => true,
+ 0x1ee3b => true,
+ 0x1ee42 => true,
+ 0x1ee47 => true,
+ 0x1ee49 => true,
+ 0x1ee4b => true,
+ 0x1ee4d...0x1ee4f => true,
+ 0x1ee51...0x1ee52 => true,
+ 0x1ee54 => true,
+ 0x1ee57 => true,
+ 0x1ee59 => true,
+ 0x1ee5b => true,
+ 0x1ee5d => true,
+ 0x1ee5f => true,
+ 0x1ee61...0x1ee62 => true,
+ 0x1ee64 => true,
+ 0x1ee67...0x1ee6a => true,
+ 0x1ee6c...0x1ee72 => true,
+ 0x1ee74...0x1ee77 => true,
+ 0x1ee79...0x1ee7c => true,
+ 0x1ee7e => true,
+ 0x1ee80...0x1ee89 => true,
+ 0x1ee8b...0x1ee9b => true,
+ 0x1eea1...0x1eea3 => true,
+ 0x1eea5...0x1eea9 => true,
+ 0x1eeab...0x1eebb => true,
+ 0x1fbf0...0x1fbf9 => true,
+ 0x20000...0x2a6df => true,
+ 0x2a700...0x2b739 => true,
+ 0x2b740...0x2b81d => true,
+ 0x2b820...0x2cea1 => true,
+ 0x2ceb0...0x2ebe0 => true,
+ 0x2f800...0x2fa1d => true,
+ 0x30000...0x3134a => true,
+ 0x31350...0x323af => true,
+ 0xe0100...0xe01ef => true,
+ else => false,
+ };
+}
+
+pub fn isXidStart(cp: u21) bool {
+ if (cp < 0x41 or cp > 0x323af) return false;
+
+ return switch (cp) {
+ 0x41...0x5a => true,
+ 0x61...0x7a => true,
+ 0xaa => true,
+ 0xb5 => true,
+ 0xba => true,
+ 0xc0...0xd6 => true,
+ 0xd8...0xf6 => true,
+ 0xf8...0x1ba => true,
+ 0x1bb => true,
+ 0x1bc...0x1bf => true,
+ 0x1c0...0x1c3 => true,
+ 0x1c4...0x293 => true,
+ 0x294 => true,
+ 0x295...0x2af => true,
+ 0x2b0...0x2c1 => true,
+ 0x2c6...0x2d1 => true,
+ 0x2e0...0x2e4 => true,
+ 0x2ec => true,
+ 0x2ee => true,
+ 0x370...0x373 => true,
+ 0x374 => true,
+ 0x376...0x377 => true,
+ 0x37b...0x37d => true,
+ 0x37f => true,
+ 0x386 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x3a1 => true,
+ 0x3a3...0x3f5 => true,
+ 0x3f7...0x481 => true,
+ 0x48a...0x52f => true,
+ 0x531...0x556 => true,
+ 0x559 => true,
+ 0x560...0x588 => true,
+ 0x5d0...0x5ea => true,
+ 0x5ef...0x5f2 => true,
+ 0x620...0x63f => true,
+ 0x640 => true,
+ 0x641...0x64a => true,
+ 0x66e...0x66f => true,
+ 0x671...0x6d3 => true,
+ 0x6d5 => true,
+ 0x6e5...0x6e6 => true,
+ 0x6ee...0x6ef => true,
+ 0x6fa...0x6fc => true,
+ 0x6ff => true,
+ 0x710 => true,
+ 0x712...0x72f => true,
+ 0x74d...0x7a5 => true,
+ 0x7b1 => true,
+ 0x7ca...0x7ea => true,
+ 0x7f4...0x7f5 => true,
+ 0x7fa => true,
+ 0x800...0x815 => true,
+ 0x81a => true,
+ 0x824 => true,
+ 0x828 => true,
+ 0x840...0x858 => true,
+ 0x860...0x86a => true,
+ 0x870...0x887 => true,
+ 0x889...0x88e => true,
+ 0x8a0...0x8c8 => true,
+ 0x8c9 => true,
+ 0x904...0x939 => true,
+ 0x93d => true,
+ 0x950 => true,
+ 0x958...0x961 => true,
+ 0x971 => true,
+ 0x972...0x980 => true,
+ 0x985...0x98c => true,
+ 0x98f...0x990 => true,
+ 0x993...0x9a8 => true,
+ 0x9aa...0x9b0 => true,
+ 0x9b2 => true,
+ 0x9b6...0x9b9 => true,
+ 0x9bd => true,
+ 0x9ce => true,
+ 0x9dc...0x9dd => true,
+ 0x9df...0x9e1 => true,
+ 0x9f0...0x9f1 => true,
+ 0x9fc => true,
+ 0xa05...0xa0a => true,
+ 0xa0f...0xa10 => true,
+ 0xa13...0xa28 => true,
+ 0xa2a...0xa30 => true,
+ 0xa32...0xa33 => true,
+ 0xa35...0xa36 => true,
+ 0xa38...0xa39 => true,
+ 0xa59...0xa5c => true,
+ 0xa5e => true,
+ 0xa72...0xa74 => true,
+ 0xa85...0xa8d => true,
+ 0xa8f...0xa91 => true,
+ 0xa93...0xaa8 => true,
+ 0xaaa...0xab0 => true,
+ 0xab2...0xab3 => true,
+ 0xab5...0xab9 => true,
+ 0xabd => true,
+ 0xad0 => true,
+ 0xae0...0xae1 => true,
+ 0xaf9 => true,
+ 0xb05...0xb0c => true,
+ 0xb0f...0xb10 => true,
+ 0xb13...0xb28 => true,
+ 0xb2a...0xb30 => true,
+ 0xb32...0xb33 => true,
+ 0xb35...0xb39 => true,
+ 0xb3d => true,
+ 0xb5c...0xb5d => true,
+ 0xb5f...0xb61 => true,
+ 0xb71 => true,
+ 0xb83 => true,
+ 0xb85...0xb8a => true,
+ 0xb8e...0xb90 => true,
+ 0xb92...0xb95 => true,
+ 0xb99...0xb9a => true,
+ 0xb9c => true,
+ 0xb9e...0xb9f => true,
+ 0xba3...0xba4 => true,
+ 0xba8...0xbaa => true,
+ 0xbae...0xbb9 => true,
+ 0xbd0 => true,
+ 0xc05...0xc0c => true,
+ 0xc0e...0xc10 => true,
+ 0xc12...0xc28 => true,
+ 0xc2a...0xc39 => true,
+ 0xc3d => true,
+ 0xc58...0xc5a => true,
+ 0xc5d => true,
+ 0xc60...0xc61 => true,
+ 0xc80 => true,
+ 0xc85...0xc8c => true,
+ 0xc8e...0xc90 => true,
+ 0xc92...0xca8 => true,
+ 0xcaa...0xcb3 => true,
+ 0xcb5...0xcb9 => true,
+ 0xcbd => true,
+ 0xcdd...0xcde => true,
+ 0xce0...0xce1 => true,
+ 0xcf1...0xcf2 => true,
+ 0xd04...0xd0c => true,
+ 0xd0e...0xd10 => true,
+ 0xd12...0xd3a => true,
+ 0xd3d => true,
+ 0xd4e => true,
+ 0xd54...0xd56 => true,
+ 0xd5f...0xd61 => true,
+ 0xd7a...0xd7f => true,
+ 0xd85...0xd96 => true,
+ 0xd9a...0xdb1 => true,
+ 0xdb3...0xdbb => true,
+ 0xdbd => true,
+ 0xdc0...0xdc6 => true,
+ 0xe01...0xe30 => true,
+ 0xe32 => true,
+ 0xe40...0xe45 => true,
+ 0xe46 => true,
+ 0xe81...0xe82 => true,
+ 0xe84 => true,
+ 0xe86...0xe8a => true,
+ 0xe8c...0xea3 => true,
+ 0xea5 => true,
+ 0xea7...0xeb0 => true,
+ 0xeb2 => true,
+ 0xebd => true,
+ 0xec0...0xec4 => true,
+ 0xec6 => true,
+ 0xedc...0xedf => true,
+ 0xf00 => true,
+ 0xf40...0xf47 => true,
+ 0xf49...0xf6c => true,
+ 0xf88...0xf8c => true,
+ 0x1000...0x102a => true,
+ 0x103f => true,
+ 0x1050...0x1055 => true,
+ 0x105a...0x105d => true,
+ 0x1061 => true,
+ 0x1065...0x1066 => true,
+ 0x106e...0x1070 => true,
+ 0x1075...0x1081 => true,
+ 0x108e => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x10d0...0x10fa => true,
+ 0x10fc => true,
+ 0x10fd...0x10ff => true,
+ 0x1100...0x1248 => true,
+ 0x124a...0x124d => true,
+ 0x1250...0x1256 => true,
+ 0x1258 => true,
+ 0x125a...0x125d => true,
+ 0x1260...0x1288 => true,
+ 0x128a...0x128d => true,
+ 0x1290...0x12b0 => true,
+ 0x12b2...0x12b5 => true,
+ 0x12b8...0x12be => true,
+ 0x12c0 => true,
+ 0x12c2...0x12c5 => true,
+ 0x12c8...0x12d6 => true,
+ 0x12d8...0x1310 => true,
+ 0x1312...0x1315 => true,
+ 0x1318...0x135a => true,
+ 0x1380...0x138f => true,
+ 0x13a0...0x13f5 => true,
+ 0x13f8...0x13fd => true,
+ 0x1401...0x166c => true,
+ 0x166f...0x167f => true,
+ 0x1681...0x169a => true,
+ 0x16a0...0x16ea => true,
+ 0x16ee...0x16f0 => true,
+ 0x16f1...0x16f8 => true,
+ 0x1700...0x1711 => true,
+ 0x171f...0x1731 => true,
+ 0x1740...0x1751 => true,
+ 0x1760...0x176c => true,
+ 0x176e...0x1770 => true,
+ 0x1780...0x17b3 => true,
+ 0x17d7 => true,
+ 0x17dc => true,
+ 0x1820...0x1842 => true,
+ 0x1843 => true,
+ 0x1844...0x1878 => true,
+ 0x1880...0x1884 => true,
+ 0x1885...0x1886 => true,
+ 0x1887...0x18a8 => true,
+ 0x18aa => true,
+ 0x18b0...0x18f5 => true,
+ 0x1900...0x191e => true,
+ 0x1950...0x196d => true,
+ 0x1970...0x1974 => true,
+ 0x1980...0x19ab => true,
+ 0x19b0...0x19c9 => true,
+ 0x1a00...0x1a16 => true,
+ 0x1a20...0x1a54 => true,
+ 0x1aa7 => true,
+ 0x1b05...0x1b33 => true,
+ 0x1b45...0x1b4c => true,
+ 0x1b83...0x1ba0 => true,
+ 0x1bae...0x1baf => true,
+ 0x1bba...0x1be5 => true,
+ 0x1c00...0x1c23 => true,
+ 0x1c4d...0x1c4f => true,
+ 0x1c5a...0x1c77 => true,
+ 0x1c78...0x1c7d => true,
+ 0x1c80...0x1c88 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1ce9...0x1cec => true,
+ 0x1cee...0x1cf3 => true,
+ 0x1cf5...0x1cf6 => true,
+ 0x1cfa => true,
+ 0x1d00...0x1d2b => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d6b...0x1d77 => true,
+ 0x1d78 => true,
+ 0x1d79...0x1d9a => true,
+ 0x1d9b...0x1dbf => true,
+ 0x1e00...0x1f15 => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f20...0x1f45 => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f...0x1f7d => true,
+ 0x1f80...0x1fb4 => true,
+ 0x1fb6...0x1fbc => true,
+ 0x1fbe => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fcc => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fdb => true,
+ 0x1fe0...0x1fec => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ffc => true,
+ 0x2071 => true,
+ 0x207f => true,
+ 0x2090...0x209c => true,
+ 0x2102 => true,
+ 0x2107 => true,
+ 0x210a...0x2113 => true,
+ 0x2115 => true,
+ 0x2118 => true,
+ 0x2119...0x211d => true,
+ 0x2124 => true,
+ 0x2126 => true,
+ 0x2128 => true,
+ 0x212a...0x212d => true,
+ 0x212e => true,
+ 0x212f...0x2134 => true,
+ 0x2135...0x2138 => true,
+ 0x2139 => true,
+ 0x213c...0x213f => true,
+ 0x2145...0x2149 => true,
+ 0x214e => true,
+ 0x2160...0x2182 => true,
+ 0x2183...0x2184 => true,
+ 0x2185...0x2188 => true,
+ 0x2c00...0x2c7b => true,
+ 0x2c7c...0x2c7d => true,
+ 0x2c7e...0x2ce4 => true,
+ 0x2ceb...0x2cee => true,
+ 0x2cf2...0x2cf3 => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0x2d30...0x2d67 => true,
+ 0x2d6f => true,
+ 0x2d80...0x2d96 => true,
+ 0x2da0...0x2da6 => true,
+ 0x2da8...0x2dae => true,
+ 0x2db0...0x2db6 => true,
+ 0x2db8...0x2dbe => true,
+ 0x2dc0...0x2dc6 => true,
+ 0x2dc8...0x2dce => true,
+ 0x2dd0...0x2dd6 => true,
+ 0x2dd8...0x2dde => true,
+ 0x3005 => true,
+ 0x3006 => true,
+ 0x3007 => true,
+ 0x3021...0x3029 => true,
+ 0x3031...0x3035 => true,
+ 0x3038...0x303a => true,
+ 0x303b => true,
+ 0x303c => true,
+ 0x3041...0x3096 => true,
+ 0x309d...0x309e => true,
+ 0x309f => true,
+ 0x30a1...0x30fa => true,
+ 0x30fc...0x30fe => true,
+ 0x30ff => true,
+ 0x3105...0x312f => true,
+ 0x3131...0x318e => true,
+ 0x31a0...0x31bf => true,
+ 0x31f0...0x31ff => true,
+ 0x3400...0x4dbf => true,
+ 0x4e00...0xa014 => true,
+ 0xa015 => true,
+ 0xa016...0xa48c => true,
+ 0xa4d0...0xa4f7 => true,
+ 0xa4f8...0xa4fd => true,
+ 0xa500...0xa60b => true,
+ 0xa60c => true,
+ 0xa610...0xa61f => true,
+ 0xa62a...0xa62b => true,
+ 0xa640...0xa66d => true,
+ 0xa66e => true,
+ 0xa67f => true,
+ 0xa680...0xa69b => true,
+ 0xa69c...0xa69d => true,
+ 0xa6a0...0xa6e5 => true,
+ 0xa6e6...0xa6ef => true,
+ 0xa717...0xa71f => true,
+ 0xa722...0xa76f => true,
+ 0xa770 => true,
+ 0xa771...0xa787 => true,
+ 0xa788 => true,
+ 0xa78b...0xa78e => true,
+ 0xa78f => true,
+ 0xa790...0xa7ca => true,
+ 0xa7d0...0xa7d1 => true,
+ 0xa7d3 => true,
+ 0xa7d5...0xa7d9 => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f5...0xa7f6 => true,
+ 0xa7f7 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa7fa => true,
+ 0xa7fb...0xa801 => true,
+ 0xa803...0xa805 => true,
+ 0xa807...0xa80a => true,
+ 0xa80c...0xa822 => true,
+ 0xa840...0xa873 => true,
+ 0xa882...0xa8b3 => true,
+ 0xa8f2...0xa8f7 => true,
+ 0xa8fb => true,
+ 0xa8fd...0xa8fe => true,
+ 0xa90a...0xa925 => true,
+ 0xa930...0xa946 => true,
+ 0xa960...0xa97c => true,
+ 0xa984...0xa9b2 => true,
+ 0xa9cf => true,
+ 0xa9e0...0xa9e4 => true,
+ 0xa9e6 => true,
+ 0xa9e7...0xa9ef => true,
+ 0xa9fa...0xa9fe => true,
+ 0xaa00...0xaa28 => true,
+ 0xaa40...0xaa42 => true,
+ 0xaa44...0xaa4b => true,
+ 0xaa60...0xaa6f => true,
+ 0xaa70 => true,
+ 0xaa71...0xaa76 => true,
+ 0xaa7a => true,
+ 0xaa7e...0xaaaf => true,
+ 0xaab1 => true,
+ 0xaab5...0xaab6 => true,
+ 0xaab9...0xaabd => true,
+ 0xaac0 => true,
+ 0xaac2 => true,
+ 0xaadb...0xaadc => true,
+ 0xaadd => true,
+ 0xaae0...0xaaea => true,
+ 0xaaf2 => true,
+ 0xaaf3...0xaaf4 => true,
+ 0xab01...0xab06 => true,
+ 0xab09...0xab0e => true,
+ 0xab11...0xab16 => true,
+ 0xab20...0xab26 => true,
+ 0xab28...0xab2e => true,
+ 0xab30...0xab5a => true,
+ 0xab5c...0xab5f => true,
+ 0xab60...0xab68 => true,
+ 0xab69 => true,
+ 0xab70...0xabbf => true,
+ 0xabc0...0xabe2 => true,
+ 0xac00...0xd7a3 => true,
+ 0xd7b0...0xd7c6 => true,
+ 0xd7cb...0xd7fb => true,
+ 0xf900...0xfa6d => true,
+ 0xfa70...0xfad9 => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xfb1d => true,
+ 0xfb1f...0xfb28 => true,
+ 0xfb2a...0xfb36 => true,
+ 0xfb38...0xfb3c => true,
+ 0xfb3e => true,
+ 0xfb40...0xfb41 => true,
+ 0xfb43...0xfb44 => true,
+ 0xfb46...0xfbb1 => true,
+ 0xfbd3...0xfc5d => true,
+ 0xfc64...0xfd3d => true,
+ 0xfd50...0xfd8f => true,
+ 0xfd92...0xfdc7 => true,
+ 0xfdf0...0xfdf9 => true,
+ 0xfe71 => true,
+ 0xfe73 => true,
+ 0xfe77 => true,
+ 0xfe79 => true,
+ 0xfe7b => true,
+ 0xfe7d => true,
+ 0xfe7f...0xfefc => true,
+ 0xff21...0xff3a => true,
+ 0xff41...0xff5a => true,
+ 0xff66...0xff6f => true,
+ 0xff70 => true,
+ 0xff71...0xff9d => true,
+ 0xffa0...0xffbe => true,
+ 0xffc2...0xffc7 => true,
+ 0xffca...0xffcf => true,
+ 0xffd2...0xffd7 => true,
+ 0xffda...0xffdc => true,
+ 0x10000...0x1000b => true,
+ 0x1000d...0x10026 => true,
+ 0x10028...0x1003a => true,
+ 0x1003c...0x1003d => true,
+ 0x1003f...0x1004d => true,
+ 0x10050...0x1005d => true,
+ 0x10080...0x100fa => true,
+ 0x10140...0x10174 => true,
+ 0x10280...0x1029c => true,
+ 0x102a0...0x102d0 => true,
+ 0x10300...0x1031f => true,
+ 0x1032d...0x10340 => true,
+ 0x10341 => true,
+ 0x10342...0x10349 => true,
+ 0x1034a => true,
+ 0x10350...0x10375 => true,
+ 0x10380...0x1039d => true,
+ 0x103a0...0x103c3 => true,
+ 0x103c8...0x103cf => true,
+ 0x103d1...0x103d5 => true,
+ 0x10400...0x1044f => true,
+ 0x10450...0x1049d => true,
+ 0x104b0...0x104d3 => true,
+ 0x104d8...0x104fb => true,
+ 0x10500...0x10527 => true,
+ 0x10530...0x10563 => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10600...0x10736 => true,
+ 0x10740...0x10755 => true,
+ 0x10760...0x10767 => true,
+ 0x10780...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x10800...0x10805 => true,
+ 0x10808 => true,
+ 0x1080a...0x10835 => true,
+ 0x10837...0x10838 => true,
+ 0x1083c => true,
+ 0x1083f...0x10855 => true,
+ 0x10860...0x10876 => true,
+ 0x10880...0x1089e => true,
+ 0x108e0...0x108f2 => true,
+ 0x108f4...0x108f5 => true,
+ 0x10900...0x10915 => true,
+ 0x10920...0x10939 => true,
+ 0x10980...0x109b7 => true,
+ 0x109be...0x109bf => true,
+ 0x10a00 => true,
+ 0x10a10...0x10a13 => true,
+ 0x10a15...0x10a17 => true,
+ 0x10a19...0x10a35 => true,
+ 0x10a60...0x10a7c => true,
+ 0x10a80...0x10a9c => true,
+ 0x10ac0...0x10ac7 => true,
+ 0x10ac9...0x10ae4 => true,
+ 0x10b00...0x10b35 => true,
+ 0x10b40...0x10b55 => true,
+ 0x10b60...0x10b72 => true,
+ 0x10b80...0x10b91 => true,
+ 0x10c00...0x10c48 => true,
+ 0x10c80...0x10cb2 => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x10d00...0x10d23 => true,
+ 0x10e80...0x10ea9 => true,
+ 0x10eb0...0x10eb1 => true,
+ 0x10f00...0x10f1c => true,
+ 0x10f27 => true,
+ 0x10f30...0x10f45 => true,
+ 0x10f70...0x10f81 => true,
+ 0x10fb0...0x10fc4 => true,
+ 0x10fe0...0x10ff6 => true,
+ 0x11003...0x11037 => true,
+ 0x11071...0x11072 => true,
+ 0x11075 => true,
+ 0x11083...0x110af => true,
+ 0x110d0...0x110e8 => true,
+ 0x11103...0x11126 => true,
+ 0x11144 => true,
+ 0x11147 => true,
+ 0x11150...0x11172 => true,
+ 0x11176 => true,
+ 0x11183...0x111b2 => true,
+ 0x111c1...0x111c4 => true,
+ 0x111da => true,
+ 0x111dc => true,
+ 0x11200...0x11211 => true,
+ 0x11213...0x1122b => true,
+ 0x1123f...0x11240 => true,
+ 0x11280...0x11286 => true,
+ 0x11288 => true,
+ 0x1128a...0x1128d => true,
+ 0x1128f...0x1129d => true,
+ 0x1129f...0x112a8 => true,
+ 0x112b0...0x112de => true,
+ 0x11305...0x1130c => true,
+ 0x1130f...0x11310 => true,
+ 0x11313...0x11328 => true,
+ 0x1132a...0x11330 => true,
+ 0x11332...0x11333 => true,
+ 0x11335...0x11339 => true,
+ 0x1133d => true,
+ 0x11350 => true,
+ 0x1135d...0x11361 => true,
+ 0x11400...0x11434 => true,
+ 0x11447...0x1144a => true,
+ 0x1145f...0x11461 => true,
+ 0x11480...0x114af => true,
+ 0x114c4...0x114c5 => true,
+ 0x114c7 => true,
+ 0x11580...0x115ae => true,
+ 0x115d8...0x115db => true,
+ 0x11600...0x1162f => true,
+ 0x11644 => true,
+ 0x11680...0x116aa => true,
+ 0x116b8 => true,
+ 0x11700...0x1171a => true,
+ 0x11740...0x11746 => true,
+ 0x11800...0x1182b => true,
+ 0x118a0...0x118df => true,
+ 0x118ff...0x11906 => true,
+ 0x11909 => true,
+ 0x1190c...0x11913 => true,
+ 0x11915...0x11916 => true,
+ 0x11918...0x1192f => true,
+ 0x1193f => true,
+ 0x11941 => true,
+ 0x119a0...0x119a7 => true,
+ 0x119aa...0x119d0 => true,
+ 0x119e1 => true,
+ 0x119e3 => true,
+ 0x11a00 => true,
+ 0x11a0b...0x11a32 => true,
+ 0x11a3a => true,
+ 0x11a50 => true,
+ 0x11a5c...0x11a89 => true,
+ 0x11a9d => true,
+ 0x11ab0...0x11af8 => true,
+ 0x11c00...0x11c08 => true,
+ 0x11c0a...0x11c2e => true,
+ 0x11c40 => true,
+ 0x11c72...0x11c8f => true,
+ 0x11d00...0x11d06 => true,
+ 0x11d08...0x11d09 => true,
+ 0x11d0b...0x11d30 => true,
+ 0x11d46 => true,
+ 0x11d60...0x11d65 => true,
+ 0x11d67...0x11d68 => true,
+ 0x11d6a...0x11d89 => true,
+ 0x11d98 => true,
+ 0x11ee0...0x11ef2 => true,
+ 0x11f02 => true,
+ 0x11f04...0x11f10 => true,
+ 0x11f12...0x11f33 => true,
+ 0x11fb0 => true,
+ 0x12000...0x12399 => true,
+ 0x12400...0x1246e => true,
+ 0x12480...0x12543 => true,
+ 0x12f90...0x12ff0 => true,
+ 0x13000...0x1342f => true,
+ 0x13441...0x13446 => true,
+ 0x14400...0x14646 => true,
+ 0x16800...0x16a38 => true,
+ 0x16a40...0x16a5e => true,
+ 0x16a70...0x16abe => true,
+ 0x16ad0...0x16aed => true,
+ 0x16b00...0x16b2f => true,
+ 0x16b40...0x16b43 => true,
+ 0x16b63...0x16b77 => true,
+ 0x16b7d...0x16b8f => true,
+ 0x16e40...0x16e7f => true,
+ 0x16f00...0x16f4a => true,
+ 0x16f50 => true,
+ 0x16f93...0x16f9f => true,
+ 0x16fe0...0x16fe1 => true,
+ 0x16fe3 => true,
+ 0x17000...0x187f7 => true,
+ 0x18800...0x18cd5 => true,
+ 0x18d00...0x18d08 => true,
+ 0x1aff0...0x1aff3 => true,
+ 0x1aff5...0x1affb => true,
+ 0x1affd...0x1affe => true,
+ 0x1b000...0x1b122 => true,
+ 0x1b132 => true,
+ 0x1b150...0x1b152 => true,
+ 0x1b155 => true,
+ 0x1b164...0x1b167 => true,
+ 0x1b170...0x1b2fb => true,
+ 0x1bc00...0x1bc6a => true,
+ 0x1bc70...0x1bc7c => true,
+ 0x1bc80...0x1bc88 => true,
+ 0x1bc90...0x1bc99 => true,
+ 0x1d400...0x1d454 => true,
+ 0x1d456...0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d51e...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d552...0x1d6a5 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6dc...0x1d6fa => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d716...0x1d734 => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d750...0x1d76e => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d78a...0x1d7a8 => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c4...0x1d7cb => true,
+ 0x1df00...0x1df09 => true,
+ 0x1df0a => true,
+ 0x1df0b...0x1df1e => true,
+ 0x1df25...0x1df2a => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e100...0x1e12c => true,
+ 0x1e137...0x1e13d => true,
+ 0x1e14e => true,
+ 0x1e290...0x1e2ad => true,
+ 0x1e2c0...0x1e2eb => true,
+ 0x1e4d0...0x1e4ea => true,
+ 0x1e4eb => true,
+ 0x1e7e0...0x1e7e6 => true,
+ 0x1e7e8...0x1e7eb => true,
+ 0x1e7ed...0x1e7ee => true,
+ 0x1e7f0...0x1e7fe => true,
+ 0x1e800...0x1e8c4 => true,
+ 0x1e900...0x1e943 => true,
+ 0x1e94b => true,
+ 0x1ee00...0x1ee03 => true,
+ 0x1ee05...0x1ee1f => true,
+ 0x1ee21...0x1ee22 => true,
+ 0x1ee24 => true,
+ 0x1ee27 => true,
+ 0x1ee29...0x1ee32 => true,
+ 0x1ee34...0x1ee37 => true,
+ 0x1ee39 => true,
+ 0x1ee3b => true,
+ 0x1ee42 => true,
+ 0x1ee47 => true,
+ 0x1ee49 => true,
+ 0x1ee4b => true,
+ 0x1ee4d...0x1ee4f => true,
+ 0x1ee51...0x1ee52 => true,
+ 0x1ee54 => true,
+ 0x1ee57 => true,
+ 0x1ee59 => true,
+ 0x1ee5b => true,
+ 0x1ee5d => true,
+ 0x1ee5f => true,
+ 0x1ee61...0x1ee62 => true,
+ 0x1ee64 => true,
+ 0x1ee67...0x1ee6a => true,
+ 0x1ee6c...0x1ee72 => true,
+ 0x1ee74...0x1ee77 => true,
+ 0x1ee79...0x1ee7c => true,
+ 0x1ee7e => true,
+ 0x1ee80...0x1ee89 => true,
+ 0x1ee8b...0x1ee9b => true,
+ 0x1eea1...0x1eea3 => true,
+ 0x1eea5...0x1eea9 => true,
+ 0x1eeab...0x1eebb => true,
+ 0x20000...0x2a6df => true,
+ 0x2a700...0x2b739 => true,
+ 0x2b740...0x2b81d => true,
+ 0x2b820...0x2cea1 => true,
+ 0x2ceb0...0x2ebe0 => true,
+ 0x2f800...0x2fa1d => true,
+ 0x30000...0x3134a => true,
+ 0x31350...0x323af => true,
+ else => false,
+ };
+}
+
+pub fn isXidContinue(cp: u21) bool {
+ if (cp < 0x30 or cp > 0xe01ef) return false;
+
+ return switch (cp) {
+ 0x30...0x39 => true,
+ 0x41...0x5a => true,
+ 0x5f => true,
+ 0x61...0x7a => true,
+ 0xaa => true,
+ 0xb5 => true,
+ 0xb7 => true,
+ 0xba => true,
+ 0xc0...0xd6 => true,
+ 0xd8...0xf6 => true,
+ 0xf8...0x1ba => true,
+ 0x1bb => true,
+ 0x1bc...0x1bf => true,
+ 0x1c0...0x1c3 => true,
+ 0x1c4...0x293 => true,
+ 0x294 => true,
+ 0x295...0x2af => true,
+ 0x2b0...0x2c1 => true,
+ 0x2c6...0x2d1 => true,
+ 0x2e0...0x2e4 => true,
+ 0x2ec => true,
+ 0x2ee => true,
+ 0x300...0x36f => true,
+ 0x370...0x373 => true,
+ 0x374 => true,
+ 0x376...0x377 => true,
+ 0x37b...0x37d => true,
+ 0x37f => true,
+ 0x386 => true,
+ 0x387 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x3a1 => true,
+ 0x3a3...0x3f5 => true,
+ 0x3f7...0x481 => true,
+ 0x483...0x487 => true,
+ 0x48a...0x52f => true,
+ 0x531...0x556 => true,
+ 0x559 => true,
+ 0x560...0x588 => true,
+ 0x591...0x5bd => true,
+ 0x5bf => true,
+ 0x5c1...0x5c2 => true,
+ 0x5c4...0x5c5 => true,
+ 0x5c7 => true,
+ 0x5d0...0x5ea => true,
+ 0x5ef...0x5f2 => true,
+ 0x610...0x61a => true,
+ 0x620...0x63f => true,
+ 0x640 => true,
+ 0x641...0x64a => true,
+ 0x64b...0x65f => true,
+ 0x660...0x669 => true,
+ 0x66e...0x66f => true,
+ 0x670 => true,
+ 0x671...0x6d3 => true,
+ 0x6d5 => true,
+ 0x6d6...0x6dc => true,
+ 0x6df...0x6e4 => true,
+ 0x6e5...0x6e6 => true,
+ 0x6e7...0x6e8 => true,
+ 0x6ea...0x6ed => true,
+ 0x6ee...0x6ef => true,
+ 0x6f0...0x6f9 => true,
+ 0x6fa...0x6fc => true,
+ 0x6ff => true,
+ 0x710 => true,
+ 0x711 => true,
+ 0x712...0x72f => true,
+ 0x730...0x74a => true,
+ 0x74d...0x7a5 => true,
+ 0x7a6...0x7b0 => true,
+ 0x7b1 => true,
+ 0x7c0...0x7c9 => true,
+ 0x7ca...0x7ea => true,
+ 0x7eb...0x7f3 => true,
+ 0x7f4...0x7f5 => true,
+ 0x7fa => true,
+ 0x7fd => true,
+ 0x800...0x815 => true,
+ 0x816...0x819 => true,
+ 0x81a => true,
+ 0x81b...0x823 => true,
+ 0x824 => true,
+ 0x825...0x827 => true,
+ 0x828 => true,
+ 0x829...0x82d => true,
+ 0x840...0x858 => true,
+ 0x859...0x85b => true,
+ 0x860...0x86a => true,
+ 0x870...0x887 => true,
+ 0x889...0x88e => true,
+ 0x898...0x89f => true,
+ 0x8a0...0x8c8 => true,
+ 0x8c9 => true,
+ 0x8ca...0x8e1 => true,
+ 0x8e3...0x902 => true,
+ 0x903 => true,
+ 0x904...0x939 => true,
+ 0x93a => true,
+ 0x93b => true,
+ 0x93c => true,
+ 0x93d => true,
+ 0x93e...0x940 => true,
+ 0x941...0x948 => true,
+ 0x949...0x94c => true,
+ 0x94d => true,
+ 0x94e...0x94f => true,
+ 0x950 => true,
+ 0x951...0x957 => true,
+ 0x958...0x961 => true,
+ 0x962...0x963 => true,
+ 0x966...0x96f => true,
+ 0x971 => true,
+ 0x972...0x980 => true,
+ 0x981 => true,
+ 0x982...0x983 => true,
+ 0x985...0x98c => true,
+ 0x98f...0x990 => true,
+ 0x993...0x9a8 => true,
+ 0x9aa...0x9b0 => true,
+ 0x9b2 => true,
+ 0x9b6...0x9b9 => true,
+ 0x9bc => true,
+ 0x9bd => true,
+ 0x9be...0x9c0 => true,
+ 0x9c1...0x9c4 => true,
+ 0x9c7...0x9c8 => true,
+ 0x9cb...0x9cc => true,
+ 0x9cd => true,
+ 0x9ce => true,
+ 0x9d7 => true,
+ 0x9dc...0x9dd => true,
+ 0x9df...0x9e1 => true,
+ 0x9e2...0x9e3 => true,
+ 0x9e6...0x9ef => true,
+ 0x9f0...0x9f1 => true,
+ 0x9fc => true,
+ 0x9fe => true,
+ 0xa01...0xa02 => true,
+ 0xa03 => true,
+ 0xa05...0xa0a => true,
+ 0xa0f...0xa10 => true,
+ 0xa13...0xa28 => true,
+ 0xa2a...0xa30 => true,
+ 0xa32...0xa33 => true,
+ 0xa35...0xa36 => true,
+ 0xa38...0xa39 => true,
+ 0xa3c => true,
+ 0xa3e...0xa40 => true,
+ 0xa41...0xa42 => true,
+ 0xa47...0xa48 => true,
+ 0xa4b...0xa4d => true,
+ 0xa51 => true,
+ 0xa59...0xa5c => true,
+ 0xa5e => true,
+ 0xa66...0xa6f => true,
+ 0xa70...0xa71 => true,
+ 0xa72...0xa74 => true,
+ 0xa75 => true,
+ 0xa81...0xa82 => true,
+ 0xa83 => true,
+ 0xa85...0xa8d => true,
+ 0xa8f...0xa91 => true,
+ 0xa93...0xaa8 => true,
+ 0xaaa...0xab0 => true,
+ 0xab2...0xab3 => true,
+ 0xab5...0xab9 => true,
+ 0xabc => true,
+ 0xabd => true,
+ 0xabe...0xac0 => true,
+ 0xac1...0xac5 => true,
+ 0xac7...0xac8 => true,
+ 0xac9 => true,
+ 0xacb...0xacc => true,
+ 0xacd => true,
+ 0xad0 => true,
+ 0xae0...0xae1 => true,
+ 0xae2...0xae3 => true,
+ 0xae6...0xaef => true,
+ 0xaf9 => true,
+ 0xafa...0xaff => true,
+ 0xb01 => true,
+ 0xb02...0xb03 => true,
+ 0xb05...0xb0c => true,
+ 0xb0f...0xb10 => true,
+ 0xb13...0xb28 => true,
+ 0xb2a...0xb30 => true,
+ 0xb32...0xb33 => true,
+ 0xb35...0xb39 => true,
+ 0xb3c => true,
+ 0xb3d => true,
+ 0xb3e => true,
+ 0xb3f => true,
+ 0xb40 => true,
+ 0xb41...0xb44 => true,
+ 0xb47...0xb48 => true,
+ 0xb4b...0xb4c => true,
+ 0xb4d => true,
+ 0xb55...0xb56 => true,
+ 0xb57 => true,
+ 0xb5c...0xb5d => true,
+ 0xb5f...0xb61 => true,
+ 0xb62...0xb63 => true,
+ 0xb66...0xb6f => true,
+ 0xb71 => true,
+ 0xb82 => true,
+ 0xb83 => true,
+ 0xb85...0xb8a => true,
+ 0xb8e...0xb90 => true,
+ 0xb92...0xb95 => true,
+ 0xb99...0xb9a => true,
+ 0xb9c => true,
+ 0xb9e...0xb9f => true,
+ 0xba3...0xba4 => true,
+ 0xba8...0xbaa => true,
+ 0xbae...0xbb9 => true,
+ 0xbbe...0xbbf => true,
+ 0xbc0 => true,
+ 0xbc1...0xbc2 => true,
+ 0xbc6...0xbc8 => true,
+ 0xbca...0xbcc => true,
+ 0xbcd => true,
+ 0xbd0 => true,
+ 0xbd7 => true,
+ 0xbe6...0xbef => true,
+ 0xc00 => true,
+ 0xc01...0xc03 => true,
+ 0xc04 => true,
+ 0xc05...0xc0c => true,
+ 0xc0e...0xc10 => true,
+ 0xc12...0xc28 => true,
+ 0xc2a...0xc39 => true,
+ 0xc3c => true,
+ 0xc3d => true,
+ 0xc3e...0xc40 => true,
+ 0xc41...0xc44 => true,
+ 0xc46...0xc48 => true,
+ 0xc4a...0xc4d => true,
+ 0xc55...0xc56 => true,
+ 0xc58...0xc5a => true,
+ 0xc5d => true,
+ 0xc60...0xc61 => true,
+ 0xc62...0xc63 => true,
+ 0xc66...0xc6f => true,
+ 0xc80 => true,
+ 0xc81 => true,
+ 0xc82...0xc83 => true,
+ 0xc85...0xc8c => true,
+ 0xc8e...0xc90 => true,
+ 0xc92...0xca8 => true,
+ 0xcaa...0xcb3 => true,
+ 0xcb5...0xcb9 => true,
+ 0xcbc => true,
+ 0xcbd => true,
+ 0xcbe => true,
+ 0xcbf => true,
+ 0xcc0...0xcc4 => true,
+ 0xcc6 => true,
+ 0xcc7...0xcc8 => true,
+ 0xcca...0xccb => true,
+ 0xccc...0xccd => true,
+ 0xcd5...0xcd6 => true,
+ 0xcdd...0xcde => true,
+ 0xce0...0xce1 => true,
+ 0xce2...0xce3 => true,
+ 0xce6...0xcef => true,
+ 0xcf1...0xcf2 => true,
+ 0xcf3 => true,
+ 0xd00...0xd01 => true,
+ 0xd02...0xd03 => true,
+ 0xd04...0xd0c => true,
+ 0xd0e...0xd10 => true,
+ 0xd12...0xd3a => true,
+ 0xd3b...0xd3c => true,
+ 0xd3d => true,
+ 0xd3e...0xd40 => true,
+ 0xd41...0xd44 => true,
+ 0xd46...0xd48 => true,
+ 0xd4a...0xd4c => true,
+ 0xd4d => true,
+ 0xd4e => true,
+ 0xd54...0xd56 => true,
+ 0xd57 => true,
+ 0xd5f...0xd61 => true,
+ 0xd62...0xd63 => true,
+ 0xd66...0xd6f => true,
+ 0xd7a...0xd7f => true,
+ 0xd81 => true,
+ 0xd82...0xd83 => true,
+ 0xd85...0xd96 => true,
+ 0xd9a...0xdb1 => true,
+ 0xdb3...0xdbb => true,
+ 0xdbd => true,
+ 0xdc0...0xdc6 => true,
+ 0xdca => true,
+ 0xdcf...0xdd1 => true,
+ 0xdd2...0xdd4 => true,
+ 0xdd6 => true,
+ 0xdd8...0xddf => true,
+ 0xde6...0xdef => true,
+ 0xdf2...0xdf3 => true,
+ 0xe01...0xe30 => true,
+ 0xe31 => true,
+ 0xe32...0xe33 => true,
+ 0xe34...0xe3a => true,
+ 0xe40...0xe45 => true,
+ 0xe46 => true,
+ 0xe47...0xe4e => true,
+ 0xe50...0xe59 => true,
+ 0xe81...0xe82 => true,
+ 0xe84 => true,
+ 0xe86...0xe8a => true,
+ 0xe8c...0xea3 => true,
+ 0xea5 => true,
+ 0xea7...0xeb0 => true,
+ 0xeb1 => true,
+ 0xeb2...0xeb3 => true,
+ 0xeb4...0xebc => true,
+ 0xebd => true,
+ 0xec0...0xec4 => true,
+ 0xec6 => true,
+ 0xec8...0xece => true,
+ 0xed0...0xed9 => true,
+ 0xedc...0xedf => true,
+ 0xf00 => true,
+ 0xf18...0xf19 => true,
+ 0xf20...0xf29 => true,
+ 0xf35 => true,
+ 0xf37 => true,
+ 0xf39 => true,
+ 0xf3e...0xf3f => true,
+ 0xf40...0xf47 => true,
+ 0xf49...0xf6c => true,
+ 0xf71...0xf7e => true,
+ 0xf7f => true,
+ 0xf80...0xf84 => true,
+ 0xf86...0xf87 => true,
+ 0xf88...0xf8c => true,
+ 0xf8d...0xf97 => true,
+ 0xf99...0xfbc => true,
+ 0xfc6 => true,
+ 0x1000...0x102a => true,
+ 0x102b...0x102c => true,
+ 0x102d...0x1030 => true,
+ 0x1031 => true,
+ 0x1032...0x1037 => true,
+ 0x1038 => true,
+ 0x1039...0x103a => true,
+ 0x103b...0x103c => true,
+ 0x103d...0x103e => true,
+ 0x103f => true,
+ 0x1040...0x1049 => true,
+ 0x1050...0x1055 => true,
+ 0x1056...0x1057 => true,
+ 0x1058...0x1059 => true,
+ 0x105a...0x105d => true,
+ 0x105e...0x1060 => true,
+ 0x1061 => true,
+ 0x1062...0x1064 => true,
+ 0x1065...0x1066 => true,
+ 0x1067...0x106d => true,
+ 0x106e...0x1070 => true,
+ 0x1071...0x1074 => true,
+ 0x1075...0x1081 => true,
+ 0x1082 => true,
+ 0x1083...0x1084 => true,
+ 0x1085...0x1086 => true,
+ 0x1087...0x108c => true,
+ 0x108d => true,
+ 0x108e => true,
+ 0x108f => true,
+ 0x1090...0x1099 => true,
+ 0x109a...0x109c => true,
+ 0x109d => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x10d0...0x10fa => true,
+ 0x10fc => true,
+ 0x10fd...0x10ff => true,
+ 0x1100...0x1248 => true,
+ 0x124a...0x124d => true,
+ 0x1250...0x1256 => true,
+ 0x1258 => true,
+ 0x125a...0x125d => true,
+ 0x1260...0x1288 => true,
+ 0x128a...0x128d => true,
+ 0x1290...0x12b0 => true,
+ 0x12b2...0x12b5 => true,
+ 0x12b8...0x12be => true,
+ 0x12c0 => true,
+ 0x12c2...0x12c5 => true,
+ 0x12c8...0x12d6 => true,
+ 0x12d8...0x1310 => true,
+ 0x1312...0x1315 => true,
+ 0x1318...0x135a => true,
+ 0x135d...0x135f => true,
+ 0x1369...0x1371 => true,
+ 0x1380...0x138f => true,
+ 0x13a0...0x13f5 => true,
+ 0x13f8...0x13fd => true,
+ 0x1401...0x166c => true,
+ 0x166f...0x167f => true,
+ 0x1681...0x169a => true,
+ 0x16a0...0x16ea => true,
+ 0x16ee...0x16f0 => true,
+ 0x16f1...0x16f8 => true,
+ 0x1700...0x1711 => true,
+ 0x1712...0x1714 => true,
+ 0x1715 => true,
+ 0x171f...0x1731 => true,
+ 0x1732...0x1733 => true,
+ 0x1734 => true,
+ 0x1740...0x1751 => true,
+ 0x1752...0x1753 => true,
+ 0x1760...0x176c => true,
+ 0x176e...0x1770 => true,
+ 0x1772...0x1773 => true,
+ 0x1780...0x17b3 => true,
+ 0x17b4...0x17b5 => true,
+ 0x17b6 => true,
+ 0x17b7...0x17bd => true,
+ 0x17be...0x17c5 => true,
+ 0x17c6 => true,
+ 0x17c7...0x17c8 => true,
+ 0x17c9...0x17d3 => true,
+ 0x17d7 => true,
+ 0x17dc => true,
+ 0x17dd => true,
+ 0x17e0...0x17e9 => true,
+ 0x180b...0x180d => true,
+ 0x180f => true,
+ 0x1810...0x1819 => true,
+ 0x1820...0x1842 => true,
+ 0x1843 => true,
+ 0x1844...0x1878 => true,
+ 0x1880...0x1884 => true,
+ 0x1885...0x1886 => true,
+ 0x1887...0x18a8 => true,
+ 0x18a9 => true,
+ 0x18aa => true,
+ 0x18b0...0x18f5 => true,
+ 0x1900...0x191e => true,
+ 0x1920...0x1922 => true,
+ 0x1923...0x1926 => true,
+ 0x1927...0x1928 => true,
+ 0x1929...0x192b => true,
+ 0x1930...0x1931 => true,
+ 0x1932 => true,
+ 0x1933...0x1938 => true,
+ 0x1939...0x193b => true,
+ 0x1946...0x194f => true,
+ 0x1950...0x196d => true,
+ 0x1970...0x1974 => true,
+ 0x1980...0x19ab => true,
+ 0x19b0...0x19c9 => true,
+ 0x19d0...0x19d9 => true,
+ 0x19da => true,
+ 0x1a00...0x1a16 => true,
+ 0x1a17...0x1a18 => true,
+ 0x1a19...0x1a1a => true,
+ 0x1a1b => true,
+ 0x1a20...0x1a54 => true,
+ 0x1a55 => true,
+ 0x1a56 => true,
+ 0x1a57 => true,
+ 0x1a58...0x1a5e => true,
+ 0x1a60 => true,
+ 0x1a61 => true,
+ 0x1a62 => true,
+ 0x1a63...0x1a64 => true,
+ 0x1a65...0x1a6c => true,
+ 0x1a6d...0x1a72 => true,
+ 0x1a73...0x1a7c => true,
+ 0x1a7f => true,
+ 0x1a80...0x1a89 => true,
+ 0x1a90...0x1a99 => true,
+ 0x1aa7 => true,
+ 0x1ab0...0x1abd => true,
+ 0x1abf...0x1ace => true,
+ 0x1b00...0x1b03 => true,
+ 0x1b04 => true,
+ 0x1b05...0x1b33 => true,
+ 0x1b34 => true,
+ 0x1b35 => true,
+ 0x1b36...0x1b3a => true,
+ 0x1b3b => true,
+ 0x1b3c => true,
+ 0x1b3d...0x1b41 => true,
+ 0x1b42 => true,
+ 0x1b43...0x1b44 => true,
+ 0x1b45...0x1b4c => true,
+ 0x1b50...0x1b59 => true,
+ 0x1b6b...0x1b73 => true,
+ 0x1b80...0x1b81 => true,
+ 0x1b82 => true,
+ 0x1b83...0x1ba0 => true,
+ 0x1ba1 => true,
+ 0x1ba2...0x1ba5 => true,
+ 0x1ba6...0x1ba7 => true,
+ 0x1ba8...0x1ba9 => true,
+ 0x1baa => true,
+ 0x1bab...0x1bad => true,
+ 0x1bae...0x1baf => true,
+ 0x1bb0...0x1bb9 => true,
+ 0x1bba...0x1be5 => true,
+ 0x1be6 => true,
+ 0x1be7 => true,
+ 0x1be8...0x1be9 => true,
+ 0x1bea...0x1bec => true,
+ 0x1bed => true,
+ 0x1bee => true,
+ 0x1bef...0x1bf1 => true,
+ 0x1bf2...0x1bf3 => true,
+ 0x1c00...0x1c23 => true,
+ 0x1c24...0x1c2b => true,
+ 0x1c2c...0x1c33 => true,
+ 0x1c34...0x1c35 => true,
+ 0x1c36...0x1c37 => true,
+ 0x1c40...0x1c49 => true,
+ 0x1c4d...0x1c4f => true,
+ 0x1c50...0x1c59 => true,
+ 0x1c5a...0x1c77 => true,
+ 0x1c78...0x1c7d => true,
+ 0x1c80...0x1c88 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1cd0...0x1cd2 => true,
+ 0x1cd4...0x1ce0 => true,
+ 0x1ce1 => true,
+ 0x1ce2...0x1ce8 => true,
+ 0x1ce9...0x1cec => true,
+ 0x1ced => true,
+ 0x1cee...0x1cf3 => true,
+ 0x1cf4 => true,
+ 0x1cf5...0x1cf6 => true,
+ 0x1cf7 => true,
+ 0x1cf8...0x1cf9 => true,
+ 0x1cfa => true,
+ 0x1d00...0x1d2b => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d6b...0x1d77 => true,
+ 0x1d78 => true,
+ 0x1d79...0x1d9a => true,
+ 0x1d9b...0x1dbf => true,
+ 0x1dc0...0x1dff => true,
+ 0x1e00...0x1f15 => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f20...0x1f45 => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f...0x1f7d => true,
+ 0x1f80...0x1fb4 => true,
+ 0x1fb6...0x1fbc => true,
+ 0x1fbe => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fcc => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fdb => true,
+ 0x1fe0...0x1fec => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ffc => true,
+ 0x203f...0x2040 => true,
+ 0x2054 => true,
+ 0x2071 => true,
+ 0x207f => true,
+ 0x2090...0x209c => true,
+ 0x20d0...0x20dc => true,
+ 0x20e1 => true,
+ 0x20e5...0x20f0 => true,
+ 0x2102 => true,
+ 0x2107 => true,
+ 0x210a...0x2113 => true,
+ 0x2115 => true,
+ 0x2118 => true,
+ 0x2119...0x211d => true,
+ 0x2124 => true,
+ 0x2126 => true,
+ 0x2128 => true,
+ 0x212a...0x212d => true,
+ 0x212e => true,
+ 0x212f...0x2134 => true,
+ 0x2135...0x2138 => true,
+ 0x2139 => true,
+ 0x213c...0x213f => true,
+ 0x2145...0x2149 => true,
+ 0x214e => true,
+ 0x2160...0x2182 => true,
+ 0x2183...0x2184 => true,
+ 0x2185...0x2188 => true,
+ 0x2c00...0x2c7b => true,
+ 0x2c7c...0x2c7d => true,
+ 0x2c7e...0x2ce4 => true,
+ 0x2ceb...0x2cee => true,
+ 0x2cef...0x2cf1 => true,
+ 0x2cf2...0x2cf3 => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0x2d30...0x2d67 => true,
+ 0x2d6f => true,
+ 0x2d7f => true,
+ 0x2d80...0x2d96 => true,
+ 0x2da0...0x2da6 => true,
+ 0x2da8...0x2dae => true,
+ 0x2db0...0x2db6 => true,
+ 0x2db8...0x2dbe => true,
+ 0x2dc0...0x2dc6 => true,
+ 0x2dc8...0x2dce => true,
+ 0x2dd0...0x2dd6 => true,
+ 0x2dd8...0x2dde => true,
+ 0x2de0...0x2dff => true,
+ 0x3005 => true,
+ 0x3006 => true,
+ 0x3007 => true,
+ 0x3021...0x3029 => true,
+ 0x302a...0x302d => true,
+ 0x302e...0x302f => true,
+ 0x3031...0x3035 => true,
+ 0x3038...0x303a => true,
+ 0x303b => true,
+ 0x303c => true,
+ 0x3041...0x3096 => true,
+ 0x3099...0x309a => true,
+ 0x309d...0x309e => true,
+ 0x309f => true,
+ 0x30a1...0x30fa => true,
+ 0x30fc...0x30fe => true,
+ 0x30ff => true,
+ 0x3105...0x312f => true,
+ 0x3131...0x318e => true,
+ 0x31a0...0x31bf => true,
+ 0x31f0...0x31ff => true,
+ 0x3400...0x4dbf => true,
+ 0x4e00...0xa014 => true,
+ 0xa015 => true,
+ 0xa016...0xa48c => true,
+ 0xa4d0...0xa4f7 => true,
+ 0xa4f8...0xa4fd => true,
+ 0xa500...0xa60b => true,
+ 0xa60c => true,
+ 0xa610...0xa61f => true,
+ 0xa620...0xa629 => true,
+ 0xa62a...0xa62b => true,
+ 0xa640...0xa66d => true,
+ 0xa66e => true,
+ 0xa66f => true,
+ 0xa674...0xa67d => true,
+ 0xa67f => true,
+ 0xa680...0xa69b => true,
+ 0xa69c...0xa69d => true,
+ 0xa69e...0xa69f => true,
+ 0xa6a0...0xa6e5 => true,
+ 0xa6e6...0xa6ef => true,
+ 0xa6f0...0xa6f1 => true,
+ 0xa717...0xa71f => true,
+ 0xa722...0xa76f => true,
+ 0xa770 => true,
+ 0xa771...0xa787 => true,
+ 0xa788 => true,
+ 0xa78b...0xa78e => true,
+ 0xa78f => true,
+ 0xa790...0xa7ca => true,
+ 0xa7d0...0xa7d1 => true,
+ 0xa7d3 => true,
+ 0xa7d5...0xa7d9 => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f5...0xa7f6 => true,
+ 0xa7f7 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa7fa => true,
+ 0xa7fb...0xa801 => true,
+ 0xa802 => true,
+ 0xa803...0xa805 => true,
+ 0xa806 => true,
+ 0xa807...0xa80a => true,
+ 0xa80b => true,
+ 0xa80c...0xa822 => true,
+ 0xa823...0xa824 => true,
+ 0xa825...0xa826 => true,
+ 0xa827 => true,
+ 0xa82c => true,
+ 0xa840...0xa873 => true,
+ 0xa880...0xa881 => true,
+ 0xa882...0xa8b3 => true,
+ 0xa8b4...0xa8c3 => true,
+ 0xa8c4...0xa8c5 => true,
+ 0xa8d0...0xa8d9 => true,
+ 0xa8e0...0xa8f1 => true,
+ 0xa8f2...0xa8f7 => true,
+ 0xa8fb => true,
+ 0xa8fd...0xa8fe => true,
+ 0xa8ff => true,
+ 0xa900...0xa909 => true,
+ 0xa90a...0xa925 => true,
+ 0xa926...0xa92d => true,
+ 0xa930...0xa946 => true,
+ 0xa947...0xa951 => true,
+ 0xa952...0xa953 => true,
+ 0xa960...0xa97c => true,
+ 0xa980...0xa982 => true,
+ 0xa983 => true,
+ 0xa984...0xa9b2 => true,
+ 0xa9b3 => true,
+ 0xa9b4...0xa9b5 => true,
+ 0xa9b6...0xa9b9 => true,
+ 0xa9ba...0xa9bb => true,
+ 0xa9bc...0xa9bd => true,
+ 0xa9be...0xa9c0 => true,
+ 0xa9cf => true,
+ 0xa9d0...0xa9d9 => true,
+ 0xa9e0...0xa9e4 => true,
+ 0xa9e5 => true,
+ 0xa9e6 => true,
+ 0xa9e7...0xa9ef => true,
+ 0xa9f0...0xa9f9 => true,
+ 0xa9fa...0xa9fe => true,
+ 0xaa00...0xaa28 => true,
+ 0xaa29...0xaa2e => true,
+ 0xaa2f...0xaa30 => true,
+ 0xaa31...0xaa32 => true,
+ 0xaa33...0xaa34 => true,
+ 0xaa35...0xaa36 => true,
+ 0xaa40...0xaa42 => true,
+ 0xaa43 => true,
+ 0xaa44...0xaa4b => true,
+ 0xaa4c => true,
+ 0xaa4d => true,
+ 0xaa50...0xaa59 => true,
+ 0xaa60...0xaa6f => true,
+ 0xaa70 => true,
+ 0xaa71...0xaa76 => true,
+ 0xaa7a => true,
+ 0xaa7b => true,
+ 0xaa7c => true,
+ 0xaa7d => true,
+ 0xaa7e...0xaaaf => true,
+ 0xaab0 => true,
+ 0xaab1 => true,
+ 0xaab2...0xaab4 => true,
+ 0xaab5...0xaab6 => true,
+ 0xaab7...0xaab8 => true,
+ 0xaab9...0xaabd => true,
+ 0xaabe...0xaabf => true,
+ 0xaac0 => true,
+ 0xaac1 => true,
+ 0xaac2 => true,
+ 0xaadb...0xaadc => true,
+ 0xaadd => true,
+ 0xaae0...0xaaea => true,
+ 0xaaeb => true,
+ 0xaaec...0xaaed => true,
+ 0xaaee...0xaaef => true,
+ 0xaaf2 => true,
+ 0xaaf3...0xaaf4 => true,
+ 0xaaf5 => true,
+ 0xaaf6 => true,
+ 0xab01...0xab06 => true,
+ 0xab09...0xab0e => true,
+ 0xab11...0xab16 => true,
+ 0xab20...0xab26 => true,
+ 0xab28...0xab2e => true,
+ 0xab30...0xab5a => true,
+ 0xab5c...0xab5f => true,
+ 0xab60...0xab68 => true,
+ 0xab69 => true,
+ 0xab70...0xabbf => true,
+ 0xabc0...0xabe2 => true,
+ 0xabe3...0xabe4 => true,
+ 0xabe5 => true,
+ 0xabe6...0xabe7 => true,
+ 0xabe8 => true,
+ 0xabe9...0xabea => true,
+ 0xabec => true,
+ 0xabed => true,
+ 0xabf0...0xabf9 => true,
+ 0xac00...0xd7a3 => true,
+ 0xd7b0...0xd7c6 => true,
+ 0xd7cb...0xd7fb => true,
+ 0xf900...0xfa6d => true,
+ 0xfa70...0xfad9 => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xfb1d => true,
+ 0xfb1e => true,
+ 0xfb1f...0xfb28 => true,
+ 0xfb2a...0xfb36 => true,
+ 0xfb38...0xfb3c => true,
+ 0xfb3e => true,
+ 0xfb40...0xfb41 => true,
+ 0xfb43...0xfb44 => true,
+ 0xfb46...0xfbb1 => true,
+ 0xfbd3...0xfc5d => true,
+ 0xfc64...0xfd3d => true,
+ 0xfd50...0xfd8f => true,
+ 0xfd92...0xfdc7 => true,
+ 0xfdf0...0xfdf9 => true,
+ 0xfe00...0xfe0f => true,
+ 0xfe20...0xfe2f => true,
+ 0xfe33...0xfe34 => true,
+ 0xfe4d...0xfe4f => true,
+ 0xfe71 => true,
+ 0xfe73 => true,
+ 0xfe77 => true,
+ 0xfe79 => true,
+ 0xfe7b => true,
+ 0xfe7d => true,
+ 0xfe7f...0xfefc => true,
+ 0xff10...0xff19 => true,
+ 0xff21...0xff3a => true,
+ 0xff3f => true,
+ 0xff41...0xff5a => true,
+ 0xff66...0xff6f => true,
+ 0xff70 => true,
+ 0xff71...0xff9d => true,
+ 0xff9e...0xff9f => true,
+ 0xffa0...0xffbe => true,
+ 0xffc2...0xffc7 => true,
+ 0xffca...0xffcf => true,
+ 0xffd2...0xffd7 => true,
+ 0xffda...0xffdc => true,
+ 0x10000...0x1000b => true,
+ 0x1000d...0x10026 => true,
+ 0x10028...0x1003a => true,
+ 0x1003c...0x1003d => true,
+ 0x1003f...0x1004d => true,
+ 0x10050...0x1005d => true,
+ 0x10080...0x100fa => true,
+ 0x10140...0x10174 => true,
+ 0x101fd => true,
+ 0x10280...0x1029c => true,
+ 0x102a0...0x102d0 => true,
+ 0x102e0 => true,
+ 0x10300...0x1031f => true,
+ 0x1032d...0x10340 => true,
+ 0x10341 => true,
+ 0x10342...0x10349 => true,
+ 0x1034a => true,
+ 0x10350...0x10375 => true,
+ 0x10376...0x1037a => true,
+ 0x10380...0x1039d => true,
+ 0x103a0...0x103c3 => true,
+ 0x103c8...0x103cf => true,
+ 0x103d1...0x103d5 => true,
+ 0x10400...0x1044f => true,
+ 0x10450...0x1049d => true,
+ 0x104a0...0x104a9 => true,
+ 0x104b0...0x104d3 => true,
+ 0x104d8...0x104fb => true,
+ 0x10500...0x10527 => true,
+ 0x10530...0x10563 => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10600...0x10736 => true,
+ 0x10740...0x10755 => true,
+ 0x10760...0x10767 => true,
+ 0x10780...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x10800...0x10805 => true,
+ 0x10808 => true,
+ 0x1080a...0x10835 => true,
+ 0x10837...0x10838 => true,
+ 0x1083c => true,
+ 0x1083f...0x10855 => true,
+ 0x10860...0x10876 => true,
+ 0x10880...0x1089e => true,
+ 0x108e0...0x108f2 => true,
+ 0x108f4...0x108f5 => true,
+ 0x10900...0x10915 => true,
+ 0x10920...0x10939 => true,
+ 0x10980...0x109b7 => true,
+ 0x109be...0x109bf => true,
+ 0x10a00 => true,
+ 0x10a01...0x10a03 => true,
+ 0x10a05...0x10a06 => true,
+ 0x10a0c...0x10a0f => true,
+ 0x10a10...0x10a13 => true,
+ 0x10a15...0x10a17 => true,
+ 0x10a19...0x10a35 => true,
+ 0x10a38...0x10a3a => true,
+ 0x10a3f => true,
+ 0x10a60...0x10a7c => true,
+ 0x10a80...0x10a9c => true,
+ 0x10ac0...0x10ac7 => true,
+ 0x10ac9...0x10ae4 => true,
+ 0x10ae5...0x10ae6 => true,
+ 0x10b00...0x10b35 => true,
+ 0x10b40...0x10b55 => true,
+ 0x10b60...0x10b72 => true,
+ 0x10b80...0x10b91 => true,
+ 0x10c00...0x10c48 => true,
+ 0x10c80...0x10cb2 => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x10d00...0x10d23 => true,
+ 0x10d24...0x10d27 => true,
+ 0x10d30...0x10d39 => true,
+ 0x10e80...0x10ea9 => true,
+ 0x10eab...0x10eac => true,
+ 0x10eb0...0x10eb1 => true,
+ 0x10efd...0x10eff => true,
+ 0x10f00...0x10f1c => true,
+ 0x10f27 => true,
+ 0x10f30...0x10f45 => true,
+ 0x10f46...0x10f50 => true,
+ 0x10f70...0x10f81 => true,
+ 0x10f82...0x10f85 => true,
+ 0x10fb0...0x10fc4 => true,
+ 0x10fe0...0x10ff6 => true,
+ 0x11000 => true,
+ 0x11001 => true,
+ 0x11002 => true,
+ 0x11003...0x11037 => true,
+ 0x11038...0x11046 => true,
+ 0x11066...0x1106f => true,
+ 0x11070 => true,
+ 0x11071...0x11072 => true,
+ 0x11073...0x11074 => true,
+ 0x11075 => true,
+ 0x1107f...0x11081 => true,
+ 0x11082 => true,
+ 0x11083...0x110af => true,
+ 0x110b0...0x110b2 => true,
+ 0x110b3...0x110b6 => true,
+ 0x110b7...0x110b8 => true,
+ 0x110b9...0x110ba => true,
+ 0x110c2 => true,
+ 0x110d0...0x110e8 => true,
+ 0x110f0...0x110f9 => true,
+ 0x11100...0x11102 => true,
+ 0x11103...0x11126 => true,
+ 0x11127...0x1112b => true,
+ 0x1112c => true,
+ 0x1112d...0x11134 => true,
+ 0x11136...0x1113f => true,
+ 0x11144 => true,
+ 0x11145...0x11146 => true,
+ 0x11147 => true,
+ 0x11150...0x11172 => true,
+ 0x11173 => true,
+ 0x11176 => true,
+ 0x11180...0x11181 => true,
+ 0x11182 => true,
+ 0x11183...0x111b2 => true,
+ 0x111b3...0x111b5 => true,
+ 0x111b6...0x111be => true,
+ 0x111bf...0x111c0 => true,
+ 0x111c1...0x111c4 => true,
+ 0x111c9...0x111cc => true,
+ 0x111ce => true,
+ 0x111cf => true,
+ 0x111d0...0x111d9 => true,
+ 0x111da => true,
+ 0x111dc => true,
+ 0x11200...0x11211 => true,
+ 0x11213...0x1122b => true,
+ 0x1122c...0x1122e => true,
+ 0x1122f...0x11231 => true,
+ 0x11232...0x11233 => true,
+ 0x11234 => true,
+ 0x11235 => true,
+ 0x11236...0x11237 => true,
+ 0x1123e => true,
+ 0x1123f...0x11240 => true,
+ 0x11241 => true,
+ 0x11280...0x11286 => true,
+ 0x11288 => true,
+ 0x1128a...0x1128d => true,
+ 0x1128f...0x1129d => true,
+ 0x1129f...0x112a8 => true,
+ 0x112b0...0x112de => true,
+ 0x112df => true,
+ 0x112e0...0x112e2 => true,
+ 0x112e3...0x112ea => true,
+ 0x112f0...0x112f9 => true,
+ 0x11300...0x11301 => true,
+ 0x11302...0x11303 => true,
+ 0x11305...0x1130c => true,
+ 0x1130f...0x11310 => true,
+ 0x11313...0x11328 => true,
+ 0x1132a...0x11330 => true,
+ 0x11332...0x11333 => true,
+ 0x11335...0x11339 => true,
+ 0x1133b...0x1133c => true,
+ 0x1133d => true,
+ 0x1133e...0x1133f => true,
+ 0x11340 => true,
+ 0x11341...0x11344 => true,
+ 0x11347...0x11348 => true,
+ 0x1134b...0x1134d => true,
+ 0x11350 => true,
+ 0x11357 => true,
+ 0x1135d...0x11361 => true,
+ 0x11362...0x11363 => true,
+ 0x11366...0x1136c => true,
+ 0x11370...0x11374 => true,
+ 0x11400...0x11434 => true,
+ 0x11435...0x11437 => true,
+ 0x11438...0x1143f => true,
+ 0x11440...0x11441 => true,
+ 0x11442...0x11444 => true,
+ 0x11445 => true,
+ 0x11446 => true,
+ 0x11447...0x1144a => true,
+ 0x11450...0x11459 => true,
+ 0x1145e => true,
+ 0x1145f...0x11461 => true,
+ 0x11480...0x114af => true,
+ 0x114b0...0x114b2 => true,
+ 0x114b3...0x114b8 => true,
+ 0x114b9 => true,
+ 0x114ba => true,
+ 0x114bb...0x114be => true,
+ 0x114bf...0x114c0 => true,
+ 0x114c1 => true,
+ 0x114c2...0x114c3 => true,
+ 0x114c4...0x114c5 => true,
+ 0x114c7 => true,
+ 0x114d0...0x114d9 => true,
+ 0x11580...0x115ae => true,
+ 0x115af...0x115b1 => true,
+ 0x115b2...0x115b5 => true,
+ 0x115b8...0x115bb => true,
+ 0x115bc...0x115bd => true,
+ 0x115be => true,
+ 0x115bf...0x115c0 => true,
+ 0x115d8...0x115db => true,
+ 0x115dc...0x115dd => true,
+ 0x11600...0x1162f => true,
+ 0x11630...0x11632 => true,
+ 0x11633...0x1163a => true,
+ 0x1163b...0x1163c => true,
+ 0x1163d => true,
+ 0x1163e => true,
+ 0x1163f...0x11640 => true,
+ 0x11644 => true,
+ 0x11650...0x11659 => true,
+ 0x11680...0x116aa => true,
+ 0x116ab => true,
+ 0x116ac => true,
+ 0x116ad => true,
+ 0x116ae...0x116af => true,
+ 0x116b0...0x116b5 => true,
+ 0x116b6 => true,
+ 0x116b7 => true,
+ 0x116b8 => true,
+ 0x116c0...0x116c9 => true,
+ 0x11700...0x1171a => true,
+ 0x1171d...0x1171f => true,
+ 0x11720...0x11721 => true,
+ 0x11722...0x11725 => true,
+ 0x11726 => true,
+ 0x11727...0x1172b => true,
+ 0x11730...0x11739 => true,
+ 0x11740...0x11746 => true,
+ 0x11800...0x1182b => true,
+ 0x1182c...0x1182e => true,
+ 0x1182f...0x11837 => true,
+ 0x11838 => true,
+ 0x11839...0x1183a => true,
+ 0x118a0...0x118df => true,
+ 0x118e0...0x118e9 => true,
+ 0x118ff...0x11906 => true,
+ 0x11909 => true,
+ 0x1190c...0x11913 => true,
+ 0x11915...0x11916 => true,
+ 0x11918...0x1192f => true,
+ 0x11930...0x11935 => true,
+ 0x11937...0x11938 => true,
+ 0x1193b...0x1193c => true,
+ 0x1193d => true,
+ 0x1193e => true,
+ 0x1193f => true,
+ 0x11940 => true,
+ 0x11941 => true,
+ 0x11942 => true,
+ 0x11943 => true,
+ 0x11950...0x11959 => true,
+ 0x119a0...0x119a7 => true,
+ 0x119aa...0x119d0 => true,
+ 0x119d1...0x119d3 => true,
+ 0x119d4...0x119d7 => true,
+ 0x119da...0x119db => true,
+ 0x119dc...0x119df => true,
+ 0x119e0 => true,
+ 0x119e1 => true,
+ 0x119e3 => true,
+ 0x119e4 => true,
+ 0x11a00 => true,
+ 0x11a01...0x11a0a => true,
+ 0x11a0b...0x11a32 => true,
+ 0x11a33...0x11a38 => true,
+ 0x11a39 => true,
+ 0x11a3a => true,
+ 0x11a3b...0x11a3e => true,
+ 0x11a47 => true,
+ 0x11a50 => true,
+ 0x11a51...0x11a56 => true,
+ 0x11a57...0x11a58 => true,
+ 0x11a59...0x11a5b => true,
+ 0x11a5c...0x11a89 => true,
+ 0x11a8a...0x11a96 => true,
+ 0x11a97 => true,
+ 0x11a98...0x11a99 => true,
+ 0x11a9d => true,
+ 0x11ab0...0x11af8 => true,
+ 0x11c00...0x11c08 => true,
+ 0x11c0a...0x11c2e => true,
+ 0x11c2f => true,
+ 0x11c30...0x11c36 => true,
+ 0x11c38...0x11c3d => true,
+ 0x11c3e => true,
+ 0x11c3f => true,
+ 0x11c40 => true,
+ 0x11c50...0x11c59 => true,
+ 0x11c72...0x11c8f => true,
+ 0x11c92...0x11ca7 => true,
+ 0x11ca9 => true,
+ 0x11caa...0x11cb0 => true,
+ 0x11cb1 => true,
+ 0x11cb2...0x11cb3 => true,
+ 0x11cb4 => true,
+ 0x11cb5...0x11cb6 => true,
+ 0x11d00...0x11d06 => true,
+ 0x11d08...0x11d09 => true,
+ 0x11d0b...0x11d30 => true,
+ 0x11d31...0x11d36 => true,
+ 0x11d3a => true,
+ 0x11d3c...0x11d3d => true,
+ 0x11d3f...0x11d45 => true,
+ 0x11d46 => true,
+ 0x11d47 => true,
+ 0x11d50...0x11d59 => true,
+ 0x11d60...0x11d65 => true,
+ 0x11d67...0x11d68 => true,
+ 0x11d6a...0x11d89 => true,
+ 0x11d8a...0x11d8e => true,
+ 0x11d90...0x11d91 => true,
+ 0x11d93...0x11d94 => true,
+ 0x11d95 => true,
+ 0x11d96 => true,
+ 0x11d97 => true,
+ 0x11d98 => true,
+ 0x11da0...0x11da9 => true,
+ 0x11ee0...0x11ef2 => true,
+ 0x11ef3...0x11ef4 => true,
+ 0x11ef5...0x11ef6 => true,
+ 0x11f00...0x11f01 => true,
+ 0x11f02 => true,
+ 0x11f03 => true,
+ 0x11f04...0x11f10 => true,
+ 0x11f12...0x11f33 => true,
+ 0x11f34...0x11f35 => true,
+ 0x11f36...0x11f3a => true,
+ 0x11f3e...0x11f3f => true,
+ 0x11f40 => true,
+ 0x11f41 => true,
+ 0x11f42 => true,
+ 0x11f50...0x11f59 => true,
+ 0x11fb0 => true,
+ 0x12000...0x12399 => true,
+ 0x12400...0x1246e => true,
+ 0x12480...0x12543 => true,
+ 0x12f90...0x12ff0 => true,
+ 0x13000...0x1342f => true,
+ 0x13440 => true,
+ 0x13441...0x13446 => true,
+ 0x13447...0x13455 => true,
+ 0x14400...0x14646 => true,
+ 0x16800...0x16a38 => true,
+ 0x16a40...0x16a5e => true,
+ 0x16a60...0x16a69 => true,
+ 0x16a70...0x16abe => true,
+ 0x16ac0...0x16ac9 => true,
+ 0x16ad0...0x16aed => true,
+ 0x16af0...0x16af4 => true,
+ 0x16b00...0x16b2f => true,
+ 0x16b30...0x16b36 => true,
+ 0x16b40...0x16b43 => true,
+ 0x16b50...0x16b59 => true,
+ 0x16b63...0x16b77 => true,
+ 0x16b7d...0x16b8f => true,
+ 0x16e40...0x16e7f => true,
+ 0x16f00...0x16f4a => true,
+ 0x16f4f => true,
+ 0x16f50 => true,
+ 0x16f51...0x16f87 => true,
+ 0x16f8f...0x16f92 => true,
+ 0x16f93...0x16f9f => true,
+ 0x16fe0...0x16fe1 => true,
+ 0x16fe3 => true,
+ 0x16fe4 => true,
+ 0x16ff0...0x16ff1 => true,
+ 0x17000...0x187f7 => true,
+ 0x18800...0x18cd5 => true,
+ 0x18d00...0x18d08 => true,
+ 0x1aff0...0x1aff3 => true,
+ 0x1aff5...0x1affb => true,
+ 0x1affd...0x1affe => true,
+ 0x1b000...0x1b122 => true,
+ 0x1b132 => true,
+ 0x1b150...0x1b152 => true,
+ 0x1b155 => true,
+ 0x1b164...0x1b167 => true,
+ 0x1b170...0x1b2fb => true,
+ 0x1bc00...0x1bc6a => true,
+ 0x1bc70...0x1bc7c => true,
+ 0x1bc80...0x1bc88 => true,
+ 0x1bc90...0x1bc99 => true,
+ 0x1bc9d...0x1bc9e => true,
+ 0x1cf00...0x1cf2d => true,
+ 0x1cf30...0x1cf46 => true,
+ 0x1d165...0x1d166 => true,
+ 0x1d167...0x1d169 => true,
+ 0x1d16d...0x1d172 => true,
+ 0x1d17b...0x1d182 => true,
+ 0x1d185...0x1d18b => true,
+ 0x1d1aa...0x1d1ad => true,
+ 0x1d242...0x1d244 => true,
+ 0x1d400...0x1d454 => true,
+ 0x1d456...0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d51e...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d552...0x1d6a5 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6dc...0x1d6fa => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d716...0x1d734 => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d750...0x1d76e => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d78a...0x1d7a8 => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c4...0x1d7cb => true,
+ 0x1d7ce...0x1d7ff => true,
+ 0x1da00...0x1da36 => true,
+ 0x1da3b...0x1da6c => true,
+ 0x1da75 => true,
+ 0x1da84 => true,
+ 0x1da9b...0x1da9f => true,
+ 0x1daa1...0x1daaf => true,
+ 0x1df00...0x1df09 => true,
+ 0x1df0a => true,
+ 0x1df0b...0x1df1e => true,
+ 0x1df25...0x1df2a => true,
+ 0x1e000...0x1e006 => true,
+ 0x1e008...0x1e018 => true,
+ 0x1e01b...0x1e021 => true,
+ 0x1e023...0x1e024 => true,
+ 0x1e026...0x1e02a => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e08f => true,
+ 0x1e100...0x1e12c => true,
+ 0x1e130...0x1e136 => true,
+ 0x1e137...0x1e13d => true,
+ 0x1e140...0x1e149 => true,
+ 0x1e14e => true,
+ 0x1e290...0x1e2ad => true,
+ 0x1e2ae => true,
+ 0x1e2c0...0x1e2eb => true,
+ 0x1e2ec...0x1e2ef => true,
+ 0x1e2f0...0x1e2f9 => true,
+ 0x1e4d0...0x1e4ea => true,
+ 0x1e4eb => true,
+ 0x1e4ec...0x1e4ef => true,
+ 0x1e4f0...0x1e4f9 => true,
+ 0x1e7e0...0x1e7e6 => true,
+ 0x1e7e8...0x1e7eb => true,
+ 0x1e7ed...0x1e7ee => true,
+ 0x1e7f0...0x1e7fe => true,
+ 0x1e800...0x1e8c4 => true,
+ 0x1e8d0...0x1e8d6 => true,
+ 0x1e900...0x1e943 => true,
+ 0x1e944...0x1e94a => true,
+ 0x1e94b => true,
+ 0x1e950...0x1e959 => true,
+ 0x1ee00...0x1ee03 => true,
+ 0x1ee05...0x1ee1f => true,
+ 0x1ee21...0x1ee22 => true,
+ 0x1ee24 => true,
+ 0x1ee27 => true,
+ 0x1ee29...0x1ee32 => true,
+ 0x1ee34...0x1ee37 => true,
+ 0x1ee39 => true,
+ 0x1ee3b => true,
+ 0x1ee42 => true,
+ 0x1ee47 => true,
+ 0x1ee49 => true,
+ 0x1ee4b => true,
+ 0x1ee4d...0x1ee4f => true,
+ 0x1ee51...0x1ee52 => true,
+ 0x1ee54 => true,
+ 0x1ee57 => true,
+ 0x1ee59 => true,
+ 0x1ee5b => true,
+ 0x1ee5d => true,
+ 0x1ee5f => true,
+ 0x1ee61...0x1ee62 => true,
+ 0x1ee64 => true,
+ 0x1ee67...0x1ee6a => true,
+ 0x1ee6c...0x1ee72 => true,
+ 0x1ee74...0x1ee77 => true,
+ 0x1ee79...0x1ee7c => true,
+ 0x1ee7e => true,
+ 0x1ee80...0x1ee89 => true,
+ 0x1ee8b...0x1ee9b => true,
+ 0x1eea1...0x1eea3 => true,
+ 0x1eea5...0x1eea9 => true,
+ 0x1eeab...0x1eebb => true,
+ 0x1fbf0...0x1fbf9 => true,
+ 0x20000...0x2a6df => true,
+ 0x2a700...0x2b739 => true,
+ 0x2b740...0x2b81d => true,
+ 0x2b820...0x2cea1 => true,
+ 0x2ceb0...0x2ebe0 => true,
+ 0x2f800...0x2fa1d => true,
+ 0x30000...0x3134a => true,
+ 0x31350...0x323af => true,
+ 0xe0100...0xe01ef => true,
+ else => false,
+ };
+}
+
+pub fn isDefaultIgnorableCodePoint(cp: u21) bool {
+ if (cp < 0xad or cp > 0xe0fff) return false;
+
+ return switch (cp) {
+ 0xad => true,
+ 0x34f => true,
+ 0x61c => true,
+ 0x115f...0x1160 => true,
+ 0x17b4...0x17b5 => true,
+ 0x180b...0x180d => true,
+ 0x180e => true,
+ 0x180f => true,
+ 0x200b...0x200f => true,
+ 0x202a...0x202e => true,
+ 0x2060...0x2064 => true,
+ 0x2065 => true,
+ 0x2066...0x206f => true,
+ 0x3164 => true,
+ 0xfe00...0xfe0f => true,
+ 0xfeff => true,
+ 0xffa0 => true,
+ 0xfff0...0xfff8 => true,
+ 0x1bca0...0x1bca3 => true,
+ 0x1d173...0x1d17a => true,
+ 0xe0000 => true,
+ 0xe0001 => true,
+ 0xe0002...0xe001f => true,
+ 0xe0020...0xe007f => true,
+ 0xe0080...0xe00ff => true,
+ 0xe0100...0xe01ef => true,
+ 0xe01f0...0xe0fff => true,
+ else => false,
+ };
+}
+
+pub fn isGraphemeExtend(cp: u21) bool {
+ if (cp < 0x300 or cp > 0xe01ef) return false;
+
+ return switch (cp) {
+ 0x300...0x36f => true,
+ 0x483...0x487 => true,
+ 0x488...0x489 => true,
+ 0x591...0x5bd => true,
+ 0x5bf => true,
+ 0x5c1...0x5c2 => true,
+ 0x5c4...0x5c5 => true,
+ 0x5c7 => true,
+ 0x610...0x61a => true,
+ 0x64b...0x65f => true,
+ 0x670 => true,
+ 0x6d6...0x6dc => true,
+ 0x6df...0x6e4 => true,
+ 0x6e7...0x6e8 => true,
+ 0x6ea...0x6ed => true,
+ 0x711 => true,
+ 0x730...0x74a => true,
+ 0x7a6...0x7b0 => true,
+ 0x7eb...0x7f3 => true,
+ 0x7fd => true,
+ 0x816...0x819 => true,
+ 0x81b...0x823 => true,
+ 0x825...0x827 => true,
+ 0x829...0x82d => true,
+ 0x859...0x85b => true,
+ 0x898...0x89f => true,
+ 0x8ca...0x8e1 => true,
+ 0x8e3...0x902 => true,
+ 0x93a => true,
+ 0x93c => true,
+ 0x941...0x948 => true,
+ 0x94d => true,
+ 0x951...0x957 => true,
+ 0x962...0x963 => true,
+ 0x981 => true,
+ 0x9bc => true,
+ 0x9be => true,
+ 0x9c1...0x9c4 => true,
+ 0x9cd => true,
+ 0x9d7 => true,
+ 0x9e2...0x9e3 => true,
+ 0x9fe => true,
+ 0xa01...0xa02 => true,
+ 0xa3c => true,
+ 0xa41...0xa42 => true,
+ 0xa47...0xa48 => true,
+ 0xa4b...0xa4d => true,
+ 0xa51 => true,
+ 0xa70...0xa71 => true,
+ 0xa75 => true,
+ 0xa81...0xa82 => true,
+ 0xabc => true,
+ 0xac1...0xac5 => true,
+ 0xac7...0xac8 => true,
+ 0xacd => true,
+ 0xae2...0xae3 => true,
+ 0xafa...0xaff => true,
+ 0xb01 => true,
+ 0xb3c => true,
+ 0xb3e => true,
+ 0xb3f => true,
+ 0xb41...0xb44 => true,
+ 0xb4d => true,
+ 0xb55...0xb56 => true,
+ 0xb57 => true,
+ 0xb62...0xb63 => true,
+ 0xb82 => true,
+ 0xbbe => true,
+ 0xbc0 => true,
+ 0xbcd => true,
+ 0xbd7 => true,
+ 0xc00 => true,
+ 0xc04 => true,
+ 0xc3c => true,
+ 0xc3e...0xc40 => true,
+ 0xc46...0xc48 => true,
+ 0xc4a...0xc4d => true,
+ 0xc55...0xc56 => true,
+ 0xc62...0xc63 => true,
+ 0xc81 => true,
+ 0xcbc => true,
+ 0xcbf => true,
+ 0xcc2 => true,
+ 0xcc6 => true,
+ 0xccc...0xccd => true,
+ 0xcd5...0xcd6 => true,
+ 0xce2...0xce3 => true,
+ 0xd00...0xd01 => true,
+ 0xd3b...0xd3c => true,
+ 0xd3e => true,
+ 0xd41...0xd44 => true,
+ 0xd4d => true,
+ 0xd57 => true,
+ 0xd62...0xd63 => true,
+ 0xd81 => true,
+ 0xdca => true,
+ 0xdcf => true,
+ 0xdd2...0xdd4 => true,
+ 0xdd6 => true,
+ 0xddf => true,
+ 0xe31 => true,
+ 0xe34...0xe3a => true,
+ 0xe47...0xe4e => true,
+ 0xeb1 => true,
+ 0xeb4...0xebc => true,
+ 0xec8...0xece => true,
+ 0xf18...0xf19 => true,
+ 0xf35 => true,
+ 0xf37 => true,
+ 0xf39 => true,
+ 0xf71...0xf7e => true,
+ 0xf80...0xf84 => true,
+ 0xf86...0xf87 => true,
+ 0xf8d...0xf97 => true,
+ 0xf99...0xfbc => true,
+ 0xfc6 => true,
+ 0x102d...0x1030 => true,
+ 0x1032...0x1037 => true,
+ 0x1039...0x103a => true,
+ 0x103d...0x103e => true,
+ 0x1058...0x1059 => true,
+ 0x105e...0x1060 => true,
+ 0x1071...0x1074 => true,
+ 0x1082 => true,
+ 0x1085...0x1086 => true,
+ 0x108d => true,
+ 0x109d => true,
+ 0x135d...0x135f => true,
+ 0x1712...0x1714 => true,
+ 0x1732...0x1733 => true,
+ 0x1752...0x1753 => true,
+ 0x1772...0x1773 => true,
+ 0x17b4...0x17b5 => true,
+ 0x17b7...0x17bd => true,
+ 0x17c6 => true,
+ 0x17c9...0x17d3 => true,
+ 0x17dd => true,
+ 0x180b...0x180d => true,
+ 0x180f => true,
+ 0x1885...0x1886 => true,
+ 0x18a9 => true,
+ 0x1920...0x1922 => true,
+ 0x1927...0x1928 => true,
+ 0x1932 => true,
+ 0x1939...0x193b => true,
+ 0x1a17...0x1a18 => true,
+ 0x1a1b => true,
+ 0x1a56 => true,
+ 0x1a58...0x1a5e => true,
+ 0x1a60 => true,
+ 0x1a62 => true,
+ 0x1a65...0x1a6c => true,
+ 0x1a73...0x1a7c => true,
+ 0x1a7f => true,
+ 0x1ab0...0x1abd => true,
+ 0x1abe => true,
+ 0x1abf...0x1ace => true,
+ 0x1b00...0x1b03 => true,
+ 0x1b34 => true,
+ 0x1b35 => true,
+ 0x1b36...0x1b3a => true,
+ 0x1b3c => true,
+ 0x1b42 => true,
+ 0x1b6b...0x1b73 => true,
+ 0x1b80...0x1b81 => true,
+ 0x1ba2...0x1ba5 => true,
+ 0x1ba8...0x1ba9 => true,
+ 0x1bab...0x1bad => true,
+ 0x1be6 => true,
+ 0x1be8...0x1be9 => true,
+ 0x1bed => true,
+ 0x1bef...0x1bf1 => true,
+ 0x1c2c...0x1c33 => true,
+ 0x1c36...0x1c37 => true,
+ 0x1cd0...0x1cd2 => true,
+ 0x1cd4...0x1ce0 => true,
+ 0x1ce2...0x1ce8 => true,
+ 0x1ced => true,
+ 0x1cf4 => true,
+ 0x1cf8...0x1cf9 => true,
+ 0x1dc0...0x1dff => true,
+ 0x200c => true,
+ 0x20d0...0x20dc => true,
+ 0x20dd...0x20e0 => true,
+ 0x20e1 => true,
+ 0x20e2...0x20e4 => true,
+ 0x20e5...0x20f0 => true,
+ 0x2cef...0x2cf1 => true,
+ 0x2d7f => true,
+ 0x2de0...0x2dff => true,
+ 0x302a...0x302d => true,
+ 0x302e...0x302f => true,
+ 0x3099...0x309a => true,
+ 0xa66f => true,
+ 0xa670...0xa672 => true,
+ 0xa674...0xa67d => true,
+ 0xa69e...0xa69f => true,
+ 0xa6f0...0xa6f1 => true,
+ 0xa802 => true,
+ 0xa806 => true,
+ 0xa80b => true,
+ 0xa825...0xa826 => true,
+ 0xa82c => true,
+ 0xa8c4...0xa8c5 => true,
+ 0xa8e0...0xa8f1 => true,
+ 0xa8ff => true,
+ 0xa926...0xa92d => true,
+ 0xa947...0xa951 => true,
+ 0xa980...0xa982 => true,
+ 0xa9b3 => true,
+ 0xa9b6...0xa9b9 => true,
+ 0xa9bc...0xa9bd => true,
+ 0xa9e5 => true,
+ 0xaa29...0xaa2e => true,
+ 0xaa31...0xaa32 => true,
+ 0xaa35...0xaa36 => true,
+ 0xaa43 => true,
+ 0xaa4c => true,
+ 0xaa7c => true,
+ 0xaab0 => true,
+ 0xaab2...0xaab4 => true,
+ 0xaab7...0xaab8 => true,
+ 0xaabe...0xaabf => true,
+ 0xaac1 => true,
+ 0xaaec...0xaaed => true,
+ 0xaaf6 => true,
+ 0xabe5 => true,
+ 0xabe8 => true,
+ 0xabed => true,
+ 0xfb1e => true,
+ 0xfe00...0xfe0f => true,
+ 0xfe20...0xfe2f => true,
+ 0xff9e...0xff9f => true,
+ 0x101fd => true,
+ 0x102e0 => true,
+ 0x10376...0x1037a => true,
+ 0x10a01...0x10a03 => true,
+ 0x10a05...0x10a06 => true,
+ 0x10a0c...0x10a0f => true,
+ 0x10a38...0x10a3a => true,
+ 0x10a3f => true,
+ 0x10ae5...0x10ae6 => true,
+ 0x10d24...0x10d27 => true,
+ 0x10eab...0x10eac => true,
+ 0x10efd...0x10eff => true,
+ 0x10f46...0x10f50 => true,
+ 0x10f82...0x10f85 => true,
+ 0x11001 => true,
+ 0x11038...0x11046 => true,
+ 0x11070 => true,
+ 0x11073...0x11074 => true,
+ 0x1107f...0x11081 => true,
+ 0x110b3...0x110b6 => true,
+ 0x110b9...0x110ba => true,
+ 0x110c2 => true,
+ 0x11100...0x11102 => true,
+ 0x11127...0x1112b => true,
+ 0x1112d...0x11134 => true,
+ 0x11173 => true,
+ 0x11180...0x11181 => true,
+ 0x111b6...0x111be => true,
+ 0x111c9...0x111cc => true,
+ 0x111cf => true,
+ 0x1122f...0x11231 => true,
+ 0x11234 => true,
+ 0x11236...0x11237 => true,
+ 0x1123e => true,
+ 0x11241 => true,
+ 0x112df => true,
+ 0x112e3...0x112ea => true,
+ 0x11300...0x11301 => true,
+ 0x1133b...0x1133c => true,
+ 0x1133e => true,
+ 0x11340 => true,
+ 0x11357 => true,
+ 0x11366...0x1136c => true,
+ 0x11370...0x11374 => true,
+ 0x11438...0x1143f => true,
+ 0x11442...0x11444 => true,
+ 0x11446 => true,
+ 0x1145e => true,
+ 0x114b0 => true,
+ 0x114b3...0x114b8 => true,
+ 0x114ba => true,
+ 0x114bd => true,
+ 0x114bf...0x114c0 => true,
+ 0x114c2...0x114c3 => true,
+ 0x115af => true,
+ 0x115b2...0x115b5 => true,
+ 0x115bc...0x115bd => true,
+ 0x115bf...0x115c0 => true,
+ 0x115dc...0x115dd => true,
+ 0x11633...0x1163a => true,
+ 0x1163d => true,
+ 0x1163f...0x11640 => true,
+ 0x116ab => true,
+ 0x116ad => true,
+ 0x116b0...0x116b5 => true,
+ 0x116b7 => true,
+ 0x1171d...0x1171f => true,
+ 0x11722...0x11725 => true,
+ 0x11727...0x1172b => true,
+ 0x1182f...0x11837 => true,
+ 0x11839...0x1183a => true,
+ 0x11930 => true,
+ 0x1193b...0x1193c => true,
+ 0x1193e => true,
+ 0x11943 => true,
+ 0x119d4...0x119d7 => true,
+ 0x119da...0x119db => true,
+ 0x119e0 => true,
+ 0x11a01...0x11a0a => true,
+ 0x11a33...0x11a38 => true,
+ 0x11a3b...0x11a3e => true,
+ 0x11a47 => true,
+ 0x11a51...0x11a56 => true,
+ 0x11a59...0x11a5b => true,
+ 0x11a8a...0x11a96 => true,
+ 0x11a98...0x11a99 => true,
+ 0x11c30...0x11c36 => true,
+ 0x11c38...0x11c3d => true,
+ 0x11c3f => true,
+ 0x11c92...0x11ca7 => true,
+ 0x11caa...0x11cb0 => true,
+ 0x11cb2...0x11cb3 => true,
+ 0x11cb5...0x11cb6 => true,
+ 0x11d31...0x11d36 => true,
+ 0x11d3a => true,
+ 0x11d3c...0x11d3d => true,
+ 0x11d3f...0x11d45 => true,
+ 0x11d47 => true,
+ 0x11d90...0x11d91 => true,
+ 0x11d95 => true,
+ 0x11d97 => true,
+ 0x11ef3...0x11ef4 => true,
+ 0x11f00...0x11f01 => true,
+ 0x11f36...0x11f3a => true,
+ 0x11f40 => true,
+ 0x11f42 => true,
+ 0x13440 => true,
+ 0x13447...0x13455 => true,
+ 0x16af0...0x16af4 => true,
+ 0x16b30...0x16b36 => true,
+ 0x16f4f => true,
+ 0x16f8f...0x16f92 => true,
+ 0x16fe4 => true,
+ 0x1bc9d...0x1bc9e => true,
+ 0x1cf00...0x1cf2d => true,
+ 0x1cf30...0x1cf46 => true,
+ 0x1d165 => true,
+ 0x1d167...0x1d169 => true,
+ 0x1d16e...0x1d172 => true,
+ 0x1d17b...0x1d182 => true,
+ 0x1d185...0x1d18b => true,
+ 0x1d1aa...0x1d1ad => true,
+ 0x1d242...0x1d244 => true,
+ 0x1da00...0x1da36 => true,
+ 0x1da3b...0x1da6c => true,
+ 0x1da75 => true,
+ 0x1da84 => true,
+ 0x1da9b...0x1da9f => true,
+ 0x1daa1...0x1daaf => true,
+ 0x1e000...0x1e006 => true,
+ 0x1e008...0x1e018 => true,
+ 0x1e01b...0x1e021 => true,
+ 0x1e023...0x1e024 => true,
+ 0x1e026...0x1e02a => true,
+ 0x1e08f => true,
+ 0x1e130...0x1e136 => true,
+ 0x1e2ae => true,
+ 0x1e2ec...0x1e2ef => true,
+ 0x1e4ec...0x1e4ef => true,
+ 0x1e8d0...0x1e8d6 => true,
+ 0x1e944...0x1e94a => true,
+ 0xe0020...0xe007f => true,
+ 0xe0100...0xe01ef => true,
+ else => false,
+ };
+}
+
+pub fn isGraphemeBase(cp: u21) bool {
+ if (cp < 0x20 or cp > 0x323af) return false;
+
+ return switch (cp) {
+ 0x20 => true,
+ 0x21...0x23 => true,
+ 0x24 => true,
+ 0x25...0x27 => true,
+ 0x28 => true,
+ 0x29 => true,
+ 0x2a => true,
+ 0x2b => true,
+ 0x2c => true,
+ 0x2d => true,
+ 0x2e...0x2f => true,
+ 0x30...0x39 => true,
+ 0x3a...0x3b => true,
+ 0x3c...0x3e => true,
+ 0x3f...0x40 => true,
+ 0x41...0x5a => true,
+ 0x5b => true,
+ 0x5c => true,
+ 0x5d => true,
+ 0x5e => true,
+ 0x5f => true,
+ 0x60 => true,
+ 0x61...0x7a => true,
+ 0x7b => true,
+ 0x7c => true,
+ 0x7d => true,
+ 0x7e => true,
+ 0xa0 => true,
+ 0xa1 => true,
+ 0xa2...0xa5 => true,
+ 0xa6 => true,
+ 0xa7 => true,
+ 0xa8 => true,
+ 0xa9 => true,
+ 0xaa => true,
+ 0xab => true,
+ 0xac => true,
+ 0xae => true,
+ 0xaf => true,
+ 0xb0 => true,
+ 0xb1 => true,
+ 0xb2...0xb3 => true,
+ 0xb4 => true,
+ 0xb5 => true,
+ 0xb6...0xb7 => true,
+ 0xb8 => true,
+ 0xb9 => true,
+ 0xba => true,
+ 0xbb => true,
+ 0xbc...0xbe => true,
+ 0xbf => true,
+ 0xc0...0xd6 => true,
+ 0xd7 => true,
+ 0xd8...0xf6 => true,
+ 0xf7 => true,
+ 0xf8...0x1ba => true,
+ 0x1bb => true,
+ 0x1bc...0x1bf => true,
+ 0x1c0...0x1c3 => true,
+ 0x1c4...0x293 => true,
+ 0x294 => true,
+ 0x295...0x2af => true,
+ 0x2b0...0x2c1 => true,
+ 0x2c2...0x2c5 => true,
+ 0x2c6...0x2d1 => true,
+ 0x2d2...0x2df => true,
+ 0x2e0...0x2e4 => true,
+ 0x2e5...0x2eb => true,
+ 0x2ec => true,
+ 0x2ed => true,
+ 0x2ee => true,
+ 0x2ef...0x2ff => true,
+ 0x370...0x373 => true,
+ 0x374 => true,
+ 0x375 => true,
+ 0x376...0x377 => true,
+ 0x37a => true,
+ 0x37b...0x37d => true,
+ 0x37e => true,
+ 0x37f => true,
+ 0x384...0x385 => true,
+ 0x386 => true,
+ 0x387 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x3a1 => true,
+ 0x3a3...0x3f5 => true,
+ 0x3f6 => true,
+ 0x3f7...0x481 => true,
+ 0x482 => true,
+ 0x48a...0x52f => true,
+ 0x531...0x556 => true,
+ 0x559 => true,
+ 0x55a...0x55f => true,
+ 0x560...0x588 => true,
+ 0x589 => true,
+ 0x58a => true,
+ 0x58d...0x58e => true,
+ 0x58f => true,
+ 0x5be => true,
+ 0x5c0 => true,
+ 0x5c3 => true,
+ 0x5c6 => true,
+ 0x5d0...0x5ea => true,
+ 0x5ef...0x5f2 => true,
+ 0x5f3...0x5f4 => true,
+ 0x606...0x608 => true,
+ 0x609...0x60a => true,
+ 0x60b => true,
+ 0x60c...0x60d => true,
+ 0x60e...0x60f => true,
+ 0x61b => true,
+ 0x61d...0x61f => true,
+ 0x620...0x63f => true,
+ 0x640 => true,
+ 0x641...0x64a => true,
+ 0x660...0x669 => true,
+ 0x66a...0x66d => true,
+ 0x66e...0x66f => true,
+ 0x671...0x6d3 => true,
+ 0x6d4 => true,
+ 0x6d5 => true,
+ 0x6de => true,
+ 0x6e5...0x6e6 => true,
+ 0x6e9 => true,
+ 0x6ee...0x6ef => true,
+ 0x6f0...0x6f9 => true,
+ 0x6fa...0x6fc => true,
+ 0x6fd...0x6fe => true,
+ 0x6ff => true,
+ 0x700...0x70d => true,
+ 0x710 => true,
+ 0x712...0x72f => true,
+ 0x74d...0x7a5 => true,
+ 0x7b1 => true,
+ 0x7c0...0x7c9 => true,
+ 0x7ca...0x7ea => true,
+ 0x7f4...0x7f5 => true,
+ 0x7f6 => true,
+ 0x7f7...0x7f9 => true,
+ 0x7fa => true,
+ 0x7fe...0x7ff => true,
+ 0x800...0x815 => true,
+ 0x81a => true,
+ 0x824 => true,
+ 0x828 => true,
+ 0x830...0x83e => true,
+ 0x840...0x858 => true,
+ 0x85e => true,
+ 0x860...0x86a => true,
+ 0x870...0x887 => true,
+ 0x888 => true,
+ 0x889...0x88e => true,
+ 0x8a0...0x8c8 => true,
+ 0x8c9 => true,
+ 0x903 => true,
+ 0x904...0x939 => true,
+ 0x93b => true,
+ 0x93d => true,
+ 0x93e...0x940 => true,
+ 0x949...0x94c => true,
+ 0x94e...0x94f => true,
+ 0x950 => true,
+ 0x958...0x961 => true,
+ 0x964...0x965 => true,
+ 0x966...0x96f => true,
+ 0x970 => true,
+ 0x971 => true,
+ 0x972...0x980 => true,
+ 0x982...0x983 => true,
+ 0x985...0x98c => true,
+ 0x98f...0x990 => true,
+ 0x993...0x9a8 => true,
+ 0x9aa...0x9b0 => true,
+ 0x9b2 => true,
+ 0x9b6...0x9b9 => true,
+ 0x9bd => true,
+ 0x9bf...0x9c0 => true,
+ 0x9c7...0x9c8 => true,
+ 0x9cb...0x9cc => true,
+ 0x9ce => true,
+ 0x9dc...0x9dd => true,
+ 0x9df...0x9e1 => true,
+ 0x9e6...0x9ef => true,
+ 0x9f0...0x9f1 => true,
+ 0x9f2...0x9f3 => true,
+ 0x9f4...0x9f9 => true,
+ 0x9fa => true,
+ 0x9fb => true,
+ 0x9fc => true,
+ 0x9fd => true,
+ 0xa03 => true,
+ 0xa05...0xa0a => true,
+ 0xa0f...0xa10 => true,
+ 0xa13...0xa28 => true,
+ 0xa2a...0xa30 => true,
+ 0xa32...0xa33 => true,
+ 0xa35...0xa36 => true,
+ 0xa38...0xa39 => true,
+ 0xa3e...0xa40 => true,
+ 0xa59...0xa5c => true,
+ 0xa5e => true,
+ 0xa66...0xa6f => true,
+ 0xa72...0xa74 => true,
+ 0xa76 => true,
+ 0xa83 => true,
+ 0xa85...0xa8d => true,
+ 0xa8f...0xa91 => true,
+ 0xa93...0xaa8 => true,
+ 0xaaa...0xab0 => true,
+ 0xab2...0xab3 => true,
+ 0xab5...0xab9 => true,
+ 0xabd => true,
+ 0xabe...0xac0 => true,
+ 0xac9 => true,
+ 0xacb...0xacc => true,
+ 0xad0 => true,
+ 0xae0...0xae1 => true,
+ 0xae6...0xaef => true,
+ 0xaf0 => true,
+ 0xaf1 => true,
+ 0xaf9 => true,
+ 0xb02...0xb03 => true,
+ 0xb05...0xb0c => true,
+ 0xb0f...0xb10 => true,
+ 0xb13...0xb28 => true,
+ 0xb2a...0xb30 => true,
+ 0xb32...0xb33 => true,
+ 0xb35...0xb39 => true,
+ 0xb3d => true,
+ 0xb40 => true,
+ 0xb47...0xb48 => true,
+ 0xb4b...0xb4c => true,
+ 0xb5c...0xb5d => true,
+ 0xb5f...0xb61 => true,
+ 0xb66...0xb6f => true,
+ 0xb70 => true,
+ 0xb71 => true,
+ 0xb72...0xb77 => true,
+ 0xb83 => true,
+ 0xb85...0xb8a => true,
+ 0xb8e...0xb90 => true,
+ 0xb92...0xb95 => true,
+ 0xb99...0xb9a => true,
+ 0xb9c => true,
+ 0xb9e...0xb9f => true,
+ 0xba3...0xba4 => true,
+ 0xba8...0xbaa => true,
+ 0xbae...0xbb9 => true,
+ 0xbbf => true,
+ 0xbc1...0xbc2 => true,
+ 0xbc6...0xbc8 => true,
+ 0xbca...0xbcc => true,
+ 0xbd0 => true,
+ 0xbe6...0xbef => true,
+ 0xbf0...0xbf2 => true,
+ 0xbf3...0xbf8 => true,
+ 0xbf9 => true,
+ 0xbfa => true,
+ 0xc01...0xc03 => true,
+ 0xc05...0xc0c => true,
+ 0xc0e...0xc10 => true,
+ 0xc12...0xc28 => true,
+ 0xc2a...0xc39 => true,
+ 0xc3d => true,
+ 0xc41...0xc44 => true,
+ 0xc58...0xc5a => true,
+ 0xc5d => true,
+ 0xc60...0xc61 => true,
+ 0xc66...0xc6f => true,
+ 0xc77 => true,
+ 0xc78...0xc7e => true,
+ 0xc7f => true,
+ 0xc80 => true,
+ 0xc82...0xc83 => true,
+ 0xc84 => true,
+ 0xc85...0xc8c => true,
+ 0xc8e...0xc90 => true,
+ 0xc92...0xca8 => true,
+ 0xcaa...0xcb3 => true,
+ 0xcb5...0xcb9 => true,
+ 0xcbd => true,
+ 0xcbe => true,
+ 0xcc0...0xcc1 => true,
+ 0xcc3...0xcc4 => true,
+ 0xcc7...0xcc8 => true,
+ 0xcca...0xccb => true,
+ 0xcdd...0xcde => true,
+ 0xce0...0xce1 => true,
+ 0xce6...0xcef => true,
+ 0xcf1...0xcf2 => true,
+ 0xcf3 => true,
+ 0xd02...0xd03 => true,
+ 0xd04...0xd0c => true,
+ 0xd0e...0xd10 => true,
+ 0xd12...0xd3a => true,
+ 0xd3d => true,
+ 0xd3f...0xd40 => true,
+ 0xd46...0xd48 => true,
+ 0xd4a...0xd4c => true,
+ 0xd4e => true,
+ 0xd4f => true,
+ 0xd54...0xd56 => true,
+ 0xd58...0xd5e => true,
+ 0xd5f...0xd61 => true,
+ 0xd66...0xd6f => true,
+ 0xd70...0xd78 => true,
+ 0xd79 => true,
+ 0xd7a...0xd7f => true,
+ 0xd82...0xd83 => true,
+ 0xd85...0xd96 => true,
+ 0xd9a...0xdb1 => true,
+ 0xdb3...0xdbb => true,
+ 0xdbd => true,
+ 0xdc0...0xdc6 => true,
+ 0xdd0...0xdd1 => true,
+ 0xdd8...0xdde => true,
+ 0xde6...0xdef => true,
+ 0xdf2...0xdf3 => true,
+ 0xdf4 => true,
+ 0xe01...0xe30 => true,
+ 0xe32...0xe33 => true,
+ 0xe3f => true,
+ 0xe40...0xe45 => true,
+ 0xe46 => true,
+ 0xe4f => true,
+ 0xe50...0xe59 => true,
+ 0xe5a...0xe5b => true,
+ 0xe81...0xe82 => true,
+ 0xe84 => true,
+ 0xe86...0xe8a => true,
+ 0xe8c...0xea3 => true,
+ 0xea5 => true,
+ 0xea7...0xeb0 => true,
+ 0xeb2...0xeb3 => true,
+ 0xebd => true,
+ 0xec0...0xec4 => true,
+ 0xec6 => true,
+ 0xed0...0xed9 => true,
+ 0xedc...0xedf => true,
+ 0xf00 => true,
+ 0xf01...0xf03 => true,
+ 0xf04...0xf12 => true,
+ 0xf13 => true,
+ 0xf14 => true,
+ 0xf15...0xf17 => true,
+ 0xf1a...0xf1f => true,
+ 0xf20...0xf29 => true,
+ 0xf2a...0xf33 => true,
+ 0xf34 => true,
+ 0xf36 => true,
+ 0xf38 => true,
+ 0xf3a => true,
+ 0xf3b => true,
+ 0xf3c => true,
+ 0xf3d => true,
+ 0xf3e...0xf3f => true,
+ 0xf40...0xf47 => true,
+ 0xf49...0xf6c => true,
+ 0xf7f => true,
+ 0xf85 => true,
+ 0xf88...0xf8c => true,
+ 0xfbe...0xfc5 => true,
+ 0xfc7...0xfcc => true,
+ 0xfce...0xfcf => true,
+ 0xfd0...0xfd4 => true,
+ 0xfd5...0xfd8 => true,
+ 0xfd9...0xfda => true,
+ 0x1000...0x102a => true,
+ 0x102b...0x102c => true,
+ 0x1031 => true,
+ 0x1038 => true,
+ 0x103b...0x103c => true,
+ 0x103f => true,
+ 0x1040...0x1049 => true,
+ 0x104a...0x104f => true,
+ 0x1050...0x1055 => true,
+ 0x1056...0x1057 => true,
+ 0x105a...0x105d => true,
+ 0x1061 => true,
+ 0x1062...0x1064 => true,
+ 0x1065...0x1066 => true,
+ 0x1067...0x106d => true,
+ 0x106e...0x1070 => true,
+ 0x1075...0x1081 => true,
+ 0x1083...0x1084 => true,
+ 0x1087...0x108c => true,
+ 0x108e => true,
+ 0x108f => true,
+ 0x1090...0x1099 => true,
+ 0x109a...0x109c => true,
+ 0x109e...0x109f => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x10d0...0x10fa => true,
+ 0x10fb => true,
+ 0x10fc => true,
+ 0x10fd...0x10ff => true,
+ 0x1100...0x1248 => true,
+ 0x124a...0x124d => true,
+ 0x1250...0x1256 => true,
+ 0x1258 => true,
+ 0x125a...0x125d => true,
+ 0x1260...0x1288 => true,
+ 0x128a...0x128d => true,
+ 0x1290...0x12b0 => true,
+ 0x12b2...0x12b5 => true,
+ 0x12b8...0x12be => true,
+ 0x12c0 => true,
+ 0x12c2...0x12c5 => true,
+ 0x12c8...0x12d6 => true,
+ 0x12d8...0x1310 => true,
+ 0x1312...0x1315 => true,
+ 0x1318...0x135a => true,
+ 0x1360...0x1368 => true,
+ 0x1369...0x137c => true,
+ 0x1380...0x138f => true,
+ 0x1390...0x1399 => true,
+ 0x13a0...0x13f5 => true,
+ 0x13f8...0x13fd => true,
+ 0x1400 => true,
+ 0x1401...0x166c => true,
+ 0x166d => true,
+ 0x166e => true,
+ 0x166f...0x167f => true,
+ 0x1680 => true,
+ 0x1681...0x169a => true,
+ 0x169b => true,
+ 0x169c => true,
+ 0x16a0...0x16ea => true,
+ 0x16eb...0x16ed => true,
+ 0x16ee...0x16f0 => true,
+ 0x16f1...0x16f8 => true,
+ 0x1700...0x1711 => true,
+ 0x1715 => true,
+ 0x171f...0x1731 => true,
+ 0x1734 => true,
+ 0x1735...0x1736 => true,
+ 0x1740...0x1751 => true,
+ 0x1760...0x176c => true,
+ 0x176e...0x1770 => true,
+ 0x1780...0x17b3 => true,
+ 0x17b6 => true,
+ 0x17be...0x17c5 => true,
+ 0x17c7...0x17c8 => true,
+ 0x17d4...0x17d6 => true,
+ 0x17d7 => true,
+ 0x17d8...0x17da => true,
+ 0x17db => true,
+ 0x17dc => true,
+ 0x17e0...0x17e9 => true,
+ 0x17f0...0x17f9 => true,
+ 0x1800...0x1805 => true,
+ 0x1806 => true,
+ 0x1807...0x180a => true,
+ 0x1810...0x1819 => true,
+ 0x1820...0x1842 => true,
+ 0x1843 => true,
+ 0x1844...0x1878 => true,
+ 0x1880...0x1884 => true,
+ 0x1887...0x18a8 => true,
+ 0x18aa => true,
+ 0x18b0...0x18f5 => true,
+ 0x1900...0x191e => true,
+ 0x1923...0x1926 => true,
+ 0x1929...0x192b => true,
+ 0x1930...0x1931 => true,
+ 0x1933...0x1938 => true,
+ 0x1940 => true,
+ 0x1944...0x1945 => true,
+ 0x1946...0x194f => true,
+ 0x1950...0x196d => true,
+ 0x1970...0x1974 => true,
+ 0x1980...0x19ab => true,
+ 0x19b0...0x19c9 => true,
+ 0x19d0...0x19d9 => true,
+ 0x19da => true,
+ 0x19de...0x19ff => true,
+ 0x1a00...0x1a16 => true,
+ 0x1a19...0x1a1a => true,
+ 0x1a1e...0x1a1f => true,
+ 0x1a20...0x1a54 => true,
+ 0x1a55 => true,
+ 0x1a57 => true,
+ 0x1a61 => true,
+ 0x1a63...0x1a64 => true,
+ 0x1a6d...0x1a72 => true,
+ 0x1a80...0x1a89 => true,
+ 0x1a90...0x1a99 => true,
+ 0x1aa0...0x1aa6 => true,
+ 0x1aa7 => true,
+ 0x1aa8...0x1aad => true,
+ 0x1b04 => true,
+ 0x1b05...0x1b33 => true,
+ 0x1b3b => true,
+ 0x1b3d...0x1b41 => true,
+ 0x1b43...0x1b44 => true,
+ 0x1b45...0x1b4c => true,
+ 0x1b50...0x1b59 => true,
+ 0x1b5a...0x1b60 => true,
+ 0x1b61...0x1b6a => true,
+ 0x1b74...0x1b7c => true,
+ 0x1b7d...0x1b7e => true,
+ 0x1b82 => true,
+ 0x1b83...0x1ba0 => true,
+ 0x1ba1 => true,
+ 0x1ba6...0x1ba7 => true,
+ 0x1baa => true,
+ 0x1bae...0x1baf => true,
+ 0x1bb0...0x1bb9 => true,
+ 0x1bba...0x1be5 => true,
+ 0x1be7 => true,
+ 0x1bea...0x1bec => true,
+ 0x1bee => true,
+ 0x1bf2...0x1bf3 => true,
+ 0x1bfc...0x1bff => true,
+ 0x1c00...0x1c23 => true,
+ 0x1c24...0x1c2b => true,
+ 0x1c34...0x1c35 => true,
+ 0x1c3b...0x1c3f => true,
+ 0x1c40...0x1c49 => true,
+ 0x1c4d...0x1c4f => true,
+ 0x1c50...0x1c59 => true,
+ 0x1c5a...0x1c77 => true,
+ 0x1c78...0x1c7d => true,
+ 0x1c7e...0x1c7f => true,
+ 0x1c80...0x1c88 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1cc0...0x1cc7 => true,
+ 0x1cd3 => true,
+ 0x1ce1 => true,
+ 0x1ce9...0x1cec => true,
+ 0x1cee...0x1cf3 => true,
+ 0x1cf5...0x1cf6 => true,
+ 0x1cf7 => true,
+ 0x1cfa => true,
+ 0x1d00...0x1d2b => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d6b...0x1d77 => true,
+ 0x1d78 => true,
+ 0x1d79...0x1d9a => true,
+ 0x1d9b...0x1dbf => true,
+ 0x1e00...0x1f15 => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f20...0x1f45 => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f...0x1f7d => true,
+ 0x1f80...0x1fb4 => true,
+ 0x1fb6...0x1fbc => true,
+ 0x1fbd => true,
+ 0x1fbe => true,
+ 0x1fbf...0x1fc1 => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fcc => true,
+ 0x1fcd...0x1fcf => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fdb => true,
+ 0x1fdd...0x1fdf => true,
+ 0x1fe0...0x1fec => true,
+ 0x1fed...0x1fef => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ffc => true,
+ 0x1ffd...0x1ffe => true,
+ 0x2000...0x200a => true,
+ 0x2010...0x2015 => true,
+ 0x2016...0x2017 => true,
+ 0x2018 => true,
+ 0x2019 => true,
+ 0x201a => true,
+ 0x201b...0x201c => true,
+ 0x201d => true,
+ 0x201e => true,
+ 0x201f => true,
+ 0x2020...0x2027 => true,
+ 0x202f => true,
+ 0x2030...0x2038 => true,
+ 0x2039 => true,
+ 0x203a => true,
+ 0x203b...0x203e => true,
+ 0x203f...0x2040 => true,
+ 0x2041...0x2043 => true,
+ 0x2044 => true,
+ 0x2045 => true,
+ 0x2046 => true,
+ 0x2047...0x2051 => true,
+ 0x2052 => true,
+ 0x2053 => true,
+ 0x2054 => true,
+ 0x2055...0x205e => true,
+ 0x205f => true,
+ 0x2070 => true,
+ 0x2071 => true,
+ 0x2074...0x2079 => true,
+ 0x207a...0x207c => true,
+ 0x207d => true,
+ 0x207e => true,
+ 0x207f => true,
+ 0x2080...0x2089 => true,
+ 0x208a...0x208c => true,
+ 0x208d => true,
+ 0x208e => true,
+ 0x2090...0x209c => true,
+ 0x20a0...0x20c0 => true,
+ 0x2100...0x2101 => true,
+ 0x2102 => true,
+ 0x2103...0x2106 => true,
+ 0x2107 => true,
+ 0x2108...0x2109 => true,
+ 0x210a...0x2113 => true,
+ 0x2114 => true,
+ 0x2115 => true,
+ 0x2116...0x2117 => true,
+ 0x2118 => true,
+ 0x2119...0x211d => true,
+ 0x211e...0x2123 => true,
+ 0x2124 => true,
+ 0x2125 => true,
+ 0x2126 => true,
+ 0x2127 => true,
+ 0x2128 => true,
+ 0x2129 => true,
+ 0x212a...0x212d => true,
+ 0x212e => true,
+ 0x212f...0x2134 => true,
+ 0x2135...0x2138 => true,
+ 0x2139 => true,
+ 0x213a...0x213b => true,
+ 0x213c...0x213f => true,
+ 0x2140...0x2144 => true,
+ 0x2145...0x2149 => true,
+ 0x214a => true,
+ 0x214b => true,
+ 0x214c...0x214d => true,
+ 0x214e => true,
+ 0x214f => true,
+ 0x2150...0x215f => true,
+ 0x2160...0x2182 => true,
+ 0x2183...0x2184 => true,
+ 0x2185...0x2188 => true,
+ 0x2189 => true,
+ 0x218a...0x218b => true,
+ 0x2190...0x2194 => true,
+ 0x2195...0x2199 => true,
+ 0x219a...0x219b => true,
+ 0x219c...0x219f => true,
+ 0x21a0 => true,
+ 0x21a1...0x21a2 => true,
+ 0x21a3 => true,
+ 0x21a4...0x21a5 => true,
+ 0x21a6 => true,
+ 0x21a7...0x21ad => true,
+ 0x21ae => true,
+ 0x21af...0x21cd => true,
+ 0x21ce...0x21cf => true,
+ 0x21d0...0x21d1 => true,
+ 0x21d2 => true,
+ 0x21d3 => true,
+ 0x21d4 => true,
+ 0x21d5...0x21f3 => true,
+ 0x21f4...0x22ff => true,
+ 0x2300...0x2307 => true,
+ 0x2308 => true,
+ 0x2309 => true,
+ 0x230a => true,
+ 0x230b => true,
+ 0x230c...0x231f => true,
+ 0x2320...0x2321 => true,
+ 0x2322...0x2328 => true,
+ 0x2329 => true,
+ 0x232a => true,
+ 0x232b...0x237b => true,
+ 0x237c => true,
+ 0x237d...0x239a => true,
+ 0x239b...0x23b3 => true,
+ 0x23b4...0x23db => true,
+ 0x23dc...0x23e1 => true,
+ 0x23e2...0x2426 => true,
+ 0x2440...0x244a => true,
+ 0x2460...0x249b => true,
+ 0x249c...0x24e9 => true,
+ 0x24ea...0x24ff => true,
+ 0x2500...0x25b6 => true,
+ 0x25b7 => true,
+ 0x25b8...0x25c0 => true,
+ 0x25c1 => true,
+ 0x25c2...0x25f7 => true,
+ 0x25f8...0x25ff => true,
+ 0x2600...0x266e => true,
+ 0x266f => true,
+ 0x2670...0x2767 => true,
+ 0x2768 => true,
+ 0x2769 => true,
+ 0x276a => true,
+ 0x276b => true,
+ 0x276c => true,
+ 0x276d => true,
+ 0x276e => true,
+ 0x276f => true,
+ 0x2770 => true,
+ 0x2771 => true,
+ 0x2772 => true,
+ 0x2773 => true,
+ 0x2774 => true,
+ 0x2775 => true,
+ 0x2776...0x2793 => true,
+ 0x2794...0x27bf => true,
+ 0x27c0...0x27c4 => true,
+ 0x27c5 => true,
+ 0x27c6 => true,
+ 0x27c7...0x27e5 => true,
+ 0x27e6 => true,
+ 0x27e7 => true,
+ 0x27e8 => true,
+ 0x27e9 => true,
+ 0x27ea => true,
+ 0x27eb => true,
+ 0x27ec => true,
+ 0x27ed => true,
+ 0x27ee => true,
+ 0x27ef => true,
+ 0x27f0...0x27ff => true,
+ 0x2800...0x28ff => true,
+ 0x2900...0x2982 => true,
+ 0x2983 => true,
+ 0x2984 => true,
+ 0x2985 => true,
+ 0x2986 => true,
+ 0x2987 => true,
+ 0x2988 => true,
+ 0x2989 => true,
+ 0x298a => true,
+ 0x298b => true,
+ 0x298c => true,
+ 0x298d => true,
+ 0x298e => true,
+ 0x298f => true,
+ 0x2990 => true,
+ 0x2991 => true,
+ 0x2992 => true,
+ 0x2993 => true,
+ 0x2994 => true,
+ 0x2995 => true,
+ 0x2996 => true,
+ 0x2997 => true,
+ 0x2998 => true,
+ 0x2999...0x29d7 => true,
+ 0x29d8 => true,
+ 0x29d9 => true,
+ 0x29da => true,
+ 0x29db => true,
+ 0x29dc...0x29fb => true,
+ 0x29fc => true,
+ 0x29fd => true,
+ 0x29fe...0x2aff => true,
+ 0x2b00...0x2b2f => true,
+ 0x2b30...0x2b44 => true,
+ 0x2b45...0x2b46 => true,
+ 0x2b47...0x2b4c => true,
+ 0x2b4d...0x2b73 => true,
+ 0x2b76...0x2b95 => true,
+ 0x2b97...0x2bff => true,
+ 0x2c00...0x2c7b => true,
+ 0x2c7c...0x2c7d => true,
+ 0x2c7e...0x2ce4 => true,
+ 0x2ce5...0x2cea => true,
+ 0x2ceb...0x2cee => true,
+ 0x2cf2...0x2cf3 => true,
+ 0x2cf9...0x2cfc => true,
+ 0x2cfd => true,
+ 0x2cfe...0x2cff => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0x2d30...0x2d67 => true,
+ 0x2d6f => true,
+ 0x2d70 => true,
+ 0x2d80...0x2d96 => true,
+ 0x2da0...0x2da6 => true,
+ 0x2da8...0x2dae => true,
+ 0x2db0...0x2db6 => true,
+ 0x2db8...0x2dbe => true,
+ 0x2dc0...0x2dc6 => true,
+ 0x2dc8...0x2dce => true,
+ 0x2dd0...0x2dd6 => true,
+ 0x2dd8...0x2dde => true,
+ 0x2e00...0x2e01 => true,
+ 0x2e02 => true,
+ 0x2e03 => true,
+ 0x2e04 => true,
+ 0x2e05 => true,
+ 0x2e06...0x2e08 => true,
+ 0x2e09 => true,
+ 0x2e0a => true,
+ 0x2e0b => true,
+ 0x2e0c => true,
+ 0x2e0d => true,
+ 0x2e0e...0x2e16 => true,
+ 0x2e17 => true,
+ 0x2e18...0x2e19 => true,
+ 0x2e1a => true,
+ 0x2e1b => true,
+ 0x2e1c => true,
+ 0x2e1d => true,
+ 0x2e1e...0x2e1f => true,
+ 0x2e20 => true,
+ 0x2e21 => true,
+ 0x2e22 => true,
+ 0x2e23 => true,
+ 0x2e24 => true,
+ 0x2e25 => true,
+ 0x2e26 => true,
+ 0x2e27 => true,
+ 0x2e28 => true,
+ 0x2e29 => true,
+ 0x2e2a...0x2e2e => true,
+ 0x2e2f => true,
+ 0x2e30...0x2e39 => true,
+ 0x2e3a...0x2e3b => true,
+ 0x2e3c...0x2e3f => true,
+ 0x2e40 => true,
+ 0x2e41 => true,
+ 0x2e42 => true,
+ 0x2e43...0x2e4f => true,
+ 0x2e50...0x2e51 => true,
+ 0x2e52...0x2e54 => true,
+ 0x2e55 => true,
+ 0x2e56 => true,
+ 0x2e57 => true,
+ 0x2e58 => true,
+ 0x2e59 => true,
+ 0x2e5a => true,
+ 0x2e5b => true,
+ 0x2e5c => true,
+ 0x2e5d => true,
+ 0x2e80...0x2e99 => true,
+ 0x2e9b...0x2ef3 => true,
+ 0x2f00...0x2fd5 => true,
+ 0x2ff0...0x2ffb => true,
+ 0x3000 => true,
+ 0x3001...0x3003 => true,
+ 0x3004 => true,
+ 0x3005 => true,
+ 0x3006 => true,
+ 0x3007 => true,
+ 0x3008 => true,
+ 0x3009 => true,
+ 0x300a => true,
+ 0x300b => true,
+ 0x300c => true,
+ 0x300d => true,
+ 0x300e => true,
+ 0x300f => true,
+ 0x3010 => true,
+ 0x3011 => true,
+ 0x3012...0x3013 => true,
+ 0x3014 => true,
+ 0x3015 => true,
+ 0x3016 => true,
+ 0x3017 => true,
+ 0x3018 => true,
+ 0x3019 => true,
+ 0x301a => true,
+ 0x301b => true,
+ 0x301c => true,
+ 0x301d => true,
+ 0x301e...0x301f => true,
+ 0x3020 => true,
+ 0x3021...0x3029 => true,
+ 0x3030 => true,
+ 0x3031...0x3035 => true,
+ 0x3036...0x3037 => true,
+ 0x3038...0x303a => true,
+ 0x303b => true,
+ 0x303c => true,
+ 0x303d => true,
+ 0x303e...0x303f => true,
+ 0x3041...0x3096 => true,
+ 0x309b...0x309c => true,
+ 0x309d...0x309e => true,
+ 0x309f => true,
+ 0x30a0 => true,
+ 0x30a1...0x30fa => true,
+ 0x30fb => true,
+ 0x30fc...0x30fe => true,
+ 0x30ff => true,
+ 0x3105...0x312f => true,
+ 0x3131...0x318e => true,
+ 0x3190...0x3191 => true,
+ 0x3192...0x3195 => true,
+ 0x3196...0x319f => true,
+ 0x31a0...0x31bf => true,
+ 0x31c0...0x31e3 => true,
+ 0x31f0...0x31ff => true,
+ 0x3200...0x321e => true,
+ 0x3220...0x3229 => true,
+ 0x322a...0x3247 => true,
+ 0x3248...0x324f => true,
+ 0x3250 => true,
+ 0x3251...0x325f => true,
+ 0x3260...0x327f => true,
+ 0x3280...0x3289 => true,
+ 0x328a...0x32b0 => true,
+ 0x32b1...0x32bf => true,
+ 0x32c0...0x33ff => true,
+ 0x3400...0x4dbf => true,
+ 0x4dc0...0x4dff => true,
+ 0x4e00...0xa014 => true,
+ 0xa015 => true,
+ 0xa016...0xa48c => true,
+ 0xa490...0xa4c6 => true,
+ 0xa4d0...0xa4f7 => true,
+ 0xa4f8...0xa4fd => true,
+ 0xa4fe...0xa4ff => true,
+ 0xa500...0xa60b => true,
+ 0xa60c => true,
+ 0xa60d...0xa60f => true,
+ 0xa610...0xa61f => true,
+ 0xa620...0xa629 => true,
+ 0xa62a...0xa62b => true,
+ 0xa640...0xa66d => true,
+ 0xa66e => true,
+ 0xa673 => true,
+ 0xa67e => true,
+ 0xa67f => true,
+ 0xa680...0xa69b => true,
+ 0xa69c...0xa69d => true,
+ 0xa6a0...0xa6e5 => true,
+ 0xa6e6...0xa6ef => true,
+ 0xa6f2...0xa6f7 => true,
+ 0xa700...0xa716 => true,
+ 0xa717...0xa71f => true,
+ 0xa720...0xa721 => true,
+ 0xa722...0xa76f => true,
+ 0xa770 => true,
+ 0xa771...0xa787 => true,
+ 0xa788 => true,
+ 0xa789...0xa78a => true,
+ 0xa78b...0xa78e => true,
+ 0xa78f => true,
+ 0xa790...0xa7ca => true,
+ 0xa7d0...0xa7d1 => true,
+ 0xa7d3 => true,
+ 0xa7d5...0xa7d9 => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f5...0xa7f6 => true,
+ 0xa7f7 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa7fa => true,
+ 0xa7fb...0xa801 => true,
+ 0xa803...0xa805 => true,
+ 0xa807...0xa80a => true,
+ 0xa80c...0xa822 => true,
+ 0xa823...0xa824 => true,
+ 0xa827 => true,
+ 0xa828...0xa82b => true,
+ 0xa830...0xa835 => true,
+ 0xa836...0xa837 => true,
+ 0xa838 => true,
+ 0xa839 => true,
+ 0xa840...0xa873 => true,
+ 0xa874...0xa877 => true,
+ 0xa880...0xa881 => true,
+ 0xa882...0xa8b3 => true,
+ 0xa8b4...0xa8c3 => true,
+ 0xa8ce...0xa8cf => true,
+ 0xa8d0...0xa8d9 => true,
+ 0xa8f2...0xa8f7 => true,
+ 0xa8f8...0xa8fa => true,
+ 0xa8fb => true,
+ 0xa8fc => true,
+ 0xa8fd...0xa8fe => true,
+ 0xa900...0xa909 => true,
+ 0xa90a...0xa925 => true,
+ 0xa92e...0xa92f => true,
+ 0xa930...0xa946 => true,
+ 0xa952...0xa953 => true,
+ 0xa95f => true,
+ 0xa960...0xa97c => true,
+ 0xa983 => true,
+ 0xa984...0xa9b2 => true,
+ 0xa9b4...0xa9b5 => true,
+ 0xa9ba...0xa9bb => true,
+ 0xa9be...0xa9c0 => true,
+ 0xa9c1...0xa9cd => true,
+ 0xa9cf => true,
+ 0xa9d0...0xa9d9 => true,
+ 0xa9de...0xa9df => true,
+ 0xa9e0...0xa9e4 => true,
+ 0xa9e6 => true,
+ 0xa9e7...0xa9ef => true,
+ 0xa9f0...0xa9f9 => true,
+ 0xa9fa...0xa9fe => true,
+ 0xaa00...0xaa28 => true,
+ 0xaa2f...0xaa30 => true,
+ 0xaa33...0xaa34 => true,
+ 0xaa40...0xaa42 => true,
+ 0xaa44...0xaa4b => true,
+ 0xaa4d => true,
+ 0xaa50...0xaa59 => true,
+ 0xaa5c...0xaa5f => true,
+ 0xaa60...0xaa6f => true,
+ 0xaa70 => true,
+ 0xaa71...0xaa76 => true,
+ 0xaa77...0xaa79 => true,
+ 0xaa7a => true,
+ 0xaa7b => true,
+ 0xaa7d => true,
+ 0xaa7e...0xaaaf => true,
+ 0xaab1 => true,
+ 0xaab5...0xaab6 => true,
+ 0xaab9...0xaabd => true,
+ 0xaac0 => true,
+ 0xaac2 => true,
+ 0xaadb...0xaadc => true,
+ 0xaadd => true,
+ 0xaade...0xaadf => true,
+ 0xaae0...0xaaea => true,
+ 0xaaeb => true,
+ 0xaaee...0xaaef => true,
+ 0xaaf0...0xaaf1 => true,
+ 0xaaf2 => true,
+ 0xaaf3...0xaaf4 => true,
+ 0xaaf5 => true,
+ 0xab01...0xab06 => true,
+ 0xab09...0xab0e => true,
+ 0xab11...0xab16 => true,
+ 0xab20...0xab26 => true,
+ 0xab28...0xab2e => true,
+ 0xab30...0xab5a => true,
+ 0xab5b => true,
+ 0xab5c...0xab5f => true,
+ 0xab60...0xab68 => true,
+ 0xab69 => true,
+ 0xab6a...0xab6b => true,
+ 0xab70...0xabbf => true,
+ 0xabc0...0xabe2 => true,
+ 0xabe3...0xabe4 => true,
+ 0xabe6...0xabe7 => true,
+ 0xabe9...0xabea => true,
+ 0xabeb => true,
+ 0xabec => true,
+ 0xabf0...0xabf9 => true,
+ 0xac00...0xd7a3 => true,
+ 0xd7b0...0xd7c6 => true,
+ 0xd7cb...0xd7fb => true,
+ 0xf900...0xfa6d => true,
+ 0xfa70...0xfad9 => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xfb1d => true,
+ 0xfb1f...0xfb28 => true,
+ 0xfb29 => true,
+ 0xfb2a...0xfb36 => true,
+ 0xfb38...0xfb3c => true,
+ 0xfb3e => true,
+ 0xfb40...0xfb41 => true,
+ 0xfb43...0xfb44 => true,
+ 0xfb46...0xfbb1 => true,
+ 0xfbb2...0xfbc2 => true,
+ 0xfbd3...0xfd3d => true,
+ 0xfd3e => true,
+ 0xfd3f => true,
+ 0xfd40...0xfd4f => true,
+ 0xfd50...0xfd8f => true,
+ 0xfd92...0xfdc7 => true,
+ 0xfdcf => true,
+ 0xfdf0...0xfdfb => true,
+ 0xfdfc => true,
+ 0xfdfd...0xfdff => true,
+ 0xfe10...0xfe16 => true,
+ 0xfe17 => true,
+ 0xfe18 => true,
+ 0xfe19 => true,
+ 0xfe30 => true,
+ 0xfe31...0xfe32 => true,
+ 0xfe33...0xfe34 => true,
+ 0xfe35 => true,
+ 0xfe36 => true,
+ 0xfe37 => true,
+ 0xfe38 => true,
+ 0xfe39 => true,
+ 0xfe3a => true,
+ 0xfe3b => true,
+ 0xfe3c => true,
+ 0xfe3d => true,
+ 0xfe3e => true,
+ 0xfe3f => true,
+ 0xfe40 => true,
+ 0xfe41 => true,
+ 0xfe42 => true,
+ 0xfe43 => true,
+ 0xfe44 => true,
+ 0xfe45...0xfe46 => true,
+ 0xfe47 => true,
+ 0xfe48 => true,
+ 0xfe49...0xfe4c => true,
+ 0xfe4d...0xfe4f => true,
+ 0xfe50...0xfe52 => true,
+ 0xfe54...0xfe57 => true,
+ 0xfe58 => true,
+ 0xfe59 => true,
+ 0xfe5a => true,
+ 0xfe5b => true,
+ 0xfe5c => true,
+ 0xfe5d => true,
+ 0xfe5e => true,
+ 0xfe5f...0xfe61 => true,
+ 0xfe62 => true,
+ 0xfe63 => true,
+ 0xfe64...0xfe66 => true,
+ 0xfe68 => true,
+ 0xfe69 => true,
+ 0xfe6a...0xfe6b => true,
+ 0xfe70...0xfe74 => true,
+ 0xfe76...0xfefc => true,
+ 0xff01...0xff03 => true,
+ 0xff04 => true,
+ 0xff05...0xff07 => true,
+ 0xff08 => true,
+ 0xff09 => true,
+ 0xff0a => true,
+ 0xff0b => true,
+ 0xff0c => true,
+ 0xff0d => true,
+ 0xff0e...0xff0f => true,
+ 0xff10...0xff19 => true,
+ 0xff1a...0xff1b => true,
+ 0xff1c...0xff1e => true,
+ 0xff1f...0xff20 => true,
+ 0xff21...0xff3a => true,
+ 0xff3b => true,
+ 0xff3c => true,
+ 0xff3d => true,
+ 0xff3e => true,
+ 0xff3f => true,
+ 0xff40 => true,
+ 0xff41...0xff5a => true,
+ 0xff5b => true,
+ 0xff5c => true,
+ 0xff5d => true,
+ 0xff5e => true,
+ 0xff5f => true,
+ 0xff60 => true,
+ 0xff61 => true,
+ 0xff62 => true,
+ 0xff63 => true,
+ 0xff64...0xff65 => true,
+ 0xff66...0xff6f => true,
+ 0xff70 => true,
+ 0xff71...0xff9d => true,
+ 0xffa0...0xffbe => true,
+ 0xffc2...0xffc7 => true,
+ 0xffca...0xffcf => true,
+ 0xffd2...0xffd7 => true,
+ 0xffda...0xffdc => true,
+ 0xffe0...0xffe1 => true,
+ 0xffe2 => true,
+ 0xffe3 => true,
+ 0xffe4 => true,
+ 0xffe5...0xffe6 => true,
+ 0xffe8 => true,
+ 0xffe9...0xffec => true,
+ 0xffed...0xffee => true,
+ 0xfffc...0xfffd => true,
+ 0x10000...0x1000b => true,
+ 0x1000d...0x10026 => true,
+ 0x10028...0x1003a => true,
+ 0x1003c...0x1003d => true,
+ 0x1003f...0x1004d => true,
+ 0x10050...0x1005d => true,
+ 0x10080...0x100fa => true,
+ 0x10100...0x10102 => true,
+ 0x10107...0x10133 => true,
+ 0x10137...0x1013f => true,
+ 0x10140...0x10174 => true,
+ 0x10175...0x10178 => true,
+ 0x10179...0x10189 => true,
+ 0x1018a...0x1018b => true,
+ 0x1018c...0x1018e => true,
+ 0x10190...0x1019c => true,
+ 0x101a0 => true,
+ 0x101d0...0x101fc => true,
+ 0x10280...0x1029c => true,
+ 0x102a0...0x102d0 => true,
+ 0x102e1...0x102fb => true,
+ 0x10300...0x1031f => true,
+ 0x10320...0x10323 => true,
+ 0x1032d...0x10340 => true,
+ 0x10341 => true,
+ 0x10342...0x10349 => true,
+ 0x1034a => true,
+ 0x10350...0x10375 => true,
+ 0x10380...0x1039d => true,
+ 0x1039f => true,
+ 0x103a0...0x103c3 => true,
+ 0x103c8...0x103cf => true,
+ 0x103d0 => true,
+ 0x103d1...0x103d5 => true,
+ 0x10400...0x1044f => true,
+ 0x10450...0x1049d => true,
+ 0x104a0...0x104a9 => true,
+ 0x104b0...0x104d3 => true,
+ 0x104d8...0x104fb => true,
+ 0x10500...0x10527 => true,
+ 0x10530...0x10563 => true,
+ 0x1056f => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10600...0x10736 => true,
+ 0x10740...0x10755 => true,
+ 0x10760...0x10767 => true,
+ 0x10780...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x10800...0x10805 => true,
+ 0x10808 => true,
+ 0x1080a...0x10835 => true,
+ 0x10837...0x10838 => true,
+ 0x1083c => true,
+ 0x1083f...0x10855 => true,
+ 0x10857 => true,
+ 0x10858...0x1085f => true,
+ 0x10860...0x10876 => true,
+ 0x10877...0x10878 => true,
+ 0x10879...0x1087f => true,
+ 0x10880...0x1089e => true,
+ 0x108a7...0x108af => true,
+ 0x108e0...0x108f2 => true,
+ 0x108f4...0x108f5 => true,
+ 0x108fb...0x108ff => true,
+ 0x10900...0x10915 => true,
+ 0x10916...0x1091b => true,
+ 0x1091f => true,
+ 0x10920...0x10939 => true,
+ 0x1093f => true,
+ 0x10980...0x109b7 => true,
+ 0x109bc...0x109bd => true,
+ 0x109be...0x109bf => true,
+ 0x109c0...0x109cf => true,
+ 0x109d2...0x109ff => true,
+ 0x10a00 => true,
+ 0x10a10...0x10a13 => true,
+ 0x10a15...0x10a17 => true,
+ 0x10a19...0x10a35 => true,
+ 0x10a40...0x10a48 => true,
+ 0x10a50...0x10a58 => true,
+ 0x10a60...0x10a7c => true,
+ 0x10a7d...0x10a7e => true,
+ 0x10a7f => true,
+ 0x10a80...0x10a9c => true,
+ 0x10a9d...0x10a9f => true,
+ 0x10ac0...0x10ac7 => true,
+ 0x10ac8 => true,
+ 0x10ac9...0x10ae4 => true,
+ 0x10aeb...0x10aef => true,
+ 0x10af0...0x10af6 => true,
+ 0x10b00...0x10b35 => true,
+ 0x10b39...0x10b3f => true,
+ 0x10b40...0x10b55 => true,
+ 0x10b58...0x10b5f => true,
+ 0x10b60...0x10b72 => true,
+ 0x10b78...0x10b7f => true,
+ 0x10b80...0x10b91 => true,
+ 0x10b99...0x10b9c => true,
+ 0x10ba9...0x10baf => true,
+ 0x10c00...0x10c48 => true,
+ 0x10c80...0x10cb2 => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x10cfa...0x10cff => true,
+ 0x10d00...0x10d23 => true,
+ 0x10d30...0x10d39 => true,
+ 0x10e60...0x10e7e => true,
+ 0x10e80...0x10ea9 => true,
+ 0x10ead => true,
+ 0x10eb0...0x10eb1 => true,
+ 0x10f00...0x10f1c => true,
+ 0x10f1d...0x10f26 => true,
+ 0x10f27 => true,
+ 0x10f30...0x10f45 => true,
+ 0x10f51...0x10f54 => true,
+ 0x10f55...0x10f59 => true,
+ 0x10f70...0x10f81 => true,
+ 0x10f86...0x10f89 => true,
+ 0x10fb0...0x10fc4 => true,
+ 0x10fc5...0x10fcb => true,
+ 0x10fe0...0x10ff6 => true,
+ 0x11000 => true,
+ 0x11002 => true,
+ 0x11003...0x11037 => true,
+ 0x11047...0x1104d => true,
+ 0x11052...0x11065 => true,
+ 0x11066...0x1106f => true,
+ 0x11071...0x11072 => true,
+ 0x11075 => true,
+ 0x11082 => true,
+ 0x11083...0x110af => true,
+ 0x110b0...0x110b2 => true,
+ 0x110b7...0x110b8 => true,
+ 0x110bb...0x110bc => true,
+ 0x110be...0x110c1 => true,
+ 0x110d0...0x110e8 => true,
+ 0x110f0...0x110f9 => true,
+ 0x11103...0x11126 => true,
+ 0x1112c => true,
+ 0x11136...0x1113f => true,
+ 0x11140...0x11143 => true,
+ 0x11144 => true,
+ 0x11145...0x11146 => true,
+ 0x11147 => true,
+ 0x11150...0x11172 => true,
+ 0x11174...0x11175 => true,
+ 0x11176 => true,
+ 0x11182 => true,
+ 0x11183...0x111b2 => true,
+ 0x111b3...0x111b5 => true,
+ 0x111bf...0x111c0 => true,
+ 0x111c1...0x111c4 => true,
+ 0x111c5...0x111c8 => true,
+ 0x111cd => true,
+ 0x111ce => true,
+ 0x111d0...0x111d9 => true,
+ 0x111da => true,
+ 0x111db => true,
+ 0x111dc => true,
+ 0x111dd...0x111df => true,
+ 0x111e1...0x111f4 => true,
+ 0x11200...0x11211 => true,
+ 0x11213...0x1122b => true,
+ 0x1122c...0x1122e => true,
+ 0x11232...0x11233 => true,
+ 0x11235 => true,
+ 0x11238...0x1123d => true,
+ 0x1123f...0x11240 => true,
+ 0x11280...0x11286 => true,
+ 0x11288 => true,
+ 0x1128a...0x1128d => true,
+ 0x1128f...0x1129d => true,
+ 0x1129f...0x112a8 => true,
+ 0x112a9 => true,
+ 0x112b0...0x112de => true,
+ 0x112e0...0x112e2 => true,
+ 0x112f0...0x112f9 => true,
+ 0x11302...0x11303 => true,
+ 0x11305...0x1130c => true,
+ 0x1130f...0x11310 => true,
+ 0x11313...0x11328 => true,
+ 0x1132a...0x11330 => true,
+ 0x11332...0x11333 => true,
+ 0x11335...0x11339 => true,
+ 0x1133d => true,
+ 0x1133f => true,
+ 0x11341...0x11344 => true,
+ 0x11347...0x11348 => true,
+ 0x1134b...0x1134d => true,
+ 0x11350 => true,
+ 0x1135d...0x11361 => true,
+ 0x11362...0x11363 => true,
+ 0x11400...0x11434 => true,
+ 0x11435...0x11437 => true,
+ 0x11440...0x11441 => true,
+ 0x11445 => true,
+ 0x11447...0x1144a => true,
+ 0x1144b...0x1144f => true,
+ 0x11450...0x11459 => true,
+ 0x1145a...0x1145b => true,
+ 0x1145d => true,
+ 0x1145f...0x11461 => true,
+ 0x11480...0x114af => true,
+ 0x114b1...0x114b2 => true,
+ 0x114b9 => true,
+ 0x114bb...0x114bc => true,
+ 0x114be => true,
+ 0x114c1 => true,
+ 0x114c4...0x114c5 => true,
+ 0x114c6 => true,
+ 0x114c7 => true,
+ 0x114d0...0x114d9 => true,
+ 0x11580...0x115ae => true,
+ 0x115b0...0x115b1 => true,
+ 0x115b8...0x115bb => true,
+ 0x115be => true,
+ 0x115c1...0x115d7 => true,
+ 0x115d8...0x115db => true,
+ 0x11600...0x1162f => true,
+ 0x11630...0x11632 => true,
+ 0x1163b...0x1163c => true,
+ 0x1163e => true,
+ 0x11641...0x11643 => true,
+ 0x11644 => true,
+ 0x11650...0x11659 => true,
+ 0x11660...0x1166c => true,
+ 0x11680...0x116aa => true,
+ 0x116ac => true,
+ 0x116ae...0x116af => true,
+ 0x116b6 => true,
+ 0x116b8 => true,
+ 0x116b9 => true,
+ 0x116c0...0x116c9 => true,
+ 0x11700...0x1171a => true,
+ 0x11720...0x11721 => true,
+ 0x11726 => true,
+ 0x11730...0x11739 => true,
+ 0x1173a...0x1173b => true,
+ 0x1173c...0x1173e => true,
+ 0x1173f => true,
+ 0x11740...0x11746 => true,
+ 0x11800...0x1182b => true,
+ 0x1182c...0x1182e => true,
+ 0x11838 => true,
+ 0x1183b => true,
+ 0x118a0...0x118df => true,
+ 0x118e0...0x118e9 => true,
+ 0x118ea...0x118f2 => true,
+ 0x118ff...0x11906 => true,
+ 0x11909 => true,
+ 0x1190c...0x11913 => true,
+ 0x11915...0x11916 => true,
+ 0x11918...0x1192f => true,
+ 0x11931...0x11935 => true,
+ 0x11937...0x11938 => true,
+ 0x1193d => true,
+ 0x1193f => true,
+ 0x11940 => true,
+ 0x11941 => true,
+ 0x11942 => true,
+ 0x11944...0x11946 => true,
+ 0x11950...0x11959 => true,
+ 0x119a0...0x119a7 => true,
+ 0x119aa...0x119d0 => true,
+ 0x119d1...0x119d3 => true,
+ 0x119dc...0x119df => true,
+ 0x119e1 => true,
+ 0x119e2 => true,
+ 0x119e3 => true,
+ 0x119e4 => true,
+ 0x11a00 => true,
+ 0x11a0b...0x11a32 => true,
+ 0x11a39 => true,
+ 0x11a3a => true,
+ 0x11a3f...0x11a46 => true,
+ 0x11a50 => true,
+ 0x11a57...0x11a58 => true,
+ 0x11a5c...0x11a89 => true,
+ 0x11a97 => true,
+ 0x11a9a...0x11a9c => true,
+ 0x11a9d => true,
+ 0x11a9e...0x11aa2 => true,
+ 0x11ab0...0x11af8 => true,
+ 0x11b00...0x11b09 => true,
+ 0x11c00...0x11c08 => true,
+ 0x11c0a...0x11c2e => true,
+ 0x11c2f => true,
+ 0x11c3e => true,
+ 0x11c40 => true,
+ 0x11c41...0x11c45 => true,
+ 0x11c50...0x11c59 => true,
+ 0x11c5a...0x11c6c => true,
+ 0x11c70...0x11c71 => true,
+ 0x11c72...0x11c8f => true,
+ 0x11ca9 => true,
+ 0x11cb1 => true,
+ 0x11cb4 => true,
+ 0x11d00...0x11d06 => true,
+ 0x11d08...0x11d09 => true,
+ 0x11d0b...0x11d30 => true,
+ 0x11d46 => true,
+ 0x11d50...0x11d59 => true,
+ 0x11d60...0x11d65 => true,
+ 0x11d67...0x11d68 => true,
+ 0x11d6a...0x11d89 => true,
+ 0x11d8a...0x11d8e => true,
+ 0x11d93...0x11d94 => true,
+ 0x11d96 => true,
+ 0x11d98 => true,
+ 0x11da0...0x11da9 => true,
+ 0x11ee0...0x11ef2 => true,
+ 0x11ef5...0x11ef6 => true,
+ 0x11ef7...0x11ef8 => true,
+ 0x11f02 => true,
+ 0x11f03 => true,
+ 0x11f04...0x11f10 => true,
+ 0x11f12...0x11f33 => true,
+ 0x11f34...0x11f35 => true,
+ 0x11f3e...0x11f3f => true,
+ 0x11f41 => true,
+ 0x11f43...0x11f4f => true,
+ 0x11f50...0x11f59 => true,
+ 0x11fb0 => true,
+ 0x11fc0...0x11fd4 => true,
+ 0x11fd5...0x11fdc => true,
+ 0x11fdd...0x11fe0 => true,
+ 0x11fe1...0x11ff1 => true,
+ 0x11fff => true,
+ 0x12000...0x12399 => true,
+ 0x12400...0x1246e => true,
+ 0x12470...0x12474 => true,
+ 0x12480...0x12543 => true,
+ 0x12f90...0x12ff0 => true,
+ 0x12ff1...0x12ff2 => true,
+ 0x13000...0x1342f => true,
+ 0x13441...0x13446 => true,
+ 0x14400...0x14646 => true,
+ 0x16800...0x16a38 => true,
+ 0x16a40...0x16a5e => true,
+ 0x16a60...0x16a69 => true,
+ 0x16a6e...0x16a6f => true,
+ 0x16a70...0x16abe => true,
+ 0x16ac0...0x16ac9 => true,
+ 0x16ad0...0x16aed => true,
+ 0x16af5 => true,
+ 0x16b00...0x16b2f => true,
+ 0x16b37...0x16b3b => true,
+ 0x16b3c...0x16b3f => true,
+ 0x16b40...0x16b43 => true,
+ 0x16b44 => true,
+ 0x16b45 => true,
+ 0x16b50...0x16b59 => true,
+ 0x16b5b...0x16b61 => true,
+ 0x16b63...0x16b77 => true,
+ 0x16b7d...0x16b8f => true,
+ 0x16e40...0x16e7f => true,
+ 0x16e80...0x16e96 => true,
+ 0x16e97...0x16e9a => true,
+ 0x16f00...0x16f4a => true,
+ 0x16f50 => true,
+ 0x16f51...0x16f87 => true,
+ 0x16f93...0x16f9f => true,
+ 0x16fe0...0x16fe1 => true,
+ 0x16fe2 => true,
+ 0x16fe3 => true,
+ 0x16ff0...0x16ff1 => true,
+ 0x17000...0x187f7 => true,
+ 0x18800...0x18cd5 => true,
+ 0x18d00...0x18d08 => true,
+ 0x1aff0...0x1aff3 => true,
+ 0x1aff5...0x1affb => true,
+ 0x1affd...0x1affe => true,
+ 0x1b000...0x1b122 => true,
+ 0x1b132 => true,
+ 0x1b150...0x1b152 => true,
+ 0x1b155 => true,
+ 0x1b164...0x1b167 => true,
+ 0x1b170...0x1b2fb => true,
+ 0x1bc00...0x1bc6a => true,
+ 0x1bc70...0x1bc7c => true,
+ 0x1bc80...0x1bc88 => true,
+ 0x1bc90...0x1bc99 => true,
+ 0x1bc9c => true,
+ 0x1bc9f => true,
+ 0x1cf50...0x1cfc3 => true,
+ 0x1d000...0x1d0f5 => true,
+ 0x1d100...0x1d126 => true,
+ 0x1d129...0x1d164 => true,
+ 0x1d166 => true,
+ 0x1d16a...0x1d16c => true,
+ 0x1d16d => true,
+ 0x1d183...0x1d184 => true,
+ 0x1d18c...0x1d1a9 => true,
+ 0x1d1ae...0x1d1ea => true,
+ 0x1d200...0x1d241 => true,
+ 0x1d245 => true,
+ 0x1d2c0...0x1d2d3 => true,
+ 0x1d2e0...0x1d2f3 => true,
+ 0x1d300...0x1d356 => true,
+ 0x1d360...0x1d378 => true,
+ 0x1d400...0x1d454 => true,
+ 0x1d456...0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d51e...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d552...0x1d6a5 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6c1 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6db => true,
+ 0x1d6dc...0x1d6fa => true,
+ 0x1d6fb => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d715 => true,
+ 0x1d716...0x1d734 => true,
+ 0x1d735 => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d74f => true,
+ 0x1d750...0x1d76e => true,
+ 0x1d76f => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d789 => true,
+ 0x1d78a...0x1d7a8 => true,
+ 0x1d7a9 => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c3 => true,
+ 0x1d7c4...0x1d7cb => true,
+ 0x1d7ce...0x1d7ff => true,
+ 0x1d800...0x1d9ff => true,
+ 0x1da37...0x1da3a => true,
+ 0x1da6d...0x1da74 => true,
+ 0x1da76...0x1da83 => true,
+ 0x1da85...0x1da86 => true,
+ 0x1da87...0x1da8b => true,
+ 0x1df00...0x1df09 => true,
+ 0x1df0a => true,
+ 0x1df0b...0x1df1e => true,
+ 0x1df25...0x1df2a => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e100...0x1e12c => true,
+ 0x1e137...0x1e13d => true,
+ 0x1e140...0x1e149 => true,
+ 0x1e14e => true,
+ 0x1e14f => true,
+ 0x1e290...0x1e2ad => true,
+ 0x1e2c0...0x1e2eb => true,
+ 0x1e2f0...0x1e2f9 => true,
+ 0x1e2ff => true,
+ 0x1e4d0...0x1e4ea => true,
+ 0x1e4eb => true,
+ 0x1e4f0...0x1e4f9 => true,
+ 0x1e7e0...0x1e7e6 => true,
+ 0x1e7e8...0x1e7eb => true,
+ 0x1e7ed...0x1e7ee => true,
+ 0x1e7f0...0x1e7fe => true,
+ 0x1e800...0x1e8c4 => true,
+ 0x1e8c7...0x1e8cf => true,
+ 0x1e900...0x1e943 => true,
+ 0x1e94b => true,
+ 0x1e950...0x1e959 => true,
+ 0x1e95e...0x1e95f => true,
+ 0x1ec71...0x1ecab => true,
+ 0x1ecac => true,
+ 0x1ecad...0x1ecaf => true,
+ 0x1ecb0 => true,
+ 0x1ecb1...0x1ecb4 => true,
+ 0x1ed01...0x1ed2d => true,
+ 0x1ed2e => true,
+ 0x1ed2f...0x1ed3d => true,
+ 0x1ee00...0x1ee03 => true,
+ 0x1ee05...0x1ee1f => true,
+ 0x1ee21...0x1ee22 => true,
+ 0x1ee24 => true,
+ 0x1ee27 => true,
+ 0x1ee29...0x1ee32 => true,
+ 0x1ee34...0x1ee37 => true,
+ 0x1ee39 => true,
+ 0x1ee3b => true,
+ 0x1ee42 => true,
+ 0x1ee47 => true,
+ 0x1ee49 => true,
+ 0x1ee4b => true,
+ 0x1ee4d...0x1ee4f => true,
+ 0x1ee51...0x1ee52 => true,
+ 0x1ee54 => true,
+ 0x1ee57 => true,
+ 0x1ee59 => true,
+ 0x1ee5b => true,
+ 0x1ee5d => true,
+ 0x1ee5f => true,
+ 0x1ee61...0x1ee62 => true,
+ 0x1ee64 => true,
+ 0x1ee67...0x1ee6a => true,
+ 0x1ee6c...0x1ee72 => true,
+ 0x1ee74...0x1ee77 => true,
+ 0x1ee79...0x1ee7c => true,
+ 0x1ee7e => true,
+ 0x1ee80...0x1ee89 => true,
+ 0x1ee8b...0x1ee9b => true,
+ 0x1eea1...0x1eea3 => true,
+ 0x1eea5...0x1eea9 => true,
+ 0x1eeab...0x1eebb => true,
+ 0x1eef0...0x1eef1 => true,
+ 0x1f000...0x1f02b => true,
+ 0x1f030...0x1f093 => true,
+ 0x1f0a0...0x1f0ae => true,
+ 0x1f0b1...0x1f0bf => true,
+ 0x1f0c1...0x1f0cf => true,
+ 0x1f0d1...0x1f0f5 => true,
+ 0x1f100...0x1f10c => true,
+ 0x1f10d...0x1f1ad => true,
+ 0x1f1e6...0x1f202 => true,
+ 0x1f210...0x1f23b => true,
+ 0x1f240...0x1f248 => true,
+ 0x1f250...0x1f251 => true,
+ 0x1f260...0x1f265 => true,
+ 0x1f300...0x1f3fa => true,
+ 0x1f3fb...0x1f3ff => true,
+ 0x1f400...0x1f6d7 => true,
+ 0x1f6dc...0x1f6ec => true,
+ 0x1f6f0...0x1f6fc => true,
+ 0x1f700...0x1f776 => true,
+ 0x1f77b...0x1f7d9 => true,
+ 0x1f7e0...0x1f7eb => true,
+ 0x1f7f0 => true,
+ 0x1f800...0x1f80b => true,
+ 0x1f810...0x1f847 => true,
+ 0x1f850...0x1f859 => true,
+ 0x1f860...0x1f887 => true,
+ 0x1f890...0x1f8ad => true,
+ 0x1f8b0...0x1f8b1 => true,
+ 0x1f900...0x1fa53 => true,
+ 0x1fa60...0x1fa6d => true,
+ 0x1fa70...0x1fa7c => true,
+ 0x1fa80...0x1fa88 => true,
+ 0x1fa90...0x1fabd => true,
+ 0x1fabf...0x1fac5 => true,
+ 0x1face...0x1fadb => true,
+ 0x1fae0...0x1fae8 => true,
+ 0x1faf0...0x1faf8 => true,
+ 0x1fb00...0x1fb92 => true,
+ 0x1fb94...0x1fbca => true,
+ 0x1fbf0...0x1fbf9 => true,
+ 0x20000...0x2a6df => true,
+ 0x2a700...0x2b739 => true,
+ 0x2b740...0x2b81d => true,
+ 0x2b820...0x2cea1 => true,
+ 0x2ceb0...0x2ebe0 => true,
+ 0x2f800...0x2fa1d => true,
+ 0x30000...0x3134a => true,
+ 0x31350...0x323af => true,
+ else => false,
+ };
+}
+
+pub fn isGraphemeLink(cp: u21) bool {
+ if (cp < 0x94d or cp > 0x11f42) return false;
+
+ return switch (cp) {
+ 0x94d => true,
+ 0x9cd => true,
+ 0xa4d => true,
+ 0xacd => true,
+ 0xb4d => true,
+ 0xbcd => true,
+ 0xc4d => true,
+ 0xccd => true,
+ 0xd3b...0xd3c => true,
+ 0xd4d => true,
+ 0xdca => true,
+ 0xe3a => true,
+ 0xeba => true,
+ 0xf84 => true,
+ 0x1039...0x103a => true,
+ 0x1714 => true,
+ 0x1715 => true,
+ 0x1734 => true,
+ 0x17d2 => true,
+ 0x1a60 => true,
+ 0x1b44 => true,
+ 0x1baa => true,
+ 0x1bab => true,
+ 0x1bf2...0x1bf3 => true,
+ 0x2d7f => true,
+ 0xa806 => true,
+ 0xa82c => true,
+ 0xa8c4 => true,
+ 0xa953 => true,
+ 0xa9c0 => true,
+ 0xaaf6 => true,
+ 0xabed => true,
+ 0x10a3f => true,
+ 0x11046 => true,
+ 0x11070 => true,
+ 0x1107f => true,
+ 0x110b9 => true,
+ 0x11133...0x11134 => true,
+ 0x111c0 => true,
+ 0x11235 => true,
+ 0x112ea => true,
+ 0x1134d => true,
+ 0x11442 => true,
+ 0x114c2 => true,
+ 0x115bf => true,
+ 0x1163f => true,
+ 0x116b6 => true,
+ 0x1172b => true,
+ 0x11839 => true,
+ 0x1193d => true,
+ 0x1193e => true,
+ 0x119e0 => true,
+ 0x11a34 => true,
+ 0x11a47 => true,
+ 0x11a99 => true,
+ 0x11c3f => true,
+ 0x11d44...0x11d45 => true,
+ 0x11d97 => true,
+ 0x11f41 => true,
+ 0x11f42 => true,
+ else => false,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/derived_east_asian_width.zig.html b/docs/src/ziglyph/autogen/derived_east_asian_width.zig.html
new file mode 100644
index 0000000..1a0b09c
--- /dev/null
+++ b/docs/src/ziglyph/autogen/derived_east_asian_width.zig.html
@@ -0,0 +1,2691 @@
+
+
+
+
+
autogen/derived_east_asian_width.zig - source view
+
+
+
+
+
+
+
+
+pub fn isNeutral(cp: u21) bool {
+ if (cp > 0xe007f) return false;
+
+ return switch (cp) {
+ 0x0...0x1f => true,
+ 0x7f...0x9f => true,
+ 0xa0 => true,
+ 0xa9 => true,
+ 0xab => true,
+ 0xb5 => true,
+ 0xbb => true,
+ 0xc0...0xc5 => true,
+ 0xc7...0xcf => true,
+ 0xd1...0xd6 => true,
+ 0xd9...0xdd => true,
+ 0xe2...0xe5 => true,
+ 0xe7 => true,
+ 0xeb => true,
+ 0xee...0xef => true,
+ 0xf1 => true,
+ 0xf4...0xf6 => true,
+ 0xfb => true,
+ 0xfd => true,
+ 0xff...0x100 => true,
+ 0x102...0x110 => true,
+ 0x112 => true,
+ 0x114...0x11a => true,
+ 0x11c...0x125 => true,
+ 0x128...0x12a => true,
+ 0x12c...0x130 => true,
+ 0x134...0x137 => true,
+ 0x139...0x13e => true,
+ 0x143 => true,
+ 0x145...0x147 => true,
+ 0x14c => true,
+ 0x14e...0x151 => true,
+ 0x154...0x165 => true,
+ 0x168...0x16a => true,
+ 0x16c...0x1ba => true,
+ 0x1bb => true,
+ 0x1bc...0x1bf => true,
+ 0x1c0...0x1c3 => true,
+ 0x1c4...0x1cd => true,
+ 0x1cf => true,
+ 0x1d1 => true,
+ 0x1d3 => true,
+ 0x1d5 => true,
+ 0x1d7 => true,
+ 0x1d9 => true,
+ 0x1db => true,
+ 0x1dd...0x250 => true,
+ 0x252...0x260 => true,
+ 0x262...0x293 => true,
+ 0x294 => true,
+ 0x295...0x2af => true,
+ 0x2b0...0x2c1 => true,
+ 0x2c2...0x2c3 => true,
+ 0x2c5 => true,
+ 0x2c6 => true,
+ 0x2c8 => true,
+ 0x2cc => true,
+ 0x2ce...0x2cf => true,
+ 0x2d1 => true,
+ 0x2d2...0x2d7 => true,
+ 0x2dc => true,
+ 0x2de => true,
+ 0x2e0...0x2e4 => true,
+ 0x2e5...0x2eb => true,
+ 0x2ec => true,
+ 0x2ed => true,
+ 0x2ee => true,
+ 0x2ef...0x2ff => true,
+ 0x370...0x373 => true,
+ 0x374 => true,
+ 0x375 => true,
+ 0x376...0x377 => true,
+ 0x37a => true,
+ 0x37b...0x37d => true,
+ 0x37e => true,
+ 0x37f => true,
+ 0x384...0x385 => true,
+ 0x386 => true,
+ 0x387 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x390 => true,
+ 0x3aa...0x3b0 => true,
+ 0x3c2 => true,
+ 0x3ca...0x3f5 => true,
+ 0x3f6 => true,
+ 0x3f7...0x400 => true,
+ 0x402...0x40f => true,
+ 0x450 => true,
+ 0x452...0x481 => true,
+ 0x482 => true,
+ 0x483...0x487 => true,
+ 0x488...0x489 => true,
+ 0x48a...0x52f => true,
+ 0x531...0x556 => true,
+ 0x559 => true,
+ 0x55a...0x55f => true,
+ 0x560...0x588 => true,
+ 0x589 => true,
+ 0x58a => true,
+ 0x58d...0x58e => true,
+ 0x58f => true,
+ 0x591...0x5bd => true,
+ 0x5be => true,
+ 0x5bf => true,
+ 0x5c0 => true,
+ 0x5c1...0x5c2 => true,
+ 0x5c3 => true,
+ 0x5c4...0x5c5 => true,
+ 0x5c6 => true,
+ 0x5c7 => true,
+ 0x5d0...0x5ea => true,
+ 0x5ef...0x5f2 => true,
+ 0x5f3...0x5f4 => true,
+ 0x600...0x605 => true,
+ 0x606...0x608 => true,
+ 0x609...0x60a => true,
+ 0x60b => true,
+ 0x60c...0x60d => true,
+ 0x60e...0x60f => true,
+ 0x610...0x61a => true,
+ 0x61b => true,
+ 0x61c => true,
+ 0x61d...0x61f => true,
+ 0x620...0x63f => true,
+ 0x640 => true,
+ 0x641...0x64a => true,
+ 0x64b...0x65f => true,
+ 0x660...0x669 => true,
+ 0x66a...0x66d => true,
+ 0x66e...0x66f => true,
+ 0x670 => true,
+ 0x671...0x6d3 => true,
+ 0x6d4 => true,
+ 0x6d5 => true,
+ 0x6d6...0x6dc => true,
+ 0x6dd => true,
+ 0x6de => true,
+ 0x6df...0x6e4 => true,
+ 0x6e5...0x6e6 => true,
+ 0x6e7...0x6e8 => true,
+ 0x6e9 => true,
+ 0x6ea...0x6ed => true,
+ 0x6ee...0x6ef => true,
+ 0x6f0...0x6f9 => true,
+ 0x6fa...0x6fc => true,
+ 0x6fd...0x6fe => true,
+ 0x6ff => true,
+ 0x700...0x70d => true,
+ 0x70f => true,
+ 0x710 => true,
+ 0x711 => true,
+ 0x712...0x72f => true,
+ 0x730...0x74a => true,
+ 0x74d...0x7a5 => true,
+ 0x7a6...0x7b0 => true,
+ 0x7b1 => true,
+ 0x7c0...0x7c9 => true,
+ 0x7ca...0x7ea => true,
+ 0x7eb...0x7f3 => true,
+ 0x7f4...0x7f5 => true,
+ 0x7f6 => true,
+ 0x7f7...0x7f9 => true,
+ 0x7fa => true,
+ 0x7fd => true,
+ 0x7fe...0x7ff => true,
+ 0x800...0x815 => true,
+ 0x816...0x819 => true,
+ 0x81a => true,
+ 0x81b...0x823 => true,
+ 0x824 => true,
+ 0x825...0x827 => true,
+ 0x828 => true,
+ 0x829...0x82d => true,
+ 0x830...0x83e => true,
+ 0x840...0x858 => true,
+ 0x859...0x85b => true,
+ 0x85e => true,
+ 0x860...0x86a => true,
+ 0x870...0x887 => true,
+ 0x888 => true,
+ 0x889...0x88e => true,
+ 0x890...0x891 => true,
+ 0x898...0x89f => true,
+ 0x8a0...0x8c8 => true,
+ 0x8c9 => true,
+ 0x8ca...0x8e1 => true,
+ 0x8e2 => true,
+ 0x8e3...0x902 => true,
+ 0x903 => true,
+ 0x904...0x939 => true,
+ 0x93a => true,
+ 0x93b => true,
+ 0x93c => true,
+ 0x93d => true,
+ 0x93e...0x940 => true,
+ 0x941...0x948 => true,
+ 0x949...0x94c => true,
+ 0x94d => true,
+ 0x94e...0x94f => true,
+ 0x950 => true,
+ 0x951...0x957 => true,
+ 0x958...0x961 => true,
+ 0x962...0x963 => true,
+ 0x964...0x965 => true,
+ 0x966...0x96f => true,
+ 0x970 => true,
+ 0x971 => true,
+ 0x972...0x980 => true,
+ 0x981 => true,
+ 0x982...0x983 => true,
+ 0x985...0x98c => true,
+ 0x98f...0x990 => true,
+ 0x993...0x9a8 => true,
+ 0x9aa...0x9b0 => true,
+ 0x9b2 => true,
+ 0x9b6...0x9b9 => true,
+ 0x9bc => true,
+ 0x9bd => true,
+ 0x9be...0x9c0 => true,
+ 0x9c1...0x9c4 => true,
+ 0x9c7...0x9c8 => true,
+ 0x9cb...0x9cc => true,
+ 0x9cd => true,
+ 0x9ce => true,
+ 0x9d7 => true,
+ 0x9dc...0x9dd => true,
+ 0x9df...0x9e1 => true,
+ 0x9e2...0x9e3 => true,
+ 0x9e6...0x9ef => true,
+ 0x9f0...0x9f1 => true,
+ 0x9f2...0x9f3 => true,
+ 0x9f4...0x9f9 => true,
+ 0x9fa => true,
+ 0x9fb => true,
+ 0x9fc => true,
+ 0x9fd => true,
+ 0x9fe => true,
+ 0xa01...0xa02 => true,
+ 0xa03 => true,
+ 0xa05...0xa0a => true,
+ 0xa0f...0xa10 => true,
+ 0xa13...0xa28 => true,
+ 0xa2a...0xa30 => true,
+ 0xa32...0xa33 => true,
+ 0xa35...0xa36 => true,
+ 0xa38...0xa39 => true,
+ 0xa3c => true,
+ 0xa3e...0xa40 => true,
+ 0xa41...0xa42 => true,
+ 0xa47...0xa48 => true,
+ 0xa4b...0xa4d => true,
+ 0xa51 => true,
+ 0xa59...0xa5c => true,
+ 0xa5e => true,
+ 0xa66...0xa6f => true,
+ 0xa70...0xa71 => true,
+ 0xa72...0xa74 => true,
+ 0xa75 => true,
+ 0xa76 => true,
+ 0xa81...0xa82 => true,
+ 0xa83 => true,
+ 0xa85...0xa8d => true,
+ 0xa8f...0xa91 => true,
+ 0xa93...0xaa8 => true,
+ 0xaaa...0xab0 => true,
+ 0xab2...0xab3 => true,
+ 0xab5...0xab9 => true,
+ 0xabc => true,
+ 0xabd => true,
+ 0xabe...0xac0 => true,
+ 0xac1...0xac5 => true,
+ 0xac7...0xac8 => true,
+ 0xac9 => true,
+ 0xacb...0xacc => true,
+ 0xacd => true,
+ 0xad0 => true,
+ 0xae0...0xae1 => true,
+ 0xae2...0xae3 => true,
+ 0xae6...0xaef => true,
+ 0xaf0 => true,
+ 0xaf1 => true,
+ 0xaf9 => true,
+ 0xafa...0xaff => true,
+ 0xb01 => true,
+ 0xb02...0xb03 => true,
+ 0xb05...0xb0c => true,
+ 0xb0f...0xb10 => true,
+ 0xb13...0xb28 => true,
+ 0xb2a...0xb30 => true,
+ 0xb32...0xb33 => true,
+ 0xb35...0xb39 => true,
+ 0xb3c => true,
+ 0xb3d => true,
+ 0xb3e => true,
+ 0xb3f => true,
+ 0xb40 => true,
+ 0xb41...0xb44 => true,
+ 0xb47...0xb48 => true,
+ 0xb4b...0xb4c => true,
+ 0xb4d => true,
+ 0xb55...0xb56 => true,
+ 0xb57 => true,
+ 0xb5c...0xb5d => true,
+ 0xb5f...0xb61 => true,
+ 0xb62...0xb63 => true,
+ 0xb66...0xb6f => true,
+ 0xb70 => true,
+ 0xb71 => true,
+ 0xb72...0xb77 => true,
+ 0xb82 => true,
+ 0xb83 => true,
+ 0xb85...0xb8a => true,
+ 0xb8e...0xb90 => true,
+ 0xb92...0xb95 => true,
+ 0xb99...0xb9a => true,
+ 0xb9c => true,
+ 0xb9e...0xb9f => true,
+ 0xba3...0xba4 => true,
+ 0xba8...0xbaa => true,
+ 0xbae...0xbb9 => true,
+ 0xbbe...0xbbf => true,
+ 0xbc0 => true,
+ 0xbc1...0xbc2 => true,
+ 0xbc6...0xbc8 => true,
+ 0xbca...0xbcc => true,
+ 0xbcd => true,
+ 0xbd0 => true,
+ 0xbd7 => true,
+ 0xbe6...0xbef => true,
+ 0xbf0...0xbf2 => true,
+ 0xbf3...0xbf8 => true,
+ 0xbf9 => true,
+ 0xbfa => true,
+ 0xc00 => true,
+ 0xc01...0xc03 => true,
+ 0xc04 => true,
+ 0xc05...0xc0c => true,
+ 0xc0e...0xc10 => true,
+ 0xc12...0xc28 => true,
+ 0xc2a...0xc39 => true,
+ 0xc3c => true,
+ 0xc3d => true,
+ 0xc3e...0xc40 => true,
+ 0xc41...0xc44 => true,
+ 0xc46...0xc48 => true,
+ 0xc4a...0xc4d => true,
+ 0xc55...0xc56 => true,
+ 0xc58...0xc5a => true,
+ 0xc5d => true,
+ 0xc60...0xc61 => true,
+ 0xc62...0xc63 => true,
+ 0xc66...0xc6f => true,
+ 0xc77 => true,
+ 0xc78...0xc7e => true,
+ 0xc7f => true,
+ 0xc80 => true,
+ 0xc81 => true,
+ 0xc82...0xc83 => true,
+ 0xc84 => true,
+ 0xc85...0xc8c => true,
+ 0xc8e...0xc90 => true,
+ 0xc92...0xca8 => true,
+ 0xcaa...0xcb3 => true,
+ 0xcb5...0xcb9 => true,
+ 0xcbc => true,
+ 0xcbd => true,
+ 0xcbe => true,
+ 0xcbf => true,
+ 0xcc0...0xcc4 => true,
+ 0xcc6 => true,
+ 0xcc7...0xcc8 => true,
+ 0xcca...0xccb => true,
+ 0xccc...0xccd => true,
+ 0xcd5...0xcd6 => true,
+ 0xcdd...0xcde => true,
+ 0xce0...0xce1 => true,
+ 0xce2...0xce3 => true,
+ 0xce6...0xcef => true,
+ 0xcf1...0xcf2 => true,
+ 0xcf3 => true,
+ 0xd00...0xd01 => true,
+ 0xd02...0xd03 => true,
+ 0xd04...0xd0c => true,
+ 0xd0e...0xd10 => true,
+ 0xd12...0xd3a => true,
+ 0xd3b...0xd3c => true,
+ 0xd3d => true,
+ 0xd3e...0xd40 => true,
+ 0xd41...0xd44 => true,
+ 0xd46...0xd48 => true,
+ 0xd4a...0xd4c => true,
+ 0xd4d => true,
+ 0xd4e => true,
+ 0xd4f => true,
+ 0xd54...0xd56 => true,
+ 0xd57 => true,
+ 0xd58...0xd5e => true,
+ 0xd5f...0xd61 => true,
+ 0xd62...0xd63 => true,
+ 0xd66...0xd6f => true,
+ 0xd70...0xd78 => true,
+ 0xd79 => true,
+ 0xd7a...0xd7f => true,
+ 0xd81 => true,
+ 0xd82...0xd83 => true,
+ 0xd85...0xd96 => true,
+ 0xd9a...0xdb1 => true,
+ 0xdb3...0xdbb => true,
+ 0xdbd => true,
+ 0xdc0...0xdc6 => true,
+ 0xdca => true,
+ 0xdcf...0xdd1 => true,
+ 0xdd2...0xdd4 => true,
+ 0xdd6 => true,
+ 0xdd8...0xddf => true,
+ 0xde6...0xdef => true,
+ 0xdf2...0xdf3 => true,
+ 0xdf4 => true,
+ 0xe01...0xe30 => true,
+ 0xe31 => true,
+ 0xe32...0xe33 => true,
+ 0xe34...0xe3a => true,
+ 0xe3f => true,
+ 0xe40...0xe45 => true,
+ 0xe46 => true,
+ 0xe47...0xe4e => true,
+ 0xe4f => true,
+ 0xe50...0xe59 => true,
+ 0xe5a...0xe5b => true,
+ 0xe81...0xe82 => true,
+ 0xe84 => true,
+ 0xe86...0xe8a => true,
+ 0xe8c...0xea3 => true,
+ 0xea5 => true,
+ 0xea7...0xeb0 => true,
+ 0xeb1 => true,
+ 0xeb2...0xeb3 => true,
+ 0xeb4...0xebc => true,
+ 0xebd => true,
+ 0xec0...0xec4 => true,
+ 0xec6 => true,
+ 0xec8...0xece => true,
+ 0xed0...0xed9 => true,
+ 0xedc...0xedf => true,
+ 0xf00 => true,
+ 0xf01...0xf03 => true,
+ 0xf04...0xf12 => true,
+ 0xf13 => true,
+ 0xf14 => true,
+ 0xf15...0xf17 => true,
+ 0xf18...0xf19 => true,
+ 0xf1a...0xf1f => true,
+ 0xf20...0xf29 => true,
+ 0xf2a...0xf33 => true,
+ 0xf34 => true,
+ 0xf35 => true,
+ 0xf36 => true,
+ 0xf37 => true,
+ 0xf38 => true,
+ 0xf39 => true,
+ 0xf3a => true,
+ 0xf3b => true,
+ 0xf3c => true,
+ 0xf3d => true,
+ 0xf3e...0xf3f => true,
+ 0xf40...0xf47 => true,
+ 0xf49...0xf6c => true,
+ 0xf71...0xf7e => true,
+ 0xf7f => true,
+ 0xf80...0xf84 => true,
+ 0xf85 => true,
+ 0xf86...0xf87 => true,
+ 0xf88...0xf8c => true,
+ 0xf8d...0xf97 => true,
+ 0xf99...0xfbc => true,
+ 0xfbe...0xfc5 => true,
+ 0xfc6 => true,
+ 0xfc7...0xfcc => true,
+ 0xfce...0xfcf => true,
+ 0xfd0...0xfd4 => true,
+ 0xfd5...0xfd8 => true,
+ 0xfd9...0xfda => true,
+ 0x1000...0x102a => true,
+ 0x102b...0x102c => true,
+ 0x102d...0x1030 => true,
+ 0x1031 => true,
+ 0x1032...0x1037 => true,
+ 0x1038 => true,
+ 0x1039...0x103a => true,
+ 0x103b...0x103c => true,
+ 0x103d...0x103e => true,
+ 0x103f => true,
+ 0x1040...0x1049 => true,
+ 0x104a...0x104f => true,
+ 0x1050...0x1055 => true,
+ 0x1056...0x1057 => true,
+ 0x1058...0x1059 => true,
+ 0x105a...0x105d => true,
+ 0x105e...0x1060 => true,
+ 0x1061 => true,
+ 0x1062...0x1064 => true,
+ 0x1065...0x1066 => true,
+ 0x1067...0x106d => true,
+ 0x106e...0x1070 => true,
+ 0x1071...0x1074 => true,
+ 0x1075...0x1081 => true,
+ 0x1082 => true,
+ 0x1083...0x1084 => true,
+ 0x1085...0x1086 => true,
+ 0x1087...0x108c => true,
+ 0x108d => true,
+ 0x108e => true,
+ 0x108f => true,
+ 0x1090...0x1099 => true,
+ 0x109a...0x109c => true,
+ 0x109d => true,
+ 0x109e...0x109f => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x10d0...0x10fa => true,
+ 0x10fb => true,
+ 0x10fc => true,
+ 0x10fd...0x10ff => true,
+ 0x1160...0x1248 => true,
+ 0x124a...0x124d => true,
+ 0x1250...0x1256 => true,
+ 0x1258 => true,
+ 0x125a...0x125d => true,
+ 0x1260...0x1288 => true,
+ 0x128a...0x128d => true,
+ 0x1290...0x12b0 => true,
+ 0x12b2...0x12b5 => true,
+ 0x12b8...0x12be => true,
+ 0x12c0 => true,
+ 0x12c2...0x12c5 => true,
+ 0x12c8...0x12d6 => true,
+ 0x12d8...0x1310 => true,
+ 0x1312...0x1315 => true,
+ 0x1318...0x135a => true,
+ 0x135d...0x135f => true,
+ 0x1360...0x1368 => true,
+ 0x1369...0x137c => true,
+ 0x1380...0x138f => true,
+ 0x1390...0x1399 => true,
+ 0x13a0...0x13f5 => true,
+ 0x13f8...0x13fd => true,
+ 0x1400 => true,
+ 0x1401...0x166c => true,
+ 0x166d => true,
+ 0x166e => true,
+ 0x166f...0x167f => true,
+ 0x1680 => true,
+ 0x1681...0x169a => true,
+ 0x169b => true,
+ 0x169c => true,
+ 0x16a0...0x16ea => true,
+ 0x16eb...0x16ed => true,
+ 0x16ee...0x16f0 => true,
+ 0x16f1...0x16f8 => true,
+ 0x1700...0x1711 => true,
+ 0x1712...0x1714 => true,
+ 0x1715 => true,
+ 0x171f...0x1731 => true,
+ 0x1732...0x1733 => true,
+ 0x1734 => true,
+ 0x1735...0x1736 => true,
+ 0x1740...0x1751 => true,
+ 0x1752...0x1753 => true,
+ 0x1760...0x176c => true,
+ 0x176e...0x1770 => true,
+ 0x1772...0x1773 => true,
+ 0x1780...0x17b3 => true,
+ 0x17b4...0x17b5 => true,
+ 0x17b6 => true,
+ 0x17b7...0x17bd => true,
+ 0x17be...0x17c5 => true,
+ 0x17c6 => true,
+ 0x17c7...0x17c8 => true,
+ 0x17c9...0x17d3 => true,
+ 0x17d4...0x17d6 => true,
+ 0x17d7 => true,
+ 0x17d8...0x17da => true,
+ 0x17db => true,
+ 0x17dc => true,
+ 0x17dd => true,
+ 0x17e0...0x17e9 => true,
+ 0x17f0...0x17f9 => true,
+ 0x1800...0x1805 => true,
+ 0x1806 => true,
+ 0x1807...0x180a => true,
+ 0x180b...0x180d => true,
+ 0x180e => true,
+ 0x180f => true,
+ 0x1810...0x1819 => true,
+ 0x1820...0x1842 => true,
+ 0x1843 => true,
+ 0x1844...0x1878 => true,
+ 0x1880...0x1884 => true,
+ 0x1885...0x1886 => true,
+ 0x1887...0x18a8 => true,
+ 0x18a9 => true,
+ 0x18aa => true,
+ 0x18b0...0x18f5 => true,
+ 0x1900...0x191e => true,
+ 0x1920...0x1922 => true,
+ 0x1923...0x1926 => true,
+ 0x1927...0x1928 => true,
+ 0x1929...0x192b => true,
+ 0x1930...0x1931 => true,
+ 0x1932 => true,
+ 0x1933...0x1938 => true,
+ 0x1939...0x193b => true,
+ 0x1940 => true,
+ 0x1944...0x1945 => true,
+ 0x1946...0x194f => true,
+ 0x1950...0x196d => true,
+ 0x1970...0x1974 => true,
+ 0x1980...0x19ab => true,
+ 0x19b0...0x19c9 => true,
+ 0x19d0...0x19d9 => true,
+ 0x19da => true,
+ 0x19de...0x19ff => true,
+ 0x1a00...0x1a16 => true,
+ 0x1a17...0x1a18 => true,
+ 0x1a19...0x1a1a => true,
+ 0x1a1b => true,
+ 0x1a1e...0x1a1f => true,
+ 0x1a20...0x1a54 => true,
+ 0x1a55 => true,
+ 0x1a56 => true,
+ 0x1a57 => true,
+ 0x1a58...0x1a5e => true,
+ 0x1a60 => true,
+ 0x1a61 => true,
+ 0x1a62 => true,
+ 0x1a63...0x1a64 => true,
+ 0x1a65...0x1a6c => true,
+ 0x1a6d...0x1a72 => true,
+ 0x1a73...0x1a7c => true,
+ 0x1a7f => true,
+ 0x1a80...0x1a89 => true,
+ 0x1a90...0x1a99 => true,
+ 0x1aa0...0x1aa6 => true,
+ 0x1aa7 => true,
+ 0x1aa8...0x1aad => true,
+ 0x1ab0...0x1abd => true,
+ 0x1abe => true,
+ 0x1abf...0x1ace => true,
+ 0x1b00...0x1b03 => true,
+ 0x1b04 => true,
+ 0x1b05...0x1b33 => true,
+ 0x1b34 => true,
+ 0x1b35 => true,
+ 0x1b36...0x1b3a => true,
+ 0x1b3b => true,
+ 0x1b3c => true,
+ 0x1b3d...0x1b41 => true,
+ 0x1b42 => true,
+ 0x1b43...0x1b44 => true,
+ 0x1b45...0x1b4c => true,
+ 0x1b50...0x1b59 => true,
+ 0x1b5a...0x1b60 => true,
+ 0x1b61...0x1b6a => true,
+ 0x1b6b...0x1b73 => true,
+ 0x1b74...0x1b7c => true,
+ 0x1b7d...0x1b7e => true,
+ 0x1b80...0x1b81 => true,
+ 0x1b82 => true,
+ 0x1b83...0x1ba0 => true,
+ 0x1ba1 => true,
+ 0x1ba2...0x1ba5 => true,
+ 0x1ba6...0x1ba7 => true,
+ 0x1ba8...0x1ba9 => true,
+ 0x1baa => true,
+ 0x1bab...0x1bad => true,
+ 0x1bae...0x1baf => true,
+ 0x1bb0...0x1bb9 => true,
+ 0x1bba...0x1be5 => true,
+ 0x1be6 => true,
+ 0x1be7 => true,
+ 0x1be8...0x1be9 => true,
+ 0x1bea...0x1bec => true,
+ 0x1bed => true,
+ 0x1bee => true,
+ 0x1bef...0x1bf1 => true,
+ 0x1bf2...0x1bf3 => true,
+ 0x1bfc...0x1bff => true,
+ 0x1c00...0x1c23 => true,
+ 0x1c24...0x1c2b => true,
+ 0x1c2c...0x1c33 => true,
+ 0x1c34...0x1c35 => true,
+ 0x1c36...0x1c37 => true,
+ 0x1c3b...0x1c3f => true,
+ 0x1c40...0x1c49 => true,
+ 0x1c4d...0x1c4f => true,
+ 0x1c50...0x1c59 => true,
+ 0x1c5a...0x1c77 => true,
+ 0x1c78...0x1c7d => true,
+ 0x1c7e...0x1c7f => true,
+ 0x1c80...0x1c88 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1cc0...0x1cc7 => true,
+ 0x1cd0...0x1cd2 => true,
+ 0x1cd3 => true,
+ 0x1cd4...0x1ce0 => true,
+ 0x1ce1 => true,
+ 0x1ce2...0x1ce8 => true,
+ 0x1ce9...0x1cec => true,
+ 0x1ced => true,
+ 0x1cee...0x1cf3 => true,
+ 0x1cf4 => true,
+ 0x1cf5...0x1cf6 => true,
+ 0x1cf7 => true,
+ 0x1cf8...0x1cf9 => true,
+ 0x1cfa => true,
+ 0x1d00...0x1d2b => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d6b...0x1d77 => true,
+ 0x1d78 => true,
+ 0x1d79...0x1d9a => true,
+ 0x1d9b...0x1dbf => true,
+ 0x1dc0...0x1dff => true,
+ 0x1e00...0x1f15 => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f20...0x1f45 => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f...0x1f7d => true,
+ 0x1f80...0x1fb4 => true,
+ 0x1fb6...0x1fbc => true,
+ 0x1fbd => true,
+ 0x1fbe => true,
+ 0x1fbf...0x1fc1 => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fcc => true,
+ 0x1fcd...0x1fcf => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fdb => true,
+ 0x1fdd...0x1fdf => true,
+ 0x1fe0...0x1fec => true,
+ 0x1fed...0x1fef => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ffc => true,
+ 0x1ffd...0x1ffe => true,
+ 0x2000...0x200a => true,
+ 0x200b...0x200f => true,
+ 0x2011...0x2012 => true,
+ 0x2017 => true,
+ 0x201a => true,
+ 0x201b => true,
+ 0x201e => true,
+ 0x201f => true,
+ 0x2023 => true,
+ 0x2028 => true,
+ 0x2029 => true,
+ 0x202a...0x202e => true,
+ 0x202f => true,
+ 0x2031 => true,
+ 0x2034 => true,
+ 0x2036...0x2038 => true,
+ 0x2039 => true,
+ 0x203a => true,
+ 0x203c...0x203d => true,
+ 0x203f...0x2040 => true,
+ 0x2041...0x2043 => true,
+ 0x2044 => true,
+ 0x2045 => true,
+ 0x2046 => true,
+ 0x2047...0x2051 => true,
+ 0x2052 => true,
+ 0x2053 => true,
+ 0x2054 => true,
+ 0x2055...0x205e => true,
+ 0x205f => true,
+ 0x2060...0x2064 => true,
+ 0x2066...0x206f => true,
+ 0x2070 => true,
+ 0x2071 => true,
+ 0x2075...0x2079 => true,
+ 0x207a...0x207c => true,
+ 0x207d => true,
+ 0x207e => true,
+ 0x2080 => true,
+ 0x2085...0x2089 => true,
+ 0x208a...0x208c => true,
+ 0x208d => true,
+ 0x208e => true,
+ 0x2090...0x209c => true,
+ 0x20a0...0x20a8 => true,
+ 0x20aa...0x20ab => true,
+ 0x20ad...0x20c0 => true,
+ 0x20d0...0x20dc => true,
+ 0x20dd...0x20e0 => true,
+ 0x20e1 => true,
+ 0x20e2...0x20e4 => true,
+ 0x20e5...0x20f0 => true,
+ 0x2100...0x2101 => true,
+ 0x2102 => true,
+ 0x2104 => true,
+ 0x2106 => true,
+ 0x2107 => true,
+ 0x2108 => true,
+ 0x210a...0x2112 => true,
+ 0x2114 => true,
+ 0x2115 => true,
+ 0x2117 => true,
+ 0x2118 => true,
+ 0x2119...0x211d => true,
+ 0x211e...0x2120 => true,
+ 0x2123 => true,
+ 0x2124 => true,
+ 0x2125 => true,
+ 0x2127 => true,
+ 0x2128 => true,
+ 0x2129 => true,
+ 0x212a => true,
+ 0x212c...0x212d => true,
+ 0x212e => true,
+ 0x212f...0x2134 => true,
+ 0x2135...0x2138 => true,
+ 0x2139 => true,
+ 0x213a...0x213b => true,
+ 0x213c...0x213f => true,
+ 0x2140...0x2144 => true,
+ 0x2145...0x2149 => true,
+ 0x214a => true,
+ 0x214b => true,
+ 0x214c...0x214d => true,
+ 0x214e => true,
+ 0x214f => true,
+ 0x2150...0x2152 => true,
+ 0x2155...0x215a => true,
+ 0x215f => true,
+ 0x216c...0x216f => true,
+ 0x217a...0x2182 => true,
+ 0x2183...0x2184 => true,
+ 0x2185...0x2188 => true,
+ 0x218a...0x218b => true,
+ 0x219a...0x219b => true,
+ 0x219c...0x219f => true,
+ 0x21a0 => true,
+ 0x21a1...0x21a2 => true,
+ 0x21a3 => true,
+ 0x21a4...0x21a5 => true,
+ 0x21a6 => true,
+ 0x21a7...0x21ad => true,
+ 0x21ae => true,
+ 0x21af...0x21b7 => true,
+ 0x21ba...0x21cd => true,
+ 0x21ce...0x21cf => true,
+ 0x21d0...0x21d1 => true,
+ 0x21d3 => true,
+ 0x21d5...0x21e6 => true,
+ 0x21e8...0x21f3 => true,
+ 0x21f4...0x21ff => true,
+ 0x2201 => true,
+ 0x2204...0x2206 => true,
+ 0x2209...0x220a => true,
+ 0x220c...0x220e => true,
+ 0x2210 => true,
+ 0x2212...0x2214 => true,
+ 0x2216...0x2219 => true,
+ 0x221b...0x221c => true,
+ 0x2221...0x2222 => true,
+ 0x2224 => true,
+ 0x2226 => true,
+ 0x222d => true,
+ 0x222f...0x2233 => true,
+ 0x2238...0x223b => true,
+ 0x223e...0x2247 => true,
+ 0x2249...0x224b => true,
+ 0x224d...0x2251 => true,
+ 0x2253...0x225f => true,
+ 0x2262...0x2263 => true,
+ 0x2268...0x2269 => true,
+ 0x226c...0x226d => true,
+ 0x2270...0x2281 => true,
+ 0x2284...0x2285 => true,
+ 0x2288...0x2294 => true,
+ 0x2296...0x2298 => true,
+ 0x229a...0x22a4 => true,
+ 0x22a6...0x22be => true,
+ 0x22c0...0x22ff => true,
+ 0x2300...0x2307 => true,
+ 0x2308 => true,
+ 0x2309 => true,
+ 0x230a => true,
+ 0x230b => true,
+ 0x230c...0x2311 => true,
+ 0x2313...0x2319 => true,
+ 0x231c...0x231f => true,
+ 0x2320...0x2321 => true,
+ 0x2322...0x2328 => true,
+ 0x232b...0x237b => true,
+ 0x237c => true,
+ 0x237d...0x239a => true,
+ 0x239b...0x23b3 => true,
+ 0x23b4...0x23db => true,
+ 0x23dc...0x23e1 => true,
+ 0x23e2...0x23e8 => true,
+ 0x23ed...0x23ef => true,
+ 0x23f1...0x23f2 => true,
+ 0x23f4...0x2426 => true,
+ 0x2440...0x244a => true,
+ 0x24ea => true,
+ 0x254c...0x254f => true,
+ 0x2574...0x257f => true,
+ 0x2590...0x2591 => true,
+ 0x2596...0x259f => true,
+ 0x25a2 => true,
+ 0x25aa...0x25b1 => true,
+ 0x25b4...0x25b5 => true,
+ 0x25b8...0x25bb => true,
+ 0x25be...0x25bf => true,
+ 0x25c2...0x25c5 => true,
+ 0x25c9...0x25ca => true,
+ 0x25cc...0x25cd => true,
+ 0x25d2...0x25e1 => true,
+ 0x25e6...0x25ee => true,
+ 0x25f0...0x25f7 => true,
+ 0x25f8...0x25fc => true,
+ 0x25ff => true,
+ 0x2600...0x2604 => true,
+ 0x2607...0x2608 => true,
+ 0x260a...0x260d => true,
+ 0x2610...0x2613 => true,
+ 0x2616...0x261b => true,
+ 0x261d => true,
+ 0x261f...0x263f => true,
+ 0x2641 => true,
+ 0x2643...0x2647 => true,
+ 0x2654...0x265f => true,
+ 0x2662 => true,
+ 0x2666 => true,
+ 0x266b => true,
+ 0x266e => true,
+ 0x2670...0x267e => true,
+ 0x2680...0x2692 => true,
+ 0x2694...0x269d => true,
+ 0x26a0 => true,
+ 0x26a2...0x26a9 => true,
+ 0x26ac...0x26bc => true,
+ 0x26c0...0x26c3 => true,
+ 0x26e2 => true,
+ 0x26e4...0x26e7 => true,
+ 0x2700...0x2704 => true,
+ 0x2706...0x2709 => true,
+ 0x270c...0x2727 => true,
+ 0x2729...0x273c => true,
+ 0x273e...0x274b => true,
+ 0x274d => true,
+ 0x274f...0x2752 => true,
+ 0x2756 => true,
+ 0x2758...0x2767 => true,
+ 0x2768 => true,
+ 0x2769 => true,
+ 0x276a => true,
+ 0x276b => true,
+ 0x276c => true,
+ 0x276d => true,
+ 0x276e => true,
+ 0x276f => true,
+ 0x2770 => true,
+ 0x2771 => true,
+ 0x2772 => true,
+ 0x2773 => true,
+ 0x2774 => true,
+ 0x2775 => true,
+ 0x2780...0x2793 => true,
+ 0x2794 => true,
+ 0x2798...0x27af => true,
+ 0x27b1...0x27be => true,
+ 0x27c0...0x27c4 => true,
+ 0x27c5 => true,
+ 0x27c6 => true,
+ 0x27c7...0x27e5 => true,
+ 0x27ee => true,
+ 0x27ef => true,
+ 0x27f0...0x27ff => true,
+ 0x2800...0x28ff => true,
+ 0x2900...0x2982 => true,
+ 0x2983 => true,
+ 0x2984 => true,
+ 0x2987 => true,
+ 0x2988 => true,
+ 0x2989 => true,
+ 0x298a => true,
+ 0x298b => true,
+ 0x298c => true,
+ 0x298d => true,
+ 0x298e => true,
+ 0x298f => true,
+ 0x2990 => true,
+ 0x2991 => true,
+ 0x2992 => true,
+ 0x2993 => true,
+ 0x2994 => true,
+ 0x2995 => true,
+ 0x2996 => true,
+ 0x2997 => true,
+ 0x2998 => true,
+ 0x2999...0x29d7 => true,
+ 0x29d8 => true,
+ 0x29d9 => true,
+ 0x29da => true,
+ 0x29db => true,
+ 0x29dc...0x29fb => true,
+ 0x29fc => true,
+ 0x29fd => true,
+ 0x29fe...0x2aff => true,
+ 0x2b00...0x2b1a => true,
+ 0x2b1d...0x2b2f => true,
+ 0x2b30...0x2b44 => true,
+ 0x2b45...0x2b46 => true,
+ 0x2b47...0x2b4c => true,
+ 0x2b4d...0x2b4f => true,
+ 0x2b51...0x2b54 => true,
+ 0x2b5a...0x2b73 => true,
+ 0x2b76...0x2b95 => true,
+ 0x2b97...0x2bff => true,
+ 0x2c00...0x2c7b => true,
+ 0x2c7c...0x2c7d => true,
+ 0x2c7e...0x2ce4 => true,
+ 0x2ce5...0x2cea => true,
+ 0x2ceb...0x2cee => true,
+ 0x2cef...0x2cf1 => true,
+ 0x2cf2...0x2cf3 => true,
+ 0x2cf9...0x2cfc => true,
+ 0x2cfd => true,
+ 0x2cfe...0x2cff => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0x2d30...0x2d67 => true,
+ 0x2d6f => true,
+ 0x2d70 => true,
+ 0x2d7f => true,
+ 0x2d80...0x2d96 => true,
+ 0x2da0...0x2da6 => true,
+ 0x2da8...0x2dae => true,
+ 0x2db0...0x2db6 => true,
+ 0x2db8...0x2dbe => true,
+ 0x2dc0...0x2dc6 => true,
+ 0x2dc8...0x2dce => true,
+ 0x2dd0...0x2dd6 => true,
+ 0x2dd8...0x2dde => true,
+ 0x2de0...0x2dff => true,
+ 0x2e00...0x2e01 => true,
+ 0x2e02 => true,
+ 0x2e03 => true,
+ 0x2e04 => true,
+ 0x2e05 => true,
+ 0x2e06...0x2e08 => true,
+ 0x2e09 => true,
+ 0x2e0a => true,
+ 0x2e0b => true,
+ 0x2e0c => true,
+ 0x2e0d => true,
+ 0x2e0e...0x2e16 => true,
+ 0x2e17 => true,
+ 0x2e18...0x2e19 => true,
+ 0x2e1a => true,
+ 0x2e1b => true,
+ 0x2e1c => true,
+ 0x2e1d => true,
+ 0x2e1e...0x2e1f => true,
+ 0x2e20 => true,
+ 0x2e21 => true,
+ 0x2e22 => true,
+ 0x2e23 => true,
+ 0x2e24 => true,
+ 0x2e25 => true,
+ 0x2e26 => true,
+ 0x2e27 => true,
+ 0x2e28 => true,
+ 0x2e29 => true,
+ 0x2e2a...0x2e2e => true,
+ 0x2e2f => true,
+ 0x2e30...0x2e39 => true,
+ 0x2e3a...0x2e3b => true,
+ 0x2e3c...0x2e3f => true,
+ 0x2e40 => true,
+ 0x2e41 => true,
+ 0x2e42 => true,
+ 0x2e43...0x2e4f => true,
+ 0x2e50...0x2e51 => true,
+ 0x2e52...0x2e54 => true,
+ 0x2e55 => true,
+ 0x2e56 => true,
+ 0x2e57 => true,
+ 0x2e58 => true,
+ 0x2e59 => true,
+ 0x2e5a => true,
+ 0x2e5b => true,
+ 0x2e5c => true,
+ 0x2e5d => true,
+ 0x303f => true,
+ 0x4dc0...0x4dff => true,
+ 0xa4d0...0xa4f7 => true,
+ 0xa4f8...0xa4fd => true,
+ 0xa4fe...0xa4ff => true,
+ 0xa500...0xa60b => true,
+ 0xa60c => true,
+ 0xa60d...0xa60f => true,
+ 0xa610...0xa61f => true,
+ 0xa620...0xa629 => true,
+ 0xa62a...0xa62b => true,
+ 0xa640...0xa66d => true,
+ 0xa66e => true,
+ 0xa66f => true,
+ 0xa670...0xa672 => true,
+ 0xa673 => true,
+ 0xa674...0xa67d => true,
+ 0xa67e => true,
+ 0xa67f => true,
+ 0xa680...0xa69b => true,
+ 0xa69c...0xa69d => true,
+ 0xa69e...0xa69f => true,
+ 0xa6a0...0xa6e5 => true,
+ 0xa6e6...0xa6ef => true,
+ 0xa6f0...0xa6f1 => true,
+ 0xa6f2...0xa6f7 => true,
+ 0xa700...0xa716 => true,
+ 0xa717...0xa71f => true,
+ 0xa720...0xa721 => true,
+ 0xa722...0xa76f => true,
+ 0xa770 => true,
+ 0xa771...0xa787 => true,
+ 0xa788 => true,
+ 0xa789...0xa78a => true,
+ 0xa78b...0xa78e => true,
+ 0xa78f => true,
+ 0xa790...0xa7ca => true,
+ 0xa7d0...0xa7d1 => true,
+ 0xa7d3 => true,
+ 0xa7d5...0xa7d9 => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f5...0xa7f6 => true,
+ 0xa7f7 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa7fa => true,
+ 0xa7fb...0xa801 => true,
+ 0xa802 => true,
+ 0xa803...0xa805 => true,
+ 0xa806 => true,
+ 0xa807...0xa80a => true,
+ 0xa80b => true,
+ 0xa80c...0xa822 => true,
+ 0xa823...0xa824 => true,
+ 0xa825...0xa826 => true,
+ 0xa827 => true,
+ 0xa828...0xa82b => true,
+ 0xa82c => true,
+ 0xa830...0xa835 => true,
+ 0xa836...0xa837 => true,
+ 0xa838 => true,
+ 0xa839 => true,
+ 0xa840...0xa873 => true,
+ 0xa874...0xa877 => true,
+ 0xa880...0xa881 => true,
+ 0xa882...0xa8b3 => true,
+ 0xa8b4...0xa8c3 => true,
+ 0xa8c4...0xa8c5 => true,
+ 0xa8ce...0xa8cf => true,
+ 0xa8d0...0xa8d9 => true,
+ 0xa8e0...0xa8f1 => true,
+ 0xa8f2...0xa8f7 => true,
+ 0xa8f8...0xa8fa => true,
+ 0xa8fb => true,
+ 0xa8fc => true,
+ 0xa8fd...0xa8fe => true,
+ 0xa8ff => true,
+ 0xa900...0xa909 => true,
+ 0xa90a...0xa925 => true,
+ 0xa926...0xa92d => true,
+ 0xa92e...0xa92f => true,
+ 0xa930...0xa946 => true,
+ 0xa947...0xa951 => true,
+ 0xa952...0xa953 => true,
+ 0xa95f => true,
+ 0xa980...0xa982 => true,
+ 0xa983 => true,
+ 0xa984...0xa9b2 => true,
+ 0xa9b3 => true,
+ 0xa9b4...0xa9b5 => true,
+ 0xa9b6...0xa9b9 => true,
+ 0xa9ba...0xa9bb => true,
+ 0xa9bc...0xa9bd => true,
+ 0xa9be...0xa9c0 => true,
+ 0xa9c1...0xa9cd => true,
+ 0xa9cf => true,
+ 0xa9d0...0xa9d9 => true,
+ 0xa9de...0xa9df => true,
+ 0xa9e0...0xa9e4 => true,
+ 0xa9e5 => true,
+ 0xa9e6 => true,
+ 0xa9e7...0xa9ef => true,
+ 0xa9f0...0xa9f9 => true,
+ 0xa9fa...0xa9fe => true,
+ 0xaa00...0xaa28 => true,
+ 0xaa29...0xaa2e => true,
+ 0xaa2f...0xaa30 => true,
+ 0xaa31...0xaa32 => true,
+ 0xaa33...0xaa34 => true,
+ 0xaa35...0xaa36 => true,
+ 0xaa40...0xaa42 => true,
+ 0xaa43 => true,
+ 0xaa44...0xaa4b => true,
+ 0xaa4c => true,
+ 0xaa4d => true,
+ 0xaa50...0xaa59 => true,
+ 0xaa5c...0xaa5f => true,
+ 0xaa60...0xaa6f => true,
+ 0xaa70 => true,
+ 0xaa71...0xaa76 => true,
+ 0xaa77...0xaa79 => true,
+ 0xaa7a => true,
+ 0xaa7b => true,
+ 0xaa7c => true,
+ 0xaa7d => true,
+ 0xaa7e...0xaaaf => true,
+ 0xaab0 => true,
+ 0xaab1 => true,
+ 0xaab2...0xaab4 => true,
+ 0xaab5...0xaab6 => true,
+ 0xaab7...0xaab8 => true,
+ 0xaab9...0xaabd => true,
+ 0xaabe...0xaabf => true,
+ 0xaac0 => true,
+ 0xaac1 => true,
+ 0xaac2 => true,
+ 0xaadb...0xaadc => true,
+ 0xaadd => true,
+ 0xaade...0xaadf => true,
+ 0xaae0...0xaaea => true,
+ 0xaaeb => true,
+ 0xaaec...0xaaed => true,
+ 0xaaee...0xaaef => true,
+ 0xaaf0...0xaaf1 => true,
+ 0xaaf2 => true,
+ 0xaaf3...0xaaf4 => true,
+ 0xaaf5 => true,
+ 0xaaf6 => true,
+ 0xab01...0xab06 => true,
+ 0xab09...0xab0e => true,
+ 0xab11...0xab16 => true,
+ 0xab20...0xab26 => true,
+ 0xab28...0xab2e => true,
+ 0xab30...0xab5a => true,
+ 0xab5b => true,
+ 0xab5c...0xab5f => true,
+ 0xab60...0xab68 => true,
+ 0xab69 => true,
+ 0xab6a...0xab6b => true,
+ 0xab70...0xabbf => true,
+ 0xabc0...0xabe2 => true,
+ 0xabe3...0xabe4 => true,
+ 0xabe5 => true,
+ 0xabe6...0xabe7 => true,
+ 0xabe8 => true,
+ 0xabe9...0xabea => true,
+ 0xabeb => true,
+ 0xabec => true,
+ 0xabed => true,
+ 0xabf0...0xabf9 => true,
+ 0xd7b0...0xd7c6 => true,
+ 0xd7cb...0xd7fb => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xfb1d => true,
+ 0xfb1e => true,
+ 0xfb1f...0xfb28 => true,
+ 0xfb29 => true,
+ 0xfb2a...0xfb36 => true,
+ 0xfb38...0xfb3c => true,
+ 0xfb3e => true,
+ 0xfb40...0xfb41 => true,
+ 0xfb43...0xfb44 => true,
+ 0xfb46...0xfbb1 => true,
+ 0xfbb2...0xfbc2 => true,
+ 0xfbd3...0xfd3d => true,
+ 0xfd3e => true,
+ 0xfd3f => true,
+ 0xfd40...0xfd4f => true,
+ 0xfd50...0xfd8f => true,
+ 0xfd92...0xfdc7 => true,
+ 0xfdcf => true,
+ 0xfdf0...0xfdfb => true,
+ 0xfdfc => true,
+ 0xfdfd...0xfdff => true,
+ 0xfe20...0xfe2f => true,
+ 0xfe70...0xfe74 => true,
+ 0xfe76...0xfefc => true,
+ 0xfeff => true,
+ 0xfff9...0xfffb => true,
+ 0xfffc => true,
+ 0x10000...0x1000b => true,
+ 0x1000d...0x10026 => true,
+ 0x10028...0x1003a => true,
+ 0x1003c...0x1003d => true,
+ 0x1003f...0x1004d => true,
+ 0x10050...0x1005d => true,
+ 0x10080...0x100fa => true,
+ 0x10100...0x10102 => true,
+ 0x10107...0x10133 => true,
+ 0x10137...0x1013f => true,
+ 0x10140...0x10174 => true,
+ 0x10175...0x10178 => true,
+ 0x10179...0x10189 => true,
+ 0x1018a...0x1018b => true,
+ 0x1018c...0x1018e => true,
+ 0x10190...0x1019c => true,
+ 0x101a0 => true,
+ 0x101d0...0x101fc => true,
+ 0x101fd => true,
+ 0x10280...0x1029c => true,
+ 0x102a0...0x102d0 => true,
+ 0x102e0 => true,
+ 0x102e1...0x102fb => true,
+ 0x10300...0x1031f => true,
+ 0x10320...0x10323 => true,
+ 0x1032d...0x10340 => true,
+ 0x10341 => true,
+ 0x10342...0x10349 => true,
+ 0x1034a => true,
+ 0x10350...0x10375 => true,
+ 0x10376...0x1037a => true,
+ 0x10380...0x1039d => true,
+ 0x1039f => true,
+ 0x103a0...0x103c3 => true,
+ 0x103c8...0x103cf => true,
+ 0x103d0 => true,
+ 0x103d1...0x103d5 => true,
+ 0x10400...0x1044f => true,
+ 0x10450...0x1049d => true,
+ 0x104a0...0x104a9 => true,
+ 0x104b0...0x104d3 => true,
+ 0x104d8...0x104fb => true,
+ 0x10500...0x10527 => true,
+ 0x10530...0x10563 => true,
+ 0x1056f => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10600...0x10736 => true,
+ 0x10740...0x10755 => true,
+ 0x10760...0x10767 => true,
+ 0x10780...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x10800...0x10805 => true,
+ 0x10808 => true,
+ 0x1080a...0x10835 => true,
+ 0x10837...0x10838 => true,
+ 0x1083c => true,
+ 0x1083f...0x10855 => true,
+ 0x10857 => true,
+ 0x10858...0x1085f => true,
+ 0x10860...0x10876 => true,
+ 0x10877...0x10878 => true,
+ 0x10879...0x1087f => true,
+ 0x10880...0x1089e => true,
+ 0x108a7...0x108af => true,
+ 0x108e0...0x108f2 => true,
+ 0x108f4...0x108f5 => true,
+ 0x108fb...0x108ff => true,
+ 0x10900...0x10915 => true,
+ 0x10916...0x1091b => true,
+ 0x1091f => true,
+ 0x10920...0x10939 => true,
+ 0x1093f => true,
+ 0x10980...0x109b7 => true,
+ 0x109bc...0x109bd => true,
+ 0x109be...0x109bf => true,
+ 0x109c0...0x109cf => true,
+ 0x109d2...0x109ff => true,
+ 0x10a00 => true,
+ 0x10a01...0x10a03 => true,
+ 0x10a05...0x10a06 => true,
+ 0x10a0c...0x10a0f => true,
+ 0x10a10...0x10a13 => true,
+ 0x10a15...0x10a17 => true,
+ 0x10a19...0x10a35 => true,
+ 0x10a38...0x10a3a => true,
+ 0x10a3f => true,
+ 0x10a40...0x10a48 => true,
+ 0x10a50...0x10a58 => true,
+ 0x10a60...0x10a7c => true,
+ 0x10a7d...0x10a7e => true,
+ 0x10a7f => true,
+ 0x10a80...0x10a9c => true,
+ 0x10a9d...0x10a9f => true,
+ 0x10ac0...0x10ac7 => true,
+ 0x10ac8 => true,
+ 0x10ac9...0x10ae4 => true,
+ 0x10ae5...0x10ae6 => true,
+ 0x10aeb...0x10aef => true,
+ 0x10af0...0x10af6 => true,
+ 0x10b00...0x10b35 => true,
+ 0x10b39...0x10b3f => true,
+ 0x10b40...0x10b55 => true,
+ 0x10b58...0x10b5f => true,
+ 0x10b60...0x10b72 => true,
+ 0x10b78...0x10b7f => true,
+ 0x10b80...0x10b91 => true,
+ 0x10b99...0x10b9c => true,
+ 0x10ba9...0x10baf => true,
+ 0x10c00...0x10c48 => true,
+ 0x10c80...0x10cb2 => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x10cfa...0x10cff => true,
+ 0x10d00...0x10d23 => true,
+ 0x10d24...0x10d27 => true,
+ 0x10d30...0x10d39 => true,
+ 0x10e60...0x10e7e => true,
+ 0x10e80...0x10ea9 => true,
+ 0x10eab...0x10eac => true,
+ 0x10ead => true,
+ 0x10eb0...0x10eb1 => true,
+ 0x10efd...0x10eff => true,
+ 0x10f00...0x10f1c => true,
+ 0x10f1d...0x10f26 => true,
+ 0x10f27 => true,
+ 0x10f30...0x10f45 => true,
+ 0x10f46...0x10f50 => true,
+ 0x10f51...0x10f54 => true,
+ 0x10f55...0x10f59 => true,
+ 0x10f70...0x10f81 => true,
+ 0x10f82...0x10f85 => true,
+ 0x10f86...0x10f89 => true,
+ 0x10fb0...0x10fc4 => true,
+ 0x10fc5...0x10fcb => true,
+ 0x10fe0...0x10ff6 => true,
+ 0x11000 => true,
+ 0x11001 => true,
+ 0x11002 => true,
+ 0x11003...0x11037 => true,
+ 0x11038...0x11046 => true,
+ 0x11047...0x1104d => true,
+ 0x11052...0x11065 => true,
+ 0x11066...0x1106f => true,
+ 0x11070 => true,
+ 0x11071...0x11072 => true,
+ 0x11073...0x11074 => true,
+ 0x11075 => true,
+ 0x1107f...0x11081 => true,
+ 0x11082 => true,
+ 0x11083...0x110af => true,
+ 0x110b0...0x110b2 => true,
+ 0x110b3...0x110b6 => true,
+ 0x110b7...0x110b8 => true,
+ 0x110b9...0x110ba => true,
+ 0x110bb...0x110bc => true,
+ 0x110bd => true,
+ 0x110be...0x110c1 => true,
+ 0x110c2 => true,
+ 0x110cd => true,
+ 0x110d0...0x110e8 => true,
+ 0x110f0...0x110f9 => true,
+ 0x11100...0x11102 => true,
+ 0x11103...0x11126 => true,
+ 0x11127...0x1112b => true,
+ 0x1112c => true,
+ 0x1112d...0x11134 => true,
+ 0x11136...0x1113f => true,
+ 0x11140...0x11143 => true,
+ 0x11144 => true,
+ 0x11145...0x11146 => true,
+ 0x11147 => true,
+ 0x11150...0x11172 => true,
+ 0x11173 => true,
+ 0x11174...0x11175 => true,
+ 0x11176 => true,
+ 0x11180...0x11181 => true,
+ 0x11182 => true,
+ 0x11183...0x111b2 => true,
+ 0x111b3...0x111b5 => true,
+ 0x111b6...0x111be => true,
+ 0x111bf...0x111c0 => true,
+ 0x111c1...0x111c4 => true,
+ 0x111c5...0x111c8 => true,
+ 0x111c9...0x111cc => true,
+ 0x111cd => true,
+ 0x111ce => true,
+ 0x111cf => true,
+ 0x111d0...0x111d9 => true,
+ 0x111da => true,
+ 0x111db => true,
+ 0x111dc => true,
+ 0x111dd...0x111df => true,
+ 0x111e1...0x111f4 => true,
+ 0x11200...0x11211 => true,
+ 0x11213...0x1122b => true,
+ 0x1122c...0x1122e => true,
+ 0x1122f...0x11231 => true,
+ 0x11232...0x11233 => true,
+ 0x11234 => true,
+ 0x11235 => true,
+ 0x11236...0x11237 => true,
+ 0x11238...0x1123d => true,
+ 0x1123e => true,
+ 0x1123f...0x11240 => true,
+ 0x11241 => true,
+ 0x11280...0x11286 => true,
+ 0x11288 => true,
+ 0x1128a...0x1128d => true,
+ 0x1128f...0x1129d => true,
+ 0x1129f...0x112a8 => true,
+ 0x112a9 => true,
+ 0x112b0...0x112de => true,
+ 0x112df => true,
+ 0x112e0...0x112e2 => true,
+ 0x112e3...0x112ea => true,
+ 0x112f0...0x112f9 => true,
+ 0x11300...0x11301 => true,
+ 0x11302...0x11303 => true,
+ 0x11305...0x1130c => true,
+ 0x1130f...0x11310 => true,
+ 0x11313...0x11328 => true,
+ 0x1132a...0x11330 => true,
+ 0x11332...0x11333 => true,
+ 0x11335...0x11339 => true,
+ 0x1133b...0x1133c => true,
+ 0x1133d => true,
+ 0x1133e...0x1133f => true,
+ 0x11340 => true,
+ 0x11341...0x11344 => true,
+ 0x11347...0x11348 => true,
+ 0x1134b...0x1134d => true,
+ 0x11350 => true,
+ 0x11357 => true,
+ 0x1135d...0x11361 => true,
+ 0x11362...0x11363 => true,
+ 0x11366...0x1136c => true,
+ 0x11370...0x11374 => true,
+ 0x11400...0x11434 => true,
+ 0x11435...0x11437 => true,
+ 0x11438...0x1143f => true,
+ 0x11440...0x11441 => true,
+ 0x11442...0x11444 => true,
+ 0x11445 => true,
+ 0x11446 => true,
+ 0x11447...0x1144a => true,
+ 0x1144b...0x1144f => true,
+ 0x11450...0x11459 => true,
+ 0x1145a...0x1145b => true,
+ 0x1145d => true,
+ 0x1145e => true,
+ 0x1145f...0x11461 => true,
+ 0x11480...0x114af => true,
+ 0x114b0...0x114b2 => true,
+ 0x114b3...0x114b8 => true,
+ 0x114b9 => true,
+ 0x114ba => true,
+ 0x114bb...0x114be => true,
+ 0x114bf...0x114c0 => true,
+ 0x114c1 => true,
+ 0x114c2...0x114c3 => true,
+ 0x114c4...0x114c5 => true,
+ 0x114c6 => true,
+ 0x114c7 => true,
+ 0x114d0...0x114d9 => true,
+ 0x11580...0x115ae => true,
+ 0x115af...0x115b1 => true,
+ 0x115b2...0x115b5 => true,
+ 0x115b8...0x115bb => true,
+ 0x115bc...0x115bd => true,
+ 0x115be => true,
+ 0x115bf...0x115c0 => true,
+ 0x115c1...0x115d7 => true,
+ 0x115d8...0x115db => true,
+ 0x115dc...0x115dd => true,
+ 0x11600...0x1162f => true,
+ 0x11630...0x11632 => true,
+ 0x11633...0x1163a => true,
+ 0x1163b...0x1163c => true,
+ 0x1163d => true,
+ 0x1163e => true,
+ 0x1163f...0x11640 => true,
+ 0x11641...0x11643 => true,
+ 0x11644 => true,
+ 0x11650...0x11659 => true,
+ 0x11660...0x1166c => true,
+ 0x11680...0x116aa => true,
+ 0x116ab => true,
+ 0x116ac => true,
+ 0x116ad => true,
+ 0x116ae...0x116af => true,
+ 0x116b0...0x116b5 => true,
+ 0x116b6 => true,
+ 0x116b7 => true,
+ 0x116b8 => true,
+ 0x116b9 => true,
+ 0x116c0...0x116c9 => true,
+ 0x11700...0x1171a => true,
+ 0x1171d...0x1171f => true,
+ 0x11720...0x11721 => true,
+ 0x11722...0x11725 => true,
+ 0x11726 => true,
+ 0x11727...0x1172b => true,
+ 0x11730...0x11739 => true,
+ 0x1173a...0x1173b => true,
+ 0x1173c...0x1173e => true,
+ 0x1173f => true,
+ 0x11740...0x11746 => true,
+ 0x11800...0x1182b => true,
+ 0x1182c...0x1182e => true,
+ 0x1182f...0x11837 => true,
+ 0x11838 => true,
+ 0x11839...0x1183a => true,
+ 0x1183b => true,
+ 0x118a0...0x118df => true,
+ 0x118e0...0x118e9 => true,
+ 0x118ea...0x118f2 => true,
+ 0x118ff...0x11906 => true,
+ 0x11909 => true,
+ 0x1190c...0x11913 => true,
+ 0x11915...0x11916 => true,
+ 0x11918...0x1192f => true,
+ 0x11930...0x11935 => true,
+ 0x11937...0x11938 => true,
+ 0x1193b...0x1193c => true,
+ 0x1193d => true,
+ 0x1193e => true,
+ 0x1193f => true,
+ 0x11940 => true,
+ 0x11941 => true,
+ 0x11942 => true,
+ 0x11943 => true,
+ 0x11944...0x11946 => true,
+ 0x11950...0x11959 => true,
+ 0x119a0...0x119a7 => true,
+ 0x119aa...0x119d0 => true,
+ 0x119d1...0x119d3 => true,
+ 0x119d4...0x119d7 => true,
+ 0x119da...0x119db => true,
+ 0x119dc...0x119df => true,
+ 0x119e0 => true,
+ 0x119e1 => true,
+ 0x119e2 => true,
+ 0x119e3 => true,
+ 0x119e4 => true,
+ 0x11a00 => true,
+ 0x11a01...0x11a0a => true,
+ 0x11a0b...0x11a32 => true,
+ 0x11a33...0x11a38 => true,
+ 0x11a39 => true,
+ 0x11a3a => true,
+ 0x11a3b...0x11a3e => true,
+ 0x11a3f...0x11a46 => true,
+ 0x11a47 => true,
+ 0x11a50 => true,
+ 0x11a51...0x11a56 => true,
+ 0x11a57...0x11a58 => true,
+ 0x11a59...0x11a5b => true,
+ 0x11a5c...0x11a89 => true,
+ 0x11a8a...0x11a96 => true,
+ 0x11a97 => true,
+ 0x11a98...0x11a99 => true,
+ 0x11a9a...0x11a9c => true,
+ 0x11a9d => true,
+ 0x11a9e...0x11aa2 => true,
+ 0x11ab0...0x11af8 => true,
+ 0x11b00...0x11b09 => true,
+ 0x11c00...0x11c08 => true,
+ 0x11c0a...0x11c2e => true,
+ 0x11c2f => true,
+ 0x11c30...0x11c36 => true,
+ 0x11c38...0x11c3d => true,
+ 0x11c3e => true,
+ 0x11c3f => true,
+ 0x11c40 => true,
+ 0x11c41...0x11c45 => true,
+ 0x11c50...0x11c59 => true,
+ 0x11c5a...0x11c6c => true,
+ 0x11c70...0x11c71 => true,
+ 0x11c72...0x11c8f => true,
+ 0x11c92...0x11ca7 => true,
+ 0x11ca9 => true,
+ 0x11caa...0x11cb0 => true,
+ 0x11cb1 => true,
+ 0x11cb2...0x11cb3 => true,
+ 0x11cb4 => true,
+ 0x11cb5...0x11cb6 => true,
+ 0x11d00...0x11d06 => true,
+ 0x11d08...0x11d09 => true,
+ 0x11d0b...0x11d30 => true,
+ 0x11d31...0x11d36 => true,
+ 0x11d3a => true,
+ 0x11d3c...0x11d3d => true,
+ 0x11d3f...0x11d45 => true,
+ 0x11d46 => true,
+ 0x11d47 => true,
+ 0x11d50...0x11d59 => true,
+ 0x11d60...0x11d65 => true,
+ 0x11d67...0x11d68 => true,
+ 0x11d6a...0x11d89 => true,
+ 0x11d8a...0x11d8e => true,
+ 0x11d90...0x11d91 => true,
+ 0x11d93...0x11d94 => true,
+ 0x11d95 => true,
+ 0x11d96 => true,
+ 0x11d97 => true,
+ 0x11d98 => true,
+ 0x11da0...0x11da9 => true,
+ 0x11ee0...0x11ef2 => true,
+ 0x11ef3...0x11ef4 => true,
+ 0x11ef5...0x11ef6 => true,
+ 0x11ef7...0x11ef8 => true,
+ 0x11f00...0x11f01 => true,
+ 0x11f02 => true,
+ 0x11f03 => true,
+ 0x11f04...0x11f10 => true,
+ 0x11f12...0x11f33 => true,
+ 0x11f34...0x11f35 => true,
+ 0x11f36...0x11f3a => true,
+ 0x11f3e...0x11f3f => true,
+ 0x11f40 => true,
+ 0x11f41 => true,
+ 0x11f42 => true,
+ 0x11f43...0x11f4f => true,
+ 0x11f50...0x11f59 => true,
+ 0x11fb0 => true,
+ 0x11fc0...0x11fd4 => true,
+ 0x11fd5...0x11fdc => true,
+ 0x11fdd...0x11fe0 => true,
+ 0x11fe1...0x11ff1 => true,
+ 0x11fff => true,
+ 0x12000...0x12399 => true,
+ 0x12400...0x1246e => true,
+ 0x12470...0x12474 => true,
+ 0x12480...0x12543 => true,
+ 0x12f90...0x12ff0 => true,
+ 0x12ff1...0x12ff2 => true,
+ 0x13000...0x1342f => true,
+ 0x13430...0x1343f => true,
+ 0x13440 => true,
+ 0x13441...0x13446 => true,
+ 0x13447...0x13455 => true,
+ 0x14400...0x14646 => true,
+ 0x16800...0x16a38 => true,
+ 0x16a40...0x16a5e => true,
+ 0x16a60...0x16a69 => true,
+ 0x16a6e...0x16a6f => true,
+ 0x16a70...0x16abe => true,
+ 0x16ac0...0x16ac9 => true,
+ 0x16ad0...0x16aed => true,
+ 0x16af0...0x16af4 => true,
+ 0x16af5 => true,
+ 0x16b00...0x16b2f => true,
+ 0x16b30...0x16b36 => true,
+ 0x16b37...0x16b3b => true,
+ 0x16b3c...0x16b3f => true,
+ 0x16b40...0x16b43 => true,
+ 0x16b44 => true,
+ 0x16b45 => true,
+ 0x16b50...0x16b59 => true,
+ 0x16b5b...0x16b61 => true,
+ 0x16b63...0x16b77 => true,
+ 0x16b7d...0x16b8f => true,
+ 0x16e40...0x16e7f => true,
+ 0x16e80...0x16e96 => true,
+ 0x16e97...0x16e9a => true,
+ 0x16f00...0x16f4a => true,
+ 0x16f4f => true,
+ 0x16f50 => true,
+ 0x16f51...0x16f87 => true,
+ 0x16f8f...0x16f92 => true,
+ 0x16f93...0x16f9f => true,
+ 0x1bc00...0x1bc6a => true,
+ 0x1bc70...0x1bc7c => true,
+ 0x1bc80...0x1bc88 => true,
+ 0x1bc90...0x1bc99 => true,
+ 0x1bc9c => true,
+ 0x1bc9d...0x1bc9e => true,
+ 0x1bc9f => true,
+ 0x1bca0...0x1bca3 => true,
+ 0x1cf00...0x1cf2d => true,
+ 0x1cf30...0x1cf46 => true,
+ 0x1cf50...0x1cfc3 => true,
+ 0x1d000...0x1d0f5 => true,
+ 0x1d100...0x1d126 => true,
+ 0x1d129...0x1d164 => true,
+ 0x1d165...0x1d166 => true,
+ 0x1d167...0x1d169 => true,
+ 0x1d16a...0x1d16c => true,
+ 0x1d16d...0x1d172 => true,
+ 0x1d173...0x1d17a => true,
+ 0x1d17b...0x1d182 => true,
+ 0x1d183...0x1d184 => true,
+ 0x1d185...0x1d18b => true,
+ 0x1d18c...0x1d1a9 => true,
+ 0x1d1aa...0x1d1ad => true,
+ 0x1d1ae...0x1d1ea => true,
+ 0x1d200...0x1d241 => true,
+ 0x1d242...0x1d244 => true,
+ 0x1d245 => true,
+ 0x1d2c0...0x1d2d3 => true,
+ 0x1d2e0...0x1d2f3 => true,
+ 0x1d300...0x1d356 => true,
+ 0x1d360...0x1d378 => true,
+ 0x1d400...0x1d454 => true,
+ 0x1d456...0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d51e...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d552...0x1d6a5 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6c1 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6db => true,
+ 0x1d6dc...0x1d6fa => true,
+ 0x1d6fb => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d715 => true,
+ 0x1d716...0x1d734 => true,
+ 0x1d735 => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d74f => true,
+ 0x1d750...0x1d76e => true,
+ 0x1d76f => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d789 => true,
+ 0x1d78a...0x1d7a8 => true,
+ 0x1d7a9 => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c3 => true,
+ 0x1d7c4...0x1d7cb => true,
+ 0x1d7ce...0x1d7ff => true,
+ 0x1d800...0x1d9ff => true,
+ 0x1da00...0x1da36 => true,
+ 0x1da37...0x1da3a => true,
+ 0x1da3b...0x1da6c => true,
+ 0x1da6d...0x1da74 => true,
+ 0x1da75 => true,
+ 0x1da76...0x1da83 => true,
+ 0x1da84 => true,
+ 0x1da85...0x1da86 => true,
+ 0x1da87...0x1da8b => true,
+ 0x1da9b...0x1da9f => true,
+ 0x1daa1...0x1daaf => true,
+ 0x1df00...0x1df09 => true,
+ 0x1df0a => true,
+ 0x1df0b...0x1df1e => true,
+ 0x1df25...0x1df2a => true,
+ 0x1e000...0x1e006 => true,
+ 0x1e008...0x1e018 => true,
+ 0x1e01b...0x1e021 => true,
+ 0x1e023...0x1e024 => true,
+ 0x1e026...0x1e02a => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e08f => true,
+ 0x1e100...0x1e12c => true,
+ 0x1e130...0x1e136 => true,
+ 0x1e137...0x1e13d => true,
+ 0x1e140...0x1e149 => true,
+ 0x1e14e => true,
+ 0x1e14f => true,
+ 0x1e290...0x1e2ad => true,
+ 0x1e2ae => true,
+ 0x1e2c0...0x1e2eb => true,
+ 0x1e2ec...0x1e2ef => true,
+ 0x1e2f0...0x1e2f9 => true,
+ 0x1e2ff => true,
+ 0x1e4d0...0x1e4ea => true,
+ 0x1e4eb => true,
+ 0x1e4ec...0x1e4ef => true,
+ 0x1e4f0...0x1e4f9 => true,
+ 0x1e7e0...0x1e7e6 => true,
+ 0x1e7e8...0x1e7eb => true,
+ 0x1e7ed...0x1e7ee => true,
+ 0x1e7f0...0x1e7fe => true,
+ 0x1e800...0x1e8c4 => true,
+ 0x1e8c7...0x1e8cf => true,
+ 0x1e8d0...0x1e8d6 => true,
+ 0x1e900...0x1e943 => true,
+ 0x1e944...0x1e94a => true,
+ 0x1e94b => true,
+ 0x1e950...0x1e959 => true,
+ 0x1e95e...0x1e95f => true,
+ 0x1ec71...0x1ecab => true,
+ 0x1ecac => true,
+ 0x1ecad...0x1ecaf => true,
+ 0x1ecb0 => true,
+ 0x1ecb1...0x1ecb4 => true,
+ 0x1ed01...0x1ed2d => true,
+ 0x1ed2e => true,
+ 0x1ed2f...0x1ed3d => true,
+ 0x1ee00...0x1ee03 => true,
+ 0x1ee05...0x1ee1f => true,
+ 0x1ee21...0x1ee22 => true,
+ 0x1ee24 => true,
+ 0x1ee27 => true,
+ 0x1ee29...0x1ee32 => true,
+ 0x1ee34...0x1ee37 => true,
+ 0x1ee39 => true,
+ 0x1ee3b => true,
+ 0x1ee42 => true,
+ 0x1ee47 => true,
+ 0x1ee49 => true,
+ 0x1ee4b => true,
+ 0x1ee4d...0x1ee4f => true,
+ 0x1ee51...0x1ee52 => true,
+ 0x1ee54 => true,
+ 0x1ee57 => true,
+ 0x1ee59 => true,
+ 0x1ee5b => true,
+ 0x1ee5d => true,
+ 0x1ee5f => true,
+ 0x1ee61...0x1ee62 => true,
+ 0x1ee64 => true,
+ 0x1ee67...0x1ee6a => true,
+ 0x1ee6c...0x1ee72 => true,
+ 0x1ee74...0x1ee77 => true,
+ 0x1ee79...0x1ee7c => true,
+ 0x1ee7e => true,
+ 0x1ee80...0x1ee89 => true,
+ 0x1ee8b...0x1ee9b => true,
+ 0x1eea1...0x1eea3 => true,
+ 0x1eea5...0x1eea9 => true,
+ 0x1eeab...0x1eebb => true,
+ 0x1eef0...0x1eef1 => true,
+ 0x1f000...0x1f003 => true,
+ 0x1f005...0x1f02b => true,
+ 0x1f030...0x1f093 => true,
+ 0x1f0a0...0x1f0ae => true,
+ 0x1f0b1...0x1f0bf => true,
+ 0x1f0c1...0x1f0ce => true,
+ 0x1f0d1...0x1f0f5 => true,
+ 0x1f10b...0x1f10c => true,
+ 0x1f10d...0x1f10f => true,
+ 0x1f12e...0x1f12f => true,
+ 0x1f16a...0x1f16f => true,
+ 0x1f1ad => true,
+ 0x1f1e6...0x1f1ff => true,
+ 0x1f321...0x1f32c => true,
+ 0x1f336 => true,
+ 0x1f37d => true,
+ 0x1f394...0x1f39f => true,
+ 0x1f3cb...0x1f3ce => true,
+ 0x1f3d4...0x1f3df => true,
+ 0x1f3f1...0x1f3f3 => true,
+ 0x1f3f5...0x1f3f7 => true,
+ 0x1f43f => true,
+ 0x1f441 => true,
+ 0x1f4fd...0x1f4fe => true,
+ 0x1f53e...0x1f54a => true,
+ 0x1f54f => true,
+ 0x1f568...0x1f579 => true,
+ 0x1f57b...0x1f594 => true,
+ 0x1f597...0x1f5a3 => true,
+ 0x1f5a5...0x1f5fa => true,
+ 0x1f650...0x1f67f => true,
+ 0x1f6c6...0x1f6cb => true,
+ 0x1f6cd...0x1f6cf => true,
+ 0x1f6d3...0x1f6d4 => true,
+ 0x1f6e0...0x1f6ea => true,
+ 0x1f6f0...0x1f6f3 => true,
+ 0x1f700...0x1f776 => true,
+ 0x1f77b...0x1f7d9 => true,
+ 0x1f800...0x1f80b => true,
+ 0x1f810...0x1f847 => true,
+ 0x1f850...0x1f859 => true,
+ 0x1f860...0x1f887 => true,
+ 0x1f890...0x1f8ad => true,
+ 0x1f8b0...0x1f8b1 => true,
+ 0x1f900...0x1f90b => true,
+ 0x1f93b => true,
+ 0x1f946 => true,
+ 0x1fa00...0x1fa53 => true,
+ 0x1fa60...0x1fa6d => true,
+ 0x1fb00...0x1fb92 => true,
+ 0x1fb94...0x1fbca => true,
+ 0x1fbf0...0x1fbf9 => true,
+ 0xe0001 => true,
+ 0xe0020...0xe007f => true,
+ else => false,
+ };
+}
+
+pub fn isAmbiguous(cp: u21) bool {
+ if (cp < 0xa1 or cp > 0x10fffd) return false;
+
+ return switch (cp) {
+ 0xa1 => true,
+ 0xa4 => true,
+ 0xa7 => true,
+ 0xa8 => true,
+ 0xaa => true,
+ 0xad => true,
+ 0xae => true,
+ 0xb0 => true,
+ 0xb1 => true,
+ 0xb2...0xb3 => true,
+ 0xb4 => true,
+ 0xb6...0xb7 => true,
+ 0xb8 => true,
+ 0xb9 => true,
+ 0xba => true,
+ 0xbc...0xbe => true,
+ 0xbf => true,
+ 0xc6 => true,
+ 0xd0 => true,
+ 0xd7 => true,
+ 0xd8 => true,
+ 0xde...0xe1 => true,
+ 0xe6 => true,
+ 0xe8...0xea => true,
+ 0xec...0xed => true,
+ 0xf0 => true,
+ 0xf2...0xf3 => true,
+ 0xf7 => true,
+ 0xf8...0xfa => true,
+ 0xfc => true,
+ 0xfe => true,
+ 0x101 => true,
+ 0x111 => true,
+ 0x113 => true,
+ 0x11b => true,
+ 0x126...0x127 => true,
+ 0x12b => true,
+ 0x131...0x133 => true,
+ 0x138 => true,
+ 0x13f...0x142 => true,
+ 0x144 => true,
+ 0x148...0x14b => true,
+ 0x14d => true,
+ 0x152...0x153 => true,
+ 0x166...0x167 => true,
+ 0x16b => true,
+ 0x1ce => true,
+ 0x1d0 => true,
+ 0x1d2 => true,
+ 0x1d4 => true,
+ 0x1d6 => true,
+ 0x1d8 => true,
+ 0x1da => true,
+ 0x1dc => true,
+ 0x251 => true,
+ 0x261 => true,
+ 0x2c4 => true,
+ 0x2c7 => true,
+ 0x2c9...0x2cb => true,
+ 0x2cd => true,
+ 0x2d0 => true,
+ 0x2d8...0x2db => true,
+ 0x2dd => true,
+ 0x2df => true,
+ 0x300...0x36f => true,
+ 0x391...0x3a1 => true,
+ 0x3a3...0x3a9 => true,
+ 0x3b1...0x3c1 => true,
+ 0x3c3...0x3c9 => true,
+ 0x401 => true,
+ 0x410...0x44f => true,
+ 0x451 => true,
+ 0x2010 => true,
+ 0x2013...0x2015 => true,
+ 0x2016 => true,
+ 0x2018 => true,
+ 0x2019 => true,
+ 0x201c => true,
+ 0x201d => true,
+ 0x2020...0x2022 => true,
+ 0x2024...0x2027 => true,
+ 0x2030 => true,
+ 0x2032...0x2033 => true,
+ 0x2035 => true,
+ 0x203b => true,
+ 0x203e => true,
+ 0x2074 => true,
+ 0x207f => true,
+ 0x2081...0x2084 => true,
+ 0x20ac => true,
+ 0x2103 => true,
+ 0x2105 => true,
+ 0x2109 => true,
+ 0x2113 => true,
+ 0x2116 => true,
+ 0x2121...0x2122 => true,
+ 0x2126 => true,
+ 0x212b => true,
+ 0x2153...0x2154 => true,
+ 0x215b...0x215e => true,
+ 0x2160...0x216b => true,
+ 0x2170...0x2179 => true,
+ 0x2189 => true,
+ 0x2190...0x2194 => true,
+ 0x2195...0x2199 => true,
+ 0x21b8...0x21b9 => true,
+ 0x21d2 => true,
+ 0x21d4 => true,
+ 0x21e7 => true,
+ 0x2200 => true,
+ 0x2202...0x2203 => true,
+ 0x2207...0x2208 => true,
+ 0x220b => true,
+ 0x220f => true,
+ 0x2211 => true,
+ 0x2215 => true,
+ 0x221a => true,
+ 0x221d...0x2220 => true,
+ 0x2223 => true,
+ 0x2225 => true,
+ 0x2227...0x222c => true,
+ 0x222e => true,
+ 0x2234...0x2237 => true,
+ 0x223c...0x223d => true,
+ 0x2248 => true,
+ 0x224c => true,
+ 0x2252 => true,
+ 0x2260...0x2261 => true,
+ 0x2264...0x2267 => true,
+ 0x226a...0x226b => true,
+ 0x226e...0x226f => true,
+ 0x2282...0x2283 => true,
+ 0x2286...0x2287 => true,
+ 0x2295 => true,
+ 0x2299 => true,
+ 0x22a5 => true,
+ 0x22bf => true,
+ 0x2312 => true,
+ 0x2460...0x249b => true,
+ 0x249c...0x24e9 => true,
+ 0x24eb...0x24ff => true,
+ 0x2500...0x254b => true,
+ 0x2550...0x2573 => true,
+ 0x2580...0x258f => true,
+ 0x2592...0x2595 => true,
+ 0x25a0...0x25a1 => true,
+ 0x25a3...0x25a9 => true,
+ 0x25b2...0x25b3 => true,
+ 0x25b6 => true,
+ 0x25b7 => true,
+ 0x25bc...0x25bd => true,
+ 0x25c0 => true,
+ 0x25c1 => true,
+ 0x25c6...0x25c8 => true,
+ 0x25cb => true,
+ 0x25ce...0x25d1 => true,
+ 0x25e2...0x25e5 => true,
+ 0x25ef => true,
+ 0x2605...0x2606 => true,
+ 0x2609 => true,
+ 0x260e...0x260f => true,
+ 0x261c => true,
+ 0x261e => true,
+ 0x2640 => true,
+ 0x2642 => true,
+ 0x2660...0x2661 => true,
+ 0x2663...0x2665 => true,
+ 0x2667...0x266a => true,
+ 0x266c...0x266d => true,
+ 0x266f => true,
+ 0x269e...0x269f => true,
+ 0x26bf => true,
+ 0x26c6...0x26cd => true,
+ 0x26cf...0x26d3 => true,
+ 0x26d5...0x26e1 => true,
+ 0x26e3 => true,
+ 0x26e8...0x26e9 => true,
+ 0x26eb...0x26f1 => true,
+ 0x26f4 => true,
+ 0x26f6...0x26f9 => true,
+ 0x26fb...0x26fc => true,
+ 0x26fe...0x26ff => true,
+ 0x273d => true,
+ 0x2776...0x277f => true,
+ 0x2b56...0x2b59 => true,
+ 0x3248...0x324f => true,
+ 0xe000...0xf8ff => true,
+ 0xfe00...0xfe0f => true,
+ 0xfffd => true,
+ 0x1f100...0x1f10a => true,
+ 0x1f110...0x1f12d => true,
+ 0x1f130...0x1f169 => true,
+ 0x1f170...0x1f18d => true,
+ 0x1f18f...0x1f190 => true,
+ 0x1f19b...0x1f1ac => true,
+ 0xe0100...0xe01ef => true,
+ 0xf0000...0xffffd => true,
+ 0x100000...0x10fffd => true,
+ else => false,
+ };
+}
+
+pub fn isHalfwidth(cp: u21) bool {
+ if (cp < 0x20a9 or cp > 0xffee) return false;
+
+ return switch (cp) {
+ 0x20a9 => true,
+ 0xff61 => true,
+ 0xff62 => true,
+ 0xff63 => true,
+ 0xff64...0xff65 => true,
+ 0xff66...0xff6f => true,
+ 0xff70 => true,
+ 0xff71...0xff9d => true,
+ 0xff9e...0xff9f => true,
+ 0xffa0...0xffbe => true,
+ 0xffc2...0xffc7 => true,
+ 0xffca...0xffcf => true,
+ 0xffd2...0xffd7 => true,
+ 0xffda...0xffdc => true,
+ 0xffe8 => true,
+ 0xffe9...0xffec => true,
+ 0xffed...0xffee => true,
+ else => false,
+ };
+}
+
+pub fn isWide(cp: u21) bool {
+ if (cp < 0x1100 or cp > 0x323af) return false;
+
+ return switch (cp) {
+ 0x1100...0x115f => true,
+ 0x231a...0x231b => true,
+ 0x2329 => true,
+ 0x232a => true,
+ 0x23e9...0x23ec => true,
+ 0x23f0 => true,
+ 0x23f3 => true,
+ 0x25fd...0x25fe => true,
+ 0x2614...0x2615 => true,
+ 0x2648...0x2653 => true,
+ 0x267f => true,
+ 0x2693 => true,
+ 0x26a1 => true,
+ 0x26aa...0x26ab => true,
+ 0x26bd...0x26be => true,
+ 0x26c4...0x26c5 => true,
+ 0x26ce => true,
+ 0x26d4 => true,
+ 0x26ea => true,
+ 0x26f2...0x26f3 => true,
+ 0x26f5 => true,
+ 0x26fa => true,
+ 0x26fd => true,
+ 0x2705 => true,
+ 0x270a...0x270b => true,
+ 0x2728 => true,
+ 0x274c => true,
+ 0x274e => true,
+ 0x2753...0x2755 => true,
+ 0x2757 => true,
+ 0x2795...0x2797 => true,
+ 0x27b0 => true,
+ 0x27bf => true,
+ 0x2b1b...0x2b1c => true,
+ 0x2b50 => true,
+ 0x2b55 => true,
+ 0x2e80...0x2e99 => true,
+ 0x2e9b...0x2ef3 => true,
+ 0x2f00...0x2fd5 => true,
+ 0x2ff0...0x2ffb => true,
+ 0x3001...0x3003 => true,
+ 0x3004 => true,
+ 0x3005 => true,
+ 0x3006 => true,
+ 0x3007 => true,
+ 0x3008 => true,
+ 0x3009 => true,
+ 0x300a => true,
+ 0x300b => true,
+ 0x300c => true,
+ 0x300d => true,
+ 0x300e => true,
+ 0x300f => true,
+ 0x3010 => true,
+ 0x3011 => true,
+ 0x3012...0x3013 => true,
+ 0x3014 => true,
+ 0x3015 => true,
+ 0x3016 => true,
+ 0x3017 => true,
+ 0x3018 => true,
+ 0x3019 => true,
+ 0x301a => true,
+ 0x301b => true,
+ 0x301c => true,
+ 0x301d => true,
+ 0x301e...0x301f => true,
+ 0x3020 => true,
+ 0x3021...0x3029 => true,
+ 0x302a...0x302d => true,
+ 0x302e...0x302f => true,
+ 0x3030 => true,
+ 0x3031...0x3035 => true,
+ 0x3036...0x3037 => true,
+ 0x3038...0x303a => true,
+ 0x303b => true,
+ 0x303c => true,
+ 0x303d => true,
+ 0x303e => true,
+ 0x3041...0x3096 => true,
+ 0x3099...0x309a => true,
+ 0x309b...0x309c => true,
+ 0x309d...0x309e => true,
+ 0x309f => true,
+ 0x30a0 => true,
+ 0x30a1...0x30fa => true,
+ 0x30fb => true,
+ 0x30fc...0x30fe => true,
+ 0x30ff => true,
+ 0x3105...0x312f => true,
+ 0x3131...0x318e => true,
+ 0x3190...0x3191 => true,
+ 0x3192...0x3195 => true,
+ 0x3196...0x319f => true,
+ 0x31a0...0x31bf => true,
+ 0x31c0...0x31e3 => true,
+ 0x31f0...0x31ff => true,
+ 0x3200...0x321e => true,
+ 0x3220...0x3229 => true,
+ 0x322a...0x3247 => true,
+ 0x3250 => true,
+ 0x3251...0x325f => true,
+ 0x3260...0x327f => true,
+ 0x3280...0x3289 => true,
+ 0x328a...0x32b0 => true,
+ 0x32b1...0x32bf => true,
+ 0x32c0...0x33ff => true,
+ 0x3400...0x4dbf => true,
+ 0x4e00...0xa014 => true,
+ 0xa015 => true,
+ 0xa016...0xa48c => true,
+ 0xa490...0xa4c6 => true,
+ 0xa960...0xa97c => true,
+ 0xac00...0xd7a3 => true,
+ 0xf900...0xfa6d => true,
+ 0xfa70...0xfad9 => true,
+ 0xfe10...0xfe16 => true,
+ 0xfe17 => true,
+ 0xfe18 => true,
+ 0xfe19 => true,
+ 0xfe30 => true,
+ 0xfe31...0xfe32 => true,
+ 0xfe33...0xfe34 => true,
+ 0xfe35 => true,
+ 0xfe36 => true,
+ 0xfe37 => true,
+ 0xfe38 => true,
+ 0xfe39 => true,
+ 0xfe3a => true,
+ 0xfe3b => true,
+ 0xfe3c => true,
+ 0xfe3d => true,
+ 0xfe3e => true,
+ 0xfe3f => true,
+ 0xfe40 => true,
+ 0xfe41 => true,
+ 0xfe42 => true,
+ 0xfe43 => true,
+ 0xfe44 => true,
+ 0xfe45...0xfe46 => true,
+ 0xfe47 => true,
+ 0xfe48 => true,
+ 0xfe49...0xfe4c => true,
+ 0xfe4d...0xfe4f => true,
+ 0xfe50...0xfe52 => true,
+ 0xfe54...0xfe57 => true,
+ 0xfe58 => true,
+ 0xfe59 => true,
+ 0xfe5a => true,
+ 0xfe5b => true,
+ 0xfe5c => true,
+ 0xfe5d => true,
+ 0xfe5e => true,
+ 0xfe5f...0xfe61 => true,
+ 0xfe62 => true,
+ 0xfe63 => true,
+ 0xfe64...0xfe66 => true,
+ 0xfe68 => true,
+ 0xfe69 => true,
+ 0xfe6a...0xfe6b => true,
+ 0x16fe0...0x16fe1 => true,
+ 0x16fe2 => true,
+ 0x16fe3 => true,
+ 0x16fe4 => true,
+ 0x16ff0...0x16ff1 => true,
+ 0x17000...0x187f7 => true,
+ 0x18800...0x18cd5 => true,
+ 0x18d00...0x18d08 => true,
+ 0x1aff0...0x1aff3 => true,
+ 0x1aff5...0x1affb => true,
+ 0x1affd...0x1affe => true,
+ 0x1b000...0x1b122 => true,
+ 0x1b132 => true,
+ 0x1b150...0x1b152 => true,
+ 0x1b155 => true,
+ 0x1b164...0x1b167 => true,
+ 0x1b170...0x1b2fb => true,
+ 0x1f004 => true,
+ 0x1f0cf => true,
+ 0x1f18e => true,
+ 0x1f191...0x1f19a => true,
+ 0x1f200...0x1f202 => true,
+ 0x1f210...0x1f23b => true,
+ 0x1f240...0x1f248 => true,
+ 0x1f250...0x1f251 => true,
+ 0x1f260...0x1f265 => true,
+ 0x1f300...0x1f320 => true,
+ 0x1f32d...0x1f335 => true,
+ 0x1f337...0x1f37c => true,
+ 0x1f37e...0x1f393 => true,
+ 0x1f3a0...0x1f3ca => true,
+ 0x1f3cf...0x1f3d3 => true,
+ 0x1f3e0...0x1f3f0 => true,
+ 0x1f3f4 => true,
+ 0x1f3f8...0x1f3fa => true,
+ 0x1f3fb...0x1f3ff => true,
+ 0x1f400...0x1f43e => true,
+ 0x1f440 => true,
+ 0x1f442...0x1f4fc => true,
+ 0x1f4ff...0x1f53d => true,
+ 0x1f54b...0x1f54e => true,
+ 0x1f550...0x1f567 => true,
+ 0x1f57a => true,
+ 0x1f595...0x1f596 => true,
+ 0x1f5a4 => true,
+ 0x1f5fb...0x1f64f => true,
+ 0x1f680...0x1f6c5 => true,
+ 0x1f6cc => true,
+ 0x1f6d0...0x1f6d2 => true,
+ 0x1f6d5...0x1f6d7 => true,
+ 0x1f6dc...0x1f6df => true,
+ 0x1f6eb...0x1f6ec => true,
+ 0x1f6f4...0x1f6fc => true,
+ 0x1f7e0...0x1f7eb => true,
+ 0x1f7f0 => true,
+ 0x1f90c...0x1f93a => true,
+ 0x1f93c...0x1f945 => true,
+ 0x1f947...0x1f9ff => true,
+ 0x1fa70...0x1fa7c => true,
+ 0x1fa80...0x1fa88 => true,
+ 0x1fa90...0x1fabd => true,
+ 0x1fabf...0x1fac5 => true,
+ 0x1face...0x1fadb => true,
+ 0x1fae0...0x1fae8 => true,
+ 0x1faf0...0x1faf8 => true,
+ 0x20000...0x2a6df => true,
+ 0x2a700...0x2b739 => true,
+ 0x2b740...0x2b81d => true,
+ 0x2b820...0x2cea1 => true,
+ 0x2ceb0...0x2ebe0 => true,
+ 0x2f800...0x2fa1d => true,
+ 0x30000...0x3134a => true,
+ 0x31350...0x323af => true,
+ else => false,
+ };
+}
+
+pub fn isFullwidth(cp: u21) bool {
+ if (cp < 0x3000 or cp > 0xffe6) return false;
+
+ return switch (cp) {
+ 0x3000 => true,
+ 0xff01...0xff03 => true,
+ 0xff04 => true,
+ 0xff05...0xff07 => true,
+ 0xff08 => true,
+ 0xff09 => true,
+ 0xff0a => true,
+ 0xff0b => true,
+ 0xff0c => true,
+ 0xff0d => true,
+ 0xff0e...0xff0f => true,
+ 0xff10...0xff19 => true,
+ 0xff1a...0xff1b => true,
+ 0xff1c...0xff1e => true,
+ 0xff1f...0xff20 => true,
+ 0xff21...0xff3a => true,
+ 0xff3b => true,
+ 0xff3c => true,
+ 0xff3d => true,
+ 0xff3e => true,
+ 0xff3f => true,
+ 0xff40 => true,
+ 0xff41...0xff5a => true,
+ 0xff5b => true,
+ 0xff5c => true,
+ 0xff5d => true,
+ 0xff5e => true,
+ 0xff5f => true,
+ 0xff60 => true,
+ 0xffe0...0xffe1 => true,
+ 0xffe2 => true,
+ 0xffe3 => true,
+ 0xffe4 => true,
+ 0xffe5...0xffe6 => true,
+ else => false,
+ };
+}
+
+pub fn isNarrow(cp: u21) bool {
+ if (cp < 0x20 or cp > 0x2986) return false;
+
+ return switch (cp) {
+ 0x20 => true,
+ 0x21...0x23 => true,
+ 0x24 => true,
+ 0x25...0x27 => true,
+ 0x28 => true,
+ 0x29 => true,
+ 0x2a => true,
+ 0x2b => true,
+ 0x2c => true,
+ 0x2d => true,
+ 0x2e...0x2f => true,
+ 0x30...0x39 => true,
+ 0x3a...0x3b => true,
+ 0x3c...0x3e => true,
+ 0x3f...0x40 => true,
+ 0x41...0x5a => true,
+ 0x5b => true,
+ 0x5c => true,
+ 0x5d => true,
+ 0x5e => true,
+ 0x5f => true,
+ 0x60 => true,
+ 0x61...0x7a => true,
+ 0x7b => true,
+ 0x7c => true,
+ 0x7d => true,
+ 0x7e => true,
+ 0xa2...0xa3 => true,
+ 0xa5 => true,
+ 0xa6 => true,
+ 0xac => true,
+ 0xaf => true,
+ 0x27e6 => true,
+ 0x27e7 => true,
+ 0x27e8 => true,
+ 0x27e9 => true,
+ 0x27ea => true,
+ 0x27eb => true,
+ 0x27ec => true,
+ 0x27ed => true,
+ 0x2985 => true,
+ 0x2986 => true,
+ else => false,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/derived_general_category.zig.html b/docs/src/ziglyph/autogen/derived_general_category.zig.html
new file mode 100644
index 0000000..3fdc863
--- /dev/null
+++ b/docs/src/ziglyph/autogen/derived_general_category.zig.html
@@ -0,0 +1,4356 @@
+
+
+
+
+
autogen/derived_general_category.zig - source view
+
+
+
+
+
+
+
+
+pub fn isUnassigned(cp: u21) bool {
+ if (cp < 0x378 or cp > 0x10ffff) return false;
+
+ return switch (cp) {
+ 0x378...0x379 => true,
+ 0x380...0x383 => true,
+ 0x38b => true,
+ 0x38d => true,
+ 0x3a2 => true,
+ 0x530 => true,
+ 0x557...0x558 => true,
+ 0x58b...0x58c => true,
+ 0x590 => true,
+ 0x5c8...0x5cf => true,
+ 0x5eb...0x5ee => true,
+ 0x5f5...0x5ff => true,
+ 0x70e => true,
+ 0x74b...0x74c => true,
+ 0x7b2...0x7bf => true,
+ 0x7fb...0x7fc => true,
+ 0x82e...0x82f => true,
+ 0x83f => true,
+ 0x85c...0x85d => true,
+ 0x85f => true,
+ 0x86b...0x86f => true,
+ 0x88f => true,
+ 0x892...0x897 => true,
+ 0x984 => true,
+ 0x98d...0x98e => true,
+ 0x991...0x992 => true,
+ 0x9a9 => true,
+ 0x9b1 => true,
+ 0x9b3...0x9b5 => true,
+ 0x9ba...0x9bb => true,
+ 0x9c5...0x9c6 => true,
+ 0x9c9...0x9ca => true,
+ 0x9cf...0x9d6 => true,
+ 0x9d8...0x9db => true,
+ 0x9de => true,
+ 0x9e4...0x9e5 => true,
+ 0x9ff...0xa00 => true,
+ 0xa04 => true,
+ 0xa0b...0xa0e => true,
+ 0xa11...0xa12 => true,
+ 0xa29 => true,
+ 0xa31 => true,
+ 0xa34 => true,
+ 0xa37 => true,
+ 0xa3a...0xa3b => true,
+ 0xa3d => true,
+ 0xa43...0xa46 => true,
+ 0xa49...0xa4a => true,
+ 0xa4e...0xa50 => true,
+ 0xa52...0xa58 => true,
+ 0xa5d => true,
+ 0xa5f...0xa65 => true,
+ 0xa77...0xa80 => true,
+ 0xa84 => true,
+ 0xa8e => true,
+ 0xa92 => true,
+ 0xaa9 => true,
+ 0xab1 => true,
+ 0xab4 => true,
+ 0xaba...0xabb => true,
+ 0xac6 => true,
+ 0xaca => true,
+ 0xace...0xacf => true,
+ 0xad1...0xadf => true,
+ 0xae4...0xae5 => true,
+ 0xaf2...0xaf8 => true,
+ 0xb00 => true,
+ 0xb04 => true,
+ 0xb0d...0xb0e => true,
+ 0xb11...0xb12 => true,
+ 0xb29 => true,
+ 0xb31 => true,
+ 0xb34 => true,
+ 0xb3a...0xb3b => true,
+ 0xb45...0xb46 => true,
+ 0xb49...0xb4a => true,
+ 0xb4e...0xb54 => true,
+ 0xb58...0xb5b => true,
+ 0xb5e => true,
+ 0xb64...0xb65 => true,
+ 0xb78...0xb81 => true,
+ 0xb84 => true,
+ 0xb8b...0xb8d => true,
+ 0xb91 => true,
+ 0xb96...0xb98 => true,
+ 0xb9b => true,
+ 0xb9d => true,
+ 0xba0...0xba2 => true,
+ 0xba5...0xba7 => true,
+ 0xbab...0xbad => true,
+ 0xbba...0xbbd => true,
+ 0xbc3...0xbc5 => true,
+ 0xbc9 => true,
+ 0xbce...0xbcf => true,
+ 0xbd1...0xbd6 => true,
+ 0xbd8...0xbe5 => true,
+ 0xbfb...0xbff => true,
+ 0xc0d => true,
+ 0xc11 => true,
+ 0xc29 => true,
+ 0xc3a...0xc3b => true,
+ 0xc45 => true,
+ 0xc49 => true,
+ 0xc4e...0xc54 => true,
+ 0xc57 => true,
+ 0xc5b...0xc5c => true,
+ 0xc5e...0xc5f => true,
+ 0xc64...0xc65 => true,
+ 0xc70...0xc76 => true,
+ 0xc8d => true,
+ 0xc91 => true,
+ 0xca9 => true,
+ 0xcb4 => true,
+ 0xcba...0xcbb => true,
+ 0xcc5 => true,
+ 0xcc9 => true,
+ 0xcce...0xcd4 => true,
+ 0xcd7...0xcdc => true,
+ 0xcdf => true,
+ 0xce4...0xce5 => true,
+ 0xcf0 => true,
+ 0xcf4...0xcff => true,
+ 0xd0d => true,
+ 0xd11 => true,
+ 0xd45 => true,
+ 0xd49 => true,
+ 0xd50...0xd53 => true,
+ 0xd64...0xd65 => true,
+ 0xd80 => true,
+ 0xd84 => true,
+ 0xd97...0xd99 => true,
+ 0xdb2 => true,
+ 0xdbc => true,
+ 0xdbe...0xdbf => true,
+ 0xdc7...0xdc9 => true,
+ 0xdcb...0xdce => true,
+ 0xdd5 => true,
+ 0xdd7 => true,
+ 0xde0...0xde5 => true,
+ 0xdf0...0xdf1 => true,
+ 0xdf5...0xe00 => true,
+ 0xe3b...0xe3e => true,
+ 0xe5c...0xe80 => true,
+ 0xe83 => true,
+ 0xe85 => true,
+ 0xe8b => true,
+ 0xea4 => true,
+ 0xea6 => true,
+ 0xebe...0xebf => true,
+ 0xec5 => true,
+ 0xec7 => true,
+ 0xecf => true,
+ 0xeda...0xedb => true,
+ 0xee0...0xeff => true,
+ 0xf48 => true,
+ 0xf6d...0xf70 => true,
+ 0xf98 => true,
+ 0xfbd => true,
+ 0xfcd => true,
+ 0xfdb...0xfff => true,
+ 0x10c6 => true,
+ 0x10c8...0x10cc => true,
+ 0x10ce...0x10cf => true,
+ 0x1249 => true,
+ 0x124e...0x124f => true,
+ 0x1257 => true,
+ 0x1259 => true,
+ 0x125e...0x125f => true,
+ 0x1289 => true,
+ 0x128e...0x128f => true,
+ 0x12b1 => true,
+ 0x12b6...0x12b7 => true,
+ 0x12bf => true,
+ 0x12c1 => true,
+ 0x12c6...0x12c7 => true,
+ 0x12d7 => true,
+ 0x1311 => true,
+ 0x1316...0x1317 => true,
+ 0x135b...0x135c => true,
+ 0x137d...0x137f => true,
+ 0x139a...0x139f => true,
+ 0x13f6...0x13f7 => true,
+ 0x13fe...0x13ff => true,
+ 0x169d...0x169f => true,
+ 0x16f9...0x16ff => true,
+ 0x1716...0x171e => true,
+ 0x1737...0x173f => true,
+ 0x1754...0x175f => true,
+ 0x176d => true,
+ 0x1771 => true,
+ 0x1774...0x177f => true,
+ 0x17de...0x17df => true,
+ 0x17ea...0x17ef => true,
+ 0x17fa...0x17ff => true,
+ 0x181a...0x181f => true,
+ 0x1879...0x187f => true,
+ 0x18ab...0x18af => true,
+ 0x18f6...0x18ff => true,
+ 0x191f => true,
+ 0x192c...0x192f => true,
+ 0x193c...0x193f => true,
+ 0x1941...0x1943 => true,
+ 0x196e...0x196f => true,
+ 0x1975...0x197f => true,
+ 0x19ac...0x19af => true,
+ 0x19ca...0x19cf => true,
+ 0x19db...0x19dd => true,
+ 0x1a1c...0x1a1d => true,
+ 0x1a5f => true,
+ 0x1a7d...0x1a7e => true,
+ 0x1a8a...0x1a8f => true,
+ 0x1a9a...0x1a9f => true,
+ 0x1aae...0x1aaf => true,
+ 0x1acf...0x1aff => true,
+ 0x1b4d...0x1b4f => true,
+ 0x1b7f => true,
+ 0x1bf4...0x1bfb => true,
+ 0x1c38...0x1c3a => true,
+ 0x1c4a...0x1c4c => true,
+ 0x1c89...0x1c8f => true,
+ 0x1cbb...0x1cbc => true,
+ 0x1cc8...0x1ccf => true,
+ 0x1cfb...0x1cff => true,
+ 0x1f16...0x1f17 => true,
+ 0x1f1e...0x1f1f => true,
+ 0x1f46...0x1f47 => true,
+ 0x1f4e...0x1f4f => true,
+ 0x1f58 => true,
+ 0x1f5a => true,
+ 0x1f5c => true,
+ 0x1f5e => true,
+ 0x1f7e...0x1f7f => true,
+ 0x1fb5 => true,
+ 0x1fc5 => true,
+ 0x1fd4...0x1fd5 => true,
+ 0x1fdc => true,
+ 0x1ff0...0x1ff1 => true,
+ 0x1ff5 => true,
+ 0x1fff => true,
+ 0x2065 => true,
+ 0x2072...0x2073 => true,
+ 0x208f => true,
+ 0x209d...0x209f => true,
+ 0x20c1...0x20cf => true,
+ 0x20f1...0x20ff => true,
+ 0x218c...0x218f => true,
+ 0x2427...0x243f => true,
+ 0x244b...0x245f => true,
+ 0x2b74...0x2b75 => true,
+ 0x2b96 => true,
+ 0x2cf4...0x2cf8 => true,
+ 0x2d26 => true,
+ 0x2d28...0x2d2c => true,
+ 0x2d2e...0x2d2f => true,
+ 0x2d68...0x2d6e => true,
+ 0x2d71...0x2d7e => true,
+ 0x2d97...0x2d9f => true,
+ 0x2da7 => true,
+ 0x2daf => true,
+ 0x2db7 => true,
+ 0x2dbf => true,
+ 0x2dc7 => true,
+ 0x2dcf => true,
+ 0x2dd7 => true,
+ 0x2ddf => true,
+ 0x2e5e...0x2e7f => true,
+ 0x2e9a => true,
+ 0x2ef4...0x2eff => true,
+ 0x2fd6...0x2fef => true,
+ 0x2ffc...0x2fff => true,
+ 0x3040 => true,
+ 0x3097...0x3098 => true,
+ 0x3100...0x3104 => true,
+ 0x3130 => true,
+ 0x318f => true,
+ 0x31e4...0x31ef => true,
+ 0x321f => true,
+ 0xa48d...0xa48f => true,
+ 0xa4c7...0xa4cf => true,
+ 0xa62c...0xa63f => true,
+ 0xa6f8...0xa6ff => true,
+ 0xa7cb...0xa7cf => true,
+ 0xa7d2 => true,
+ 0xa7d4 => true,
+ 0xa7da...0xa7f1 => true,
+ 0xa82d...0xa82f => true,
+ 0xa83a...0xa83f => true,
+ 0xa878...0xa87f => true,
+ 0xa8c6...0xa8cd => true,
+ 0xa8da...0xa8df => true,
+ 0xa954...0xa95e => true,
+ 0xa97d...0xa97f => true,
+ 0xa9ce => true,
+ 0xa9da...0xa9dd => true,
+ 0xa9ff => true,
+ 0xaa37...0xaa3f => true,
+ 0xaa4e...0xaa4f => true,
+ 0xaa5a...0xaa5b => true,
+ 0xaac3...0xaada => true,
+ 0xaaf7...0xab00 => true,
+ 0xab07...0xab08 => true,
+ 0xab0f...0xab10 => true,
+ 0xab17...0xab1f => true,
+ 0xab27 => true,
+ 0xab2f => true,
+ 0xab6c...0xab6f => true,
+ 0xabee...0xabef => true,
+ 0xabfa...0xabff => true,
+ 0xd7a4...0xd7af => true,
+ 0xd7c7...0xd7ca => true,
+ 0xd7fc...0xd7ff => true,
+ 0xfa6e...0xfa6f => true,
+ 0xfada...0xfaff => true,
+ 0xfb07...0xfb12 => true,
+ 0xfb18...0xfb1c => true,
+ 0xfb37 => true,
+ 0xfb3d => true,
+ 0xfb3f => true,
+ 0xfb42 => true,
+ 0xfb45 => true,
+ 0xfbc3...0xfbd2 => true,
+ 0xfd90...0xfd91 => true,
+ 0xfdc8...0xfdce => true,
+ 0xfdd0...0xfdef => true,
+ 0xfe1a...0xfe1f => true,
+ 0xfe53 => true,
+ 0xfe67 => true,
+ 0xfe6c...0xfe6f => true,
+ 0xfe75 => true,
+ 0xfefd...0xfefe => true,
+ 0xff00 => true,
+ 0xffbf...0xffc1 => true,
+ 0xffc8...0xffc9 => true,
+ 0xffd0...0xffd1 => true,
+ 0xffd8...0xffd9 => true,
+ 0xffdd...0xffdf => true,
+ 0xffe7 => true,
+ 0xffef...0xfff8 => true,
+ 0xfffe...0xffff => true,
+ 0x1000c => true,
+ 0x10027 => true,
+ 0x1003b => true,
+ 0x1003e => true,
+ 0x1004e...0x1004f => true,
+ 0x1005e...0x1007f => true,
+ 0x100fb...0x100ff => true,
+ 0x10103...0x10106 => true,
+ 0x10134...0x10136 => true,
+ 0x1018f => true,
+ 0x1019d...0x1019f => true,
+ 0x101a1...0x101cf => true,
+ 0x101fe...0x1027f => true,
+ 0x1029d...0x1029f => true,
+ 0x102d1...0x102df => true,
+ 0x102fc...0x102ff => true,
+ 0x10324...0x1032c => true,
+ 0x1034b...0x1034f => true,
+ 0x1037b...0x1037f => true,
+ 0x1039e => true,
+ 0x103c4...0x103c7 => true,
+ 0x103d6...0x103ff => true,
+ 0x1049e...0x1049f => true,
+ 0x104aa...0x104af => true,
+ 0x104d4...0x104d7 => true,
+ 0x104fc...0x104ff => true,
+ 0x10528...0x1052f => true,
+ 0x10564...0x1056e => true,
+ 0x1057b => true,
+ 0x1058b => true,
+ 0x10593 => true,
+ 0x10596 => true,
+ 0x105a2 => true,
+ 0x105b2 => true,
+ 0x105ba => true,
+ 0x105bd...0x105ff => true,
+ 0x10737...0x1073f => true,
+ 0x10756...0x1075f => true,
+ 0x10768...0x1077f => true,
+ 0x10786 => true,
+ 0x107b1 => true,
+ 0x107bb...0x107ff => true,
+ 0x10806...0x10807 => true,
+ 0x10809 => true,
+ 0x10836 => true,
+ 0x10839...0x1083b => true,
+ 0x1083d...0x1083e => true,
+ 0x10856 => true,
+ 0x1089f...0x108a6 => true,
+ 0x108b0...0x108df => true,
+ 0x108f3 => true,
+ 0x108f6...0x108fa => true,
+ 0x1091c...0x1091e => true,
+ 0x1093a...0x1093e => true,
+ 0x10940...0x1097f => true,
+ 0x109b8...0x109bb => true,
+ 0x109d0...0x109d1 => true,
+ 0x10a04 => true,
+ 0x10a07...0x10a0b => true,
+ 0x10a14 => true,
+ 0x10a18 => true,
+ 0x10a36...0x10a37 => true,
+ 0x10a3b...0x10a3e => true,
+ 0x10a49...0x10a4f => true,
+ 0x10a59...0x10a5f => true,
+ 0x10aa0...0x10abf => true,
+ 0x10ae7...0x10aea => true,
+ 0x10af7...0x10aff => true,
+ 0x10b36...0x10b38 => true,
+ 0x10b56...0x10b57 => true,
+ 0x10b73...0x10b77 => true,
+ 0x10b92...0x10b98 => true,
+ 0x10b9d...0x10ba8 => true,
+ 0x10bb0...0x10bff => true,
+ 0x10c49...0x10c7f => true,
+ 0x10cb3...0x10cbf => true,
+ 0x10cf3...0x10cf9 => true,
+ 0x10d28...0x10d2f => true,
+ 0x10d3a...0x10e5f => true,
+ 0x10e7f => true,
+ 0x10eaa => true,
+ 0x10eae...0x10eaf => true,
+ 0x10eb2...0x10efc => true,
+ 0x10f28...0x10f2f => true,
+ 0x10f5a...0x10f6f => true,
+ 0x10f8a...0x10faf => true,
+ 0x10fcc...0x10fdf => true,
+ 0x10ff7...0x10fff => true,
+ 0x1104e...0x11051 => true,
+ 0x11076...0x1107e => true,
+ 0x110c3...0x110cc => true,
+ 0x110ce...0x110cf => true,
+ 0x110e9...0x110ef => true,
+ 0x110fa...0x110ff => true,
+ 0x11135 => true,
+ 0x11148...0x1114f => true,
+ 0x11177...0x1117f => true,
+ 0x111e0 => true,
+ 0x111f5...0x111ff => true,
+ 0x11212 => true,
+ 0x11242...0x1127f => true,
+ 0x11287 => true,
+ 0x11289 => true,
+ 0x1128e => true,
+ 0x1129e => true,
+ 0x112aa...0x112af => true,
+ 0x112eb...0x112ef => true,
+ 0x112fa...0x112ff => true,
+ 0x11304 => true,
+ 0x1130d...0x1130e => true,
+ 0x11311...0x11312 => true,
+ 0x11329 => true,
+ 0x11331 => true,
+ 0x11334 => true,
+ 0x1133a => true,
+ 0x11345...0x11346 => true,
+ 0x11349...0x1134a => true,
+ 0x1134e...0x1134f => true,
+ 0x11351...0x11356 => true,
+ 0x11358...0x1135c => true,
+ 0x11364...0x11365 => true,
+ 0x1136d...0x1136f => true,
+ 0x11375...0x113ff => true,
+ 0x1145c => true,
+ 0x11462...0x1147f => true,
+ 0x114c8...0x114cf => true,
+ 0x114da...0x1157f => true,
+ 0x115b6...0x115b7 => true,
+ 0x115de...0x115ff => true,
+ 0x11645...0x1164f => true,
+ 0x1165a...0x1165f => true,
+ 0x1166d...0x1167f => true,
+ 0x116ba...0x116bf => true,
+ 0x116ca...0x116ff => true,
+ 0x1171b...0x1171c => true,
+ 0x1172c...0x1172f => true,
+ 0x11747...0x117ff => true,
+ 0x1183c...0x1189f => true,
+ 0x118f3...0x118fe => true,
+ 0x11907...0x11908 => true,
+ 0x1190a...0x1190b => true,
+ 0x11914 => true,
+ 0x11917 => true,
+ 0x11936 => true,
+ 0x11939...0x1193a => true,
+ 0x11947...0x1194f => true,
+ 0x1195a...0x1199f => true,
+ 0x119a8...0x119a9 => true,
+ 0x119d8...0x119d9 => true,
+ 0x119e5...0x119ff => true,
+ 0x11a48...0x11a4f => true,
+ 0x11aa3...0x11aaf => true,
+ 0x11af9...0x11aff => true,
+ 0x11b0a...0x11bff => true,
+ 0x11c09 => true,
+ 0x11c37 => true,
+ 0x11c46...0x11c4f => true,
+ 0x11c6d...0x11c6f => true,
+ 0x11c90...0x11c91 => true,
+ 0x11ca8 => true,
+ 0x11cb7...0x11cff => true,
+ 0x11d07 => true,
+ 0x11d0a => true,
+ 0x11d37...0x11d39 => true,
+ 0x11d3b => true,
+ 0x11d3e => true,
+ 0x11d48...0x11d4f => true,
+ 0x11d5a...0x11d5f => true,
+ 0x11d66 => true,
+ 0x11d69 => true,
+ 0x11d8f => true,
+ 0x11d92 => true,
+ 0x11d99...0x11d9f => true,
+ 0x11daa...0x11edf => true,
+ 0x11ef9...0x11eff => true,
+ 0x11f11 => true,
+ 0x11f3b...0x11f3d => true,
+ 0x11f5a...0x11faf => true,
+ 0x11fb1...0x11fbf => true,
+ 0x11ff2...0x11ffe => true,
+ 0x1239a...0x123ff => true,
+ 0x1246f => true,
+ 0x12475...0x1247f => true,
+ 0x12544...0x12f8f => true,
+ 0x12ff3...0x12fff => true,
+ 0x13456...0x143ff => true,
+ 0x14647...0x167ff => true,
+ 0x16a39...0x16a3f => true,
+ 0x16a5f => true,
+ 0x16a6a...0x16a6d => true,
+ 0x16abf => true,
+ 0x16aca...0x16acf => true,
+ 0x16aee...0x16aef => true,
+ 0x16af6...0x16aff => true,
+ 0x16b46...0x16b4f => true,
+ 0x16b5a => true,
+ 0x16b62 => true,
+ 0x16b78...0x16b7c => true,
+ 0x16b90...0x16e3f => true,
+ 0x16e9b...0x16eff => true,
+ 0x16f4b...0x16f4e => true,
+ 0x16f88...0x16f8e => true,
+ 0x16fa0...0x16fdf => true,
+ 0x16fe5...0x16fef => true,
+ 0x16ff2...0x16fff => true,
+ 0x187f8...0x187ff => true,
+ 0x18cd6...0x18cff => true,
+ 0x18d09...0x1afef => true,
+ 0x1aff4 => true,
+ 0x1affc => true,
+ 0x1afff => true,
+ 0x1b123...0x1b131 => true,
+ 0x1b133...0x1b14f => true,
+ 0x1b153...0x1b154 => true,
+ 0x1b156...0x1b163 => true,
+ 0x1b168...0x1b16f => true,
+ 0x1b2fc...0x1bbff => true,
+ 0x1bc6b...0x1bc6f => true,
+ 0x1bc7d...0x1bc7f => true,
+ 0x1bc89...0x1bc8f => true,
+ 0x1bc9a...0x1bc9b => true,
+ 0x1bca4...0x1ceff => true,
+ 0x1cf2e...0x1cf2f => true,
+ 0x1cf47...0x1cf4f => true,
+ 0x1cfc4...0x1cfff => true,
+ 0x1d0f6...0x1d0ff => true,
+ 0x1d127...0x1d128 => true,
+ 0x1d1eb...0x1d1ff => true,
+ 0x1d246...0x1d2bf => true,
+ 0x1d2d4...0x1d2df => true,
+ 0x1d2f4...0x1d2ff => true,
+ 0x1d357...0x1d35f => true,
+ 0x1d379...0x1d3ff => true,
+ 0x1d455 => true,
+ 0x1d49d => true,
+ 0x1d4a0...0x1d4a1 => true,
+ 0x1d4a3...0x1d4a4 => true,
+ 0x1d4a7...0x1d4a8 => true,
+ 0x1d4ad => true,
+ 0x1d4ba => true,
+ 0x1d4bc => true,
+ 0x1d4c4 => true,
+ 0x1d506 => true,
+ 0x1d50b...0x1d50c => true,
+ 0x1d515 => true,
+ 0x1d51d => true,
+ 0x1d53a => true,
+ 0x1d53f => true,
+ 0x1d545 => true,
+ 0x1d547...0x1d549 => true,
+ 0x1d551 => true,
+ 0x1d6a6...0x1d6a7 => true,
+ 0x1d7cc...0x1d7cd => true,
+ 0x1da8c...0x1da9a => true,
+ 0x1daa0 => true,
+ 0x1dab0...0x1deff => true,
+ 0x1df1f...0x1df24 => true,
+ 0x1df2b...0x1dfff => true,
+ 0x1e007 => true,
+ 0x1e019...0x1e01a => true,
+ 0x1e022 => true,
+ 0x1e025 => true,
+ 0x1e02b...0x1e02f => true,
+ 0x1e06e...0x1e08e => true,
+ 0x1e090...0x1e0ff => true,
+ 0x1e12d...0x1e12f => true,
+ 0x1e13e...0x1e13f => true,
+ 0x1e14a...0x1e14d => true,
+ 0x1e150...0x1e28f => true,
+ 0x1e2af...0x1e2bf => true,
+ 0x1e2fa...0x1e2fe => true,
+ 0x1e300...0x1e4cf => true,
+ 0x1e4fa...0x1e7df => true,
+ 0x1e7e7 => true,
+ 0x1e7ec => true,
+ 0x1e7ef => true,
+ 0x1e7ff => true,
+ 0x1e8c5...0x1e8c6 => true,
+ 0x1e8d7...0x1e8ff => true,
+ 0x1e94c...0x1e94f => true,
+ 0x1e95a...0x1e95d => true,
+ 0x1e960...0x1ec70 => true,
+ 0x1ecb5...0x1ed00 => true,
+ 0x1ed3e...0x1edff => true,
+ 0x1ee04 => true,
+ 0x1ee20 => true,
+ 0x1ee23 => true,
+ 0x1ee25...0x1ee26 => true,
+ 0x1ee28 => true,
+ 0x1ee33 => true,
+ 0x1ee38 => true,
+ 0x1ee3a => true,
+ 0x1ee3c...0x1ee41 => true,
+ 0x1ee43...0x1ee46 => true,
+ 0x1ee48 => true,
+ 0x1ee4a => true,
+ 0x1ee4c => true,
+ 0x1ee50 => true,
+ 0x1ee53 => true,
+ 0x1ee55...0x1ee56 => true,
+ 0x1ee58 => true,
+ 0x1ee5a => true,
+ 0x1ee5c => true,
+ 0x1ee5e => true,
+ 0x1ee60 => true,
+ 0x1ee63 => true,
+ 0x1ee65...0x1ee66 => true,
+ 0x1ee6b => true,
+ 0x1ee73 => true,
+ 0x1ee78 => true,
+ 0x1ee7d => true,
+ 0x1ee7f => true,
+ 0x1ee8a => true,
+ 0x1ee9c...0x1eea0 => true,
+ 0x1eea4 => true,
+ 0x1eeaa => true,
+ 0x1eebc...0x1eeef => true,
+ 0x1eef2...0x1efff => true,
+ 0x1f02c...0x1f02f => true,
+ 0x1f094...0x1f09f => true,
+ 0x1f0af...0x1f0b0 => true,
+ 0x1f0c0 => true,
+ 0x1f0d0 => true,
+ 0x1f0f6...0x1f0ff => true,
+ 0x1f1ae...0x1f1e5 => true,
+ 0x1f203...0x1f20f => true,
+ 0x1f23c...0x1f23f => true,
+ 0x1f249...0x1f24f => true,
+ 0x1f252...0x1f25f => true,
+ 0x1f266...0x1f2ff => true,
+ 0x1f6d8...0x1f6db => true,
+ 0x1f6ed...0x1f6ef => true,
+ 0x1f6fd...0x1f6ff => true,
+ 0x1f777...0x1f77a => true,
+ 0x1f7da...0x1f7df => true,
+ 0x1f7ec...0x1f7ef => true,
+ 0x1f7f1...0x1f7ff => true,
+ 0x1f80c...0x1f80f => true,
+ 0x1f848...0x1f84f => true,
+ 0x1f85a...0x1f85f => true,
+ 0x1f888...0x1f88f => true,
+ 0x1f8ae...0x1f8af => true,
+ 0x1f8b2...0x1f8ff => true,
+ 0x1fa54...0x1fa5f => true,
+ 0x1fa6e...0x1fa6f => true,
+ 0x1fa7d...0x1fa7f => true,
+ 0x1fa89...0x1fa8f => true,
+ 0x1fabe => true,
+ 0x1fac6...0x1facd => true,
+ 0x1fadc...0x1fadf => true,
+ 0x1fae9...0x1faef => true,
+ 0x1faf9...0x1faff => true,
+ 0x1fb93 => true,
+ 0x1fbcb...0x1fbef => true,
+ 0x1fbfa...0x1ffff => true,
+ 0x2a6e0...0x2a6ff => true,
+ 0x2b73a...0x2b73f => true,
+ 0x2b81e...0x2b81f => true,
+ 0x2cea2...0x2ceaf => true,
+ 0x2ebe1...0x2f7ff => true,
+ 0x2fa1e...0x2ffff => true,
+ 0x3134b...0x3134f => true,
+ 0x323b0...0xe0000 => true,
+ 0xe0002...0xe001f => true,
+ 0xe0080...0xe00ff => true,
+ 0xe01f0...0xeffff => true,
+ 0xffffe...0xfffff => true,
+ 0x10fffe...0x10ffff => true,
+ else => false,
+ };
+}
+
+pub fn isUppercaseLetter(cp: u21) bool {
+ if (cp < 0x41 or cp > 0x1e921) return false;
+
+ return switch (cp) {
+ 0x41...0x5a => true,
+ 0xc0...0xd6 => true,
+ 0xd8...0xde => true,
+ 0x100 => true,
+ 0x102 => true,
+ 0x104 => true,
+ 0x106 => true,
+ 0x108 => true,
+ 0x10a => true,
+ 0x10c => true,
+ 0x10e => true,
+ 0x110 => true,
+ 0x112 => true,
+ 0x114 => true,
+ 0x116 => true,
+ 0x118 => true,
+ 0x11a => true,
+ 0x11c => true,
+ 0x11e => true,
+ 0x120 => true,
+ 0x122 => true,
+ 0x124 => true,
+ 0x126 => true,
+ 0x128 => true,
+ 0x12a => true,
+ 0x12c => true,
+ 0x12e => true,
+ 0x130 => true,
+ 0x132 => true,
+ 0x134 => true,
+ 0x136 => true,
+ 0x139 => true,
+ 0x13b => true,
+ 0x13d => true,
+ 0x13f => true,
+ 0x141 => true,
+ 0x143 => true,
+ 0x145 => true,
+ 0x147 => true,
+ 0x14a => true,
+ 0x14c => true,
+ 0x14e => true,
+ 0x150 => true,
+ 0x152 => true,
+ 0x154 => true,
+ 0x156 => true,
+ 0x158 => true,
+ 0x15a => true,
+ 0x15c => true,
+ 0x15e => true,
+ 0x160 => true,
+ 0x162 => true,
+ 0x164 => true,
+ 0x166 => true,
+ 0x168 => true,
+ 0x16a => true,
+ 0x16c => true,
+ 0x16e => true,
+ 0x170 => true,
+ 0x172 => true,
+ 0x174 => true,
+ 0x176 => true,
+ 0x178...0x179 => true,
+ 0x17b => true,
+ 0x17d => true,
+ 0x181...0x182 => true,
+ 0x184 => true,
+ 0x186...0x187 => true,
+ 0x189...0x18b => true,
+ 0x18e...0x191 => true,
+ 0x193...0x194 => true,
+ 0x196...0x198 => true,
+ 0x19c...0x19d => true,
+ 0x19f...0x1a0 => true,
+ 0x1a2 => true,
+ 0x1a4 => true,
+ 0x1a6...0x1a7 => true,
+ 0x1a9 => true,
+ 0x1ac => true,
+ 0x1ae...0x1af => true,
+ 0x1b1...0x1b3 => true,
+ 0x1b5 => true,
+ 0x1b7...0x1b8 => true,
+ 0x1bc => true,
+ 0x1c4 => true,
+ 0x1c7 => true,
+ 0x1ca => true,
+ 0x1cd => true,
+ 0x1cf => true,
+ 0x1d1 => true,
+ 0x1d3 => true,
+ 0x1d5 => true,
+ 0x1d7 => true,
+ 0x1d9 => true,
+ 0x1db => true,
+ 0x1de => true,
+ 0x1e0 => true,
+ 0x1e2 => true,
+ 0x1e4 => true,
+ 0x1e6 => true,
+ 0x1e8 => true,
+ 0x1ea => true,
+ 0x1ec => true,
+ 0x1ee => true,
+ 0x1f1 => true,
+ 0x1f4 => true,
+ 0x1f6...0x1f8 => true,
+ 0x1fa => true,
+ 0x1fc => true,
+ 0x1fe => true,
+ 0x200 => true,
+ 0x202 => true,
+ 0x204 => true,
+ 0x206 => true,
+ 0x208 => true,
+ 0x20a => true,
+ 0x20c => true,
+ 0x20e => true,
+ 0x210 => true,
+ 0x212 => true,
+ 0x214 => true,
+ 0x216 => true,
+ 0x218 => true,
+ 0x21a => true,
+ 0x21c => true,
+ 0x21e => true,
+ 0x220 => true,
+ 0x222 => true,
+ 0x224 => true,
+ 0x226 => true,
+ 0x228 => true,
+ 0x22a => true,
+ 0x22c => true,
+ 0x22e => true,
+ 0x230 => true,
+ 0x232 => true,
+ 0x23a...0x23b => true,
+ 0x23d...0x23e => true,
+ 0x241 => true,
+ 0x243...0x246 => true,
+ 0x248 => true,
+ 0x24a => true,
+ 0x24c => true,
+ 0x24e => true,
+ 0x370 => true,
+ 0x372 => true,
+ 0x376 => true,
+ 0x37f => true,
+ 0x386 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x38f => true,
+ 0x391...0x3a1 => true,
+ 0x3a3...0x3ab => true,
+ 0x3cf => true,
+ 0x3d2...0x3d4 => true,
+ 0x3d8 => true,
+ 0x3da => true,
+ 0x3dc => true,
+ 0x3de => true,
+ 0x3e0 => true,
+ 0x3e2 => true,
+ 0x3e4 => true,
+ 0x3e6 => true,
+ 0x3e8 => true,
+ 0x3ea => true,
+ 0x3ec => true,
+ 0x3ee => true,
+ 0x3f4 => true,
+ 0x3f7 => true,
+ 0x3f9...0x3fa => true,
+ 0x3fd...0x42f => true,
+ 0x460 => true,
+ 0x462 => true,
+ 0x464 => true,
+ 0x466 => true,
+ 0x468 => true,
+ 0x46a => true,
+ 0x46c => true,
+ 0x46e => true,
+ 0x470 => true,
+ 0x472 => true,
+ 0x474 => true,
+ 0x476 => true,
+ 0x478 => true,
+ 0x47a => true,
+ 0x47c => true,
+ 0x47e => true,
+ 0x480 => true,
+ 0x48a => true,
+ 0x48c => true,
+ 0x48e => true,
+ 0x490 => true,
+ 0x492 => true,
+ 0x494 => true,
+ 0x496 => true,
+ 0x498 => true,
+ 0x49a => true,
+ 0x49c => true,
+ 0x49e => true,
+ 0x4a0 => true,
+ 0x4a2 => true,
+ 0x4a4 => true,
+ 0x4a6 => true,
+ 0x4a8 => true,
+ 0x4aa => true,
+ 0x4ac => true,
+ 0x4ae => true,
+ 0x4b0 => true,
+ 0x4b2 => true,
+ 0x4b4 => true,
+ 0x4b6 => true,
+ 0x4b8 => true,
+ 0x4ba => true,
+ 0x4bc => true,
+ 0x4be => true,
+ 0x4c0...0x4c1 => true,
+ 0x4c3 => true,
+ 0x4c5 => true,
+ 0x4c7 => true,
+ 0x4c9 => true,
+ 0x4cb => true,
+ 0x4cd => true,
+ 0x4d0 => true,
+ 0x4d2 => true,
+ 0x4d4 => true,
+ 0x4d6 => true,
+ 0x4d8 => true,
+ 0x4da => true,
+ 0x4dc => true,
+ 0x4de => true,
+ 0x4e0 => true,
+ 0x4e2 => true,
+ 0x4e4 => true,
+ 0x4e6 => true,
+ 0x4e8 => true,
+ 0x4ea => true,
+ 0x4ec => true,
+ 0x4ee => true,
+ 0x4f0 => true,
+ 0x4f2 => true,
+ 0x4f4 => true,
+ 0x4f6 => true,
+ 0x4f8 => true,
+ 0x4fa => true,
+ 0x4fc => true,
+ 0x4fe => true,
+ 0x500 => true,
+ 0x502 => true,
+ 0x504 => true,
+ 0x506 => true,
+ 0x508 => true,
+ 0x50a => true,
+ 0x50c => true,
+ 0x50e => true,
+ 0x510 => true,
+ 0x512 => true,
+ 0x514 => true,
+ 0x516 => true,
+ 0x518 => true,
+ 0x51a => true,
+ 0x51c => true,
+ 0x51e => true,
+ 0x520 => true,
+ 0x522 => true,
+ 0x524 => true,
+ 0x526 => true,
+ 0x528 => true,
+ 0x52a => true,
+ 0x52c => true,
+ 0x52e => true,
+ 0x531...0x556 => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x13a0...0x13f5 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1e00 => true,
+ 0x1e02 => true,
+ 0x1e04 => true,
+ 0x1e06 => true,
+ 0x1e08 => true,
+ 0x1e0a => true,
+ 0x1e0c => true,
+ 0x1e0e => true,
+ 0x1e10 => true,
+ 0x1e12 => true,
+ 0x1e14 => true,
+ 0x1e16 => true,
+ 0x1e18 => true,
+ 0x1e1a => true,
+ 0x1e1c => true,
+ 0x1e1e => true,
+ 0x1e20 => true,
+ 0x1e22 => true,
+ 0x1e24 => true,
+ 0x1e26 => true,
+ 0x1e28 => true,
+ 0x1e2a => true,
+ 0x1e2c => true,
+ 0x1e2e => true,
+ 0x1e30 => true,
+ 0x1e32 => true,
+ 0x1e34 => true,
+ 0x1e36 => true,
+ 0x1e38 => true,
+ 0x1e3a => true,
+ 0x1e3c => true,
+ 0x1e3e => true,
+ 0x1e40 => true,
+ 0x1e42 => true,
+ 0x1e44 => true,
+ 0x1e46 => true,
+ 0x1e48 => true,
+ 0x1e4a => true,
+ 0x1e4c => true,
+ 0x1e4e => true,
+ 0x1e50 => true,
+ 0x1e52 => true,
+ 0x1e54 => true,
+ 0x1e56 => true,
+ 0x1e58 => true,
+ 0x1e5a => true,
+ 0x1e5c => true,
+ 0x1e5e => true,
+ 0x1e60 => true,
+ 0x1e62 => true,
+ 0x1e64 => true,
+ 0x1e66 => true,
+ 0x1e68 => true,
+ 0x1e6a => true,
+ 0x1e6c => true,
+ 0x1e6e => true,
+ 0x1e70 => true,
+ 0x1e72 => true,
+ 0x1e74 => true,
+ 0x1e76 => true,
+ 0x1e78 => true,
+ 0x1e7a => true,
+ 0x1e7c => true,
+ 0x1e7e => true,
+ 0x1e80 => true,
+ 0x1e82 => true,
+ 0x1e84 => true,
+ 0x1e86 => true,
+ 0x1e88 => true,
+ 0x1e8a => true,
+ 0x1e8c => true,
+ 0x1e8e => true,
+ 0x1e90 => true,
+ 0x1e92 => true,
+ 0x1e94 => true,
+ 0x1e9e => true,
+ 0x1ea0 => true,
+ 0x1ea2 => true,
+ 0x1ea4 => true,
+ 0x1ea6 => true,
+ 0x1ea8 => true,
+ 0x1eaa => true,
+ 0x1eac => true,
+ 0x1eae => true,
+ 0x1eb0 => true,
+ 0x1eb2 => true,
+ 0x1eb4 => true,
+ 0x1eb6 => true,
+ 0x1eb8 => true,
+ 0x1eba => true,
+ 0x1ebc => true,
+ 0x1ebe => true,
+ 0x1ec0 => true,
+ 0x1ec2 => true,
+ 0x1ec4 => true,
+ 0x1ec6 => true,
+ 0x1ec8 => true,
+ 0x1eca => true,
+ 0x1ecc => true,
+ 0x1ece => true,
+ 0x1ed0 => true,
+ 0x1ed2 => true,
+ 0x1ed4 => true,
+ 0x1ed6 => true,
+ 0x1ed8 => true,
+ 0x1eda => true,
+ 0x1edc => true,
+ 0x1ede => true,
+ 0x1ee0 => true,
+ 0x1ee2 => true,
+ 0x1ee4 => true,
+ 0x1ee6 => true,
+ 0x1ee8 => true,
+ 0x1eea => true,
+ 0x1eec => true,
+ 0x1eee => true,
+ 0x1ef0 => true,
+ 0x1ef2 => true,
+ 0x1ef4 => true,
+ 0x1ef6 => true,
+ 0x1ef8 => true,
+ 0x1efa => true,
+ 0x1efc => true,
+ 0x1efe => true,
+ 0x1f08...0x1f0f => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f28...0x1f2f => true,
+ 0x1f38...0x1f3f => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f => true,
+ 0x1f68...0x1f6f => true,
+ 0x1fb8...0x1fbb => true,
+ 0x1fc8...0x1fcb => true,
+ 0x1fd8...0x1fdb => true,
+ 0x1fe8...0x1fec => true,
+ 0x1ff8...0x1ffb => true,
+ 0x2102 => true,
+ 0x2107 => true,
+ 0x210b...0x210d => true,
+ 0x2110...0x2112 => true,
+ 0x2115 => true,
+ 0x2119...0x211d => true,
+ 0x2124 => true,
+ 0x2126 => true,
+ 0x2128 => true,
+ 0x212a...0x212d => true,
+ 0x2130...0x2133 => true,
+ 0x213e...0x213f => true,
+ 0x2145 => true,
+ 0x2183 => true,
+ 0x2c00...0x2c2f => true,
+ 0x2c60 => true,
+ 0x2c62...0x2c64 => true,
+ 0x2c67 => true,
+ 0x2c69 => true,
+ 0x2c6b => true,
+ 0x2c6d...0x2c70 => true,
+ 0x2c72 => true,
+ 0x2c75 => true,
+ 0x2c7e...0x2c80 => true,
+ 0x2c82 => true,
+ 0x2c84 => true,
+ 0x2c86 => true,
+ 0x2c88 => true,
+ 0x2c8a => true,
+ 0x2c8c => true,
+ 0x2c8e => true,
+ 0x2c90 => true,
+ 0x2c92 => true,
+ 0x2c94 => true,
+ 0x2c96 => true,
+ 0x2c98 => true,
+ 0x2c9a => true,
+ 0x2c9c => true,
+ 0x2c9e => true,
+ 0x2ca0 => true,
+ 0x2ca2 => true,
+ 0x2ca4 => true,
+ 0x2ca6 => true,
+ 0x2ca8 => true,
+ 0x2caa => true,
+ 0x2cac => true,
+ 0x2cae => true,
+ 0x2cb0 => true,
+ 0x2cb2 => true,
+ 0x2cb4 => true,
+ 0x2cb6 => true,
+ 0x2cb8 => true,
+ 0x2cba => true,
+ 0x2cbc => true,
+ 0x2cbe => true,
+ 0x2cc0 => true,
+ 0x2cc2 => true,
+ 0x2cc4 => true,
+ 0x2cc6 => true,
+ 0x2cc8 => true,
+ 0x2cca => true,
+ 0x2ccc => true,
+ 0x2cce => true,
+ 0x2cd0 => true,
+ 0x2cd2 => true,
+ 0x2cd4 => true,
+ 0x2cd6 => true,
+ 0x2cd8 => true,
+ 0x2cda => true,
+ 0x2cdc => true,
+ 0x2cde => true,
+ 0x2ce0 => true,
+ 0x2ce2 => true,
+ 0x2ceb => true,
+ 0x2ced => true,
+ 0x2cf2 => true,
+ 0xa640 => true,
+ 0xa642 => true,
+ 0xa644 => true,
+ 0xa646 => true,
+ 0xa648 => true,
+ 0xa64a => true,
+ 0xa64c => true,
+ 0xa64e => true,
+ 0xa650 => true,
+ 0xa652 => true,
+ 0xa654 => true,
+ 0xa656 => true,
+ 0xa658 => true,
+ 0xa65a => true,
+ 0xa65c => true,
+ 0xa65e => true,
+ 0xa660 => true,
+ 0xa662 => true,
+ 0xa664 => true,
+ 0xa666 => true,
+ 0xa668 => true,
+ 0xa66a => true,
+ 0xa66c => true,
+ 0xa680 => true,
+ 0xa682 => true,
+ 0xa684 => true,
+ 0xa686 => true,
+ 0xa688 => true,
+ 0xa68a => true,
+ 0xa68c => true,
+ 0xa68e => true,
+ 0xa690 => true,
+ 0xa692 => true,
+ 0xa694 => true,
+ 0xa696 => true,
+ 0xa698 => true,
+ 0xa69a => true,
+ 0xa722 => true,
+ 0xa724 => true,
+ 0xa726 => true,
+ 0xa728 => true,
+ 0xa72a => true,
+ 0xa72c => true,
+ 0xa72e => true,
+ 0xa732 => true,
+ 0xa734 => true,
+ 0xa736 => true,
+ 0xa738 => true,
+ 0xa73a => true,
+ 0xa73c => true,
+ 0xa73e => true,
+ 0xa740 => true,
+ 0xa742 => true,
+ 0xa744 => true,
+ 0xa746 => true,
+ 0xa748 => true,
+ 0xa74a => true,
+ 0xa74c => true,
+ 0xa74e => true,
+ 0xa750 => true,
+ 0xa752 => true,
+ 0xa754 => true,
+ 0xa756 => true,
+ 0xa758 => true,
+ 0xa75a => true,
+ 0xa75c => true,
+ 0xa75e => true,
+ 0xa760 => true,
+ 0xa762 => true,
+ 0xa764 => true,
+ 0xa766 => true,
+ 0xa768 => true,
+ 0xa76a => true,
+ 0xa76c => true,
+ 0xa76e => true,
+ 0xa779 => true,
+ 0xa77b => true,
+ 0xa77d...0xa77e => true,
+ 0xa780 => true,
+ 0xa782 => true,
+ 0xa784 => true,
+ 0xa786 => true,
+ 0xa78b => true,
+ 0xa78d => true,
+ 0xa790 => true,
+ 0xa792 => true,
+ 0xa796 => true,
+ 0xa798 => true,
+ 0xa79a => true,
+ 0xa79c => true,
+ 0xa79e => true,
+ 0xa7a0 => true,
+ 0xa7a2 => true,
+ 0xa7a4 => true,
+ 0xa7a6 => true,
+ 0xa7a8 => true,
+ 0xa7aa...0xa7ae => true,
+ 0xa7b0...0xa7b4 => true,
+ 0xa7b6 => true,
+ 0xa7b8 => true,
+ 0xa7ba => true,
+ 0xa7bc => true,
+ 0xa7be => true,
+ 0xa7c0 => true,
+ 0xa7c2 => true,
+ 0xa7c4...0xa7c7 => true,
+ 0xa7c9 => true,
+ 0xa7d0 => true,
+ 0xa7d6 => true,
+ 0xa7d8 => true,
+ 0xa7f5 => true,
+ 0xff21...0xff3a => true,
+ 0x10400...0x10427 => true,
+ 0x104b0...0x104d3 => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10c80...0x10cb2 => true,
+ 0x118a0...0x118bf => true,
+ 0x16e40...0x16e5f => true,
+ 0x1d400...0x1d419 => true,
+ 0x1d434...0x1d44d => true,
+ 0x1d468...0x1d481 => true,
+ 0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b5 => true,
+ 0x1d4d0...0x1d4e9 => true,
+ 0x1d504...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d538...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d56c...0x1d585 => true,
+ 0x1d5a0...0x1d5b9 => true,
+ 0x1d5d4...0x1d5ed => true,
+ 0x1d608...0x1d621 => true,
+ 0x1d63c...0x1d655 => true,
+ 0x1d670...0x1d689 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6e2...0x1d6fa => true,
+ 0x1d71c...0x1d734 => true,
+ 0x1d756...0x1d76e => true,
+ 0x1d790...0x1d7a8 => true,
+ 0x1d7ca => true,
+ 0x1e900...0x1e921 => true,
+ else => false,
+ };
+}
+
+pub fn isLowercaseLetter(cp: u21) bool {
+ if (cp < 0x61 or cp > 0x1e943) return false;
+
+ return switch (cp) {
+ 0x61...0x7a => true,
+ 0xb5 => true,
+ 0xdf...0xf6 => true,
+ 0xf8...0xff => true,
+ 0x101 => true,
+ 0x103 => true,
+ 0x105 => true,
+ 0x107 => true,
+ 0x109 => true,
+ 0x10b => true,
+ 0x10d => true,
+ 0x10f => true,
+ 0x111 => true,
+ 0x113 => true,
+ 0x115 => true,
+ 0x117 => true,
+ 0x119 => true,
+ 0x11b => true,
+ 0x11d => true,
+ 0x11f => true,
+ 0x121 => true,
+ 0x123 => true,
+ 0x125 => true,
+ 0x127 => true,
+ 0x129 => true,
+ 0x12b => true,
+ 0x12d => true,
+ 0x12f => true,
+ 0x131 => true,
+ 0x133 => true,
+ 0x135 => true,
+ 0x137...0x138 => true,
+ 0x13a => true,
+ 0x13c => true,
+ 0x13e => true,
+ 0x140 => true,
+ 0x142 => true,
+ 0x144 => true,
+ 0x146 => true,
+ 0x148...0x149 => true,
+ 0x14b => true,
+ 0x14d => true,
+ 0x14f => true,
+ 0x151 => true,
+ 0x153 => true,
+ 0x155 => true,
+ 0x157 => true,
+ 0x159 => true,
+ 0x15b => true,
+ 0x15d => true,
+ 0x15f => true,
+ 0x161 => true,
+ 0x163 => true,
+ 0x165 => true,
+ 0x167 => true,
+ 0x169 => true,
+ 0x16b => true,
+ 0x16d => true,
+ 0x16f => true,
+ 0x171 => true,
+ 0x173 => true,
+ 0x175 => true,
+ 0x177 => true,
+ 0x17a => true,
+ 0x17c => true,
+ 0x17e...0x180 => true,
+ 0x183 => true,
+ 0x185 => true,
+ 0x188 => true,
+ 0x18c...0x18d => true,
+ 0x192 => true,
+ 0x195 => true,
+ 0x199...0x19b => true,
+ 0x19e => true,
+ 0x1a1 => true,
+ 0x1a3 => true,
+ 0x1a5 => true,
+ 0x1a8 => true,
+ 0x1aa...0x1ab => true,
+ 0x1ad => true,
+ 0x1b0 => true,
+ 0x1b4 => true,
+ 0x1b6 => true,
+ 0x1b9...0x1ba => true,
+ 0x1bd...0x1bf => true,
+ 0x1c6 => true,
+ 0x1c9 => true,
+ 0x1cc => true,
+ 0x1ce => true,
+ 0x1d0 => true,
+ 0x1d2 => true,
+ 0x1d4 => true,
+ 0x1d6 => true,
+ 0x1d8 => true,
+ 0x1da => true,
+ 0x1dc...0x1dd => true,
+ 0x1df => true,
+ 0x1e1 => true,
+ 0x1e3 => true,
+ 0x1e5 => true,
+ 0x1e7 => true,
+ 0x1e9 => true,
+ 0x1eb => true,
+ 0x1ed => true,
+ 0x1ef...0x1f0 => true,
+ 0x1f3 => true,
+ 0x1f5 => true,
+ 0x1f9 => true,
+ 0x1fb => true,
+ 0x1fd => true,
+ 0x1ff => true,
+ 0x201 => true,
+ 0x203 => true,
+ 0x205 => true,
+ 0x207 => true,
+ 0x209 => true,
+ 0x20b => true,
+ 0x20d => true,
+ 0x20f => true,
+ 0x211 => true,
+ 0x213 => true,
+ 0x215 => true,
+ 0x217 => true,
+ 0x219 => true,
+ 0x21b => true,
+ 0x21d => true,
+ 0x21f => true,
+ 0x221 => true,
+ 0x223 => true,
+ 0x225 => true,
+ 0x227 => true,
+ 0x229 => true,
+ 0x22b => true,
+ 0x22d => true,
+ 0x22f => true,
+ 0x231 => true,
+ 0x233...0x239 => true,
+ 0x23c => true,
+ 0x23f...0x240 => true,
+ 0x242 => true,
+ 0x247 => true,
+ 0x249 => true,
+ 0x24b => true,
+ 0x24d => true,
+ 0x24f...0x293 => true,
+ 0x295...0x2af => true,
+ 0x371 => true,
+ 0x373 => true,
+ 0x377 => true,
+ 0x37b...0x37d => true,
+ 0x390 => true,
+ 0x3ac...0x3ce => true,
+ 0x3d0...0x3d1 => true,
+ 0x3d5...0x3d7 => true,
+ 0x3d9 => true,
+ 0x3db => true,
+ 0x3dd => true,
+ 0x3df => true,
+ 0x3e1 => true,
+ 0x3e3 => true,
+ 0x3e5 => true,
+ 0x3e7 => true,
+ 0x3e9 => true,
+ 0x3eb => true,
+ 0x3ed => true,
+ 0x3ef...0x3f3 => true,
+ 0x3f5 => true,
+ 0x3f8 => true,
+ 0x3fb...0x3fc => true,
+ 0x430...0x45f => true,
+ 0x461 => true,
+ 0x463 => true,
+ 0x465 => true,
+ 0x467 => true,
+ 0x469 => true,
+ 0x46b => true,
+ 0x46d => true,
+ 0x46f => true,
+ 0x471 => true,
+ 0x473 => true,
+ 0x475 => true,
+ 0x477 => true,
+ 0x479 => true,
+ 0x47b => true,
+ 0x47d => true,
+ 0x47f => true,
+ 0x481 => true,
+ 0x48b => true,
+ 0x48d => true,
+ 0x48f => true,
+ 0x491 => true,
+ 0x493 => true,
+ 0x495 => true,
+ 0x497 => true,
+ 0x499 => true,
+ 0x49b => true,
+ 0x49d => true,
+ 0x49f => true,
+ 0x4a1 => true,
+ 0x4a3 => true,
+ 0x4a5 => true,
+ 0x4a7 => true,
+ 0x4a9 => true,
+ 0x4ab => true,
+ 0x4ad => true,
+ 0x4af => true,
+ 0x4b1 => true,
+ 0x4b3 => true,
+ 0x4b5 => true,
+ 0x4b7 => true,
+ 0x4b9 => true,
+ 0x4bb => true,
+ 0x4bd => true,
+ 0x4bf => true,
+ 0x4c2 => true,
+ 0x4c4 => true,
+ 0x4c6 => true,
+ 0x4c8 => true,
+ 0x4ca => true,
+ 0x4cc => true,
+ 0x4ce...0x4cf => true,
+ 0x4d1 => true,
+ 0x4d3 => true,
+ 0x4d5 => true,
+ 0x4d7 => true,
+ 0x4d9 => true,
+ 0x4db => true,
+ 0x4dd => true,
+ 0x4df => true,
+ 0x4e1 => true,
+ 0x4e3 => true,
+ 0x4e5 => true,
+ 0x4e7 => true,
+ 0x4e9 => true,
+ 0x4eb => true,
+ 0x4ed => true,
+ 0x4ef => true,
+ 0x4f1 => true,
+ 0x4f3 => true,
+ 0x4f5 => true,
+ 0x4f7 => true,
+ 0x4f9 => true,
+ 0x4fb => true,
+ 0x4fd => true,
+ 0x4ff => true,
+ 0x501 => true,
+ 0x503 => true,
+ 0x505 => true,
+ 0x507 => true,
+ 0x509 => true,
+ 0x50b => true,
+ 0x50d => true,
+ 0x50f => true,
+ 0x511 => true,
+ 0x513 => true,
+ 0x515 => true,
+ 0x517 => true,
+ 0x519 => true,
+ 0x51b => true,
+ 0x51d => true,
+ 0x51f => true,
+ 0x521 => true,
+ 0x523 => true,
+ 0x525 => true,
+ 0x527 => true,
+ 0x529 => true,
+ 0x52b => true,
+ 0x52d => true,
+ 0x52f => true,
+ 0x560...0x588 => true,
+ 0x10d0...0x10fa => true,
+ 0x10fd...0x10ff => true,
+ 0x13f8...0x13fd => true,
+ 0x1c80...0x1c88 => true,
+ 0x1d00...0x1d2b => true,
+ 0x1d6b...0x1d77 => true,
+ 0x1d79...0x1d9a => true,
+ 0x1e01 => true,
+ 0x1e03 => true,
+ 0x1e05 => true,
+ 0x1e07 => true,
+ 0x1e09 => true,
+ 0x1e0b => true,
+ 0x1e0d => true,
+ 0x1e0f => true,
+ 0x1e11 => true,
+ 0x1e13 => true,
+ 0x1e15 => true,
+ 0x1e17 => true,
+ 0x1e19 => true,
+ 0x1e1b => true,
+ 0x1e1d => true,
+ 0x1e1f => true,
+ 0x1e21 => true,
+ 0x1e23 => true,
+ 0x1e25 => true,
+ 0x1e27 => true,
+ 0x1e29 => true,
+ 0x1e2b => true,
+ 0x1e2d => true,
+ 0x1e2f => true,
+ 0x1e31 => true,
+ 0x1e33 => true,
+ 0x1e35 => true,
+ 0x1e37 => true,
+ 0x1e39 => true,
+ 0x1e3b => true,
+ 0x1e3d => true,
+ 0x1e3f => true,
+ 0x1e41 => true,
+ 0x1e43 => true,
+ 0x1e45 => true,
+ 0x1e47 => true,
+ 0x1e49 => true,
+ 0x1e4b => true,
+ 0x1e4d => true,
+ 0x1e4f => true,
+ 0x1e51 => true,
+ 0x1e53 => true,
+ 0x1e55 => true,
+ 0x1e57 => true,
+ 0x1e59 => true,
+ 0x1e5b => true,
+ 0x1e5d => true,
+ 0x1e5f => true,
+ 0x1e61 => true,
+ 0x1e63 => true,
+ 0x1e65 => true,
+ 0x1e67 => true,
+ 0x1e69 => true,
+ 0x1e6b => true,
+ 0x1e6d => true,
+ 0x1e6f => true,
+ 0x1e71 => true,
+ 0x1e73 => true,
+ 0x1e75 => true,
+ 0x1e77 => true,
+ 0x1e79 => true,
+ 0x1e7b => true,
+ 0x1e7d => true,
+ 0x1e7f => true,
+ 0x1e81 => true,
+ 0x1e83 => true,
+ 0x1e85 => true,
+ 0x1e87 => true,
+ 0x1e89 => true,
+ 0x1e8b => true,
+ 0x1e8d => true,
+ 0x1e8f => true,
+ 0x1e91 => true,
+ 0x1e93 => true,
+ 0x1e95...0x1e9d => true,
+ 0x1e9f => true,
+ 0x1ea1 => true,
+ 0x1ea3 => true,
+ 0x1ea5 => true,
+ 0x1ea7 => true,
+ 0x1ea9 => true,
+ 0x1eab => true,
+ 0x1ead => true,
+ 0x1eaf => true,
+ 0x1eb1 => true,
+ 0x1eb3 => true,
+ 0x1eb5 => true,
+ 0x1eb7 => true,
+ 0x1eb9 => true,
+ 0x1ebb => true,
+ 0x1ebd => true,
+ 0x1ebf => true,
+ 0x1ec1 => true,
+ 0x1ec3 => true,
+ 0x1ec5 => true,
+ 0x1ec7 => true,
+ 0x1ec9 => true,
+ 0x1ecb => true,
+ 0x1ecd => true,
+ 0x1ecf => true,
+ 0x1ed1 => true,
+ 0x1ed3 => true,
+ 0x1ed5 => true,
+ 0x1ed7 => true,
+ 0x1ed9 => true,
+ 0x1edb => true,
+ 0x1edd => true,
+ 0x1edf => true,
+ 0x1ee1 => true,
+ 0x1ee3 => true,
+ 0x1ee5 => true,
+ 0x1ee7 => true,
+ 0x1ee9 => true,
+ 0x1eeb => true,
+ 0x1eed => true,
+ 0x1eef => true,
+ 0x1ef1 => true,
+ 0x1ef3 => true,
+ 0x1ef5 => true,
+ 0x1ef7 => true,
+ 0x1ef9 => true,
+ 0x1efb => true,
+ 0x1efd => true,
+ 0x1eff...0x1f07 => true,
+ 0x1f10...0x1f15 => true,
+ 0x1f20...0x1f27 => true,
+ 0x1f30...0x1f37 => true,
+ 0x1f40...0x1f45 => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f60...0x1f67 => true,
+ 0x1f70...0x1f7d => true,
+ 0x1f80...0x1f87 => true,
+ 0x1f90...0x1f97 => true,
+ 0x1fa0...0x1fa7 => true,
+ 0x1fb0...0x1fb4 => true,
+ 0x1fb6...0x1fb7 => true,
+ 0x1fbe => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fc7 => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fd7 => true,
+ 0x1fe0...0x1fe7 => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ff7 => true,
+ 0x210a => true,
+ 0x210e...0x210f => true,
+ 0x2113 => true,
+ 0x212f => true,
+ 0x2134 => true,
+ 0x2139 => true,
+ 0x213c...0x213d => true,
+ 0x2146...0x2149 => true,
+ 0x214e => true,
+ 0x2184 => true,
+ 0x2c30...0x2c5f => true,
+ 0x2c61 => true,
+ 0x2c65...0x2c66 => true,
+ 0x2c68 => true,
+ 0x2c6a => true,
+ 0x2c6c => true,
+ 0x2c71 => true,
+ 0x2c73...0x2c74 => true,
+ 0x2c76...0x2c7b => true,
+ 0x2c81 => true,
+ 0x2c83 => true,
+ 0x2c85 => true,
+ 0x2c87 => true,
+ 0x2c89 => true,
+ 0x2c8b => true,
+ 0x2c8d => true,
+ 0x2c8f => true,
+ 0x2c91 => true,
+ 0x2c93 => true,
+ 0x2c95 => true,
+ 0x2c97 => true,
+ 0x2c99 => true,
+ 0x2c9b => true,
+ 0x2c9d => true,
+ 0x2c9f => true,
+ 0x2ca1 => true,
+ 0x2ca3 => true,
+ 0x2ca5 => true,
+ 0x2ca7 => true,
+ 0x2ca9 => true,
+ 0x2cab => true,
+ 0x2cad => true,
+ 0x2caf => true,
+ 0x2cb1 => true,
+ 0x2cb3 => true,
+ 0x2cb5 => true,
+ 0x2cb7 => true,
+ 0x2cb9 => true,
+ 0x2cbb => true,
+ 0x2cbd => true,
+ 0x2cbf => true,
+ 0x2cc1 => true,
+ 0x2cc3 => true,
+ 0x2cc5 => true,
+ 0x2cc7 => true,
+ 0x2cc9 => true,
+ 0x2ccb => true,
+ 0x2ccd => true,
+ 0x2ccf => true,
+ 0x2cd1 => true,
+ 0x2cd3 => true,
+ 0x2cd5 => true,
+ 0x2cd7 => true,
+ 0x2cd9 => true,
+ 0x2cdb => true,
+ 0x2cdd => true,
+ 0x2cdf => true,
+ 0x2ce1 => true,
+ 0x2ce3...0x2ce4 => true,
+ 0x2cec => true,
+ 0x2cee => true,
+ 0x2cf3 => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0xa641 => true,
+ 0xa643 => true,
+ 0xa645 => true,
+ 0xa647 => true,
+ 0xa649 => true,
+ 0xa64b => true,
+ 0xa64d => true,
+ 0xa64f => true,
+ 0xa651 => true,
+ 0xa653 => true,
+ 0xa655 => true,
+ 0xa657 => true,
+ 0xa659 => true,
+ 0xa65b => true,
+ 0xa65d => true,
+ 0xa65f => true,
+ 0xa661 => true,
+ 0xa663 => true,
+ 0xa665 => true,
+ 0xa667 => true,
+ 0xa669 => true,
+ 0xa66b => true,
+ 0xa66d => true,
+ 0xa681 => true,
+ 0xa683 => true,
+ 0xa685 => true,
+ 0xa687 => true,
+ 0xa689 => true,
+ 0xa68b => true,
+ 0xa68d => true,
+ 0xa68f => true,
+ 0xa691 => true,
+ 0xa693 => true,
+ 0xa695 => true,
+ 0xa697 => true,
+ 0xa699 => true,
+ 0xa69b => true,
+ 0xa723 => true,
+ 0xa725 => true,
+ 0xa727 => true,
+ 0xa729 => true,
+ 0xa72b => true,
+ 0xa72d => true,
+ 0xa72f...0xa731 => true,
+ 0xa733 => true,
+ 0xa735 => true,
+ 0xa737 => true,
+ 0xa739 => true,
+ 0xa73b => true,
+ 0xa73d => true,
+ 0xa73f => true,
+ 0xa741 => true,
+ 0xa743 => true,
+ 0xa745 => true,
+ 0xa747 => true,
+ 0xa749 => true,
+ 0xa74b => true,
+ 0xa74d => true,
+ 0xa74f => true,
+ 0xa751 => true,
+ 0xa753 => true,
+ 0xa755 => true,
+ 0xa757 => true,
+ 0xa759 => true,
+ 0xa75b => true,
+ 0xa75d => true,
+ 0xa75f => true,
+ 0xa761 => true,
+ 0xa763 => true,
+ 0xa765 => true,
+ 0xa767 => true,
+ 0xa769 => true,
+ 0xa76b => true,
+ 0xa76d => true,
+ 0xa76f => true,
+ 0xa771...0xa778 => true,
+ 0xa77a => true,
+ 0xa77c => true,
+ 0xa77f => true,
+ 0xa781 => true,
+ 0xa783 => true,
+ 0xa785 => true,
+ 0xa787 => true,
+ 0xa78c => true,
+ 0xa78e => true,
+ 0xa791 => true,
+ 0xa793...0xa795 => true,
+ 0xa797 => true,
+ 0xa799 => true,
+ 0xa79b => true,
+ 0xa79d => true,
+ 0xa79f => true,
+ 0xa7a1 => true,
+ 0xa7a3 => true,
+ 0xa7a5 => true,
+ 0xa7a7 => true,
+ 0xa7a9 => true,
+ 0xa7af => true,
+ 0xa7b5 => true,
+ 0xa7b7 => true,
+ 0xa7b9 => true,
+ 0xa7bb => true,
+ 0xa7bd => true,
+ 0xa7bf => true,
+ 0xa7c1 => true,
+ 0xa7c3 => true,
+ 0xa7c8 => true,
+ 0xa7ca => true,
+ 0xa7d1 => true,
+ 0xa7d3 => true,
+ 0xa7d5 => true,
+ 0xa7d7 => true,
+ 0xa7d9 => true,
+ 0xa7f6 => true,
+ 0xa7fa => true,
+ 0xab30...0xab5a => true,
+ 0xab60...0xab68 => true,
+ 0xab70...0xabbf => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xff41...0xff5a => true,
+ 0x10428...0x1044f => true,
+ 0x104d8...0x104fb => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x118c0...0x118df => true,
+ 0x16e60...0x16e7f => true,
+ 0x1d41a...0x1d433 => true,
+ 0x1d44e...0x1d454 => true,
+ 0x1d456...0x1d467 => true,
+ 0x1d482...0x1d49b => true,
+ 0x1d4b6...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d4cf => true,
+ 0x1d4ea...0x1d503 => true,
+ 0x1d51e...0x1d537 => true,
+ 0x1d552...0x1d56b => true,
+ 0x1d586...0x1d59f => true,
+ 0x1d5ba...0x1d5d3 => true,
+ 0x1d5ee...0x1d607 => true,
+ 0x1d622...0x1d63b => true,
+ 0x1d656...0x1d66f => true,
+ 0x1d68a...0x1d6a5 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6dc...0x1d6e1 => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d716...0x1d71b => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d750...0x1d755 => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d78a...0x1d78f => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c4...0x1d7c9 => true,
+ 0x1d7cb => true,
+ 0x1df00...0x1df09 => true,
+ 0x1df0b...0x1df1e => true,
+ 0x1df25...0x1df2a => true,
+ 0x1e922...0x1e943 => true,
+ else => false,
+ };
+}
+
+pub fn isTitlecaseLetter(cp: u21) bool {
+ if (cp < 0x1c5 or cp > 0x1ffc) return false;
+
+ return switch (cp) {
+ 0x1c5 => true,
+ 0x1c8 => true,
+ 0x1cb => true,
+ 0x1f2 => true,
+ 0x1f88...0x1f8f => true,
+ 0x1f98...0x1f9f => true,
+ 0x1fa8...0x1faf => true,
+ 0x1fbc => true,
+ 0x1fcc => true,
+ 0x1ffc => true,
+ else => false,
+ };
+}
+
+pub fn isModifierLetter(cp: u21) bool {
+ if (cp < 0x2b0 or cp > 0x1e94b) return false;
+
+ return switch (cp) {
+ 0x2b0...0x2c1 => true,
+ 0x2c6...0x2d1 => true,
+ 0x2e0...0x2e4 => true,
+ 0x2ec => true,
+ 0x2ee => true,
+ 0x374 => true,
+ 0x37a => true,
+ 0x559 => true,
+ 0x640 => true,
+ 0x6e5...0x6e6 => true,
+ 0x7f4...0x7f5 => true,
+ 0x7fa => true,
+ 0x81a => true,
+ 0x824 => true,
+ 0x828 => true,
+ 0x8c9 => true,
+ 0x971 => true,
+ 0xe46 => true,
+ 0xec6 => true,
+ 0x10fc => true,
+ 0x17d7 => true,
+ 0x1843 => true,
+ 0x1aa7 => true,
+ 0x1c78...0x1c7d => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d78 => true,
+ 0x1d9b...0x1dbf => true,
+ 0x2071 => true,
+ 0x207f => true,
+ 0x2090...0x209c => true,
+ 0x2c7c...0x2c7d => true,
+ 0x2d6f => true,
+ 0x2e2f => true,
+ 0x3005 => true,
+ 0x3031...0x3035 => true,
+ 0x303b => true,
+ 0x309d...0x309e => true,
+ 0x30fc...0x30fe => true,
+ 0xa015 => true,
+ 0xa4f8...0xa4fd => true,
+ 0xa60c => true,
+ 0xa67f => true,
+ 0xa69c...0xa69d => true,
+ 0xa717...0xa71f => true,
+ 0xa770 => true,
+ 0xa788 => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa9cf => true,
+ 0xa9e6 => true,
+ 0xaa70 => true,
+ 0xaadd => true,
+ 0xaaf3...0xaaf4 => true,
+ 0xab5c...0xab5f => true,
+ 0xab69 => true,
+ 0xff70 => true,
+ 0xff9e...0xff9f => true,
+ 0x10780...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x16b40...0x16b43 => true,
+ 0x16f93...0x16f9f => true,
+ 0x16fe0...0x16fe1 => true,
+ 0x16fe3 => true,
+ 0x1aff0...0x1aff3 => true,
+ 0x1aff5...0x1affb => true,
+ 0x1affd...0x1affe => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e137...0x1e13d => true,
+ 0x1e4eb => true,
+ 0x1e94b => true,
+ else => false,
+ };
+}
+
+pub fn isOtherLetter(cp: u21) bool {
+ if (cp < 0xaa or cp > 0x323af) return false;
+
+ return switch (cp) {
+ 0xaa => true,
+ 0xba => true,
+ 0x1bb => true,
+ 0x1c0...0x1c3 => true,
+ 0x294 => true,
+ 0x5d0...0x5ea => true,
+ 0x5ef...0x5f2 => true,
+ 0x620...0x63f => true,
+ 0x641...0x64a => true,
+ 0x66e...0x66f => true,
+ 0x671...0x6d3 => true,
+ 0x6d5 => true,
+ 0x6ee...0x6ef => true,
+ 0x6fa...0x6fc => true,
+ 0x6ff => true,
+ 0x710 => true,
+ 0x712...0x72f => true,
+ 0x74d...0x7a5 => true,
+ 0x7b1 => true,
+ 0x7ca...0x7ea => true,
+ 0x800...0x815 => true,
+ 0x840...0x858 => true,
+ 0x860...0x86a => true,
+ 0x870...0x887 => true,
+ 0x889...0x88e => true,
+ 0x8a0...0x8c8 => true,
+ 0x904...0x939 => true,
+ 0x93d => true,
+ 0x950 => true,
+ 0x958...0x961 => true,
+ 0x972...0x980 => true,
+ 0x985...0x98c => true,
+ 0x98f...0x990 => true,
+ 0x993...0x9a8 => true,
+ 0x9aa...0x9b0 => true,
+ 0x9b2 => true,
+ 0x9b6...0x9b9 => true,
+ 0x9bd => true,
+ 0x9ce => true,
+ 0x9dc...0x9dd => true,
+ 0x9df...0x9e1 => true,
+ 0x9f0...0x9f1 => true,
+ 0x9fc => true,
+ 0xa05...0xa0a => true,
+ 0xa0f...0xa10 => true,
+ 0xa13...0xa28 => true,
+ 0xa2a...0xa30 => true,
+ 0xa32...0xa33 => true,
+ 0xa35...0xa36 => true,
+ 0xa38...0xa39 => true,
+ 0xa59...0xa5c => true,
+ 0xa5e => true,
+ 0xa72...0xa74 => true,
+ 0xa85...0xa8d => true,
+ 0xa8f...0xa91 => true,
+ 0xa93...0xaa8 => true,
+ 0xaaa...0xab0 => true,
+ 0xab2...0xab3 => true,
+ 0xab5...0xab9 => true,
+ 0xabd => true,
+ 0xad0 => true,
+ 0xae0...0xae1 => true,
+ 0xaf9 => true,
+ 0xb05...0xb0c => true,
+ 0xb0f...0xb10 => true,
+ 0xb13...0xb28 => true,
+ 0xb2a...0xb30 => true,
+ 0xb32...0xb33 => true,
+ 0xb35...0xb39 => true,
+ 0xb3d => true,
+ 0xb5c...0xb5d => true,
+ 0xb5f...0xb61 => true,
+ 0xb71 => true,
+ 0xb83 => true,
+ 0xb85...0xb8a => true,
+ 0xb8e...0xb90 => true,
+ 0xb92...0xb95 => true,
+ 0xb99...0xb9a => true,
+ 0xb9c => true,
+ 0xb9e...0xb9f => true,
+ 0xba3...0xba4 => true,
+ 0xba8...0xbaa => true,
+ 0xbae...0xbb9 => true,
+ 0xbd0 => true,
+ 0xc05...0xc0c => true,
+ 0xc0e...0xc10 => true,
+ 0xc12...0xc28 => true,
+ 0xc2a...0xc39 => true,
+ 0xc3d => true,
+ 0xc58...0xc5a => true,
+ 0xc5d => true,
+ 0xc60...0xc61 => true,
+ 0xc80 => true,
+ 0xc85...0xc8c => true,
+ 0xc8e...0xc90 => true,
+ 0xc92...0xca8 => true,
+ 0xcaa...0xcb3 => true,
+ 0xcb5...0xcb9 => true,
+ 0xcbd => true,
+ 0xcdd...0xcde => true,
+ 0xce0...0xce1 => true,
+ 0xcf1...0xcf2 => true,
+ 0xd04...0xd0c => true,
+ 0xd0e...0xd10 => true,
+ 0xd12...0xd3a => true,
+ 0xd3d => true,
+ 0xd4e => true,
+ 0xd54...0xd56 => true,
+ 0xd5f...0xd61 => true,
+ 0xd7a...0xd7f => true,
+ 0xd85...0xd96 => true,
+ 0xd9a...0xdb1 => true,
+ 0xdb3...0xdbb => true,
+ 0xdbd => true,
+ 0xdc0...0xdc6 => true,
+ 0xe01...0xe30 => true,
+ 0xe32...0xe33 => true,
+ 0xe40...0xe45 => true,
+ 0xe81...0xe82 => true,
+ 0xe84 => true,
+ 0xe86...0xe8a => true,
+ 0xe8c...0xea3 => true,
+ 0xea5 => true,
+ 0xea7...0xeb0 => true,
+ 0xeb2...0xeb3 => true,
+ 0xebd => true,
+ 0xec0...0xec4 => true,
+ 0xedc...0xedf => true,
+ 0xf00 => true,
+ 0xf40...0xf47 => true,
+ 0xf49...0xf6c => true,
+ 0xf88...0xf8c => true,
+ 0x1000...0x102a => true,
+ 0x103f => true,
+ 0x1050...0x1055 => true,
+ 0x105a...0x105d => true,
+ 0x1061 => true,
+ 0x1065...0x1066 => true,
+ 0x106e...0x1070 => true,
+ 0x1075...0x1081 => true,
+ 0x108e => true,
+ 0x1100...0x1248 => true,
+ 0x124a...0x124d => true,
+ 0x1250...0x1256 => true,
+ 0x1258 => true,
+ 0x125a...0x125d => true,
+ 0x1260...0x1288 => true,
+ 0x128a...0x128d => true,
+ 0x1290...0x12b0 => true,
+ 0x12b2...0x12b5 => true,
+ 0x12b8...0x12be => true,
+ 0x12c0 => true,
+ 0x12c2...0x12c5 => true,
+ 0x12c8...0x12d6 => true,
+ 0x12d8...0x1310 => true,
+ 0x1312...0x1315 => true,
+ 0x1318...0x135a => true,
+ 0x1380...0x138f => true,
+ 0x1401...0x166c => true,
+ 0x166f...0x167f => true,
+ 0x1681...0x169a => true,
+ 0x16a0...0x16ea => true,
+ 0x16f1...0x16f8 => true,
+ 0x1700...0x1711 => true,
+ 0x171f...0x1731 => true,
+ 0x1740...0x1751 => true,
+ 0x1760...0x176c => true,
+ 0x176e...0x1770 => true,
+ 0x1780...0x17b3 => true,
+ 0x17dc => true,
+ 0x1820...0x1842 => true,
+ 0x1844...0x1878 => true,
+ 0x1880...0x1884 => true,
+ 0x1887...0x18a8 => true,
+ 0x18aa => true,
+ 0x18b0...0x18f5 => true,
+ 0x1900...0x191e => true,
+ 0x1950...0x196d => true,
+ 0x1970...0x1974 => true,
+ 0x1980...0x19ab => true,
+ 0x19b0...0x19c9 => true,
+ 0x1a00...0x1a16 => true,
+ 0x1a20...0x1a54 => true,
+ 0x1b05...0x1b33 => true,
+ 0x1b45...0x1b4c => true,
+ 0x1b83...0x1ba0 => true,
+ 0x1bae...0x1baf => true,
+ 0x1bba...0x1be5 => true,
+ 0x1c00...0x1c23 => true,
+ 0x1c4d...0x1c4f => true,
+ 0x1c5a...0x1c77 => true,
+ 0x1ce9...0x1cec => true,
+ 0x1cee...0x1cf3 => true,
+ 0x1cf5...0x1cf6 => true,
+ 0x1cfa => true,
+ 0x2135...0x2138 => true,
+ 0x2d30...0x2d67 => true,
+ 0x2d80...0x2d96 => true,
+ 0x2da0...0x2da6 => true,
+ 0x2da8...0x2dae => true,
+ 0x2db0...0x2db6 => true,
+ 0x2db8...0x2dbe => true,
+ 0x2dc0...0x2dc6 => true,
+ 0x2dc8...0x2dce => true,
+ 0x2dd0...0x2dd6 => true,
+ 0x2dd8...0x2dde => true,
+ 0x3006 => true,
+ 0x303c => true,
+ 0x3041...0x3096 => true,
+ 0x309f => true,
+ 0x30a1...0x30fa => true,
+ 0x30ff => true,
+ 0x3105...0x312f => true,
+ 0x3131...0x318e => true,
+ 0x31a0...0x31bf => true,
+ 0x31f0...0x31ff => true,
+ 0x3400...0x4dbf => true,
+ 0x4e00...0xa014 => true,
+ 0xa016...0xa48c => true,
+ 0xa4d0...0xa4f7 => true,
+ 0xa500...0xa60b => true,
+ 0xa610...0xa61f => true,
+ 0xa62a...0xa62b => true,
+ 0xa66e => true,
+ 0xa6a0...0xa6e5 => true,
+ 0xa78f => true,
+ 0xa7f7 => true,
+ 0xa7fb...0xa801 => true,
+ 0xa803...0xa805 => true,
+ 0xa807...0xa80a => true,
+ 0xa80c...0xa822 => true,
+ 0xa840...0xa873 => true,
+ 0xa882...0xa8b3 => true,
+ 0xa8f2...0xa8f7 => true,
+ 0xa8fb => true,
+ 0xa8fd...0xa8fe => true,
+ 0xa90a...0xa925 => true,
+ 0xa930...0xa946 => true,
+ 0xa960...0xa97c => true,
+ 0xa984...0xa9b2 => true,
+ 0xa9e0...0xa9e4 => true,
+ 0xa9e7...0xa9ef => true,
+ 0xa9fa...0xa9fe => true,
+ 0xaa00...0xaa28 => true,
+ 0xaa40...0xaa42 => true,
+ 0xaa44...0xaa4b => true,
+ 0xaa60...0xaa6f => true,
+ 0xaa71...0xaa76 => true,
+ 0xaa7a => true,
+ 0xaa7e...0xaaaf => true,
+ 0xaab1 => true,
+ 0xaab5...0xaab6 => true,
+ 0xaab9...0xaabd => true,
+ 0xaac0 => true,
+ 0xaac2 => true,
+ 0xaadb...0xaadc => true,
+ 0xaae0...0xaaea => true,
+ 0xaaf2 => true,
+ 0xab01...0xab06 => true,
+ 0xab09...0xab0e => true,
+ 0xab11...0xab16 => true,
+ 0xab20...0xab26 => true,
+ 0xab28...0xab2e => true,
+ 0xabc0...0xabe2 => true,
+ 0xac00...0xd7a3 => true,
+ 0xd7b0...0xd7c6 => true,
+ 0xd7cb...0xd7fb => true,
+ 0xf900...0xfa6d => true,
+ 0xfa70...0xfad9 => true,
+ 0xfb1d => true,
+ 0xfb1f...0xfb28 => true,
+ 0xfb2a...0xfb36 => true,
+ 0xfb38...0xfb3c => true,
+ 0xfb3e => true,
+ 0xfb40...0xfb41 => true,
+ 0xfb43...0xfb44 => true,
+ 0xfb46...0xfbb1 => true,
+ 0xfbd3...0xfd3d => true,
+ 0xfd50...0xfd8f => true,
+ 0xfd92...0xfdc7 => true,
+ 0xfdf0...0xfdfb => true,
+ 0xfe70...0xfe74 => true,
+ 0xfe76...0xfefc => true,
+ 0xff66...0xff6f => true,
+ 0xff71...0xff9d => true,
+ 0xffa0...0xffbe => true,
+ 0xffc2...0xffc7 => true,
+ 0xffca...0xffcf => true,
+ 0xffd2...0xffd7 => true,
+ 0xffda...0xffdc => true,
+ 0x10000...0x1000b => true,
+ 0x1000d...0x10026 => true,
+ 0x10028...0x1003a => true,
+ 0x1003c...0x1003d => true,
+ 0x1003f...0x1004d => true,
+ 0x10050...0x1005d => true,
+ 0x10080...0x100fa => true,
+ 0x10280...0x1029c => true,
+ 0x102a0...0x102d0 => true,
+ 0x10300...0x1031f => true,
+ 0x1032d...0x10340 => true,
+ 0x10342...0x10349 => true,
+ 0x10350...0x10375 => true,
+ 0x10380...0x1039d => true,
+ 0x103a0...0x103c3 => true,
+ 0x103c8...0x103cf => true,
+ 0x10450...0x1049d => true,
+ 0x10500...0x10527 => true,
+ 0x10530...0x10563 => true,
+ 0x10600...0x10736 => true,
+ 0x10740...0x10755 => true,
+ 0x10760...0x10767 => true,
+ 0x10800...0x10805 => true,
+ 0x10808 => true,
+ 0x1080a...0x10835 => true,
+ 0x10837...0x10838 => true,
+ 0x1083c => true,
+ 0x1083f...0x10855 => true,
+ 0x10860...0x10876 => true,
+ 0x10880...0x1089e => true,
+ 0x108e0...0x108f2 => true,
+ 0x108f4...0x108f5 => true,
+ 0x10900...0x10915 => true,
+ 0x10920...0x10939 => true,
+ 0x10980...0x109b7 => true,
+ 0x109be...0x109bf => true,
+ 0x10a00 => true,
+ 0x10a10...0x10a13 => true,
+ 0x10a15...0x10a17 => true,
+ 0x10a19...0x10a35 => true,
+ 0x10a60...0x10a7c => true,
+ 0x10a80...0x10a9c => true,
+ 0x10ac0...0x10ac7 => true,
+ 0x10ac9...0x10ae4 => true,
+ 0x10b00...0x10b35 => true,
+ 0x10b40...0x10b55 => true,
+ 0x10b60...0x10b72 => true,
+ 0x10b80...0x10b91 => true,
+ 0x10c00...0x10c48 => true,
+ 0x10d00...0x10d23 => true,
+ 0x10e80...0x10ea9 => true,
+ 0x10eb0...0x10eb1 => true,
+ 0x10f00...0x10f1c => true,
+ 0x10f27 => true,
+ 0x10f30...0x10f45 => true,
+ 0x10f70...0x10f81 => true,
+ 0x10fb0...0x10fc4 => true,
+ 0x10fe0...0x10ff6 => true,
+ 0x11003...0x11037 => true,
+ 0x11071...0x11072 => true,
+ 0x11075 => true,
+ 0x11083...0x110af => true,
+ 0x110d0...0x110e8 => true,
+ 0x11103...0x11126 => true,
+ 0x11144 => true,
+ 0x11147 => true,
+ 0x11150...0x11172 => true,
+ 0x11176 => true,
+ 0x11183...0x111b2 => true,
+ 0x111c1...0x111c4 => true,
+ 0x111da => true,
+ 0x111dc => true,
+ 0x11200...0x11211 => true,
+ 0x11213...0x1122b => true,
+ 0x1123f...0x11240 => true,
+ 0x11280...0x11286 => true,
+ 0x11288 => true,
+ 0x1128a...0x1128d => true,
+ 0x1128f...0x1129d => true,
+ 0x1129f...0x112a8 => true,
+ 0x112b0...0x112de => true,
+ 0x11305...0x1130c => true,
+ 0x1130f...0x11310 => true,
+ 0x11313...0x11328 => true,
+ 0x1132a...0x11330 => true,
+ 0x11332...0x11333 => true,
+ 0x11335...0x11339 => true,
+ 0x1133d => true,
+ 0x11350 => true,
+ 0x1135d...0x11361 => true,
+ 0x11400...0x11434 => true,
+ 0x11447...0x1144a => true,
+ 0x1145f...0x11461 => true,
+ 0x11480...0x114af => true,
+ 0x114c4...0x114c5 => true,
+ 0x114c7 => true,
+ 0x11580...0x115ae => true,
+ 0x115d8...0x115db => true,
+ 0x11600...0x1162f => true,
+ 0x11644 => true,
+ 0x11680...0x116aa => true,
+ 0x116b8 => true,
+ 0x11700...0x1171a => true,
+ 0x11740...0x11746 => true,
+ 0x11800...0x1182b => true,
+ 0x118ff...0x11906 => true,
+ 0x11909 => true,
+ 0x1190c...0x11913 => true,
+ 0x11915...0x11916 => true,
+ 0x11918...0x1192f => true,
+ 0x1193f => true,
+ 0x11941 => true,
+ 0x119a0...0x119a7 => true,
+ 0x119aa...0x119d0 => true,
+ 0x119e1 => true,
+ 0x119e3 => true,
+ 0x11a00 => true,
+ 0x11a0b...0x11a32 => true,
+ 0x11a3a => true,
+ 0x11a50 => true,
+ 0x11a5c...0x11a89 => true,
+ 0x11a9d => true,
+ 0x11ab0...0x11af8 => true,
+ 0x11c00...0x11c08 => true,
+ 0x11c0a...0x11c2e => true,
+ 0x11c40 => true,
+ 0x11c72...0x11c8f => true,
+ 0x11d00...0x11d06 => true,
+ 0x11d08...0x11d09 => true,
+ 0x11d0b...0x11d30 => true,
+ 0x11d46 => true,
+ 0x11d60...0x11d65 => true,
+ 0x11d67...0x11d68 => true,
+ 0x11d6a...0x11d89 => true,
+ 0x11d98 => true,
+ 0x11ee0...0x11ef2 => true,
+ 0x11f02 => true,
+ 0x11f04...0x11f10 => true,
+ 0x11f12...0x11f33 => true,
+ 0x11fb0 => true,
+ 0x12000...0x12399 => true,
+ 0x12480...0x12543 => true,
+ 0x12f90...0x12ff0 => true,
+ 0x13000...0x1342f => true,
+ 0x13441...0x13446 => true,
+ 0x14400...0x14646 => true,
+ 0x16800...0x16a38 => true,
+ 0x16a40...0x16a5e => true,
+ 0x16a70...0x16abe => true,
+ 0x16ad0...0x16aed => true,
+ 0x16b00...0x16b2f => true,
+ 0x16b63...0x16b77 => true,
+ 0x16b7d...0x16b8f => true,
+ 0x16f00...0x16f4a => true,
+ 0x16f50 => true,
+ 0x17000...0x187f7 => true,
+ 0x18800...0x18cd5 => true,
+ 0x18d00...0x18d08 => true,
+ 0x1b000...0x1b122 => true,
+ 0x1b132 => true,
+ 0x1b150...0x1b152 => true,
+ 0x1b155 => true,
+ 0x1b164...0x1b167 => true,
+ 0x1b170...0x1b2fb => true,
+ 0x1bc00...0x1bc6a => true,
+ 0x1bc70...0x1bc7c => true,
+ 0x1bc80...0x1bc88 => true,
+ 0x1bc90...0x1bc99 => true,
+ 0x1df0a => true,
+ 0x1e100...0x1e12c => true,
+ 0x1e14e => true,
+ 0x1e290...0x1e2ad => true,
+ 0x1e2c0...0x1e2eb => true,
+ 0x1e4d0...0x1e4ea => true,
+ 0x1e7e0...0x1e7e6 => true,
+ 0x1e7e8...0x1e7eb => true,
+ 0x1e7ed...0x1e7ee => true,
+ 0x1e7f0...0x1e7fe => true,
+ 0x1e800...0x1e8c4 => true,
+ 0x1ee00...0x1ee03 => true,
+ 0x1ee05...0x1ee1f => true,
+ 0x1ee21...0x1ee22 => true,
+ 0x1ee24 => true,
+ 0x1ee27 => true,
+ 0x1ee29...0x1ee32 => true,
+ 0x1ee34...0x1ee37 => true,
+ 0x1ee39 => true,
+ 0x1ee3b => true,
+ 0x1ee42 => true,
+ 0x1ee47 => true,
+ 0x1ee49 => true,
+ 0x1ee4b => true,
+ 0x1ee4d...0x1ee4f => true,
+ 0x1ee51...0x1ee52 => true,
+ 0x1ee54 => true,
+ 0x1ee57 => true,
+ 0x1ee59 => true,
+ 0x1ee5b => true,
+ 0x1ee5d => true,
+ 0x1ee5f => true,
+ 0x1ee61...0x1ee62 => true,
+ 0x1ee64 => true,
+ 0x1ee67...0x1ee6a => true,
+ 0x1ee6c...0x1ee72 => true,
+ 0x1ee74...0x1ee77 => true,
+ 0x1ee79...0x1ee7c => true,
+ 0x1ee7e => true,
+ 0x1ee80...0x1ee89 => true,
+ 0x1ee8b...0x1ee9b => true,
+ 0x1eea1...0x1eea3 => true,
+ 0x1eea5...0x1eea9 => true,
+ 0x1eeab...0x1eebb => true,
+ 0x20000...0x2a6df => true,
+ 0x2a700...0x2b739 => true,
+ 0x2b740...0x2b81d => true,
+ 0x2b820...0x2cea1 => true,
+ 0x2ceb0...0x2ebe0 => true,
+ 0x2f800...0x2fa1d => true,
+ 0x30000...0x3134a => true,
+ 0x31350...0x323af => true,
+ else => false,
+ };
+}
+
+pub fn isNonspacingMark(cp: u21) bool {
+ if (cp < 0x300 or cp > 0xe01ef) return false;
+
+ return switch (cp) {
+ 0x300...0x36f => true,
+ 0x483...0x487 => true,
+ 0x591...0x5bd => true,
+ 0x5bf => true,
+ 0x5c1...0x5c2 => true,
+ 0x5c4...0x5c5 => true,
+ 0x5c7 => true,
+ 0x610...0x61a => true,
+ 0x64b...0x65f => true,
+ 0x670 => true,
+ 0x6d6...0x6dc => true,
+ 0x6df...0x6e4 => true,
+ 0x6e7...0x6e8 => true,
+ 0x6ea...0x6ed => true,
+ 0x711 => true,
+ 0x730...0x74a => true,
+ 0x7a6...0x7b0 => true,
+ 0x7eb...0x7f3 => true,
+ 0x7fd => true,
+ 0x816...0x819 => true,
+ 0x81b...0x823 => true,
+ 0x825...0x827 => true,
+ 0x829...0x82d => true,
+ 0x859...0x85b => true,
+ 0x898...0x89f => true,
+ 0x8ca...0x8e1 => true,
+ 0x8e3...0x902 => true,
+ 0x93a => true,
+ 0x93c => true,
+ 0x941...0x948 => true,
+ 0x94d => true,
+ 0x951...0x957 => true,
+ 0x962...0x963 => true,
+ 0x981 => true,
+ 0x9bc => true,
+ 0x9c1...0x9c4 => true,
+ 0x9cd => true,
+ 0x9e2...0x9e3 => true,
+ 0x9fe => true,
+ 0xa01...0xa02 => true,
+ 0xa3c => true,
+ 0xa41...0xa42 => true,
+ 0xa47...0xa48 => true,
+ 0xa4b...0xa4d => true,
+ 0xa51 => true,
+ 0xa70...0xa71 => true,
+ 0xa75 => true,
+ 0xa81...0xa82 => true,
+ 0xabc => true,
+ 0xac1...0xac5 => true,
+ 0xac7...0xac8 => true,
+ 0xacd => true,
+ 0xae2...0xae3 => true,
+ 0xafa...0xaff => true,
+ 0xb01 => true,
+ 0xb3c => true,
+ 0xb3f => true,
+ 0xb41...0xb44 => true,
+ 0xb4d => true,
+ 0xb55...0xb56 => true,
+ 0xb62...0xb63 => true,
+ 0xb82 => true,
+ 0xbc0 => true,
+ 0xbcd => true,
+ 0xc00 => true,
+ 0xc04 => true,
+ 0xc3c => true,
+ 0xc3e...0xc40 => true,
+ 0xc46...0xc48 => true,
+ 0xc4a...0xc4d => true,
+ 0xc55...0xc56 => true,
+ 0xc62...0xc63 => true,
+ 0xc81 => true,
+ 0xcbc => true,
+ 0xcbf => true,
+ 0xcc6 => true,
+ 0xccc...0xccd => true,
+ 0xce2...0xce3 => true,
+ 0xd00...0xd01 => true,
+ 0xd3b...0xd3c => true,
+ 0xd41...0xd44 => true,
+ 0xd4d => true,
+ 0xd62...0xd63 => true,
+ 0xd81 => true,
+ 0xdca => true,
+ 0xdd2...0xdd4 => true,
+ 0xdd6 => true,
+ 0xe31 => true,
+ 0xe34...0xe3a => true,
+ 0xe47...0xe4e => true,
+ 0xeb1 => true,
+ 0xeb4...0xebc => true,
+ 0xec8...0xece => true,
+ 0xf18...0xf19 => true,
+ 0xf35 => true,
+ 0xf37 => true,
+ 0xf39 => true,
+ 0xf71...0xf7e => true,
+ 0xf80...0xf84 => true,
+ 0xf86...0xf87 => true,
+ 0xf8d...0xf97 => true,
+ 0xf99...0xfbc => true,
+ 0xfc6 => true,
+ 0x102d...0x1030 => true,
+ 0x1032...0x1037 => true,
+ 0x1039...0x103a => true,
+ 0x103d...0x103e => true,
+ 0x1058...0x1059 => true,
+ 0x105e...0x1060 => true,
+ 0x1071...0x1074 => true,
+ 0x1082 => true,
+ 0x1085...0x1086 => true,
+ 0x108d => true,
+ 0x109d => true,
+ 0x135d...0x135f => true,
+ 0x1712...0x1714 => true,
+ 0x1732...0x1733 => true,
+ 0x1752...0x1753 => true,
+ 0x1772...0x1773 => true,
+ 0x17b4...0x17b5 => true,
+ 0x17b7...0x17bd => true,
+ 0x17c6 => true,
+ 0x17c9...0x17d3 => true,
+ 0x17dd => true,
+ 0x180b...0x180d => true,
+ 0x180f => true,
+ 0x1885...0x1886 => true,
+ 0x18a9 => true,
+ 0x1920...0x1922 => true,
+ 0x1927...0x1928 => true,
+ 0x1932 => true,
+ 0x1939...0x193b => true,
+ 0x1a17...0x1a18 => true,
+ 0x1a1b => true,
+ 0x1a56 => true,
+ 0x1a58...0x1a5e => true,
+ 0x1a60 => true,
+ 0x1a62 => true,
+ 0x1a65...0x1a6c => true,
+ 0x1a73...0x1a7c => true,
+ 0x1a7f => true,
+ 0x1ab0...0x1abd => true,
+ 0x1abf...0x1ace => true,
+ 0x1b00...0x1b03 => true,
+ 0x1b34 => true,
+ 0x1b36...0x1b3a => true,
+ 0x1b3c => true,
+ 0x1b42 => true,
+ 0x1b6b...0x1b73 => true,
+ 0x1b80...0x1b81 => true,
+ 0x1ba2...0x1ba5 => true,
+ 0x1ba8...0x1ba9 => true,
+ 0x1bab...0x1bad => true,
+ 0x1be6 => true,
+ 0x1be8...0x1be9 => true,
+ 0x1bed => true,
+ 0x1bef...0x1bf1 => true,
+ 0x1c2c...0x1c33 => true,
+ 0x1c36...0x1c37 => true,
+ 0x1cd0...0x1cd2 => true,
+ 0x1cd4...0x1ce0 => true,
+ 0x1ce2...0x1ce8 => true,
+ 0x1ced => true,
+ 0x1cf4 => true,
+ 0x1cf8...0x1cf9 => true,
+ 0x1dc0...0x1dff => true,
+ 0x20d0...0x20dc => true,
+ 0x20e1 => true,
+ 0x20e5...0x20f0 => true,
+ 0x2cef...0x2cf1 => true,
+ 0x2d7f => true,
+ 0x2de0...0x2dff => true,
+ 0x302a...0x302d => true,
+ 0x3099...0x309a => true,
+ 0xa66f => true,
+ 0xa674...0xa67d => true,
+ 0xa69e...0xa69f => true,
+ 0xa6f0...0xa6f1 => true,
+ 0xa802 => true,
+ 0xa806 => true,
+ 0xa80b => true,
+ 0xa825...0xa826 => true,
+ 0xa82c => true,
+ 0xa8c4...0xa8c5 => true,
+ 0xa8e0...0xa8f1 => true,
+ 0xa8ff => true,
+ 0xa926...0xa92d => true,
+ 0xa947...0xa951 => true,
+ 0xa980...0xa982 => true,
+ 0xa9b3 => true,
+ 0xa9b6...0xa9b9 => true,
+ 0xa9bc...0xa9bd => true,
+ 0xa9e5 => true,
+ 0xaa29...0xaa2e => true,
+ 0xaa31...0xaa32 => true,
+ 0xaa35...0xaa36 => true,
+ 0xaa43 => true,
+ 0xaa4c => true,
+ 0xaa7c => true,
+ 0xaab0 => true,
+ 0xaab2...0xaab4 => true,
+ 0xaab7...0xaab8 => true,
+ 0xaabe...0xaabf => true,
+ 0xaac1 => true,
+ 0xaaec...0xaaed => true,
+ 0xaaf6 => true,
+ 0xabe5 => true,
+ 0xabe8 => true,
+ 0xabed => true,
+ 0xfb1e => true,
+ 0xfe00...0xfe0f => true,
+ 0xfe20...0xfe2f => true,
+ 0x101fd => true,
+ 0x102e0 => true,
+ 0x10376...0x1037a => true,
+ 0x10a01...0x10a03 => true,
+ 0x10a05...0x10a06 => true,
+ 0x10a0c...0x10a0f => true,
+ 0x10a38...0x10a3a => true,
+ 0x10a3f => true,
+ 0x10ae5...0x10ae6 => true,
+ 0x10d24...0x10d27 => true,
+ 0x10eab...0x10eac => true,
+ 0x10efd...0x10eff => true,
+ 0x10f46...0x10f50 => true,
+ 0x10f82...0x10f85 => true,
+ 0x11001 => true,
+ 0x11038...0x11046 => true,
+ 0x11070 => true,
+ 0x11073...0x11074 => true,
+ 0x1107f...0x11081 => true,
+ 0x110b3...0x110b6 => true,
+ 0x110b9...0x110ba => true,
+ 0x110c2 => true,
+ 0x11100...0x11102 => true,
+ 0x11127...0x1112b => true,
+ 0x1112d...0x11134 => true,
+ 0x11173 => true,
+ 0x11180...0x11181 => true,
+ 0x111b6...0x111be => true,
+ 0x111c9...0x111cc => true,
+ 0x111cf => true,
+ 0x1122f...0x11231 => true,
+ 0x11234 => true,
+ 0x11236...0x11237 => true,
+ 0x1123e => true,
+ 0x11241 => true,
+ 0x112df => true,
+ 0x112e3...0x112ea => true,
+ 0x11300...0x11301 => true,
+ 0x1133b...0x1133c => true,
+ 0x11340 => true,
+ 0x11366...0x1136c => true,
+ 0x11370...0x11374 => true,
+ 0x11438...0x1143f => true,
+ 0x11442...0x11444 => true,
+ 0x11446 => true,
+ 0x1145e => true,
+ 0x114b3...0x114b8 => true,
+ 0x114ba => true,
+ 0x114bf...0x114c0 => true,
+ 0x114c2...0x114c3 => true,
+ 0x115b2...0x115b5 => true,
+ 0x115bc...0x115bd => true,
+ 0x115bf...0x115c0 => true,
+ 0x115dc...0x115dd => true,
+ 0x11633...0x1163a => true,
+ 0x1163d => true,
+ 0x1163f...0x11640 => true,
+ 0x116ab => true,
+ 0x116ad => true,
+ 0x116b0...0x116b5 => true,
+ 0x116b7 => true,
+ 0x1171d...0x1171f => true,
+ 0x11722...0x11725 => true,
+ 0x11727...0x1172b => true,
+ 0x1182f...0x11837 => true,
+ 0x11839...0x1183a => true,
+ 0x1193b...0x1193c => true,
+ 0x1193e => true,
+ 0x11943 => true,
+ 0x119d4...0x119d7 => true,
+ 0x119da...0x119db => true,
+ 0x119e0 => true,
+ 0x11a01...0x11a0a => true,
+ 0x11a33...0x11a38 => true,
+ 0x11a3b...0x11a3e => true,
+ 0x11a47 => true,
+ 0x11a51...0x11a56 => true,
+ 0x11a59...0x11a5b => true,
+ 0x11a8a...0x11a96 => true,
+ 0x11a98...0x11a99 => true,
+ 0x11c30...0x11c36 => true,
+ 0x11c38...0x11c3d => true,
+ 0x11c3f => true,
+ 0x11c92...0x11ca7 => true,
+ 0x11caa...0x11cb0 => true,
+ 0x11cb2...0x11cb3 => true,
+ 0x11cb5...0x11cb6 => true,
+ 0x11d31...0x11d36 => true,
+ 0x11d3a => true,
+ 0x11d3c...0x11d3d => true,
+ 0x11d3f...0x11d45 => true,
+ 0x11d47 => true,
+ 0x11d90...0x11d91 => true,
+ 0x11d95 => true,
+ 0x11d97 => true,
+ 0x11ef3...0x11ef4 => true,
+ 0x11f00...0x11f01 => true,
+ 0x11f36...0x11f3a => true,
+ 0x11f40 => true,
+ 0x11f42 => true,
+ 0x13440 => true,
+ 0x13447...0x13455 => true,
+ 0x16af0...0x16af4 => true,
+ 0x16b30...0x16b36 => true,
+ 0x16f4f => true,
+ 0x16f8f...0x16f92 => true,
+ 0x16fe4 => true,
+ 0x1bc9d...0x1bc9e => true,
+ 0x1cf00...0x1cf2d => true,
+ 0x1cf30...0x1cf46 => true,
+ 0x1d167...0x1d169 => true,
+ 0x1d17b...0x1d182 => true,
+ 0x1d185...0x1d18b => true,
+ 0x1d1aa...0x1d1ad => true,
+ 0x1d242...0x1d244 => true,
+ 0x1da00...0x1da36 => true,
+ 0x1da3b...0x1da6c => true,
+ 0x1da75 => true,
+ 0x1da84 => true,
+ 0x1da9b...0x1da9f => true,
+ 0x1daa1...0x1daaf => true,
+ 0x1e000...0x1e006 => true,
+ 0x1e008...0x1e018 => true,
+ 0x1e01b...0x1e021 => true,
+ 0x1e023...0x1e024 => true,
+ 0x1e026...0x1e02a => true,
+ 0x1e08f => true,
+ 0x1e130...0x1e136 => true,
+ 0x1e2ae => true,
+ 0x1e2ec...0x1e2ef => true,
+ 0x1e4ec...0x1e4ef => true,
+ 0x1e8d0...0x1e8d6 => true,
+ 0x1e944...0x1e94a => true,
+ 0xe0100...0xe01ef => true,
+ else => false,
+ };
+}
+
+pub fn isEnclosingMark(cp: u21) bool {
+ if (cp < 0x488 or cp > 0xa672) return false;
+
+ return switch (cp) {
+ 0x488...0x489 => true,
+ 0x1abe => true,
+ 0x20dd...0x20e0 => true,
+ 0x20e2...0x20e4 => true,
+ 0xa670...0xa672 => true,
+ else => false,
+ };
+}
+
+pub fn isSpacingMark(cp: u21) bool {
+ if (cp < 0x903 or cp > 0x1d172) return false;
+
+ return switch (cp) {
+ 0x903 => true,
+ 0x93b => true,
+ 0x93e...0x940 => true,
+ 0x949...0x94c => true,
+ 0x94e...0x94f => true,
+ 0x982...0x983 => true,
+ 0x9be...0x9c0 => true,
+ 0x9c7...0x9c8 => true,
+ 0x9cb...0x9cc => true,
+ 0x9d7 => true,
+ 0xa03 => true,
+ 0xa3e...0xa40 => true,
+ 0xa83 => true,
+ 0xabe...0xac0 => true,
+ 0xac9 => true,
+ 0xacb...0xacc => true,
+ 0xb02...0xb03 => true,
+ 0xb3e => true,
+ 0xb40 => true,
+ 0xb47...0xb48 => true,
+ 0xb4b...0xb4c => true,
+ 0xb57 => true,
+ 0xbbe...0xbbf => true,
+ 0xbc1...0xbc2 => true,
+ 0xbc6...0xbc8 => true,
+ 0xbca...0xbcc => true,
+ 0xbd7 => true,
+ 0xc01...0xc03 => true,
+ 0xc41...0xc44 => true,
+ 0xc82...0xc83 => true,
+ 0xcbe => true,
+ 0xcc0...0xcc4 => true,
+ 0xcc7...0xcc8 => true,
+ 0xcca...0xccb => true,
+ 0xcd5...0xcd6 => true,
+ 0xcf3 => true,
+ 0xd02...0xd03 => true,
+ 0xd3e...0xd40 => true,
+ 0xd46...0xd48 => true,
+ 0xd4a...0xd4c => true,
+ 0xd57 => true,
+ 0xd82...0xd83 => true,
+ 0xdcf...0xdd1 => true,
+ 0xdd8...0xddf => true,
+ 0xdf2...0xdf3 => true,
+ 0xf3e...0xf3f => true,
+ 0xf7f => true,
+ 0x102b...0x102c => true,
+ 0x1031 => true,
+ 0x1038 => true,
+ 0x103b...0x103c => true,
+ 0x1056...0x1057 => true,
+ 0x1062...0x1064 => true,
+ 0x1067...0x106d => true,
+ 0x1083...0x1084 => true,
+ 0x1087...0x108c => true,
+ 0x108f => true,
+ 0x109a...0x109c => true,
+ 0x1715 => true,
+ 0x1734 => true,
+ 0x17b6 => true,
+ 0x17be...0x17c5 => true,
+ 0x17c7...0x17c8 => true,
+ 0x1923...0x1926 => true,
+ 0x1929...0x192b => true,
+ 0x1930...0x1931 => true,
+ 0x1933...0x1938 => true,
+ 0x1a19...0x1a1a => true,
+ 0x1a55 => true,
+ 0x1a57 => true,
+ 0x1a61 => true,
+ 0x1a63...0x1a64 => true,
+ 0x1a6d...0x1a72 => true,
+ 0x1b04 => true,
+ 0x1b35 => true,
+ 0x1b3b => true,
+ 0x1b3d...0x1b41 => true,
+ 0x1b43...0x1b44 => true,
+ 0x1b82 => true,
+ 0x1ba1 => true,
+ 0x1ba6...0x1ba7 => true,
+ 0x1baa => true,
+ 0x1be7 => true,
+ 0x1bea...0x1bec => true,
+ 0x1bee => true,
+ 0x1bf2...0x1bf3 => true,
+ 0x1c24...0x1c2b => true,
+ 0x1c34...0x1c35 => true,
+ 0x1ce1 => true,
+ 0x1cf7 => true,
+ 0x302e...0x302f => true,
+ 0xa823...0xa824 => true,
+ 0xa827 => true,
+ 0xa880...0xa881 => true,
+ 0xa8b4...0xa8c3 => true,
+ 0xa952...0xa953 => true,
+ 0xa983 => true,
+ 0xa9b4...0xa9b5 => true,
+ 0xa9ba...0xa9bb => true,
+ 0xa9be...0xa9c0 => true,
+ 0xaa2f...0xaa30 => true,
+ 0xaa33...0xaa34 => true,
+ 0xaa4d => true,
+ 0xaa7b => true,
+ 0xaa7d => true,
+ 0xaaeb => true,
+ 0xaaee...0xaaef => true,
+ 0xaaf5 => true,
+ 0xabe3...0xabe4 => true,
+ 0xabe6...0xabe7 => true,
+ 0xabe9...0xabea => true,
+ 0xabec => true,
+ 0x11000 => true,
+ 0x11002 => true,
+ 0x11082 => true,
+ 0x110b0...0x110b2 => true,
+ 0x110b7...0x110b8 => true,
+ 0x1112c => true,
+ 0x11145...0x11146 => true,
+ 0x11182 => true,
+ 0x111b3...0x111b5 => true,
+ 0x111bf...0x111c0 => true,
+ 0x111ce => true,
+ 0x1122c...0x1122e => true,
+ 0x11232...0x11233 => true,
+ 0x11235 => true,
+ 0x112e0...0x112e2 => true,
+ 0x11302...0x11303 => true,
+ 0x1133e...0x1133f => true,
+ 0x11341...0x11344 => true,
+ 0x11347...0x11348 => true,
+ 0x1134b...0x1134d => true,
+ 0x11357 => true,
+ 0x11362...0x11363 => true,
+ 0x11435...0x11437 => true,
+ 0x11440...0x11441 => true,
+ 0x11445 => true,
+ 0x114b0...0x114b2 => true,
+ 0x114b9 => true,
+ 0x114bb...0x114be => true,
+ 0x114c1 => true,
+ 0x115af...0x115b1 => true,
+ 0x115b8...0x115bb => true,
+ 0x115be => true,
+ 0x11630...0x11632 => true,
+ 0x1163b...0x1163c => true,
+ 0x1163e => true,
+ 0x116ac => true,
+ 0x116ae...0x116af => true,
+ 0x116b6 => true,
+ 0x11720...0x11721 => true,
+ 0x11726 => true,
+ 0x1182c...0x1182e => true,
+ 0x11838 => true,
+ 0x11930...0x11935 => true,
+ 0x11937...0x11938 => true,
+ 0x1193d => true,
+ 0x11940 => true,
+ 0x11942 => true,
+ 0x119d1...0x119d3 => true,
+ 0x119dc...0x119df => true,
+ 0x119e4 => true,
+ 0x11a39 => true,
+ 0x11a57...0x11a58 => true,
+ 0x11a97 => true,
+ 0x11c2f => true,
+ 0x11c3e => true,
+ 0x11ca9 => true,
+ 0x11cb1 => true,
+ 0x11cb4 => true,
+ 0x11d8a...0x11d8e => true,
+ 0x11d93...0x11d94 => true,
+ 0x11d96 => true,
+ 0x11ef5...0x11ef6 => true,
+ 0x11f03 => true,
+ 0x11f34...0x11f35 => true,
+ 0x11f3e...0x11f3f => true,
+ 0x11f41 => true,
+ 0x16f51...0x16f87 => true,
+ 0x16ff0...0x16ff1 => true,
+ 0x1d165...0x1d166 => true,
+ 0x1d16d...0x1d172 => true,
+ else => false,
+ };
+}
+
+pub fn isDecimalNumber(cp: u21) bool {
+ if (cp < 0x30 or cp > 0x1fbf9) return false;
+
+ return switch (cp) {
+ 0x30...0x39 => true,
+ 0x660...0x669 => true,
+ 0x6f0...0x6f9 => true,
+ 0x7c0...0x7c9 => true,
+ 0x966...0x96f => true,
+ 0x9e6...0x9ef => true,
+ 0xa66...0xa6f => true,
+ 0xae6...0xaef => true,
+ 0xb66...0xb6f => true,
+ 0xbe6...0xbef => true,
+ 0xc66...0xc6f => true,
+ 0xce6...0xcef => true,
+ 0xd66...0xd6f => true,
+ 0xde6...0xdef => true,
+ 0xe50...0xe59 => true,
+ 0xed0...0xed9 => true,
+ 0xf20...0xf29 => true,
+ 0x1040...0x1049 => true,
+ 0x1090...0x1099 => true,
+ 0x17e0...0x17e9 => true,
+ 0x1810...0x1819 => true,
+ 0x1946...0x194f => true,
+ 0x19d0...0x19d9 => true,
+ 0x1a80...0x1a89 => true,
+ 0x1a90...0x1a99 => true,
+ 0x1b50...0x1b59 => true,
+ 0x1bb0...0x1bb9 => true,
+ 0x1c40...0x1c49 => true,
+ 0x1c50...0x1c59 => true,
+ 0xa620...0xa629 => true,
+ 0xa8d0...0xa8d9 => true,
+ 0xa900...0xa909 => true,
+ 0xa9d0...0xa9d9 => true,
+ 0xa9f0...0xa9f9 => true,
+ 0xaa50...0xaa59 => true,
+ 0xabf0...0xabf9 => true,
+ 0xff10...0xff19 => true,
+ 0x104a0...0x104a9 => true,
+ 0x10d30...0x10d39 => true,
+ 0x11066...0x1106f => true,
+ 0x110f0...0x110f9 => true,
+ 0x11136...0x1113f => true,
+ 0x111d0...0x111d9 => true,
+ 0x112f0...0x112f9 => true,
+ 0x11450...0x11459 => true,
+ 0x114d0...0x114d9 => true,
+ 0x11650...0x11659 => true,
+ 0x116c0...0x116c9 => true,
+ 0x11730...0x11739 => true,
+ 0x118e0...0x118e9 => true,
+ 0x11950...0x11959 => true,
+ 0x11c50...0x11c59 => true,
+ 0x11d50...0x11d59 => true,
+ 0x11da0...0x11da9 => true,
+ 0x11f50...0x11f59 => true,
+ 0x16a60...0x16a69 => true,
+ 0x16ac0...0x16ac9 => true,
+ 0x16b50...0x16b59 => true,
+ 0x1d7ce...0x1d7ff => true,
+ 0x1e140...0x1e149 => true,
+ 0x1e2f0...0x1e2f9 => true,
+ 0x1e4f0...0x1e4f9 => true,
+ 0x1e950...0x1e959 => true,
+ 0x1fbf0...0x1fbf9 => true,
+ else => false,
+ };
+}
+
+pub fn isLetterNumber(cp: u21) bool {
+ if (cp < 0x16ee or cp > 0x1246e) return false;
+
+ return switch (cp) {
+ 0x16ee...0x16f0 => true,
+ 0x2160...0x2182 => true,
+ 0x2185...0x2188 => true,
+ 0x3007 => true,
+ 0x3021...0x3029 => true,
+ 0x3038...0x303a => true,
+ 0xa6e6...0xa6ef => true,
+ 0x10140...0x10174 => true,
+ 0x10341 => true,
+ 0x1034a => true,
+ 0x103d1...0x103d5 => true,
+ 0x12400...0x1246e => true,
+ else => false,
+ };
+}
+
+pub fn isOtherNumber(cp: u21) bool {
+ if (cp < 0xb2 or cp > 0x1f10c) return false;
+
+ return switch (cp) {
+ 0xb2...0xb3 => true,
+ 0xb9 => true,
+ 0xbc...0xbe => true,
+ 0x9f4...0x9f9 => true,
+ 0xb72...0xb77 => true,
+ 0xbf0...0xbf2 => true,
+ 0xc78...0xc7e => true,
+ 0xd58...0xd5e => true,
+ 0xd70...0xd78 => true,
+ 0xf2a...0xf33 => true,
+ 0x1369...0x137c => true,
+ 0x17f0...0x17f9 => true,
+ 0x19da => true,
+ 0x2070 => true,
+ 0x2074...0x2079 => true,
+ 0x2080...0x2089 => true,
+ 0x2150...0x215f => true,
+ 0x2189 => true,
+ 0x2460...0x249b => true,
+ 0x24ea...0x24ff => true,
+ 0x2776...0x2793 => true,
+ 0x2cfd => true,
+ 0x3192...0x3195 => true,
+ 0x3220...0x3229 => true,
+ 0x3248...0x324f => true,
+ 0x3251...0x325f => true,
+ 0x3280...0x3289 => true,
+ 0x32b1...0x32bf => true,
+ 0xa830...0xa835 => true,
+ 0x10107...0x10133 => true,
+ 0x10175...0x10178 => true,
+ 0x1018a...0x1018b => true,
+ 0x102e1...0x102fb => true,
+ 0x10320...0x10323 => true,
+ 0x10858...0x1085f => true,
+ 0x10879...0x1087f => true,
+ 0x108a7...0x108af => true,
+ 0x108fb...0x108ff => true,
+ 0x10916...0x1091b => true,
+ 0x109bc...0x109bd => true,
+ 0x109c0...0x109cf => true,
+ 0x109d2...0x109ff => true,
+ 0x10a40...0x10a48 => true,
+ 0x10a7d...0x10a7e => true,
+ 0x10a9d...0x10a9f => true,
+ 0x10aeb...0x10aef => true,
+ 0x10b58...0x10b5f => true,
+ 0x10b78...0x10b7f => true,
+ 0x10ba9...0x10baf => true,
+ 0x10cfa...0x10cff => true,
+ 0x10e60...0x10e7e => true,
+ 0x10f1d...0x10f26 => true,
+ 0x10f51...0x10f54 => true,
+ 0x10fc5...0x10fcb => true,
+ 0x11052...0x11065 => true,
+ 0x111e1...0x111f4 => true,
+ 0x1173a...0x1173b => true,
+ 0x118ea...0x118f2 => true,
+ 0x11c5a...0x11c6c => true,
+ 0x11fc0...0x11fd4 => true,
+ 0x16b5b...0x16b61 => true,
+ 0x16e80...0x16e96 => true,
+ 0x1d2c0...0x1d2d3 => true,
+ 0x1d2e0...0x1d2f3 => true,
+ 0x1d360...0x1d378 => true,
+ 0x1e8c7...0x1e8cf => true,
+ 0x1ec71...0x1ecab => true,
+ 0x1ecad...0x1ecaf => true,
+ 0x1ecb1...0x1ecb4 => true,
+ 0x1ed01...0x1ed2d => true,
+ 0x1ed2f...0x1ed3d => true,
+ 0x1f100...0x1f10c => true,
+ else => false,
+ };
+}
+
+pub fn isSpaceSeparator(cp: u21) bool {
+ if (cp < 0x20 or cp > 0x3000) return false;
+
+ return switch (cp) {
+ 0x20 => true,
+ 0xa0 => true,
+ 0x1680 => true,
+ 0x2000...0x200a => true,
+ 0x202f => true,
+ 0x205f => true,
+ 0x3000 => true,
+ else => false,
+ };
+}
+
+pub fn isLineSeparator(cp: u21) bool {
+ return cp == 0x2028;
+}
+
+pub fn isParagraphSeparator(cp: u21) bool {
+ return cp == 0x2029;
+}
+
+pub fn isControl(cp: u21) bool {
+ if (cp > 0x9f) return false;
+
+ return switch (cp) {
+ 0x0...0x1f => true,
+ 0x7f...0x9f => true,
+ else => false,
+ };
+}
+
+pub fn isFormat(cp: u21) bool {
+ if (cp < 0xad or cp > 0xe007f) return false;
+
+ return switch (cp) {
+ 0xad => true,
+ 0x600...0x605 => true,
+ 0x61c => true,
+ 0x6dd => true,
+ 0x70f => true,
+ 0x890...0x891 => true,
+ 0x8e2 => true,
+ 0x180e => true,
+ 0x200b...0x200f => true,
+ 0x202a...0x202e => true,
+ 0x2060...0x2064 => true,
+ 0x2066...0x206f => true,
+ 0xfeff => true,
+ 0xfff9...0xfffb => true,
+ 0x110bd => true,
+ 0x110cd => true,
+ 0x13430...0x1343f => true,
+ 0x1bca0...0x1bca3 => true,
+ 0x1d173...0x1d17a => true,
+ 0xe0001 => true,
+ 0xe0020...0xe007f => true,
+ else => false,
+ };
+}
+
+pub fn isPrivateUse(cp: u21) bool {
+ if (cp < 0xe000 or cp > 0x10fffd) return false;
+
+ return switch (cp) {
+ 0xe000...0xf8ff => true,
+ 0xf0000...0xffffd => true,
+ 0x100000...0x10fffd => true,
+ else => false,
+ };
+}
+
+pub fn isSurrogate(cp: u21) bool {
+ if (cp < 0xd800 or cp > 0xdfff) return false;
+
+ return switch (cp) {
+ 0xd800...0xdfff => true,
+ else => false,
+ };
+}
+
+pub fn isDashPunctuation(cp: u21) bool {
+ if (cp < 0x2d or cp > 0x10ead) return false;
+
+ return switch (cp) {
+ 0x2d => true,
+ 0x58a => true,
+ 0x5be => true,
+ 0x1400 => true,
+ 0x1806 => true,
+ 0x2010...0x2015 => true,
+ 0x2e17 => true,
+ 0x2e1a => true,
+ 0x2e3a...0x2e3b => true,
+ 0x2e40 => true,
+ 0x2e5d => true,
+ 0x301c => true,
+ 0x3030 => true,
+ 0x30a0 => true,
+ 0xfe31...0xfe32 => true,
+ 0xfe58 => true,
+ 0xfe63 => true,
+ 0xff0d => true,
+ 0x10ead => true,
+ else => false,
+ };
+}
+
+pub fn isOpenPunctuation(cp: u21) bool {
+ if (cp < 0x28 or cp > 0xff62) return false;
+
+ return switch (cp) {
+ 0x28 => true,
+ 0x5b => true,
+ 0x7b => true,
+ 0xf3a => true,
+ 0xf3c => true,
+ 0x169b => true,
+ 0x201a => true,
+ 0x201e => true,
+ 0x2045 => true,
+ 0x207d => true,
+ 0x208d => true,
+ 0x2308 => true,
+ 0x230a => true,
+ 0x2329 => true,
+ 0x2768 => true,
+ 0x276a => true,
+ 0x276c => true,
+ 0x276e => true,
+ 0x2770 => true,
+ 0x2772 => true,
+ 0x2774 => true,
+ 0x27c5 => true,
+ 0x27e6 => true,
+ 0x27e8 => true,
+ 0x27ea => true,
+ 0x27ec => true,
+ 0x27ee => true,
+ 0x2983 => true,
+ 0x2985 => true,
+ 0x2987 => true,
+ 0x2989 => true,
+ 0x298b => true,
+ 0x298d => true,
+ 0x298f => true,
+ 0x2991 => true,
+ 0x2993 => true,
+ 0x2995 => true,
+ 0x2997 => true,
+ 0x29d8 => true,
+ 0x29da => true,
+ 0x29fc => true,
+ 0x2e22 => true,
+ 0x2e24 => true,
+ 0x2e26 => true,
+ 0x2e28 => true,
+ 0x2e42 => true,
+ 0x2e55 => true,
+ 0x2e57 => true,
+ 0x2e59 => true,
+ 0x2e5b => true,
+ 0x3008 => true,
+ 0x300a => true,
+ 0x300c => true,
+ 0x300e => true,
+ 0x3010 => true,
+ 0x3014 => true,
+ 0x3016 => true,
+ 0x3018 => true,
+ 0x301a => true,
+ 0x301d => true,
+ 0xfd3f => true,
+ 0xfe17 => true,
+ 0xfe35 => true,
+ 0xfe37 => true,
+ 0xfe39 => true,
+ 0xfe3b => true,
+ 0xfe3d => true,
+ 0xfe3f => true,
+ 0xfe41 => true,
+ 0xfe43 => true,
+ 0xfe47 => true,
+ 0xfe59 => true,
+ 0xfe5b => true,
+ 0xfe5d => true,
+ 0xff08 => true,
+ 0xff3b => true,
+ 0xff5b => true,
+ 0xff5f => true,
+ 0xff62 => true,
+ else => false,
+ };
+}
+
+pub fn isClosePunctuation(cp: u21) bool {
+ if (cp < 0x29 or cp > 0xff63) return false;
+
+ return switch (cp) {
+ 0x29 => true,
+ 0x5d => true,
+ 0x7d => true,
+ 0xf3b => true,
+ 0xf3d => true,
+ 0x169c => true,
+ 0x2046 => true,
+ 0x207e => true,
+ 0x208e => true,
+ 0x2309 => true,
+ 0x230b => true,
+ 0x232a => true,
+ 0x2769 => true,
+ 0x276b => true,
+ 0x276d => true,
+ 0x276f => true,
+ 0x2771 => true,
+ 0x2773 => true,
+ 0x2775 => true,
+ 0x27c6 => true,
+ 0x27e7 => true,
+ 0x27e9 => true,
+ 0x27eb => true,
+ 0x27ed => true,
+ 0x27ef => true,
+ 0x2984 => true,
+ 0x2986 => true,
+ 0x2988 => true,
+ 0x298a => true,
+ 0x298c => true,
+ 0x298e => true,
+ 0x2990 => true,
+ 0x2992 => true,
+ 0x2994 => true,
+ 0x2996 => true,
+ 0x2998 => true,
+ 0x29d9 => true,
+ 0x29db => true,
+ 0x29fd => true,
+ 0x2e23 => true,
+ 0x2e25 => true,
+ 0x2e27 => true,
+ 0x2e29 => true,
+ 0x2e56 => true,
+ 0x2e58 => true,
+ 0x2e5a => true,
+ 0x2e5c => true,
+ 0x3009 => true,
+ 0x300b => true,
+ 0x300d => true,
+ 0x300f => true,
+ 0x3011 => true,
+ 0x3015 => true,
+ 0x3017 => true,
+ 0x3019 => true,
+ 0x301b => true,
+ 0x301e...0x301f => true,
+ 0xfd3e => true,
+ 0xfe18 => true,
+ 0xfe36 => true,
+ 0xfe38 => true,
+ 0xfe3a => true,
+ 0xfe3c => true,
+ 0xfe3e => true,
+ 0xfe40 => true,
+ 0xfe42 => true,
+ 0xfe44 => true,
+ 0xfe48 => true,
+ 0xfe5a => true,
+ 0xfe5c => true,
+ 0xfe5e => true,
+ 0xff09 => true,
+ 0xff3d => true,
+ 0xff5d => true,
+ 0xff60 => true,
+ 0xff63 => true,
+ else => false,
+ };
+}
+
+pub fn isConnectorPunctuation(cp: u21) bool {
+ if (cp < 0x5f or cp > 0xff3f) return false;
+
+ return switch (cp) {
+ 0x5f => true,
+ 0x203f...0x2040 => true,
+ 0x2054 => true,
+ 0xfe33...0xfe34 => true,
+ 0xfe4d...0xfe4f => true,
+ 0xff3f => true,
+ else => false,
+ };
+}
+
+pub fn isOtherPunctuation(cp: u21) bool {
+ if (cp < 0x21 or cp > 0x1e95f) return false;
+
+ return switch (cp) {
+ 0x21...0x23 => true,
+ 0x25...0x27 => true,
+ 0x2a => true,
+ 0x2c => true,
+ 0x2e...0x2f => true,
+ 0x3a...0x3b => true,
+ 0x3f...0x40 => true,
+ 0x5c => true,
+ 0xa1 => true,
+ 0xa7 => true,
+ 0xb6...0xb7 => true,
+ 0xbf => true,
+ 0x37e => true,
+ 0x387 => true,
+ 0x55a...0x55f => true,
+ 0x589 => true,
+ 0x5c0 => true,
+ 0x5c3 => true,
+ 0x5c6 => true,
+ 0x5f3...0x5f4 => true,
+ 0x609...0x60a => true,
+ 0x60c...0x60d => true,
+ 0x61b => true,
+ 0x61d...0x61f => true,
+ 0x66a...0x66d => true,
+ 0x6d4 => true,
+ 0x700...0x70d => true,
+ 0x7f7...0x7f9 => true,
+ 0x830...0x83e => true,
+ 0x85e => true,
+ 0x964...0x965 => true,
+ 0x970 => true,
+ 0x9fd => true,
+ 0xa76 => true,
+ 0xaf0 => true,
+ 0xc77 => true,
+ 0xc84 => true,
+ 0xdf4 => true,
+ 0xe4f => true,
+ 0xe5a...0xe5b => true,
+ 0xf04...0xf12 => true,
+ 0xf14 => true,
+ 0xf85 => true,
+ 0xfd0...0xfd4 => true,
+ 0xfd9...0xfda => true,
+ 0x104a...0x104f => true,
+ 0x10fb => true,
+ 0x1360...0x1368 => true,
+ 0x166e => true,
+ 0x16eb...0x16ed => true,
+ 0x1735...0x1736 => true,
+ 0x17d4...0x17d6 => true,
+ 0x17d8...0x17da => true,
+ 0x1800...0x1805 => true,
+ 0x1807...0x180a => true,
+ 0x1944...0x1945 => true,
+ 0x1a1e...0x1a1f => true,
+ 0x1aa0...0x1aa6 => true,
+ 0x1aa8...0x1aad => true,
+ 0x1b5a...0x1b60 => true,
+ 0x1b7d...0x1b7e => true,
+ 0x1bfc...0x1bff => true,
+ 0x1c3b...0x1c3f => true,
+ 0x1c7e...0x1c7f => true,
+ 0x1cc0...0x1cc7 => true,
+ 0x1cd3 => true,
+ 0x2016...0x2017 => true,
+ 0x2020...0x2027 => true,
+ 0x2030...0x2038 => true,
+ 0x203b...0x203e => true,
+ 0x2041...0x2043 => true,
+ 0x2047...0x2051 => true,
+ 0x2053 => true,
+ 0x2055...0x205e => true,
+ 0x2cf9...0x2cfc => true,
+ 0x2cfe...0x2cff => true,
+ 0x2d70 => true,
+ 0x2e00...0x2e01 => true,
+ 0x2e06...0x2e08 => true,
+ 0x2e0b => true,
+ 0x2e0e...0x2e16 => true,
+ 0x2e18...0x2e19 => true,
+ 0x2e1b => true,
+ 0x2e1e...0x2e1f => true,
+ 0x2e2a...0x2e2e => true,
+ 0x2e30...0x2e39 => true,
+ 0x2e3c...0x2e3f => true,
+ 0x2e41 => true,
+ 0x2e43...0x2e4f => true,
+ 0x2e52...0x2e54 => true,
+ 0x3001...0x3003 => true,
+ 0x303d => true,
+ 0x30fb => true,
+ 0xa4fe...0xa4ff => true,
+ 0xa60d...0xa60f => true,
+ 0xa673 => true,
+ 0xa67e => true,
+ 0xa6f2...0xa6f7 => true,
+ 0xa874...0xa877 => true,
+ 0xa8ce...0xa8cf => true,
+ 0xa8f8...0xa8fa => true,
+ 0xa8fc => true,
+ 0xa92e...0xa92f => true,
+ 0xa95f => true,
+ 0xa9c1...0xa9cd => true,
+ 0xa9de...0xa9df => true,
+ 0xaa5c...0xaa5f => true,
+ 0xaade...0xaadf => true,
+ 0xaaf0...0xaaf1 => true,
+ 0xabeb => true,
+ 0xfe10...0xfe16 => true,
+ 0xfe19 => true,
+ 0xfe30 => true,
+ 0xfe45...0xfe46 => true,
+ 0xfe49...0xfe4c => true,
+ 0xfe50...0xfe52 => true,
+ 0xfe54...0xfe57 => true,
+ 0xfe5f...0xfe61 => true,
+ 0xfe68 => true,
+ 0xfe6a...0xfe6b => true,
+ 0xff01...0xff03 => true,
+ 0xff05...0xff07 => true,
+ 0xff0a => true,
+ 0xff0c => true,
+ 0xff0e...0xff0f => true,
+ 0xff1a...0xff1b => true,
+ 0xff1f...0xff20 => true,
+ 0xff3c => true,
+ 0xff61 => true,
+ 0xff64...0xff65 => true,
+ 0x10100...0x10102 => true,
+ 0x1039f => true,
+ 0x103d0 => true,
+ 0x1056f => true,
+ 0x10857 => true,
+ 0x1091f => true,
+ 0x1093f => true,
+ 0x10a50...0x10a58 => true,
+ 0x10a7f => true,
+ 0x10af0...0x10af6 => true,
+ 0x10b39...0x10b3f => true,
+ 0x10b99...0x10b9c => true,
+ 0x10f55...0x10f59 => true,
+ 0x10f86...0x10f89 => true,
+ 0x11047...0x1104d => true,
+ 0x110bb...0x110bc => true,
+ 0x110be...0x110c1 => true,
+ 0x11140...0x11143 => true,
+ 0x11174...0x11175 => true,
+ 0x111c5...0x111c8 => true,
+ 0x111cd => true,
+ 0x111db => true,
+ 0x111dd...0x111df => true,
+ 0x11238...0x1123d => true,
+ 0x112a9 => true,
+ 0x1144b...0x1144f => true,
+ 0x1145a...0x1145b => true,
+ 0x1145d => true,
+ 0x114c6 => true,
+ 0x115c1...0x115d7 => true,
+ 0x11641...0x11643 => true,
+ 0x11660...0x1166c => true,
+ 0x116b9 => true,
+ 0x1173c...0x1173e => true,
+ 0x1183b => true,
+ 0x11944...0x11946 => true,
+ 0x119e2 => true,
+ 0x11a3f...0x11a46 => true,
+ 0x11a9a...0x11a9c => true,
+ 0x11a9e...0x11aa2 => true,
+ 0x11b00...0x11b09 => true,
+ 0x11c41...0x11c45 => true,
+ 0x11c70...0x11c71 => true,
+ 0x11ef7...0x11ef8 => true,
+ 0x11f43...0x11f4f => true,
+ 0x11fff => true,
+ 0x12470...0x12474 => true,
+ 0x12ff1...0x12ff2 => true,
+ 0x16a6e...0x16a6f => true,
+ 0x16af5 => true,
+ 0x16b37...0x16b3b => true,
+ 0x16b44 => true,
+ 0x16e97...0x16e9a => true,
+ 0x16fe2 => true,
+ 0x1bc9f => true,
+ 0x1da87...0x1da8b => true,
+ 0x1e95e...0x1e95f => true,
+ else => false,
+ };
+}
+
+pub fn isMathSymbol(cp: u21) bool {
+ if (cp < 0x2b or cp > 0x1eef1) return false;
+
+ return switch (cp) {
+ 0x2b => true,
+ 0x3c...0x3e => true,
+ 0x7c => true,
+ 0x7e => true,
+ 0xac => true,
+ 0xb1 => true,
+ 0xd7 => true,
+ 0xf7 => true,
+ 0x3f6 => true,
+ 0x606...0x608 => true,
+ 0x2044 => true,
+ 0x2052 => true,
+ 0x207a...0x207c => true,
+ 0x208a...0x208c => true,
+ 0x2118 => true,
+ 0x2140...0x2144 => true,
+ 0x214b => true,
+ 0x2190...0x2194 => true,
+ 0x219a...0x219b => true,
+ 0x21a0 => true,
+ 0x21a3 => true,
+ 0x21a6 => true,
+ 0x21ae => true,
+ 0x21ce...0x21cf => true,
+ 0x21d2 => true,
+ 0x21d4 => true,
+ 0x21f4...0x22ff => true,
+ 0x2320...0x2321 => true,
+ 0x237c => true,
+ 0x239b...0x23b3 => true,
+ 0x23dc...0x23e1 => true,
+ 0x25b7 => true,
+ 0x25c1 => true,
+ 0x25f8...0x25ff => true,
+ 0x266f => true,
+ 0x27c0...0x27c4 => true,
+ 0x27c7...0x27e5 => true,
+ 0x27f0...0x27ff => true,
+ 0x2900...0x2982 => true,
+ 0x2999...0x29d7 => true,
+ 0x29dc...0x29fb => true,
+ 0x29fe...0x2aff => true,
+ 0x2b30...0x2b44 => true,
+ 0x2b47...0x2b4c => true,
+ 0xfb29 => true,
+ 0xfe62 => true,
+ 0xfe64...0xfe66 => true,
+ 0xff0b => true,
+ 0xff1c...0xff1e => true,
+ 0xff5c => true,
+ 0xff5e => true,
+ 0xffe2 => true,
+ 0xffe9...0xffec => true,
+ 0x1d6c1 => true,
+ 0x1d6db => true,
+ 0x1d6fb => true,
+ 0x1d715 => true,
+ 0x1d735 => true,
+ 0x1d74f => true,
+ 0x1d76f => true,
+ 0x1d789 => true,
+ 0x1d7a9 => true,
+ 0x1d7c3 => true,
+ 0x1eef0...0x1eef1 => true,
+ else => false,
+ };
+}
+
+pub fn isCurrencySymbol(cp: u21) bool {
+ if (cp < 0x24 or cp > 0x1ecb0) return false;
+
+ return switch (cp) {
+ 0x24 => true,
+ 0xa2...0xa5 => true,
+ 0x58f => true,
+ 0x60b => true,
+ 0x7fe...0x7ff => true,
+ 0x9f2...0x9f3 => true,
+ 0x9fb => true,
+ 0xaf1 => true,
+ 0xbf9 => true,
+ 0xe3f => true,
+ 0x17db => true,
+ 0x20a0...0x20c0 => true,
+ 0xa838 => true,
+ 0xfdfc => true,
+ 0xfe69 => true,
+ 0xff04 => true,
+ 0xffe0...0xffe1 => true,
+ 0xffe5...0xffe6 => true,
+ 0x11fdd...0x11fe0 => true,
+ 0x1e2ff => true,
+ 0x1ecb0 => true,
+ else => false,
+ };
+}
+
+pub fn isModifierSymbol(cp: u21) bool {
+ if (cp < 0x5e or cp > 0x1f3ff) return false;
+
+ return switch (cp) {
+ 0x5e => true,
+ 0x60 => true,
+ 0xa8 => true,
+ 0xaf => true,
+ 0xb4 => true,
+ 0xb8 => true,
+ 0x2c2...0x2c5 => true,
+ 0x2d2...0x2df => true,
+ 0x2e5...0x2eb => true,
+ 0x2ed => true,
+ 0x2ef...0x2ff => true,
+ 0x375 => true,
+ 0x384...0x385 => true,
+ 0x888 => true,
+ 0x1fbd => true,
+ 0x1fbf...0x1fc1 => true,
+ 0x1fcd...0x1fcf => true,
+ 0x1fdd...0x1fdf => true,
+ 0x1fed...0x1fef => true,
+ 0x1ffd...0x1ffe => true,
+ 0x309b...0x309c => true,
+ 0xa700...0xa716 => true,
+ 0xa720...0xa721 => true,
+ 0xa789...0xa78a => true,
+ 0xab5b => true,
+ 0xab6a...0xab6b => true,
+ 0xfbb2...0xfbc2 => true,
+ 0xff3e => true,
+ 0xff40 => true,
+ 0xffe3 => true,
+ 0x1f3fb...0x1f3ff => true,
+ else => false,
+ };
+}
+
+pub fn isOtherSymbol(cp: u21) bool {
+ if (cp < 0xa6 or cp > 0x1fbca) return false;
+
+ return switch (cp) {
+ 0xa6 => true,
+ 0xa9 => true,
+ 0xae => true,
+ 0xb0 => true,
+ 0x482 => true,
+ 0x58d...0x58e => true,
+ 0x60e...0x60f => true,
+ 0x6de => true,
+ 0x6e9 => true,
+ 0x6fd...0x6fe => true,
+ 0x7f6 => true,
+ 0x9fa => true,
+ 0xb70 => true,
+ 0xbf3...0xbf8 => true,
+ 0xbfa => true,
+ 0xc7f => true,
+ 0xd4f => true,
+ 0xd79 => true,
+ 0xf01...0xf03 => true,
+ 0xf13 => true,
+ 0xf15...0xf17 => true,
+ 0xf1a...0xf1f => true,
+ 0xf34 => true,
+ 0xf36 => true,
+ 0xf38 => true,
+ 0xfbe...0xfc5 => true,
+ 0xfc7...0xfcc => true,
+ 0xfce...0xfcf => true,
+ 0xfd5...0xfd8 => true,
+ 0x109e...0x109f => true,
+ 0x1390...0x1399 => true,
+ 0x166d => true,
+ 0x1940 => true,
+ 0x19de...0x19ff => true,
+ 0x1b61...0x1b6a => true,
+ 0x1b74...0x1b7c => true,
+ 0x2100...0x2101 => true,
+ 0x2103...0x2106 => true,
+ 0x2108...0x2109 => true,
+ 0x2114 => true,
+ 0x2116...0x2117 => true,
+ 0x211e...0x2123 => true,
+ 0x2125 => true,
+ 0x2127 => true,
+ 0x2129 => true,
+ 0x212e => true,
+ 0x213a...0x213b => true,
+ 0x214a => true,
+ 0x214c...0x214d => true,
+ 0x214f => true,
+ 0x218a...0x218b => true,
+ 0x2195...0x2199 => true,
+ 0x219c...0x219f => true,
+ 0x21a1...0x21a2 => true,
+ 0x21a4...0x21a5 => true,
+ 0x21a7...0x21ad => true,
+ 0x21af...0x21cd => true,
+ 0x21d0...0x21d1 => true,
+ 0x21d3 => true,
+ 0x21d5...0x21f3 => true,
+ 0x2300...0x2307 => true,
+ 0x230c...0x231f => true,
+ 0x2322...0x2328 => true,
+ 0x232b...0x237b => true,
+ 0x237d...0x239a => true,
+ 0x23b4...0x23db => true,
+ 0x23e2...0x2426 => true,
+ 0x2440...0x244a => true,
+ 0x249c...0x24e9 => true,
+ 0x2500...0x25b6 => true,
+ 0x25b8...0x25c0 => true,
+ 0x25c2...0x25f7 => true,
+ 0x2600...0x266e => true,
+ 0x2670...0x2767 => true,
+ 0x2794...0x27bf => true,
+ 0x2800...0x28ff => true,
+ 0x2b00...0x2b2f => true,
+ 0x2b45...0x2b46 => true,
+ 0x2b4d...0x2b73 => true,
+ 0x2b76...0x2b95 => true,
+ 0x2b97...0x2bff => true,
+ 0x2ce5...0x2cea => true,
+ 0x2e50...0x2e51 => true,
+ 0x2e80...0x2e99 => true,
+ 0x2e9b...0x2ef3 => true,
+ 0x2f00...0x2fd5 => true,
+ 0x2ff0...0x2ffb => true,
+ 0x3004 => true,
+ 0x3012...0x3013 => true,
+ 0x3020 => true,
+ 0x3036...0x3037 => true,
+ 0x303e...0x303f => true,
+ 0x3190...0x3191 => true,
+ 0x3196...0x319f => true,
+ 0x31c0...0x31e3 => true,
+ 0x3200...0x321e => true,
+ 0x322a...0x3247 => true,
+ 0x3250 => true,
+ 0x3260...0x327f => true,
+ 0x328a...0x32b0 => true,
+ 0x32c0...0x33ff => true,
+ 0x4dc0...0x4dff => true,
+ 0xa490...0xa4c6 => true,
+ 0xa828...0xa82b => true,
+ 0xa836...0xa837 => true,
+ 0xa839 => true,
+ 0xaa77...0xaa79 => true,
+ 0xfd40...0xfd4f => true,
+ 0xfdcf => true,
+ 0xfdfd...0xfdff => true,
+ 0xffe4 => true,
+ 0xffe8 => true,
+ 0xffed...0xffee => true,
+ 0xfffc...0xfffd => true,
+ 0x10137...0x1013f => true,
+ 0x10179...0x10189 => true,
+ 0x1018c...0x1018e => true,
+ 0x10190...0x1019c => true,
+ 0x101a0 => true,
+ 0x101d0...0x101fc => true,
+ 0x10877...0x10878 => true,
+ 0x10ac8 => true,
+ 0x1173f => true,
+ 0x11fd5...0x11fdc => true,
+ 0x11fe1...0x11ff1 => true,
+ 0x16b3c...0x16b3f => true,
+ 0x16b45 => true,
+ 0x1bc9c => true,
+ 0x1cf50...0x1cfc3 => true,
+ 0x1d000...0x1d0f5 => true,
+ 0x1d100...0x1d126 => true,
+ 0x1d129...0x1d164 => true,
+ 0x1d16a...0x1d16c => true,
+ 0x1d183...0x1d184 => true,
+ 0x1d18c...0x1d1a9 => true,
+ 0x1d1ae...0x1d1ea => true,
+ 0x1d200...0x1d241 => true,
+ 0x1d245 => true,
+ 0x1d300...0x1d356 => true,
+ 0x1d800...0x1d9ff => true,
+ 0x1da37...0x1da3a => true,
+ 0x1da6d...0x1da74 => true,
+ 0x1da76...0x1da83 => true,
+ 0x1da85...0x1da86 => true,
+ 0x1e14f => true,
+ 0x1ecac => true,
+ 0x1ed2e => true,
+ 0x1f000...0x1f02b => true,
+ 0x1f030...0x1f093 => true,
+ 0x1f0a0...0x1f0ae => true,
+ 0x1f0b1...0x1f0bf => true,
+ 0x1f0c1...0x1f0cf => true,
+ 0x1f0d1...0x1f0f5 => true,
+ 0x1f10d...0x1f1ad => true,
+ 0x1f1e6...0x1f202 => true,
+ 0x1f210...0x1f23b => true,
+ 0x1f240...0x1f248 => true,
+ 0x1f250...0x1f251 => true,
+ 0x1f260...0x1f265 => true,
+ 0x1f300...0x1f3fa => true,
+ 0x1f400...0x1f6d7 => true,
+ 0x1f6dc...0x1f6ec => true,
+ 0x1f6f0...0x1f6fc => true,
+ 0x1f700...0x1f776 => true,
+ 0x1f77b...0x1f7d9 => true,
+ 0x1f7e0...0x1f7eb => true,
+ 0x1f7f0 => true,
+ 0x1f800...0x1f80b => true,
+ 0x1f810...0x1f847 => true,
+ 0x1f850...0x1f859 => true,
+ 0x1f860...0x1f887 => true,
+ 0x1f890...0x1f8ad => true,
+ 0x1f8b0...0x1f8b1 => true,
+ 0x1f900...0x1fa53 => true,
+ 0x1fa60...0x1fa6d => true,
+ 0x1fa70...0x1fa7c => true,
+ 0x1fa80...0x1fa88 => true,
+ 0x1fa90...0x1fabd => true,
+ 0x1fabf...0x1fac5 => true,
+ 0x1face...0x1fadb => true,
+ 0x1fae0...0x1fae8 => true,
+ 0x1faf0...0x1faf8 => true,
+ 0x1fb00...0x1fb92 => true,
+ 0x1fb94...0x1fbca => true,
+ else => false,
+ };
+}
+
+pub fn isInitialPunctuation(cp: u21) bool {
+ if (cp < 0xab or cp > 0x2e20) return false;
+
+ return switch (cp) {
+ 0xab => true,
+ 0x2018 => true,
+ 0x201b...0x201c => true,
+ 0x201f => true,
+ 0x2039 => true,
+ 0x2e02 => true,
+ 0x2e04 => true,
+ 0x2e09 => true,
+ 0x2e0c => true,
+ 0x2e1c => true,
+ 0x2e20 => true,
+ else => false,
+ };
+}
+
+pub fn isFinalPunctuation(cp: u21) bool {
+ if (cp < 0xbb or cp > 0x2e21) return false;
+
+ return switch (cp) {
+ 0xbb => true,
+ 0x2019 => true,
+ 0x201d => true,
+ 0x203a => true,
+ 0x2e03 => true,
+ 0x2e05 => true,
+ 0x2e0a => true,
+ 0x2e0d => true,
+ 0x2e1d => true,
+ 0x2e21 => true,
+ else => false,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/derived_normalization_props.zig.html b/docs/src/ziglyph/autogen/derived_normalization_props.zig.html
new file mode 100644
index 0000000..9936757
--- /dev/null
+++ b/docs/src/ziglyph/autogen/derived_normalization_props.zig.html
@@ -0,0 +1,8605 @@
+
+
+
+
+
autogen/derived_normalization_props.zig - source view
+
+
+
+
+
+
+
+
+
+pub fn isFcx(cp: u21) bool {
+ return switch (cp) {
+ 0x340...0x341 => true,
+ 0x343...0x344 => true,
+ 0x374 => true,
+ 0x37E => true,
+ 0x387 => true,
+ 0x958...0x95F => true,
+ 0x9DC...0x9DD => true,
+ 0x9DF => true,
+ 0xA33 => true,
+ 0xA36 => true,
+ 0xA59...0xA5B => true,
+ 0xA5E => true,
+ 0xB5C...0xB5D => true,
+ 0xF43 => true,
+ 0xF4D => true,
+ 0xF52 => true,
+ 0xF57 => true,
+ 0xF5C => true,
+ 0xF69 => true,
+ 0xF73 => true,
+ 0xF75...0xF76 => true,
+ 0xF78 => true,
+ 0xF81 => true,
+ 0xF93 => true,
+ 0xF9D => true,
+ 0xFA2 => true,
+ 0xFA7 => true,
+ 0xFAC => true,
+ 0xFB9 => true,
+ 0x1F71 => true,
+ 0x1F73 => true,
+ 0x1F75 => true,
+ 0x1F77 => true,
+ 0x1F79 => true,
+ 0x1F7B => true,
+ 0x1F7D => true,
+ 0x1FBB => true,
+ 0x1FBE => true,
+ 0x1FC9 => true,
+ 0x1FCB => true,
+ 0x1FD3 => true,
+ 0x1FDB => true,
+ 0x1FE3 => true,
+ 0x1FEB => true,
+ 0x1FEE...0x1FEF => true,
+ 0x1FF9 => true,
+ 0x1FFB => true,
+ 0x1FFD => true,
+ 0x2000...0x2001 => true,
+ 0x2126 => true,
+ 0x212A...0x212B => true,
+ 0x2329 => true,
+ 0x232A => true,
+ 0x2ADC => true,
+ 0xF900...0xFA0D => true,
+ 0xFA10 => true,
+ 0xFA12 => true,
+ 0xFA15...0xFA1E => true,
+ 0xFA20 => true,
+ 0xFA22 => true,
+ 0xFA25...0xFA26 => true,
+ 0xFA2A...0xFA6D => true,
+ 0xFA70...0xFAD9 => true,
+ 0xFB1D => true,
+ 0xFB1F => true,
+ 0xFB2A...0xFB36 => true,
+ 0xFB38...0xFB3C => true,
+ 0xFB3E => true,
+ 0xFB40...0xFB41 => true,
+ 0xFB43...0xFB44 => true,
+ 0xFB46...0xFB4E => true,
+ 0x1D15E...0x1D164 => true,
+ 0x1D1BB...0x1D1C0 => true,
+ 0x2F800...0x2FA1D => true,
+ else => false,
+ };
+}
+
+
+pub fn isNfd(cp: u21) bool {
+ return switch (cp) {
+ 0xC0...0xC5 => false,
+ 0xC7...0xCF => false,
+ 0xD1...0xD6 => false,
+ 0xD9...0xDD => false,
+ 0xE0...0xE5 => false,
+ 0xE7...0xEF => false,
+ 0xF1...0xF6 => false,
+ 0xF9...0xFD => false,
+ 0xFF...0x10F => false,
+ 0x112...0x125 => false,
+ 0x128...0x130 => false,
+ 0x134...0x137 => false,
+ 0x139...0x13E => false,
+ 0x143...0x148 => false,
+ 0x14C...0x151 => false,
+ 0x154...0x165 => false,
+ 0x168...0x17E => false,
+ 0x1A0...0x1A1 => false,
+ 0x1AF...0x1B0 => false,
+ 0x1CD...0x1DC => false,
+ 0x1DE...0x1E3 => false,
+ 0x1E6...0x1F0 => false,
+ 0x1F4...0x1F5 => false,
+ 0x1F8...0x21B => false,
+ 0x21E...0x21F => false,
+ 0x226...0x233 => false,
+ 0x340...0x341 => false,
+ 0x343...0x344 => false,
+ 0x374 => false,
+ 0x37E => false,
+ 0x385 => false,
+ 0x386 => false,
+ 0x387 => false,
+ 0x388...0x38A => false,
+ 0x38C => false,
+ 0x38E...0x390 => false,
+ 0x3AA...0x3B0 => false,
+ 0x3CA...0x3CE => false,
+ 0x3D3...0x3D4 => false,
+ 0x400...0x401 => false,
+ 0x403 => false,
+ 0x407 => false,
+ 0x40C...0x40E => false,
+ 0x419 => false,
+ 0x439 => false,
+ 0x450...0x451 => false,
+ 0x453 => false,
+ 0x457 => false,
+ 0x45C...0x45E => false,
+ 0x476...0x477 => false,
+ 0x4C1...0x4C2 => false,
+ 0x4D0...0x4D3 => false,
+ 0x4D6...0x4D7 => false,
+ 0x4DA...0x4DF => false,
+ 0x4E2...0x4E7 => false,
+ 0x4EA...0x4F5 => false,
+ 0x4F8...0x4F9 => false,
+ 0x622...0x626 => false,
+ 0x6C0 => false,
+ 0x6C2 => false,
+ 0x6D3 => false,
+ 0x929 => false,
+ 0x931 => false,
+ 0x934 => false,
+ 0x958...0x95F => false,
+ 0x9CB...0x9CC => false,
+ 0x9DC...0x9DD => false,
+ 0x9DF => false,
+ 0xA33 => false,
+ 0xA36 => false,
+ 0xA59...0xA5B => false,
+ 0xA5E => false,
+ 0xB48 => false,
+ 0xB4B...0xB4C => false,
+ 0xB5C...0xB5D => false,
+ 0xB94 => false,
+ 0xBCA...0xBCC => false,
+ 0xC48 => false,
+ 0xCC0 => false,
+ 0xCC7...0xCC8 => false,
+ 0xCCA...0xCCB => false,
+ 0xD4A...0xD4C => false,
+ 0xDDA => false,
+ 0xDDC...0xDDE => false,
+ 0xF43 => false,
+ 0xF4D => false,
+ 0xF52 => false,
+ 0xF57 => false,
+ 0xF5C => false,
+ 0xF69 => false,
+ 0xF73 => false,
+ 0xF75...0xF76 => false,
+ 0xF78 => false,
+ 0xF81 => false,
+ 0xF93 => false,
+ 0xF9D => false,
+ 0xFA2 => false,
+ 0xFA7 => false,
+ 0xFAC => false,
+ 0xFB9 => false,
+ 0x1026 => false,
+ 0x1B06 => false,
+ 0x1B08 => false,
+ 0x1B0A => false,
+ 0x1B0C => false,
+ 0x1B0E => false,
+ 0x1B12 => false,
+ 0x1B3B => false,
+ 0x1B3D => false,
+ 0x1B40...0x1B41 => false,
+ 0x1B43 => false,
+ 0x1E00...0x1E99 => false,
+ 0x1E9B => false,
+ 0x1EA0...0x1EF9 => false,
+ 0x1F00...0x1F15 => false,
+ 0x1F18...0x1F1D => false,
+ 0x1F20...0x1F45 => false,
+ 0x1F48...0x1F4D => false,
+ 0x1F50...0x1F57 => false,
+ 0x1F59 => false,
+ 0x1F5B => false,
+ 0x1F5D => false,
+ 0x1F5F...0x1F7D => false,
+ 0x1F80...0x1FB4 => false,
+ 0x1FB6...0x1FBC => false,
+ 0x1FBE => false,
+ 0x1FC1 => false,
+ 0x1FC2...0x1FC4 => false,
+ 0x1FC6...0x1FCC => false,
+ 0x1FCD...0x1FCF => false,
+ 0x1FD0...0x1FD3 => false,
+ 0x1FD6...0x1FDB => false,
+ 0x1FDD...0x1FDF => false,
+ 0x1FE0...0x1FEC => false,
+ 0x1FED...0x1FEF => false,
+ 0x1FF2...0x1FF4 => false,
+ 0x1FF6...0x1FFC => false,
+ 0x1FFD => false,
+ 0x2000...0x2001 => false,
+ 0x2126 => false,
+ 0x212A...0x212B => false,
+ 0x219A...0x219B => false,
+ 0x21AE => false,
+ 0x21CD => false,
+ 0x21CE...0x21CF => false,
+ 0x2204 => false,
+ 0x2209 => false,
+ 0x220C => false,
+ 0x2224 => false,
+ 0x2226 => false,
+ 0x2241 => false,
+ 0x2244 => false,
+ 0x2247 => false,
+ 0x2249 => false,
+ 0x2260 => false,
+ 0x2262 => false,
+ 0x226D...0x2271 => false,
+ 0x2274...0x2275 => false,
+ 0x2278...0x2279 => false,
+ 0x2280...0x2281 => false,
+ 0x2284...0x2285 => false,
+ 0x2288...0x2289 => false,
+ 0x22AC...0x22AF => false,
+ 0x22E0...0x22E3 => false,
+ 0x22EA...0x22ED => false,
+ 0x2329 => false,
+ 0x232A => false,
+ 0x2ADC => false,
+ 0x304C => false,
+ 0x304E => false,
+ 0x3050 => false,
+ 0x3052 => false,
+ 0x3054 => false,
+ 0x3056 => false,
+ 0x3058 => false,
+ 0x305A => false,
+ 0x305C => false,
+ 0x305E => false,
+ 0x3060 => false,
+ 0x3062 => false,
+ 0x3065 => false,
+ 0x3067 => false,
+ 0x3069 => false,
+ 0x3070...0x3071 => false,
+ 0x3073...0x3074 => false,
+ 0x3076...0x3077 => false,
+ 0x3079...0x307A => false,
+ 0x307C...0x307D => false,
+ 0x3094 => false,
+ 0x309E => false,
+ 0x30AC => false,
+ 0x30AE => false,
+ 0x30B0 => false,
+ 0x30B2 => false,
+ 0x30B4 => false,
+ 0x30B6 => false,
+ 0x30B8 => false,
+ 0x30BA => false,
+ 0x30BC => false,
+ 0x30BE => false,
+ 0x30C0 => false,
+ 0x30C2 => false,
+ 0x30C5 => false,
+ 0x30C7 => false,
+ 0x30C9 => false,
+ 0x30D0...0x30D1 => false,
+ 0x30D3...0x30D4 => false,
+ 0x30D6...0x30D7 => false,
+ 0x30D9...0x30DA => false,
+ 0x30DC...0x30DD => false,
+ 0x30F4 => false,
+ 0x30F7...0x30FA => false,
+ 0x30FE => false,
+ 0xAC00...0xD7A3 => false,
+ 0xF900...0xFA0D => false,
+ 0xFA10 => false,
+ 0xFA12 => false,
+ 0xFA15...0xFA1E => false,
+ 0xFA20 => false,
+ 0xFA22 => false,
+ 0xFA25...0xFA26 => false,
+ 0xFA2A...0xFA6D => false,
+ 0xFA70...0xFAD9 => false,
+ 0xFB1D => false,
+ 0xFB1F => false,
+ 0xFB2A...0xFB36 => false,
+ 0xFB38...0xFB3C => false,
+ 0xFB3E => false,
+ 0xFB40...0xFB41 => false,
+ 0xFB43...0xFB44 => false,
+ 0xFB46...0xFB4E => false,
+ 0x1109A => false,
+ 0x1109C => false,
+ 0x110AB => false,
+ 0x1112E...0x1112F => false,
+ 0x1134B...0x1134C => false,
+ 0x114BB...0x114BC => false,
+ 0x114BE => false,
+ 0x115BA...0x115BB => false,
+ 0x11938 => false,
+ 0x1D15E...0x1D164 => false,
+ 0x1D1BB...0x1D1C0 => false,
+ 0x2F800...0x2FA1D => false,
+ else => true,
+ };
+}
+
+
+pub fn isNfc(cp: u21) bool {
+ return switch (cp) {
+ 0x340...0x341 => false,
+ 0x343...0x344 => false,
+ 0x374 => false,
+ 0x37E => false,
+ 0x387 => false,
+ 0x958...0x95F => false,
+ 0x9DC...0x9DD => false,
+ 0x9DF => false,
+ 0xA33 => false,
+ 0xA36 => false,
+ 0xA59...0xA5B => false,
+ 0xA5E => false,
+ 0xB5C...0xB5D => false,
+ 0xF43 => false,
+ 0xF4D => false,
+ 0xF52 => false,
+ 0xF57 => false,
+ 0xF5C => false,
+ 0xF69 => false,
+ 0xF73 => false,
+ 0xF75...0xF76 => false,
+ 0xF78 => false,
+ 0xF81 => false,
+ 0xF93 => false,
+ 0xF9D => false,
+ 0xFA2 => false,
+ 0xFA7 => false,
+ 0xFAC => false,
+ 0xFB9 => false,
+ 0x1F71 => false,
+ 0x1F73 => false,
+ 0x1F75 => false,
+ 0x1F77 => false,
+ 0x1F79 => false,
+ 0x1F7B => false,
+ 0x1F7D => false,
+ 0x1FBB => false,
+ 0x1FBE => false,
+ 0x1FC9 => false,
+ 0x1FCB => false,
+ 0x1FD3 => false,
+ 0x1FDB => false,
+ 0x1FE3 => false,
+ 0x1FEB => false,
+ 0x1FEE...0x1FEF => false,
+ 0x1FF9 => false,
+ 0x1FFB => false,
+ 0x1FFD => false,
+ 0x2000...0x2001 => false,
+ 0x2126 => false,
+ 0x212A...0x212B => false,
+ 0x2329 => false,
+ 0x232A => false,
+ 0x2ADC => false,
+ 0xF900...0xFA0D => false,
+ 0xFA10 => false,
+ 0xFA12 => false,
+ 0xFA15...0xFA1E => false,
+ 0xFA20 => false,
+ 0xFA22 => false,
+ 0xFA25...0xFA26 => false,
+ 0xFA2A...0xFA6D => false,
+ 0xFA70...0xFAD9 => false,
+ 0xFB1D => false,
+ 0xFB1F => false,
+ 0xFB2A...0xFB36 => false,
+ 0xFB38...0xFB3C => false,
+ 0xFB3E => false,
+ 0xFB40...0xFB41 => false,
+ 0xFB43...0xFB44 => false,
+ 0xFB46...0xFB4E => false,
+ 0x1D15E...0x1D164 => false,
+ 0x1D1BB...0x1D1C0 => false,
+ 0x2F800...0x2FA1D => false,
+ else => true,
+ };
+}
+
+
+pub fn isNfkd(cp: u21) bool {
+ return switch (cp) {
+ 0xA0 => false,
+ 0xA8 => false,
+ 0xAA => false,
+ 0xAF => false,
+ 0xB2...0xB3 => false,
+ 0xB4 => false,
+ 0xB5 => false,
+ 0xB8 => false,
+ 0xB9 => false,
+ 0xBA => false,
+ 0xBC...0xBE => false,
+ 0xC0...0xC5 => false,
+ 0xC7...0xCF => false,
+ 0xD1...0xD6 => false,
+ 0xD9...0xDD => false,
+ 0xE0...0xE5 => false,
+ 0xE7...0xEF => false,
+ 0xF1...0xF6 => false,
+ 0xF9...0xFD => false,
+ 0xFF...0x10F => false,
+ 0x112...0x125 => false,
+ 0x128...0x130 => false,
+ 0x132...0x137 => false,
+ 0x139...0x140 => false,
+ 0x143...0x149 => false,
+ 0x14C...0x151 => false,
+ 0x154...0x165 => false,
+ 0x168...0x17F => false,
+ 0x1A0...0x1A1 => false,
+ 0x1AF...0x1B0 => false,
+ 0x1C4...0x1DC => false,
+ 0x1DE...0x1E3 => false,
+ 0x1E6...0x1F5 => false,
+ 0x1F8...0x21B => false,
+ 0x21E...0x21F => false,
+ 0x226...0x233 => false,
+ 0x2B0...0x2B8 => false,
+ 0x2D8...0x2DD => false,
+ 0x2E0...0x2E4 => false,
+ 0x340...0x341 => false,
+ 0x343...0x344 => false,
+ 0x374 => false,
+ 0x37A => false,
+ 0x37E => false,
+ 0x384...0x385 => false,
+ 0x386 => false,
+ 0x387 => false,
+ 0x388...0x38A => false,
+ 0x38C => false,
+ 0x38E...0x390 => false,
+ 0x3AA...0x3B0 => false,
+ 0x3CA...0x3CE => false,
+ 0x3D0...0x3D6 => false,
+ 0x3F0...0x3F2 => false,
+ 0x3F4...0x3F5 => false,
+ 0x3F9 => false,
+ 0x400...0x401 => false,
+ 0x403 => false,
+ 0x407 => false,
+ 0x40C...0x40E => false,
+ 0x419 => false,
+ 0x439 => false,
+ 0x450...0x451 => false,
+ 0x453 => false,
+ 0x457 => false,
+ 0x45C...0x45E => false,
+ 0x476...0x477 => false,
+ 0x4C1...0x4C2 => false,
+ 0x4D0...0x4D3 => false,
+ 0x4D6...0x4D7 => false,
+ 0x4DA...0x4DF => false,
+ 0x4E2...0x4E7 => false,
+ 0x4EA...0x4F5 => false,
+ 0x4F8...0x4F9 => false,
+ 0x587 => false,
+ 0x622...0x626 => false,
+ 0x675...0x678 => false,
+ 0x6C0 => false,
+ 0x6C2 => false,
+ 0x6D3 => false,
+ 0x929 => false,
+ 0x931 => false,
+ 0x934 => false,
+ 0x958...0x95F => false,
+ 0x9CB...0x9CC => false,
+ 0x9DC...0x9DD => false,
+ 0x9DF => false,
+ 0xA33 => false,
+ 0xA36 => false,
+ 0xA59...0xA5B => false,
+ 0xA5E => false,
+ 0xB48 => false,
+ 0xB4B...0xB4C => false,
+ 0xB5C...0xB5D => false,
+ 0xB94 => false,
+ 0xBCA...0xBCC => false,
+ 0xC48 => false,
+ 0xCC0 => false,
+ 0xCC7...0xCC8 => false,
+ 0xCCA...0xCCB => false,
+ 0xD4A...0xD4C => false,
+ 0xDDA => false,
+ 0xDDC...0xDDE => false,
+ 0xE33 => false,
+ 0xEB3 => false,
+ 0xEDC...0xEDD => false,
+ 0xF0C => false,
+ 0xF43 => false,
+ 0xF4D => false,
+ 0xF52 => false,
+ 0xF57 => false,
+ 0xF5C => false,
+ 0xF69 => false,
+ 0xF73 => false,
+ 0xF75...0xF79 => false,
+ 0xF81 => false,
+ 0xF93 => false,
+ 0xF9D => false,
+ 0xFA2 => false,
+ 0xFA7 => false,
+ 0xFAC => false,
+ 0xFB9 => false,
+ 0x1026 => false,
+ 0x10FC => false,
+ 0x1B06 => false,
+ 0x1B08 => false,
+ 0x1B0A => false,
+ 0x1B0C => false,
+ 0x1B0E => false,
+ 0x1B12 => false,
+ 0x1B3B => false,
+ 0x1B3D => false,
+ 0x1B40...0x1B41 => false,
+ 0x1B43 => false,
+ 0x1D2C...0x1D2E => false,
+ 0x1D30...0x1D3A => false,
+ 0x1D3C...0x1D4D => false,
+ 0x1D4F...0x1D6A => false,
+ 0x1D78 => false,
+ 0x1D9B...0x1DBF => false,
+ 0x1E00...0x1E9B => false,
+ 0x1EA0...0x1EF9 => false,
+ 0x1F00...0x1F15 => false,
+ 0x1F18...0x1F1D => false,
+ 0x1F20...0x1F45 => false,
+ 0x1F48...0x1F4D => false,
+ 0x1F50...0x1F57 => false,
+ 0x1F59 => false,
+ 0x1F5B => false,
+ 0x1F5D => false,
+ 0x1F5F...0x1F7D => false,
+ 0x1F80...0x1FB4 => false,
+ 0x1FB6...0x1FBC => false,
+ 0x1FBD => false,
+ 0x1FBE => false,
+ 0x1FBF...0x1FC1 => false,
+ 0x1FC2...0x1FC4 => false,
+ 0x1FC6...0x1FCC => false,
+ 0x1FCD...0x1FCF => false,
+ 0x1FD0...0x1FD3 => false,
+ 0x1FD6...0x1FDB => false,
+ 0x1FDD...0x1FDF => false,
+ 0x1FE0...0x1FEC => false,
+ 0x1FED...0x1FEF => false,
+ 0x1FF2...0x1FF4 => false,
+ 0x1FF6...0x1FFC => false,
+ 0x1FFD...0x1FFE => false,
+ 0x2000...0x200A => false,
+ 0x2011 => false,
+ 0x2017 => false,
+ 0x2024...0x2026 => false,
+ 0x202F => false,
+ 0x2033...0x2034 => false,
+ 0x2036...0x2037 => false,
+ 0x203C => false,
+ 0x203E => false,
+ 0x2047...0x2049 => false,
+ 0x2057 => false,
+ 0x205F => false,
+ 0x2070 => false,
+ 0x2071 => false,
+ 0x2074...0x2079 => false,
+ 0x207A...0x207C => false,
+ 0x207D => false,
+ 0x207E => false,
+ 0x207F => false,
+ 0x2080...0x2089 => false,
+ 0x208A...0x208C => false,
+ 0x208D => false,
+ 0x208E => false,
+ 0x2090...0x209C => false,
+ 0x20A8 => false,
+ 0x2100...0x2101 => false,
+ 0x2102 => false,
+ 0x2103 => false,
+ 0x2105...0x2106 => false,
+ 0x2107 => false,
+ 0x2109 => false,
+ 0x210A...0x2113 => false,
+ 0x2115 => false,
+ 0x2116 => false,
+ 0x2119...0x211D => false,
+ 0x2120...0x2122 => false,
+ 0x2124 => false,
+ 0x2126 => false,
+ 0x2128 => false,
+ 0x212A...0x212D => false,
+ 0x212F...0x2131 => false,
+ 0x2133...0x2134 => false,
+ 0x2135...0x2138 => false,
+ 0x2139 => false,
+ 0x213B => false,
+ 0x213C...0x213F => false,
+ 0x2140 => false,
+ 0x2145...0x2149 => false,
+ 0x2150...0x215F => false,
+ 0x2160...0x217F => false,
+ 0x2189 => false,
+ 0x219A...0x219B => false,
+ 0x21AE => false,
+ 0x21CD => false,
+ 0x21CE...0x21CF => false,
+ 0x2204 => false,
+ 0x2209 => false,
+ 0x220C => false,
+ 0x2224 => false,
+ 0x2226 => false,
+ 0x222C...0x222D => false,
+ 0x222F...0x2230 => false,
+ 0x2241 => false,
+ 0x2244 => false,
+ 0x2247 => false,
+ 0x2249 => false,
+ 0x2260 => false,
+ 0x2262 => false,
+ 0x226D...0x2271 => false,
+ 0x2274...0x2275 => false,
+ 0x2278...0x2279 => false,
+ 0x2280...0x2281 => false,
+ 0x2284...0x2285 => false,
+ 0x2288...0x2289 => false,
+ 0x22AC...0x22AF => false,
+ 0x22E0...0x22E3 => false,
+ 0x22EA...0x22ED => false,
+ 0x2329 => false,
+ 0x232A => false,
+ 0x2460...0x249B => false,
+ 0x249C...0x24E9 => false,
+ 0x24EA => false,
+ 0x2A0C => false,
+ 0x2A74...0x2A76 => false,
+ 0x2ADC => false,
+ 0x2C7C...0x2C7D => false,
+ 0x2D6F => false,
+ 0x2E9F => false,
+ 0x2EF3 => false,
+ 0x2F00...0x2FD5 => false,
+ 0x3000 => false,
+ 0x3036 => false,
+ 0x3038...0x303A => false,
+ 0x304C => false,
+ 0x304E => false,
+ 0x3050 => false,
+ 0x3052 => false,
+ 0x3054 => false,
+ 0x3056 => false,
+ 0x3058 => false,
+ 0x305A => false,
+ 0x305C => false,
+ 0x305E => false,
+ 0x3060 => false,
+ 0x3062 => false,
+ 0x3065 => false,
+ 0x3067 => false,
+ 0x3069 => false,
+ 0x3070...0x3071 => false,
+ 0x3073...0x3074 => false,
+ 0x3076...0x3077 => false,
+ 0x3079...0x307A => false,
+ 0x307C...0x307D => false,
+ 0x3094 => false,
+ 0x309B...0x309C => false,
+ 0x309E => false,
+ 0x309F => false,
+ 0x30AC => false,
+ 0x30AE => false,
+ 0x30B0 => false,
+ 0x30B2 => false,
+ 0x30B4 => false,
+ 0x30B6 => false,
+ 0x30B8 => false,
+ 0x30BA => false,
+ 0x30BC => false,
+ 0x30BE => false,
+ 0x30C0 => false,
+ 0x30C2 => false,
+ 0x30C5 => false,
+ 0x30C7 => false,
+ 0x30C9 => false,
+ 0x30D0...0x30D1 => false,
+ 0x30D3...0x30D4 => false,
+ 0x30D6...0x30D7 => false,
+ 0x30D9...0x30DA => false,
+ 0x30DC...0x30DD => false,
+ 0x30F4 => false,
+ 0x30F7...0x30FA => false,
+ 0x30FE => false,
+ 0x30FF => false,
+ 0x3131...0x318E => false,
+ 0x3192...0x3195 => false,
+ 0x3196...0x319F => false,
+ 0x3200...0x321E => false,
+ 0x3220...0x3229 => false,
+ 0x322A...0x3247 => false,
+ 0x3250 => false,
+ 0x3251...0x325F => false,
+ 0x3260...0x327E => false,
+ 0x3280...0x3289 => false,
+ 0x328A...0x32B0 => false,
+ 0x32B1...0x32BF => false,
+ 0x32C0...0x33FF => false,
+ 0xA69C...0xA69D => false,
+ 0xA770 => false,
+ 0xA7F2...0xA7F4 => false,
+ 0xA7F8...0xA7F9 => false,
+ 0xAB5C...0xAB5F => false,
+ 0xAB69 => false,
+ 0xAC00...0xD7A3 => false,
+ 0xF900...0xFA0D => false,
+ 0xFA10 => false,
+ 0xFA12 => false,
+ 0xFA15...0xFA1E => false,
+ 0xFA20 => false,
+ 0xFA22 => false,
+ 0xFA25...0xFA26 => false,
+ 0xFA2A...0xFA6D => false,
+ 0xFA70...0xFAD9 => false,
+ 0xFB00...0xFB06 => false,
+ 0xFB13...0xFB17 => false,
+ 0xFB1D => false,
+ 0xFB1F...0xFB28 => false,
+ 0xFB29 => false,
+ 0xFB2A...0xFB36 => false,
+ 0xFB38...0xFB3C => false,
+ 0xFB3E => false,
+ 0xFB40...0xFB41 => false,
+ 0xFB43...0xFB44 => false,
+ 0xFB46...0xFBB1 => false,
+ 0xFBD3...0xFD3D => false,
+ 0xFD50...0xFD8F => false,
+ 0xFD92...0xFDC7 => false,
+ 0xFDF0...0xFDFB => false,
+ 0xFDFC => false,
+ 0xFE10...0xFE16 => false,
+ 0xFE17 => false,
+ 0xFE18 => false,
+ 0xFE19 => false,
+ 0xFE30 => false,
+ 0xFE31...0xFE32 => false,
+ 0xFE33...0xFE34 => false,
+ 0xFE35 => false,
+ 0xFE36 => false,
+ 0xFE37 => false,
+ 0xFE38 => false,
+ 0xFE39 => false,
+ 0xFE3A => false,
+ 0xFE3B => false,
+ 0xFE3C => false,
+ 0xFE3D => false,
+ 0xFE3E => false,
+ 0xFE3F => false,
+ 0xFE40 => false,
+ 0xFE41 => false,
+ 0xFE42 => false,
+ 0xFE43 => false,
+ 0xFE44 => false,
+ 0xFE47 => false,
+ 0xFE48 => false,
+ 0xFE49...0xFE4C => false,
+ 0xFE4D...0xFE4F => false,
+ 0xFE50...0xFE52 => false,
+ 0xFE54...0xFE57 => false,
+ 0xFE58 => false,
+ 0xFE59 => false,
+ 0xFE5A => false,
+ 0xFE5B => false,
+ 0xFE5C => false,
+ 0xFE5D => false,
+ 0xFE5E => false,
+ 0xFE5F...0xFE61 => false,
+ 0xFE62 => false,
+ 0xFE63 => false,
+ 0xFE64...0xFE66 => false,
+ 0xFE68 => false,
+ 0xFE69 => false,
+ 0xFE6A...0xFE6B => false,
+ 0xFE70...0xFE72 => false,
+ 0xFE74 => false,
+ 0xFE76...0xFEFC => false,
+ 0xFF01...0xFF03 => false,
+ 0xFF04 => false,
+ 0xFF05...0xFF07 => false,
+ 0xFF08 => false,
+ 0xFF09 => false,
+ 0xFF0A => false,
+ 0xFF0B => false,
+ 0xFF0C => false,
+ 0xFF0D => false,
+ 0xFF0E...0xFF0F => false,
+ 0xFF10...0xFF19 => false,
+ 0xFF1A...0xFF1B => false,
+ 0xFF1C...0xFF1E => false,
+ 0xFF1F...0xFF20 => false,
+ 0xFF21...0xFF3A => false,
+ 0xFF3B => false,
+ 0xFF3C => false,
+ 0xFF3D => false,
+ 0xFF3E => false,
+ 0xFF3F => false,
+ 0xFF40 => false,
+ 0xFF41...0xFF5A => false,
+ 0xFF5B => false,
+ 0xFF5C => false,
+ 0xFF5D => false,
+ 0xFF5E => false,
+ 0xFF5F => false,
+ 0xFF60 => false,
+ 0xFF61 => false,
+ 0xFF62 => false,
+ 0xFF63 => false,
+ 0xFF64...0xFF65 => false,
+ 0xFF66...0xFF6F => false,
+ 0xFF70 => false,
+ 0xFF71...0xFF9D => false,
+ 0xFF9E...0xFF9F => false,
+ 0xFFA0...0xFFBE => false,
+ 0xFFC2...0xFFC7 => false,
+ 0xFFCA...0xFFCF => false,
+ 0xFFD2...0xFFD7 => false,
+ 0xFFDA...0xFFDC => false,
+ 0xFFE0...0xFFE1 => false,
+ 0xFFE2 => false,
+ 0xFFE3 => false,
+ 0xFFE4 => false,
+ 0xFFE5...0xFFE6 => false,
+ 0xFFE8 => false,
+ 0xFFE9...0xFFEC => false,
+ 0xFFED...0xFFEE => false,
+ 0x10781...0x10785 => false,
+ 0x10787...0x107B0 => false,
+ 0x107B2...0x107BA => false,
+ 0x1109A => false,
+ 0x1109C => false,
+ 0x110AB => false,
+ 0x1112E...0x1112F => false,
+ 0x1134B...0x1134C => false,
+ 0x114BB...0x114BC => false,
+ 0x114BE => false,
+ 0x115BA...0x115BB => false,
+ 0x11938 => false,
+ 0x1D15E...0x1D164 => false,
+ 0x1D1BB...0x1D1C0 => false,
+ 0x1D400...0x1D454 => false,
+ 0x1D456...0x1D49C => false,
+ 0x1D49E...0x1D49F => false,
+ 0x1D4A2 => false,
+ 0x1D4A5...0x1D4A6 => false,
+ 0x1D4A9...0x1D4AC => false,
+ 0x1D4AE...0x1D4B9 => false,
+ 0x1D4BB => false,
+ 0x1D4BD...0x1D4C3 => false,
+ 0x1D4C5...0x1D505 => false,
+ 0x1D507...0x1D50A => false,
+ 0x1D50D...0x1D514 => false,
+ 0x1D516...0x1D51C => false,
+ 0x1D51E...0x1D539 => false,
+ 0x1D53B...0x1D53E => false,
+ 0x1D540...0x1D544 => false,
+ 0x1D546 => false,
+ 0x1D54A...0x1D550 => false,
+ 0x1D552...0x1D6A5 => false,
+ 0x1D6A8...0x1D6C0 => false,
+ 0x1D6C1 => false,
+ 0x1D6C2...0x1D6DA => false,
+ 0x1D6DB => false,
+ 0x1D6DC...0x1D6FA => false,
+ 0x1D6FB => false,
+ 0x1D6FC...0x1D714 => false,
+ 0x1D715 => false,
+ 0x1D716...0x1D734 => false,
+ 0x1D735 => false,
+ 0x1D736...0x1D74E => false,
+ 0x1D74F => false,
+ 0x1D750...0x1D76E => false,
+ 0x1D76F => false,
+ 0x1D770...0x1D788 => false,
+ 0x1D789 => false,
+ 0x1D78A...0x1D7A8 => false,
+ 0x1D7A9 => false,
+ 0x1D7AA...0x1D7C2 => false,
+ 0x1D7C3 => false,
+ 0x1D7C4...0x1D7CB => false,
+ 0x1D7CE...0x1D7FF => false,
+ 0x1E030...0x1E06D => false,
+ 0x1EE00...0x1EE03 => false,
+ 0x1EE05...0x1EE1F => false,
+ 0x1EE21...0x1EE22 => false,
+ 0x1EE24 => false,
+ 0x1EE27 => false,
+ 0x1EE29...0x1EE32 => false,
+ 0x1EE34...0x1EE37 => false,
+ 0x1EE39 => false,
+ 0x1EE3B => false,
+ 0x1EE42 => false,
+ 0x1EE47 => false,
+ 0x1EE49 => false,
+ 0x1EE4B => false,
+ 0x1EE4D...0x1EE4F => false,
+ 0x1EE51...0x1EE52 => false,
+ 0x1EE54 => false,
+ 0x1EE57 => false,
+ 0x1EE59 => false,
+ 0x1EE5B => false,
+ 0x1EE5D => false,
+ 0x1EE5F => false,
+ 0x1EE61...0x1EE62 => false,
+ 0x1EE64 => false,
+ 0x1EE67...0x1EE6A => false,
+ 0x1EE6C...0x1EE72 => false,
+ 0x1EE74...0x1EE77 => false,
+ 0x1EE79...0x1EE7C => false,
+ 0x1EE7E => false,
+ 0x1EE80...0x1EE89 => false,
+ 0x1EE8B...0x1EE9B => false,
+ 0x1EEA1...0x1EEA3 => false,
+ 0x1EEA5...0x1EEA9 => false,
+ 0x1EEAB...0x1EEBB => false,
+ 0x1F100...0x1F10A => false,
+ 0x1F110...0x1F12E => false,
+ 0x1F130...0x1F14F => false,
+ 0x1F16A...0x1F16C => false,
+ 0x1F190 => false,
+ 0x1F200...0x1F202 => false,
+ 0x1F210...0x1F23B => false,
+ 0x1F240...0x1F248 => false,
+ 0x1F250...0x1F251 => false,
+ 0x1FBF0...0x1FBF9 => false,
+ 0x2F800...0x2FA1D => false,
+ else => true,
+ };
+}
+
+
+pub fn isNFKC(cp: u21) bool {
+ return switch (cp) {
+ 0xA0 => false,
+ 0xA8 => false,
+ 0xAA => false,
+ 0xAF => false,
+ 0xB2...0xB3 => false,
+ 0xB4 => false,
+ 0xB5 => false,
+ 0xB8 => false,
+ 0xB9 => false,
+ 0xBA => false,
+ 0xBC...0xBE => false,
+ 0x132...0x133 => false,
+ 0x13F...0x140 => false,
+ 0x149 => false,
+ 0x17F => false,
+ 0x1C4...0x1CC => false,
+ 0x1F1...0x1F3 => false,
+ 0x2B0...0x2B8 => false,
+ 0x2D8...0x2DD => false,
+ 0x2E0...0x2E4 => false,
+ 0x340...0x341 => false,
+ 0x343...0x344 => false,
+ 0x374 => false,
+ 0x37A => false,
+ 0x37E => false,
+ 0x384...0x385 => false,
+ 0x387 => false,
+ 0x3D0...0x3D6 => false,
+ 0x3F0...0x3F2 => false,
+ 0x3F4...0x3F5 => false,
+ 0x3F9 => false,
+ 0x587 => false,
+ 0x675...0x678 => false,
+ 0x958...0x95F => false,
+ 0x9DC...0x9DD => false,
+ 0x9DF => false,
+ 0xA33 => false,
+ 0xA36 => false,
+ 0xA59...0xA5B => false,
+ 0xA5E => false,
+ 0xB5C...0xB5D => false,
+ 0xE33 => false,
+ 0xEB3 => false,
+ 0xEDC...0xEDD => false,
+ 0xF0C => false,
+ 0xF43 => false,
+ 0xF4D => false,
+ 0xF52 => false,
+ 0xF57 => false,
+ 0xF5C => false,
+ 0xF69 => false,
+ 0xF73 => false,
+ 0xF75...0xF79 => false,
+ 0xF81 => false,
+ 0xF93 => false,
+ 0xF9D => false,
+ 0xFA2 => false,
+ 0xFA7 => false,
+ 0xFAC => false,
+ 0xFB9 => false,
+ 0x10FC => false,
+ 0x1D2C...0x1D2E => false,
+ 0x1D30...0x1D3A => false,
+ 0x1D3C...0x1D4D => false,
+ 0x1D4F...0x1D6A => false,
+ 0x1D78 => false,
+ 0x1D9B...0x1DBF => false,
+ 0x1E9A...0x1E9B => false,
+ 0x1F71 => false,
+ 0x1F73 => false,
+ 0x1F75 => false,
+ 0x1F77 => false,
+ 0x1F79 => false,
+ 0x1F7B => false,
+ 0x1F7D => false,
+ 0x1FBB => false,
+ 0x1FBD => false,
+ 0x1FBE => false,
+ 0x1FBF...0x1FC1 => false,
+ 0x1FC9 => false,
+ 0x1FCB => false,
+ 0x1FCD...0x1FCF => false,
+ 0x1FD3 => false,
+ 0x1FDB => false,
+ 0x1FDD...0x1FDF => false,
+ 0x1FE3 => false,
+ 0x1FEB => false,
+ 0x1FED...0x1FEF => false,
+ 0x1FF9 => false,
+ 0x1FFB => false,
+ 0x1FFD...0x1FFE => false,
+ 0x2000...0x200A => false,
+ 0x2011 => false,
+ 0x2017 => false,
+ 0x2024...0x2026 => false,
+ 0x202F => false,
+ 0x2033...0x2034 => false,
+ 0x2036...0x2037 => false,
+ 0x203C => false,
+ 0x203E => false,
+ 0x2047...0x2049 => false,
+ 0x2057 => false,
+ 0x205F => false,
+ 0x2070 => false,
+ 0x2071 => false,
+ 0x2074...0x2079 => false,
+ 0x207A...0x207C => false,
+ 0x207D => false,
+ 0x207E => false,
+ 0x207F => false,
+ 0x2080...0x2089 => false,
+ 0x208A...0x208C => false,
+ 0x208D => false,
+ 0x208E => false,
+ 0x2090...0x209C => false,
+ 0x20A8 => false,
+ 0x2100...0x2101 => false,
+ 0x2102 => false,
+ 0x2103 => false,
+ 0x2105...0x2106 => false,
+ 0x2107 => false,
+ 0x2109 => false,
+ 0x210A...0x2113 => false,
+ 0x2115 => false,
+ 0x2116 => false,
+ 0x2119...0x211D => false,
+ 0x2120...0x2122 => false,
+ 0x2124 => false,
+ 0x2126 => false,
+ 0x2128 => false,
+ 0x212A...0x212D => false,
+ 0x212F...0x2131 => false,
+ 0x2133...0x2134 => false,
+ 0x2135...0x2138 => false,
+ 0x2139 => false,
+ 0x213B => false,
+ 0x213C...0x213F => false,
+ 0x2140 => false,
+ 0x2145...0x2149 => false,
+ 0x2150...0x215F => false,
+ 0x2160...0x217F => false,
+ 0x2189 => false,
+ 0x222C...0x222D => false,
+ 0x222F...0x2230 => false,
+ 0x2329 => false,
+ 0x232A => false,
+ 0x2460...0x249B => false,
+ 0x249C...0x24E9 => false,
+ 0x24EA => false,
+ 0x2A0C => false,
+ 0x2A74...0x2A76 => false,
+ 0x2ADC => false,
+ 0x2C7C...0x2C7D => false,
+ 0x2D6F => false,
+ 0x2E9F => false,
+ 0x2EF3 => false,
+ 0x2F00...0x2FD5 => false,
+ 0x3000 => false,
+ 0x3036 => false,
+ 0x3038...0x303A => false,
+ 0x309B...0x309C => false,
+ 0x309F => false,
+ 0x30FF => false,
+ 0x3131...0x318E => false,
+ 0x3192...0x3195 => false,
+ 0x3196...0x319F => false,
+ 0x3200...0x321E => false,
+ 0x3220...0x3229 => false,
+ 0x322A...0x3247 => false,
+ 0x3250 => false,
+ 0x3251...0x325F => false,
+ 0x3260...0x327E => false,
+ 0x3280...0x3289 => false,
+ 0x328A...0x32B0 => false,
+ 0x32B1...0x32BF => false,
+ 0x32C0...0x33FF => false,
+ 0xA69C...0xA69D => false,
+ 0xA770 => false,
+ 0xA7F2...0xA7F4 => false,
+ 0xA7F8...0xA7F9 => false,
+ 0xAB5C...0xAB5F => false,
+ 0xAB69 => false,
+ 0xF900...0xFA0D => false,
+ 0xFA10 => false,
+ 0xFA12 => false,
+ 0xFA15...0xFA1E => false,
+ 0xFA20 => false,
+ 0xFA22 => false,
+ 0xFA25...0xFA26 => false,
+ 0xFA2A...0xFA6D => false,
+ 0xFA70...0xFAD9 => false,
+ 0xFB00...0xFB06 => false,
+ 0xFB13...0xFB17 => false,
+ 0xFB1D => false,
+ 0xFB1F...0xFB28 => false,
+ 0xFB29 => false,
+ 0xFB2A...0xFB36 => false,
+ 0xFB38...0xFB3C => false,
+ 0xFB3E => false,
+ 0xFB40...0xFB41 => false,
+ 0xFB43...0xFB44 => false,
+ 0xFB46...0xFBB1 => false,
+ 0xFBD3...0xFD3D => false,
+ 0xFD50...0xFD8F => false,
+ 0xFD92...0xFDC7 => false,
+ 0xFDF0...0xFDFB => false,
+ 0xFDFC => false,
+ 0xFE10...0xFE16 => false,
+ 0xFE17 => false,
+ 0xFE18 => false,
+ 0xFE19 => false,
+ 0xFE30 => false,
+ 0xFE31...0xFE32 => false,
+ 0xFE33...0xFE34 => false,
+ 0xFE35 => false,
+ 0xFE36 => false,
+ 0xFE37 => false,
+ 0xFE38 => false,
+ 0xFE39 => false,
+ 0xFE3A => false,
+ 0xFE3B => false,
+ 0xFE3C => false,
+ 0xFE3D => false,
+ 0xFE3E => false,
+ 0xFE3F => false,
+ 0xFE40 => false,
+ 0xFE41 => false,
+ 0xFE42 => false,
+ 0xFE43 => false,
+ 0xFE44 => false,
+ 0xFE47 => false,
+ 0xFE48 => false,
+ 0xFE49...0xFE4C => false,
+ 0xFE4D...0xFE4F => false,
+ 0xFE50...0xFE52 => false,
+ 0xFE54...0xFE57 => false,
+ 0xFE58 => false,
+ 0xFE59 => false,
+ 0xFE5A => false,
+ 0xFE5B => false,
+ 0xFE5C => false,
+ 0xFE5D => false,
+ 0xFE5E => false,
+ 0xFE5F...0xFE61 => false,
+ 0xFE62 => false,
+ 0xFE63 => false,
+ 0xFE64...0xFE66 => false,
+ 0xFE68 => false,
+ 0xFE69 => false,
+ 0xFE6A...0xFE6B => false,
+ 0xFE70...0xFE72 => false,
+ 0xFE74 => false,
+ 0xFE76...0xFEFC => false,
+ 0xFF01...0xFF03 => false,
+ 0xFF04 => false,
+ 0xFF05...0xFF07 => false,
+ 0xFF08 => false,
+ 0xFF09 => false,
+ 0xFF0A => false,
+ 0xFF0B => false,
+ 0xFF0C => false,
+ 0xFF0D => false,
+ 0xFF0E...0xFF0F => false,
+ 0xFF10...0xFF19 => false,
+ 0xFF1A...0xFF1B => false,
+ 0xFF1C...0xFF1E => false,
+ 0xFF1F...0xFF20 => false,
+ 0xFF21...0xFF3A => false,
+ 0xFF3B => false,
+ 0xFF3C => false,
+ 0xFF3D => false,
+ 0xFF3E => false,
+ 0xFF3F => false,
+ 0xFF40 => false,
+ 0xFF41...0xFF5A => false,
+ 0xFF5B => false,
+ 0xFF5C => false,
+ 0xFF5D => false,
+ 0xFF5E => false,
+ 0xFF5F => false,
+ 0xFF60 => false,
+ 0xFF61 => false,
+ 0xFF62 => false,
+ 0xFF63 => false,
+ 0xFF64...0xFF65 => false,
+ 0xFF66...0xFF6F => false,
+ 0xFF70 => false,
+ 0xFF71...0xFF9D => false,
+ 0xFF9E...0xFF9F => false,
+ 0xFFA0...0xFFBE => false,
+ 0xFFC2...0xFFC7 => false,
+ 0xFFCA...0xFFCF => false,
+ 0xFFD2...0xFFD7 => false,
+ 0xFFDA...0xFFDC => false,
+ 0xFFE0...0xFFE1 => false,
+ 0xFFE2 => false,
+ 0xFFE3 => false,
+ 0xFFE4 => false,
+ 0xFFE5...0xFFE6 => false,
+ 0xFFE8 => false,
+ 0xFFE9...0xFFEC => false,
+ 0xFFED...0xFFEE => false,
+ 0x10781...0x10785 => false,
+ 0x10787...0x107B0 => false,
+ 0x107B2...0x107BA => false,
+ 0x1D15E...0x1D164 => false,
+ 0x1D1BB...0x1D1C0 => false,
+ 0x1D400...0x1D454 => false,
+ 0x1D456...0x1D49C => false,
+ 0x1D49E...0x1D49F => false,
+ 0x1D4A2 => false,
+ 0x1D4A5...0x1D4A6 => false,
+ 0x1D4A9...0x1D4AC => false,
+ 0x1D4AE...0x1D4B9 => false,
+ 0x1D4BB => false,
+ 0x1D4BD...0x1D4C3 => false,
+ 0x1D4C5...0x1D505 => false,
+ 0x1D507...0x1D50A => false,
+ 0x1D50D...0x1D514 => false,
+ 0x1D516...0x1D51C => false,
+ 0x1D51E...0x1D539 => false,
+ 0x1D53B...0x1D53E => false,
+ 0x1D540...0x1D544 => false,
+ 0x1D546 => false,
+ 0x1D54A...0x1D550 => false,
+ 0x1D552...0x1D6A5 => false,
+ 0x1D6A8...0x1D6C0 => false,
+ 0x1D6C1 => false,
+ 0x1D6C2...0x1D6DA => false,
+ 0x1D6DB => false,
+ 0x1D6DC...0x1D6FA => false,
+ 0x1D6FB => false,
+ 0x1D6FC...0x1D714 => false,
+ 0x1D715 => false,
+ 0x1D716...0x1D734 => false,
+ 0x1D735 => false,
+ 0x1D736...0x1D74E => false,
+ 0x1D74F => false,
+ 0x1D750...0x1D76E => false,
+ 0x1D76F => false,
+ 0x1D770...0x1D788 => false,
+ 0x1D789 => false,
+ 0x1D78A...0x1D7A8 => false,
+ 0x1D7A9 => false,
+ 0x1D7AA...0x1D7C2 => false,
+ 0x1D7C3 => false,
+ 0x1D7C4...0x1D7CB => false,
+ 0x1D7CE...0x1D7FF => false,
+ 0x1E030...0x1E06D => false,
+ 0x1EE00...0x1EE03 => false,
+ 0x1EE05...0x1EE1F => false,
+ 0x1EE21...0x1EE22 => false,
+ 0x1EE24 => false,
+ 0x1EE27 => false,
+ 0x1EE29...0x1EE32 => false,
+ 0x1EE34...0x1EE37 => false,
+ 0x1EE39 => false,
+ 0x1EE3B => false,
+ 0x1EE42 => false,
+ 0x1EE47 => false,
+ 0x1EE49 => false,
+ 0x1EE4B => false,
+ 0x1EE4D...0x1EE4F => false,
+ 0x1EE51...0x1EE52 => false,
+ 0x1EE54 => false,
+ 0x1EE57 => false,
+ 0x1EE59 => false,
+ 0x1EE5B => false,
+ 0x1EE5D => false,
+ 0x1EE5F => false,
+ 0x1EE61...0x1EE62 => false,
+ 0x1EE64 => false,
+ 0x1EE67...0x1EE6A => false,
+ 0x1EE6C...0x1EE72 => false,
+ 0x1EE74...0x1EE77 => false,
+ 0x1EE79...0x1EE7C => false,
+ 0x1EE7E => false,
+ 0x1EE80...0x1EE89 => false,
+ 0x1EE8B...0x1EE9B => false,
+ 0x1EEA1...0x1EEA3 => false,
+ 0x1EEA5...0x1EEA9 => false,
+ 0x1EEAB...0x1EEBB => false,
+ 0x1F100...0x1F10A => false,
+ 0x1F110...0x1F12E => false,
+ 0x1F130...0x1F14F => false,
+ 0x1F16A...0x1F16C => false,
+ 0x1F190 => false,
+ 0x1F200...0x1F202 => false,
+ 0x1F210...0x1F23B => false,
+ 0x1F240...0x1F248 => false,
+ 0x1F250...0x1F251 => false,
+ 0x1FBF0...0x1FBF9 => false,
+ 0x2F800...0x2FA1D => false,
+ else => true,
+ };
+}
+
+
+
+
+pub fn toNfkcCaseFold(cp: u21) ?[18]u21 {
+ const slice: ?[]const u21 = switch (cp) {
+ 0x41 => &.{0x61},
+ 0x42 => &.{0x62},
+ 0x43 => &.{0x63},
+ 0x44 => &.{0x64},
+ 0x45 => &.{0x65},
+ 0x46 => &.{0x66},
+ 0x47 => &.{0x67},
+ 0x48 => &.{0x68},
+ 0x49 => &.{0x69},
+ 0x4A => &.{0x6A},
+ 0x4B => &.{0x6B},
+ 0x4C => &.{0x6C},
+ 0x4D => &.{0x6D},
+ 0x4E => &.{0x6E},
+ 0x4F => &.{0x6F},
+ 0x50 => &.{0x70},
+ 0x51 => &.{0x71},
+ 0x52 => &.{0x72},
+ 0x53 => &.{0x73},
+ 0x54 => &.{0x74},
+ 0x55 => &.{0x75},
+ 0x56 => &.{0x76},
+ 0x57 => &.{0x77},
+ 0x58 => &.{0x78},
+ 0x59 => &.{0x79},
+ 0x5A => &.{0x7A},
+ 0xA0 => &.{0x20},
+ 0xA8 => &.{ 0x20, 0x308 },
+ 0xAA => &.{0x61},
+ 0xAD => null,
+ 0xAF => &.{ 0x20, 0x304 },
+ 0xB2 => &.{0x32},
+ 0xB3 => &.{0x33},
+ 0xB4 => &.{ 0x20, 0x301 },
+ 0xB5 => &.{0x3BC},
+ 0xB8 => &.{ 0x20, 0x327 },
+ 0xB9 => &.{0x31},
+ 0xBA => &.{0x6F},
+ 0xBC => &.{ 0x31, 0x2044, 0x34 },
+ 0xBD => &.{ 0x31, 0x2044, 0x32 },
+ 0xBE => &.{ 0x33, 0x2044, 0x34 },
+ 0xC0 => &.{0xE0},
+ 0xC1 => &.{0xE1},
+ 0xC2 => &.{0xE2},
+ 0xC3 => &.{0xE3},
+ 0xC4 => &.{0xE4},
+ 0xC5 => &.{0xE5},
+ 0xC6 => &.{0xE6},
+ 0xC7 => &.{0xE7},
+ 0xC8 => &.{0xE8},
+ 0xC9 => &.{0xE9},
+ 0xCA => &.{0xEA},
+ 0xCB => &.{0xEB},
+ 0xCC => &.{0xEC},
+ 0xCD => &.{0xED},
+ 0xCE => &.{0xEE},
+ 0xCF => &.{0xEF},
+ 0xD0 => &.{0xF0},
+ 0xD1 => &.{0xF1},
+ 0xD2 => &.{0xF2},
+ 0xD3 => &.{0xF3},
+ 0xD4 => &.{0xF4},
+ 0xD5 => &.{0xF5},
+ 0xD6 => &.{0xF6},
+ 0xD8 => &.{0xF8},
+ 0xD9 => &.{0xF9},
+ 0xDA => &.{0xFA},
+ 0xDB => &.{0xFB},
+ 0xDC => &.{0xFC},
+ 0xDD => &.{0xFD},
+ 0xDE => &.{0xFE},
+ 0xDF => &.{ 0x73, 0x73 },
+ 0x100 => &.{0x101},
+ 0x102 => &.{0x103},
+ 0x104 => &.{0x105},
+ 0x106 => &.{0x107},
+ 0x108 => &.{0x109},
+ 0x10A => &.{0x10B},
+ 0x10C => &.{0x10D},
+ 0x10E => &.{0x10F},
+ 0x110 => &.{0x111},
+ 0x112 => &.{0x113},
+ 0x114 => &.{0x115},
+ 0x116 => &.{0x117},
+ 0x118 => &.{0x119},
+ 0x11A => &.{0x11B},
+ 0x11C => &.{0x11D},
+ 0x11E => &.{0x11F},
+ 0x120 => &.{0x121},
+ 0x122 => &.{0x123},
+ 0x124 => &.{0x125},
+ 0x126 => &.{0x127},
+ 0x128 => &.{0x129},
+ 0x12A => &.{0x12B},
+ 0x12C => &.{0x12D},
+ 0x12E => &.{0x12F},
+ 0x130 => &.{ 0x69, 0x307 },
+ 0x132...0x133 => &.{ 0x69, 0x6A },
+ 0x134 => &.{0x135},
+ 0x136 => &.{0x137},
+ 0x139 => &.{0x13A},
+ 0x13B => &.{0x13C},
+ 0x13D => &.{0x13E},
+ 0x13F...0x140 => &.{ 0x6C, 0xB7 },
+ 0x141 => &.{0x142},
+ 0x143 => &.{0x144},
+ 0x145 => &.{0x146},
+ 0x147 => &.{0x148},
+ 0x149 => &.{ 0x2BC, 0x6E },
+ 0x14A => &.{0x14B},
+ 0x14C => &.{0x14D},
+ 0x14E => &.{0x14F},
+ 0x150 => &.{0x151},
+ 0x152 => &.{0x153},
+ 0x154 => &.{0x155},
+ 0x156 => &.{0x157},
+ 0x158 => &.{0x159},
+ 0x15A => &.{0x15B},
+ 0x15C => &.{0x15D},
+ 0x15E => &.{0x15F},
+ 0x160 => &.{0x161},
+ 0x162 => &.{0x163},
+ 0x164 => &.{0x165},
+ 0x166 => &.{0x167},
+ 0x168 => &.{0x169},
+ 0x16A => &.{0x16B},
+ 0x16C => &.{0x16D},
+ 0x16E => &.{0x16F},
+ 0x170 => &.{0x171},
+ 0x172 => &.{0x173},
+ 0x174 => &.{0x175},
+ 0x176 => &.{0x177},
+ 0x178 => &.{0xFF},
+ 0x179 => &.{0x17A},
+ 0x17B => &.{0x17C},
+ 0x17D => &.{0x17E},
+ 0x17F => &.{0x73},
+ 0x181 => &.{0x253},
+ 0x182 => &.{0x183},
+ 0x184 => &.{0x185},
+ 0x186 => &.{0x254},
+ 0x187 => &.{0x188},
+ 0x189 => &.{0x256},
+ 0x18A => &.{0x257},
+ 0x18B => &.{0x18C},
+ 0x18E => &.{0x1DD},
+ 0x18F => &.{0x259},
+ 0x190 => &.{0x25B},
+ 0x191 => &.{0x192},
+ 0x193 => &.{0x260},
+ 0x194 => &.{0x263},
+ 0x196 => &.{0x269},
+ 0x197 => &.{0x268},
+ 0x198 => &.{0x199},
+ 0x19C => &.{0x26F},
+ 0x19D => &.{0x272},
+ 0x19F => &.{0x275},
+ 0x1A0 => &.{0x1A1},
+ 0x1A2 => &.{0x1A3},
+ 0x1A4 => &.{0x1A5},
+ 0x1A6 => &.{0x280},
+ 0x1A7 => &.{0x1A8},
+ 0x1A9 => &.{0x283},
+ 0x1AC => &.{0x1AD},
+ 0x1AE => &.{0x288},
+ 0x1AF => &.{0x1B0},
+ 0x1B1 => &.{0x28A},
+ 0x1B2 => &.{0x28B},
+ 0x1B3 => &.{0x1B4},
+ 0x1B5 => &.{0x1B6},
+ 0x1B7 => &.{0x292},
+ 0x1B8 => &.{0x1B9},
+ 0x1BC => &.{0x1BD},
+ 0x1C4...0x1C6 => &.{ 0x64, 0x17E },
+ 0x1C7...0x1C9 => &.{ 0x6C, 0x6A },
+ 0x1CA...0x1CC => &.{ 0x6E, 0x6A },
+ 0x1CD => &.{0x1CE},
+ 0x1CF => &.{0x1D0},
+ 0x1D1 => &.{0x1D2},
+ 0x1D3 => &.{0x1D4},
+ 0x1D5 => &.{0x1D6},
+ 0x1D7 => &.{0x1D8},
+ 0x1D9 => &.{0x1DA},
+ 0x1DB => &.{0x1DC},
+ 0x1DE => &.{0x1DF},
+ 0x1E0 => &.{0x1E1},
+ 0x1E2 => &.{0x1E3},
+ 0x1E4 => &.{0x1E5},
+ 0x1E6 => &.{0x1E7},
+ 0x1E8 => &.{0x1E9},
+ 0x1EA => &.{0x1EB},
+ 0x1EC => &.{0x1ED},
+ 0x1EE => &.{0x1EF},
+ 0x1F1...0x1F3 => &.{ 0x64, 0x7A },
+ 0x1F4 => &.{0x1F5},
+ 0x1F6 => &.{0x195},
+ 0x1F7 => &.{0x1BF},
+ 0x1F8 => &.{0x1F9},
+ 0x1FA => &.{0x1FB},
+ 0x1FC => &.{0x1FD},
+ 0x1FE => &.{0x1FF},
+ 0x200 => &.{0x201},
+ 0x202 => &.{0x203},
+ 0x204 => &.{0x205},
+ 0x206 => &.{0x207},
+ 0x208 => &.{0x209},
+ 0x20A => &.{0x20B},
+ 0x20C => &.{0x20D},
+ 0x20E => &.{0x20F},
+ 0x210 => &.{0x211},
+ 0x212 => &.{0x213},
+ 0x214 => &.{0x215},
+ 0x216 => &.{0x217},
+ 0x218 => &.{0x219},
+ 0x21A => &.{0x21B},
+ 0x21C => &.{0x21D},
+ 0x21E => &.{0x21F},
+ 0x220 => &.{0x19E},
+ 0x222 => &.{0x223},
+ 0x224 => &.{0x225},
+ 0x226 => &.{0x227},
+ 0x228 => &.{0x229},
+ 0x22A => &.{0x22B},
+ 0x22C => &.{0x22D},
+ 0x22E => &.{0x22F},
+ 0x230 => &.{0x231},
+ 0x232 => &.{0x233},
+ 0x23A => &.{0x2C65},
+ 0x23B => &.{0x23C},
+ 0x23D => &.{0x19A},
+ 0x23E => &.{0x2C66},
+ 0x241 => &.{0x242},
+ 0x243 => &.{0x180},
+ 0x244 => &.{0x289},
+ 0x245 => &.{0x28C},
+ 0x246 => &.{0x247},
+ 0x248 => &.{0x249},
+ 0x24A => &.{0x24B},
+ 0x24C => &.{0x24D},
+ 0x24E => &.{0x24F},
+ 0x2B0 => &.{0x68},
+ 0x2B1 => &.{0x266},
+ 0x2B2 => &.{0x6A},
+ 0x2B3 => &.{0x72},
+ 0x2B4 => &.{0x279},
+ 0x2B5 => &.{0x27B},
+ 0x2B6 => &.{0x281},
+ 0x2B7 => &.{0x77},
+ 0x2B8 => &.{0x79},
+ 0x2D8 => &.{ 0x20, 0x306 },
+ 0x2D9 => &.{ 0x20, 0x307 },
+ 0x2DA => &.{ 0x20, 0x30A },
+ 0x2DB => &.{ 0x20, 0x328 },
+ 0x2DC => &.{ 0x20, 0x303 },
+ 0x2DD => &.{ 0x20, 0x30B },
+ 0x2E0 => &.{0x263},
+ 0x2E1 => &.{0x6C},
+ 0x2E2 => &.{0x73},
+ 0x2E3 => &.{0x78},
+ 0x2E4 => &.{0x295},
+ 0x340 => &.{0x300},
+ 0x341 => &.{0x301},
+ 0x343 => &.{0x313},
+ 0x344 => &.{ 0x308, 0x301 },
+ 0x345 => &.{0x3B9},
+ 0x34F => null,
+ 0x370 => &.{0x371},
+ 0x372 => &.{0x373},
+ 0x374 => &.{0x2B9},
+ 0x376 => &.{0x377},
+ 0x37A => &.{ 0x20, 0x3B9 },
+ 0x37E => &.{0x3B},
+ 0x37F => &.{0x3F3},
+ 0x384 => &.{ 0x20, 0x301 },
+ 0x385 => &.{ 0x20, 0x308, 0x301 },
+ 0x386 => &.{0x3AC},
+ 0x387 => &.{0xB7},
+ 0x388 => &.{0x3AD},
+ 0x389 => &.{0x3AE},
+ 0x38A => &.{0x3AF},
+ 0x38C => &.{0x3CC},
+ 0x38E => &.{0x3CD},
+ 0x38F => &.{0x3CE},
+ 0x391 => &.{0x3B1},
+ 0x392 => &.{0x3B2},
+ 0x393 => &.{0x3B3},
+ 0x394 => &.{0x3B4},
+ 0x395 => &.{0x3B5},
+ 0x396 => &.{0x3B6},
+ 0x397 => &.{0x3B7},
+ 0x398 => &.{0x3B8},
+ 0x399 => &.{0x3B9},
+ 0x39A => &.{0x3BA},
+ 0x39B => &.{0x3BB},
+ 0x39C => &.{0x3BC},
+ 0x39D => &.{0x3BD},
+ 0x39E => &.{0x3BE},
+ 0x39F => &.{0x3BF},
+ 0x3A0 => &.{0x3C0},
+ 0x3A1 => &.{0x3C1},
+ 0x3A3 => &.{0x3C3},
+ 0x3A4 => &.{0x3C4},
+ 0x3A5 => &.{0x3C5},
+ 0x3A6 => &.{0x3C6},
+ 0x3A7 => &.{0x3C7},
+ 0x3A8 => &.{0x3C8},
+ 0x3A9 => &.{0x3C9},
+ 0x3AA => &.{0x3CA},
+ 0x3AB => &.{0x3CB},
+ 0x3C2 => &.{0x3C3},
+ 0x3CF => &.{0x3D7},
+ 0x3D0 => &.{0x3B2},
+ 0x3D1 => &.{0x3B8},
+ 0x3D2 => &.{0x3C5},
+ 0x3D3 => &.{0x3CD},
+ 0x3D4 => &.{0x3CB},
+ 0x3D5 => &.{0x3C6},
+ 0x3D6 => &.{0x3C0},
+ 0x3D8 => &.{0x3D9},
+ 0x3DA => &.{0x3DB},
+ 0x3DC => &.{0x3DD},
+ 0x3DE => &.{0x3DF},
+ 0x3E0 => &.{0x3E1},
+ 0x3E2 => &.{0x3E3},
+ 0x3E4 => &.{0x3E5},
+ 0x3E6 => &.{0x3E7},
+ 0x3E8 => &.{0x3E9},
+ 0x3EA => &.{0x3EB},
+ 0x3EC => &.{0x3ED},
+ 0x3EE => &.{0x3EF},
+ 0x3F0 => &.{0x3BA},
+ 0x3F1 => &.{0x3C1},
+ 0x3F2 => &.{0x3C3},
+ 0x3F4 => &.{0x3B8},
+ 0x3F5 => &.{0x3B5},
+ 0x3F7 => &.{0x3F8},
+ 0x3F9 => &.{0x3C3},
+ 0x3FA => &.{0x3FB},
+ 0x3FD => &.{0x37B},
+ 0x3FE => &.{0x37C},
+ 0x3FF => &.{0x37D},
+ 0x400 => &.{0x450},
+ 0x401 => &.{0x451},
+ 0x402 => &.{0x452},
+ 0x403 => &.{0x453},
+ 0x404 => &.{0x454},
+ 0x405 => &.{0x455},
+ 0x406 => &.{0x456},
+ 0x407 => &.{0x457},
+ 0x408 => &.{0x458},
+ 0x409 => &.{0x459},
+ 0x40A => &.{0x45A},
+ 0x40B => &.{0x45B},
+ 0x40C => &.{0x45C},
+ 0x40D => &.{0x45D},
+ 0x40E => &.{0x45E},
+ 0x40F => &.{0x45F},
+ 0x410 => &.{0x430},
+ 0x411 => &.{0x431},
+ 0x412 => &.{0x432},
+ 0x413 => &.{0x433},
+ 0x414 => &.{0x434},
+ 0x415 => &.{0x435},
+ 0x416 => &.{0x436},
+ 0x417 => &.{0x437},
+ 0x418 => &.{0x438},
+ 0x419 => &.{0x439},
+ 0x41A => &.{0x43A},
+ 0x41B => &.{0x43B},
+ 0x41C => &.{0x43C},
+ 0x41D => &.{0x43D},
+ 0x41E => &.{0x43E},
+ 0x41F => &.{0x43F},
+ 0x420 => &.{0x440},
+ 0x421 => &.{0x441},
+ 0x422 => &.{0x442},
+ 0x423 => &.{0x443},
+ 0x424 => &.{0x444},
+ 0x425 => &.{0x445},
+ 0x426 => &.{0x446},
+ 0x427 => &.{0x447},
+ 0x428 => &.{0x448},
+ 0x429 => &.{0x449},
+ 0x42A => &.{0x44A},
+ 0x42B => &.{0x44B},
+ 0x42C => &.{0x44C},
+ 0x42D => &.{0x44D},
+ 0x42E => &.{0x44E},
+ 0x42F => &.{0x44F},
+ 0x460 => &.{0x461},
+ 0x462 => &.{0x463},
+ 0x464 => &.{0x465},
+ 0x466 => &.{0x467},
+ 0x468 => &.{0x469},
+ 0x46A => &.{0x46B},
+ 0x46C => &.{0x46D},
+ 0x46E => &.{0x46F},
+ 0x470 => &.{0x471},
+ 0x472 => &.{0x473},
+ 0x474 => &.{0x475},
+ 0x476 => &.{0x477},
+ 0x478 => &.{0x479},
+ 0x47A => &.{0x47B},
+ 0x47C => &.{0x47D},
+ 0x47E => &.{0x47F},
+ 0x480 => &.{0x481},
+ 0x48A => &.{0x48B},
+ 0x48C => &.{0x48D},
+ 0x48E => &.{0x48F},
+ 0x490 => &.{0x491},
+ 0x492 => &.{0x493},
+ 0x494 => &.{0x495},
+ 0x496 => &.{0x497},
+ 0x498 => &.{0x499},
+ 0x49A => &.{0x49B},
+ 0x49C => &.{0x49D},
+ 0x49E => &.{0x49F},
+ 0x4A0 => &.{0x4A1},
+ 0x4A2 => &.{0x4A3},
+ 0x4A4 => &.{0x4A5},
+ 0x4A6 => &.{0x4A7},
+ 0x4A8 => &.{0x4A9},
+ 0x4AA => &.{0x4AB},
+ 0x4AC => &.{0x4AD},
+ 0x4AE => &.{0x4AF},
+ 0x4B0 => &.{0x4B1},
+ 0x4B2 => &.{0x4B3},
+ 0x4B4 => &.{0x4B5},
+ 0x4B6 => &.{0x4B7},
+ 0x4B8 => &.{0x4B9},
+ 0x4BA => &.{0x4BB},
+ 0x4BC => &.{0x4BD},
+ 0x4BE => &.{0x4BF},
+ 0x4C0 => &.{0x4CF},
+ 0x4C1 => &.{0x4C2},
+ 0x4C3 => &.{0x4C4},
+ 0x4C5 => &.{0x4C6},
+ 0x4C7 => &.{0x4C8},
+ 0x4C9 => &.{0x4CA},
+ 0x4CB => &.{0x4CC},
+ 0x4CD => &.{0x4CE},
+ 0x4D0 => &.{0x4D1},
+ 0x4D2 => &.{0x4D3},
+ 0x4D4 => &.{0x4D5},
+ 0x4D6 => &.{0x4D7},
+ 0x4D8 => &.{0x4D9},
+ 0x4DA => &.{0x4DB},
+ 0x4DC => &.{0x4DD},
+ 0x4DE => &.{0x4DF},
+ 0x4E0 => &.{0x4E1},
+ 0x4E2 => &.{0x4E3},
+ 0x4E4 => &.{0x4E5},
+ 0x4E6 => &.{0x4E7},
+ 0x4E8 => &.{0x4E9},
+ 0x4EA => &.{0x4EB},
+ 0x4EC => &.{0x4ED},
+ 0x4EE => &.{0x4EF},
+ 0x4F0 => &.{0x4F1},
+ 0x4F2 => &.{0x4F3},
+ 0x4F4 => &.{0x4F5},
+ 0x4F6 => &.{0x4F7},
+ 0x4F8 => &.{0x4F9},
+ 0x4FA => &.{0x4FB},
+ 0x4FC => &.{0x4FD},
+ 0x4FE => &.{0x4FF},
+ 0x500 => &.{0x501},
+ 0x502 => &.{0x503},
+ 0x504 => &.{0x505},
+ 0x506 => &.{0x507},
+ 0x508 => &.{0x509},
+ 0x50A => &.{0x50B},
+ 0x50C => &.{0x50D},
+ 0x50E => &.{0x50F},
+ 0x510 => &.{0x511},
+ 0x512 => &.{0x513},
+ 0x514 => &.{0x515},
+ 0x516 => &.{0x517},
+ 0x518 => &.{0x519},
+ 0x51A => &.{0x51B},
+ 0x51C => &.{0x51D},
+ 0x51E => &.{0x51F},
+ 0x520 => &.{0x521},
+ 0x522 => &.{0x523},
+ 0x524 => &.{0x525},
+ 0x526 => &.{0x527},
+ 0x528 => &.{0x529},
+ 0x52A => &.{0x52B},
+ 0x52C => &.{0x52D},
+ 0x52E => &.{0x52F},
+ 0x531 => &.{0x561},
+ 0x532 => &.{0x562},
+ 0x533 => &.{0x563},
+ 0x534 => &.{0x564},
+ 0x535 => &.{0x565},
+ 0x536 => &.{0x566},
+ 0x537 => &.{0x567},
+ 0x538 => &.{0x568},
+ 0x539 => &.{0x569},
+ 0x53A => &.{0x56A},
+ 0x53B => &.{0x56B},
+ 0x53C => &.{0x56C},
+ 0x53D => &.{0x56D},
+ 0x53E => &.{0x56E},
+ 0x53F => &.{0x56F},
+ 0x540 => &.{0x570},
+ 0x541 => &.{0x571},
+ 0x542 => &.{0x572},
+ 0x543 => &.{0x573},
+ 0x544 => &.{0x574},
+ 0x545 => &.{0x575},
+ 0x546 => &.{0x576},
+ 0x547 => &.{0x577},
+ 0x548 => &.{0x578},
+ 0x549 => &.{0x579},
+ 0x54A => &.{0x57A},
+ 0x54B => &.{0x57B},
+ 0x54C => &.{0x57C},
+ 0x54D => &.{0x57D},
+ 0x54E => &.{0x57E},
+ 0x54F => &.{0x57F},
+ 0x550 => &.{0x580},
+ 0x551 => &.{0x581},
+ 0x552 => &.{0x582},
+ 0x553 => &.{0x583},
+ 0x554 => &.{0x584},
+ 0x555 => &.{0x585},
+ 0x556 => &.{0x586},
+ 0x587 => &.{ 0x565, 0x582 },
+ 0x61C => null,
+ 0x675 => &.{ 0x627, 0x674 },
+ 0x676 => &.{ 0x648, 0x674 },
+ 0x677 => &.{ 0x6C7, 0x674 },
+ 0x678 => &.{ 0x64A, 0x674 },
+ 0x958 => &.{ 0x915, 0x93C },
+ 0x959 => &.{ 0x916, 0x93C },
+ 0x95A => &.{ 0x917, 0x93C },
+ 0x95B => &.{ 0x91C, 0x93C },
+ 0x95C => &.{ 0x921, 0x93C },
+ 0x95D => &.{ 0x922, 0x93C },
+ 0x95E => &.{ 0x92B, 0x93C },
+ 0x95F => &.{ 0x92F, 0x93C },
+ 0x9DC => &.{ 0x9A1, 0x9BC },
+ 0x9DD => &.{ 0x9A2, 0x9BC },
+ 0x9DF => &.{ 0x9AF, 0x9BC },
+ 0xA33 => &.{ 0xA32, 0xA3C },
+ 0xA36 => &.{ 0xA38, 0xA3C },
+ 0xA59 => &.{ 0xA16, 0xA3C },
+ 0xA5A => &.{ 0xA17, 0xA3C },
+ 0xA5B => &.{ 0xA1C, 0xA3C },
+ 0xA5E => &.{ 0xA2B, 0xA3C },
+ 0xB5C => &.{ 0xB21, 0xB3C },
+ 0xB5D => &.{ 0xB22, 0xB3C },
+ 0xE33 => &.{ 0xE4D, 0xE32 },
+ 0xEB3 => &.{ 0xECD, 0xEB2 },
+ 0xEDC => &.{ 0xEAB, 0xE99 },
+ 0xEDD => &.{ 0xEAB, 0xEA1 },
+ 0xF0C => &.{0xF0B},
+ 0xF43 => &.{ 0xF42, 0xFB7 },
+ 0xF4D => &.{ 0xF4C, 0xFB7 },
+ 0xF52 => &.{ 0xF51, 0xFB7 },
+ 0xF57 => &.{ 0xF56, 0xFB7 },
+ 0xF5C => &.{ 0xF5B, 0xFB7 },
+ 0xF69 => &.{ 0xF40, 0xFB5 },
+ 0xF73 => &.{ 0xF71, 0xF72 },
+ 0xF75 => &.{ 0xF71, 0xF74 },
+ 0xF76 => &.{ 0xFB2, 0xF80 },
+ 0xF77 => &.{ 0xFB2, 0xF71, 0xF80 },
+ 0xF78 => &.{ 0xFB3, 0xF80 },
+ 0xF79 => &.{ 0xFB3, 0xF71, 0xF80 },
+ 0xF81 => &.{ 0xF71, 0xF80 },
+ 0xF93 => &.{ 0xF92, 0xFB7 },
+ 0xF9D => &.{ 0xF9C, 0xFB7 },
+ 0xFA2 => &.{ 0xFA1, 0xFB7 },
+ 0xFA7 => &.{ 0xFA6, 0xFB7 },
+ 0xFAC => &.{ 0xFAB, 0xFB7 },
+ 0xFB9 => &.{ 0xF90, 0xFB5 },
+ 0x10A0 => &.{0x2D00},
+ 0x10A1 => &.{0x2D01},
+ 0x10A2 => &.{0x2D02},
+ 0x10A3 => &.{0x2D03},
+ 0x10A4 => &.{0x2D04},
+ 0x10A5 => &.{0x2D05},
+ 0x10A6 => &.{0x2D06},
+ 0x10A7 => &.{0x2D07},
+ 0x10A8 => &.{0x2D08},
+ 0x10A9 => &.{0x2D09},
+ 0x10AA => &.{0x2D0A},
+ 0x10AB => &.{0x2D0B},
+ 0x10AC => &.{0x2D0C},
+ 0x10AD => &.{0x2D0D},
+ 0x10AE => &.{0x2D0E},
+ 0x10AF => &.{0x2D0F},
+ 0x10B0 => &.{0x2D10},
+ 0x10B1 => &.{0x2D11},
+ 0x10B2 => &.{0x2D12},
+ 0x10B3 => &.{0x2D13},
+ 0x10B4 => &.{0x2D14},
+ 0x10B5 => &.{0x2D15},
+ 0x10B6 => &.{0x2D16},
+ 0x10B7 => &.{0x2D17},
+ 0x10B8 => &.{0x2D18},
+ 0x10B9 => &.{0x2D19},
+ 0x10BA => &.{0x2D1A},
+ 0x10BB => &.{0x2D1B},
+ 0x10BC => &.{0x2D1C},
+ 0x10BD => &.{0x2D1D},
+ 0x10BE => &.{0x2D1E},
+ 0x10BF => &.{0x2D1F},
+ 0x10C0 => &.{0x2D20},
+ 0x10C1 => &.{0x2D21},
+ 0x10C2 => &.{0x2D22},
+ 0x10C3 => &.{0x2D23},
+ 0x10C4 => &.{0x2D24},
+ 0x10C5 => &.{0x2D25},
+ 0x10C7 => &.{0x2D27},
+ 0x10CD => &.{0x2D2D},
+ 0x10FC => &.{0x10DC},
+ 0x115F...0x1160 => null,
+ 0x13F8 => &.{0x13F0},
+ 0x13F9 => &.{0x13F1},
+ 0x13FA => &.{0x13F2},
+ 0x13FB => &.{0x13F3},
+ 0x13FC => &.{0x13F4},
+ 0x13FD => &.{0x13F5},
+ 0x17B4...0x17B5 => null,
+ 0x180B...0x180D => null,
+ 0x180E => null,
+ 0x180F => null,
+ 0x1C80 => &.{0x432},
+ 0x1C81 => &.{0x434},
+ 0x1C82 => &.{0x43E},
+ 0x1C83 => &.{0x441},
+ 0x1C84...0x1C85 => &.{0x442},
+ 0x1C86 => &.{0x44A},
+ 0x1C87 => &.{0x463},
+ 0x1C88 => &.{0xA64B},
+ 0x1C90 => &.{0x10D0},
+ 0x1C91 => &.{0x10D1},
+ 0x1C92 => &.{0x10D2},
+ 0x1C93 => &.{0x10D3},
+ 0x1C94 => &.{0x10D4},
+ 0x1C95 => &.{0x10D5},
+ 0x1C96 => &.{0x10D6},
+ 0x1C97 => &.{0x10D7},
+ 0x1C98 => &.{0x10D8},
+ 0x1C99 => &.{0x10D9},
+ 0x1C9A => &.{0x10DA},
+ 0x1C9B => &.{0x10DB},
+ 0x1C9C => &.{0x10DC},
+ 0x1C9D => &.{0x10DD},
+ 0x1C9E => &.{0x10DE},
+ 0x1C9F => &.{0x10DF},
+ 0x1CA0 => &.{0x10E0},
+ 0x1CA1 => &.{0x10E1},
+ 0x1CA2 => &.{0x10E2},
+ 0x1CA3 => &.{0x10E3},
+ 0x1CA4 => &.{0x10E4},
+ 0x1CA5 => &.{0x10E5},
+ 0x1CA6 => &.{0x10E6},
+ 0x1CA7 => &.{0x10E7},
+ 0x1CA8 => &.{0x10E8},
+ 0x1CA9 => &.{0x10E9},
+ 0x1CAA => &.{0x10EA},
+ 0x1CAB => &.{0x10EB},
+ 0x1CAC => &.{0x10EC},
+ 0x1CAD => &.{0x10ED},
+ 0x1CAE => &.{0x10EE},
+ 0x1CAF => &.{0x10EF},
+ 0x1CB0 => &.{0x10F0},
+ 0x1CB1 => &.{0x10F1},
+ 0x1CB2 => &.{0x10F2},
+ 0x1CB3 => &.{0x10F3},
+ 0x1CB4 => &.{0x10F4},
+ 0x1CB5 => &.{0x10F5},
+ 0x1CB6 => &.{0x10F6},
+ 0x1CB7 => &.{0x10F7},
+ 0x1CB8 => &.{0x10F8},
+ 0x1CB9 => &.{0x10F9},
+ 0x1CBA => &.{0x10FA},
+ 0x1CBD => &.{0x10FD},
+ 0x1CBE => &.{0x10FE},
+ 0x1CBF => &.{0x10FF},
+ 0x1D2C => &.{0x61},
+ 0x1D2D => &.{0xE6},
+ 0x1D2E => &.{0x62},
+ 0x1D30 => &.{0x64},
+ 0x1D31 => &.{0x65},
+ 0x1D32 => &.{0x1DD},
+ 0x1D33 => &.{0x67},
+ 0x1D34 => &.{0x68},
+ 0x1D35 => &.{0x69},
+ 0x1D36 => &.{0x6A},
+ 0x1D37 => &.{0x6B},
+ 0x1D38 => &.{0x6C},
+ 0x1D39 => &.{0x6D},
+ 0x1D3A => &.{0x6E},
+ 0x1D3C => &.{0x6F},
+ 0x1D3D => &.{0x223},
+ 0x1D3E => &.{0x70},
+ 0x1D3F => &.{0x72},
+ 0x1D40 => &.{0x74},
+ 0x1D41 => &.{0x75},
+ 0x1D42 => &.{0x77},
+ 0x1D43 => &.{0x61},
+ 0x1D44 => &.{0x250},
+ 0x1D45 => &.{0x251},
+ 0x1D46 => &.{0x1D02},
+ 0x1D47 => &.{0x62},
+ 0x1D48 => &.{0x64},
+ 0x1D49 => &.{0x65},
+ 0x1D4A => &.{0x259},
+ 0x1D4B => &.{0x25B},
+ 0x1D4C => &.{0x25C},
+ 0x1D4D => &.{0x67},
+ 0x1D4F => &.{0x6B},
+ 0x1D50 => &.{0x6D},
+ 0x1D51 => &.{0x14B},
+ 0x1D52 => &.{0x6F},
+ 0x1D53 => &.{0x254},
+ 0x1D54 => &.{0x1D16},
+ 0x1D55 => &.{0x1D17},
+ 0x1D56 => &.{0x70},
+ 0x1D57 => &.{0x74},
+ 0x1D58 => &.{0x75},
+ 0x1D59 => &.{0x1D1D},
+ 0x1D5A => &.{0x26F},
+ 0x1D5B => &.{0x76},
+ 0x1D5C => &.{0x1D25},
+ 0x1D5D => &.{0x3B2},
+ 0x1D5E => &.{0x3B3},
+ 0x1D5F => &.{0x3B4},
+ 0x1D60 => &.{0x3C6},
+ 0x1D61 => &.{0x3C7},
+ 0x1D62 => &.{0x69},
+ 0x1D63 => &.{0x72},
+ 0x1D64 => &.{0x75},
+ 0x1D65 => &.{0x76},
+ 0x1D66 => &.{0x3B2},
+ 0x1D67 => &.{0x3B3},
+ 0x1D68 => &.{0x3C1},
+ 0x1D69 => &.{0x3C6},
+ 0x1D6A => &.{0x3C7},
+ 0x1D78 => &.{0x43D},
+ 0x1D9B => &.{0x252},
+ 0x1D9C => &.{0x63},
+ 0x1D9D => &.{0x255},
+ 0x1D9E => &.{0xF0},
+ 0x1D9F => &.{0x25C},
+ 0x1DA0 => &.{0x66},
+ 0x1DA1 => &.{0x25F},
+ 0x1DA2 => &.{0x261},
+ 0x1DA3 => &.{0x265},
+ 0x1DA4 => &.{0x268},
+ 0x1DA5 => &.{0x269},
+ 0x1DA6 => &.{0x26A},
+ 0x1DA7 => &.{0x1D7B},
+ 0x1DA8 => &.{0x29D},
+ 0x1DA9 => &.{0x26D},
+ 0x1DAA => &.{0x1D85},
+ 0x1DAB => &.{0x29F},
+ 0x1DAC => &.{0x271},
+ 0x1DAD => &.{0x270},
+ 0x1DAE => &.{0x272},
+ 0x1DAF => &.{0x273},
+ 0x1DB0 => &.{0x274},
+ 0x1DB1 => &.{0x275},
+ 0x1DB2 => &.{0x278},
+ 0x1DB3 => &.{0x282},
+ 0x1DB4 => &.{0x283},
+ 0x1DB5 => &.{0x1AB},
+ 0x1DB6 => &.{0x289},
+ 0x1DB7 => &.{0x28A},
+ 0x1DB8 => &.{0x1D1C},
+ 0x1DB9 => &.{0x28B},
+ 0x1DBA => &.{0x28C},
+ 0x1DBB => &.{0x7A},
+ 0x1DBC => &.{0x290},
+ 0x1DBD => &.{0x291},
+ 0x1DBE => &.{0x292},
+ 0x1DBF => &.{0x3B8},
+ 0x1E00 => &.{0x1E01},
+ 0x1E02 => &.{0x1E03},
+ 0x1E04 => &.{0x1E05},
+ 0x1E06 => &.{0x1E07},
+ 0x1E08 => &.{0x1E09},
+ 0x1E0A => &.{0x1E0B},
+ 0x1E0C => &.{0x1E0D},
+ 0x1E0E => &.{0x1E0F},
+ 0x1E10 => &.{0x1E11},
+ 0x1E12 => &.{0x1E13},
+ 0x1E14 => &.{0x1E15},
+ 0x1E16 => &.{0x1E17},
+ 0x1E18 => &.{0x1E19},
+ 0x1E1A => &.{0x1E1B},
+ 0x1E1C => &.{0x1E1D},
+ 0x1E1E => &.{0x1E1F},
+ 0x1E20 => &.{0x1E21},
+ 0x1E22 => &.{0x1E23},
+ 0x1E24 => &.{0x1E25},
+ 0x1E26 => &.{0x1E27},
+ 0x1E28 => &.{0x1E29},
+ 0x1E2A => &.{0x1E2B},
+ 0x1E2C => &.{0x1E2D},
+ 0x1E2E => &.{0x1E2F},
+ 0x1E30 => &.{0x1E31},
+ 0x1E32 => &.{0x1E33},
+ 0x1E34 => &.{0x1E35},
+ 0x1E36 => &.{0x1E37},
+ 0x1E38 => &.{0x1E39},
+ 0x1E3A => &.{0x1E3B},
+ 0x1E3C => &.{0x1E3D},
+ 0x1E3E => &.{0x1E3F},
+ 0x1E40 => &.{0x1E41},
+ 0x1E42 => &.{0x1E43},
+ 0x1E44 => &.{0x1E45},
+ 0x1E46 => &.{0x1E47},
+ 0x1E48 => &.{0x1E49},
+ 0x1E4A => &.{0x1E4B},
+ 0x1E4C => &.{0x1E4D},
+ 0x1E4E => &.{0x1E4F},
+ 0x1E50 => &.{0x1E51},
+ 0x1E52 => &.{0x1E53},
+ 0x1E54 => &.{0x1E55},
+ 0x1E56 => &.{0x1E57},
+ 0x1E58 => &.{0x1E59},
+ 0x1E5A => &.{0x1E5B},
+ 0x1E5C => &.{0x1E5D},
+ 0x1E5E => &.{0x1E5F},
+ 0x1E60 => &.{0x1E61},
+ 0x1E62 => &.{0x1E63},
+ 0x1E64 => &.{0x1E65},
+ 0x1E66 => &.{0x1E67},
+ 0x1E68 => &.{0x1E69},
+ 0x1E6A => &.{0x1E6B},
+ 0x1E6C => &.{0x1E6D},
+ 0x1E6E => &.{0x1E6F},
+ 0x1E70 => &.{0x1E71},
+ 0x1E72 => &.{0x1E73},
+ 0x1E74 => &.{0x1E75},
+ 0x1E76 => &.{0x1E77},
+ 0x1E78 => &.{0x1E79},
+ 0x1E7A => &.{0x1E7B},
+ 0x1E7C => &.{0x1E7D},
+ 0x1E7E => &.{0x1E7F},
+ 0x1E80 => &.{0x1E81},
+ 0x1E82 => &.{0x1E83},
+ 0x1E84 => &.{0x1E85},
+ 0x1E86 => &.{0x1E87},
+ 0x1E88 => &.{0x1E89},
+ 0x1E8A => &.{0x1E8B},
+ 0x1E8C => &.{0x1E8D},
+ 0x1E8E => &.{0x1E8F},
+ 0x1E90 => &.{0x1E91},
+ 0x1E92 => &.{0x1E93},
+ 0x1E94 => &.{0x1E95},
+ 0x1E9A => &.{ 0x61, 0x2BE },
+ 0x1E9B => &.{0x1E61},
+ 0x1E9E => &.{ 0x73, 0x73 },
+ 0x1EA0 => &.{0x1EA1},
+ 0x1EA2 => &.{0x1EA3},
+ 0x1EA4 => &.{0x1EA5},
+ 0x1EA6 => &.{0x1EA7},
+ 0x1EA8 => &.{0x1EA9},
+ 0x1EAA => &.{0x1EAB},
+ 0x1EAC => &.{0x1EAD},
+ 0x1EAE => &.{0x1EAF},
+ 0x1EB0 => &.{0x1EB1},
+ 0x1EB2 => &.{0x1EB3},
+ 0x1EB4 => &.{0x1EB5},
+ 0x1EB6 => &.{0x1EB7},
+ 0x1EB8 => &.{0x1EB9},
+ 0x1EBA => &.{0x1EBB},
+ 0x1EBC => &.{0x1EBD},
+ 0x1EBE => &.{0x1EBF},
+ 0x1EC0 => &.{0x1EC1},
+ 0x1EC2 => &.{0x1EC3},
+ 0x1EC4 => &.{0x1EC5},
+ 0x1EC6 => &.{0x1EC7},
+ 0x1EC8 => &.{0x1EC9},
+ 0x1ECA => &.{0x1ECB},
+ 0x1ECC => &.{0x1ECD},
+ 0x1ECE => &.{0x1ECF},
+ 0x1ED0 => &.{0x1ED1},
+ 0x1ED2 => &.{0x1ED3},
+ 0x1ED4 => &.{0x1ED5},
+ 0x1ED6 => &.{0x1ED7},
+ 0x1ED8 => &.{0x1ED9},
+ 0x1EDA => &.{0x1EDB},
+ 0x1EDC => &.{0x1EDD},
+ 0x1EDE => &.{0x1EDF},
+ 0x1EE0 => &.{0x1EE1},
+ 0x1EE2 => &.{0x1EE3},
+ 0x1EE4 => &.{0x1EE5},
+ 0x1EE6 => &.{0x1EE7},
+ 0x1EE8 => &.{0x1EE9},
+ 0x1EEA => &.{0x1EEB},
+ 0x1EEC => &.{0x1EED},
+ 0x1EEE => &.{0x1EEF},
+ 0x1EF0 => &.{0x1EF1},
+ 0x1EF2 => &.{0x1EF3},
+ 0x1EF4 => &.{0x1EF5},
+ 0x1EF6 => &.{0x1EF7},
+ 0x1EF8 => &.{0x1EF9},
+ 0x1EFA => &.{0x1EFB},
+ 0x1EFC => &.{0x1EFD},
+ 0x1EFE => &.{0x1EFF},
+ 0x1F08 => &.{0x1F00},
+ 0x1F09 => &.{0x1F01},
+ 0x1F0A => &.{0x1F02},
+ 0x1F0B => &.{0x1F03},
+ 0x1F0C => &.{0x1F04},
+ 0x1F0D => &.{0x1F05},
+ 0x1F0E => &.{0x1F06},
+ 0x1F0F => &.{0x1F07},
+ 0x1F18 => &.{0x1F10},
+ 0x1F19 => &.{0x1F11},
+ 0x1F1A => &.{0x1F12},
+ 0x1F1B => &.{0x1F13},
+ 0x1F1C => &.{0x1F14},
+ 0x1F1D => &.{0x1F15},
+ 0x1F28 => &.{0x1F20},
+ 0x1F29 => &.{0x1F21},
+ 0x1F2A => &.{0x1F22},
+ 0x1F2B => &.{0x1F23},
+ 0x1F2C => &.{0x1F24},
+ 0x1F2D => &.{0x1F25},
+ 0x1F2E => &.{0x1F26},
+ 0x1F2F => &.{0x1F27},
+ 0x1F38 => &.{0x1F30},
+ 0x1F39 => &.{0x1F31},
+ 0x1F3A => &.{0x1F32},
+ 0x1F3B => &.{0x1F33},
+ 0x1F3C => &.{0x1F34},
+ 0x1F3D => &.{0x1F35},
+ 0x1F3E => &.{0x1F36},
+ 0x1F3F => &.{0x1F37},
+ 0x1F48 => &.{0x1F40},
+ 0x1F49 => &.{0x1F41},
+ 0x1F4A => &.{0x1F42},
+ 0x1F4B => &.{0x1F43},
+ 0x1F4C => &.{0x1F44},
+ 0x1F4D => &.{0x1F45},
+ 0x1F59 => &.{0x1F51},
+ 0x1F5B => &.{0x1F53},
+ 0x1F5D => &.{0x1F55},
+ 0x1F5F => &.{0x1F57},
+ 0x1F68 => &.{0x1F60},
+ 0x1F69 => &.{0x1F61},
+ 0x1F6A => &.{0x1F62},
+ 0x1F6B => &.{0x1F63},
+ 0x1F6C => &.{0x1F64},
+ 0x1F6D => &.{0x1F65},
+ 0x1F6E => &.{0x1F66},
+ 0x1F6F => &.{0x1F67},
+ 0x1F71 => &.{0x3AC},
+ 0x1F73 => &.{0x3AD},
+ 0x1F75 => &.{0x3AE},
+ 0x1F77 => &.{0x3AF},
+ 0x1F79 => &.{0x3CC},
+ 0x1F7B => &.{0x3CD},
+ 0x1F7D => &.{0x3CE},
+ 0x1F80 => &.{ 0x1F00, 0x3B9 },
+ 0x1F81 => &.{ 0x1F01, 0x3B9 },
+ 0x1F82 => &.{ 0x1F02, 0x3B9 },
+ 0x1F83 => &.{ 0x1F03, 0x3B9 },
+ 0x1F84 => &.{ 0x1F04, 0x3B9 },
+ 0x1F85 => &.{ 0x1F05, 0x3B9 },
+ 0x1F86 => &.{ 0x1F06, 0x3B9 },
+ 0x1F87 => &.{ 0x1F07, 0x3B9 },
+ 0x1F88 => &.{ 0x1F00, 0x3B9 },
+ 0x1F89 => &.{ 0x1F01, 0x3B9 },
+ 0x1F8A => &.{ 0x1F02, 0x3B9 },
+ 0x1F8B => &.{ 0x1F03, 0x3B9 },
+ 0x1F8C => &.{ 0x1F04, 0x3B9 },
+ 0x1F8D => &.{ 0x1F05, 0x3B9 },
+ 0x1F8E => &.{ 0x1F06, 0x3B9 },
+ 0x1F8F => &.{ 0x1F07, 0x3B9 },
+ 0x1F90 => &.{ 0x1F20, 0x3B9 },
+ 0x1F91 => &.{ 0x1F21, 0x3B9 },
+ 0x1F92 => &.{ 0x1F22, 0x3B9 },
+ 0x1F93 => &.{ 0x1F23, 0x3B9 },
+ 0x1F94 => &.{ 0x1F24, 0x3B9 },
+ 0x1F95 => &.{ 0x1F25, 0x3B9 },
+ 0x1F96 => &.{ 0x1F26, 0x3B9 },
+ 0x1F97 => &.{ 0x1F27, 0x3B9 },
+ 0x1F98 => &.{ 0x1F20, 0x3B9 },
+ 0x1F99 => &.{ 0x1F21, 0x3B9 },
+ 0x1F9A => &.{ 0x1F22, 0x3B9 },
+ 0x1F9B => &.{ 0x1F23, 0x3B9 },
+ 0x1F9C => &.{ 0x1F24, 0x3B9 },
+ 0x1F9D => &.{ 0x1F25, 0x3B9 },
+ 0x1F9E => &.{ 0x1F26, 0x3B9 },
+ 0x1F9F => &.{ 0x1F27, 0x3B9 },
+ 0x1FA0 => &.{ 0x1F60, 0x3B9 },
+ 0x1FA1 => &.{ 0x1F61, 0x3B9 },
+ 0x1FA2 => &.{ 0x1F62, 0x3B9 },
+ 0x1FA3 => &.{ 0x1F63, 0x3B9 },
+ 0x1FA4 => &.{ 0x1F64, 0x3B9 },
+ 0x1FA5 => &.{ 0x1F65, 0x3B9 },
+ 0x1FA6 => &.{ 0x1F66, 0x3B9 },
+ 0x1FA7 => &.{ 0x1F67, 0x3B9 },
+ 0x1FA8 => &.{ 0x1F60, 0x3B9 },
+ 0x1FA9 => &.{ 0x1F61, 0x3B9 },
+ 0x1FAA => &.{ 0x1F62, 0x3B9 },
+ 0x1FAB => &.{ 0x1F63, 0x3B9 },
+ 0x1FAC => &.{ 0x1F64, 0x3B9 },
+ 0x1FAD => &.{ 0x1F65, 0x3B9 },
+ 0x1FAE => &.{ 0x1F66, 0x3B9 },
+ 0x1FAF => &.{ 0x1F67, 0x3B9 },
+ 0x1FB2 => &.{ 0x1F70, 0x3B9 },
+ 0x1FB3 => &.{ 0x3B1, 0x3B9 },
+ 0x1FB4 => &.{ 0x3AC, 0x3B9 },
+ 0x1FB7 => &.{ 0x1FB6, 0x3B9 },
+ 0x1FB8 => &.{0x1FB0},
+ 0x1FB9 => &.{0x1FB1},
+ 0x1FBA => &.{0x1F70},
+ 0x1FBB => &.{0x3AC},
+ 0x1FBC => &.{ 0x3B1, 0x3B9 },
+ 0x1FBD => &.{ 0x20, 0x313 },
+ 0x1FBE => &.{0x3B9},
+ 0x1FBF => &.{ 0x20, 0x313 },
+ 0x1FC0 => &.{ 0x20, 0x342 },
+ 0x1FC1 => &.{ 0x20, 0x308, 0x342 },
+ 0x1FC2 => &.{ 0x1F74, 0x3B9 },
+ 0x1FC3 => &.{ 0x3B7, 0x3B9 },
+ 0x1FC4 => &.{ 0x3AE, 0x3B9 },
+ 0x1FC7 => &.{ 0x1FC6, 0x3B9 },
+ 0x1FC8 => &.{0x1F72},
+ 0x1FC9 => &.{0x3AD},
+ 0x1FCA => &.{0x1F74},
+ 0x1FCB => &.{0x3AE},
+ 0x1FCC => &.{ 0x3B7, 0x3B9 },
+ 0x1FCD => &.{ 0x20, 0x313, 0x300 },
+ 0x1FCE => &.{ 0x20, 0x313, 0x301 },
+ 0x1FCF => &.{ 0x20, 0x313, 0x342 },
+ 0x1FD3 => &.{0x390},
+ 0x1FD8 => &.{0x1FD0},
+ 0x1FD9 => &.{0x1FD1},
+ 0x1FDA => &.{0x1F76},
+ 0x1FDB => &.{0x3AF},
+ 0x1FDD => &.{ 0x20, 0x314, 0x300 },
+ 0x1FDE => &.{ 0x20, 0x314, 0x301 },
+ 0x1FDF => &.{ 0x20, 0x314, 0x342 },
+ 0x1FE3 => &.{0x3B0},
+ 0x1FE8 => &.{0x1FE0},
+ 0x1FE9 => &.{0x1FE1},
+ 0x1FEA => &.{0x1F7A},
+ 0x1FEB => &.{0x3CD},
+ 0x1FEC => &.{0x1FE5},
+ 0x1FED => &.{ 0x20, 0x308, 0x300 },
+ 0x1FEE => &.{ 0x20, 0x308, 0x301 },
+ 0x1FEF => &.{0x60},
+ 0x1FF2 => &.{ 0x1F7C, 0x3B9 },
+ 0x1FF3 => &.{ 0x3C9, 0x3B9 },
+ 0x1FF4 => &.{ 0x3CE, 0x3B9 },
+ 0x1FF7 => &.{ 0x1FF6, 0x3B9 },
+ 0x1FF8 => &.{0x1F78},
+ 0x1FF9 => &.{0x3CC},
+ 0x1FFA => &.{0x1F7C},
+ 0x1FFB => &.{0x3CE},
+ 0x1FFC => &.{ 0x3C9, 0x3B9 },
+ 0x1FFD => &.{ 0x20, 0x301 },
+ 0x1FFE => &.{ 0x20, 0x314 },
+ 0x2000...0x200A => &.{0x20},
+ 0x200B...0x200F => null,
+ 0x2011 => &.{0x2010},
+ 0x2017 => &.{ 0x20, 0x333 },
+ 0x2024 => &.{0x2E},
+ 0x2025 => &.{ 0x2E, 0x2E },
+ 0x2026 => &.{ 0x2E, 0x2E, 0x2E },
+ 0x202A...0x202E => null,
+ 0x202F => &.{0x20},
+ 0x2033 => &.{ 0x2032, 0x2032 },
+ 0x2034 => &.{ 0x2032, 0x2032, 0x2032 },
+ 0x2036 => &.{ 0x2035, 0x2035 },
+ 0x2037 => &.{ 0x2035, 0x2035, 0x2035 },
+ 0x203C => &.{ 0x21, 0x21 },
+ 0x203E => &.{ 0x20, 0x305 },
+ 0x2047 => &.{ 0x3F, 0x3F },
+ 0x2048 => &.{ 0x3F, 0x21 },
+ 0x2049 => &.{ 0x21, 0x3F },
+ 0x2057 => &.{ 0x2032, 0x2032, 0x2032, 0x2032 },
+ 0x205F => &.{0x20},
+ 0x2060...0x2064 => null,
+ 0x2065 => null,
+ 0x2066...0x206F => null,
+ 0x2070 => &.{0x30},
+ 0x2071 => &.{0x69},
+ 0x2074 => &.{0x34},
+ 0x2075 => &.{0x35},
+ 0x2076 => &.{0x36},
+ 0x2077 => &.{0x37},
+ 0x2078 => &.{0x38},
+ 0x2079 => &.{0x39},
+ 0x207A => &.{0x2B},
+ 0x207B => &.{0x2212},
+ 0x207C => &.{0x3D},
+ 0x207D => &.{0x28},
+ 0x207E => &.{0x29},
+ 0x207F => &.{0x6E},
+ 0x2080 => &.{0x30},
+ 0x2081 => &.{0x31},
+ 0x2082 => &.{0x32},
+ 0x2083 => &.{0x33},
+ 0x2084 => &.{0x34},
+ 0x2085 => &.{0x35},
+ 0x2086 => &.{0x36},
+ 0x2087 => &.{0x37},
+ 0x2088 => &.{0x38},
+ 0x2089 => &.{0x39},
+ 0x208A => &.{0x2B},
+ 0x208B => &.{0x2212},
+ 0x208C => &.{0x3D},
+ 0x208D => &.{0x28},
+ 0x208E => &.{0x29},
+ 0x2090 => &.{0x61},
+ 0x2091 => &.{0x65},
+ 0x2092 => &.{0x6F},
+ 0x2093 => &.{0x78},
+ 0x2094 => &.{0x259},
+ 0x2095 => &.{0x68},
+ 0x2096 => &.{0x6B},
+ 0x2097 => &.{0x6C},
+ 0x2098 => &.{0x6D},
+ 0x2099 => &.{0x6E},
+ 0x209A => &.{0x70},
+ 0x209B => &.{0x73},
+ 0x209C => &.{0x74},
+ 0x20A8 => &.{ 0x72, 0x73 },
+ 0x2100 => &.{ 0x61, 0x2F, 0x63 },
+ 0x2101 => &.{ 0x61, 0x2F, 0x73 },
+ 0x2102 => &.{0x63},
+ 0x2103 => &.{ 0xB0, 0x63 },
+ 0x2105 => &.{ 0x63, 0x2F, 0x6F },
+ 0x2106 => &.{ 0x63, 0x2F, 0x75 },
+ 0x2107 => &.{0x25B},
+ 0x2109 => &.{ 0xB0, 0x66 },
+ 0x210A => &.{0x67},
+ 0x210B...0x210E => &.{0x68},
+ 0x210F => &.{0x127},
+ 0x2110...0x2111 => &.{0x69},
+ 0x2112...0x2113 => &.{0x6C},
+ 0x2115 => &.{0x6E},
+ 0x2116 => &.{ 0x6E, 0x6F },
+ 0x2119 => &.{0x70},
+ 0x211A => &.{0x71},
+ 0x211B...0x211D => &.{0x72},
+ 0x2120 => &.{ 0x73, 0x6D },
+ 0x2121 => &.{ 0x74, 0x65, 0x6C },
+ 0x2122 => &.{ 0x74, 0x6D },
+ 0x2124 => &.{0x7A},
+ 0x2126 => &.{0x3C9},
+ 0x2128 => &.{0x7A},
+ 0x212A => &.{0x6B},
+ 0x212B => &.{0xE5},
+ 0x212C => &.{0x62},
+ 0x212D => &.{0x63},
+ 0x212F...0x2130 => &.{0x65},
+ 0x2131 => &.{0x66},
+ 0x2132 => &.{0x214E},
+ 0x2133 => &.{0x6D},
+ 0x2134 => &.{0x6F},
+ 0x2135 => &.{0x5D0},
+ 0x2136 => &.{0x5D1},
+ 0x2137 => &.{0x5D2},
+ 0x2138 => &.{0x5D3},
+ 0x2139 => &.{0x69},
+ 0x213B => &.{ 0x66, 0x61, 0x78 },
+ 0x213C => &.{0x3C0},
+ 0x213D...0x213E => &.{0x3B3},
+ 0x213F => &.{0x3C0},
+ 0x2140 => &.{0x2211},
+ 0x2145...0x2146 => &.{0x64},
+ 0x2147 => &.{0x65},
+ 0x2148 => &.{0x69},
+ 0x2149 => &.{0x6A},
+ 0x2150 => &.{ 0x31, 0x2044, 0x37 },
+ 0x2151 => &.{ 0x31, 0x2044, 0x39 },
+ 0x2152 => &.{ 0x31, 0x2044, 0x31, 0x30 },
+ 0x2153 => &.{ 0x31, 0x2044, 0x33 },
+ 0x2154 => &.{ 0x32, 0x2044, 0x33 },
+ 0x2155 => &.{ 0x31, 0x2044, 0x35 },
+ 0x2156 => &.{ 0x32, 0x2044, 0x35 },
+ 0x2157 => &.{ 0x33, 0x2044, 0x35 },
+ 0x2158 => &.{ 0x34, 0x2044, 0x35 },
+ 0x2159 => &.{ 0x31, 0x2044, 0x36 },
+ 0x215A => &.{ 0x35, 0x2044, 0x36 },
+ 0x215B => &.{ 0x31, 0x2044, 0x38 },
+ 0x215C => &.{ 0x33, 0x2044, 0x38 },
+ 0x215D => &.{ 0x35, 0x2044, 0x38 },
+ 0x215E => &.{ 0x37, 0x2044, 0x38 },
+ 0x215F => &.{ 0x31, 0x2044 },
+ 0x2160 => &.{0x69},
+ 0x2161 => &.{ 0x69, 0x69 },
+ 0x2162 => &.{ 0x69, 0x69, 0x69 },
+ 0x2163 => &.{ 0x69, 0x76 },
+ 0x2164 => &.{0x76},
+ 0x2165 => &.{ 0x76, 0x69 },
+ 0x2166 => &.{ 0x76, 0x69, 0x69 },
+ 0x2167 => &.{ 0x76, 0x69, 0x69, 0x69 },
+ 0x2168 => &.{ 0x69, 0x78 },
+ 0x2169 => &.{0x78},
+ 0x216A => &.{ 0x78, 0x69 },
+ 0x216B => &.{ 0x78, 0x69, 0x69 },
+ 0x216C => &.{0x6C},
+ 0x216D => &.{0x63},
+ 0x216E => &.{0x64},
+ 0x216F => &.{0x6D},
+ 0x2170 => &.{0x69},
+ 0x2171 => &.{ 0x69, 0x69 },
+ 0x2172 => &.{ 0x69, 0x69, 0x69 },
+ 0x2173 => &.{ 0x69, 0x76 },
+ 0x2174 => &.{0x76},
+ 0x2175 => &.{ 0x76, 0x69 },
+ 0x2176 => &.{ 0x76, 0x69, 0x69 },
+ 0x2177 => &.{ 0x76, 0x69, 0x69, 0x69 },
+ 0x2178 => &.{ 0x69, 0x78 },
+ 0x2179 => &.{0x78},
+ 0x217A => &.{ 0x78, 0x69 },
+ 0x217B => &.{ 0x78, 0x69, 0x69 },
+ 0x217C => &.{0x6C},
+ 0x217D => &.{0x63},
+ 0x217E => &.{0x64},
+ 0x217F => &.{0x6D},
+ 0x2183 => &.{0x2184},
+ 0x2189 => &.{ 0x30, 0x2044, 0x33 },
+ 0x222C => &.{ 0x222B, 0x222B },
+ 0x222D => &.{ 0x222B, 0x222B, 0x222B },
+ 0x222F => &.{ 0x222E, 0x222E },
+ 0x2230 => &.{ 0x222E, 0x222E, 0x222E },
+ 0x2329 => &.{0x3008},
+ 0x232A => &.{0x3009},
+ 0x2460 => &.{0x31},
+ 0x2461 => &.{0x32},
+ 0x2462 => &.{0x33},
+ 0x2463 => &.{0x34},
+ 0x2464 => &.{0x35},
+ 0x2465 => &.{0x36},
+ 0x2466 => &.{0x37},
+ 0x2467 => &.{0x38},
+ 0x2468 => &.{0x39},
+ 0x2469 => &.{ 0x31, 0x30 },
+ 0x246A => &.{ 0x31, 0x31 },
+ 0x246B => &.{ 0x31, 0x32 },
+ 0x246C => &.{ 0x31, 0x33 },
+ 0x246D => &.{ 0x31, 0x34 },
+ 0x246E => &.{ 0x31, 0x35 },
+ 0x246F => &.{ 0x31, 0x36 },
+ 0x2470 => &.{ 0x31, 0x37 },
+ 0x2471 => &.{ 0x31, 0x38 },
+ 0x2472 => &.{ 0x31, 0x39 },
+ 0x2473 => &.{ 0x32, 0x30 },
+ 0x2474 => &.{ 0x28, 0x31, 0x29 },
+ 0x2475 => &.{ 0x28, 0x32, 0x29 },
+ 0x2476 => &.{ 0x28, 0x33, 0x29 },
+ 0x2477 => &.{ 0x28, 0x34, 0x29 },
+ 0x2478 => &.{ 0x28, 0x35, 0x29 },
+ 0x2479 => &.{ 0x28, 0x36, 0x29 },
+ 0x247A => &.{ 0x28, 0x37, 0x29 },
+ 0x247B => &.{ 0x28, 0x38, 0x29 },
+ 0x247C => &.{ 0x28, 0x39, 0x29 },
+ 0x247D => &.{ 0x28, 0x31, 0x30, 0x29 },
+ 0x247E => &.{ 0x28, 0x31, 0x31, 0x29 },
+ 0x247F => &.{ 0x28, 0x31, 0x32, 0x29 },
+ 0x2480 => &.{ 0x28, 0x31, 0x33, 0x29 },
+ 0x2481 => &.{ 0x28, 0x31, 0x34, 0x29 },
+ 0x2482 => &.{ 0x28, 0x31, 0x35, 0x29 },
+ 0x2483 => &.{ 0x28, 0x31, 0x36, 0x29 },
+ 0x2484 => &.{ 0x28, 0x31, 0x37, 0x29 },
+ 0x2485 => &.{ 0x28, 0x31, 0x38, 0x29 },
+ 0x2486 => &.{ 0x28, 0x31, 0x39, 0x29 },
+ 0x2487 => &.{ 0x28, 0x32, 0x30, 0x29 },
+ 0x2488 => &.{ 0x31, 0x2E },
+ 0x2489 => &.{ 0x32, 0x2E },
+ 0x248A => &.{ 0x33, 0x2E },
+ 0x248B => &.{ 0x34, 0x2E },
+ 0x248C => &.{ 0x35, 0x2E },
+ 0x248D => &.{ 0x36, 0x2E },
+ 0x248E => &.{ 0x37, 0x2E },
+ 0x248F => &.{ 0x38, 0x2E },
+ 0x2490 => &.{ 0x39, 0x2E },
+ 0x2491 => &.{ 0x31, 0x30, 0x2E },
+ 0x2492 => &.{ 0x31, 0x31, 0x2E },
+ 0x2493 => &.{ 0x31, 0x32, 0x2E },
+ 0x2494 => &.{ 0x31, 0x33, 0x2E },
+ 0x2495 => &.{ 0x31, 0x34, 0x2E },
+ 0x2496 => &.{ 0x31, 0x35, 0x2E },
+ 0x2497 => &.{ 0x31, 0x36, 0x2E },
+ 0x2498 => &.{ 0x31, 0x37, 0x2E },
+ 0x2499 => &.{ 0x31, 0x38, 0x2E },
+ 0x249A => &.{ 0x31, 0x39, 0x2E },
+ 0x249B => &.{ 0x32, 0x30, 0x2E },
+ 0x249C => &.{ 0x28, 0x61, 0x29 },
+ 0x249D => &.{ 0x28, 0x62, 0x29 },
+ 0x249E => &.{ 0x28, 0x63, 0x29 },
+ 0x249F => &.{ 0x28, 0x64, 0x29 },
+ 0x24A0 => &.{ 0x28, 0x65, 0x29 },
+ 0x24A1 => &.{ 0x28, 0x66, 0x29 },
+ 0x24A2 => &.{ 0x28, 0x67, 0x29 },
+ 0x24A3 => &.{ 0x28, 0x68, 0x29 },
+ 0x24A4 => &.{ 0x28, 0x69, 0x29 },
+ 0x24A5 => &.{ 0x28, 0x6A, 0x29 },
+ 0x24A6 => &.{ 0x28, 0x6B, 0x29 },
+ 0x24A7 => &.{ 0x28, 0x6C, 0x29 },
+ 0x24A8 => &.{ 0x28, 0x6D, 0x29 },
+ 0x24A9 => &.{ 0x28, 0x6E, 0x29 },
+ 0x24AA => &.{ 0x28, 0x6F, 0x29 },
+ 0x24AB => &.{ 0x28, 0x70, 0x29 },
+ 0x24AC => &.{ 0x28, 0x71, 0x29 },
+ 0x24AD => &.{ 0x28, 0x72, 0x29 },
+ 0x24AE => &.{ 0x28, 0x73, 0x29 },
+ 0x24AF => &.{ 0x28, 0x74, 0x29 },
+ 0x24B0 => &.{ 0x28, 0x75, 0x29 },
+ 0x24B1 => &.{ 0x28, 0x76, 0x29 },
+ 0x24B2 => &.{ 0x28, 0x77, 0x29 },
+ 0x24B3 => &.{ 0x28, 0x78, 0x29 },
+ 0x24B4 => &.{ 0x28, 0x79, 0x29 },
+ 0x24B5 => &.{ 0x28, 0x7A, 0x29 },
+ 0x24B6 => &.{0x61},
+ 0x24B7 => &.{0x62},
+ 0x24B8 => &.{0x63},
+ 0x24B9 => &.{0x64},
+ 0x24BA => &.{0x65},
+ 0x24BB => &.{0x66},
+ 0x24BC => &.{0x67},
+ 0x24BD => &.{0x68},
+ 0x24BE => &.{0x69},
+ 0x24BF => &.{0x6A},
+ 0x24C0 => &.{0x6B},
+ 0x24C1 => &.{0x6C},
+ 0x24C2 => &.{0x6D},
+ 0x24C3 => &.{0x6E},
+ 0x24C4 => &.{0x6F},
+ 0x24C5 => &.{0x70},
+ 0x24C6 => &.{0x71},
+ 0x24C7 => &.{0x72},
+ 0x24C8 => &.{0x73},
+ 0x24C9 => &.{0x74},
+ 0x24CA => &.{0x75},
+ 0x24CB => &.{0x76},
+ 0x24CC => &.{0x77},
+ 0x24CD => &.{0x78},
+ 0x24CE => &.{0x79},
+ 0x24CF => &.{0x7A},
+ 0x24D0 => &.{0x61},
+ 0x24D1 => &.{0x62},
+ 0x24D2 => &.{0x63},
+ 0x24D3 => &.{0x64},
+ 0x24D4 => &.{0x65},
+ 0x24D5 => &.{0x66},
+ 0x24D6 => &.{0x67},
+ 0x24D7 => &.{0x68},
+ 0x24D8 => &.{0x69},
+ 0x24D9 => &.{0x6A},
+ 0x24DA => &.{0x6B},
+ 0x24DB => &.{0x6C},
+ 0x24DC => &.{0x6D},
+ 0x24DD => &.{0x6E},
+ 0x24DE => &.{0x6F},
+ 0x24DF => &.{0x70},
+ 0x24E0 => &.{0x71},
+ 0x24E1 => &.{0x72},
+ 0x24E2 => &.{0x73},
+ 0x24E3 => &.{0x74},
+ 0x24E4 => &.{0x75},
+ 0x24E5 => &.{0x76},
+ 0x24E6 => &.{0x77},
+ 0x24E7 => &.{0x78},
+ 0x24E8 => &.{0x79},
+ 0x24E9 => &.{0x7A},
+ 0x24EA => &.{0x30},
+ 0x2A0C => &.{ 0x222B, 0x222B, 0x222B, 0x222B },
+ 0x2A74 => &.{ 0x3A, 0x3A, 0x3D },
+ 0x2A75 => &.{ 0x3D, 0x3D },
+ 0x2A76 => &.{ 0x3D, 0x3D, 0x3D },
+ 0x2ADC => &.{ 0x2ADD, 0x338 },
+ 0x2C00 => &.{0x2C30},
+ 0x2C01 => &.{0x2C31},
+ 0x2C02 => &.{0x2C32},
+ 0x2C03 => &.{0x2C33},
+ 0x2C04 => &.{0x2C34},
+ 0x2C05 => &.{0x2C35},
+ 0x2C06 => &.{0x2C36},
+ 0x2C07 => &.{0x2C37},
+ 0x2C08 => &.{0x2C38},
+ 0x2C09 => &.{0x2C39},
+ 0x2C0A => &.{0x2C3A},
+ 0x2C0B => &.{0x2C3B},
+ 0x2C0C => &.{0x2C3C},
+ 0x2C0D => &.{0x2C3D},
+ 0x2C0E => &.{0x2C3E},
+ 0x2C0F => &.{0x2C3F},
+ 0x2C10 => &.{0x2C40},
+ 0x2C11 => &.{0x2C41},
+ 0x2C12 => &.{0x2C42},
+ 0x2C13 => &.{0x2C43},
+ 0x2C14 => &.{0x2C44},
+ 0x2C15 => &.{0x2C45},
+ 0x2C16 => &.{0x2C46},
+ 0x2C17 => &.{0x2C47},
+ 0x2C18 => &.{0x2C48},
+ 0x2C19 => &.{0x2C49},
+ 0x2C1A => &.{0x2C4A},
+ 0x2C1B => &.{0x2C4B},
+ 0x2C1C => &.{0x2C4C},
+ 0x2C1D => &.{0x2C4D},
+ 0x2C1E => &.{0x2C4E},
+ 0x2C1F => &.{0x2C4F},
+ 0x2C20 => &.{0x2C50},
+ 0x2C21 => &.{0x2C51},
+ 0x2C22 => &.{0x2C52},
+ 0x2C23 => &.{0x2C53},
+ 0x2C24 => &.{0x2C54},
+ 0x2C25 => &.{0x2C55},
+ 0x2C26 => &.{0x2C56},
+ 0x2C27 => &.{0x2C57},
+ 0x2C28 => &.{0x2C58},
+ 0x2C29 => &.{0x2C59},
+ 0x2C2A => &.{0x2C5A},
+ 0x2C2B => &.{0x2C5B},
+ 0x2C2C => &.{0x2C5C},
+ 0x2C2D => &.{0x2C5D},
+ 0x2C2E => &.{0x2C5E},
+ 0x2C2F => &.{0x2C5F},
+ 0x2C60 => &.{0x2C61},
+ 0x2C62 => &.{0x26B},
+ 0x2C63 => &.{0x1D7D},
+ 0x2C64 => &.{0x27D},
+ 0x2C67 => &.{0x2C68},
+ 0x2C69 => &.{0x2C6A},
+ 0x2C6B => &.{0x2C6C},
+ 0x2C6D => &.{0x251},
+ 0x2C6E => &.{0x271},
+ 0x2C6F => &.{0x250},
+ 0x2C70 => &.{0x252},
+ 0x2C72 => &.{0x2C73},
+ 0x2C75 => &.{0x2C76},
+ 0x2C7C => &.{0x6A},
+ 0x2C7D => &.{0x76},
+ 0x2C7E => &.{0x23F},
+ 0x2C7F => &.{0x240},
+ 0x2C80 => &.{0x2C81},
+ 0x2C82 => &.{0x2C83},
+ 0x2C84 => &.{0x2C85},
+ 0x2C86 => &.{0x2C87},
+ 0x2C88 => &.{0x2C89},
+ 0x2C8A => &.{0x2C8B},
+ 0x2C8C => &.{0x2C8D},
+ 0x2C8E => &.{0x2C8F},
+ 0x2C90 => &.{0x2C91},
+ 0x2C92 => &.{0x2C93},
+ 0x2C94 => &.{0x2C95},
+ 0x2C96 => &.{0x2C97},
+ 0x2C98 => &.{0x2C99},
+ 0x2C9A => &.{0x2C9B},
+ 0x2C9C => &.{0x2C9D},
+ 0x2C9E => &.{0x2C9F},
+ 0x2CA0 => &.{0x2CA1},
+ 0x2CA2 => &.{0x2CA3},
+ 0x2CA4 => &.{0x2CA5},
+ 0x2CA6 => &.{0x2CA7},
+ 0x2CA8 => &.{0x2CA9},
+ 0x2CAA => &.{0x2CAB},
+ 0x2CAC => &.{0x2CAD},
+ 0x2CAE => &.{0x2CAF},
+ 0x2CB0 => &.{0x2CB1},
+ 0x2CB2 => &.{0x2CB3},
+ 0x2CB4 => &.{0x2CB5},
+ 0x2CB6 => &.{0x2CB7},
+ 0x2CB8 => &.{0x2CB9},
+ 0x2CBA => &.{0x2CBB},
+ 0x2CBC => &.{0x2CBD},
+ 0x2CBE => &.{0x2CBF},
+ 0x2CC0 => &.{0x2CC1},
+ 0x2CC2 => &.{0x2CC3},
+ 0x2CC4 => &.{0x2CC5},
+ 0x2CC6 => &.{0x2CC7},
+ 0x2CC8 => &.{0x2CC9},
+ 0x2CCA => &.{0x2CCB},
+ 0x2CCC => &.{0x2CCD},
+ 0x2CCE => &.{0x2CCF},
+ 0x2CD0 => &.{0x2CD1},
+ 0x2CD2 => &.{0x2CD3},
+ 0x2CD4 => &.{0x2CD5},
+ 0x2CD6 => &.{0x2CD7},
+ 0x2CD8 => &.{0x2CD9},
+ 0x2CDA => &.{0x2CDB},
+ 0x2CDC => &.{0x2CDD},
+ 0x2CDE => &.{0x2CDF},
+ 0x2CE0 => &.{0x2CE1},
+ 0x2CE2 => &.{0x2CE3},
+ 0x2CEB => &.{0x2CEC},
+ 0x2CED => &.{0x2CEE},
+ 0x2CF2 => &.{0x2CF3},
+ 0x2D6F => &.{0x2D61},
+ 0x2E9F => &.{0x6BCD},
+ 0x2EF3 => &.{0x9F9F},
+ 0x2F00 => &.{0x4E00},
+ 0x2F01 => &.{0x4E28},
+ 0x2F02 => &.{0x4E36},
+ 0x2F03 => &.{0x4E3F},
+ 0x2F04 => &.{0x4E59},
+ 0x2F05 => &.{0x4E85},
+ 0x2F06 => &.{0x4E8C},
+ 0x2F07 => &.{0x4EA0},
+ 0x2F08 => &.{0x4EBA},
+ 0x2F09 => &.{0x513F},
+ 0x2F0A => &.{0x5165},
+ 0x2F0B => &.{0x516B},
+ 0x2F0C => &.{0x5182},
+ 0x2F0D => &.{0x5196},
+ 0x2F0E => &.{0x51AB},
+ 0x2F0F => &.{0x51E0},
+ 0x2F10 => &.{0x51F5},
+ 0x2F11 => &.{0x5200},
+ 0x2F12 => &.{0x529B},
+ 0x2F13 => &.{0x52F9},
+ 0x2F14 => &.{0x5315},
+ 0x2F15 => &.{0x531A},
+ 0x2F16 => &.{0x5338},
+ 0x2F17 => &.{0x5341},
+ 0x2F18 => &.{0x535C},
+ 0x2F19 => &.{0x5369},
+ 0x2F1A => &.{0x5382},
+ 0x2F1B => &.{0x53B6},
+ 0x2F1C => &.{0x53C8},
+ 0x2F1D => &.{0x53E3},
+ 0x2F1E => &.{0x56D7},
+ 0x2F1F => &.{0x571F},
+ 0x2F20 => &.{0x58EB},
+ 0x2F21 => &.{0x5902},
+ 0x2F22 => &.{0x590A},
+ 0x2F23 => &.{0x5915},
+ 0x2F24 => &.{0x5927},
+ 0x2F25 => &.{0x5973},
+ 0x2F26 => &.{0x5B50},
+ 0x2F27 => &.{0x5B80},
+ 0x2F28 => &.{0x5BF8},
+ 0x2F29 => &.{0x5C0F},
+ 0x2F2A => &.{0x5C22},
+ 0x2F2B => &.{0x5C38},
+ 0x2F2C => &.{0x5C6E},
+ 0x2F2D => &.{0x5C71},
+ 0x2F2E => &.{0x5DDB},
+ 0x2F2F => &.{0x5DE5},
+ 0x2F30 => &.{0x5DF1},
+ 0x2F31 => &.{0x5DFE},
+ 0x2F32 => &.{0x5E72},
+ 0x2F33 => &.{0x5E7A},
+ 0x2F34 => &.{0x5E7F},
+ 0x2F35 => &.{0x5EF4},
+ 0x2F36 => &.{0x5EFE},
+ 0x2F37 => &.{0x5F0B},
+ 0x2F38 => &.{0x5F13},
+ 0x2F39 => &.{0x5F50},
+ 0x2F3A => &.{0x5F61},
+ 0x2F3B => &.{0x5F73},
+ 0x2F3C => &.{0x5FC3},
+ 0x2F3D => &.{0x6208},
+ 0x2F3E => &.{0x6236},
+ 0x2F3F => &.{0x624B},
+ 0x2F40 => &.{0x652F},
+ 0x2F41 => &.{0x6534},
+ 0x2F42 => &.{0x6587},
+ 0x2F43 => &.{0x6597},
+ 0x2F44 => &.{0x65A4},
+ 0x2F45 => &.{0x65B9},
+ 0x2F46 => &.{0x65E0},
+ 0x2F47 => &.{0x65E5},
+ 0x2F48 => &.{0x66F0},
+ 0x2F49 => &.{0x6708},
+ 0x2F4A => &.{0x6728},
+ 0x2F4B => &.{0x6B20},
+ 0x2F4C => &.{0x6B62},
+ 0x2F4D => &.{0x6B79},
+ 0x2F4E => &.{0x6BB3},
+ 0x2F4F => &.{0x6BCB},
+ 0x2F50 => &.{0x6BD4},
+ 0x2F51 => &.{0x6BDB},
+ 0x2F52 => &.{0x6C0F},
+ 0x2F53 => &.{0x6C14},
+ 0x2F54 => &.{0x6C34},
+ 0x2F55 => &.{0x706B},
+ 0x2F56 => &.{0x722A},
+ 0x2F57 => &.{0x7236},
+ 0x2F58 => &.{0x723B},
+ 0x2F59 => &.{0x723F},
+ 0x2F5A => &.{0x7247},
+ 0x2F5B => &.{0x7259},
+ 0x2F5C => &.{0x725B},
+ 0x2F5D => &.{0x72AC},
+ 0x2F5E => &.{0x7384},
+ 0x2F5F => &.{0x7389},
+ 0x2F60 => &.{0x74DC},
+ 0x2F61 => &.{0x74E6},
+ 0x2F62 => &.{0x7518},
+ 0x2F63 => &.{0x751F},
+ 0x2F64 => &.{0x7528},
+ 0x2F65 => &.{0x7530},
+ 0x2F66 => &.{0x758B},
+ 0x2F67 => &.{0x7592},
+ 0x2F68 => &.{0x7676},
+ 0x2F69 => &.{0x767D},
+ 0x2F6A => &.{0x76AE},
+ 0x2F6B => &.{0x76BF},
+ 0x2F6C => &.{0x76EE},
+ 0x2F6D => &.{0x77DB},
+ 0x2F6E => &.{0x77E2},
+ 0x2F6F => &.{0x77F3},
+ 0x2F70 => &.{0x793A},
+ 0x2F71 => &.{0x79B8},
+ 0x2F72 => &.{0x79BE},
+ 0x2F73 => &.{0x7A74},
+ 0x2F74 => &.{0x7ACB},
+ 0x2F75 => &.{0x7AF9},
+ 0x2F76 => &.{0x7C73},
+ 0x2F77 => &.{0x7CF8},
+ 0x2F78 => &.{0x7F36},
+ 0x2F79 => &.{0x7F51},
+ 0x2F7A => &.{0x7F8A},
+ 0x2F7B => &.{0x7FBD},
+ 0x2F7C => &.{0x8001},
+ 0x2F7D => &.{0x800C},
+ 0x2F7E => &.{0x8012},
+ 0x2F7F => &.{0x8033},
+ 0x2F80 => &.{0x807F},
+ 0x2F81 => &.{0x8089},
+ 0x2F82 => &.{0x81E3},
+ 0x2F83 => &.{0x81EA},
+ 0x2F84 => &.{0x81F3},
+ 0x2F85 => &.{0x81FC},
+ 0x2F86 => &.{0x820C},
+ 0x2F87 => &.{0x821B},
+ 0x2F88 => &.{0x821F},
+ 0x2F89 => &.{0x826E},
+ 0x2F8A => &.{0x8272},
+ 0x2F8B => &.{0x8278},
+ 0x2F8C => &.{0x864D},
+ 0x2F8D => &.{0x866B},
+ 0x2F8E => &.{0x8840},
+ 0x2F8F => &.{0x884C},
+ 0x2F90 => &.{0x8863},
+ 0x2F91 => &.{0x897E},
+ 0x2F92 => &.{0x898B},
+ 0x2F93 => &.{0x89D2},
+ 0x2F94 => &.{0x8A00},
+ 0x2F95 => &.{0x8C37},
+ 0x2F96 => &.{0x8C46},
+ 0x2F97 => &.{0x8C55},
+ 0x2F98 => &.{0x8C78},
+ 0x2F99 => &.{0x8C9D},
+ 0x2F9A => &.{0x8D64},
+ 0x2F9B => &.{0x8D70},
+ 0x2F9C => &.{0x8DB3},
+ 0x2F9D => &.{0x8EAB},
+ 0x2F9E => &.{0x8ECA},
+ 0x2F9F => &.{0x8F9B},
+ 0x2FA0 => &.{0x8FB0},
+ 0x2FA1 => &.{0x8FB5},
+ 0x2FA2 => &.{0x9091},
+ 0x2FA3 => &.{0x9149},
+ 0x2FA4 => &.{0x91C6},
+ 0x2FA5 => &.{0x91CC},
+ 0x2FA6 => &.{0x91D1},
+ 0x2FA7 => &.{0x9577},
+ 0x2FA8 => &.{0x9580},
+ 0x2FA9 => &.{0x961C},
+ 0x2FAA => &.{0x96B6},
+ 0x2FAB => &.{0x96B9},
+ 0x2FAC => &.{0x96E8},
+ 0x2FAD => &.{0x9751},
+ 0x2FAE => &.{0x975E},
+ 0x2FAF => &.{0x9762},
+ 0x2FB0 => &.{0x9769},
+ 0x2FB1 => &.{0x97CB},
+ 0x2FB2 => &.{0x97ED},
+ 0x2FB3 => &.{0x97F3},
+ 0x2FB4 => &.{0x9801},
+ 0x2FB5 => &.{0x98A8},
+ 0x2FB6 => &.{0x98DB},
+ 0x2FB7 => &.{0x98DF},
+ 0x2FB8 => &.{0x9996},
+ 0x2FB9 => &.{0x9999},
+ 0x2FBA => &.{0x99AC},
+ 0x2FBB => &.{0x9AA8},
+ 0x2FBC => &.{0x9AD8},
+ 0x2FBD => &.{0x9ADF},
+ 0x2FBE => &.{0x9B25},
+ 0x2FBF => &.{0x9B2F},
+ 0x2FC0 => &.{0x9B32},
+ 0x2FC1 => &.{0x9B3C},
+ 0x2FC2 => &.{0x9B5A},
+ 0x2FC3 => &.{0x9CE5},
+ 0x2FC4 => &.{0x9E75},
+ 0x2FC5 => &.{0x9E7F},
+ 0x2FC6 => &.{0x9EA5},
+ 0x2FC7 => &.{0x9EBB},
+ 0x2FC8 => &.{0x9EC3},
+ 0x2FC9 => &.{0x9ECD},
+ 0x2FCA => &.{0x9ED1},
+ 0x2FCB => &.{0x9EF9},
+ 0x2FCC => &.{0x9EFD},
+ 0x2FCD => &.{0x9F0E},
+ 0x2FCE => &.{0x9F13},
+ 0x2FCF => &.{0x9F20},
+ 0x2FD0 => &.{0x9F3B},
+ 0x2FD1 => &.{0x9F4A},
+ 0x2FD2 => &.{0x9F52},
+ 0x2FD3 => &.{0x9F8D},
+ 0x2FD4 => &.{0x9F9C},
+ 0x2FD5 => &.{0x9FA0},
+ 0x3000 => &.{0x20},
+ 0x3036 => &.{0x3012},
+ 0x3038 => &.{0x5341},
+ 0x3039 => &.{0x5344},
+ 0x303A => &.{0x5345},
+ 0x309B => &.{ 0x20, 0x3099 },
+ 0x309C => &.{ 0x20, 0x309A },
+ 0x309F => &.{ 0x3088, 0x308A },
+ 0x30FF => &.{ 0x30B3, 0x30C8 },
+ 0x3131 => &.{0x1100},
+ 0x3132 => &.{0x1101},
+ 0x3133 => &.{0x11AA},
+ 0x3134 => &.{0x1102},
+ 0x3135 => &.{0x11AC},
+ 0x3136 => &.{0x11AD},
+ 0x3137 => &.{0x1103},
+ 0x3138 => &.{0x1104},
+ 0x3139 => &.{0x1105},
+ 0x313A => &.{0x11B0},
+ 0x313B => &.{0x11B1},
+ 0x313C => &.{0x11B2},
+ 0x313D => &.{0x11B3},
+ 0x313E => &.{0x11B4},
+ 0x313F => &.{0x11B5},
+ 0x3140 => &.{0x111A},
+ 0x3141 => &.{0x1106},
+ 0x3142 => &.{0x1107},
+ 0x3143 => &.{0x1108},
+ 0x3144 => &.{0x1121},
+ 0x3145 => &.{0x1109},
+ 0x3146 => &.{0x110A},
+ 0x3147 => &.{0x110B},
+ 0x3148 => &.{0x110C},
+ 0x3149 => &.{0x110D},
+ 0x314A => &.{0x110E},
+ 0x314B => &.{0x110F},
+ 0x314C => &.{0x1110},
+ 0x314D => &.{0x1111},
+ 0x314E => &.{0x1112},
+ 0x314F => &.{0x1161},
+ 0x3150 => &.{0x1162},
+ 0x3151 => &.{0x1163},
+ 0x3152 => &.{0x1164},
+ 0x3153 => &.{0x1165},
+ 0x3154 => &.{0x1166},
+ 0x3155 => &.{0x1167},
+ 0x3156 => &.{0x1168},
+ 0x3157 => &.{0x1169},
+ 0x3158 => &.{0x116A},
+ 0x3159 => &.{0x116B},
+ 0x315A => &.{0x116C},
+ 0x315B => &.{0x116D},
+ 0x315C => &.{0x116E},
+ 0x315D => &.{0x116F},
+ 0x315E => &.{0x1170},
+ 0x315F => &.{0x1171},
+ 0x3160 => &.{0x1172},
+ 0x3161 => &.{0x1173},
+ 0x3162 => &.{0x1174},
+ 0x3163 => &.{0x1175},
+ 0x3164 => null,
+ 0x3165 => &.{0x1114},
+ 0x3166 => &.{0x1115},
+ 0x3167 => &.{0x11C7},
+ 0x3168 => &.{0x11C8},
+ 0x3169 => &.{0x11CC},
+ 0x316A => &.{0x11CE},
+ 0x316B => &.{0x11D3},
+ 0x316C => &.{0x11D7},
+ 0x316D => &.{0x11D9},
+ 0x316E => &.{0x111C},
+ 0x316F => &.{0x11DD},
+ 0x3170 => &.{0x11DF},
+ 0x3171 => &.{0x111D},
+ 0x3172 => &.{0x111E},
+ 0x3173 => &.{0x1120},
+ 0x3174 => &.{0x1122},
+ 0x3175 => &.{0x1123},
+ 0x3176 => &.{0x1127},
+ 0x3177 => &.{0x1129},
+ 0x3178 => &.{0x112B},
+ 0x3179 => &.{0x112C},
+ 0x317A => &.{0x112D},
+ 0x317B => &.{0x112E},
+ 0x317C => &.{0x112F},
+ 0x317D => &.{0x1132},
+ 0x317E => &.{0x1136},
+ 0x317F => &.{0x1140},
+ 0x3180 => &.{0x1147},
+ 0x3181 => &.{0x114C},
+ 0x3182 => &.{0x11F1},
+ 0x3183 => &.{0x11F2},
+ 0x3184 => &.{0x1157},
+ 0x3185 => &.{0x1158},
+ 0x3186 => &.{0x1159},
+ 0x3187 => &.{0x1184},
+ 0x3188 => &.{0x1185},
+ 0x3189 => &.{0x1188},
+ 0x318A => &.{0x1191},
+ 0x318B => &.{0x1192},
+ 0x318C => &.{0x1194},
+ 0x318D => &.{0x119E},
+ 0x318E => &.{0x11A1},
+ 0x3192 => &.{0x4E00},
+ 0x3193 => &.{0x4E8C},
+ 0x3194 => &.{0x4E09},
+ 0x3195 => &.{0x56DB},
+ 0x3196 => &.{0x4E0A},
+ 0x3197 => &.{0x4E2D},
+ 0x3198 => &.{0x4E0B},
+ 0x3199 => &.{0x7532},
+ 0x319A => &.{0x4E59},
+ 0x319B => &.{0x4E19},
+ 0x319C => &.{0x4E01},
+ 0x319D => &.{0x5929},
+ 0x319E => &.{0x5730},
+ 0x319F => &.{0x4EBA},
+ 0x3200 => &.{ 0x28, 0x1100, 0x29 },
+ 0x3201 => &.{ 0x28, 0x1102, 0x29 },
+ 0x3202 => &.{ 0x28, 0x1103, 0x29 },
+ 0x3203 => &.{ 0x28, 0x1105, 0x29 },
+ 0x3204 => &.{ 0x28, 0x1106, 0x29 },
+ 0x3205 => &.{ 0x28, 0x1107, 0x29 },
+ 0x3206 => &.{ 0x28, 0x1109, 0x29 },
+ 0x3207 => &.{ 0x28, 0x110B, 0x29 },
+ 0x3208 => &.{ 0x28, 0x110C, 0x29 },
+ 0x3209 => &.{ 0x28, 0x110E, 0x29 },
+ 0x320A => &.{ 0x28, 0x110F, 0x29 },
+ 0x320B => &.{ 0x28, 0x1110, 0x29 },
+ 0x320C => &.{ 0x28, 0x1111, 0x29 },
+ 0x320D => &.{ 0x28, 0x1112, 0x29 },
+ 0x320E => &.{ 0x28, 0xAC00, 0x29 },
+ 0x320F => &.{ 0x28, 0xB098, 0x29 },
+ 0x3210 => &.{ 0x28, 0xB2E4, 0x29 },
+ 0x3211 => &.{ 0x28, 0xB77C, 0x29 },
+ 0x3212 => &.{ 0x28, 0xB9C8, 0x29 },
+ 0x3213 => &.{ 0x28, 0xBC14, 0x29 },
+ 0x3214 => &.{ 0x28, 0xC0AC, 0x29 },
+ 0x3215 => &.{ 0x28, 0xC544, 0x29 },
+ 0x3216 => &.{ 0x28, 0xC790, 0x29 },
+ 0x3217 => &.{ 0x28, 0xCC28, 0x29 },
+ 0x3218 => &.{ 0x28, 0xCE74, 0x29 },
+ 0x3219 => &.{ 0x28, 0xD0C0, 0x29 },
+ 0x321A => &.{ 0x28, 0xD30C, 0x29 },
+ 0x321B => &.{ 0x28, 0xD558, 0x29 },
+ 0x321C => &.{ 0x28, 0xC8FC, 0x29 },
+ 0x321D => &.{ 0x28, 0xC624, 0xC804, 0x29 },
+ 0x321E => &.{ 0x28, 0xC624, 0xD6C4, 0x29 },
+ 0x3220 => &.{ 0x28, 0x4E00, 0x29 },
+ 0x3221 => &.{ 0x28, 0x4E8C, 0x29 },
+ 0x3222 => &.{ 0x28, 0x4E09, 0x29 },
+ 0x3223 => &.{ 0x28, 0x56DB, 0x29 },
+ 0x3224 => &.{ 0x28, 0x4E94, 0x29 },
+ 0x3225 => &.{ 0x28, 0x516D, 0x29 },
+ 0x3226 => &.{ 0x28, 0x4E03, 0x29 },
+ 0x3227 => &.{ 0x28, 0x516B, 0x29 },
+ 0x3228 => &.{ 0x28, 0x4E5D, 0x29 },
+ 0x3229 => &.{ 0x28, 0x5341, 0x29 },
+ 0x322A => &.{ 0x28, 0x6708, 0x29 },
+ 0x322B => &.{ 0x28, 0x706B, 0x29 },
+ 0x322C => &.{ 0x28, 0x6C34, 0x29 },
+ 0x322D => &.{ 0x28, 0x6728, 0x29 },
+ 0x322E => &.{ 0x28, 0x91D1, 0x29 },
+ 0x322F => &.{ 0x28, 0x571F, 0x29 },
+ 0x3230 => &.{ 0x28, 0x65E5, 0x29 },
+ 0x3231 => &.{ 0x28, 0x682A, 0x29 },
+ 0x3232 => &.{ 0x28, 0x6709, 0x29 },
+ 0x3233 => &.{ 0x28, 0x793E, 0x29 },
+ 0x3234 => &.{ 0x28, 0x540D, 0x29 },
+ 0x3235 => &.{ 0x28, 0x7279, 0x29 },
+ 0x3236 => &.{ 0x28, 0x8CA1, 0x29 },
+ 0x3237 => &.{ 0x28, 0x795D, 0x29 },
+ 0x3238 => &.{ 0x28, 0x52B4, 0x29 },
+ 0x3239 => &.{ 0x28, 0x4EE3, 0x29 },
+ 0x323A => &.{ 0x28, 0x547C, 0x29 },
+ 0x323B => &.{ 0x28, 0x5B66, 0x29 },
+ 0x323C => &.{ 0x28, 0x76E3, 0x29 },
+ 0x323D => &.{ 0x28, 0x4F01, 0x29 },
+ 0x323E => &.{ 0x28, 0x8CC7, 0x29 },
+ 0x323F => &.{ 0x28, 0x5354, 0x29 },
+ 0x3240 => &.{ 0x28, 0x796D, 0x29 },
+ 0x3241 => &.{ 0x28, 0x4F11, 0x29 },
+ 0x3242 => &.{ 0x28, 0x81EA, 0x29 },
+ 0x3243 => &.{ 0x28, 0x81F3, 0x29 },
+ 0x3244 => &.{0x554F},
+ 0x3245 => &.{0x5E7C},
+ 0x3246 => &.{0x6587},
+ 0x3247 => &.{0x7B8F},
+ 0x3250 => &.{ 0x70, 0x74, 0x65 },
+ 0x3251 => &.{ 0x32, 0x31 },
+ 0x3252 => &.{ 0x32, 0x32 },
+ 0x3253 => &.{ 0x32, 0x33 },
+ 0x3254 => &.{ 0x32, 0x34 },
+ 0x3255 => &.{ 0x32, 0x35 },
+ 0x3256 => &.{ 0x32, 0x36 },
+ 0x3257 => &.{ 0x32, 0x37 },
+ 0x3258 => &.{ 0x32, 0x38 },
+ 0x3259 => &.{ 0x32, 0x39 },
+ 0x325A => &.{ 0x33, 0x30 },
+ 0x325B => &.{ 0x33, 0x31 },
+ 0x325C => &.{ 0x33, 0x32 },
+ 0x325D => &.{ 0x33, 0x33 },
+ 0x325E => &.{ 0x33, 0x34 },
+ 0x325F => &.{ 0x33, 0x35 },
+ 0x3260 => &.{0x1100},
+ 0x3261 => &.{0x1102},
+ 0x3262 => &.{0x1103},
+ 0x3263 => &.{0x1105},
+ 0x3264 => &.{0x1106},
+ 0x3265 => &.{0x1107},
+ 0x3266 => &.{0x1109},
+ 0x3267 => &.{0x110B},
+ 0x3268 => &.{0x110C},
+ 0x3269 => &.{0x110E},
+ 0x326A => &.{0x110F},
+ 0x326B => &.{0x1110},
+ 0x326C => &.{0x1111},
+ 0x326D => &.{0x1112},
+ 0x326E => &.{0xAC00},
+ 0x326F => &.{0xB098},
+ 0x3270 => &.{0xB2E4},
+ 0x3271 => &.{0xB77C},
+ 0x3272 => &.{0xB9C8},
+ 0x3273 => &.{0xBC14},
+ 0x3274 => &.{0xC0AC},
+ 0x3275 => &.{0xC544},
+ 0x3276 => &.{0xC790},
+ 0x3277 => &.{0xCC28},
+ 0x3278 => &.{0xCE74},
+ 0x3279 => &.{0xD0C0},
+ 0x327A => &.{0xD30C},
+ 0x327B => &.{0xD558},
+ 0x327C => &.{ 0xCC38, 0xACE0 },
+ 0x327D => &.{ 0xC8FC, 0xC758 },
+ 0x327E => &.{0xC6B0},
+ 0x3280 => &.{0x4E00},
+ 0x3281 => &.{0x4E8C},
+ 0x3282 => &.{0x4E09},
+ 0x3283 => &.{0x56DB},
+ 0x3284 => &.{0x4E94},
+ 0x3285 => &.{0x516D},
+ 0x3286 => &.{0x4E03},
+ 0x3287 => &.{0x516B},
+ 0x3288 => &.{0x4E5D},
+ 0x3289 => &.{0x5341},
+ 0x328A => &.{0x6708},
+ 0x328B => &.{0x706B},
+ 0x328C => &.{0x6C34},
+ 0x328D => &.{0x6728},
+ 0x328E => &.{0x91D1},
+ 0x328F => &.{0x571F},
+ 0x3290 => &.{0x65E5},
+ 0x3291 => &.{0x682A},
+ 0x3292 => &.{0x6709},
+ 0x3293 => &.{0x793E},
+ 0x3294 => &.{0x540D},
+ 0x3295 => &.{0x7279},
+ 0x3296 => &.{0x8CA1},
+ 0x3297 => &.{0x795D},
+ 0x3298 => &.{0x52B4},
+ 0x3299 => &.{0x79D8},
+ 0x329A => &.{0x7537},
+ 0x329B => &.{0x5973},
+ 0x329C => &.{0x9069},
+ 0x329D => &.{0x512A},
+ 0x329E => &.{0x5370},
+ 0x329F => &.{0x6CE8},
+ 0x32A0 => &.{0x9805},
+ 0x32A1 => &.{0x4F11},
+ 0x32A2 => &.{0x5199},
+ 0x32A3 => &.{0x6B63},
+ 0x32A4 => &.{0x4E0A},
+ 0x32A5 => &.{0x4E2D},
+ 0x32A6 => &.{0x4E0B},
+ 0x32A7 => &.{0x5DE6},
+ 0x32A8 => &.{0x53F3},
+ 0x32A9 => &.{0x533B},
+ 0x32AA => &.{0x5B97},
+ 0x32AB => &.{0x5B66},
+ 0x32AC => &.{0x76E3},
+ 0x32AD => &.{0x4F01},
+ 0x32AE => &.{0x8CC7},
+ 0x32AF => &.{0x5354},
+ 0x32B0 => &.{0x591C},
+ 0x32B1 => &.{ 0x33, 0x36 },
+ 0x32B2 => &.{ 0x33, 0x37 },
+ 0x32B3 => &.{ 0x33, 0x38 },
+ 0x32B4 => &.{ 0x33, 0x39 },
+ 0x32B5 => &.{ 0x34, 0x30 },
+ 0x32B6 => &.{ 0x34, 0x31 },
+ 0x32B7 => &.{ 0x34, 0x32 },
+ 0x32B8 => &.{ 0x34, 0x33 },
+ 0x32B9 => &.{ 0x34, 0x34 },
+ 0x32BA => &.{ 0x34, 0x35 },
+ 0x32BB => &.{ 0x34, 0x36 },
+ 0x32BC => &.{ 0x34, 0x37 },
+ 0x32BD => &.{ 0x34, 0x38 },
+ 0x32BE => &.{ 0x34, 0x39 },
+ 0x32BF => &.{ 0x35, 0x30 },
+ 0x32C0 => &.{ 0x31, 0x6708 },
+ 0x32C1 => &.{ 0x32, 0x6708 },
+ 0x32C2 => &.{ 0x33, 0x6708 },
+ 0x32C3 => &.{ 0x34, 0x6708 },
+ 0x32C4 => &.{ 0x35, 0x6708 },
+ 0x32C5 => &.{ 0x36, 0x6708 },
+ 0x32C6 => &.{ 0x37, 0x6708 },
+ 0x32C7 => &.{ 0x38, 0x6708 },
+ 0x32C8 => &.{ 0x39, 0x6708 },
+ 0x32C9 => &.{ 0x31, 0x30, 0x6708 },
+ 0x32CA => &.{ 0x31, 0x31, 0x6708 },
+ 0x32CB => &.{ 0x31, 0x32, 0x6708 },
+ 0x32CC => &.{ 0x68, 0x67 },
+ 0x32CD => &.{ 0x65, 0x72, 0x67 },
+ 0x32CE => &.{ 0x65, 0x76 },
+ 0x32CF => &.{ 0x6C, 0x74, 0x64 },
+ 0x32D0 => &.{0x30A2},
+ 0x32D1 => &.{0x30A4},
+ 0x32D2 => &.{0x30A6},
+ 0x32D3 => &.{0x30A8},
+ 0x32D4 => &.{0x30AA},
+ 0x32D5 => &.{0x30AB},
+ 0x32D6 => &.{0x30AD},
+ 0x32D7 => &.{0x30AF},
+ 0x32D8 => &.{0x30B1},
+ 0x32D9 => &.{0x30B3},
+ 0x32DA => &.{0x30B5},
+ 0x32DB => &.{0x30B7},
+ 0x32DC => &.{0x30B9},
+ 0x32DD => &.{0x30BB},
+ 0x32DE => &.{0x30BD},
+ 0x32DF => &.{0x30BF},
+ 0x32E0 => &.{0x30C1},
+ 0x32E1 => &.{0x30C4},
+ 0x32E2 => &.{0x30C6},
+ 0x32E3 => &.{0x30C8},
+ 0x32E4 => &.{0x30CA},
+ 0x32E5 => &.{0x30CB},
+ 0x32E6 => &.{0x30CC},
+ 0x32E7 => &.{0x30CD},
+ 0x32E8 => &.{0x30CE},
+ 0x32E9 => &.{0x30CF},
+ 0x32EA => &.{0x30D2},
+ 0x32EB => &.{0x30D5},
+ 0x32EC => &.{0x30D8},
+ 0x32ED => &.{0x30DB},
+ 0x32EE => &.{0x30DE},
+ 0x32EF => &.{0x30DF},
+ 0x32F0 => &.{0x30E0},
+ 0x32F1 => &.{0x30E1},
+ 0x32F2 => &.{0x30E2},
+ 0x32F3 => &.{0x30E4},
+ 0x32F4 => &.{0x30E6},
+ 0x32F5 => &.{0x30E8},
+ 0x32F6 => &.{0x30E9},
+ 0x32F7 => &.{0x30EA},
+ 0x32F8 => &.{0x30EB},
+ 0x32F9 => &.{0x30EC},
+ 0x32FA => &.{0x30ED},
+ 0x32FB => &.{0x30EF},
+ 0x32FC => &.{0x30F0},
+ 0x32FD => &.{0x30F1},
+ 0x32FE => &.{0x30F2},
+ 0x32FF => &.{ 0x4EE4, 0x548C },
+ 0x3300 => &.{ 0x30A2, 0x30D1, 0x30FC, 0x30C8 },
+ 0x3301 => &.{ 0x30A2, 0x30EB, 0x30D5, 0x30A1 },
+ 0x3302 => &.{ 0x30A2, 0x30F3, 0x30DA, 0x30A2 },
+ 0x3303 => &.{ 0x30A2, 0x30FC, 0x30EB },
+ 0x3304 => &.{ 0x30A4, 0x30CB, 0x30F3, 0x30B0 },
+ 0x3305 => &.{ 0x30A4, 0x30F3, 0x30C1 },
+ 0x3306 => &.{ 0x30A6, 0x30A9, 0x30F3 },
+ 0x3307 => &.{ 0x30A8, 0x30B9, 0x30AF, 0x30FC, 0x30C9 },
+ 0x3308 => &.{ 0x30A8, 0x30FC, 0x30AB, 0x30FC },
+ 0x3309 => &.{ 0x30AA, 0x30F3, 0x30B9 },
+ 0x330A => &.{ 0x30AA, 0x30FC, 0x30E0 },
+ 0x330B => &.{ 0x30AB, 0x30A4, 0x30EA },
+ 0x330C => &.{ 0x30AB, 0x30E9, 0x30C3, 0x30C8 },
+ 0x330D => &.{ 0x30AB, 0x30ED, 0x30EA, 0x30FC },
+ 0x330E => &.{ 0x30AC, 0x30ED, 0x30F3 },
+ 0x330F => &.{ 0x30AC, 0x30F3, 0x30DE },
+ 0x3310 => &.{ 0x30AE, 0x30AC },
+ 0x3311 => &.{ 0x30AE, 0x30CB, 0x30FC },
+ 0x3312 => &.{ 0x30AD, 0x30E5, 0x30EA, 0x30FC },
+ 0x3313 => &.{ 0x30AE, 0x30EB, 0x30C0, 0x30FC },
+ 0x3314 => &.{ 0x30AD, 0x30ED },
+ 0x3315 => &.{ 0x30AD, 0x30ED, 0x30B0, 0x30E9, 0x30E0 },
+ 0x3316 => &.{ 0x30AD, 0x30ED, 0x30E1, 0x30FC, 0x30C8, 0x30EB },
+ 0x3317 => &.{ 0x30AD, 0x30ED, 0x30EF, 0x30C3, 0x30C8 },
+ 0x3318 => &.{ 0x30B0, 0x30E9, 0x30E0 },
+ 0x3319 => &.{ 0x30B0, 0x30E9, 0x30E0, 0x30C8, 0x30F3 },
+ 0x331A => &.{ 0x30AF, 0x30EB, 0x30BC, 0x30A4, 0x30ED },
+ 0x331B => &.{ 0x30AF, 0x30ED, 0x30FC, 0x30CD },
+ 0x331C => &.{ 0x30B1, 0x30FC, 0x30B9 },
+ 0x331D => &.{ 0x30B3, 0x30EB, 0x30CA },
+ 0x331E => &.{ 0x30B3, 0x30FC, 0x30DD },
+ 0x331F => &.{ 0x30B5, 0x30A4, 0x30AF, 0x30EB },
+ 0x3320 => &.{ 0x30B5, 0x30F3, 0x30C1, 0x30FC, 0x30E0 },
+ 0x3321 => &.{ 0x30B7, 0x30EA, 0x30F3, 0x30B0 },
+ 0x3322 => &.{ 0x30BB, 0x30F3, 0x30C1 },
+ 0x3323 => &.{ 0x30BB, 0x30F3, 0x30C8 },
+ 0x3324 => &.{ 0x30C0, 0x30FC, 0x30B9 },
+ 0x3325 => &.{ 0x30C7, 0x30B7 },
+ 0x3326 => &.{ 0x30C9, 0x30EB },
+ 0x3327 => &.{ 0x30C8, 0x30F3 },
+ 0x3328 => &.{ 0x30CA, 0x30CE },
+ 0x3329 => &.{ 0x30CE, 0x30C3, 0x30C8 },
+ 0x332A => &.{ 0x30CF, 0x30A4, 0x30C4 },
+ 0x332B => &.{ 0x30D1, 0x30FC, 0x30BB, 0x30F3, 0x30C8 },
+ 0x332C => &.{ 0x30D1, 0x30FC, 0x30C4 },
+ 0x332D => &.{ 0x30D0, 0x30FC, 0x30EC, 0x30EB },
+ 0x332E => &.{ 0x30D4, 0x30A2, 0x30B9, 0x30C8, 0x30EB },
+ 0x332F => &.{ 0x30D4, 0x30AF, 0x30EB },
+ 0x3330 => &.{ 0x30D4, 0x30B3 },
+ 0x3331 => &.{ 0x30D3, 0x30EB },
+ 0x3332 => &.{ 0x30D5, 0x30A1, 0x30E9, 0x30C3, 0x30C9 },
+ 0x3333 => &.{ 0x30D5, 0x30A3, 0x30FC, 0x30C8 },
+ 0x3334 => &.{ 0x30D6, 0x30C3, 0x30B7, 0x30A7, 0x30EB },
+ 0x3335 => &.{ 0x30D5, 0x30E9, 0x30F3 },
+ 0x3336 => &.{ 0x30D8, 0x30AF, 0x30BF, 0x30FC, 0x30EB },
+ 0x3337 => &.{ 0x30DA, 0x30BD },
+ 0x3338 => &.{ 0x30DA, 0x30CB, 0x30D2 },
+ 0x3339 => &.{ 0x30D8, 0x30EB, 0x30C4 },
+ 0x333A => &.{ 0x30DA, 0x30F3, 0x30B9 },
+ 0x333B => &.{ 0x30DA, 0x30FC, 0x30B8 },
+ 0x333C => &.{ 0x30D9, 0x30FC, 0x30BF },
+ 0x333D => &.{ 0x30DD, 0x30A4, 0x30F3, 0x30C8 },
+ 0x333E => &.{ 0x30DC, 0x30EB, 0x30C8 },
+ 0x333F => &.{ 0x30DB, 0x30F3 },
+ 0x3340 => &.{ 0x30DD, 0x30F3, 0x30C9 },
+ 0x3341 => &.{ 0x30DB, 0x30FC, 0x30EB },
+ 0x3342 => &.{ 0x30DB, 0x30FC, 0x30F3 },
+ 0x3343 => &.{ 0x30DE, 0x30A4, 0x30AF, 0x30ED },
+ 0x3344 => &.{ 0x30DE, 0x30A4, 0x30EB },
+ 0x3345 => &.{ 0x30DE, 0x30C3, 0x30CF },
+ 0x3346 => &.{ 0x30DE, 0x30EB, 0x30AF },
+ 0x3347 => &.{ 0x30DE, 0x30F3, 0x30B7, 0x30E7, 0x30F3 },
+ 0x3348 => &.{ 0x30DF, 0x30AF, 0x30ED, 0x30F3 },
+ 0x3349 => &.{ 0x30DF, 0x30EA },
+ 0x334A => &.{ 0x30DF, 0x30EA, 0x30D0, 0x30FC, 0x30EB },
+ 0x334B => &.{ 0x30E1, 0x30AC },
+ 0x334C => &.{ 0x30E1, 0x30AC, 0x30C8, 0x30F3 },
+ 0x334D => &.{ 0x30E1, 0x30FC, 0x30C8, 0x30EB },
+ 0x334E => &.{ 0x30E4, 0x30FC, 0x30C9 },
+ 0x334F => &.{ 0x30E4, 0x30FC, 0x30EB },
+ 0x3350 => &.{ 0x30E6, 0x30A2, 0x30F3 },
+ 0x3351 => &.{ 0x30EA, 0x30C3, 0x30C8, 0x30EB },
+ 0x3352 => &.{ 0x30EA, 0x30E9 },
+ 0x3353 => &.{ 0x30EB, 0x30D4, 0x30FC },
+ 0x3354 => &.{ 0x30EB, 0x30FC, 0x30D6, 0x30EB },
+ 0x3355 => &.{ 0x30EC, 0x30E0 },
+ 0x3356 => &.{ 0x30EC, 0x30F3, 0x30C8, 0x30B2, 0x30F3 },
+ 0x3357 => &.{ 0x30EF, 0x30C3, 0x30C8 },
+ 0x3358 => &.{ 0x30, 0x70B9 },
+ 0x3359 => &.{ 0x31, 0x70B9 },
+ 0x335A => &.{ 0x32, 0x70B9 },
+ 0x335B => &.{ 0x33, 0x70B9 },
+ 0x335C => &.{ 0x34, 0x70B9 },
+ 0x335D => &.{ 0x35, 0x70B9 },
+ 0x335E => &.{ 0x36, 0x70B9 },
+ 0x335F => &.{ 0x37, 0x70B9 },
+ 0x3360 => &.{ 0x38, 0x70B9 },
+ 0x3361 => &.{ 0x39, 0x70B9 },
+ 0x3362 => &.{ 0x31, 0x30, 0x70B9 },
+ 0x3363 => &.{ 0x31, 0x31, 0x70B9 },
+ 0x3364 => &.{ 0x31, 0x32, 0x70B9 },
+ 0x3365 => &.{ 0x31, 0x33, 0x70B9 },
+ 0x3366 => &.{ 0x31, 0x34, 0x70B9 },
+ 0x3367 => &.{ 0x31, 0x35, 0x70B9 },
+ 0x3368 => &.{ 0x31, 0x36, 0x70B9 },
+ 0x3369 => &.{ 0x31, 0x37, 0x70B9 },
+ 0x336A => &.{ 0x31, 0x38, 0x70B9 },
+ 0x336B => &.{ 0x31, 0x39, 0x70B9 },
+ 0x336C => &.{ 0x32, 0x30, 0x70B9 },
+ 0x336D => &.{ 0x32, 0x31, 0x70B9 },
+ 0x336E => &.{ 0x32, 0x32, 0x70B9 },
+ 0x336F => &.{ 0x32, 0x33, 0x70B9 },
+ 0x3370 => &.{ 0x32, 0x34, 0x70B9 },
+ 0x3371 => &.{ 0x68, 0x70, 0x61 },
+ 0x3372 => &.{ 0x64, 0x61 },
+ 0x3373 => &.{ 0x61, 0x75 },
+ 0x3374 => &.{ 0x62, 0x61, 0x72 },
+ 0x3375 => &.{ 0x6F, 0x76 },
+ 0x3376 => &.{ 0x70, 0x63 },
+ 0x3377 => &.{ 0x64, 0x6D },
+ 0x3378 => &.{ 0x64, 0x6D, 0x32 },
+ 0x3379 => &.{ 0x64, 0x6D, 0x33 },
+ 0x337A => &.{ 0x69, 0x75 },
+ 0x337B => &.{ 0x5E73, 0x6210 },
+ 0x337C => &.{ 0x662D, 0x548C },
+ 0x337D => &.{ 0x5927, 0x6B63 },
+ 0x337E => &.{ 0x660E, 0x6CBB },
+ 0x337F => &.{ 0x682A, 0x5F0F, 0x4F1A, 0x793E },
+ 0x3380 => &.{ 0x70, 0x61 },
+ 0x3381 => &.{ 0x6E, 0x61 },
+ 0x3382 => &.{ 0x3BC, 0x61 },
+ 0x3383 => &.{ 0x6D, 0x61 },
+ 0x3384 => &.{ 0x6B, 0x61 },
+ 0x3385 => &.{ 0x6B, 0x62 },
+ 0x3386 => &.{ 0x6D, 0x62 },
+ 0x3387 => &.{ 0x67, 0x62 },
+ 0x3388 => &.{ 0x63, 0x61, 0x6C },
+ 0x3389 => &.{ 0x6B, 0x63, 0x61, 0x6C },
+ 0x338A => &.{ 0x70, 0x66 },
+ 0x338B => &.{ 0x6E, 0x66 },
+ 0x338C => &.{ 0x3BC, 0x66 },
+ 0x338D => &.{ 0x3BC, 0x67 },
+ 0x338E => &.{ 0x6D, 0x67 },
+ 0x338F => &.{ 0x6B, 0x67 },
+ 0x3390 => &.{ 0x68, 0x7A },
+ 0x3391 => &.{ 0x6B, 0x68, 0x7A },
+ 0x3392 => &.{ 0x6D, 0x68, 0x7A },
+ 0x3393 => &.{ 0x67, 0x68, 0x7A },
+ 0x3394 => &.{ 0x74, 0x68, 0x7A },
+ 0x3395 => &.{ 0x3BC, 0x6C },
+ 0x3396 => &.{ 0x6D, 0x6C },
+ 0x3397 => &.{ 0x64, 0x6C },
+ 0x3398 => &.{ 0x6B, 0x6C },
+ 0x3399 => &.{ 0x66, 0x6D },
+ 0x339A => &.{ 0x6E, 0x6D },
+ 0x339B => &.{ 0x3BC, 0x6D },
+ 0x339C => &.{ 0x6D, 0x6D },
+ 0x339D => &.{ 0x63, 0x6D },
+ 0x339E => &.{ 0x6B, 0x6D },
+ 0x339F => &.{ 0x6D, 0x6D, 0x32 },
+ 0x33A0 => &.{ 0x63, 0x6D, 0x32 },
+ 0x33A1 => &.{ 0x6D, 0x32 },
+ 0x33A2 => &.{ 0x6B, 0x6D, 0x32 },
+ 0x33A3 => &.{ 0x6D, 0x6D, 0x33 },
+ 0x33A4 => &.{ 0x63, 0x6D, 0x33 },
+ 0x33A5 => &.{ 0x6D, 0x33 },
+ 0x33A6 => &.{ 0x6B, 0x6D, 0x33 },
+ 0x33A7 => &.{ 0x6D, 0x2215, 0x73 },
+ 0x33A8 => &.{ 0x6D, 0x2215, 0x73, 0x32 },
+ 0x33A9 => &.{ 0x70, 0x61 },
+ 0x33AA => &.{ 0x6B, 0x70, 0x61 },
+ 0x33AB => &.{ 0x6D, 0x70, 0x61 },
+ 0x33AC => &.{ 0x67, 0x70, 0x61 },
+ 0x33AD => &.{ 0x72, 0x61, 0x64 },
+ 0x33AE => &.{ 0x72, 0x61, 0x64, 0x2215, 0x73 },
+ 0x33AF => &.{ 0x72, 0x61, 0x64, 0x2215, 0x73, 0x32 },
+ 0x33B0 => &.{ 0x70, 0x73 },
+ 0x33B1 => &.{ 0x6E, 0x73 },
+ 0x33B2 => &.{ 0x3BC, 0x73 },
+ 0x33B3 => &.{ 0x6D, 0x73 },
+ 0x33B4 => &.{ 0x70, 0x76 },
+ 0x33B5 => &.{ 0x6E, 0x76 },
+ 0x33B6 => &.{ 0x3BC, 0x76 },
+ 0x33B7 => &.{ 0x6D, 0x76 },
+ 0x33B8 => &.{ 0x6B, 0x76 },
+ 0x33B9 => &.{ 0x6D, 0x76 },
+ 0x33BA => &.{ 0x70, 0x77 },
+ 0x33BB => &.{ 0x6E, 0x77 },
+ 0x33BC => &.{ 0x3BC, 0x77 },
+ 0x33BD => &.{ 0x6D, 0x77 },
+ 0x33BE => &.{ 0x6B, 0x77 },
+ 0x33BF => &.{ 0x6D, 0x77 },
+ 0x33C0 => &.{ 0x6B, 0x3C9 },
+ 0x33C1 => &.{ 0x6D, 0x3C9 },
+ 0x33C2 => &.{ 0x61, 0x2E, 0x6D, 0x2E },
+ 0x33C3 => &.{ 0x62, 0x71 },
+ 0x33C4 => &.{ 0x63, 0x63 },
+ 0x33C5 => &.{ 0x63, 0x64 },
+ 0x33C6 => &.{ 0x63, 0x2215, 0x6B, 0x67 },
+ 0x33C7 => &.{ 0x63, 0x6F, 0x2E },
+ 0x33C8 => &.{ 0x64, 0x62 },
+ 0x33C9 => &.{ 0x67, 0x79 },
+ 0x33CA => &.{ 0x68, 0x61 },
+ 0x33CB => &.{ 0x68, 0x70 },
+ 0x33CC => &.{ 0x69, 0x6E },
+ 0x33CD => &.{ 0x6B, 0x6B },
+ 0x33CE => &.{ 0x6B, 0x6D },
+ 0x33CF => &.{ 0x6B, 0x74 },
+ 0x33D0 => &.{ 0x6C, 0x6D },
+ 0x33D1 => &.{ 0x6C, 0x6E },
+ 0x33D2 => &.{ 0x6C, 0x6F, 0x67 },
+ 0x33D3 => &.{ 0x6C, 0x78 },
+ 0x33D4 => &.{ 0x6D, 0x62 },
+ 0x33D5 => &.{ 0x6D, 0x69, 0x6C },
+ 0x33D6 => &.{ 0x6D, 0x6F, 0x6C },
+ 0x33D7 => &.{ 0x70, 0x68 },
+ 0x33D8 => &.{ 0x70, 0x2E, 0x6D, 0x2E },
+ 0x33D9 => &.{ 0x70, 0x70, 0x6D },
+ 0x33DA => &.{ 0x70, 0x72 },
+ 0x33DB => &.{ 0x73, 0x72 },
+ 0x33DC => &.{ 0x73, 0x76 },
+ 0x33DD => &.{ 0x77, 0x62 },
+ 0x33DE => &.{ 0x76, 0x2215, 0x6D },
+ 0x33DF => &.{ 0x61, 0x2215, 0x6D },
+ 0x33E0 => &.{ 0x31, 0x65E5 },
+ 0x33E1 => &.{ 0x32, 0x65E5 },
+ 0x33E2 => &.{ 0x33, 0x65E5 },
+ 0x33E3 => &.{ 0x34, 0x65E5 },
+ 0x33E4 => &.{ 0x35, 0x65E5 },
+ 0x33E5 => &.{ 0x36, 0x65E5 },
+ 0x33E6 => &.{ 0x37, 0x65E5 },
+ 0x33E7 => &.{ 0x38, 0x65E5 },
+ 0x33E8 => &.{ 0x39, 0x65E5 },
+ 0x33E9 => &.{ 0x31, 0x30, 0x65E5 },
+ 0x33EA => &.{ 0x31, 0x31, 0x65E5 },
+ 0x33EB => &.{ 0x31, 0x32, 0x65E5 },
+ 0x33EC => &.{ 0x31, 0x33, 0x65E5 },
+ 0x33ED => &.{ 0x31, 0x34, 0x65E5 },
+ 0x33EE => &.{ 0x31, 0x35, 0x65E5 },
+ 0x33EF => &.{ 0x31, 0x36, 0x65E5 },
+ 0x33F0 => &.{ 0x31, 0x37, 0x65E5 },
+ 0x33F1 => &.{ 0x31, 0x38, 0x65E5 },
+ 0x33F2 => &.{ 0x31, 0x39, 0x65E5 },
+ 0x33F3 => &.{ 0x32, 0x30, 0x65E5 },
+ 0x33F4 => &.{ 0x32, 0x31, 0x65E5 },
+ 0x33F5 => &.{ 0x32, 0x32, 0x65E5 },
+ 0x33F6 => &.{ 0x32, 0x33, 0x65E5 },
+ 0x33F7 => &.{ 0x32, 0x34, 0x65E5 },
+ 0x33F8 => &.{ 0x32, 0x35, 0x65E5 },
+ 0x33F9 => &.{ 0x32, 0x36, 0x65E5 },
+ 0x33FA => &.{ 0x32, 0x37, 0x65E5 },
+ 0x33FB => &.{ 0x32, 0x38, 0x65E5 },
+ 0x33FC => &.{ 0x32, 0x39, 0x65E5 },
+ 0x33FD => &.{ 0x33, 0x30, 0x65E5 },
+ 0x33FE => &.{ 0x33, 0x31, 0x65E5 },
+ 0x33FF => &.{ 0x67, 0x61, 0x6C },
+ 0xA640 => &.{0xA641},
+ 0xA642 => &.{0xA643},
+ 0xA644 => &.{0xA645},
+ 0xA646 => &.{0xA647},
+ 0xA648 => &.{0xA649},
+ 0xA64A => &.{0xA64B},
+ 0xA64C => &.{0xA64D},
+ 0xA64E => &.{0xA64F},
+ 0xA650 => &.{0xA651},
+ 0xA652 => &.{0xA653},
+ 0xA654 => &.{0xA655},
+ 0xA656 => &.{0xA657},
+ 0xA658 => &.{0xA659},
+ 0xA65A => &.{0xA65B},
+ 0xA65C => &.{0xA65D},
+ 0xA65E => &.{0xA65F},
+ 0xA660 => &.{0xA661},
+ 0xA662 => &.{0xA663},
+ 0xA664 => &.{0xA665},
+ 0xA666 => &.{0xA667},
+ 0xA668 => &.{0xA669},
+ 0xA66A => &.{0xA66B},
+ 0xA66C => &.{0xA66D},
+ 0xA680 => &.{0xA681},
+ 0xA682 => &.{0xA683},
+ 0xA684 => &.{0xA685},
+ 0xA686 => &.{0xA687},
+ 0xA688 => &.{0xA689},
+ 0xA68A => &.{0xA68B},
+ 0xA68C => &.{0xA68D},
+ 0xA68E => &.{0xA68F},
+ 0xA690 => &.{0xA691},
+ 0xA692 => &.{0xA693},
+ 0xA694 => &.{0xA695},
+ 0xA696 => &.{0xA697},
+ 0xA698 => &.{0xA699},
+ 0xA69A => &.{0xA69B},
+ 0xA69C => &.{0x44A},
+ 0xA69D => &.{0x44C},
+ 0xA722 => &.{0xA723},
+ 0xA724 => &.{0xA725},
+ 0xA726 => &.{0xA727},
+ 0xA728 => &.{0xA729},
+ 0xA72A => &.{0xA72B},
+ 0xA72C => &.{0xA72D},
+ 0xA72E => &.{0xA72F},
+ 0xA732 => &.{0xA733},
+ 0xA734 => &.{0xA735},
+ 0xA736 => &.{0xA737},
+ 0xA738 => &.{0xA739},
+ 0xA73A => &.{0xA73B},
+ 0xA73C => &.{0xA73D},
+ 0xA73E => &.{0xA73F},
+ 0xA740 => &.{0xA741},
+ 0xA742 => &.{0xA743},
+ 0xA744 => &.{0xA745},
+ 0xA746 => &.{0xA747},
+ 0xA748 => &.{0xA749},
+ 0xA74A => &.{0xA74B},
+ 0xA74C => &.{0xA74D},
+ 0xA74E => &.{0xA74F},
+ 0xA750 => &.{0xA751},
+ 0xA752 => &.{0xA753},
+ 0xA754 => &.{0xA755},
+ 0xA756 => &.{0xA757},
+ 0xA758 => &.{0xA759},
+ 0xA75A => &.{0xA75B},
+ 0xA75C => &.{0xA75D},
+ 0xA75E => &.{0xA75F},
+ 0xA760 => &.{0xA761},
+ 0xA762 => &.{0xA763},
+ 0xA764 => &.{0xA765},
+ 0xA766 => &.{0xA767},
+ 0xA768 => &.{0xA769},
+ 0xA76A => &.{0xA76B},
+ 0xA76C => &.{0xA76D},
+ 0xA76E => &.{0xA76F},
+ 0xA770 => &.{0xA76F},
+ 0xA779 => &.{0xA77A},
+ 0xA77B => &.{0xA77C},
+ 0xA77D => &.{0x1D79},
+ 0xA77E => &.{0xA77F},
+ 0xA780 => &.{0xA781},
+ 0xA782 => &.{0xA783},
+ 0xA784 => &.{0xA785},
+ 0xA786 => &.{0xA787},
+ 0xA78B => &.{0xA78C},
+ 0xA78D => &.{0x265},
+ 0xA790 => &.{0xA791},
+ 0xA792 => &.{0xA793},
+ 0xA796 => &.{0xA797},
+ 0xA798 => &.{0xA799},
+ 0xA79A => &.{0xA79B},
+ 0xA79C => &.{0xA79D},
+ 0xA79E => &.{0xA79F},
+ 0xA7A0 => &.{0xA7A1},
+ 0xA7A2 => &.{0xA7A3},
+ 0xA7A4 => &.{0xA7A5},
+ 0xA7A6 => &.{0xA7A7},
+ 0xA7A8 => &.{0xA7A9},
+ 0xA7AA => &.{0x266},
+ 0xA7AB => &.{0x25C},
+ 0xA7AC => &.{0x261},
+ 0xA7AD => &.{0x26C},
+ 0xA7AE => &.{0x26A},
+ 0xA7B0 => &.{0x29E},
+ 0xA7B1 => &.{0x287},
+ 0xA7B2 => &.{0x29D},
+ 0xA7B3 => &.{0xAB53},
+ 0xA7B4 => &.{0xA7B5},
+ 0xA7B6 => &.{0xA7B7},
+ 0xA7B8 => &.{0xA7B9},
+ 0xA7BA => &.{0xA7BB},
+ 0xA7BC => &.{0xA7BD},
+ 0xA7BE => &.{0xA7BF},
+ 0xA7C0 => &.{0xA7C1},
+ 0xA7C2 => &.{0xA7C3},
+ 0xA7C4 => &.{0xA794},
+ 0xA7C5 => &.{0x282},
+ 0xA7C6 => &.{0x1D8E},
+ 0xA7C7 => &.{0xA7C8},
+ 0xA7C9 => &.{0xA7CA},
+ 0xA7D0 => &.{0xA7D1},
+ 0xA7D6 => &.{0xA7D7},
+ 0xA7D8 => &.{0xA7D9},
+ 0xA7F2 => &.{0x63},
+ 0xA7F3 => &.{0x66},
+ 0xA7F4 => &.{0x71},
+ 0xA7F5 => &.{0xA7F6},
+ 0xA7F8 => &.{0x127},
+ 0xA7F9 => &.{0x153},
+ 0xAB5C => &.{0xA727},
+ 0xAB5D => &.{0xAB37},
+ 0xAB5E => &.{0x26B},
+ 0xAB5F => &.{0xAB52},
+ 0xAB69 => &.{0x28D},
+ 0xAB70 => &.{0x13A0},
+ 0xAB71 => &.{0x13A1},
+ 0xAB72 => &.{0x13A2},
+ 0xAB73 => &.{0x13A3},
+ 0xAB74 => &.{0x13A4},
+ 0xAB75 => &.{0x13A5},
+ 0xAB76 => &.{0x13A6},
+ 0xAB77 => &.{0x13A7},
+ 0xAB78 => &.{0x13A8},
+ 0xAB79 => &.{0x13A9},
+ 0xAB7A => &.{0x13AA},
+ 0xAB7B => &.{0x13AB},
+ 0xAB7C => &.{0x13AC},
+ 0xAB7D => &.{0x13AD},
+ 0xAB7E => &.{0x13AE},
+ 0xAB7F => &.{0x13AF},
+ 0xAB80 => &.{0x13B0},
+ 0xAB81 => &.{0x13B1},
+ 0xAB82 => &.{0x13B2},
+ 0xAB83 => &.{0x13B3},
+ 0xAB84 => &.{0x13B4},
+ 0xAB85 => &.{0x13B5},
+ 0xAB86 => &.{0x13B6},
+ 0xAB87 => &.{0x13B7},
+ 0xAB88 => &.{0x13B8},
+ 0xAB89 => &.{0x13B9},
+ 0xAB8A => &.{0x13BA},
+ 0xAB8B => &.{0x13BB},
+ 0xAB8C => &.{0x13BC},
+ 0xAB8D => &.{0x13BD},
+ 0xAB8E => &.{0x13BE},
+ 0xAB8F => &.{0x13BF},
+ 0xAB90 => &.{0x13C0},
+ 0xAB91 => &.{0x13C1},
+ 0xAB92 => &.{0x13C2},
+ 0xAB93 => &.{0x13C3},
+ 0xAB94 => &.{0x13C4},
+ 0xAB95 => &.{0x13C5},
+ 0xAB96 => &.{0x13C6},
+ 0xAB97 => &.{0x13C7},
+ 0xAB98 => &.{0x13C8},
+ 0xAB99 => &.{0x13C9},
+ 0xAB9A => &.{0x13CA},
+ 0xAB9B => &.{0x13CB},
+ 0xAB9C => &.{0x13CC},
+ 0xAB9D => &.{0x13CD},
+ 0xAB9E => &.{0x13CE},
+ 0xAB9F => &.{0x13CF},
+ 0xABA0 => &.{0x13D0},
+ 0xABA1 => &.{0x13D1},
+ 0xABA2 => &.{0x13D2},
+ 0xABA3 => &.{0x13D3},
+ 0xABA4 => &.{0x13D4},
+ 0xABA5 => &.{0x13D5},
+ 0xABA6 => &.{0x13D6},
+ 0xABA7 => &.{0x13D7},
+ 0xABA8 => &.{0x13D8},
+ 0xABA9 => &.{0x13D9},
+ 0xABAA => &.{0x13DA},
+ 0xABAB => &.{0x13DB},
+ 0xABAC => &.{0x13DC},
+ 0xABAD => &.{0x13DD},
+ 0xABAE => &.{0x13DE},
+ 0xABAF => &.{0x13DF},
+ 0xABB0 => &.{0x13E0},
+ 0xABB1 => &.{0x13E1},
+ 0xABB2 => &.{0x13E2},
+ 0xABB3 => &.{0x13E3},
+ 0xABB4 => &.{0x13E4},
+ 0xABB5 => &.{0x13E5},
+ 0xABB6 => &.{0x13E6},
+ 0xABB7 => &.{0x13E7},
+ 0xABB8 => &.{0x13E8},
+ 0xABB9 => &.{0x13E9},
+ 0xABBA => &.{0x13EA},
+ 0xABBB => &.{0x13EB},
+ 0xABBC => &.{0x13EC},
+ 0xABBD => &.{0x13ED},
+ 0xABBE => &.{0x13EE},
+ 0xABBF => &.{0x13EF},
+ 0xF900 => &.{0x8C48},
+ 0xF901 => &.{0x66F4},
+ 0xF902 => &.{0x8ECA},
+ 0xF903 => &.{0x8CC8},
+ 0xF904 => &.{0x6ED1},
+ 0xF905 => &.{0x4E32},
+ 0xF906 => &.{0x53E5},
+ 0xF907...0xF908 => &.{0x9F9C},
+ 0xF909 => &.{0x5951},
+ 0xF90A => &.{0x91D1},
+ 0xF90B => &.{0x5587},
+ 0xF90C => &.{0x5948},
+ 0xF90D => &.{0x61F6},
+ 0xF90E => &.{0x7669},
+ 0xF90F => &.{0x7F85},
+ 0xF910 => &.{0x863F},
+ 0xF911 => &.{0x87BA},
+ 0xF912 => &.{0x88F8},
+ 0xF913 => &.{0x908F},
+ 0xF914 => &.{0x6A02},
+ 0xF915 => &.{0x6D1B},
+ 0xF916 => &.{0x70D9},
+ 0xF917 => &.{0x73DE},
+ 0xF918 => &.{0x843D},
+ 0xF919 => &.{0x916A},
+ 0xF91A => &.{0x99F1},
+ 0xF91B => &.{0x4E82},
+ 0xF91C => &.{0x5375},
+ 0xF91D => &.{0x6B04},
+ 0xF91E => &.{0x721B},
+ 0xF91F => &.{0x862D},
+ 0xF920 => &.{0x9E1E},
+ 0xF921 => &.{0x5D50},
+ 0xF922 => &.{0x6FEB},
+ 0xF923 => &.{0x85CD},
+ 0xF924 => &.{0x8964},
+ 0xF925 => &.{0x62C9},
+ 0xF926 => &.{0x81D8},
+ 0xF927 => &.{0x881F},
+ 0xF928 => &.{0x5ECA},
+ 0xF929 => &.{0x6717},
+ 0xF92A => &.{0x6D6A},
+ 0xF92B => &.{0x72FC},
+ 0xF92C => &.{0x90CE},
+ 0xF92D => &.{0x4F86},
+ 0xF92E => &.{0x51B7},
+ 0xF92F => &.{0x52DE},
+ 0xF930 => &.{0x64C4},
+ 0xF931 => &.{0x6AD3},
+ 0xF932 => &.{0x7210},
+ 0xF933 => &.{0x76E7},
+ 0xF934 => &.{0x8001},
+ 0xF935 => &.{0x8606},
+ 0xF936 => &.{0x865C},
+ 0xF937 => &.{0x8DEF},
+ 0xF938 => &.{0x9732},
+ 0xF939 => &.{0x9B6F},
+ 0xF93A => &.{0x9DFA},
+ 0xF93B => &.{0x788C},
+ 0xF93C => &.{0x797F},
+ 0xF93D => &.{0x7DA0},
+ 0xF93E => &.{0x83C9},
+ 0xF93F => &.{0x9304},
+ 0xF940 => &.{0x9E7F},
+ 0xF941 => &.{0x8AD6},
+ 0xF942 => &.{0x58DF},
+ 0xF943 => &.{0x5F04},
+ 0xF944 => &.{0x7C60},
+ 0xF945 => &.{0x807E},
+ 0xF946 => &.{0x7262},
+ 0xF947 => &.{0x78CA},
+ 0xF948 => &.{0x8CC2},
+ 0xF949 => &.{0x96F7},
+ 0xF94A => &.{0x58D8},
+ 0xF94B => &.{0x5C62},
+ 0xF94C => &.{0x6A13},
+ 0xF94D => &.{0x6DDA},
+ 0xF94E => &.{0x6F0F},
+ 0xF94F => &.{0x7D2F},
+ 0xF950 => &.{0x7E37},
+ 0xF951 => &.{0x964B},
+ 0xF952 => &.{0x52D2},
+ 0xF953 => &.{0x808B},
+ 0xF954 => &.{0x51DC},
+ 0xF955 => &.{0x51CC},
+ 0xF956 => &.{0x7A1C},
+ 0xF957 => &.{0x7DBE},
+ 0xF958 => &.{0x83F1},
+ 0xF959 => &.{0x9675},
+ 0xF95A => &.{0x8B80},
+ 0xF95B => &.{0x62CF},
+ 0xF95C => &.{0x6A02},
+ 0xF95D => &.{0x8AFE},
+ 0xF95E => &.{0x4E39},
+ 0xF95F => &.{0x5BE7},
+ 0xF960 => &.{0x6012},
+ 0xF961 => &.{0x7387},
+ 0xF962 => &.{0x7570},
+ 0xF963 => &.{0x5317},
+ 0xF964 => &.{0x78FB},
+ 0xF965 => &.{0x4FBF},
+ 0xF966 => &.{0x5FA9},
+ 0xF967 => &.{0x4E0D},
+ 0xF968 => &.{0x6CCC},
+ 0xF969 => &.{0x6578},
+ 0xF96A => &.{0x7D22},
+ 0xF96B => &.{0x53C3},
+ 0xF96C => &.{0x585E},
+ 0xF96D => &.{0x7701},
+ 0xF96E => &.{0x8449},
+ 0xF96F => &.{0x8AAA},
+ 0xF970 => &.{0x6BBA},
+ 0xF971 => &.{0x8FB0},
+ 0xF972 => &.{0x6C88},
+ 0xF973 => &.{0x62FE},
+ 0xF974 => &.{0x82E5},
+ 0xF975 => &.{0x63A0},
+ 0xF976 => &.{0x7565},
+ 0xF977 => &.{0x4EAE},
+ 0xF978 => &.{0x5169},
+ 0xF979 => &.{0x51C9},
+ 0xF97A => &.{0x6881},
+ 0xF97B => &.{0x7CE7},
+ 0xF97C => &.{0x826F},
+ 0xF97D => &.{0x8AD2},
+ 0xF97E => &.{0x91CF},
+ 0xF97F => &.{0x52F5},
+ 0xF980 => &.{0x5442},
+ 0xF981 => &.{0x5973},
+ 0xF982 => &.{0x5EEC},
+ 0xF983 => &.{0x65C5},
+ 0xF984 => &.{0x6FFE},
+ 0xF985 => &.{0x792A},
+ 0xF986 => &.{0x95AD},
+ 0xF987 => &.{0x9A6A},
+ 0xF988 => &.{0x9E97},
+ 0xF989 => &.{0x9ECE},
+ 0xF98A => &.{0x529B},
+ 0xF98B => &.{0x66C6},
+ 0xF98C => &.{0x6B77},
+ 0xF98D => &.{0x8F62},
+ 0xF98E => &.{0x5E74},
+ 0xF98F => &.{0x6190},
+ 0xF990 => &.{0x6200},
+ 0xF991 => &.{0x649A},
+ 0xF992 => &.{0x6F23},
+ 0xF993 => &.{0x7149},
+ 0xF994 => &.{0x7489},
+ 0xF995 => &.{0x79CA},
+ 0xF996 => &.{0x7DF4},
+ 0xF997 => &.{0x806F},
+ 0xF998 => &.{0x8F26},
+ 0xF999 => &.{0x84EE},
+ 0xF99A => &.{0x9023},
+ 0xF99B => &.{0x934A},
+ 0xF99C => &.{0x5217},
+ 0xF99D => &.{0x52A3},
+ 0xF99E => &.{0x54BD},
+ 0xF99F => &.{0x70C8},
+ 0xF9A0 => &.{0x88C2},
+ 0xF9A1 => &.{0x8AAA},
+ 0xF9A2 => &.{0x5EC9},
+ 0xF9A3 => &.{0x5FF5},
+ 0xF9A4 => &.{0x637B},
+ 0xF9A5 => &.{0x6BAE},
+ 0xF9A6 => &.{0x7C3E},
+ 0xF9A7 => &.{0x7375},
+ 0xF9A8 => &.{0x4EE4},
+ 0xF9A9 => &.{0x56F9},
+ 0xF9AA => &.{0x5BE7},
+ 0xF9AB => &.{0x5DBA},
+ 0xF9AC => &.{0x601C},
+ 0xF9AD => &.{0x73B2},
+ 0xF9AE => &.{0x7469},
+ 0xF9AF => &.{0x7F9A},
+ 0xF9B0 => &.{0x8046},
+ 0xF9B1 => &.{0x9234},
+ 0xF9B2 => &.{0x96F6},
+ 0xF9B3 => &.{0x9748},
+ 0xF9B4 => &.{0x9818},
+ 0xF9B5 => &.{0x4F8B},
+ 0xF9B6 => &.{0x79AE},
+ 0xF9B7 => &.{0x91B4},
+ 0xF9B8 => &.{0x96B8},
+ 0xF9B9 => &.{0x60E1},
+ 0xF9BA => &.{0x4E86},
+ 0xF9BB => &.{0x50DA},
+ 0xF9BC => &.{0x5BEE},
+ 0xF9BD => &.{0x5C3F},
+ 0xF9BE => &.{0x6599},
+ 0xF9BF => &.{0x6A02},
+ 0xF9C0 => &.{0x71CE},
+ 0xF9C1 => &.{0x7642},
+ 0xF9C2 => &.{0x84FC},
+ 0xF9C3 => &.{0x907C},
+ 0xF9C4 => &.{0x9F8D},
+ 0xF9C5 => &.{0x6688},
+ 0xF9C6 => &.{0x962E},
+ 0xF9C7 => &.{0x5289},
+ 0xF9C8 => &.{0x677B},
+ 0xF9C9 => &.{0x67F3},
+ 0xF9CA => &.{0x6D41},
+ 0xF9CB => &.{0x6E9C},
+ 0xF9CC => &.{0x7409},
+ 0xF9CD => &.{0x7559},
+ 0xF9CE => &.{0x786B},
+ 0xF9CF => &.{0x7D10},
+ 0xF9D0 => &.{0x985E},
+ 0xF9D1 => &.{0x516D},
+ 0xF9D2 => &.{0x622E},
+ 0xF9D3 => &.{0x9678},
+ 0xF9D4 => &.{0x502B},
+ 0xF9D5 => &.{0x5D19},
+ 0xF9D6 => &.{0x6DEA},
+ 0xF9D7 => &.{0x8F2A},
+ 0xF9D8 => &.{0x5F8B},
+ 0xF9D9 => &.{0x6144},
+ 0xF9DA => &.{0x6817},
+ 0xF9DB => &.{0x7387},
+ 0xF9DC => &.{0x9686},
+ 0xF9DD => &.{0x5229},
+ 0xF9DE => &.{0x540F},
+ 0xF9DF => &.{0x5C65},
+ 0xF9E0 => &.{0x6613},
+ 0xF9E1 => &.{0x674E},
+ 0xF9E2 => &.{0x68A8},
+ 0xF9E3 => &.{0x6CE5},
+ 0xF9E4 => &.{0x7406},
+ 0xF9E5 => &.{0x75E2},
+ 0xF9E6 => &.{0x7F79},
+ 0xF9E7 => &.{0x88CF},
+ 0xF9E8 => &.{0x88E1},
+ 0xF9E9 => &.{0x91CC},
+ 0xF9EA => &.{0x96E2},
+ 0xF9EB => &.{0x533F},
+ 0xF9EC => &.{0x6EBA},
+ 0xF9ED => &.{0x541D},
+ 0xF9EE => &.{0x71D0},
+ 0xF9EF => &.{0x7498},
+ 0xF9F0 => &.{0x85FA},
+ 0xF9F1 => &.{0x96A3},
+ 0xF9F2 => &.{0x9C57},
+ 0xF9F3 => &.{0x9E9F},
+ 0xF9F4 => &.{0x6797},
+ 0xF9F5 => &.{0x6DCB},
+ 0xF9F6 => &.{0x81E8},
+ 0xF9F7 => &.{0x7ACB},
+ 0xF9F8 => &.{0x7B20},
+ 0xF9F9 => &.{0x7C92},
+ 0xF9FA => &.{0x72C0},
+ 0xF9FB => &.{0x7099},
+ 0xF9FC => &.{0x8B58},
+ 0xF9FD => &.{0x4EC0},
+ 0xF9FE => &.{0x8336},
+ 0xF9FF => &.{0x523A},
+ 0xFA00 => &.{0x5207},
+ 0xFA01 => &.{0x5EA6},
+ 0xFA02 => &.{0x62D3},
+ 0xFA03 => &.{0x7CD6},
+ 0xFA04 => &.{0x5B85},
+ 0xFA05 => &.{0x6D1E},
+ 0xFA06 => &.{0x66B4},
+ 0xFA07 => &.{0x8F3B},
+ 0xFA08 => &.{0x884C},
+ 0xFA09 => &.{0x964D},
+ 0xFA0A => &.{0x898B},
+ 0xFA0B => &.{0x5ED3},
+ 0xFA0C => &.{0x5140},
+ 0xFA0D => &.{0x55C0},
+ 0xFA10 => &.{0x585A},
+ 0xFA12 => &.{0x6674},
+ 0xFA15 => &.{0x51DE},
+ 0xFA16 => &.{0x732A},
+ 0xFA17 => &.{0x76CA},
+ 0xFA18 => &.{0x793C},
+ 0xFA19 => &.{0x795E},
+ 0xFA1A => &.{0x7965},
+ 0xFA1B => &.{0x798F},
+ 0xFA1C => &.{0x9756},
+ 0xFA1D => &.{0x7CBE},
+ 0xFA1E => &.{0x7FBD},
+ 0xFA20 => &.{0x8612},
+ 0xFA22 => &.{0x8AF8},
+ 0xFA25 => &.{0x9038},
+ 0xFA26 => &.{0x90FD},
+ 0xFA2A => &.{0x98EF},
+ 0xFA2B => &.{0x98FC},
+ 0xFA2C => &.{0x9928},
+ 0xFA2D => &.{0x9DB4},
+ 0xFA2E => &.{0x90DE},
+ 0xFA2F => &.{0x96B7},
+ 0xFA30 => &.{0x4FAE},
+ 0xFA31 => &.{0x50E7},
+ 0xFA32 => &.{0x514D},
+ 0xFA33 => &.{0x52C9},
+ 0xFA34 => &.{0x52E4},
+ 0xFA35 => &.{0x5351},
+ 0xFA36 => &.{0x559D},
+ 0xFA37 => &.{0x5606},
+ 0xFA38 => &.{0x5668},
+ 0xFA39 => &.{0x5840},
+ 0xFA3A => &.{0x58A8},
+ 0xFA3B => &.{0x5C64},
+ 0xFA3C => &.{0x5C6E},
+ 0xFA3D => &.{0x6094},
+ 0xFA3E => &.{0x6168},
+ 0xFA3F => &.{0x618E},
+ 0xFA40 => &.{0x61F2},
+ 0xFA41 => &.{0x654F},
+ 0xFA42 => &.{0x65E2},
+ 0xFA43 => &.{0x6691},
+ 0xFA44 => &.{0x6885},
+ 0xFA45 => &.{0x6D77},
+ 0xFA46 => &.{0x6E1A},
+ 0xFA47 => &.{0x6F22},
+ 0xFA48 => &.{0x716E},
+ 0xFA49 => &.{0x722B},
+ 0xFA4A => &.{0x7422},
+ 0xFA4B => &.{0x7891},
+ 0xFA4C => &.{0x793E},
+ 0xFA4D => &.{0x7949},
+ 0xFA4E => &.{0x7948},
+ 0xFA4F => &.{0x7950},
+ 0xFA50 => &.{0x7956},
+ 0xFA51 => &.{0x795D},
+ 0xFA52 => &.{0x798D},
+ 0xFA53 => &.{0x798E},
+ 0xFA54 => &.{0x7A40},
+ 0xFA55 => &.{0x7A81},
+ 0xFA56 => &.{0x7BC0},
+ 0xFA57 => &.{0x7DF4},
+ 0xFA58 => &.{0x7E09},
+ 0xFA59 => &.{0x7E41},
+ 0xFA5A => &.{0x7F72},
+ 0xFA5B => &.{0x8005},
+ 0xFA5C => &.{0x81ED},
+ 0xFA5D...0xFA5E => &.{0x8279},
+ 0xFA5F => &.{0x8457},
+ 0xFA60 => &.{0x8910},
+ 0xFA61 => &.{0x8996},
+ 0xFA62 => &.{0x8B01},
+ 0xFA63 => &.{0x8B39},
+ 0xFA64 => &.{0x8CD3},
+ 0xFA65 => &.{0x8D08},
+ 0xFA66 => &.{0x8FB6},
+ 0xFA67 => &.{0x9038},
+ 0xFA68 => &.{0x96E3},
+ 0xFA69 => &.{0x97FF},
+ 0xFA6A => &.{0x983B},
+ 0xFA6B => &.{0x6075},
+ 0xFA6C => &.{0x242EE},
+ 0xFA6D => &.{0x8218},
+ 0xFA70 => &.{0x4E26},
+ 0xFA71 => &.{0x51B5},
+ 0xFA72 => &.{0x5168},
+ 0xFA73 => &.{0x4F80},
+ 0xFA74 => &.{0x5145},
+ 0xFA75 => &.{0x5180},
+ 0xFA76 => &.{0x52C7},
+ 0xFA77 => &.{0x52FA},
+ 0xFA78 => &.{0x559D},
+ 0xFA79 => &.{0x5555},
+ 0xFA7A => &.{0x5599},
+ 0xFA7B => &.{0x55E2},
+ 0xFA7C => &.{0x585A},
+ 0xFA7D => &.{0x58B3},
+ 0xFA7E => &.{0x5944},
+ 0xFA7F => &.{0x5954},
+ 0xFA80 => &.{0x5A62},
+ 0xFA81 => &.{0x5B28},
+ 0xFA82 => &.{0x5ED2},
+ 0xFA83 => &.{0x5ED9},
+ 0xFA84 => &.{0x5F69},
+ 0xFA85 => &.{0x5FAD},
+ 0xFA86 => &.{0x60D8},
+ 0xFA87 => &.{0x614E},
+ 0xFA88 => &.{0x6108},
+ 0xFA89 => &.{0x618E},
+ 0xFA8A => &.{0x6160},
+ 0xFA8B => &.{0x61F2},
+ 0xFA8C => &.{0x6234},
+ 0xFA8D => &.{0x63C4},
+ 0xFA8E => &.{0x641C},
+ 0xFA8F => &.{0x6452},
+ 0xFA90 => &.{0x6556},
+ 0xFA91 => &.{0x6674},
+ 0xFA92 => &.{0x6717},
+ 0xFA93 => &.{0x671B},
+ 0xFA94 => &.{0x6756},
+ 0xFA95 => &.{0x6B79},
+ 0xFA96 => &.{0x6BBA},
+ 0xFA97 => &.{0x6D41},
+ 0xFA98 => &.{0x6EDB},
+ 0xFA99 => &.{0x6ECB},
+ 0xFA9A => &.{0x6F22},
+ 0xFA9B => &.{0x701E},
+ 0xFA9C => &.{0x716E},
+ 0xFA9D => &.{0x77A7},
+ 0xFA9E => &.{0x7235},
+ 0xFA9F => &.{0x72AF},
+ 0xFAA0 => &.{0x732A},
+ 0xFAA1 => &.{0x7471},
+ 0xFAA2 => &.{0x7506},
+ 0xFAA3 => &.{0x753B},
+ 0xFAA4 => &.{0x761D},
+ 0xFAA5 => &.{0x761F},
+ 0xFAA6 => &.{0x76CA},
+ 0xFAA7 => &.{0x76DB},
+ 0xFAA8 => &.{0x76F4},
+ 0xFAA9 => &.{0x774A},
+ 0xFAAA => &.{0x7740},
+ 0xFAAB => &.{0x78CC},
+ 0xFAAC => &.{0x7AB1},
+ 0xFAAD => &.{0x7BC0},
+ 0xFAAE => &.{0x7C7B},
+ 0xFAAF => &.{0x7D5B},
+ 0xFAB0 => &.{0x7DF4},
+ 0xFAB1 => &.{0x7F3E},
+ 0xFAB2 => &.{0x8005},
+ 0xFAB3 => &.{0x8352},
+ 0xFAB4 => &.{0x83EF},
+ 0xFAB5 => &.{0x8779},
+ 0xFAB6 => &.{0x8941},
+ 0xFAB7 => &.{0x8986},
+ 0xFAB8 => &.{0x8996},
+ 0xFAB9 => &.{0x8ABF},
+ 0xFABA => &.{0x8AF8},
+ 0xFABB => &.{0x8ACB},
+ 0xFABC => &.{0x8B01},
+ 0xFABD => &.{0x8AFE},
+ 0xFABE => &.{0x8AED},
+ 0xFABF => &.{0x8B39},
+ 0xFAC0 => &.{0x8B8A},
+ 0xFAC1 => &.{0x8D08},
+ 0xFAC2 => &.{0x8F38},
+ 0xFAC3 => &.{0x9072},
+ 0xFAC4 => &.{0x9199},
+ 0xFAC5 => &.{0x9276},
+ 0xFAC6 => &.{0x967C},
+ 0xFAC7 => &.{0x96E3},
+ 0xFAC8 => &.{0x9756},
+ 0xFAC9 => &.{0x97DB},
+ 0xFACA => &.{0x97FF},
+ 0xFACB => &.{0x980B},
+ 0xFACC => &.{0x983B},
+ 0xFACD => &.{0x9B12},
+ 0xFACE => &.{0x9F9C},
+ 0xFACF => &.{0x2284A},
+ 0xFAD0 => &.{0x22844},
+ 0xFAD1 => &.{0x233D5},
+ 0xFAD2 => &.{0x3B9D},
+ 0xFAD3 => &.{0x4018},
+ 0xFAD4 => &.{0x4039},
+ 0xFAD5 => &.{0x25249},
+ 0xFAD6 => &.{0x25CD0},
+ 0xFAD7 => &.{0x27ED3},
+ 0xFAD8 => &.{0x9F43},
+ 0xFAD9 => &.{0x9F8E},
+ 0xFB00 => &.{ 0x66, 0x66 },
+ 0xFB01 => &.{ 0x66, 0x69 },
+ 0xFB02 => &.{ 0x66, 0x6C },
+ 0xFB03 => &.{ 0x66, 0x66, 0x69 },
+ 0xFB04 => &.{ 0x66, 0x66, 0x6C },
+ 0xFB05...0xFB06 => &.{ 0x73, 0x74 },
+ 0xFB13 => &.{ 0x574, 0x576 },
+ 0xFB14 => &.{ 0x574, 0x565 },
+ 0xFB15 => &.{ 0x574, 0x56B },
+ 0xFB16 => &.{ 0x57E, 0x576 },
+ 0xFB17 => &.{ 0x574, 0x56D },
+ 0xFB1D => &.{ 0x5D9, 0x5B4 },
+ 0xFB1F => &.{ 0x5F2, 0x5B7 },
+ 0xFB20 => &.{0x5E2},
+ 0xFB21 => &.{0x5D0},
+ 0xFB22 => &.{0x5D3},
+ 0xFB23 => &.{0x5D4},
+ 0xFB24 => &.{0x5DB},
+ 0xFB25 => &.{0x5DC},
+ 0xFB26 => &.{0x5DD},
+ 0xFB27 => &.{0x5E8},
+ 0xFB28 => &.{0x5EA},
+ 0xFB29 => &.{0x2B},
+ 0xFB2A => &.{ 0x5E9, 0x5C1 },
+ 0xFB2B => &.{ 0x5E9, 0x5C2 },
+ 0xFB2C => &.{ 0x5E9, 0x5BC, 0x5C1 },
+ 0xFB2D => &.{ 0x5E9, 0x5BC, 0x5C2 },
+ 0xFB2E => &.{ 0x5D0, 0x5B7 },
+ 0xFB2F => &.{ 0x5D0, 0x5B8 },
+ 0xFB30 => &.{ 0x5D0, 0x5BC },
+ 0xFB31 => &.{ 0x5D1, 0x5BC },
+ 0xFB32 => &.{ 0x5D2, 0x5BC },
+ 0xFB33 => &.{ 0x5D3, 0x5BC },
+ 0xFB34 => &.{ 0x5D4, 0x5BC },
+ 0xFB35 => &.{ 0x5D5, 0x5BC },
+ 0xFB36 => &.{ 0x5D6, 0x5BC },
+ 0xFB38 => &.{ 0x5D8, 0x5BC },
+ 0xFB39 => &.{ 0x5D9, 0x5BC },
+ 0xFB3A => &.{ 0x5DA, 0x5BC },
+ 0xFB3B => &.{ 0x5DB, 0x5BC },
+ 0xFB3C => &.{ 0x5DC, 0x5BC },
+ 0xFB3E => &.{ 0x5DE, 0x5BC },
+ 0xFB40 => &.{ 0x5E0, 0x5BC },
+ 0xFB41 => &.{ 0x5E1, 0x5BC },
+ 0xFB43 => &.{ 0x5E3, 0x5BC },
+ 0xFB44 => &.{ 0x5E4, 0x5BC },
+ 0xFB46 => &.{ 0x5E6, 0x5BC },
+ 0xFB47 => &.{ 0x5E7, 0x5BC },
+ 0xFB48 => &.{ 0x5E8, 0x5BC },
+ 0xFB49 => &.{ 0x5E9, 0x5BC },
+ 0xFB4A => &.{ 0x5EA, 0x5BC },
+ 0xFB4B => &.{ 0x5D5, 0x5B9 },
+ 0xFB4C => &.{ 0x5D1, 0x5BF },
+ 0xFB4D => &.{ 0x5DB, 0x5BF },
+ 0xFB4E => &.{ 0x5E4, 0x5BF },
+ 0xFB4F => &.{ 0x5D0, 0x5DC },
+ 0xFB50...0xFB51 => &.{0x671},
+ 0xFB52...0xFB55 => &.{0x67B},
+ 0xFB56...0xFB59 => &.{0x67E},
+ 0xFB5A...0xFB5D => &.{0x680},
+ 0xFB5E...0xFB61 => &.{0x67A},
+ 0xFB62...0xFB65 => &.{0x67F},
+ 0xFB66...0xFB69 => &.{0x679},
+ 0xFB6A...0xFB6D => &.{0x6A4},
+ 0xFB6E...0xFB71 => &.{0x6A6},
+ 0xFB72...0xFB75 => &.{0x684},
+ 0xFB76...0xFB79 => &.{0x683},
+ 0xFB7A...0xFB7D => &.{0x686},
+ 0xFB7E...0xFB81 => &.{0x687},
+ 0xFB82...0xFB83 => &.{0x68D},
+ 0xFB84...0xFB85 => &.{0x68C},
+ 0xFB86...0xFB87 => &.{0x68E},
+ 0xFB88...0xFB89 => &.{0x688},
+ 0xFB8A...0xFB8B => &.{0x698},
+ 0xFB8C...0xFB8D => &.{0x691},
+ 0xFB8E...0xFB91 => &.{0x6A9},
+ 0xFB92...0xFB95 => &.{0x6AF},
+ 0xFB96...0xFB99 => &.{0x6B3},
+ 0xFB9A...0xFB9D => &.{0x6B1},
+ 0xFB9E...0xFB9F => &.{0x6BA},
+ 0xFBA0...0xFBA3 => &.{0x6BB},
+ 0xFBA4...0xFBA5 => &.{0x6C0},
+ 0xFBA6...0xFBA9 => &.{0x6C1},
+ 0xFBAA...0xFBAD => &.{0x6BE},
+ 0xFBAE...0xFBAF => &.{0x6D2},
+ 0xFBB0...0xFBB1 => &.{0x6D3},
+ 0xFBD3...0xFBD6 => &.{0x6AD},
+ 0xFBD7...0xFBD8 => &.{0x6C7},
+ 0xFBD9...0xFBDA => &.{0x6C6},
+ 0xFBDB...0xFBDC => &.{0x6C8},
+ 0xFBDD => &.{ 0x6C7, 0x674 },
+ 0xFBDE...0xFBDF => &.{0x6CB},
+ 0xFBE0...0xFBE1 => &.{0x6C5},
+ 0xFBE2...0xFBE3 => &.{0x6C9},
+ 0xFBE4...0xFBE7 => &.{0x6D0},
+ 0xFBE8...0xFBE9 => &.{0x649},
+ 0xFBEA...0xFBEB => &.{ 0x626, 0x627 },
+ 0xFBEC...0xFBED => &.{ 0x626, 0x6D5 },
+ 0xFBEE...0xFBEF => &.{ 0x626, 0x648 },
+ 0xFBF0...0xFBF1 => &.{ 0x626, 0x6C7 },
+ 0xFBF2...0xFBF3 => &.{ 0x626, 0x6C6 },
+ 0xFBF4...0xFBF5 => &.{ 0x626, 0x6C8 },
+ 0xFBF6...0xFBF8 => &.{ 0x626, 0x6D0 },
+ 0xFBF9...0xFBFB => &.{ 0x626, 0x649 },
+ 0xFBFC...0xFBFF => &.{0x6CC},
+ 0xFC00 => &.{ 0x626, 0x62C },
+ 0xFC01 => &.{ 0x626, 0x62D },
+ 0xFC02 => &.{ 0x626, 0x645 },
+ 0xFC03 => &.{ 0x626, 0x649 },
+ 0xFC04 => &.{ 0x626, 0x64A },
+ 0xFC05 => &.{ 0x628, 0x62C },
+ 0xFC06 => &.{ 0x628, 0x62D },
+ 0xFC07 => &.{ 0x628, 0x62E },
+ 0xFC08 => &.{ 0x628, 0x645 },
+ 0xFC09 => &.{ 0x628, 0x649 },
+ 0xFC0A => &.{ 0x628, 0x64A },
+ 0xFC0B => &.{ 0x62A, 0x62C },
+ 0xFC0C => &.{ 0x62A, 0x62D },
+ 0xFC0D => &.{ 0x62A, 0x62E },
+ 0xFC0E => &.{ 0x62A, 0x645 },
+ 0xFC0F => &.{ 0x62A, 0x649 },
+ 0xFC10 => &.{ 0x62A, 0x64A },
+ 0xFC11 => &.{ 0x62B, 0x62C },
+ 0xFC12 => &.{ 0x62B, 0x645 },
+ 0xFC13 => &.{ 0x62B, 0x649 },
+ 0xFC14 => &.{ 0x62B, 0x64A },
+ 0xFC15 => &.{ 0x62C, 0x62D },
+ 0xFC16 => &.{ 0x62C, 0x645 },
+ 0xFC17 => &.{ 0x62D, 0x62C },
+ 0xFC18 => &.{ 0x62D, 0x645 },
+ 0xFC19 => &.{ 0x62E, 0x62C },
+ 0xFC1A => &.{ 0x62E, 0x62D },
+ 0xFC1B => &.{ 0x62E, 0x645 },
+ 0xFC1C => &.{ 0x633, 0x62C },
+ 0xFC1D => &.{ 0x633, 0x62D },
+ 0xFC1E => &.{ 0x633, 0x62E },
+ 0xFC1F => &.{ 0x633, 0x645 },
+ 0xFC20 => &.{ 0x635, 0x62D },
+ 0xFC21 => &.{ 0x635, 0x645 },
+ 0xFC22 => &.{ 0x636, 0x62C },
+ 0xFC23 => &.{ 0x636, 0x62D },
+ 0xFC24 => &.{ 0x636, 0x62E },
+ 0xFC25 => &.{ 0x636, 0x645 },
+ 0xFC26 => &.{ 0x637, 0x62D },
+ 0xFC27 => &.{ 0x637, 0x645 },
+ 0xFC28 => &.{ 0x638, 0x645 },
+ 0xFC29 => &.{ 0x639, 0x62C },
+ 0xFC2A => &.{ 0x639, 0x645 },
+ 0xFC2B => &.{ 0x63A, 0x62C },
+ 0xFC2C => &.{ 0x63A, 0x645 },
+ 0xFC2D => &.{ 0x641, 0x62C },
+ 0xFC2E => &.{ 0x641, 0x62D },
+ 0xFC2F => &.{ 0x641, 0x62E },
+ 0xFC30 => &.{ 0x641, 0x645 },
+ 0xFC31 => &.{ 0x641, 0x649 },
+ 0xFC32 => &.{ 0x641, 0x64A },
+ 0xFC33 => &.{ 0x642, 0x62D },
+ 0xFC34 => &.{ 0x642, 0x645 },
+ 0xFC35 => &.{ 0x642, 0x649 },
+ 0xFC36 => &.{ 0x642, 0x64A },
+ 0xFC37 => &.{ 0x643, 0x627 },
+ 0xFC38 => &.{ 0x643, 0x62C },
+ 0xFC39 => &.{ 0x643, 0x62D },
+ 0xFC3A => &.{ 0x643, 0x62E },
+ 0xFC3B => &.{ 0x643, 0x644 },
+ 0xFC3C => &.{ 0x643, 0x645 },
+ 0xFC3D => &.{ 0x643, 0x649 },
+ 0xFC3E => &.{ 0x643, 0x64A },
+ 0xFC3F => &.{ 0x644, 0x62C },
+ 0xFC40 => &.{ 0x644, 0x62D },
+ 0xFC41 => &.{ 0x644, 0x62E },
+ 0xFC42 => &.{ 0x644, 0x645 },
+ 0xFC43 => &.{ 0x644, 0x649 },
+ 0xFC44 => &.{ 0x644, 0x64A },
+ 0xFC45 => &.{ 0x645, 0x62C },
+ 0xFC46 => &.{ 0x645, 0x62D },
+ 0xFC47 => &.{ 0x645, 0x62E },
+ 0xFC48 => &.{ 0x645, 0x645 },
+ 0xFC49 => &.{ 0x645, 0x649 },
+ 0xFC4A => &.{ 0x645, 0x64A },
+ 0xFC4B => &.{ 0x646, 0x62C },
+ 0xFC4C => &.{ 0x646, 0x62D },
+ 0xFC4D => &.{ 0x646, 0x62E },
+ 0xFC4E => &.{ 0x646, 0x645 },
+ 0xFC4F => &.{ 0x646, 0x649 },
+ 0xFC50 => &.{ 0x646, 0x64A },
+ 0xFC51 => &.{ 0x647, 0x62C },
+ 0xFC52 => &.{ 0x647, 0x645 },
+ 0xFC53 => &.{ 0x647, 0x649 },
+ 0xFC54 => &.{ 0x647, 0x64A },
+ 0xFC55 => &.{ 0x64A, 0x62C },
+ 0xFC56 => &.{ 0x64A, 0x62D },
+ 0xFC57 => &.{ 0x64A, 0x62E },
+ 0xFC58 => &.{ 0x64A, 0x645 },
+ 0xFC59 => &.{ 0x64A, 0x649 },
+ 0xFC5A => &.{ 0x64A, 0x64A },
+ 0xFC5B => &.{ 0x630, 0x670 },
+ 0xFC5C => &.{ 0x631, 0x670 },
+ 0xFC5D => &.{ 0x649, 0x670 },
+ 0xFC5E => &.{ 0x20, 0x64C, 0x651 },
+ 0xFC5F => &.{ 0x20, 0x64D, 0x651 },
+ 0xFC60 => &.{ 0x20, 0x64E, 0x651 },
+ 0xFC61 => &.{ 0x20, 0x64F, 0x651 },
+ 0xFC62 => &.{ 0x20, 0x650, 0x651 },
+ 0xFC63 => &.{ 0x20, 0x651, 0x670 },
+ 0xFC64 => &.{ 0x626, 0x631 },
+ 0xFC65 => &.{ 0x626, 0x632 },
+ 0xFC66 => &.{ 0x626, 0x645 },
+ 0xFC67 => &.{ 0x626, 0x646 },
+ 0xFC68 => &.{ 0x626, 0x649 },
+ 0xFC69 => &.{ 0x626, 0x64A },
+ 0xFC6A => &.{ 0x628, 0x631 },
+ 0xFC6B => &.{ 0x628, 0x632 },
+ 0xFC6C => &.{ 0x628, 0x645 },
+ 0xFC6D => &.{ 0x628, 0x646 },
+ 0xFC6E => &.{ 0x628, 0x649 },
+ 0xFC6F => &.{ 0x628, 0x64A },
+ 0xFC70 => &.{ 0x62A, 0x631 },
+ 0xFC71 => &.{ 0x62A, 0x632 },
+ 0xFC72 => &.{ 0x62A, 0x645 },
+ 0xFC73 => &.{ 0x62A, 0x646 },
+ 0xFC74 => &.{ 0x62A, 0x649 },
+ 0xFC75 => &.{ 0x62A, 0x64A },
+ 0xFC76 => &.{ 0x62B, 0x631 },
+ 0xFC77 => &.{ 0x62B, 0x632 },
+ 0xFC78 => &.{ 0x62B, 0x645 },
+ 0xFC79 => &.{ 0x62B, 0x646 },
+ 0xFC7A => &.{ 0x62B, 0x649 },
+ 0xFC7B => &.{ 0x62B, 0x64A },
+ 0xFC7C => &.{ 0x641, 0x649 },
+ 0xFC7D => &.{ 0x641, 0x64A },
+ 0xFC7E => &.{ 0x642, 0x649 },
+ 0xFC7F => &.{ 0x642, 0x64A },
+ 0xFC80 => &.{ 0x643, 0x627 },
+ 0xFC81 => &.{ 0x643, 0x644 },
+ 0xFC82 => &.{ 0x643, 0x645 },
+ 0xFC83 => &.{ 0x643, 0x649 },
+ 0xFC84 => &.{ 0x643, 0x64A },
+ 0xFC85 => &.{ 0x644, 0x645 },
+ 0xFC86 => &.{ 0x644, 0x649 },
+ 0xFC87 => &.{ 0x644, 0x64A },
+ 0xFC88 => &.{ 0x645, 0x627 },
+ 0xFC89 => &.{ 0x645, 0x645 },
+ 0xFC8A => &.{ 0x646, 0x631 },
+ 0xFC8B => &.{ 0x646, 0x632 },
+ 0xFC8C => &.{ 0x646, 0x645 },
+ 0xFC8D => &.{ 0x646, 0x646 },
+ 0xFC8E => &.{ 0x646, 0x649 },
+ 0xFC8F => &.{ 0x646, 0x64A },
+ 0xFC90 => &.{ 0x649, 0x670 },
+ 0xFC91 => &.{ 0x64A, 0x631 },
+ 0xFC92 => &.{ 0x64A, 0x632 },
+ 0xFC93 => &.{ 0x64A, 0x645 },
+ 0xFC94 => &.{ 0x64A, 0x646 },
+ 0xFC95 => &.{ 0x64A, 0x649 },
+ 0xFC96 => &.{ 0x64A, 0x64A },
+ 0xFC97 => &.{ 0x626, 0x62C },
+ 0xFC98 => &.{ 0x626, 0x62D },
+ 0xFC99 => &.{ 0x626, 0x62E },
+ 0xFC9A => &.{ 0x626, 0x645 },
+ 0xFC9B => &.{ 0x626, 0x647 },
+ 0xFC9C => &.{ 0x628, 0x62C },
+ 0xFC9D => &.{ 0x628, 0x62D },
+ 0xFC9E => &.{ 0x628, 0x62E },
+ 0xFC9F => &.{ 0x628, 0x645 },
+ 0xFCA0 => &.{ 0x628, 0x647 },
+ 0xFCA1 => &.{ 0x62A, 0x62C },
+ 0xFCA2 => &.{ 0x62A, 0x62D },
+ 0xFCA3 => &.{ 0x62A, 0x62E },
+ 0xFCA4 => &.{ 0x62A, 0x645 },
+ 0xFCA5 => &.{ 0x62A, 0x647 },
+ 0xFCA6 => &.{ 0x62B, 0x645 },
+ 0xFCA7 => &.{ 0x62C, 0x62D },
+ 0xFCA8 => &.{ 0x62C, 0x645 },
+ 0xFCA9 => &.{ 0x62D, 0x62C },
+ 0xFCAA => &.{ 0x62D, 0x645 },
+ 0xFCAB => &.{ 0x62E, 0x62C },
+ 0xFCAC => &.{ 0x62E, 0x645 },
+ 0xFCAD => &.{ 0x633, 0x62C },
+ 0xFCAE => &.{ 0x633, 0x62D },
+ 0xFCAF => &.{ 0x633, 0x62E },
+ 0xFCB0 => &.{ 0x633, 0x645 },
+ 0xFCB1 => &.{ 0x635, 0x62D },
+ 0xFCB2 => &.{ 0x635, 0x62E },
+ 0xFCB3 => &.{ 0x635, 0x645 },
+ 0xFCB4 => &.{ 0x636, 0x62C },
+ 0xFCB5 => &.{ 0x636, 0x62D },
+ 0xFCB6 => &.{ 0x636, 0x62E },
+ 0xFCB7 => &.{ 0x636, 0x645 },
+ 0xFCB8 => &.{ 0x637, 0x62D },
+ 0xFCB9 => &.{ 0x638, 0x645 },
+ 0xFCBA => &.{ 0x639, 0x62C },
+ 0xFCBB => &.{ 0x639, 0x645 },
+ 0xFCBC => &.{ 0x63A, 0x62C },
+ 0xFCBD => &.{ 0x63A, 0x645 },
+ 0xFCBE => &.{ 0x641, 0x62C },
+ 0xFCBF => &.{ 0x641, 0x62D },
+ 0xFCC0 => &.{ 0x641, 0x62E },
+ 0xFCC1 => &.{ 0x641, 0x645 },
+ 0xFCC2 => &.{ 0x642, 0x62D },
+ 0xFCC3 => &.{ 0x642, 0x645 },
+ 0xFCC4 => &.{ 0x643, 0x62C },
+ 0xFCC5 => &.{ 0x643, 0x62D },
+ 0xFCC6 => &.{ 0x643, 0x62E },
+ 0xFCC7 => &.{ 0x643, 0x644 },
+ 0xFCC8 => &.{ 0x643, 0x645 },
+ 0xFCC9 => &.{ 0x644, 0x62C },
+ 0xFCCA => &.{ 0x644, 0x62D },
+ 0xFCCB => &.{ 0x644, 0x62E },
+ 0xFCCC => &.{ 0x644, 0x645 },
+ 0xFCCD => &.{ 0x644, 0x647 },
+ 0xFCCE => &.{ 0x645, 0x62C },
+ 0xFCCF => &.{ 0x645, 0x62D },
+ 0xFCD0 => &.{ 0x645, 0x62E },
+ 0xFCD1 => &.{ 0x645, 0x645 },
+ 0xFCD2 => &.{ 0x646, 0x62C },
+ 0xFCD3 => &.{ 0x646, 0x62D },
+ 0xFCD4 => &.{ 0x646, 0x62E },
+ 0xFCD5 => &.{ 0x646, 0x645 },
+ 0xFCD6 => &.{ 0x646, 0x647 },
+ 0xFCD7 => &.{ 0x647, 0x62C },
+ 0xFCD8 => &.{ 0x647, 0x645 },
+ 0xFCD9 => &.{ 0x647, 0x670 },
+ 0xFCDA => &.{ 0x64A, 0x62C },
+ 0xFCDB => &.{ 0x64A, 0x62D },
+ 0xFCDC => &.{ 0x64A, 0x62E },
+ 0xFCDD => &.{ 0x64A, 0x645 },
+ 0xFCDE => &.{ 0x64A, 0x647 },
+ 0xFCDF => &.{ 0x626, 0x645 },
+ 0xFCE0 => &.{ 0x626, 0x647 },
+ 0xFCE1 => &.{ 0x628, 0x645 },
+ 0xFCE2 => &.{ 0x628, 0x647 },
+ 0xFCE3 => &.{ 0x62A, 0x645 },
+ 0xFCE4 => &.{ 0x62A, 0x647 },
+ 0xFCE5 => &.{ 0x62B, 0x645 },
+ 0xFCE6 => &.{ 0x62B, 0x647 },
+ 0xFCE7 => &.{ 0x633, 0x645 },
+ 0xFCE8 => &.{ 0x633, 0x647 },
+ 0xFCE9 => &.{ 0x634, 0x645 },
+ 0xFCEA => &.{ 0x634, 0x647 },
+ 0xFCEB => &.{ 0x643, 0x644 },
+ 0xFCEC => &.{ 0x643, 0x645 },
+ 0xFCED => &.{ 0x644, 0x645 },
+ 0xFCEE => &.{ 0x646, 0x645 },
+ 0xFCEF => &.{ 0x646, 0x647 },
+ 0xFCF0 => &.{ 0x64A, 0x645 },
+ 0xFCF1 => &.{ 0x64A, 0x647 },
+ 0xFCF2 => &.{ 0x640, 0x64E, 0x651 },
+ 0xFCF3 => &.{ 0x640, 0x64F, 0x651 },
+ 0xFCF4 => &.{ 0x640, 0x650, 0x651 },
+ 0xFCF5 => &.{ 0x637, 0x649 },
+ 0xFCF6 => &.{ 0x637, 0x64A },
+ 0xFCF7 => &.{ 0x639, 0x649 },
+ 0xFCF8 => &.{ 0x639, 0x64A },
+ 0xFCF9 => &.{ 0x63A, 0x649 },
+ 0xFCFA => &.{ 0x63A, 0x64A },
+ 0xFCFB => &.{ 0x633, 0x649 },
+ 0xFCFC => &.{ 0x633, 0x64A },
+ 0xFCFD => &.{ 0x634, 0x649 },
+ 0xFCFE => &.{ 0x634, 0x64A },
+ 0xFCFF => &.{ 0x62D, 0x649 },
+ 0xFD00 => &.{ 0x62D, 0x64A },
+ 0xFD01 => &.{ 0x62C, 0x649 },
+ 0xFD02 => &.{ 0x62C, 0x64A },
+ 0xFD03 => &.{ 0x62E, 0x649 },
+ 0xFD04 => &.{ 0x62E, 0x64A },
+ 0xFD05 => &.{ 0x635, 0x649 },
+ 0xFD06 => &.{ 0x635, 0x64A },
+ 0xFD07 => &.{ 0x636, 0x649 },
+ 0xFD08 => &.{ 0x636, 0x64A },
+ 0xFD09 => &.{ 0x634, 0x62C },
+ 0xFD0A => &.{ 0x634, 0x62D },
+ 0xFD0B => &.{ 0x634, 0x62E },
+ 0xFD0C => &.{ 0x634, 0x645 },
+ 0xFD0D => &.{ 0x634, 0x631 },
+ 0xFD0E => &.{ 0x633, 0x631 },
+ 0xFD0F => &.{ 0x635, 0x631 },
+ 0xFD10 => &.{ 0x636, 0x631 },
+ 0xFD11 => &.{ 0x637, 0x649 },
+ 0xFD12 => &.{ 0x637, 0x64A },
+ 0xFD13 => &.{ 0x639, 0x649 },
+ 0xFD14 => &.{ 0x639, 0x64A },
+ 0xFD15 => &.{ 0x63A, 0x649 },
+ 0xFD16 => &.{ 0x63A, 0x64A },
+ 0xFD17 => &.{ 0x633, 0x649 },
+ 0xFD18 => &.{ 0x633, 0x64A },
+ 0xFD19 => &.{ 0x634, 0x649 },
+ 0xFD1A => &.{ 0x634, 0x64A },
+ 0xFD1B => &.{ 0x62D, 0x649 },
+ 0xFD1C => &.{ 0x62D, 0x64A },
+ 0xFD1D => &.{ 0x62C, 0x649 },
+ 0xFD1E => &.{ 0x62C, 0x64A },
+ 0xFD1F => &.{ 0x62E, 0x649 },
+ 0xFD20 => &.{ 0x62E, 0x64A },
+ 0xFD21 => &.{ 0x635, 0x649 },
+ 0xFD22 => &.{ 0x635, 0x64A },
+ 0xFD23 => &.{ 0x636, 0x649 },
+ 0xFD24 => &.{ 0x636, 0x64A },
+ 0xFD25 => &.{ 0x634, 0x62C },
+ 0xFD26 => &.{ 0x634, 0x62D },
+ 0xFD27 => &.{ 0x634, 0x62E },
+ 0xFD28 => &.{ 0x634, 0x645 },
+ 0xFD29 => &.{ 0x634, 0x631 },
+ 0xFD2A => &.{ 0x633, 0x631 },
+ 0xFD2B => &.{ 0x635, 0x631 },
+ 0xFD2C => &.{ 0x636, 0x631 },
+ 0xFD2D => &.{ 0x634, 0x62C },
+ 0xFD2E => &.{ 0x634, 0x62D },
+ 0xFD2F => &.{ 0x634, 0x62E },
+ 0xFD30 => &.{ 0x634, 0x645 },
+ 0xFD31 => &.{ 0x633, 0x647 },
+ 0xFD32 => &.{ 0x634, 0x647 },
+ 0xFD33 => &.{ 0x637, 0x645 },
+ 0xFD34 => &.{ 0x633, 0x62C },
+ 0xFD35 => &.{ 0x633, 0x62D },
+ 0xFD36 => &.{ 0x633, 0x62E },
+ 0xFD37 => &.{ 0x634, 0x62C },
+ 0xFD38 => &.{ 0x634, 0x62D },
+ 0xFD39 => &.{ 0x634, 0x62E },
+ 0xFD3A => &.{ 0x637, 0x645 },
+ 0xFD3B => &.{ 0x638, 0x645 },
+ 0xFD3C...0xFD3D => &.{ 0x627, 0x64B },
+ 0xFD50 => &.{ 0x62A, 0x62C, 0x645 },
+ 0xFD51...0xFD52 => &.{ 0x62A, 0x62D, 0x62C },
+ 0xFD53 => &.{ 0x62A, 0x62D, 0x645 },
+ 0xFD54 => &.{ 0x62A, 0x62E, 0x645 },
+ 0xFD55 => &.{ 0x62A, 0x645, 0x62C },
+ 0xFD56 => &.{ 0x62A, 0x645, 0x62D },
+ 0xFD57 => &.{ 0x62A, 0x645, 0x62E },
+ 0xFD58...0xFD59 => &.{ 0x62C, 0x645, 0x62D },
+ 0xFD5A => &.{ 0x62D, 0x645, 0x64A },
+ 0xFD5B => &.{ 0x62D, 0x645, 0x649 },
+ 0xFD5C => &.{ 0x633, 0x62D, 0x62C },
+ 0xFD5D => &.{ 0x633, 0x62C, 0x62D },
+ 0xFD5E => &.{ 0x633, 0x62C, 0x649 },
+ 0xFD5F...0xFD60 => &.{ 0x633, 0x645, 0x62D },
+ 0xFD61 => &.{ 0x633, 0x645, 0x62C },
+ 0xFD62...0xFD63 => &.{ 0x633, 0x645, 0x645 },
+ 0xFD64...0xFD65 => &.{ 0x635, 0x62D, 0x62D },
+ 0xFD66 => &.{ 0x635, 0x645, 0x645 },
+ 0xFD67...0xFD68 => &.{ 0x634, 0x62D, 0x645 },
+ 0xFD69 => &.{ 0x634, 0x62C, 0x64A },
+ 0xFD6A...0xFD6B => &.{ 0x634, 0x645, 0x62E },
+ 0xFD6C...0xFD6D => &.{ 0x634, 0x645, 0x645 },
+ 0xFD6E => &.{ 0x636, 0x62D, 0x649 },
+ 0xFD6F...0xFD70 => &.{ 0x636, 0x62E, 0x645 },
+ 0xFD71...0xFD72 => &.{ 0x637, 0x645, 0x62D },
+ 0xFD73 => &.{ 0x637, 0x645, 0x645 },
+ 0xFD74 => &.{ 0x637, 0x645, 0x64A },
+ 0xFD75 => &.{ 0x639, 0x62C, 0x645 },
+ 0xFD76...0xFD77 => &.{ 0x639, 0x645, 0x645 },
+ 0xFD78 => &.{ 0x639, 0x645, 0x649 },
+ 0xFD79 => &.{ 0x63A, 0x645, 0x645 },
+ 0xFD7A => &.{ 0x63A, 0x645, 0x64A },
+ 0xFD7B => &.{ 0x63A, 0x645, 0x649 },
+ 0xFD7C...0xFD7D => &.{ 0x641, 0x62E, 0x645 },
+ 0xFD7E => &.{ 0x642, 0x645, 0x62D },
+ 0xFD7F => &.{ 0x642, 0x645, 0x645 },
+ 0xFD80 => &.{ 0x644, 0x62D, 0x645 },
+ 0xFD81 => &.{ 0x644, 0x62D, 0x64A },
+ 0xFD82 => &.{ 0x644, 0x62D, 0x649 },
+ 0xFD83...0xFD84 => &.{ 0x644, 0x62C, 0x62C },
+ 0xFD85...0xFD86 => &.{ 0x644, 0x62E, 0x645 },
+ 0xFD87...0xFD88 => &.{ 0x644, 0x645, 0x62D },
+ 0xFD89 => &.{ 0x645, 0x62D, 0x62C },
+ 0xFD8A => &.{ 0x645, 0x62D, 0x645 },
+ 0xFD8B => &.{ 0x645, 0x62D, 0x64A },
+ 0xFD8C => &.{ 0x645, 0x62C, 0x62D },
+ 0xFD8D => &.{ 0x645, 0x62C, 0x645 },
+ 0xFD8E => &.{ 0x645, 0x62E, 0x62C },
+ 0xFD8F => &.{ 0x645, 0x62E, 0x645 },
+ 0xFD92 => &.{ 0x645, 0x62C, 0x62E },
+ 0xFD93 => &.{ 0x647, 0x645, 0x62C },
+ 0xFD94 => &.{ 0x647, 0x645, 0x645 },
+ 0xFD95 => &.{ 0x646, 0x62D, 0x645 },
+ 0xFD96 => &.{ 0x646, 0x62D, 0x649 },
+ 0xFD97...0xFD98 => &.{ 0x646, 0x62C, 0x645 },
+ 0xFD99 => &.{ 0x646, 0x62C, 0x649 },
+ 0xFD9A => &.{ 0x646, 0x645, 0x64A },
+ 0xFD9B => &.{ 0x646, 0x645, 0x649 },
+ 0xFD9C...0xFD9D => &.{ 0x64A, 0x645, 0x645 },
+ 0xFD9E => &.{ 0x628, 0x62E, 0x64A },
+ 0xFD9F => &.{ 0x62A, 0x62C, 0x64A },
+ 0xFDA0 => &.{ 0x62A, 0x62C, 0x649 },
+ 0xFDA1 => &.{ 0x62A, 0x62E, 0x64A },
+ 0xFDA2 => &.{ 0x62A, 0x62E, 0x649 },
+ 0xFDA3 => &.{ 0x62A, 0x645, 0x64A },
+ 0xFDA4 => &.{ 0x62A, 0x645, 0x649 },
+ 0xFDA5 => &.{ 0x62C, 0x645, 0x64A },
+ 0xFDA6 => &.{ 0x62C, 0x62D, 0x649 },
+ 0xFDA7 => &.{ 0x62C, 0x645, 0x649 },
+ 0xFDA8 => &.{ 0x633, 0x62E, 0x649 },
+ 0xFDA9 => &.{ 0x635, 0x62D, 0x64A },
+ 0xFDAA => &.{ 0x634, 0x62D, 0x64A },
+ 0xFDAB => &.{ 0x636, 0x62D, 0x64A },
+ 0xFDAC => &.{ 0x644, 0x62C, 0x64A },
+ 0xFDAD => &.{ 0x644, 0x645, 0x64A },
+ 0xFDAE => &.{ 0x64A, 0x62D, 0x64A },
+ 0xFDAF => &.{ 0x64A, 0x62C, 0x64A },
+ 0xFDB0 => &.{ 0x64A, 0x645, 0x64A },
+ 0xFDB1 => &.{ 0x645, 0x645, 0x64A },
+ 0xFDB2 => &.{ 0x642, 0x645, 0x64A },
+ 0xFDB3 => &.{ 0x646, 0x62D, 0x64A },
+ 0xFDB4 => &.{ 0x642, 0x645, 0x62D },
+ 0xFDB5 => &.{ 0x644, 0x62D, 0x645 },
+ 0xFDB6 => &.{ 0x639, 0x645, 0x64A },
+ 0xFDB7 => &.{ 0x643, 0x645, 0x64A },
+ 0xFDB8 => &.{ 0x646, 0x62C, 0x62D },
+ 0xFDB9 => &.{ 0x645, 0x62E, 0x64A },
+ 0xFDBA => &.{ 0x644, 0x62C, 0x645 },
+ 0xFDBB => &.{ 0x643, 0x645, 0x645 },
+ 0xFDBC => &.{ 0x644, 0x62C, 0x645 },
+ 0xFDBD => &.{ 0x646, 0x62C, 0x62D },
+ 0xFDBE => &.{ 0x62C, 0x62D, 0x64A },
+ 0xFDBF => &.{ 0x62D, 0x62C, 0x64A },
+ 0xFDC0 => &.{ 0x645, 0x62C, 0x64A },
+ 0xFDC1 => &.{ 0x641, 0x645, 0x64A },
+ 0xFDC2 => &.{ 0x628, 0x62D, 0x64A },
+ 0xFDC3 => &.{ 0x643, 0x645, 0x645 },
+ 0xFDC4 => &.{ 0x639, 0x62C, 0x645 },
+ 0xFDC5 => &.{ 0x635, 0x645, 0x645 },
+ 0xFDC6 => &.{ 0x633, 0x62E, 0x64A },
+ 0xFDC7 => &.{ 0x646, 0x62C, 0x64A },
+ 0xFDF0 => &.{ 0x635, 0x644, 0x6D2 },
+ 0xFDF1 => &.{ 0x642, 0x644, 0x6D2 },
+ 0xFDF2 => &.{ 0x627, 0x644, 0x644, 0x647 },
+ 0xFDF3 => &.{ 0x627, 0x643, 0x628, 0x631 },
+ 0xFDF4 => &.{ 0x645, 0x62D, 0x645, 0x62F },
+ 0xFDF5 => &.{ 0x635, 0x644, 0x639, 0x645 },
+ 0xFDF6 => &.{ 0x631, 0x633, 0x648, 0x644 },
+ 0xFDF7 => &.{ 0x639, 0x644, 0x64A, 0x647 },
+ 0xFDF8 => &.{ 0x648, 0x633, 0x644, 0x645 },
+ 0xFDF9 => &.{ 0x635, 0x644, 0x649 },
+ 0xFDFA => &.{ 0x635, 0x644, 0x649, 0x20, 0x627, 0x644, 0x644, 0x647, 0x20, 0x639, 0x644, 0x64A, 0x647, 0x20, 0x648, 0x633, 0x644, 0x645 },
+ 0xFDFB => &.{ 0x62C, 0x644, 0x20, 0x62C, 0x644, 0x627, 0x644, 0x647 },
+ 0xFDFC => &.{ 0x631, 0x6CC, 0x627, 0x644 },
+ 0xFE00...0xFE0F => null,
+ 0xFE10 => &.{0x2C},
+ 0xFE11 => &.{0x3001},
+ 0xFE12 => &.{0x3002},
+ 0xFE13 => &.{0x3A},
+ 0xFE14 => &.{0x3B},
+ 0xFE15 => &.{0x21},
+ 0xFE16 => &.{0x3F},
+ 0xFE17 => &.{0x3016},
+ 0xFE18 => &.{0x3017},
+ 0xFE19 => &.{ 0x2E, 0x2E, 0x2E },
+ 0xFE30 => &.{ 0x2E, 0x2E },
+ 0xFE31 => &.{0x2014},
+ 0xFE32 => &.{0x2013},
+ 0xFE33...0xFE34 => &.{0x5F},
+ 0xFE35 => &.{0x28},
+ 0xFE36 => &.{0x29},
+ 0xFE37 => &.{0x7B},
+ 0xFE38 => &.{0x7D},
+ 0xFE39 => &.{0x3014},
+ 0xFE3A => &.{0x3015},
+ 0xFE3B => &.{0x3010},
+ 0xFE3C => &.{0x3011},
+ 0xFE3D => &.{0x300A},
+ 0xFE3E => &.{0x300B},
+ 0xFE3F => &.{0x3008},
+ 0xFE40 => &.{0x3009},
+ 0xFE41 => &.{0x300C},
+ 0xFE42 => &.{0x300D},
+ 0xFE43 => &.{0x300E},
+ 0xFE44 => &.{0x300F},
+ 0xFE47 => &.{0x5B},
+ 0xFE48 => &.{0x5D},
+ 0xFE49...0xFE4C => &.{ 0x20, 0x305 },
+ 0xFE4D...0xFE4F => &.{0x5F},
+ 0xFE50 => &.{0x2C},
+ 0xFE51 => &.{0x3001},
+ 0xFE52 => &.{0x2E},
+ 0xFE54 => &.{0x3B},
+ 0xFE55 => &.{0x3A},
+ 0xFE56 => &.{0x3F},
+ 0xFE57 => &.{0x21},
+ 0xFE58 => &.{0x2014},
+ 0xFE59 => &.{0x28},
+ 0xFE5A => &.{0x29},
+ 0xFE5B => &.{0x7B},
+ 0xFE5C => &.{0x7D},
+ 0xFE5D => &.{0x3014},
+ 0xFE5E => &.{0x3015},
+ 0xFE5F => &.{0x23},
+ 0xFE60 => &.{0x26},
+ 0xFE61 => &.{0x2A},
+ 0xFE62 => &.{0x2B},
+ 0xFE63 => &.{0x2D},
+ 0xFE64 => &.{0x3C},
+ 0xFE65 => &.{0x3E},
+ 0xFE66 => &.{0x3D},
+ 0xFE68 => &.{0x5C},
+ 0xFE69 => &.{0x24},
+ 0xFE6A => &.{0x25},
+ 0xFE6B => &.{0x40},
+ 0xFE70 => &.{ 0x20, 0x64B },
+ 0xFE71 => &.{ 0x640, 0x64B },
+ 0xFE72 => &.{ 0x20, 0x64C },
+ 0xFE74 => &.{ 0x20, 0x64D },
+ 0xFE76 => &.{ 0x20, 0x64E },
+ 0xFE77 => &.{ 0x640, 0x64E },
+ 0xFE78 => &.{ 0x20, 0x64F },
+ 0xFE79 => &.{ 0x640, 0x64F },
+ 0xFE7A => &.{ 0x20, 0x650 },
+ 0xFE7B => &.{ 0x640, 0x650 },
+ 0xFE7C => &.{ 0x20, 0x651 },
+ 0xFE7D => &.{ 0x640, 0x651 },
+ 0xFE7E => &.{ 0x20, 0x652 },
+ 0xFE7F => &.{ 0x640, 0x652 },
+ 0xFE80 => &.{0x621},
+ 0xFE81...0xFE82 => &.{0x622},
+ 0xFE83...0xFE84 => &.{0x623},
+ 0xFE85...0xFE86 => &.{0x624},
+ 0xFE87...0xFE88 => &.{0x625},
+ 0xFE89...0xFE8C => &.{0x626},
+ 0xFE8D...0xFE8E => &.{0x627},
+ 0xFE8F...0xFE92 => &.{0x628},
+ 0xFE93...0xFE94 => &.{0x629},
+ 0xFE95...0xFE98 => &.{0x62A},
+ 0xFE99...0xFE9C => &.{0x62B},
+ 0xFE9D...0xFEA0 => &.{0x62C},
+ 0xFEA1...0xFEA4 => &.{0x62D},
+ 0xFEA5...0xFEA8 => &.{0x62E},
+ 0xFEA9...0xFEAA => &.{0x62F},
+ 0xFEAB...0xFEAC => &.{0x630},
+ 0xFEAD...0xFEAE => &.{0x631},
+ 0xFEAF...0xFEB0 => &.{0x632},
+ 0xFEB1...0xFEB4 => &.{0x633},
+ 0xFEB5...0xFEB8 => &.{0x634},
+ 0xFEB9...0xFEBC => &.{0x635},
+ 0xFEBD...0xFEC0 => &.{0x636},
+ 0xFEC1...0xFEC4 => &.{0x637},
+ 0xFEC5...0xFEC8 => &.{0x638},
+ 0xFEC9...0xFECC => &.{0x639},
+ 0xFECD...0xFED0 => &.{0x63A},
+ 0xFED1...0xFED4 => &.{0x641},
+ 0xFED5...0xFED8 => &.{0x642},
+ 0xFED9...0xFEDC => &.{0x643},
+ 0xFEDD...0xFEE0 => &.{0x644},
+ 0xFEE1...0xFEE4 => &.{0x645},
+ 0xFEE5...0xFEE8 => &.{0x646},
+ 0xFEE9...0xFEEC => &.{0x647},
+ 0xFEED...0xFEEE => &.{0x648},
+ 0xFEEF...0xFEF0 => &.{0x649},
+ 0xFEF1...0xFEF4 => &.{0x64A},
+ 0xFEF5...0xFEF6 => &.{ 0x644, 0x622 },
+ 0xFEF7...0xFEF8 => &.{ 0x644, 0x623 },
+ 0xFEF9...0xFEFA => &.{ 0x644, 0x625 },
+ 0xFEFB...0xFEFC => &.{ 0x644, 0x627 },
+ 0xFEFF => null,
+ 0xFF01 => &.{0x21},
+ 0xFF02 => &.{0x22},
+ 0xFF03 => &.{0x23},
+ 0xFF04 => &.{0x24},
+ 0xFF05 => &.{0x25},
+ 0xFF06 => &.{0x26},
+ 0xFF07 => &.{0x27},
+ 0xFF08 => &.{0x28},
+ 0xFF09 => &.{0x29},
+ 0xFF0A => &.{0x2A},
+ 0xFF0B => &.{0x2B},
+ 0xFF0C => &.{0x2C},
+ 0xFF0D => &.{0x2D},
+ 0xFF0E => &.{0x2E},
+ 0xFF0F => &.{0x2F},
+ 0xFF10 => &.{0x30},
+ 0xFF11 => &.{0x31},
+ 0xFF12 => &.{0x32},
+ 0xFF13 => &.{0x33},
+ 0xFF14 => &.{0x34},
+ 0xFF15 => &.{0x35},
+ 0xFF16 => &.{0x36},
+ 0xFF17 => &.{0x37},
+ 0xFF18 => &.{0x38},
+ 0xFF19 => &.{0x39},
+ 0xFF1A => &.{0x3A},
+ 0xFF1B => &.{0x3B},
+ 0xFF1C => &.{0x3C},
+ 0xFF1D => &.{0x3D},
+ 0xFF1E => &.{0x3E},
+ 0xFF1F => &.{0x3F},
+ 0xFF20 => &.{0x40},
+ 0xFF21 => &.{0x61},
+ 0xFF22 => &.{0x62},
+ 0xFF23 => &.{0x63},
+ 0xFF24 => &.{0x64},
+ 0xFF25 => &.{0x65},
+ 0xFF26 => &.{0x66},
+ 0xFF27 => &.{0x67},
+ 0xFF28 => &.{0x68},
+ 0xFF29 => &.{0x69},
+ 0xFF2A => &.{0x6A},
+ 0xFF2B => &.{0x6B},
+ 0xFF2C => &.{0x6C},
+ 0xFF2D => &.{0x6D},
+ 0xFF2E => &.{0x6E},
+ 0xFF2F => &.{0x6F},
+ 0xFF30 => &.{0x70},
+ 0xFF31 => &.{0x71},
+ 0xFF32 => &.{0x72},
+ 0xFF33 => &.{0x73},
+ 0xFF34 => &.{0x74},
+ 0xFF35 => &.{0x75},
+ 0xFF36 => &.{0x76},
+ 0xFF37 => &.{0x77},
+ 0xFF38 => &.{0x78},
+ 0xFF39 => &.{0x79},
+ 0xFF3A => &.{0x7A},
+ 0xFF3B => &.{0x5B},
+ 0xFF3C => &.{0x5C},
+ 0xFF3D => &.{0x5D},
+ 0xFF3E => &.{0x5E},
+ 0xFF3F => &.{0x5F},
+ 0xFF40 => &.{0x60},
+ 0xFF41 => &.{0x61},
+ 0xFF42 => &.{0x62},
+ 0xFF43 => &.{0x63},
+ 0xFF44 => &.{0x64},
+ 0xFF45 => &.{0x65},
+ 0xFF46 => &.{0x66},
+ 0xFF47 => &.{0x67},
+ 0xFF48 => &.{0x68},
+ 0xFF49 => &.{0x69},
+ 0xFF4A => &.{0x6A},
+ 0xFF4B => &.{0x6B},
+ 0xFF4C => &.{0x6C},
+ 0xFF4D => &.{0x6D},
+ 0xFF4E => &.{0x6E},
+ 0xFF4F => &.{0x6F},
+ 0xFF50 => &.{0x70},
+ 0xFF51 => &.{0x71},
+ 0xFF52 => &.{0x72},
+ 0xFF53 => &.{0x73},
+ 0xFF54 => &.{0x74},
+ 0xFF55 => &.{0x75},
+ 0xFF56 => &.{0x76},
+ 0xFF57 => &.{0x77},
+ 0xFF58 => &.{0x78},
+ 0xFF59 => &.{0x79},
+ 0xFF5A => &.{0x7A},
+ 0xFF5B => &.{0x7B},
+ 0xFF5C => &.{0x7C},
+ 0xFF5D => &.{0x7D},
+ 0xFF5E => &.{0x7E},
+ 0xFF5F => &.{0x2985},
+ 0xFF60 => &.{0x2986},
+ 0xFF61 => &.{0x3002},
+ 0xFF62 => &.{0x300C},
+ 0xFF63 => &.{0x300D},
+ 0xFF64 => &.{0x3001},
+ 0xFF65 => &.{0x30FB},
+ 0xFF66 => &.{0x30F2},
+ 0xFF67 => &.{0x30A1},
+ 0xFF68 => &.{0x30A3},
+ 0xFF69 => &.{0x30A5},
+ 0xFF6A => &.{0x30A7},
+ 0xFF6B => &.{0x30A9},
+ 0xFF6C => &.{0x30E3},
+ 0xFF6D => &.{0x30E5},
+ 0xFF6E => &.{0x30E7},
+ 0xFF6F => &.{0x30C3},
+ 0xFF70 => &.{0x30FC},
+ 0xFF71 => &.{0x30A2},
+ 0xFF72 => &.{0x30A4},
+ 0xFF73 => &.{0x30A6},
+ 0xFF74 => &.{0x30A8},
+ 0xFF75 => &.{0x30AA},
+ 0xFF76 => &.{0x30AB},
+ 0xFF77 => &.{0x30AD},
+ 0xFF78 => &.{0x30AF},
+ 0xFF79 => &.{0x30B1},
+ 0xFF7A => &.{0x30B3},
+ 0xFF7B => &.{0x30B5},
+ 0xFF7C => &.{0x30B7},
+ 0xFF7D => &.{0x30B9},
+ 0xFF7E => &.{0x30BB},
+ 0xFF7F => &.{0x30BD},
+ 0xFF80 => &.{0x30BF},
+ 0xFF81 => &.{0x30C1},
+ 0xFF82 => &.{0x30C4},
+ 0xFF83 => &.{0x30C6},
+ 0xFF84 => &.{0x30C8},
+ 0xFF85 => &.{0x30CA},
+ 0xFF86 => &.{0x30CB},
+ 0xFF87 => &.{0x30CC},
+ 0xFF88 => &.{0x30CD},
+ 0xFF89 => &.{0x30CE},
+ 0xFF8A => &.{0x30CF},
+ 0xFF8B => &.{0x30D2},
+ 0xFF8C => &.{0x30D5},
+ 0xFF8D => &.{0x30D8},
+ 0xFF8E => &.{0x30DB},
+ 0xFF8F => &.{0x30DE},
+ 0xFF90 => &.{0x30DF},
+ 0xFF91 => &.{0x30E0},
+ 0xFF92 => &.{0x30E1},
+ 0xFF93 => &.{0x30E2},
+ 0xFF94 => &.{0x30E4},
+ 0xFF95 => &.{0x30E6},
+ 0xFF96 => &.{0x30E8},
+ 0xFF97 => &.{0x30E9},
+ 0xFF98 => &.{0x30EA},
+ 0xFF99 => &.{0x30EB},
+ 0xFF9A => &.{0x30EC},
+ 0xFF9B => &.{0x30ED},
+ 0xFF9C => &.{0x30EF},
+ 0xFF9D => &.{0x30F3},
+ 0xFF9E => &.{0x3099},
+ 0xFF9F => &.{0x309A},
+ 0xFFA0 => null,
+ 0xFFA1 => &.{0x1100},
+ 0xFFA2 => &.{0x1101},
+ 0xFFA3 => &.{0x11AA},
+ 0xFFA4 => &.{0x1102},
+ 0xFFA5 => &.{0x11AC},
+ 0xFFA6 => &.{0x11AD},
+ 0xFFA7 => &.{0x1103},
+ 0xFFA8 => &.{0x1104},
+ 0xFFA9 => &.{0x1105},
+ 0xFFAA => &.{0x11B0},
+ 0xFFAB => &.{0x11B1},
+ 0xFFAC => &.{0x11B2},
+ 0xFFAD => &.{0x11B3},
+ 0xFFAE => &.{0x11B4},
+ 0xFFAF => &.{0x11B5},
+ 0xFFB0 => &.{0x111A},
+ 0xFFB1 => &.{0x1106},
+ 0xFFB2 => &.{0x1107},
+ 0xFFB3 => &.{0x1108},
+ 0xFFB4 => &.{0x1121},
+ 0xFFB5 => &.{0x1109},
+ 0xFFB6 => &.{0x110A},
+ 0xFFB7 => &.{0x110B},
+ 0xFFB8 => &.{0x110C},
+ 0xFFB9 => &.{0x110D},
+ 0xFFBA => &.{0x110E},
+ 0xFFBB => &.{0x110F},
+ 0xFFBC => &.{0x1110},
+ 0xFFBD => &.{0x1111},
+ 0xFFBE => &.{0x1112},
+ 0xFFC2 => &.{0x1161},
+ 0xFFC3 => &.{0x1162},
+ 0xFFC4 => &.{0x1163},
+ 0xFFC5 => &.{0x1164},
+ 0xFFC6 => &.{0x1165},
+ 0xFFC7 => &.{0x1166},
+ 0xFFCA => &.{0x1167},
+ 0xFFCB => &.{0x1168},
+ 0xFFCC => &.{0x1169},
+ 0xFFCD => &.{0x116A},
+ 0xFFCE => &.{0x116B},
+ 0xFFCF => &.{0x116C},
+ 0xFFD2 => &.{0x116D},
+ 0xFFD3 => &.{0x116E},
+ 0xFFD4 => &.{0x116F},
+ 0xFFD5 => &.{0x1170},
+ 0xFFD6 => &.{0x1171},
+ 0xFFD7 => &.{0x1172},
+ 0xFFDA => &.{0x1173},
+ 0xFFDB => &.{0x1174},
+ 0xFFDC => &.{0x1175},
+ 0xFFE0 => &.{0xA2},
+ 0xFFE1 => &.{0xA3},
+ 0xFFE2 => &.{0xAC},
+ 0xFFE3 => &.{ 0x20, 0x304 },
+ 0xFFE4 => &.{0xA6},
+ 0xFFE5 => &.{0xA5},
+ 0xFFE6 => &.{0x20A9},
+ 0xFFE8 => &.{0x2502},
+ 0xFFE9 => &.{0x2190},
+ 0xFFEA => &.{0x2191},
+ 0xFFEB => &.{0x2192},
+ 0xFFEC => &.{0x2193},
+ 0xFFED => &.{0x25A0},
+ 0xFFEE => &.{0x25CB},
+ 0xFFF0...0xFFF8 => null,
+ 0x10400 => &.{0x10428},
+ 0x10401 => &.{0x10429},
+ 0x10402 => &.{0x1042A},
+ 0x10403 => &.{0x1042B},
+ 0x10404 => &.{0x1042C},
+ 0x10405 => &.{0x1042D},
+ 0x10406 => &.{0x1042E},
+ 0x10407 => &.{0x1042F},
+ 0x10408 => &.{0x10430},
+ 0x10409 => &.{0x10431},
+ 0x1040A => &.{0x10432},
+ 0x1040B => &.{0x10433},
+ 0x1040C => &.{0x10434},
+ 0x1040D => &.{0x10435},
+ 0x1040E => &.{0x10436},
+ 0x1040F => &.{0x10437},
+ 0x10410 => &.{0x10438},
+ 0x10411 => &.{0x10439},
+ 0x10412 => &.{0x1043A},
+ 0x10413 => &.{0x1043B},
+ 0x10414 => &.{0x1043C},
+ 0x10415 => &.{0x1043D},
+ 0x10416 => &.{0x1043E},
+ 0x10417 => &.{0x1043F},
+ 0x10418 => &.{0x10440},
+ 0x10419 => &.{0x10441},
+ 0x1041A => &.{0x10442},
+ 0x1041B => &.{0x10443},
+ 0x1041C => &.{0x10444},
+ 0x1041D => &.{0x10445},
+ 0x1041E => &.{0x10446},
+ 0x1041F => &.{0x10447},
+ 0x10420 => &.{0x10448},
+ 0x10421 => &.{0x10449},
+ 0x10422 => &.{0x1044A},
+ 0x10423 => &.{0x1044B},
+ 0x10424 => &.{0x1044C},
+ 0x10425 => &.{0x1044D},
+ 0x10426 => &.{0x1044E},
+ 0x10427 => &.{0x1044F},
+ 0x104B0 => &.{0x104D8},
+ 0x104B1 => &.{0x104D9},
+ 0x104B2 => &.{0x104DA},
+ 0x104B3 => &.{0x104DB},
+ 0x104B4 => &.{0x104DC},
+ 0x104B5 => &.{0x104DD},
+ 0x104B6 => &.{0x104DE},
+ 0x104B7 => &.{0x104DF},
+ 0x104B8 => &.{0x104E0},
+ 0x104B9 => &.{0x104E1},
+ 0x104BA => &.{0x104E2},
+ 0x104BB => &.{0x104E3},
+ 0x104BC => &.{0x104E4},
+ 0x104BD => &.{0x104E5},
+ 0x104BE => &.{0x104E6},
+ 0x104BF => &.{0x104E7},
+ 0x104C0 => &.{0x104E8},
+ 0x104C1 => &.{0x104E9},
+ 0x104C2 => &.{0x104EA},
+ 0x104C3 => &.{0x104EB},
+ 0x104C4 => &.{0x104EC},
+ 0x104C5 => &.{0x104ED},
+ 0x104C6 => &.{0x104EE},
+ 0x104C7 => &.{0x104EF},
+ 0x104C8 => &.{0x104F0},
+ 0x104C9 => &.{0x104F1},
+ 0x104CA => &.{0x104F2},
+ 0x104CB => &.{0x104F3},
+ 0x104CC => &.{0x104F4},
+ 0x104CD => &.{0x104F5},
+ 0x104CE => &.{0x104F6},
+ 0x104CF => &.{0x104F7},
+ 0x104D0 => &.{0x104F8},
+ 0x104D1 => &.{0x104F9},
+ 0x104D2 => &.{0x104FA},
+ 0x104D3 => &.{0x104FB},
+ 0x10570 => &.{0x10597},
+ 0x10571 => &.{0x10598},
+ 0x10572 => &.{0x10599},
+ 0x10573 => &.{0x1059A},
+ 0x10574 => &.{0x1059B},
+ 0x10575 => &.{0x1059C},
+ 0x10576 => &.{0x1059D},
+ 0x10577 => &.{0x1059E},
+ 0x10578 => &.{0x1059F},
+ 0x10579 => &.{0x105A0},
+ 0x1057A => &.{0x105A1},
+ 0x1057C => &.{0x105A3},
+ 0x1057D => &.{0x105A4},
+ 0x1057E => &.{0x105A5},
+ 0x1057F => &.{0x105A6},
+ 0x10580 => &.{0x105A7},
+ 0x10581 => &.{0x105A8},
+ 0x10582 => &.{0x105A9},
+ 0x10583 => &.{0x105AA},
+ 0x10584 => &.{0x105AB},
+ 0x10585 => &.{0x105AC},
+ 0x10586 => &.{0x105AD},
+ 0x10587 => &.{0x105AE},
+ 0x10588 => &.{0x105AF},
+ 0x10589 => &.{0x105B0},
+ 0x1058A => &.{0x105B1},
+ 0x1058C => &.{0x105B3},
+ 0x1058D => &.{0x105B4},
+ 0x1058E => &.{0x105B5},
+ 0x1058F => &.{0x105B6},
+ 0x10590 => &.{0x105B7},
+ 0x10591 => &.{0x105B8},
+ 0x10592 => &.{0x105B9},
+ 0x10594 => &.{0x105BB},
+ 0x10595 => &.{0x105BC},
+ 0x10781 => &.{0x2D0},
+ 0x10782 => &.{0x2D1},
+ 0x10783 => &.{0xE6},
+ 0x10784 => &.{0x299},
+ 0x10785 => &.{0x253},
+ 0x10787 => &.{0x2A3},
+ 0x10788 => &.{0xAB66},
+ 0x10789 => &.{0x2A5},
+ 0x1078A => &.{0x2A4},
+ 0x1078B => &.{0x256},
+ 0x1078C => &.{0x257},
+ 0x1078D => &.{0x1D91},
+ 0x1078E => &.{0x258},
+ 0x1078F => &.{0x25E},
+ 0x10790 => &.{0x2A9},
+ 0x10791 => &.{0x264},
+ 0x10792 => &.{0x262},
+ 0x10793 => &.{0x260},
+ 0x10794 => &.{0x29B},
+ 0x10795 => &.{0x127},
+ 0x10796 => &.{0x29C},
+ 0x10797 => &.{0x267},
+ 0x10798 => &.{0x284},
+ 0x10799 => &.{0x2AA},
+ 0x1079A => &.{0x2AB},
+ 0x1079B => &.{0x26C},
+ 0x1079C => &.{0x1DF04},
+ 0x1079D => &.{0xA78E},
+ 0x1079E => &.{0x26E},
+ 0x1079F => &.{0x1DF05},
+ 0x107A0 => &.{0x28E},
+ 0x107A1 => &.{0x1DF06},
+ 0x107A2 => &.{0xF8},
+ 0x107A3 => &.{0x276},
+ 0x107A4 => &.{0x277},
+ 0x107A5 => &.{0x71},
+ 0x107A6 => &.{0x27A},
+ 0x107A7 => &.{0x1DF08},
+ 0x107A8 => &.{0x27D},
+ 0x107A9 => &.{0x27E},
+ 0x107AA => &.{0x280},
+ 0x107AB => &.{0x2A8},
+ 0x107AC => &.{0x2A6},
+ 0x107AD => &.{0xAB67},
+ 0x107AE => &.{0x2A7},
+ 0x107AF => &.{0x288},
+ 0x107B0 => &.{0x2C71},
+ 0x107B2 => &.{0x28F},
+ 0x107B3 => &.{0x2A1},
+ 0x107B4 => &.{0x2A2},
+ 0x107B5 => &.{0x298},
+ 0x107B6 => &.{0x1C0},
+ 0x107B7 => &.{0x1C1},
+ 0x107B8 => &.{0x1C2},
+ 0x107B9 => &.{0x1DF0A},
+ 0x107BA => &.{0x1DF1E},
+ 0x10C80 => &.{0x10CC0},
+ 0x10C81 => &.{0x10CC1},
+ 0x10C82 => &.{0x10CC2},
+ 0x10C83 => &.{0x10CC3},
+ 0x10C84 => &.{0x10CC4},
+ 0x10C85 => &.{0x10CC5},
+ 0x10C86 => &.{0x10CC6},
+ 0x10C87 => &.{0x10CC7},
+ 0x10C88 => &.{0x10CC8},
+ 0x10C89 => &.{0x10CC9},
+ 0x10C8A => &.{0x10CCA},
+ 0x10C8B => &.{0x10CCB},
+ 0x10C8C => &.{0x10CCC},
+ 0x10C8D => &.{0x10CCD},
+ 0x10C8E => &.{0x10CCE},
+ 0x10C8F => &.{0x10CCF},
+ 0x10C90 => &.{0x10CD0},
+ 0x10C91 => &.{0x10CD1},
+ 0x10C92 => &.{0x10CD2},
+ 0x10C93 => &.{0x10CD3},
+ 0x10C94 => &.{0x10CD4},
+ 0x10C95 => &.{0x10CD5},
+ 0x10C96 => &.{0x10CD6},
+ 0x10C97 => &.{0x10CD7},
+ 0x10C98 => &.{0x10CD8},
+ 0x10C99 => &.{0x10CD9},
+ 0x10C9A => &.{0x10CDA},
+ 0x10C9B => &.{0x10CDB},
+ 0x10C9C => &.{0x10CDC},
+ 0x10C9D => &.{0x10CDD},
+ 0x10C9E => &.{0x10CDE},
+ 0x10C9F => &.{0x10CDF},
+ 0x10CA0 => &.{0x10CE0},
+ 0x10CA1 => &.{0x10CE1},
+ 0x10CA2 => &.{0x10CE2},
+ 0x10CA3 => &.{0x10CE3},
+ 0x10CA4 => &.{0x10CE4},
+ 0x10CA5 => &.{0x10CE5},
+ 0x10CA6 => &.{0x10CE6},
+ 0x10CA7 => &.{0x10CE7},
+ 0x10CA8 => &.{0x10CE8},
+ 0x10CA9 => &.{0x10CE9},
+ 0x10CAA => &.{0x10CEA},
+ 0x10CAB => &.{0x10CEB},
+ 0x10CAC => &.{0x10CEC},
+ 0x10CAD => &.{0x10CED},
+ 0x10CAE => &.{0x10CEE},
+ 0x10CAF => &.{0x10CEF},
+ 0x10CB0 => &.{0x10CF0},
+ 0x10CB1 => &.{0x10CF1},
+ 0x10CB2 => &.{0x10CF2},
+ 0x118A0 => &.{0x118C0},
+ 0x118A1 => &.{0x118C1},
+ 0x118A2 => &.{0x118C2},
+ 0x118A3 => &.{0x118C3},
+ 0x118A4 => &.{0x118C4},
+ 0x118A5 => &.{0x118C5},
+ 0x118A6 => &.{0x118C6},
+ 0x118A7 => &.{0x118C7},
+ 0x118A8 => &.{0x118C8},
+ 0x118A9 => &.{0x118C9},
+ 0x118AA => &.{0x118CA},
+ 0x118AB => &.{0x118CB},
+ 0x118AC => &.{0x118CC},
+ 0x118AD => &.{0x118CD},
+ 0x118AE => &.{0x118CE},
+ 0x118AF => &.{0x118CF},
+ 0x118B0 => &.{0x118D0},
+ 0x118B1 => &.{0x118D1},
+ 0x118B2 => &.{0x118D2},
+ 0x118B3 => &.{0x118D3},
+ 0x118B4 => &.{0x118D4},
+ 0x118B5 => &.{0x118D5},
+ 0x118B6 => &.{0x118D6},
+ 0x118B7 => &.{0x118D7},
+ 0x118B8 => &.{0x118D8},
+ 0x118B9 => &.{0x118D9},
+ 0x118BA => &.{0x118DA},
+ 0x118BB => &.{0x118DB},
+ 0x118BC => &.{0x118DC},
+ 0x118BD => &.{0x118DD},
+ 0x118BE => &.{0x118DE},
+ 0x118BF => &.{0x118DF},
+ 0x16E40 => &.{0x16E60},
+ 0x16E41 => &.{0x16E61},
+ 0x16E42 => &.{0x16E62},
+ 0x16E43 => &.{0x16E63},
+ 0x16E44 => &.{0x16E64},
+ 0x16E45 => &.{0x16E65},
+ 0x16E46 => &.{0x16E66},
+ 0x16E47 => &.{0x16E67},
+ 0x16E48 => &.{0x16E68},
+ 0x16E49 => &.{0x16E69},
+ 0x16E4A => &.{0x16E6A},
+ 0x16E4B => &.{0x16E6B},
+ 0x16E4C => &.{0x16E6C},
+ 0x16E4D => &.{0x16E6D},
+ 0x16E4E => &.{0x16E6E},
+ 0x16E4F => &.{0x16E6F},
+ 0x16E50 => &.{0x16E70},
+ 0x16E51 => &.{0x16E71},
+ 0x16E52 => &.{0x16E72},
+ 0x16E53 => &.{0x16E73},
+ 0x16E54 => &.{0x16E74},
+ 0x16E55 => &.{0x16E75},
+ 0x16E56 => &.{0x16E76},
+ 0x16E57 => &.{0x16E77},
+ 0x16E58 => &.{0x16E78},
+ 0x16E59 => &.{0x16E79},
+ 0x16E5A => &.{0x16E7A},
+ 0x16E5B => &.{0x16E7B},
+ 0x16E5C => &.{0x16E7C},
+ 0x16E5D => &.{0x16E7D},
+ 0x16E5E => &.{0x16E7E},
+ 0x16E5F => &.{0x16E7F},
+ 0x1BCA0...0x1BCA3 => null,
+ 0x1D15E => &.{ 0x1D157, 0x1D165 },
+ 0x1D15F => &.{ 0x1D158, 0x1D165 },
+ 0x1D160 => &.{ 0x1D158, 0x1D165, 0x1D16E },
+ 0x1D161 => &.{ 0x1D158, 0x1D165, 0x1D16F },
+ 0x1D162 => &.{ 0x1D158, 0x1D165, 0x1D170 },
+ 0x1D163 => &.{ 0x1D158, 0x1D165, 0x1D171 },
+ 0x1D164 => &.{ 0x1D158, 0x1D165, 0x1D172 },
+ 0x1D173...0x1D17A => null,
+ 0x1D1BB => &.{ 0x1D1B9, 0x1D165 },
+ 0x1D1BC => &.{ 0x1D1BA, 0x1D165 },
+ 0x1D1BD => &.{ 0x1D1B9, 0x1D165, 0x1D16E },
+ 0x1D1BE => &.{ 0x1D1BA, 0x1D165, 0x1D16E },
+ 0x1D1BF => &.{ 0x1D1B9, 0x1D165, 0x1D16F },
+ 0x1D1C0 => &.{ 0x1D1BA, 0x1D165, 0x1D16F },
+ 0x1D400 => &.{0x61},
+ 0x1D401 => &.{0x62},
+ 0x1D402 => &.{0x63},
+ 0x1D403 => &.{0x64},
+ 0x1D404 => &.{0x65},
+ 0x1D405 => &.{0x66},
+ 0x1D406 => &.{0x67},
+ 0x1D407 => &.{0x68},
+ 0x1D408 => &.{0x69},
+ 0x1D409 => &.{0x6A},
+ 0x1D40A => &.{0x6B},
+ 0x1D40B => &.{0x6C},
+ 0x1D40C => &.{0x6D},
+ 0x1D40D => &.{0x6E},
+ 0x1D40E => &.{0x6F},
+ 0x1D40F => &.{0x70},
+ 0x1D410 => &.{0x71},
+ 0x1D411 => &.{0x72},
+ 0x1D412 => &.{0x73},
+ 0x1D413 => &.{0x74},
+ 0x1D414 => &.{0x75},
+ 0x1D415 => &.{0x76},
+ 0x1D416 => &.{0x77},
+ 0x1D417 => &.{0x78},
+ 0x1D418 => &.{0x79},
+ 0x1D419 => &.{0x7A},
+ 0x1D41A => &.{0x61},
+ 0x1D41B => &.{0x62},
+ 0x1D41C => &.{0x63},
+ 0x1D41D => &.{0x64},
+ 0x1D41E => &.{0x65},
+ 0x1D41F => &.{0x66},
+ 0x1D420 => &.{0x67},
+ 0x1D421 => &.{0x68},
+ 0x1D422 => &.{0x69},
+ 0x1D423 => &.{0x6A},
+ 0x1D424 => &.{0x6B},
+ 0x1D425 => &.{0x6C},
+ 0x1D426 => &.{0x6D},
+ 0x1D427 => &.{0x6E},
+ 0x1D428 => &.{0x6F},
+ 0x1D429 => &.{0x70},
+ 0x1D42A => &.{0x71},
+ 0x1D42B => &.{0x72},
+ 0x1D42C => &.{0x73},
+ 0x1D42D => &.{0x74},
+ 0x1D42E => &.{0x75},
+ 0x1D42F => &.{0x76},
+ 0x1D430 => &.{0x77},
+ 0x1D431 => &.{0x78},
+ 0x1D432 => &.{0x79},
+ 0x1D433 => &.{0x7A},
+ 0x1D434 => &.{0x61},
+ 0x1D435 => &.{0x62},
+ 0x1D436 => &.{0x63},
+ 0x1D437 => &.{0x64},
+ 0x1D438 => &.{0x65},
+ 0x1D439 => &.{0x66},
+ 0x1D43A => &.{0x67},
+ 0x1D43B => &.{0x68},
+ 0x1D43C => &.{0x69},
+ 0x1D43D => &.{0x6A},
+ 0x1D43E => &.{0x6B},
+ 0x1D43F => &.{0x6C},
+ 0x1D440 => &.{0x6D},
+ 0x1D441 => &.{0x6E},
+ 0x1D442 => &.{0x6F},
+ 0x1D443 => &.{0x70},
+ 0x1D444 => &.{0x71},
+ 0x1D445 => &.{0x72},
+ 0x1D446 => &.{0x73},
+ 0x1D447 => &.{0x74},
+ 0x1D448 => &.{0x75},
+ 0x1D449 => &.{0x76},
+ 0x1D44A => &.{0x77},
+ 0x1D44B => &.{0x78},
+ 0x1D44C => &.{0x79},
+ 0x1D44D => &.{0x7A},
+ 0x1D44E => &.{0x61},
+ 0x1D44F => &.{0x62},
+ 0x1D450 => &.{0x63},
+ 0x1D451 => &.{0x64},
+ 0x1D452 => &.{0x65},
+ 0x1D453 => &.{0x66},
+ 0x1D454 => &.{0x67},
+ 0x1D456 => &.{0x69},
+ 0x1D457 => &.{0x6A},
+ 0x1D458 => &.{0x6B},
+ 0x1D459 => &.{0x6C},
+ 0x1D45A => &.{0x6D},
+ 0x1D45B => &.{0x6E},
+ 0x1D45C => &.{0x6F},
+ 0x1D45D => &.{0x70},
+ 0x1D45E => &.{0x71},
+ 0x1D45F => &.{0x72},
+ 0x1D460 => &.{0x73},
+ 0x1D461 => &.{0x74},
+ 0x1D462 => &.{0x75},
+ 0x1D463 => &.{0x76},
+ 0x1D464 => &.{0x77},
+ 0x1D465 => &.{0x78},
+ 0x1D466 => &.{0x79},
+ 0x1D467 => &.{0x7A},
+ 0x1D468 => &.{0x61},
+ 0x1D469 => &.{0x62},
+ 0x1D46A => &.{0x63},
+ 0x1D46B => &.{0x64},
+ 0x1D46C => &.{0x65},
+ 0x1D46D => &.{0x66},
+ 0x1D46E => &.{0x67},
+ 0x1D46F => &.{0x68},
+ 0x1D470 => &.{0x69},
+ 0x1D471 => &.{0x6A},
+ 0x1D472 => &.{0x6B},
+ 0x1D473 => &.{0x6C},
+ 0x1D474 => &.{0x6D},
+ 0x1D475 => &.{0x6E},
+ 0x1D476 => &.{0x6F},
+ 0x1D477 => &.{0x70},
+ 0x1D478 => &.{0x71},
+ 0x1D479 => &.{0x72},
+ 0x1D47A => &.{0x73},
+ 0x1D47B => &.{0x74},
+ 0x1D47C => &.{0x75},
+ 0x1D47D => &.{0x76},
+ 0x1D47E => &.{0x77},
+ 0x1D47F => &.{0x78},
+ 0x1D480 => &.{0x79},
+ 0x1D481 => &.{0x7A},
+ 0x1D482 => &.{0x61},
+ 0x1D483 => &.{0x62},
+ 0x1D484 => &.{0x63},
+ 0x1D485 => &.{0x64},
+ 0x1D486 => &.{0x65},
+ 0x1D487 => &.{0x66},
+ 0x1D488 => &.{0x67},
+ 0x1D489 => &.{0x68},
+ 0x1D48A => &.{0x69},
+ 0x1D48B => &.{0x6A},
+ 0x1D48C => &.{0x6B},
+ 0x1D48D => &.{0x6C},
+ 0x1D48E => &.{0x6D},
+ 0x1D48F => &.{0x6E},
+ 0x1D490 => &.{0x6F},
+ 0x1D491 => &.{0x70},
+ 0x1D492 => &.{0x71},
+ 0x1D493 => &.{0x72},
+ 0x1D494 => &.{0x73},
+ 0x1D495 => &.{0x74},
+ 0x1D496 => &.{0x75},
+ 0x1D497 => &.{0x76},
+ 0x1D498 => &.{0x77},
+ 0x1D499 => &.{0x78},
+ 0x1D49A => &.{0x79},
+ 0x1D49B => &.{0x7A},
+ 0x1D49C => &.{0x61},
+ 0x1D49E => &.{0x63},
+ 0x1D49F => &.{0x64},
+ 0x1D4A2 => &.{0x67},
+ 0x1D4A5 => &.{0x6A},
+ 0x1D4A6 => &.{0x6B},
+ 0x1D4A9 => &.{0x6E},
+ 0x1D4AA => &.{0x6F},
+ 0x1D4AB => &.{0x70},
+ 0x1D4AC => &.{0x71},
+ 0x1D4AE => &.{0x73},
+ 0x1D4AF => &.{0x74},
+ 0x1D4B0 => &.{0x75},
+ 0x1D4B1 => &.{0x76},
+ 0x1D4B2 => &.{0x77},
+ 0x1D4B3 => &.{0x78},
+ 0x1D4B4 => &.{0x79},
+ 0x1D4B5 => &.{0x7A},
+ 0x1D4B6 => &.{0x61},
+ 0x1D4B7 => &.{0x62},
+ 0x1D4B8 => &.{0x63},
+ 0x1D4B9 => &.{0x64},
+ 0x1D4BB => &.{0x66},
+ 0x1D4BD => &.{0x68},
+ 0x1D4BE => &.{0x69},
+ 0x1D4BF => &.{0x6A},
+ 0x1D4C0 => &.{0x6B},
+ 0x1D4C1 => &.{0x6C},
+ 0x1D4C2 => &.{0x6D},
+ 0x1D4C3 => &.{0x6E},
+ 0x1D4C5 => &.{0x70},
+ 0x1D4C6 => &.{0x71},
+ 0x1D4C7 => &.{0x72},
+ 0x1D4C8 => &.{0x73},
+ 0x1D4C9 => &.{0x74},
+ 0x1D4CA => &.{0x75},
+ 0x1D4CB => &.{0x76},
+ 0x1D4CC => &.{0x77},
+ 0x1D4CD => &.{0x78},
+ 0x1D4CE => &.{0x79},
+ 0x1D4CF => &.{0x7A},
+ 0x1D4D0 => &.{0x61},
+ 0x1D4D1 => &.{0x62},
+ 0x1D4D2 => &.{0x63},
+ 0x1D4D3 => &.{0x64},
+ 0x1D4D4 => &.{0x65},
+ 0x1D4D5 => &.{0x66},
+ 0x1D4D6 => &.{0x67},
+ 0x1D4D7 => &.{0x68},
+ 0x1D4D8 => &.{0x69},
+ 0x1D4D9 => &.{0x6A},
+ 0x1D4DA => &.{0x6B},
+ 0x1D4DB => &.{0x6C},
+ 0x1D4DC => &.{0x6D},
+ 0x1D4DD => &.{0x6E},
+ 0x1D4DE => &.{0x6F},
+ 0x1D4DF => &.{0x70},
+ 0x1D4E0 => &.{0x71},
+ 0x1D4E1 => &.{0x72},
+ 0x1D4E2 => &.{0x73},
+ 0x1D4E3 => &.{0x74},
+ 0x1D4E4 => &.{0x75},
+ 0x1D4E5 => &.{0x76},
+ 0x1D4E6 => &.{0x77},
+ 0x1D4E7 => &.{0x78},
+ 0x1D4E8 => &.{0x79},
+ 0x1D4E9 => &.{0x7A},
+ 0x1D4EA => &.{0x61},
+ 0x1D4EB => &.{0x62},
+ 0x1D4EC => &.{0x63},
+ 0x1D4ED => &.{0x64},
+ 0x1D4EE => &.{0x65},
+ 0x1D4EF => &.{0x66},
+ 0x1D4F0 => &.{0x67},
+ 0x1D4F1 => &.{0x68},
+ 0x1D4F2 => &.{0x69},
+ 0x1D4F3 => &.{0x6A},
+ 0x1D4F4 => &.{0x6B},
+ 0x1D4F5 => &.{0x6C},
+ 0x1D4F6 => &.{0x6D},
+ 0x1D4F7 => &.{0x6E},
+ 0x1D4F8 => &.{0x6F},
+ 0x1D4F9 => &.{0x70},
+ 0x1D4FA => &.{0x71},
+ 0x1D4FB => &.{0x72},
+ 0x1D4FC => &.{0x73},
+ 0x1D4FD => &.{0x74},
+ 0x1D4FE => &.{0x75},
+ 0x1D4FF => &.{0x76},
+ 0x1D500 => &.{0x77},
+ 0x1D501 => &.{0x78},
+ 0x1D502 => &.{0x79},
+ 0x1D503 => &.{0x7A},
+ 0x1D504 => &.{0x61},
+ 0x1D505 => &.{0x62},
+ 0x1D507 => &.{0x64},
+ 0x1D508 => &.{0x65},
+ 0x1D509 => &.{0x66},
+ 0x1D50A => &.{0x67},
+ 0x1D50D => &.{0x6A},
+ 0x1D50E => &.{0x6B},
+ 0x1D50F => &.{0x6C},
+ 0x1D510 => &.{0x6D},
+ 0x1D511 => &.{0x6E},
+ 0x1D512 => &.{0x6F},
+ 0x1D513 => &.{0x70},
+ 0x1D514 => &.{0x71},
+ 0x1D516 => &.{0x73},
+ 0x1D517 => &.{0x74},
+ 0x1D518 => &.{0x75},
+ 0x1D519 => &.{0x76},
+ 0x1D51A => &.{0x77},
+ 0x1D51B => &.{0x78},
+ 0x1D51C => &.{0x79},
+ 0x1D51E => &.{0x61},
+ 0x1D51F => &.{0x62},
+ 0x1D520 => &.{0x63},
+ 0x1D521 => &.{0x64},
+ 0x1D522 => &.{0x65},
+ 0x1D523 => &.{0x66},
+ 0x1D524 => &.{0x67},
+ 0x1D525 => &.{0x68},
+ 0x1D526 => &.{0x69},
+ 0x1D527 => &.{0x6A},
+ 0x1D528 => &.{0x6B},
+ 0x1D529 => &.{0x6C},
+ 0x1D52A => &.{0x6D},
+ 0x1D52B => &.{0x6E},
+ 0x1D52C => &.{0x6F},
+ 0x1D52D => &.{0x70},
+ 0x1D52E => &.{0x71},
+ 0x1D52F => &.{0x72},
+ 0x1D530 => &.{0x73},
+ 0x1D531 => &.{0x74},
+ 0x1D532 => &.{0x75},
+ 0x1D533 => &.{0x76},
+ 0x1D534 => &.{0x77},
+ 0x1D535 => &.{0x78},
+ 0x1D536 => &.{0x79},
+ 0x1D537 => &.{0x7A},
+ 0x1D538 => &.{0x61},
+ 0x1D539 => &.{0x62},
+ 0x1D53B => &.{0x64},
+ 0x1D53C => &.{0x65},
+ 0x1D53D => &.{0x66},
+ 0x1D53E => &.{0x67},
+ 0x1D540 => &.{0x69},
+ 0x1D541 => &.{0x6A},
+ 0x1D542 => &.{0x6B},
+ 0x1D543 => &.{0x6C},
+ 0x1D544 => &.{0x6D},
+ 0x1D546 => &.{0x6F},
+ 0x1D54A => &.{0x73},
+ 0x1D54B => &.{0x74},
+ 0x1D54C => &.{0x75},
+ 0x1D54D => &.{0x76},
+ 0x1D54E => &.{0x77},
+ 0x1D54F => &.{0x78},
+ 0x1D550 => &.{0x79},
+ 0x1D552 => &.{0x61},
+ 0x1D553 => &.{0x62},
+ 0x1D554 => &.{0x63},
+ 0x1D555 => &.{0x64},
+ 0x1D556 => &.{0x65},
+ 0x1D557 => &.{0x66},
+ 0x1D558 => &.{0x67},
+ 0x1D559 => &.{0x68},
+ 0x1D55A => &.{0x69},
+ 0x1D55B => &.{0x6A},
+ 0x1D55C => &.{0x6B},
+ 0x1D55D => &.{0x6C},
+ 0x1D55E => &.{0x6D},
+ 0x1D55F => &.{0x6E},
+ 0x1D560 => &.{0x6F},
+ 0x1D561 => &.{0x70},
+ 0x1D562 => &.{0x71},
+ 0x1D563 => &.{0x72},
+ 0x1D564 => &.{0x73},
+ 0x1D565 => &.{0x74},
+ 0x1D566 => &.{0x75},
+ 0x1D567 => &.{0x76},
+ 0x1D568 => &.{0x77},
+ 0x1D569 => &.{0x78},
+ 0x1D56A => &.{0x79},
+ 0x1D56B => &.{0x7A},
+ 0x1D56C => &.{0x61},
+ 0x1D56D => &.{0x62},
+ 0x1D56E => &.{0x63},
+ 0x1D56F => &.{0x64},
+ 0x1D570 => &.{0x65},
+ 0x1D571 => &.{0x66},
+ 0x1D572 => &.{0x67},
+ 0x1D573 => &.{0x68},
+ 0x1D574 => &.{0x69},
+ 0x1D575 => &.{0x6A},
+ 0x1D576 => &.{0x6B},
+ 0x1D577 => &.{0x6C},
+ 0x1D578 => &.{0x6D},
+ 0x1D579 => &.{0x6E},
+ 0x1D57A => &.{0x6F},
+ 0x1D57B => &.{0x70},
+ 0x1D57C => &.{0x71},
+ 0x1D57D => &.{0x72},
+ 0x1D57E => &.{0x73},
+ 0x1D57F => &.{0x74},
+ 0x1D580 => &.{0x75},
+ 0x1D581 => &.{0x76},
+ 0x1D582 => &.{0x77},
+ 0x1D583 => &.{0x78},
+ 0x1D584 => &.{0x79},
+ 0x1D585 => &.{0x7A},
+ 0x1D586 => &.{0x61},
+ 0x1D587 => &.{0x62},
+ 0x1D588 => &.{0x63},
+ 0x1D589 => &.{0x64},
+ 0x1D58A => &.{0x65},
+ 0x1D58B => &.{0x66},
+ 0x1D58C => &.{0x67},
+ 0x1D58D => &.{0x68},
+ 0x1D58E => &.{0x69},
+ 0x1D58F => &.{0x6A},
+ 0x1D590 => &.{0x6B},
+ 0x1D591 => &.{0x6C},
+ 0x1D592 => &.{0x6D},
+ 0x1D593 => &.{0x6E},
+ 0x1D594 => &.{0x6F},
+ 0x1D595 => &.{0x70},
+ 0x1D596 => &.{0x71},
+ 0x1D597 => &.{0x72},
+ 0x1D598 => &.{0x73},
+ 0x1D599 => &.{0x74},
+ 0x1D59A => &.{0x75},
+ 0x1D59B => &.{0x76},
+ 0x1D59C => &.{0x77},
+ 0x1D59D => &.{0x78},
+ 0x1D59E => &.{0x79},
+ 0x1D59F => &.{0x7A},
+ 0x1D5A0 => &.{0x61},
+ 0x1D5A1 => &.{0x62},
+ 0x1D5A2 => &.{0x63},
+ 0x1D5A3 => &.{0x64},
+ 0x1D5A4 => &.{0x65},
+ 0x1D5A5 => &.{0x66},
+ 0x1D5A6 => &.{0x67},
+ 0x1D5A7 => &.{0x68},
+ 0x1D5A8 => &.{0x69},
+ 0x1D5A9 => &.{0x6A},
+ 0x1D5AA => &.{0x6B},
+ 0x1D5AB => &.{0x6C},
+ 0x1D5AC => &.{0x6D},
+ 0x1D5AD => &.{0x6E},
+ 0x1D5AE => &.{0x6F},
+ 0x1D5AF => &.{0x70},
+ 0x1D5B0 => &.{0x71},
+ 0x1D5B1 => &.{0x72},
+ 0x1D5B2 => &.{0x73},
+ 0x1D5B3 => &.{0x74},
+ 0x1D5B4 => &.{0x75},
+ 0x1D5B5 => &.{0x76},
+ 0x1D5B6 => &.{0x77},
+ 0x1D5B7 => &.{0x78},
+ 0x1D5B8 => &.{0x79},
+ 0x1D5B9 => &.{0x7A},
+ 0x1D5BA => &.{0x61},
+ 0x1D5BB => &.{0x62},
+ 0x1D5BC => &.{0x63},
+ 0x1D5BD => &.{0x64},
+ 0x1D5BE => &.{0x65},
+ 0x1D5BF => &.{0x66},
+ 0x1D5C0 => &.{0x67},
+ 0x1D5C1 => &.{0x68},
+ 0x1D5C2 => &.{0x69},
+ 0x1D5C3 => &.{0x6A},
+ 0x1D5C4 => &.{0x6B},
+ 0x1D5C5 => &.{0x6C},
+ 0x1D5C6 => &.{0x6D},
+ 0x1D5C7 => &.{0x6E},
+ 0x1D5C8 => &.{0x6F},
+ 0x1D5C9 => &.{0x70},
+ 0x1D5CA => &.{0x71},
+ 0x1D5CB => &.{0x72},
+ 0x1D5CC => &.{0x73},
+ 0x1D5CD => &.{0x74},
+ 0x1D5CE => &.{0x75},
+ 0x1D5CF => &.{0x76},
+ 0x1D5D0 => &.{0x77},
+ 0x1D5D1 => &.{0x78},
+ 0x1D5D2 => &.{0x79},
+ 0x1D5D3 => &.{0x7A},
+ 0x1D5D4 => &.{0x61},
+ 0x1D5D5 => &.{0x62},
+ 0x1D5D6 => &.{0x63},
+ 0x1D5D7 => &.{0x64},
+ 0x1D5D8 => &.{0x65},
+ 0x1D5D9 => &.{0x66},
+ 0x1D5DA => &.{0x67},
+ 0x1D5DB => &.{0x68},
+ 0x1D5DC => &.{0x69},
+ 0x1D5DD => &.{0x6A},
+ 0x1D5DE => &.{0x6B},
+ 0x1D5DF => &.{0x6C},
+ 0x1D5E0 => &.{0x6D},
+ 0x1D5E1 => &.{0x6E},
+ 0x1D5E2 => &.{0x6F},
+ 0x1D5E3 => &.{0x70},
+ 0x1D5E4 => &.{0x71},
+ 0x1D5E5 => &.{0x72},
+ 0x1D5E6 => &.{0x73},
+ 0x1D5E7 => &.{0x74},
+ 0x1D5E8 => &.{0x75},
+ 0x1D5E9 => &.{0x76},
+ 0x1D5EA => &.{0x77},
+ 0x1D5EB => &.{0x78},
+ 0x1D5EC => &.{0x79},
+ 0x1D5ED => &.{0x7A},
+ 0x1D5EE => &.{0x61},
+ 0x1D5EF => &.{0x62},
+ 0x1D5F0 => &.{0x63},
+ 0x1D5F1 => &.{0x64},
+ 0x1D5F2 => &.{0x65},
+ 0x1D5F3 => &.{0x66},
+ 0x1D5F4 => &.{0x67},
+ 0x1D5F5 => &.{0x68},
+ 0x1D5F6 => &.{0x69},
+ 0x1D5F7 => &.{0x6A},
+ 0x1D5F8 => &.{0x6B},
+ 0x1D5F9 => &.{0x6C},
+ 0x1D5FA => &.{0x6D},
+ 0x1D5FB => &.{0x6E},
+ 0x1D5FC => &.{0x6F},
+ 0x1D5FD => &.{0x70},
+ 0x1D5FE => &.{0x71},
+ 0x1D5FF => &.{0x72},
+ 0x1D600 => &.{0x73},
+ 0x1D601 => &.{0x74},
+ 0x1D602 => &.{0x75},
+ 0x1D603 => &.{0x76},
+ 0x1D604 => &.{0x77},
+ 0x1D605 => &.{0x78},
+ 0x1D606 => &.{0x79},
+ 0x1D607 => &.{0x7A},
+ 0x1D608 => &.{0x61},
+ 0x1D609 => &.{0x62},
+ 0x1D60A => &.{0x63},
+ 0x1D60B => &.{0x64},
+ 0x1D60C => &.{0x65},
+ 0x1D60D => &.{0x66},
+ 0x1D60E => &.{0x67},
+ 0x1D60F => &.{0x68},
+ 0x1D610 => &.{0x69},
+ 0x1D611 => &.{0x6A},
+ 0x1D612 => &.{0x6B},
+ 0x1D613 => &.{0x6C},
+ 0x1D614 => &.{0x6D},
+ 0x1D615 => &.{0x6E},
+ 0x1D616 => &.{0x6F},
+ 0x1D617 => &.{0x70},
+ 0x1D618 => &.{0x71},
+ 0x1D619 => &.{0x72},
+ 0x1D61A => &.{0x73},
+ 0x1D61B => &.{0x74},
+ 0x1D61C => &.{0x75},
+ 0x1D61D => &.{0x76},
+ 0x1D61E => &.{0x77},
+ 0x1D61F => &.{0x78},
+ 0x1D620 => &.{0x79},
+ 0x1D621 => &.{0x7A},
+ 0x1D622 => &.{0x61},
+ 0x1D623 => &.{0x62},
+ 0x1D624 => &.{0x63},
+ 0x1D625 => &.{0x64},
+ 0x1D626 => &.{0x65},
+ 0x1D627 => &.{0x66},
+ 0x1D628 => &.{0x67},
+ 0x1D629 => &.{0x68},
+ 0x1D62A => &.{0x69},
+ 0x1D62B => &.{0x6A},
+ 0x1D62C => &.{0x6B},
+ 0x1D62D => &.{0x6C},
+ 0x1D62E => &.{0x6D},
+ 0x1D62F => &.{0x6E},
+ 0x1D630 => &.{0x6F},
+ 0x1D631 => &.{0x70},
+ 0x1D632 => &.{0x71},
+ 0x1D633 => &.{0x72},
+ 0x1D634 => &.{0x73},
+ 0x1D635 => &.{0x74},
+ 0x1D636 => &.{0x75},
+ 0x1D637 => &.{0x76},
+ 0x1D638 => &.{0x77},
+ 0x1D639 => &.{0x78},
+ 0x1D63A => &.{0x79},
+ 0x1D63B => &.{0x7A},
+ 0x1D63C => &.{0x61},
+ 0x1D63D => &.{0x62},
+ 0x1D63E => &.{0x63},
+ 0x1D63F => &.{0x64},
+ 0x1D640 => &.{0x65},
+ 0x1D641 => &.{0x66},
+ 0x1D642 => &.{0x67},
+ 0x1D643 => &.{0x68},
+ 0x1D644 => &.{0x69},
+ 0x1D645 => &.{0x6A},
+ 0x1D646 => &.{0x6B},
+ 0x1D647 => &.{0x6C},
+ 0x1D648 => &.{0x6D},
+ 0x1D649 => &.{0x6E},
+ 0x1D64A => &.{0x6F},
+ 0x1D64B => &.{0x70},
+ 0x1D64C => &.{0x71},
+ 0x1D64D => &.{0x72},
+ 0x1D64E => &.{0x73},
+ 0x1D64F => &.{0x74},
+ 0x1D650 => &.{0x75},
+ 0x1D651 => &.{0x76},
+ 0x1D652 => &.{0x77},
+ 0x1D653 => &.{0x78},
+ 0x1D654 => &.{0x79},
+ 0x1D655 => &.{0x7A},
+ 0x1D656 => &.{0x61},
+ 0x1D657 => &.{0x62},
+ 0x1D658 => &.{0x63},
+ 0x1D659 => &.{0x64},
+ 0x1D65A => &.{0x65},
+ 0x1D65B => &.{0x66},
+ 0x1D65C => &.{0x67},
+ 0x1D65D => &.{0x68},
+ 0x1D65E => &.{0x69},
+ 0x1D65F => &.{0x6A},
+ 0x1D660 => &.{0x6B},
+ 0x1D661 => &.{0x6C},
+ 0x1D662 => &.{0x6D},
+ 0x1D663 => &.{0x6E},
+ 0x1D664 => &.{0x6F},
+ 0x1D665 => &.{0x70},
+ 0x1D666 => &.{0x71},
+ 0x1D667 => &.{0x72},
+ 0x1D668 => &.{0x73},
+ 0x1D669 => &.{0x74},
+ 0x1D66A => &.{0x75},
+ 0x1D66B => &.{0x76},
+ 0x1D66C => &.{0x77},
+ 0x1D66D => &.{0x78},
+ 0x1D66E => &.{0x79},
+ 0x1D66F => &.{0x7A},
+ 0x1D670 => &.{0x61},
+ 0x1D671 => &.{0x62},
+ 0x1D672 => &.{0x63},
+ 0x1D673 => &.{0x64},
+ 0x1D674 => &.{0x65},
+ 0x1D675 => &.{0x66},
+ 0x1D676 => &.{0x67},
+ 0x1D677 => &.{0x68},
+ 0x1D678 => &.{0x69},
+ 0x1D679 => &.{0x6A},
+ 0x1D67A => &.{0x6B},
+ 0x1D67B => &.{0x6C},
+ 0x1D67C => &.{0x6D},
+ 0x1D67D => &.{0x6E},
+ 0x1D67E => &.{0x6F},
+ 0x1D67F => &.{0x70},
+ 0x1D680 => &.{0x71},
+ 0x1D681 => &.{0x72},
+ 0x1D682 => &.{0x73},
+ 0x1D683 => &.{0x74},
+ 0x1D684 => &.{0x75},
+ 0x1D685 => &.{0x76},
+ 0x1D686 => &.{0x77},
+ 0x1D687 => &.{0x78},
+ 0x1D688 => &.{0x79},
+ 0x1D689 => &.{0x7A},
+ 0x1D68A => &.{0x61},
+ 0x1D68B => &.{0x62},
+ 0x1D68C => &.{0x63},
+ 0x1D68D => &.{0x64},
+ 0x1D68E => &.{0x65},
+ 0x1D68F => &.{0x66},
+ 0x1D690 => &.{0x67},
+ 0x1D691 => &.{0x68},
+ 0x1D692 => &.{0x69},
+ 0x1D693 => &.{0x6A},
+ 0x1D694 => &.{0x6B},
+ 0x1D695 => &.{0x6C},
+ 0x1D696 => &.{0x6D},
+ 0x1D697 => &.{0x6E},
+ 0x1D698 => &.{0x6F},
+ 0x1D699 => &.{0x70},
+ 0x1D69A => &.{0x71},
+ 0x1D69B => &.{0x72},
+ 0x1D69C => &.{0x73},
+ 0x1D69D => &.{0x74},
+ 0x1D69E => &.{0x75},
+ 0x1D69F => &.{0x76},
+ 0x1D6A0 => &.{0x77},
+ 0x1D6A1 => &.{0x78},
+ 0x1D6A2 => &.{0x79},
+ 0x1D6A3 => &.{0x7A},
+ 0x1D6A4 => &.{0x131},
+ 0x1D6A5 => &.{0x237},
+ 0x1D6A8 => &.{0x3B1},
+ 0x1D6A9 => &.{0x3B2},
+ 0x1D6AA => &.{0x3B3},
+ 0x1D6AB => &.{0x3B4},
+ 0x1D6AC => &.{0x3B5},
+ 0x1D6AD => &.{0x3B6},
+ 0x1D6AE => &.{0x3B7},
+ 0x1D6AF => &.{0x3B8},
+ 0x1D6B0 => &.{0x3B9},
+ 0x1D6B1 => &.{0x3BA},
+ 0x1D6B2 => &.{0x3BB},
+ 0x1D6B3 => &.{0x3BC},
+ 0x1D6B4 => &.{0x3BD},
+ 0x1D6B5 => &.{0x3BE},
+ 0x1D6B6 => &.{0x3BF},
+ 0x1D6B7 => &.{0x3C0},
+ 0x1D6B8 => &.{0x3C1},
+ 0x1D6B9 => &.{0x3B8},
+ 0x1D6BA => &.{0x3C3},
+ 0x1D6BB => &.{0x3C4},
+ 0x1D6BC => &.{0x3C5},
+ 0x1D6BD => &.{0x3C6},
+ 0x1D6BE => &.{0x3C7},
+ 0x1D6BF => &.{0x3C8},
+ 0x1D6C0 => &.{0x3C9},
+ 0x1D6C1 => &.{0x2207},
+ 0x1D6C2 => &.{0x3B1},
+ 0x1D6C3 => &.{0x3B2},
+ 0x1D6C4 => &.{0x3B3},
+ 0x1D6C5 => &.{0x3B4},
+ 0x1D6C6 => &.{0x3B5},
+ 0x1D6C7 => &.{0x3B6},
+ 0x1D6C8 => &.{0x3B7},
+ 0x1D6C9 => &.{0x3B8},
+ 0x1D6CA => &.{0x3B9},
+ 0x1D6CB => &.{0x3BA},
+ 0x1D6CC => &.{0x3BB},
+ 0x1D6CD => &.{0x3BC},
+ 0x1D6CE => &.{0x3BD},
+ 0x1D6CF => &.{0x3BE},
+ 0x1D6D0 => &.{0x3BF},
+ 0x1D6D1 => &.{0x3C0},
+ 0x1D6D2 => &.{0x3C1},
+ 0x1D6D3...0x1D6D4 => &.{0x3C3},
+ 0x1D6D5 => &.{0x3C4},
+ 0x1D6D6 => &.{0x3C5},
+ 0x1D6D7 => &.{0x3C6},
+ 0x1D6D8 => &.{0x3C7},
+ 0x1D6D9 => &.{0x3C8},
+ 0x1D6DA => &.{0x3C9},
+ 0x1D6DB => &.{0x2202},
+ 0x1D6DC => &.{0x3B5},
+ 0x1D6DD => &.{0x3B8},
+ 0x1D6DE => &.{0x3BA},
+ 0x1D6DF => &.{0x3C6},
+ 0x1D6E0 => &.{0x3C1},
+ 0x1D6E1 => &.{0x3C0},
+ 0x1D6E2 => &.{0x3B1},
+ 0x1D6E3 => &.{0x3B2},
+ 0x1D6E4 => &.{0x3B3},
+ 0x1D6E5 => &.{0x3B4},
+ 0x1D6E6 => &.{0x3B5},
+ 0x1D6E7 => &.{0x3B6},
+ 0x1D6E8 => &.{0x3B7},
+ 0x1D6E9 => &.{0x3B8},
+ 0x1D6EA => &.{0x3B9},
+ 0x1D6EB => &.{0x3BA},
+ 0x1D6EC => &.{0x3BB},
+ 0x1D6ED => &.{0x3BC},
+ 0x1D6EE => &.{0x3BD},
+ 0x1D6EF => &.{0x3BE},
+ 0x1D6F0 => &.{0x3BF},
+ 0x1D6F1 => &.{0x3C0},
+ 0x1D6F2 => &.{0x3C1},
+ 0x1D6F3 => &.{0x3B8},
+ 0x1D6F4 => &.{0x3C3},
+ 0x1D6F5 => &.{0x3C4},
+ 0x1D6F6 => &.{0x3C5},
+ 0x1D6F7 => &.{0x3C6},
+ 0x1D6F8 => &.{0x3C7},
+ 0x1D6F9 => &.{0x3C8},
+ 0x1D6FA => &.{0x3C9},
+ 0x1D6FB => &.{0x2207},
+ 0x1D6FC => &.{0x3B1},
+ 0x1D6FD => &.{0x3B2},
+ 0x1D6FE => &.{0x3B3},
+ 0x1D6FF => &.{0x3B4},
+ 0x1D700 => &.{0x3B5},
+ 0x1D701 => &.{0x3B6},
+ 0x1D702 => &.{0x3B7},
+ 0x1D703 => &.{0x3B8},
+ 0x1D704 => &.{0x3B9},
+ 0x1D705 => &.{0x3BA},
+ 0x1D706 => &.{0x3BB},
+ 0x1D707 => &.{0x3BC},
+ 0x1D708 => &.{0x3BD},
+ 0x1D709 => &.{0x3BE},
+ 0x1D70A => &.{0x3BF},
+ 0x1D70B => &.{0x3C0},
+ 0x1D70C => &.{0x3C1},
+ 0x1D70D...0x1D70E => &.{0x3C3},
+ 0x1D70F => &.{0x3C4},
+ 0x1D710 => &.{0x3C5},
+ 0x1D711 => &.{0x3C6},
+ 0x1D712 => &.{0x3C7},
+ 0x1D713 => &.{0x3C8},
+ 0x1D714 => &.{0x3C9},
+ 0x1D715 => &.{0x2202},
+ 0x1D716 => &.{0x3B5},
+ 0x1D717 => &.{0x3B8},
+ 0x1D718 => &.{0x3BA},
+ 0x1D719 => &.{0x3C6},
+ 0x1D71A => &.{0x3C1},
+ 0x1D71B => &.{0x3C0},
+ 0x1D71C => &.{0x3B1},
+ 0x1D71D => &.{0x3B2},
+ 0x1D71E => &.{0x3B3},
+ 0x1D71F => &.{0x3B4},
+ 0x1D720 => &.{0x3B5},
+ 0x1D721 => &.{0x3B6},
+ 0x1D722 => &.{0x3B7},
+ 0x1D723 => &.{0x3B8},
+ 0x1D724 => &.{0x3B9},
+ 0x1D725 => &.{0x3BA},
+ 0x1D726 => &.{0x3BB},
+ 0x1D727 => &.{0x3BC},
+ 0x1D728 => &.{0x3BD},
+ 0x1D729 => &.{0x3BE},
+ 0x1D72A => &.{0x3BF},
+ 0x1D72B => &.{0x3C0},
+ 0x1D72C => &.{0x3C1},
+ 0x1D72D => &.{0x3B8},
+ 0x1D72E => &.{0x3C3},
+ 0x1D72F => &.{0x3C4},
+ 0x1D730 => &.{0x3C5},
+ 0x1D731 => &.{0x3C6},
+ 0x1D732 => &.{0x3C7},
+ 0x1D733 => &.{0x3C8},
+ 0x1D734 => &.{0x3C9},
+ 0x1D735 => &.{0x2207},
+ 0x1D736 => &.{0x3B1},
+ 0x1D737 => &.{0x3B2},
+ 0x1D738 => &.{0x3B3},
+ 0x1D739 => &.{0x3B4},
+ 0x1D73A => &.{0x3B5},
+ 0x1D73B => &.{0x3B6},
+ 0x1D73C => &.{0x3B7},
+ 0x1D73D => &.{0x3B8},
+ 0x1D73E => &.{0x3B9},
+ 0x1D73F => &.{0x3BA},
+ 0x1D740 => &.{0x3BB},
+ 0x1D741 => &.{0x3BC},
+ 0x1D742 => &.{0x3BD},
+ 0x1D743 => &.{0x3BE},
+ 0x1D744 => &.{0x3BF},
+ 0x1D745 => &.{0x3C0},
+ 0x1D746 => &.{0x3C1},
+ 0x1D747...0x1D748 => &.{0x3C3},
+ 0x1D749 => &.{0x3C4},
+ 0x1D74A => &.{0x3C5},
+ 0x1D74B => &.{0x3C6},
+ 0x1D74C => &.{0x3C7},
+ 0x1D74D => &.{0x3C8},
+ 0x1D74E => &.{0x3C9},
+ 0x1D74F => &.{0x2202},
+ 0x1D750 => &.{0x3B5},
+ 0x1D751 => &.{0x3B8},
+ 0x1D752 => &.{0x3BA},
+ 0x1D753 => &.{0x3C6},
+ 0x1D754 => &.{0x3C1},
+ 0x1D755 => &.{0x3C0},
+ 0x1D756 => &.{0x3B1},
+ 0x1D757 => &.{0x3B2},
+ 0x1D758 => &.{0x3B3},
+ 0x1D759 => &.{0x3B4},
+ 0x1D75A => &.{0x3B5},
+ 0x1D75B => &.{0x3B6},
+ 0x1D75C => &.{0x3B7},
+ 0x1D75D => &.{0x3B8},
+ 0x1D75E => &.{0x3B9},
+ 0x1D75F => &.{0x3BA},
+ 0x1D760 => &.{0x3BB},
+ 0x1D761 => &.{0x3BC},
+ 0x1D762 => &.{0x3BD},
+ 0x1D763 => &.{0x3BE},
+ 0x1D764 => &.{0x3BF},
+ 0x1D765 => &.{0x3C0},
+ 0x1D766 => &.{0x3C1},
+ 0x1D767 => &.{0x3B8},
+ 0x1D768 => &.{0x3C3},
+ 0x1D769 => &.{0x3C4},
+ 0x1D76A => &.{0x3C5},
+ 0x1D76B => &.{0x3C6},
+ 0x1D76C => &.{0x3C7},
+ 0x1D76D => &.{0x3C8},
+ 0x1D76E => &.{0x3C9},
+ 0x1D76F => &.{0x2207},
+ 0x1D770 => &.{0x3B1},
+ 0x1D771 => &.{0x3B2},
+ 0x1D772 => &.{0x3B3},
+ 0x1D773 => &.{0x3B4},
+ 0x1D774 => &.{0x3B5},
+ 0x1D775 => &.{0x3B6},
+ 0x1D776 => &.{0x3B7},
+ 0x1D777 => &.{0x3B8},
+ 0x1D778 => &.{0x3B9},
+ 0x1D779 => &.{0x3BA},
+ 0x1D77A => &.{0x3BB},
+ 0x1D77B => &.{0x3BC},
+ 0x1D77C => &.{0x3BD},
+ 0x1D77D => &.{0x3BE},
+ 0x1D77E => &.{0x3BF},
+ 0x1D77F => &.{0x3C0},
+ 0x1D780 => &.{0x3C1},
+ 0x1D781...0x1D782 => &.{0x3C3},
+ 0x1D783 => &.{0x3C4},
+ 0x1D784 => &.{0x3C5},
+ 0x1D785 => &.{0x3C6},
+ 0x1D786 => &.{0x3C7},
+ 0x1D787 => &.{0x3C8},
+ 0x1D788 => &.{0x3C9},
+ 0x1D789 => &.{0x2202},
+ 0x1D78A => &.{0x3B5},
+ 0x1D78B => &.{0x3B8},
+ 0x1D78C => &.{0x3BA},
+ 0x1D78D => &.{0x3C6},
+ 0x1D78E => &.{0x3C1},
+ 0x1D78F => &.{0x3C0},
+ 0x1D790 => &.{0x3B1},
+ 0x1D791 => &.{0x3B2},
+ 0x1D792 => &.{0x3B3},
+ 0x1D793 => &.{0x3B4},
+ 0x1D794 => &.{0x3B5},
+ 0x1D795 => &.{0x3B6},
+ 0x1D796 => &.{0x3B7},
+ 0x1D797 => &.{0x3B8},
+ 0x1D798 => &.{0x3B9},
+ 0x1D799 => &.{0x3BA},
+ 0x1D79A => &.{0x3BB},
+ 0x1D79B => &.{0x3BC},
+ 0x1D79C => &.{0x3BD},
+ 0x1D79D => &.{0x3BE},
+ 0x1D79E => &.{0x3BF},
+ 0x1D79F => &.{0x3C0},
+ 0x1D7A0 => &.{0x3C1},
+ 0x1D7A1 => &.{0x3B8},
+ 0x1D7A2 => &.{0x3C3},
+ 0x1D7A3 => &.{0x3C4},
+ 0x1D7A4 => &.{0x3C5},
+ 0x1D7A5 => &.{0x3C6},
+ 0x1D7A6 => &.{0x3C7},
+ 0x1D7A7 => &.{0x3C8},
+ 0x1D7A8 => &.{0x3C9},
+ 0x1D7A9 => &.{0x2207},
+ 0x1D7AA => &.{0x3B1},
+ 0x1D7AB => &.{0x3B2},
+ 0x1D7AC => &.{0x3B3},
+ 0x1D7AD => &.{0x3B4},
+ 0x1D7AE => &.{0x3B5},
+ 0x1D7AF => &.{0x3B6},
+ 0x1D7B0 => &.{0x3B7},
+ 0x1D7B1 => &.{0x3B8},
+ 0x1D7B2 => &.{0x3B9},
+ 0x1D7B3 => &.{0x3BA},
+ 0x1D7B4 => &.{0x3BB},
+ 0x1D7B5 => &.{0x3BC},
+ 0x1D7B6 => &.{0x3BD},
+ 0x1D7B7 => &.{0x3BE},
+ 0x1D7B8 => &.{0x3BF},
+ 0x1D7B9 => &.{0x3C0},
+ 0x1D7BA => &.{0x3C1},
+ 0x1D7BB...0x1D7BC => &.{0x3C3},
+ 0x1D7BD => &.{0x3C4},
+ 0x1D7BE => &.{0x3C5},
+ 0x1D7BF => &.{0x3C6},
+ 0x1D7C0 => &.{0x3C7},
+ 0x1D7C1 => &.{0x3C8},
+ 0x1D7C2 => &.{0x3C9},
+ 0x1D7C3 => &.{0x2202},
+ 0x1D7C4 => &.{0x3B5},
+ 0x1D7C5 => &.{0x3B8},
+ 0x1D7C6 => &.{0x3BA},
+ 0x1D7C7 => &.{0x3C6},
+ 0x1D7C8 => &.{0x3C1},
+ 0x1D7C9 => &.{0x3C0},
+ 0x1D7CA...0x1D7CB => &.{0x3DD},
+ 0x1D7CE => &.{0x30},
+ 0x1D7CF => &.{0x31},
+ 0x1D7D0 => &.{0x32},
+ 0x1D7D1 => &.{0x33},
+ 0x1D7D2 => &.{0x34},
+ 0x1D7D3 => &.{0x35},
+ 0x1D7D4 => &.{0x36},
+ 0x1D7D5 => &.{0x37},
+ 0x1D7D6 => &.{0x38},
+ 0x1D7D7 => &.{0x39},
+ 0x1D7D8 => &.{0x30},
+ 0x1D7D9 => &.{0x31},
+ 0x1D7DA => &.{0x32},
+ 0x1D7DB => &.{0x33},
+ 0x1D7DC => &.{0x34},
+ 0x1D7DD => &.{0x35},
+ 0x1D7DE => &.{0x36},
+ 0x1D7DF => &.{0x37},
+ 0x1D7E0 => &.{0x38},
+ 0x1D7E1 => &.{0x39},
+ 0x1D7E2 => &.{0x30},
+ 0x1D7E3 => &.{0x31},
+ 0x1D7E4 => &.{0x32},
+ 0x1D7E5 => &.{0x33},
+ 0x1D7E6 => &.{0x34},
+ 0x1D7E7 => &.{0x35},
+ 0x1D7E8 => &.{0x36},
+ 0x1D7E9 => &.{0x37},
+ 0x1D7EA => &.{0x38},
+ 0x1D7EB => &.{0x39},
+ 0x1D7EC => &.{0x30},
+ 0x1D7ED => &.{0x31},
+ 0x1D7EE => &.{0x32},
+ 0x1D7EF => &.{0x33},
+ 0x1D7F0 => &.{0x34},
+ 0x1D7F1 => &.{0x35},
+ 0x1D7F2 => &.{0x36},
+ 0x1D7F3 => &.{0x37},
+ 0x1D7F4 => &.{0x38},
+ 0x1D7F5 => &.{0x39},
+ 0x1D7F6 => &.{0x30},
+ 0x1D7F7 => &.{0x31},
+ 0x1D7F8 => &.{0x32},
+ 0x1D7F9 => &.{0x33},
+ 0x1D7FA => &.{0x34},
+ 0x1D7FB => &.{0x35},
+ 0x1D7FC => &.{0x36},
+ 0x1D7FD => &.{0x37},
+ 0x1D7FE => &.{0x38},
+ 0x1D7FF => &.{0x39},
+ 0x1E030 => &.{0x430},
+ 0x1E031 => &.{0x431},
+ 0x1E032 => &.{0x432},
+ 0x1E033 => &.{0x433},
+ 0x1E034 => &.{0x434},
+ 0x1E035 => &.{0x435},
+ 0x1E036 => &.{0x436},
+ 0x1E037 => &.{0x437},
+ 0x1E038 => &.{0x438},
+ 0x1E039 => &.{0x43A},
+ 0x1E03A => &.{0x43B},
+ 0x1E03B => &.{0x43C},
+ 0x1E03C => &.{0x43E},
+ 0x1E03D => &.{0x43F},
+ 0x1E03E => &.{0x440},
+ 0x1E03F => &.{0x441},
+ 0x1E040 => &.{0x442},
+ 0x1E041 => &.{0x443},
+ 0x1E042 => &.{0x444},
+ 0x1E043 => &.{0x445},
+ 0x1E044 => &.{0x446},
+ 0x1E045 => &.{0x447},
+ 0x1E046 => &.{0x448},
+ 0x1E047 => &.{0x44B},
+ 0x1E048 => &.{0x44D},
+ 0x1E049 => &.{0x44E},
+ 0x1E04A => &.{0xA689},
+ 0x1E04B => &.{0x4D9},
+ 0x1E04C => &.{0x456},
+ 0x1E04D => &.{0x458},
+ 0x1E04E => &.{0x4E9},
+ 0x1E04F => &.{0x4AF},
+ 0x1E050 => &.{0x4CF},
+ 0x1E051 => &.{0x430},
+ 0x1E052 => &.{0x431},
+ 0x1E053 => &.{0x432},
+ 0x1E054 => &.{0x433},
+ 0x1E055 => &.{0x434},
+ 0x1E056 => &.{0x435},
+ 0x1E057 => &.{0x436},
+ 0x1E058 => &.{0x437},
+ 0x1E059 => &.{0x438},
+ 0x1E05A => &.{0x43A},
+ 0x1E05B => &.{0x43B},
+ 0x1E05C => &.{0x43E},
+ 0x1E05D => &.{0x43F},
+ 0x1E05E => &.{0x441},
+ 0x1E05F => &.{0x443},
+ 0x1E060 => &.{0x444},
+ 0x1E061 => &.{0x445},
+ 0x1E062 => &.{0x446},
+ 0x1E063 => &.{0x447},
+ 0x1E064 => &.{0x448},
+ 0x1E065 => &.{0x44A},
+ 0x1E066 => &.{0x44B},
+ 0x1E067 => &.{0x491},
+ 0x1E068 => &.{0x456},
+ 0x1E069 => &.{0x455},
+ 0x1E06A => &.{0x45F},
+ 0x1E06B => &.{0x4AB},
+ 0x1E06C => &.{0xA651},
+ 0x1E06D => &.{0x4B1},
+ 0x1E900 => &.{0x1E922},
+ 0x1E901 => &.{0x1E923},
+ 0x1E902 => &.{0x1E924},
+ 0x1E903 => &.{0x1E925},
+ 0x1E904 => &.{0x1E926},
+ 0x1E905 => &.{0x1E927},
+ 0x1E906 => &.{0x1E928},
+ 0x1E907 => &.{0x1E929},
+ 0x1E908 => &.{0x1E92A},
+ 0x1E909 => &.{0x1E92B},
+ 0x1E90A => &.{0x1E92C},
+ 0x1E90B => &.{0x1E92D},
+ 0x1E90C => &.{0x1E92E},
+ 0x1E90D => &.{0x1E92F},
+ 0x1E90E => &.{0x1E930},
+ 0x1E90F => &.{0x1E931},
+ 0x1E910 => &.{0x1E932},
+ 0x1E911 => &.{0x1E933},
+ 0x1E912 => &.{0x1E934},
+ 0x1E913 => &.{0x1E935},
+ 0x1E914 => &.{0x1E936},
+ 0x1E915 => &.{0x1E937},
+ 0x1E916 => &.{0x1E938},
+ 0x1E917 => &.{0x1E939},
+ 0x1E918 => &.{0x1E93A},
+ 0x1E919 => &.{0x1E93B},
+ 0x1E91A => &.{0x1E93C},
+ 0x1E91B => &.{0x1E93D},
+ 0x1E91C => &.{0x1E93E},
+ 0x1E91D => &.{0x1E93F},
+ 0x1E91E => &.{0x1E940},
+ 0x1E91F => &.{0x1E941},
+ 0x1E920 => &.{0x1E942},
+ 0x1E921 => &.{0x1E943},
+ 0x1EE00 => &.{0x627},
+ 0x1EE01 => &.{0x628},
+ 0x1EE02 => &.{0x62C},
+ 0x1EE03 => &.{0x62F},
+ 0x1EE05 => &.{0x648},
+ 0x1EE06 => &.{0x632},
+ 0x1EE07 => &.{0x62D},
+ 0x1EE08 => &.{0x637},
+ 0x1EE09 => &.{0x64A},
+ 0x1EE0A => &.{0x643},
+ 0x1EE0B => &.{0x644},
+ 0x1EE0C => &.{0x645},
+ 0x1EE0D => &.{0x646},
+ 0x1EE0E => &.{0x633},
+ 0x1EE0F => &.{0x639},
+ 0x1EE10 => &.{0x641},
+ 0x1EE11 => &.{0x635},
+ 0x1EE12 => &.{0x642},
+ 0x1EE13 => &.{0x631},
+ 0x1EE14 => &.{0x634},
+ 0x1EE15 => &.{0x62A},
+ 0x1EE16 => &.{0x62B},
+ 0x1EE17 => &.{0x62E},
+ 0x1EE18 => &.{0x630},
+ 0x1EE19 => &.{0x636},
+ 0x1EE1A => &.{0x638},
+ 0x1EE1B => &.{0x63A},
+ 0x1EE1C => &.{0x66E},
+ 0x1EE1D => &.{0x6BA},
+ 0x1EE1E => &.{0x6A1},
+ 0x1EE1F => &.{0x66F},
+ 0x1EE21 => &.{0x628},
+ 0x1EE22 => &.{0x62C},
+ 0x1EE24 => &.{0x647},
+ 0x1EE27 => &.{0x62D},
+ 0x1EE29 => &.{0x64A},
+ 0x1EE2A => &.{0x643},
+ 0x1EE2B => &.{0x644},
+ 0x1EE2C => &.{0x645},
+ 0x1EE2D => &.{0x646},
+ 0x1EE2E => &.{0x633},
+ 0x1EE2F => &.{0x639},
+ 0x1EE30 => &.{0x641},
+ 0x1EE31 => &.{0x635},
+ 0x1EE32 => &.{0x642},
+ 0x1EE34 => &.{0x634},
+ 0x1EE35 => &.{0x62A},
+ 0x1EE36 => &.{0x62B},
+ 0x1EE37 => &.{0x62E},
+ 0x1EE39 => &.{0x636},
+ 0x1EE3B => &.{0x63A},
+ 0x1EE42 => &.{0x62C},
+ 0x1EE47 => &.{0x62D},
+ 0x1EE49 => &.{0x64A},
+ 0x1EE4B => &.{0x644},
+ 0x1EE4D => &.{0x646},
+ 0x1EE4E => &.{0x633},
+ 0x1EE4F => &.{0x639},
+ 0x1EE51 => &.{0x635},
+ 0x1EE52 => &.{0x642},
+ 0x1EE54 => &.{0x634},
+ 0x1EE57 => &.{0x62E},
+ 0x1EE59 => &.{0x636},
+ 0x1EE5B => &.{0x63A},
+ 0x1EE5D => &.{0x6BA},
+ 0x1EE5F => &.{0x66F},
+ 0x1EE61 => &.{0x628},
+ 0x1EE62 => &.{0x62C},
+ 0x1EE64 => &.{0x647},
+ 0x1EE67 => &.{0x62D},
+ 0x1EE68 => &.{0x637},
+ 0x1EE69 => &.{0x64A},
+ 0x1EE6A => &.{0x643},
+ 0x1EE6C => &.{0x645},
+ 0x1EE6D => &.{0x646},
+ 0x1EE6E => &.{0x633},
+ 0x1EE6F => &.{0x639},
+ 0x1EE70 => &.{0x641},
+ 0x1EE71 => &.{0x635},
+ 0x1EE72 => &.{0x642},
+ 0x1EE74 => &.{0x634},
+ 0x1EE75 => &.{0x62A},
+ 0x1EE76 => &.{0x62B},
+ 0x1EE77 => &.{0x62E},
+ 0x1EE79 => &.{0x636},
+ 0x1EE7A => &.{0x638},
+ 0x1EE7B => &.{0x63A},
+ 0x1EE7C => &.{0x66E},
+ 0x1EE7E => &.{0x6A1},
+ 0x1EE80 => &.{0x627},
+ 0x1EE81 => &.{0x628},
+ 0x1EE82 => &.{0x62C},
+ 0x1EE83 => &.{0x62F},
+ 0x1EE84 => &.{0x647},
+ 0x1EE85 => &.{0x648},
+ 0x1EE86 => &.{0x632},
+ 0x1EE87 => &.{0x62D},
+ 0x1EE88 => &.{0x637},
+ 0x1EE89 => &.{0x64A},
+ 0x1EE8B => &.{0x644},
+ 0x1EE8C => &.{0x645},
+ 0x1EE8D => &.{0x646},
+ 0x1EE8E => &.{0x633},
+ 0x1EE8F => &.{0x639},
+ 0x1EE90 => &.{0x641},
+ 0x1EE91 => &.{0x635},
+ 0x1EE92 => &.{0x642},
+ 0x1EE93 => &.{0x631},
+ 0x1EE94 => &.{0x634},
+ 0x1EE95 => &.{0x62A},
+ 0x1EE96 => &.{0x62B},
+ 0x1EE97 => &.{0x62E},
+ 0x1EE98 => &.{0x630},
+ 0x1EE99 => &.{0x636},
+ 0x1EE9A => &.{0x638},
+ 0x1EE9B => &.{0x63A},
+ 0x1EEA1 => &.{0x628},
+ 0x1EEA2 => &.{0x62C},
+ 0x1EEA3 => &.{0x62F},
+ 0x1EEA5 => &.{0x648},
+ 0x1EEA6 => &.{0x632},
+ 0x1EEA7 => &.{0x62D},
+ 0x1EEA8 => &.{0x637},
+ 0x1EEA9 => &.{0x64A},
+ 0x1EEAB => &.{0x644},
+ 0x1EEAC => &.{0x645},
+ 0x1EEAD => &.{0x646},
+ 0x1EEAE => &.{0x633},
+ 0x1EEAF => &.{0x639},
+ 0x1EEB0 => &.{0x641},
+ 0x1EEB1 => &.{0x635},
+ 0x1EEB2 => &.{0x642},
+ 0x1EEB3 => &.{0x631},
+ 0x1EEB4 => &.{0x634},
+ 0x1EEB5 => &.{0x62A},
+ 0x1EEB6 => &.{0x62B},
+ 0x1EEB7 => &.{0x62E},
+ 0x1EEB8 => &.{0x630},
+ 0x1EEB9 => &.{0x636},
+ 0x1EEBA => &.{0x638},
+ 0x1EEBB => &.{0x63A},
+ 0x1F100 => &.{ 0x30, 0x2E },
+ 0x1F101 => &.{ 0x30, 0x2C },
+ 0x1F102 => &.{ 0x31, 0x2C },
+ 0x1F103 => &.{ 0x32, 0x2C },
+ 0x1F104 => &.{ 0x33, 0x2C },
+ 0x1F105 => &.{ 0x34, 0x2C },
+ 0x1F106 => &.{ 0x35, 0x2C },
+ 0x1F107 => &.{ 0x36, 0x2C },
+ 0x1F108 => &.{ 0x37, 0x2C },
+ 0x1F109 => &.{ 0x38, 0x2C },
+ 0x1F10A => &.{ 0x39, 0x2C },
+ 0x1F110 => &.{ 0x28, 0x61, 0x29 },
+ 0x1F111 => &.{ 0x28, 0x62, 0x29 },
+ 0x1F112 => &.{ 0x28, 0x63, 0x29 },
+ 0x1F113 => &.{ 0x28, 0x64, 0x29 },
+ 0x1F114 => &.{ 0x28, 0x65, 0x29 },
+ 0x1F115 => &.{ 0x28, 0x66, 0x29 },
+ 0x1F116 => &.{ 0x28, 0x67, 0x29 },
+ 0x1F117 => &.{ 0x28, 0x68, 0x29 },
+ 0x1F118 => &.{ 0x28, 0x69, 0x29 },
+ 0x1F119 => &.{ 0x28, 0x6A, 0x29 },
+ 0x1F11A => &.{ 0x28, 0x6B, 0x29 },
+ 0x1F11B => &.{ 0x28, 0x6C, 0x29 },
+ 0x1F11C => &.{ 0x28, 0x6D, 0x29 },
+ 0x1F11D => &.{ 0x28, 0x6E, 0x29 },
+ 0x1F11E => &.{ 0x28, 0x6F, 0x29 },
+ 0x1F11F => &.{ 0x28, 0x70, 0x29 },
+ 0x1F120 => &.{ 0x28, 0x71, 0x29 },
+ 0x1F121 => &.{ 0x28, 0x72, 0x29 },
+ 0x1F122 => &.{ 0x28, 0x73, 0x29 },
+ 0x1F123 => &.{ 0x28, 0x74, 0x29 },
+ 0x1F124 => &.{ 0x28, 0x75, 0x29 },
+ 0x1F125 => &.{ 0x28, 0x76, 0x29 },
+ 0x1F126 => &.{ 0x28, 0x77, 0x29 },
+ 0x1F127 => &.{ 0x28, 0x78, 0x29 },
+ 0x1F128 => &.{ 0x28, 0x79, 0x29 },
+ 0x1F129 => &.{ 0x28, 0x7A, 0x29 },
+ 0x1F12A => &.{ 0x3014, 0x73, 0x3015 },
+ 0x1F12B => &.{0x63},
+ 0x1F12C => &.{0x72},
+ 0x1F12D => &.{ 0x63, 0x64 },
+ 0x1F12E => &.{ 0x77, 0x7A },
+ 0x1F130 => &.{0x61},
+ 0x1F131 => &.{0x62},
+ 0x1F132 => &.{0x63},
+ 0x1F133 => &.{0x64},
+ 0x1F134 => &.{0x65},
+ 0x1F135 => &.{0x66},
+ 0x1F136 => &.{0x67},
+ 0x1F137 => &.{0x68},
+ 0x1F138 => &.{0x69},
+ 0x1F139 => &.{0x6A},
+ 0x1F13A => &.{0x6B},
+ 0x1F13B => &.{0x6C},
+ 0x1F13C => &.{0x6D},
+ 0x1F13D => &.{0x6E},
+ 0x1F13E => &.{0x6F},
+ 0x1F13F => &.{0x70},
+ 0x1F140 => &.{0x71},
+ 0x1F141 => &.{0x72},
+ 0x1F142 => &.{0x73},
+ 0x1F143 => &.{0x74},
+ 0x1F144 => &.{0x75},
+ 0x1F145 => &.{0x76},
+ 0x1F146 => &.{0x77},
+ 0x1F147 => &.{0x78},
+ 0x1F148 => &.{0x79},
+ 0x1F149 => &.{0x7A},
+ 0x1F14A => &.{ 0x68, 0x76 },
+ 0x1F14B => &.{ 0x6D, 0x76 },
+ 0x1F14C => &.{ 0x73, 0x64 },
+ 0x1F14D => &.{ 0x73, 0x73 },
+ 0x1F14E => &.{ 0x70, 0x70, 0x76 },
+ 0x1F14F => &.{ 0x77, 0x63 },
+ 0x1F16A => &.{ 0x6D, 0x63 },
+ 0x1F16B => &.{ 0x6D, 0x64 },
+ 0x1F16C => &.{ 0x6D, 0x72 },
+ 0x1F190 => &.{ 0x64, 0x6A },
+ 0x1F200 => &.{ 0x307B, 0x304B },
+ 0x1F201 => &.{ 0x30B3, 0x30B3 },
+ 0x1F202 => &.{0x30B5},
+ 0x1F210 => &.{0x624B},
+ 0x1F211 => &.{0x5B57},
+ 0x1F212 => &.{0x53CC},
+ 0x1F213 => &.{0x30C7},
+ 0x1F214 => &.{0x4E8C},
+ 0x1F215 => &.{0x591A},
+ 0x1F216 => &.{0x89E3},
+ 0x1F217 => &.{0x5929},
+ 0x1F218 => &.{0x4EA4},
+ 0x1F219 => &.{0x6620},
+ 0x1F21A => &.{0x7121},
+ 0x1F21B => &.{0x6599},
+ 0x1F21C => &.{0x524D},
+ 0x1F21D => &.{0x5F8C},
+ 0x1F21E => &.{0x518D},
+ 0x1F21F => &.{0x65B0},
+ 0x1F220 => &.{0x521D},
+ 0x1F221 => &.{0x7D42},
+ 0x1F222 => &.{0x751F},
+ 0x1F223 => &.{0x8CA9},
+ 0x1F224 => &.{0x58F0},
+ 0x1F225 => &.{0x5439},
+ 0x1F226 => &.{0x6F14},
+ 0x1F227 => &.{0x6295},
+ 0x1F228 => &.{0x6355},
+ 0x1F229 => &.{0x4E00},
+ 0x1F22A => &.{0x4E09},
+ 0x1F22B => &.{0x904A},
+ 0x1F22C => &.{0x5DE6},
+ 0x1F22D => &.{0x4E2D},
+ 0x1F22E => &.{0x53F3},
+ 0x1F22F => &.{0x6307},
+ 0x1F230 => &.{0x8D70},
+ 0x1F231 => &.{0x6253},
+ 0x1F232 => &.{0x7981},
+ 0x1F233 => &.{0x7A7A},
+ 0x1F234 => &.{0x5408},
+ 0x1F235 => &.{0x6E80},
+ 0x1F236 => &.{0x6709},
+ 0x1F237 => &.{0x6708},
+ 0x1F238 => &.{0x7533},
+ 0x1F239 => &.{0x5272},
+ 0x1F23A => &.{0x55B6},
+ 0x1F23B => &.{0x914D},
+ 0x1F240 => &.{ 0x3014, 0x672C, 0x3015 },
+ 0x1F241 => &.{ 0x3014, 0x4E09, 0x3015 },
+ 0x1F242 => &.{ 0x3014, 0x4E8C, 0x3015 },
+ 0x1F243 => &.{ 0x3014, 0x5B89, 0x3015 },
+ 0x1F244 => &.{ 0x3014, 0x70B9, 0x3015 },
+ 0x1F245 => &.{ 0x3014, 0x6253, 0x3015 },
+ 0x1F246 => &.{ 0x3014, 0x76D7, 0x3015 },
+ 0x1F247 => &.{ 0x3014, 0x52DD, 0x3015 },
+ 0x1F248 => &.{ 0x3014, 0x6557, 0x3015 },
+ 0x1F250 => &.{0x5F97},
+ 0x1F251 => &.{0x53EF},
+ 0x1FBF0 => &.{0x30},
+ 0x1FBF1 => &.{0x31},
+ 0x1FBF2 => &.{0x32},
+ 0x1FBF3 => &.{0x33},
+ 0x1FBF4 => &.{0x34},
+ 0x1FBF5 => &.{0x35},
+ 0x1FBF6 => &.{0x36},
+ 0x1FBF7 => &.{0x37},
+ 0x1FBF8 => &.{0x38},
+ 0x1FBF9 => &.{0x39},
+ 0x2F800 => &.{0x4E3D},
+ 0x2F801 => &.{0x4E38},
+ 0x2F802 => &.{0x4E41},
+ 0x2F803 => &.{0x20122},
+ 0x2F804 => &.{0x4F60},
+ 0x2F805 => &.{0x4FAE},
+ 0x2F806 => &.{0x4FBB},
+ 0x2F807 => &.{0x5002},
+ 0x2F808 => &.{0x507A},
+ 0x2F809 => &.{0x5099},
+ 0x2F80A => &.{0x50E7},
+ 0x2F80B => &.{0x50CF},
+ 0x2F80C => &.{0x349E},
+ 0x2F80D => &.{0x2063A},
+ 0x2F80E => &.{0x514D},
+ 0x2F80F => &.{0x5154},
+ 0x2F810 => &.{0x5164},
+ 0x2F811 => &.{0x5177},
+ 0x2F812 => &.{0x2051C},
+ 0x2F813 => &.{0x34B9},
+ 0x2F814 => &.{0x5167},
+ 0x2F815 => &.{0x518D},
+ 0x2F816 => &.{0x2054B},
+ 0x2F817 => &.{0x5197},
+ 0x2F818 => &.{0x51A4},
+ 0x2F819 => &.{0x4ECC},
+ 0x2F81A => &.{0x51AC},
+ 0x2F81B => &.{0x51B5},
+ 0x2F81C => &.{0x291DF},
+ 0x2F81D => &.{0x51F5},
+ 0x2F81E => &.{0x5203},
+ 0x2F81F => &.{0x34DF},
+ 0x2F820 => &.{0x523B},
+ 0x2F821 => &.{0x5246},
+ 0x2F822 => &.{0x5272},
+ 0x2F823 => &.{0x5277},
+ 0x2F824 => &.{0x3515},
+ 0x2F825 => &.{0x52C7},
+ 0x2F826 => &.{0x52C9},
+ 0x2F827 => &.{0x52E4},
+ 0x2F828 => &.{0x52FA},
+ 0x2F829 => &.{0x5305},
+ 0x2F82A => &.{0x5306},
+ 0x2F82B => &.{0x5317},
+ 0x2F82C => &.{0x5349},
+ 0x2F82D => &.{0x5351},
+ 0x2F82E => &.{0x535A},
+ 0x2F82F => &.{0x5373},
+ 0x2F830 => &.{0x537D},
+ 0x2F831...0x2F833 => &.{0x537F},
+ 0x2F834 => &.{0x20A2C},
+ 0x2F835 => &.{0x7070},
+ 0x2F836 => &.{0x53CA},
+ 0x2F837 => &.{0x53DF},
+ 0x2F838 => &.{0x20B63},
+ 0x2F839 => &.{0x53EB},
+ 0x2F83A => &.{0x53F1},
+ 0x2F83B => &.{0x5406},
+ 0x2F83C => &.{0x549E},
+ 0x2F83D => &.{0x5438},
+ 0x2F83E => &.{0x5448},
+ 0x2F83F => &.{0x5468},
+ 0x2F840 => &.{0x54A2},
+ 0x2F841 => &.{0x54F6},
+ 0x2F842 => &.{0x5510},
+ 0x2F843 => &.{0x5553},
+ 0x2F844 => &.{0x5563},
+ 0x2F845...0x2F846 => &.{0x5584},
+ 0x2F847 => &.{0x5599},
+ 0x2F848 => &.{0x55AB},
+ 0x2F849 => &.{0x55B3},
+ 0x2F84A => &.{0x55C2},
+ 0x2F84B => &.{0x5716},
+ 0x2F84C => &.{0x5606},
+ 0x2F84D => &.{0x5717},
+ 0x2F84E => &.{0x5651},
+ 0x2F84F => &.{0x5674},
+ 0x2F850 => &.{0x5207},
+ 0x2F851 => &.{0x58EE},
+ 0x2F852 => &.{0x57CE},
+ 0x2F853 => &.{0x57F4},
+ 0x2F854 => &.{0x580D},
+ 0x2F855 => &.{0x578B},
+ 0x2F856 => &.{0x5832},
+ 0x2F857 => &.{0x5831},
+ 0x2F858 => &.{0x58AC},
+ 0x2F859 => &.{0x214E4},
+ 0x2F85A => &.{0x58F2},
+ 0x2F85B => &.{0x58F7},
+ 0x2F85C => &.{0x5906},
+ 0x2F85D => &.{0x591A},
+ 0x2F85E => &.{0x5922},
+ 0x2F85F => &.{0x5962},
+ 0x2F860 => &.{0x216A8},
+ 0x2F861 => &.{0x216EA},
+ 0x2F862 => &.{0x59EC},
+ 0x2F863 => &.{0x5A1B},
+ 0x2F864 => &.{0x5A27},
+ 0x2F865 => &.{0x59D8},
+ 0x2F866 => &.{0x5A66},
+ 0x2F867 => &.{0x36EE},
+ 0x2F868 => &.{0x36FC},
+ 0x2F869 => &.{0x5B08},
+ 0x2F86A...0x2F86B => &.{0x5B3E},
+ 0x2F86C => &.{0x219C8},
+ 0x2F86D => &.{0x5BC3},
+ 0x2F86E => &.{0x5BD8},
+ 0x2F86F => &.{0x5BE7},
+ 0x2F870 => &.{0x5BF3},
+ 0x2F871 => &.{0x21B18},
+ 0x2F872 => &.{0x5BFF},
+ 0x2F873 => &.{0x5C06},
+ 0x2F874 => &.{0x5F53},
+ 0x2F875 => &.{0x5C22},
+ 0x2F876 => &.{0x3781},
+ 0x2F877 => &.{0x5C60},
+ 0x2F878 => &.{0x5C6E},
+ 0x2F879 => &.{0x5CC0},
+ 0x2F87A => &.{0x5C8D},
+ 0x2F87B => &.{0x21DE4},
+ 0x2F87C => &.{0x5D43},
+ 0x2F87D => &.{0x21DE6},
+ 0x2F87E => &.{0x5D6E},
+ 0x2F87F => &.{0x5D6B},
+ 0x2F880 => &.{0x5D7C},
+ 0x2F881 => &.{0x5DE1},
+ 0x2F882 => &.{0x5DE2},
+ 0x2F883 => &.{0x382F},
+ 0x2F884 => &.{0x5DFD},
+ 0x2F885 => &.{0x5E28},
+ 0x2F886 => &.{0x5E3D},
+ 0x2F887 => &.{0x5E69},
+ 0x2F888 => &.{0x3862},
+ 0x2F889 => &.{0x22183},
+ 0x2F88A => &.{0x387C},
+ 0x2F88B => &.{0x5EB0},
+ 0x2F88C => &.{0x5EB3},
+ 0x2F88D => &.{0x5EB6},
+ 0x2F88E => &.{0x5ECA},
+ 0x2F88F => &.{0x2A392},
+ 0x2F890 => &.{0x5EFE},
+ 0x2F891...0x2F892 => &.{0x22331},
+ 0x2F893 => &.{0x8201},
+ 0x2F894...0x2F895 => &.{0x5F22},
+ 0x2F896 => &.{0x38C7},
+ 0x2F897 => &.{0x232B8},
+ 0x2F898 => &.{0x261DA},
+ 0x2F899 => &.{0x5F62},
+ 0x2F89A => &.{0x5F6B},
+ 0x2F89B => &.{0x38E3},
+ 0x2F89C => &.{0x5F9A},
+ 0x2F89D => &.{0x5FCD},
+ 0x2F89E => &.{0x5FD7},
+ 0x2F89F => &.{0x5FF9},
+ 0x2F8A0 => &.{0x6081},
+ 0x2F8A1 => &.{0x393A},
+ 0x2F8A2 => &.{0x391C},
+ 0x2F8A3 => &.{0x6094},
+ 0x2F8A4 => &.{0x226D4},
+ 0x2F8A5 => &.{0x60C7},
+ 0x2F8A6 => &.{0x6148},
+ 0x2F8A7 => &.{0x614C},
+ 0x2F8A8 => &.{0x614E},
+ 0x2F8A9 => &.{0x614C},
+ 0x2F8AA => &.{0x617A},
+ 0x2F8AB => &.{0x618E},
+ 0x2F8AC => &.{0x61B2},
+ 0x2F8AD => &.{0x61A4},
+ 0x2F8AE => &.{0x61AF},
+ 0x2F8AF => &.{0x61DE},
+ 0x2F8B0 => &.{0x61F2},
+ 0x2F8B1 => &.{0x61F6},
+ 0x2F8B2 => &.{0x6210},
+ 0x2F8B3 => &.{0x621B},
+ 0x2F8B4 => &.{0x625D},
+ 0x2F8B5 => &.{0x62B1},
+ 0x2F8B6 => &.{0x62D4},
+ 0x2F8B7 => &.{0x6350},
+ 0x2F8B8 => &.{0x22B0C},
+ 0x2F8B9 => &.{0x633D},
+ 0x2F8BA => &.{0x62FC},
+ 0x2F8BB => &.{0x6368},
+ 0x2F8BC => &.{0x6383},
+ 0x2F8BD => &.{0x63E4},
+ 0x2F8BE => &.{0x22BF1},
+ 0x2F8BF => &.{0x6422},
+ 0x2F8C0 => &.{0x63C5},
+ 0x2F8C1 => &.{0x63A9},
+ 0x2F8C2 => &.{0x3A2E},
+ 0x2F8C3 => &.{0x6469},
+ 0x2F8C4 => &.{0x647E},
+ 0x2F8C5 => &.{0x649D},
+ 0x2F8C6 => &.{0x6477},
+ 0x2F8C7 => &.{0x3A6C},
+ 0x2F8C8 => &.{0x654F},
+ 0x2F8C9 => &.{0x656C},
+ 0x2F8CA => &.{0x2300A},
+ 0x2F8CB => &.{0x65E3},
+ 0x2F8CC => &.{0x66F8},
+ 0x2F8CD => &.{0x6649},
+ 0x2F8CE => &.{0x3B19},
+ 0x2F8CF => &.{0x6691},
+ 0x2F8D0 => &.{0x3B08},
+ 0x2F8D1 => &.{0x3AE4},
+ 0x2F8D2 => &.{0x5192},
+ 0x2F8D3 => &.{0x5195},
+ 0x2F8D4 => &.{0x6700},
+ 0x2F8D5 => &.{0x669C},
+ 0x2F8D6 => &.{0x80AD},
+ 0x2F8D7 => &.{0x43D9},
+ 0x2F8D8 => &.{0x6717},
+ 0x2F8D9 => &.{0x671B},
+ 0x2F8DA => &.{0x6721},
+ 0x2F8DB => &.{0x675E},
+ 0x2F8DC => &.{0x6753},
+ 0x2F8DD => &.{0x233C3},
+ 0x2F8DE => &.{0x3B49},
+ 0x2F8DF => &.{0x67FA},
+ 0x2F8E0 => &.{0x6785},
+ 0x2F8E1 => &.{0x6852},
+ 0x2F8E2 => &.{0x6885},
+ 0x2F8E3 => &.{0x2346D},
+ 0x2F8E4 => &.{0x688E},
+ 0x2F8E5 => &.{0x681F},
+ 0x2F8E6 => &.{0x6914},
+ 0x2F8E7 => &.{0x3B9D},
+ 0x2F8E8 => &.{0x6942},
+ 0x2F8E9 => &.{0x69A3},
+ 0x2F8EA => &.{0x69EA},
+ 0x2F8EB => &.{0x6AA8},
+ 0x2F8EC => &.{0x236A3},
+ 0x2F8ED => &.{0x6ADB},
+ 0x2F8EE => &.{0x3C18},
+ 0x2F8EF => &.{0x6B21},
+ 0x2F8F0 => &.{0x238A7},
+ 0x2F8F1 => &.{0x6B54},
+ 0x2F8F2 => &.{0x3C4E},
+ 0x2F8F3 => &.{0x6B72},
+ 0x2F8F4 => &.{0x6B9F},
+ 0x2F8F5 => &.{0x6BBA},
+ 0x2F8F6 => &.{0x6BBB},
+ 0x2F8F7 => &.{0x23A8D},
+ 0x2F8F8 => &.{0x21D0B},
+ 0x2F8F9 => &.{0x23AFA},
+ 0x2F8FA => &.{0x6C4E},
+ 0x2F8FB => &.{0x23CBC},
+ 0x2F8FC => &.{0x6CBF},
+ 0x2F8FD => &.{0x6CCD},
+ 0x2F8FE => &.{0x6C67},
+ 0x2F8FF => &.{0x6D16},
+ 0x2F900 => &.{0x6D3E},
+ 0x2F901 => &.{0x6D77},
+ 0x2F902 => &.{0x6D41},
+ 0x2F903 => &.{0x6D69},
+ 0x2F904 => &.{0x6D78},
+ 0x2F905 => &.{0x6D85},
+ 0x2F906 => &.{0x23D1E},
+ 0x2F907 => &.{0x6D34},
+ 0x2F908 => &.{0x6E2F},
+ 0x2F909 => &.{0x6E6E},
+ 0x2F90A => &.{0x3D33},
+ 0x2F90B => &.{0x6ECB},
+ 0x2F90C => &.{0x6EC7},
+ 0x2F90D => &.{0x23ED1},
+ 0x2F90E => &.{0x6DF9},
+ 0x2F90F => &.{0x6F6E},
+ 0x2F910 => &.{0x23F5E},
+ 0x2F911 => &.{0x23F8E},
+ 0x2F912 => &.{0x6FC6},
+ 0x2F913 => &.{0x7039},
+ 0x2F914 => &.{0x701E},
+ 0x2F915 => &.{0x701B},
+ 0x2F916 => &.{0x3D96},
+ 0x2F917 => &.{0x704A},
+ 0x2F918 => &.{0x707D},
+ 0x2F919 => &.{0x7077},
+ 0x2F91A => &.{0x70AD},
+ 0x2F91B => &.{0x20525},
+ 0x2F91C => &.{0x7145},
+ 0x2F91D => &.{0x24263},
+ 0x2F91E => &.{0x719C},
+ 0x2F91F => &.{0x243AB},
+ 0x2F920 => &.{0x7228},
+ 0x2F921 => &.{0x7235},
+ 0x2F922 => &.{0x7250},
+ 0x2F923 => &.{0x24608},
+ 0x2F924 => &.{0x7280},
+ 0x2F925 => &.{0x7295},
+ 0x2F926 => &.{0x24735},
+ 0x2F927 => &.{0x24814},
+ 0x2F928 => &.{0x737A},
+ 0x2F929 => &.{0x738B},
+ 0x2F92A => &.{0x3EAC},
+ 0x2F92B => &.{0x73A5},
+ 0x2F92C...0x2F92D => &.{0x3EB8},
+ 0x2F92E => &.{0x7447},
+ 0x2F92F => &.{0x745C},
+ 0x2F930 => &.{0x7471},
+ 0x2F931 => &.{0x7485},
+ 0x2F932 => &.{0x74CA},
+ 0x2F933 => &.{0x3F1B},
+ 0x2F934 => &.{0x7524},
+ 0x2F935 => &.{0x24C36},
+ 0x2F936 => &.{0x753E},
+ 0x2F937 => &.{0x24C92},
+ 0x2F938 => &.{0x7570},
+ 0x2F939 => &.{0x2219F},
+ 0x2F93A => &.{0x7610},
+ 0x2F93B => &.{0x24FA1},
+ 0x2F93C => &.{0x24FB8},
+ 0x2F93D => &.{0x25044},
+ 0x2F93E => &.{0x3FFC},
+ 0x2F93F => &.{0x4008},
+ 0x2F940 => &.{0x76F4},
+ 0x2F941 => &.{0x250F3},
+ 0x2F942 => &.{0x250F2},
+ 0x2F943 => &.{0x25119},
+ 0x2F944 => &.{0x25133},
+ 0x2F945 => &.{0x771E},
+ 0x2F946...0x2F947 => &.{0x771F},
+ 0x2F948 => &.{0x774A},
+ 0x2F949 => &.{0x4039},
+ 0x2F94A => &.{0x778B},
+ 0x2F94B => &.{0x4046},
+ 0x2F94C => &.{0x4096},
+ 0x2F94D => &.{0x2541D},
+ 0x2F94E => &.{0x784E},
+ 0x2F94F => &.{0x788C},
+ 0x2F950 => &.{0x78CC},
+ 0x2F951 => &.{0x40E3},
+ 0x2F952 => &.{0x25626},
+ 0x2F953 => &.{0x7956},
+ 0x2F954 => &.{0x2569A},
+ 0x2F955 => &.{0x256C5},
+ 0x2F956 => &.{0x798F},
+ 0x2F957 => &.{0x79EB},
+ 0x2F958 => &.{0x412F},
+ 0x2F959 => &.{0x7A40},
+ 0x2F95A => &.{0x7A4A},
+ 0x2F95B => &.{0x7A4F},
+ 0x2F95C => &.{0x2597C},
+ 0x2F95D...0x2F95E => &.{0x25AA7},
+ 0x2F95F => &.{0x7AEE},
+ 0x2F960 => &.{0x4202},
+ 0x2F961 => &.{0x25BAB},
+ 0x2F962 => &.{0x7BC6},
+ 0x2F963 => &.{0x7BC9},
+ 0x2F964 => &.{0x4227},
+ 0x2F965 => &.{0x25C80},
+ 0x2F966 => &.{0x7CD2},
+ 0x2F967 => &.{0x42A0},
+ 0x2F968 => &.{0x7CE8},
+ 0x2F969 => &.{0x7CE3},
+ 0x2F96A => &.{0x7D00},
+ 0x2F96B => &.{0x25F86},
+ 0x2F96C => &.{0x7D63},
+ 0x2F96D => &.{0x4301},
+ 0x2F96E => &.{0x7DC7},
+ 0x2F96F => &.{0x7E02},
+ 0x2F970 => &.{0x7E45},
+ 0x2F971 => &.{0x4334},
+ 0x2F972 => &.{0x26228},
+ 0x2F973 => &.{0x26247},
+ 0x2F974 => &.{0x4359},
+ 0x2F975 => &.{0x262D9},
+ 0x2F976 => &.{0x7F7A},
+ 0x2F977 => &.{0x2633E},
+ 0x2F978 => &.{0x7F95},
+ 0x2F979 => &.{0x7FFA},
+ 0x2F97A => &.{0x8005},
+ 0x2F97B => &.{0x264DA},
+ 0x2F97C => &.{0x26523},
+ 0x2F97D => &.{0x8060},
+ 0x2F97E => &.{0x265A8},
+ 0x2F97F => &.{0x8070},
+ 0x2F980 => &.{0x2335F},
+ 0x2F981 => &.{0x43D5},
+ 0x2F982 => &.{0x80B2},
+ 0x2F983 => &.{0x8103},
+ 0x2F984 => &.{0x440B},
+ 0x2F985 => &.{0x813E},
+ 0x2F986 => &.{0x5AB5},
+ 0x2F987 => &.{0x267A7},
+ 0x2F988 => &.{0x267B5},
+ 0x2F989 => &.{0x23393},
+ 0x2F98A => &.{0x2339C},
+ 0x2F98B => &.{0x8201},
+ 0x2F98C => &.{0x8204},
+ 0x2F98D => &.{0x8F9E},
+ 0x2F98E => &.{0x446B},
+ 0x2F98F => &.{0x8291},
+ 0x2F990 => &.{0x828B},
+ 0x2F991 => &.{0x829D},
+ 0x2F992 => &.{0x52B3},
+ 0x2F993 => &.{0x82B1},
+ 0x2F994 => &.{0x82B3},
+ 0x2F995 => &.{0x82BD},
+ 0x2F996 => &.{0x82E6},
+ 0x2F997 => &.{0x26B3C},
+ 0x2F998 => &.{0x82E5},
+ 0x2F999 => &.{0x831D},
+ 0x2F99A => &.{0x8363},
+ 0x2F99B => &.{0x83AD},
+ 0x2F99C => &.{0x8323},
+ 0x2F99D => &.{0x83BD},
+ 0x2F99E => &.{0x83E7},
+ 0x2F99F => &.{0x8457},
+ 0x2F9A0 => &.{0x8353},
+ 0x2F9A1 => &.{0x83CA},
+ 0x2F9A2 => &.{0x83CC},
+ 0x2F9A3 => &.{0x83DC},
+ 0x2F9A4 => &.{0x26C36},
+ 0x2F9A5 => &.{0x26D6B},
+ 0x2F9A6 => &.{0x26CD5},
+ 0x2F9A7 => &.{0x452B},
+ 0x2F9A8 => &.{0x84F1},
+ 0x2F9A9 => &.{0x84F3},
+ 0x2F9AA => &.{0x8516},
+ 0x2F9AB => &.{0x273CA},
+ 0x2F9AC => &.{0x8564},
+ 0x2F9AD => &.{0x26F2C},
+ 0x2F9AE => &.{0x455D},
+ 0x2F9AF => &.{0x4561},
+ 0x2F9B0 => &.{0x26FB1},
+ 0x2F9B1 => &.{0x270D2},
+ 0x2F9B2 => &.{0x456B},
+ 0x2F9B3 => &.{0x8650},
+ 0x2F9B4 => &.{0x865C},
+ 0x2F9B5 => &.{0x8667},
+ 0x2F9B6 => &.{0x8669},
+ 0x2F9B7 => &.{0x86A9},
+ 0x2F9B8 => &.{0x8688},
+ 0x2F9B9 => &.{0x870E},
+ 0x2F9BA => &.{0x86E2},
+ 0x2F9BB => &.{0x8779},
+ 0x2F9BC => &.{0x8728},
+ 0x2F9BD => &.{0x876B},
+ 0x2F9BE => &.{0x8786},
+ 0x2F9BF => &.{0x45D7},
+ 0x2F9C0 => &.{0x87E1},
+ 0x2F9C1 => &.{0x8801},
+ 0x2F9C2 => &.{0x45F9},
+ 0x2F9C3 => &.{0x8860},
+ 0x2F9C4 => &.{0x8863},
+ 0x2F9C5 => &.{0x27667},
+ 0x2F9C6 => &.{0x88D7},
+ 0x2F9C7 => &.{0x88DE},
+ 0x2F9C8 => &.{0x4635},
+ 0x2F9C9 => &.{0x88FA},
+ 0x2F9CA => &.{0x34BB},
+ 0x2F9CB => &.{0x278AE},
+ 0x2F9CC => &.{0x27966},
+ 0x2F9CD => &.{0x46BE},
+ 0x2F9CE => &.{0x46C7},
+ 0x2F9CF => &.{0x8AA0},
+ 0x2F9D0 => &.{0x8AED},
+ 0x2F9D1 => &.{0x8B8A},
+ 0x2F9D2 => &.{0x8C55},
+ 0x2F9D3 => &.{0x27CA8},
+ 0x2F9D4 => &.{0x8CAB},
+ 0x2F9D5 => &.{0x8CC1},
+ 0x2F9D6 => &.{0x8D1B},
+ 0x2F9D7 => &.{0x8D77},
+ 0x2F9D8 => &.{0x27F2F},
+ 0x2F9D9 => &.{0x20804},
+ 0x2F9DA => &.{0x8DCB},
+ 0x2F9DB => &.{0x8DBC},
+ 0x2F9DC => &.{0x8DF0},
+ 0x2F9DD => &.{0x208DE},
+ 0x2F9DE => &.{0x8ED4},
+ 0x2F9DF => &.{0x8F38},
+ 0x2F9E0 => &.{0x285D2},
+ 0x2F9E1 => &.{0x285ED},
+ 0x2F9E2 => &.{0x9094},
+ 0x2F9E3 => &.{0x90F1},
+ 0x2F9E4 => &.{0x9111},
+ 0x2F9E5 => &.{0x2872E},
+ 0x2F9E6 => &.{0x911B},
+ 0x2F9E7 => &.{0x9238},
+ 0x2F9E8 => &.{0x92D7},
+ 0x2F9E9 => &.{0x92D8},
+ 0x2F9EA => &.{0x927C},
+ 0x2F9EB => &.{0x93F9},
+ 0x2F9EC => &.{0x9415},
+ 0x2F9ED => &.{0x28BFA},
+ 0x2F9EE => &.{0x958B},
+ 0x2F9EF => &.{0x4995},
+ 0x2F9F0 => &.{0x95B7},
+ 0x2F9F1 => &.{0x28D77},
+ 0x2F9F2 => &.{0x49E6},
+ 0x2F9F3 => &.{0x96C3},
+ 0x2F9F4 => &.{0x5DB2},
+ 0x2F9F5 => &.{0x9723},
+ 0x2F9F6 => &.{0x29145},
+ 0x2F9F7 => &.{0x2921A},
+ 0x2F9F8 => &.{0x4A6E},
+ 0x2F9F9 => &.{0x4A76},
+ 0x2F9FA => &.{0x97E0},
+ 0x2F9FB => &.{0x2940A},
+ 0x2F9FC => &.{0x4AB2},
+ 0x2F9FD => &.{0x29496},
+ 0x2F9FE...0x2F9FF => &.{0x980B},
+ 0x2FA00 => &.{0x9829},
+ 0x2FA01 => &.{0x295B6},
+ 0x2FA02 => &.{0x98E2},
+ 0x2FA03 => &.{0x4B33},
+ 0x2FA04 => &.{0x9929},
+ 0x2FA05 => &.{0x99A7},
+ 0x2FA06 => &.{0x99C2},
+ 0x2FA07 => &.{0x99FE},
+ 0x2FA08 => &.{0x4BCE},
+ 0x2FA09 => &.{0x29B30},
+ 0x2FA0A => &.{0x9B12},
+ 0x2FA0B => &.{0x9C40},
+ 0x2FA0C => &.{0x9CFD},
+ 0x2FA0D => &.{0x4CCE},
+ 0x2FA0E => &.{0x4CED},
+ 0x2FA0F => &.{0x9D67},
+ 0x2FA10 => &.{0x2A0CE},
+ 0x2FA11 => &.{0x4CF8},
+ 0x2FA12 => &.{0x2A105},
+ 0x2FA13 => &.{0x2A20E},
+ 0x2FA14 => &.{0x2A291},
+ 0x2FA15 => &.{0x9EBB},
+ 0x2FA16 => &.{0x4D56},
+ 0x2FA17 => &.{0x9EF9},
+ 0x2FA18 => &.{0x9EFE},
+ 0x2FA19 => &.{0x9F05},
+ 0x2FA1A => &.{0x9F0F},
+ 0x2FA1B => &.{0x9F16},
+ 0x2FA1C => &.{0x9F3B},
+ 0x2FA1D => &.{0x2A600},
+ 0xE0000 => null,
+ 0xE0001 => null,
+ 0xE0002...0xE001F => null,
+ 0xE0020...0xE007F => null,
+ 0xE0080...0xE00FF => null,
+ 0xE0100...0xE01EF => null,
+ 0xE01F0...0xE0FFF => null,
+ else => &.{cp},
+ };
+
+ if (slice) |s| {
+ var array = [_]u21{0} ** 18;
+ @memcpy(array[0..s.len], s);
+
+ return array;
+ }
+
+ return null;
+}
+
+
+pub fn changesWhenNfkcCaseFold(cp: u21) bool {
+ return switch (cp) {
+ 0x41...0x5A => true,
+ 0xA0 => true,
+ 0xA8 => true,
+ 0xAA => true,
+ 0xAD => true,
+ 0xAF => true,
+ 0xB2...0xB3 => true,
+ 0xB4 => true,
+ 0xB5 => true,
+ 0xB8 => true,
+ 0xB9 => true,
+ 0xBA => true,
+ 0xBC...0xBE => true,
+ 0xC0...0xD6 => true,
+ 0xD8...0xDF => true,
+ 0x100 => true,
+ 0x102 => true,
+ 0x104 => true,
+ 0x106 => true,
+ 0x108 => true,
+ 0x10A => true,
+ 0x10C => true,
+ 0x10E => true,
+ 0x110 => true,
+ 0x112 => true,
+ 0x114 => true,
+ 0x116 => true,
+ 0x118 => true,
+ 0x11A => true,
+ 0x11C => true,
+ 0x11E => true,
+ 0x120 => true,
+ 0x122 => true,
+ 0x124 => true,
+ 0x126 => true,
+ 0x128 => true,
+ 0x12A => true,
+ 0x12C => true,
+ 0x12E => true,
+ 0x130 => true,
+ 0x132...0x134 => true,
+ 0x136 => true,
+ 0x139 => true,
+ 0x13B => true,
+ 0x13D => true,
+ 0x13F...0x141 => true,
+ 0x143 => true,
+ 0x145 => true,
+ 0x147 => true,
+ 0x149...0x14A => true,
+ 0x14C => true,
+ 0x14E => true,
+ 0x150 => true,
+ 0x152 => true,
+ 0x154 => true,
+ 0x156 => true,
+ 0x158 => true,
+ 0x15A => true,
+ 0x15C => true,
+ 0x15E => true,
+ 0x160 => true,
+ 0x162 => true,
+ 0x164 => true,
+ 0x166 => true,
+ 0x168 => true,
+ 0x16A => true,
+ 0x16C => true,
+ 0x16E => true,
+ 0x170 => true,
+ 0x172 => true,
+ 0x174 => true,
+ 0x176 => true,
+ 0x178...0x179 => true,
+ 0x17B => true,
+ 0x17D => true,
+ 0x17F => true,
+ 0x181...0x182 => true,
+ 0x184 => true,
+ 0x186...0x187 => true,
+ 0x189...0x18B => true,
+ 0x18E...0x191 => true,
+ 0x193...0x194 => true,
+ 0x196...0x198 => true,
+ 0x19C...0x19D => true,
+ 0x19F...0x1A0 => true,
+ 0x1A2 => true,
+ 0x1A4 => true,
+ 0x1A6...0x1A7 => true,
+ 0x1A9 => true,
+ 0x1AC => true,
+ 0x1AE...0x1AF => true,
+ 0x1B1...0x1B3 => true,
+ 0x1B5 => true,
+ 0x1B7...0x1B8 => true,
+ 0x1BC => true,
+ 0x1C4...0x1CD => true,
+ 0x1CF => true,
+ 0x1D1 => true,
+ 0x1D3 => true,
+ 0x1D5 => true,
+ 0x1D7 => true,
+ 0x1D9 => true,
+ 0x1DB => true,
+ 0x1DE => true,
+ 0x1E0 => true,
+ 0x1E2 => true,
+ 0x1E4 => true,
+ 0x1E6 => true,
+ 0x1E8 => true,
+ 0x1EA => true,
+ 0x1EC => true,
+ 0x1EE => true,
+ 0x1F1...0x1F4 => true,
+ 0x1F6...0x1F8 => true,
+ 0x1FA => true,
+ 0x1FC => true,
+ 0x1FE => true,
+ 0x200 => true,
+ 0x202 => true,
+ 0x204 => true,
+ 0x206 => true,
+ 0x208 => true,
+ 0x20A => true,
+ 0x20C => true,
+ 0x20E => true,
+ 0x210 => true,
+ 0x212 => true,
+ 0x214 => true,
+ 0x216 => true,
+ 0x218 => true,
+ 0x21A => true,
+ 0x21C => true,
+ 0x21E => true,
+ 0x220 => true,
+ 0x222 => true,
+ 0x224 => true,
+ 0x226 => true,
+ 0x228 => true,
+ 0x22A => true,
+ 0x22C => true,
+ 0x22E => true,
+ 0x230 => true,
+ 0x232 => true,
+ 0x23A...0x23B => true,
+ 0x23D...0x23E => true,
+ 0x241 => true,
+ 0x243...0x246 => true,
+ 0x248 => true,
+ 0x24A => true,
+ 0x24C => true,
+ 0x24E => true,
+ 0x2B0...0x2B8 => true,
+ 0x2D8...0x2DD => true,
+ 0x2E0...0x2E4 => true,
+ 0x340...0x341 => true,
+ 0x343...0x345 => true,
+ 0x34F => true,
+ 0x370 => true,
+ 0x372 => true,
+ 0x374 => true,
+ 0x376 => true,
+ 0x37A => true,
+ 0x37E => true,
+ 0x37F => true,
+ 0x384...0x385 => true,
+ 0x386 => true,
+ 0x387 => true,
+ 0x388...0x38A => true,
+ 0x38C => true,
+ 0x38E...0x38F => true,
+ 0x391...0x3A1 => true,
+ 0x3A3...0x3AB => true,
+ 0x3C2 => true,
+ 0x3CF...0x3D6 => true,
+ 0x3D8 => true,
+ 0x3DA => true,
+ 0x3DC => true,
+ 0x3DE => true,
+ 0x3E0 => true,
+ 0x3E2 => true,
+ 0x3E4 => true,
+ 0x3E6 => true,
+ 0x3E8 => true,
+ 0x3EA => true,
+ 0x3EC => true,
+ 0x3EE => true,
+ 0x3F0...0x3F2 => true,
+ 0x3F4...0x3F5 => true,
+ 0x3F7 => true,
+ 0x3F9...0x3FA => true,
+ 0x3FD...0x42F => true,
+ 0x460 => true,
+ 0x462 => true,
+ 0x464 => true,
+ 0x466 => true,
+ 0x468 => true,
+ 0x46A => true,
+ 0x46C => true,
+ 0x46E => true,
+ 0x470 => true,
+ 0x472 => true,
+ 0x474 => true,
+ 0x476 => true,
+ 0x478 => true,
+ 0x47A => true,
+ 0x47C => true,
+ 0x47E => true,
+ 0x480 => true,
+ 0x48A => true,
+ 0x48C => true,
+ 0x48E => true,
+ 0x490 => true,
+ 0x492 => true,
+ 0x494 => true,
+ 0x496 => true,
+ 0x498 => true,
+ 0x49A => true,
+ 0x49C => true,
+ 0x49E => true,
+ 0x4A0 => true,
+ 0x4A2 => true,
+ 0x4A4 => true,
+ 0x4A6 => true,
+ 0x4A8 => true,
+ 0x4AA => true,
+ 0x4AC => true,
+ 0x4AE => true,
+ 0x4B0 => true,
+ 0x4B2 => true,
+ 0x4B4 => true,
+ 0x4B6 => true,
+ 0x4B8 => true,
+ 0x4BA => true,
+ 0x4BC => true,
+ 0x4BE => true,
+ 0x4C0...0x4C1 => true,
+ 0x4C3 => true,
+ 0x4C5 => true,
+ 0x4C7 => true,
+ 0x4C9 => true,
+ 0x4CB => true,
+ 0x4CD => true,
+ 0x4D0 => true,
+ 0x4D2 => true,
+ 0x4D4 => true,
+ 0x4D6 => true,
+ 0x4D8 => true,
+ 0x4DA => true,
+ 0x4DC => true,
+ 0x4DE => true,
+ 0x4E0 => true,
+ 0x4E2 => true,
+ 0x4E4 => true,
+ 0x4E6 => true,
+ 0x4E8 => true,
+ 0x4EA => true,
+ 0x4EC => true,
+ 0x4EE => true,
+ 0x4F0 => true,
+ 0x4F2 => true,
+ 0x4F4 => true,
+ 0x4F6 => true,
+ 0x4F8 => true,
+ 0x4FA => true,
+ 0x4FC => true,
+ 0x4FE => true,
+ 0x500 => true,
+ 0x502 => true,
+ 0x504 => true,
+ 0x506 => true,
+ 0x508 => true,
+ 0x50A => true,
+ 0x50C => true,
+ 0x50E => true,
+ 0x510 => true,
+ 0x512 => true,
+ 0x514 => true,
+ 0x516 => true,
+ 0x518 => true,
+ 0x51A => true,
+ 0x51C => true,
+ 0x51E => true,
+ 0x520 => true,
+ 0x522 => true,
+ 0x524 => true,
+ 0x526 => true,
+ 0x528 => true,
+ 0x52A => true,
+ 0x52C => true,
+ 0x52E => true,
+ 0x531...0x556 => true,
+ 0x587 => true,
+ 0x61C => true,
+ 0x675...0x678 => true,
+ 0x958...0x95F => true,
+ 0x9DC...0x9DD => true,
+ 0x9DF => true,
+ 0xA33 => true,
+ 0xA36 => true,
+ 0xA59...0xA5B => true,
+ 0xA5E => true,
+ 0xB5C...0xB5D => true,
+ 0xE33 => true,
+ 0xEB3 => true,
+ 0xEDC...0xEDD => true,
+ 0xF0C => true,
+ 0xF43 => true,
+ 0xF4D => true,
+ 0xF52 => true,
+ 0xF57 => true,
+ 0xF5C => true,
+ 0xF69 => true,
+ 0xF73 => true,
+ 0xF75...0xF79 => true,
+ 0xF81 => true,
+ 0xF93 => true,
+ 0xF9D => true,
+ 0xFA2 => true,
+ 0xFA7 => true,
+ 0xFAC => true,
+ 0xFB9 => true,
+ 0x10A0...0x10C5 => true,
+ 0x10C7 => true,
+ 0x10CD => true,
+ 0x10FC => true,
+ 0x115F...0x1160 => true,
+ 0x13F8...0x13FD => true,
+ 0x17B4...0x17B5 => true,
+ 0x180B...0x180D => true,
+ 0x180E => true,
+ 0x180F => true,
+ 0x1C80...0x1C88 => true,
+ 0x1C90...0x1CBA => true,
+ 0x1CBD...0x1CBF => true,
+ 0x1D2C...0x1D2E => true,
+ 0x1D30...0x1D3A => true,
+ 0x1D3C...0x1D4D => true,
+ 0x1D4F...0x1D6A => true,
+ 0x1D78 => true,
+ 0x1D9B...0x1DBF => true,
+ 0x1E00 => true,
+ 0x1E02 => true,
+ 0x1E04 => true,
+ 0x1E06 => true,
+ 0x1E08 => true,
+ 0x1E0A => true,
+ 0x1E0C => true,
+ 0x1E0E => true,
+ 0x1E10 => true,
+ 0x1E12 => true,
+ 0x1E14 => true,
+ 0x1E16 => true,
+ 0x1E18 => true,
+ 0x1E1A => true,
+ 0x1E1C => true,
+ 0x1E1E => true,
+ 0x1E20 => true,
+ 0x1E22 => true,
+ 0x1E24 => true,
+ 0x1E26 => true,
+ 0x1E28 => true,
+ 0x1E2A => true,
+ 0x1E2C => true,
+ 0x1E2E => true,
+ 0x1E30 => true,
+ 0x1E32 => true,
+ 0x1E34 => true,
+ 0x1E36 => true,
+ 0x1E38 => true,
+ 0x1E3A => true,
+ 0x1E3C => true,
+ 0x1E3E => true,
+ 0x1E40 => true,
+ 0x1E42 => true,
+ 0x1E44 => true,
+ 0x1E46 => true,
+ 0x1E48 => true,
+ 0x1E4A => true,
+ 0x1E4C => true,
+ 0x1E4E => true,
+ 0x1E50 => true,
+ 0x1E52 => true,
+ 0x1E54 => true,
+ 0x1E56 => true,
+ 0x1E58 => true,
+ 0x1E5A => true,
+ 0x1E5C => true,
+ 0x1E5E => true,
+ 0x1E60 => true,
+ 0x1E62 => true,
+ 0x1E64 => true,
+ 0x1E66 => true,
+ 0x1E68 => true,
+ 0x1E6A => true,
+ 0x1E6C => true,
+ 0x1E6E => true,
+ 0x1E70 => true,
+ 0x1E72 => true,
+ 0x1E74 => true,
+ 0x1E76 => true,
+ 0x1E78 => true,
+ 0x1E7A => true,
+ 0x1E7C => true,
+ 0x1E7E => true,
+ 0x1E80 => true,
+ 0x1E82 => true,
+ 0x1E84 => true,
+ 0x1E86 => true,
+ 0x1E88 => true,
+ 0x1E8A => true,
+ 0x1E8C => true,
+ 0x1E8E => true,
+ 0x1E90 => true,
+ 0x1E92 => true,
+ 0x1E94 => true,
+ 0x1E9A...0x1E9B => true,
+ 0x1E9E => true,
+ 0x1EA0 => true,
+ 0x1EA2 => true,
+ 0x1EA4 => true,
+ 0x1EA6 => true,
+ 0x1EA8 => true,
+ 0x1EAA => true,
+ 0x1EAC => true,
+ 0x1EAE => true,
+ 0x1EB0 => true,
+ 0x1EB2 => true,
+ 0x1EB4 => true,
+ 0x1EB6 => true,
+ 0x1EB8 => true,
+ 0x1EBA => true,
+ 0x1EBC => true,
+ 0x1EBE => true,
+ 0x1EC0 => true,
+ 0x1EC2 => true,
+ 0x1EC4 => true,
+ 0x1EC6 => true,
+ 0x1EC8 => true,
+ 0x1ECA => true,
+ 0x1ECC => true,
+ 0x1ECE => true,
+ 0x1ED0 => true,
+ 0x1ED2 => true,
+ 0x1ED4 => true,
+ 0x1ED6 => true,
+ 0x1ED8 => true,
+ 0x1EDA => true,
+ 0x1EDC => true,
+ 0x1EDE => true,
+ 0x1EE0 => true,
+ 0x1EE2 => true,
+ 0x1EE4 => true,
+ 0x1EE6 => true,
+ 0x1EE8 => true,
+ 0x1EEA => true,
+ 0x1EEC => true,
+ 0x1EEE => true,
+ 0x1EF0 => true,
+ 0x1EF2 => true,
+ 0x1EF4 => true,
+ 0x1EF6 => true,
+ 0x1EF8 => true,
+ 0x1EFA => true,
+ 0x1EFC => true,
+ 0x1EFE => true,
+ 0x1F08...0x1F0F => true,
+ 0x1F18...0x1F1D => true,
+ 0x1F28...0x1F2F => true,
+ 0x1F38...0x1F3F => true,
+ 0x1F48...0x1F4D => true,
+ 0x1F59 => true,
+ 0x1F5B => true,
+ 0x1F5D => true,
+ 0x1F5F => true,
+ 0x1F68...0x1F6F => true,
+ 0x1F71 => true,
+ 0x1F73 => true,
+ 0x1F75 => true,
+ 0x1F77 => true,
+ 0x1F79 => true,
+ 0x1F7B => true,
+ 0x1F7D => true,
+ 0x1F80...0x1FAF => true,
+ 0x1FB2...0x1FB4 => true,
+ 0x1FB7...0x1FBC => true,
+ 0x1FBD => true,
+ 0x1FBE => true,
+ 0x1FBF...0x1FC1 => true,
+ 0x1FC2...0x1FC4 => true,
+ 0x1FC7...0x1FCC => true,
+ 0x1FCD...0x1FCF => true,
+ 0x1FD3 => true,
+ 0x1FD8...0x1FDB => true,
+ 0x1FDD...0x1FDF => true,
+ 0x1FE3 => true,
+ 0x1FE8...0x1FEC => true,
+ 0x1FED...0x1FEF => true,
+ 0x1FF2...0x1FF4 => true,
+ 0x1FF7...0x1FFC => true,
+ 0x1FFD...0x1FFE => true,
+ 0x2000...0x200A => true,
+ 0x200B...0x200F => true,
+ 0x2011 => true,
+ 0x2017 => true,
+ 0x2024...0x2026 => true,
+ 0x202A...0x202E => true,
+ 0x202F => true,
+ 0x2033...0x2034 => true,
+ 0x2036...0x2037 => true,
+ 0x203C => true,
+ 0x203E => true,
+ 0x2047...0x2049 => true,
+ 0x2057 => true,
+ 0x205F => true,
+ 0x2060...0x2064 => true,
+ 0x2065 => true,
+ 0x2066...0x206F => true,
+ 0x2070 => true,
+ 0x2071 => true,
+ 0x2074...0x2079 => true,
+ 0x207A...0x207C => true,
+ 0x207D => true,
+ 0x207E => true,
+ 0x207F => true,
+ 0x2080...0x2089 => true,
+ 0x208A...0x208C => true,
+ 0x208D => true,
+ 0x208E => true,
+ 0x2090...0x209C => true,
+ 0x20A8 => true,
+ 0x2100...0x2101 => true,
+ 0x2102 => true,
+ 0x2103 => true,
+ 0x2105...0x2106 => true,
+ 0x2107 => true,
+ 0x2109 => true,
+ 0x210A...0x2113 => true,
+ 0x2115 => true,
+ 0x2116 => true,
+ 0x2119...0x211D => true,
+ 0x2120...0x2122 => true,
+ 0x2124 => true,
+ 0x2126 => true,
+ 0x2128 => true,
+ 0x212A...0x212D => true,
+ 0x212F...0x2134 => true,
+ 0x2135...0x2138 => true,
+ 0x2139 => true,
+ 0x213B => true,
+ 0x213C...0x213F => true,
+ 0x2140 => true,
+ 0x2145...0x2149 => true,
+ 0x2150...0x215F => true,
+ 0x2160...0x217F => true,
+ 0x2183 => true,
+ 0x2189 => true,
+ 0x222C...0x222D => true,
+ 0x222F...0x2230 => true,
+ 0x2329 => true,
+ 0x232A => true,
+ 0x2460...0x249B => true,
+ 0x249C...0x24E9 => true,
+ 0x24EA => true,
+ 0x2A0C => true,
+ 0x2A74...0x2A76 => true,
+ 0x2ADC => true,
+ 0x2C00...0x2C2F => true,
+ 0x2C60 => true,
+ 0x2C62...0x2C64 => true,
+ 0x2C67 => true,
+ 0x2C69 => true,
+ 0x2C6B => true,
+ 0x2C6D...0x2C70 => true,
+ 0x2C72 => true,
+ 0x2C75 => true,
+ 0x2C7C...0x2C7D => true,
+ 0x2C7E...0x2C80 => true,
+ 0x2C82 => true,
+ 0x2C84 => true,
+ 0x2C86 => true,
+ 0x2C88 => true,
+ 0x2C8A => true,
+ 0x2C8C => true,
+ 0x2C8E => true,
+ 0x2C90 => true,
+ 0x2C92 => true,
+ 0x2C94 => true,
+ 0x2C96 => true,
+ 0x2C98 => true,
+ 0x2C9A => true,
+ 0x2C9C => true,
+ 0x2C9E => true,
+ 0x2CA0 => true,
+ 0x2CA2 => true,
+ 0x2CA4 => true,
+ 0x2CA6 => true,
+ 0x2CA8 => true,
+ 0x2CAA => true,
+ 0x2CAC => true,
+ 0x2CAE => true,
+ 0x2CB0 => true,
+ 0x2CB2 => true,
+ 0x2CB4 => true,
+ 0x2CB6 => true,
+ 0x2CB8 => true,
+ 0x2CBA => true,
+ 0x2CBC => true,
+ 0x2CBE => true,
+ 0x2CC0 => true,
+ 0x2CC2 => true,
+ 0x2CC4 => true,
+ 0x2CC6 => true,
+ 0x2CC8 => true,
+ 0x2CCA => true,
+ 0x2CCC => true,
+ 0x2CCE => true,
+ 0x2CD0 => true,
+ 0x2CD2 => true,
+ 0x2CD4 => true,
+ 0x2CD6 => true,
+ 0x2CD8 => true,
+ 0x2CDA => true,
+ 0x2CDC => true,
+ 0x2CDE => true,
+ 0x2CE0 => true,
+ 0x2CE2 => true,
+ 0x2CEB => true,
+ 0x2CED => true,
+ 0x2CF2 => true,
+ 0x2D6F => true,
+ 0x2E9F => true,
+ 0x2EF3 => true,
+ 0x2F00...0x2FD5 => true,
+ 0x3000 => true,
+ 0x3036 => true,
+ 0x3038...0x303A => true,
+ 0x309B...0x309C => true,
+ 0x309F => true,
+ 0x30FF => true,
+ 0x3131...0x318E => true,
+ 0x3192...0x3195 => true,
+ 0x3196...0x319F => true,
+ 0x3200...0x321E => true,
+ 0x3220...0x3229 => true,
+ 0x322A...0x3247 => true,
+ 0x3250 => true,
+ 0x3251...0x325F => true,
+ 0x3260...0x327E => true,
+ 0x3280...0x3289 => true,
+ 0x328A...0x32B0 => true,
+ 0x32B1...0x32BF => true,
+ 0x32C0...0x33FF => true,
+ 0xA640 => true,
+ 0xA642 => true,
+ 0xA644 => true,
+ 0xA646 => true,
+ 0xA648 => true,
+ 0xA64A => true,
+ 0xA64C => true,
+ 0xA64E => true,
+ 0xA650 => true,
+ 0xA652 => true,
+ 0xA654 => true,
+ 0xA656 => true,
+ 0xA658 => true,
+ 0xA65A => true,
+ 0xA65C => true,
+ 0xA65E => true,
+ 0xA660 => true,
+ 0xA662 => true,
+ 0xA664 => true,
+ 0xA666 => true,
+ 0xA668 => true,
+ 0xA66A => true,
+ 0xA66C => true,
+ 0xA680 => true,
+ 0xA682 => true,
+ 0xA684 => true,
+ 0xA686 => true,
+ 0xA688 => true,
+ 0xA68A => true,
+ 0xA68C => true,
+ 0xA68E => true,
+ 0xA690 => true,
+ 0xA692 => true,
+ 0xA694 => true,
+ 0xA696 => true,
+ 0xA698 => true,
+ 0xA69A => true,
+ 0xA69C...0xA69D => true,
+ 0xA722 => true,
+ 0xA724 => true,
+ 0xA726 => true,
+ 0xA728 => true,
+ 0xA72A => true,
+ 0xA72C => true,
+ 0xA72E => true,
+ 0xA732 => true,
+ 0xA734 => true,
+ 0xA736 => true,
+ 0xA738 => true,
+ 0xA73A => true,
+ 0xA73C => true,
+ 0xA73E => true,
+ 0xA740 => true,
+ 0xA742 => true,
+ 0xA744 => true,
+ 0xA746 => true,
+ 0xA748 => true,
+ 0xA74A => true,
+ 0xA74C => true,
+ 0xA74E => true,
+ 0xA750 => true,
+ 0xA752 => true,
+ 0xA754 => true,
+ 0xA756 => true,
+ 0xA758 => true,
+ 0xA75A => true,
+ 0xA75C => true,
+ 0xA75E => true,
+ 0xA760 => true,
+ 0xA762 => true,
+ 0xA764 => true,
+ 0xA766 => true,
+ 0xA768 => true,
+ 0xA76A => true,
+ 0xA76C => true,
+ 0xA76E => true,
+ 0xA770 => true,
+ 0xA779 => true,
+ 0xA77B => true,
+ 0xA77D...0xA77E => true,
+ 0xA780 => true,
+ 0xA782 => true,
+ 0xA784 => true,
+ 0xA786 => true,
+ 0xA78B => true,
+ 0xA78D => true,
+ 0xA790 => true,
+ 0xA792 => true,
+ 0xA796 => true,
+ 0xA798 => true,
+ 0xA79A => true,
+ 0xA79C => true,
+ 0xA79E => true,
+ 0xA7A0 => true,
+ 0xA7A2 => true,
+ 0xA7A4 => true,
+ 0xA7A6 => true,
+ 0xA7A8 => true,
+ 0xA7AA...0xA7AE => true,
+ 0xA7B0...0xA7B4 => true,
+ 0xA7B6 => true,
+ 0xA7B8 => true,
+ 0xA7BA => true,
+ 0xA7BC => true,
+ 0xA7BE => true,
+ 0xA7C0 => true,
+ 0xA7C2 => true,
+ 0xA7C4...0xA7C7 => true,
+ 0xA7C9 => true,
+ 0xA7D0 => true,
+ 0xA7D6 => true,
+ 0xA7D8 => true,
+ 0xA7F2...0xA7F4 => true,
+ 0xA7F5 => true,
+ 0xA7F8...0xA7F9 => true,
+ 0xAB5C...0xAB5F => true,
+ 0xAB69 => true,
+ 0xAB70...0xABBF => true,
+ 0xF900...0xFA0D => true,
+ 0xFA10 => true,
+ 0xFA12 => true,
+ 0xFA15...0xFA1E => true,
+ 0xFA20 => true,
+ 0xFA22 => true,
+ 0xFA25...0xFA26 => true,
+ 0xFA2A...0xFA6D => true,
+ 0xFA70...0xFAD9 => true,
+ 0xFB00...0xFB06 => true,
+ 0xFB13...0xFB17 => true,
+ 0xFB1D => true,
+ 0xFB1F...0xFB28 => true,
+ 0xFB29 => true,
+ 0xFB2A...0xFB36 => true,
+ 0xFB38...0xFB3C => true,
+ 0xFB3E => true,
+ 0xFB40...0xFB41 => true,
+ 0xFB43...0xFB44 => true,
+ 0xFB46...0xFBB1 => true,
+ 0xFBD3...0xFD3D => true,
+ 0xFD50...0xFD8F => true,
+ 0xFD92...0xFDC7 => true,
+ 0xFDF0...0xFDFB => true,
+ 0xFDFC => true,
+ 0xFE00...0xFE0F => true,
+ 0xFE10...0xFE16 => true,
+ 0xFE17 => true,
+ 0xFE18 => true,
+ 0xFE19 => true,
+ 0xFE30 => true,
+ 0xFE31...0xFE32 => true,
+ 0xFE33...0xFE34 => true,
+ 0xFE35 => true,
+ 0xFE36 => true,
+ 0xFE37 => true,
+ 0xFE38 => true,
+ 0xFE39 => true,
+ 0xFE3A => true,
+ 0xFE3B => true,
+ 0xFE3C => true,
+ 0xFE3D => true,
+ 0xFE3E => true,
+ 0xFE3F => true,
+ 0xFE40 => true,
+ 0xFE41 => true,
+ 0xFE42 => true,
+ 0xFE43 => true,
+ 0xFE44 => true,
+ 0xFE47 => true,
+ 0xFE48 => true,
+ 0xFE49...0xFE4C => true,
+ 0xFE4D...0xFE4F => true,
+ 0xFE50...0xFE52 => true,
+ 0xFE54...0xFE57 => true,
+ 0xFE58 => true,
+ 0xFE59 => true,
+ 0xFE5A => true,
+ 0xFE5B => true,
+ 0xFE5C => true,
+ 0xFE5D => true,
+ 0xFE5E => true,
+ 0xFE5F...0xFE61 => true,
+ 0xFE62 => true,
+ 0xFE63 => true,
+ 0xFE64...0xFE66 => true,
+ 0xFE68 => true,
+ 0xFE69 => true,
+ 0xFE6A...0xFE6B => true,
+ 0xFE70...0xFE72 => true,
+ 0xFE74 => true,
+ 0xFE76...0xFEFC => true,
+ 0xFEFF => true,
+ 0xFF01...0xFF03 => true,
+ 0xFF04 => true,
+ 0xFF05...0xFF07 => true,
+ 0xFF08 => true,
+ 0xFF09 => true,
+ 0xFF0A => true,
+ 0xFF0B => true,
+ 0xFF0C => true,
+ 0xFF0D => true,
+ 0xFF0E...0xFF0F => true,
+ 0xFF10...0xFF19 => true,
+ 0xFF1A...0xFF1B => true,
+ 0xFF1C...0xFF1E => true,
+ 0xFF1F...0xFF20 => true,
+ 0xFF21...0xFF3A => true,
+ 0xFF3B => true,
+ 0xFF3C => true,
+ 0xFF3D => true,
+ 0xFF3E => true,
+ 0xFF3F => true,
+ 0xFF40 => true,
+ 0xFF41...0xFF5A => true,
+ 0xFF5B => true,
+ 0xFF5C => true,
+ 0xFF5D => true,
+ 0xFF5E => true,
+ 0xFF5F => true,
+ 0xFF60 => true,
+ 0xFF61 => true,
+ 0xFF62 => true,
+ 0xFF63 => true,
+ 0xFF64...0xFF65 => true,
+ 0xFF66...0xFF6F => true,
+ 0xFF70 => true,
+ 0xFF71...0xFF9D => true,
+ 0xFF9E...0xFF9F => true,
+ 0xFFA0...0xFFBE => true,
+ 0xFFC2...0xFFC7 => true,
+ 0xFFCA...0xFFCF => true,
+ 0xFFD2...0xFFD7 => true,
+ 0xFFDA...0xFFDC => true,
+ 0xFFE0...0xFFE1 => true,
+ 0xFFE2 => true,
+ 0xFFE3 => true,
+ 0xFFE4 => true,
+ 0xFFE5...0xFFE6 => true,
+ 0xFFE8 => true,
+ 0xFFE9...0xFFEC => true,
+ 0xFFED...0xFFEE => true,
+ 0xFFF0...0xFFF8 => true,
+ 0x10400...0x10427 => true,
+ 0x104B0...0x104D3 => true,
+ 0x10570...0x1057A => true,
+ 0x1057C...0x1058A => true,
+ 0x1058C...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10781...0x10785 => true,
+ 0x10787...0x107B0 => true,
+ 0x107B2...0x107BA => true,
+ 0x10C80...0x10CB2 => true,
+ 0x118A0...0x118BF => true,
+ 0x16E40...0x16E5F => true,
+ 0x1BCA0...0x1BCA3 => true,
+ 0x1D15E...0x1D164 => true,
+ 0x1D173...0x1D17A => true,
+ 0x1D1BB...0x1D1C0 => true,
+ 0x1D400...0x1D454 => true,
+ 0x1D456...0x1D49C => true,
+ 0x1D49E...0x1D49F => true,
+ 0x1D4A2 => true,
+ 0x1D4A5...0x1D4A6 => true,
+ 0x1D4A9...0x1D4AC => true,
+ 0x1D4AE...0x1D4B9 => true,
+ 0x1D4BB => true,
+ 0x1D4BD...0x1D4C3 => true,
+ 0x1D4C5...0x1D505 => true,
+ 0x1D507...0x1D50A => true,
+ 0x1D50D...0x1D514 => true,
+ 0x1D516...0x1D51C => true,
+ 0x1D51E...0x1D539 => true,
+ 0x1D53B...0x1D53E => true,
+ 0x1D540...0x1D544 => true,
+ 0x1D546 => true,
+ 0x1D54A...0x1D550 => true,
+ 0x1D552...0x1D6A5 => true,
+ 0x1D6A8...0x1D6C0 => true,
+ 0x1D6C1 => true,
+ 0x1D6C2...0x1D6DA => true,
+ 0x1D6DB => true,
+ 0x1D6DC...0x1D6FA => true,
+ 0x1D6FB => true,
+ 0x1D6FC...0x1D714 => true,
+ 0x1D715 => true,
+ 0x1D716...0x1D734 => true,
+ 0x1D735 => true,
+ 0x1D736...0x1D74E => true,
+ 0x1D74F => true,
+ 0x1D750...0x1D76E => true,
+ 0x1D76F => true,
+ 0x1D770...0x1D788 => true,
+ 0x1D789 => true,
+ 0x1D78A...0x1D7A8 => true,
+ 0x1D7A9 => true,
+ 0x1D7AA...0x1D7C2 => true,
+ 0x1D7C3 => true,
+ 0x1D7C4...0x1D7CB => true,
+ 0x1D7CE...0x1D7FF => true,
+ 0x1E030...0x1E06D => true,
+ 0x1E900...0x1E921 => true,
+ 0x1EE00...0x1EE03 => true,
+ 0x1EE05...0x1EE1F => true,
+ 0x1EE21...0x1EE22 => true,
+ 0x1EE24 => true,
+ 0x1EE27 => true,
+ 0x1EE29...0x1EE32 => true,
+ 0x1EE34...0x1EE37 => true,
+ 0x1EE39 => true,
+ 0x1EE3B => true,
+ 0x1EE42 => true,
+ 0x1EE47 => true,
+ 0x1EE49 => true,
+ 0x1EE4B => true,
+ 0x1EE4D...0x1EE4F => true,
+ 0x1EE51...0x1EE52 => true,
+ 0x1EE54 => true,
+ 0x1EE57 => true,
+ 0x1EE59 => true,
+ 0x1EE5B => true,
+ 0x1EE5D => true,
+ 0x1EE5F => true,
+ 0x1EE61...0x1EE62 => true,
+ 0x1EE64 => true,
+ 0x1EE67...0x1EE6A => true,
+ 0x1EE6C...0x1EE72 => true,
+ 0x1EE74...0x1EE77 => true,
+ 0x1EE79...0x1EE7C => true,
+ 0x1EE7E => true,
+ 0x1EE80...0x1EE89 => true,
+ 0x1EE8B...0x1EE9B => true,
+ 0x1EEA1...0x1EEA3 => true,
+ 0x1EEA5...0x1EEA9 => true,
+ 0x1EEAB...0x1EEBB => true,
+ 0x1F100...0x1F10A => true,
+ 0x1F110...0x1F12E => true,
+ 0x1F130...0x1F14F => true,
+ 0x1F16A...0x1F16C => true,
+ 0x1F190 => true,
+ 0x1F200...0x1F202 => true,
+ 0x1F210...0x1F23B => true,
+ 0x1F240...0x1F248 => true,
+ 0x1F250...0x1F251 => true,
+ 0x1FBF0...0x1FBF9 => true,
+ 0x2F800...0x2FA1D => true,
+ 0xE0000 => true,
+ 0xE0001 => true,
+ 0xE0002...0xE001F => true,
+ 0xE0020...0xE007F => true,
+ 0xE0080...0xE00FF => true,
+ 0xE0100...0xE01EF => true,
+ 0xE01F0...0xE0FFF => true,
+ else => false,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/derived_numeric_type.zig.html b/docs/src/ziglyph/autogen/derived_numeric_type.zig.html
new file mode 100644
index 0000000..2d22e48
--- /dev/null
+++ b/docs/src/ziglyph/autogen/derived_numeric_type.zig.html
@@ -0,0 +1,382 @@
+
+
+
+
+
autogen/derived_numeric_type.zig - source view
+
+
+
+
+
+
+
+
+pub fn isNumeric(cp: u21) bool {
+ if (cp < 0xbc or cp > 0x2f890) return false;
+
+ return switch (cp) {
+ 0xbc...0xbe => true,
+ 0x9f4...0x9f9 => true,
+ 0xb72...0xb77 => true,
+ 0xbf0...0xbf2 => true,
+ 0xc78...0xc7e => true,
+ 0xd58...0xd5e => true,
+ 0xd70...0xd78 => true,
+ 0xf2a...0xf33 => true,
+ 0x1372...0x137c => true,
+ 0x16ee...0x16f0 => true,
+ 0x17f0...0x17f9 => true,
+ 0x2150...0x215f => true,
+ 0x2160...0x2182 => true,
+ 0x2185...0x2188 => true,
+ 0x2189 => true,
+ 0x2469...0x2473 => true,
+ 0x247d...0x2487 => true,
+ 0x2491...0x249b => true,
+ 0x24eb...0x24f4 => true,
+ 0x24fe => true,
+ 0x277f => true,
+ 0x2789 => true,
+ 0x2793 => true,
+ 0x2cfd => true,
+ 0x3007 => true,
+ 0x3021...0x3029 => true,
+ 0x3038...0x303a => true,
+ 0x3192...0x3195 => true,
+ 0x3220...0x3229 => true,
+ 0x3248...0x324f => true,
+ 0x3251...0x325f => true,
+ 0x3280...0x3289 => true,
+ 0x32b1...0x32bf => true,
+ 0x3405 => true,
+ 0x3483 => true,
+ 0x382a => true,
+ 0x3b4d => true,
+ 0x4e00 => true,
+ 0x4e03 => true,
+ 0x4e07 => true,
+ 0x4e09 => true,
+ 0x4e5d => true,
+ 0x4e8c => true,
+ 0x4e94 => true,
+ 0x4e96 => true,
+ 0x4ebf...0x4ec0 => true,
+ 0x4edf => true,
+ 0x4ee8 => true,
+ 0x4f0d => true,
+ 0x4f70 => true,
+ 0x5104 => true,
+ 0x5146 => true,
+ 0x5169 => true,
+ 0x516b => true,
+ 0x516d => true,
+ 0x5341 => true,
+ 0x5343...0x5345 => true,
+ 0x534c => true,
+ 0x53c1...0x53c4 => true,
+ 0x56db => true,
+ 0x58f1 => true,
+ 0x58f9 => true,
+ 0x5e7a => true,
+ 0x5efe...0x5eff => true,
+ 0x5f0c...0x5f0e => true,
+ 0x5f10 => true,
+ 0x62fe => true,
+ 0x634c => true,
+ 0x67d2 => true,
+ 0x6f06 => true,
+ 0x7396 => true,
+ 0x767e => true,
+ 0x8086 => true,
+ 0x842c => true,
+ 0x8cae => true,
+ 0x8cb3 => true,
+ 0x8d30 => true,
+ 0x9621 => true,
+ 0x9646 => true,
+ 0x964c => true,
+ 0x9678 => true,
+ 0x96f6 => true,
+ 0xa6e6...0xa6ef => true,
+ 0xa830...0xa835 => true,
+ 0xf96b => true,
+ 0xf973 => true,
+ 0xf978 => true,
+ 0xf9b2 => true,
+ 0xf9d1 => true,
+ 0xf9d3 => true,
+ 0xf9fd => true,
+ 0x10107...0x10133 => true,
+ 0x10140...0x10174 => true,
+ 0x10175...0x10178 => true,
+ 0x1018a...0x1018b => true,
+ 0x102e1...0x102fb => true,
+ 0x10320...0x10323 => true,
+ 0x10341 => true,
+ 0x1034a => true,
+ 0x103d1...0x103d5 => true,
+ 0x10858...0x1085f => true,
+ 0x10879...0x1087f => true,
+ 0x108a7...0x108af => true,
+ 0x108fb...0x108ff => true,
+ 0x10916...0x1091b => true,
+ 0x109bc...0x109bd => true,
+ 0x109c0...0x109cf => true,
+ 0x109d2...0x109ff => true,
+ 0x10a44...0x10a48 => true,
+ 0x10a7d...0x10a7e => true,
+ 0x10a9d...0x10a9f => true,
+ 0x10aeb...0x10aef => true,
+ 0x10b58...0x10b5f => true,
+ 0x10b78...0x10b7f => true,
+ 0x10ba9...0x10baf => true,
+ 0x10cfa...0x10cff => true,
+ 0x10e69...0x10e7e => true,
+ 0x10f1d...0x10f26 => true,
+ 0x10f51...0x10f54 => true,
+ 0x10fc5...0x10fcb => true,
+ 0x1105b...0x11065 => true,
+ 0x111e1...0x111f4 => true,
+ 0x1173a...0x1173b => true,
+ 0x118ea...0x118f2 => true,
+ 0x11c5a...0x11c6c => true,
+ 0x11fc0...0x11fd4 => true,
+ 0x12400...0x1246e => true,
+ 0x16b5b...0x16b61 => true,
+ 0x16e80...0x16e96 => true,
+ 0x1d2c0...0x1d2d3 => true,
+ 0x1d2e0...0x1d2f3 => true,
+ 0x1d360...0x1d378 => true,
+ 0x1e8c7...0x1e8cf => true,
+ 0x1ec71...0x1ecab => true,
+ 0x1ecad...0x1ecaf => true,
+ 0x1ecb1...0x1ecb4 => true,
+ 0x1ed01...0x1ed2d => true,
+ 0x1ed2f...0x1ed3d => true,
+ 0x1f10b...0x1f10c => true,
+ 0x20001 => true,
+ 0x20064 => true,
+ 0x200e2 => true,
+ 0x20121 => true,
+ 0x2092a => true,
+ 0x20983 => true,
+ 0x2098c => true,
+ 0x2099c => true,
+ 0x20aea => true,
+ 0x20afd => true,
+ 0x20b19 => true,
+ 0x22390 => true,
+ 0x22998 => true,
+ 0x23b1b => true,
+ 0x2626d => true,
+ 0x2f890 => true,
+ else => false,
+ };
+}
+
+pub fn isDigit(cp: u21) bool {
+ if (cp < 0xb2 or cp > 0x1f10a) return false;
+
+ return switch (cp) {
+ 0xb2...0xb3 => true,
+ 0xb9 => true,
+ 0x1369...0x1371 => true,
+ 0x19da => true,
+ 0x2070 => true,
+ 0x2074...0x2079 => true,
+ 0x2080...0x2089 => true,
+ 0x2460...0x2468 => true,
+ 0x2474...0x247c => true,
+ 0x2488...0x2490 => true,
+ 0x24ea => true,
+ 0x24f5...0x24fd => true,
+ 0x24ff => true,
+ 0x2776...0x277e => true,
+ 0x2780...0x2788 => true,
+ 0x278a...0x2792 => true,
+ 0x10a40...0x10a43 => true,
+ 0x10e60...0x10e68 => true,
+ 0x11052...0x1105a => true,
+ 0x1f100...0x1f10a => true,
+ else => false,
+ };
+}
+
+pub fn isDecimal(cp: u21) bool {
+ if (cp < 0x30 or cp > 0x1fbf9) return false;
+
+ return switch (cp) {
+ 0x30...0x39 => true,
+ 0x660...0x669 => true,
+ 0x6f0...0x6f9 => true,
+ 0x7c0...0x7c9 => true,
+ 0x966...0x96f => true,
+ 0x9e6...0x9ef => true,
+ 0xa66...0xa6f => true,
+ 0xae6...0xaef => true,
+ 0xb66...0xb6f => true,
+ 0xbe6...0xbef => true,
+ 0xc66...0xc6f => true,
+ 0xce6...0xcef => true,
+ 0xd66...0xd6f => true,
+ 0xde6...0xdef => true,
+ 0xe50...0xe59 => true,
+ 0xed0...0xed9 => true,
+ 0xf20...0xf29 => true,
+ 0x1040...0x1049 => true,
+ 0x1090...0x1099 => true,
+ 0x17e0...0x17e9 => true,
+ 0x1810...0x1819 => true,
+ 0x1946...0x194f => true,
+ 0x19d0...0x19d9 => true,
+ 0x1a80...0x1a89 => true,
+ 0x1a90...0x1a99 => true,
+ 0x1b50...0x1b59 => true,
+ 0x1bb0...0x1bb9 => true,
+ 0x1c40...0x1c49 => true,
+ 0x1c50...0x1c59 => true,
+ 0xa620...0xa629 => true,
+ 0xa8d0...0xa8d9 => true,
+ 0xa900...0xa909 => true,
+ 0xa9d0...0xa9d9 => true,
+ 0xa9f0...0xa9f9 => true,
+ 0xaa50...0xaa59 => true,
+ 0xabf0...0xabf9 => true,
+ 0xff10...0xff19 => true,
+ 0x104a0...0x104a9 => true,
+ 0x10d30...0x10d39 => true,
+ 0x11066...0x1106f => true,
+ 0x110f0...0x110f9 => true,
+ 0x11136...0x1113f => true,
+ 0x111d0...0x111d9 => true,
+ 0x112f0...0x112f9 => true,
+ 0x11450...0x11459 => true,
+ 0x114d0...0x114d9 => true,
+ 0x11650...0x11659 => true,
+ 0x116c0...0x116c9 => true,
+ 0x11730...0x11739 => true,
+ 0x118e0...0x118e9 => true,
+ 0x11950...0x11959 => true,
+ 0x11c50...0x11c59 => true,
+ 0x11d50...0x11d59 => true,
+ 0x11da0...0x11da9 => true,
+ 0x11f50...0x11f59 => true,
+ 0x16a60...0x16a69 => true,
+ 0x16ac0...0x16ac9 => true,
+ 0x16b50...0x16b59 => true,
+ 0x1d7ce...0x1d7ff => true,
+ 0x1e140...0x1e149 => true,
+ 0x1e2f0...0x1e2f9 => true,
+ 0x1e4f0...0x1e4f9 => true,
+ 0x1e950...0x1e959 => true,
+ 0x1fbf0...0x1fbf9 => true,
+ else => false,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/emoji_data.zig.html b/docs/src/ziglyph/autogen/emoji_data.zig.html
new file mode 100644
index 0000000..2365242
--- /dev/null
+++ b/docs/src/ziglyph/autogen/emoji_data.zig.html
@@ -0,0 +1,1425 @@
+
+
+
+
+
autogen/emoji_data.zig - source view
+
+
+
+
+
+
+
+
+pub fn isEmoji(cp: u21) bool {
+ if (cp < 0x23 or cp > 0x1faf8) return false;
+
+ return switch (cp) {
+ 0x23 => true,
+ 0x2a => true,
+ 0x30...0x39 => true,
+ 0xa9 => true,
+ 0xae => true,
+ 0x203c => true,
+ 0x2049 => true,
+ 0x2122 => true,
+ 0x2139 => true,
+ 0x2194...0x2199 => true,
+ 0x21a9...0x21aa => true,
+ 0x231a...0x231b => true,
+ 0x2328 => true,
+ 0x23cf => true,
+ 0x23e9...0x23ec => true,
+ 0x23ed...0x23ee => true,
+ 0x23ef => true,
+ 0x23f0 => true,
+ 0x23f1...0x23f2 => true,
+ 0x23f3 => true,
+ 0x23f8...0x23fa => true,
+ 0x24c2 => true,
+ 0x25aa...0x25ab => true,
+ 0x25b6 => true,
+ 0x25c0 => true,
+ 0x25fb...0x25fe => true,
+ 0x2600...0x2601 => true,
+ 0x2602...0x2603 => true,
+ 0x2604 => true,
+ 0x260e => true,
+ 0x2611 => true,
+ 0x2614...0x2615 => true,
+ 0x2618 => true,
+ 0x261d => true,
+ 0x2620 => true,
+ 0x2622...0x2623 => true,
+ 0x2626 => true,
+ 0x262a => true,
+ 0x262e => true,
+ 0x262f => true,
+ 0x2638...0x2639 => true,
+ 0x263a => true,
+ 0x2640 => true,
+ 0x2642 => true,
+ 0x2648...0x2653 => true,
+ 0x265f => true,
+ 0x2660 => true,
+ 0x2663 => true,
+ 0x2665...0x2666 => true,
+ 0x2668 => true,
+ 0x267b => true,
+ 0x267e => true,
+ 0x267f => true,
+ 0x2692 => true,
+ 0x2693 => true,
+ 0x2694 => true,
+ 0x2695 => true,
+ 0x2696...0x2697 => true,
+ 0x2699 => true,
+ 0x269b...0x269c => true,
+ 0x26a0...0x26a1 => true,
+ 0x26a7 => true,
+ 0x26aa...0x26ab => true,
+ 0x26b0...0x26b1 => true,
+ 0x26bd...0x26be => true,
+ 0x26c4...0x26c5 => true,
+ 0x26c8 => true,
+ 0x26ce => true,
+ 0x26cf => true,
+ 0x26d1 => true,
+ 0x26d3 => true,
+ 0x26d4 => true,
+ 0x26e9 => true,
+ 0x26ea => true,
+ 0x26f0...0x26f1 => true,
+ 0x26f2...0x26f3 => true,
+ 0x26f4 => true,
+ 0x26f5 => true,
+ 0x26f7...0x26f9 => true,
+ 0x26fa => true,
+ 0x26fd => true,
+ 0x2702 => true,
+ 0x2705 => true,
+ 0x2708...0x270c => true,
+ 0x270d => true,
+ 0x270f => true,
+ 0x2712 => true,
+ 0x2714 => true,
+ 0x2716 => true,
+ 0x271d => true,
+ 0x2721 => true,
+ 0x2728 => true,
+ 0x2733...0x2734 => true,
+ 0x2744 => true,
+ 0x2747 => true,
+ 0x274c => true,
+ 0x274e => true,
+ 0x2753...0x2755 => true,
+ 0x2757 => true,
+ 0x2763 => true,
+ 0x2764 => true,
+ 0x2795...0x2797 => true,
+ 0x27a1 => true,
+ 0x27b0 => true,
+ 0x27bf => true,
+ 0x2934...0x2935 => true,
+ 0x2b05...0x2b07 => true,
+ 0x2b1b...0x2b1c => true,
+ 0x2b50 => true,
+ 0x2b55 => true,
+ 0x3030 => true,
+ 0x303d => true,
+ 0x3297 => true,
+ 0x3299 => true,
+ 0x1f004 => true,
+ 0x1f0cf => true,
+ 0x1f170...0x1f171 => true,
+ 0x1f17e...0x1f17f => true,
+ 0x1f18e => true,
+ 0x1f191...0x1f19a => true,
+ 0x1f1e6...0x1f1ff => true,
+ 0x1f201...0x1f202 => true,
+ 0x1f21a => true,
+ 0x1f22f => true,
+ 0x1f232...0x1f23a => true,
+ 0x1f250...0x1f251 => true,
+ 0x1f300...0x1f30c => true,
+ 0x1f30d...0x1f30e => true,
+ 0x1f30f => true,
+ 0x1f310 => true,
+ 0x1f311 => true,
+ 0x1f312 => true,
+ 0x1f313...0x1f315 => true,
+ 0x1f316...0x1f318 => true,
+ 0x1f319 => true,
+ 0x1f31a => true,
+ 0x1f31b => true,
+ 0x1f31c => true,
+ 0x1f31d...0x1f31e => true,
+ 0x1f31f...0x1f320 => true,
+ 0x1f321 => true,
+ 0x1f324...0x1f32c => true,
+ 0x1f32d...0x1f32f => true,
+ 0x1f330...0x1f331 => true,
+ 0x1f332...0x1f333 => true,
+ 0x1f334...0x1f335 => true,
+ 0x1f336 => true,
+ 0x1f337...0x1f34a => true,
+ 0x1f34b => true,
+ 0x1f34c...0x1f34f => true,
+ 0x1f350 => true,
+ 0x1f351...0x1f37b => true,
+ 0x1f37c => true,
+ 0x1f37d => true,
+ 0x1f37e...0x1f37f => true,
+ 0x1f380...0x1f393 => true,
+ 0x1f396...0x1f397 => true,
+ 0x1f399...0x1f39b => true,
+ 0x1f39e...0x1f39f => true,
+ 0x1f3a0...0x1f3c4 => true,
+ 0x1f3c5 => true,
+ 0x1f3c6 => true,
+ 0x1f3c7 => true,
+ 0x1f3c8 => true,
+ 0x1f3c9 => true,
+ 0x1f3ca => true,
+ 0x1f3cb...0x1f3ce => true,
+ 0x1f3cf...0x1f3d3 => true,
+ 0x1f3d4...0x1f3df => true,
+ 0x1f3e0...0x1f3e3 => true,
+ 0x1f3e4 => true,
+ 0x1f3e5...0x1f3f0 => true,
+ 0x1f3f3 => true,
+ 0x1f3f4 => true,
+ 0x1f3f5 => true,
+ 0x1f3f7 => true,
+ 0x1f3f8...0x1f407 => true,
+ 0x1f408 => true,
+ 0x1f409...0x1f40b => true,
+ 0x1f40c...0x1f40e => true,
+ 0x1f40f...0x1f410 => true,
+ 0x1f411...0x1f412 => true,
+ 0x1f413 => true,
+ 0x1f414 => true,
+ 0x1f415 => true,
+ 0x1f416 => true,
+ 0x1f417...0x1f429 => true,
+ 0x1f42a => true,
+ 0x1f42b...0x1f43e => true,
+ 0x1f43f => true,
+ 0x1f440 => true,
+ 0x1f441 => true,
+ 0x1f442...0x1f464 => true,
+ 0x1f465 => true,
+ 0x1f466...0x1f46b => true,
+ 0x1f46c...0x1f46d => true,
+ 0x1f46e...0x1f4ac => true,
+ 0x1f4ad => true,
+ 0x1f4ae...0x1f4b5 => true,
+ 0x1f4b6...0x1f4b7 => true,
+ 0x1f4b8...0x1f4eb => true,
+ 0x1f4ec...0x1f4ed => true,
+ 0x1f4ee => true,
+ 0x1f4ef => true,
+ 0x1f4f0...0x1f4f4 => true,
+ 0x1f4f5 => true,
+ 0x1f4f6...0x1f4f7 => true,
+ 0x1f4f8 => true,
+ 0x1f4f9...0x1f4fc => true,
+ 0x1f4fd => true,
+ 0x1f4ff...0x1f502 => true,
+ 0x1f503 => true,
+ 0x1f504...0x1f507 => true,
+ 0x1f508 => true,
+ 0x1f509 => true,
+ 0x1f50a...0x1f514 => true,
+ 0x1f515 => true,
+ 0x1f516...0x1f52b => true,
+ 0x1f52c...0x1f52d => true,
+ 0x1f52e...0x1f53d => true,
+ 0x1f549...0x1f54a => true,
+ 0x1f54b...0x1f54e => true,
+ 0x1f550...0x1f55b => true,
+ 0x1f55c...0x1f567 => true,
+ 0x1f56f...0x1f570 => true,
+ 0x1f573...0x1f579 => true,
+ 0x1f57a => true,
+ 0x1f587 => true,
+ 0x1f58a...0x1f58d => true,
+ 0x1f590 => true,
+ 0x1f595...0x1f596 => true,
+ 0x1f5a4 => true,
+ 0x1f5a5 => true,
+ 0x1f5a8 => true,
+ 0x1f5b1...0x1f5b2 => true,
+ 0x1f5bc => true,
+ 0x1f5c2...0x1f5c4 => true,
+ 0x1f5d1...0x1f5d3 => true,
+ 0x1f5dc...0x1f5de => true,
+ 0x1f5e1 => true,
+ 0x1f5e3 => true,
+ 0x1f5e8 => true,
+ 0x1f5ef => true,
+ 0x1f5f3 => true,
+ 0x1f5fa => true,
+ 0x1f5fb...0x1f5ff => true,
+ 0x1f600 => true,
+ 0x1f601...0x1f606 => true,
+ 0x1f607...0x1f608 => true,
+ 0x1f609...0x1f60d => true,
+ 0x1f60e => true,
+ 0x1f60f => true,
+ 0x1f610 => true,
+ 0x1f611 => true,
+ 0x1f612...0x1f614 => true,
+ 0x1f615 => true,
+ 0x1f616 => true,
+ 0x1f617 => true,
+ 0x1f618 => true,
+ 0x1f619 => true,
+ 0x1f61a => true,
+ 0x1f61b => true,
+ 0x1f61c...0x1f61e => true,
+ 0x1f61f => true,
+ 0x1f620...0x1f625 => true,
+ 0x1f626...0x1f627 => true,
+ 0x1f628...0x1f62b => true,
+ 0x1f62c => true,
+ 0x1f62d => true,
+ 0x1f62e...0x1f62f => true,
+ 0x1f630...0x1f633 => true,
+ 0x1f634 => true,
+ 0x1f635 => true,
+ 0x1f636 => true,
+ 0x1f637...0x1f640 => true,
+ 0x1f641...0x1f644 => true,
+ 0x1f645...0x1f64f => true,
+ 0x1f680 => true,
+ 0x1f681...0x1f682 => true,
+ 0x1f683...0x1f685 => true,
+ 0x1f686 => true,
+ 0x1f687 => true,
+ 0x1f688 => true,
+ 0x1f689 => true,
+ 0x1f68a...0x1f68b => true,
+ 0x1f68c => true,
+ 0x1f68d => true,
+ 0x1f68e => true,
+ 0x1f68f => true,
+ 0x1f690 => true,
+ 0x1f691...0x1f693 => true,
+ 0x1f694 => true,
+ 0x1f695 => true,
+ 0x1f696 => true,
+ 0x1f697 => true,
+ 0x1f698 => true,
+ 0x1f699...0x1f69a => true,
+ 0x1f69b...0x1f6a1 => true,
+ 0x1f6a2 => true,
+ 0x1f6a3 => true,
+ 0x1f6a4...0x1f6a5 => true,
+ 0x1f6a6 => true,
+ 0x1f6a7...0x1f6ad => true,
+ 0x1f6ae...0x1f6b1 => true,
+ 0x1f6b2 => true,
+ 0x1f6b3...0x1f6b5 => true,
+ 0x1f6b6 => true,
+ 0x1f6b7...0x1f6b8 => true,
+ 0x1f6b9...0x1f6be => true,
+ 0x1f6bf => true,
+ 0x1f6c0 => true,
+ 0x1f6c1...0x1f6c5 => true,
+ 0x1f6cb => true,
+ 0x1f6cc => true,
+ 0x1f6cd...0x1f6cf => true,
+ 0x1f6d0 => true,
+ 0x1f6d1...0x1f6d2 => true,
+ 0x1f6d5 => true,
+ 0x1f6d6...0x1f6d7 => true,
+ 0x1f6dc => true,
+ 0x1f6dd...0x1f6df => true,
+ 0x1f6e0...0x1f6e5 => true,
+ 0x1f6e9 => true,
+ 0x1f6eb...0x1f6ec => true,
+ 0x1f6f0 => true,
+ 0x1f6f3 => true,
+ 0x1f6f4...0x1f6f6 => true,
+ 0x1f6f7...0x1f6f8 => true,
+ 0x1f6f9 => true,
+ 0x1f6fa => true,
+ 0x1f6fb...0x1f6fc => true,
+ 0x1f7e0...0x1f7eb => true,
+ 0x1f7f0 => true,
+ 0x1f90c => true,
+ 0x1f90d...0x1f90f => true,
+ 0x1f910...0x1f918 => true,
+ 0x1f919...0x1f91e => true,
+ 0x1f91f => true,
+ 0x1f920...0x1f927 => true,
+ 0x1f928...0x1f92f => true,
+ 0x1f930 => true,
+ 0x1f931...0x1f932 => true,
+ 0x1f933...0x1f93a => true,
+ 0x1f93c...0x1f93e => true,
+ 0x1f93f => true,
+ 0x1f940...0x1f945 => true,
+ 0x1f947...0x1f94b => true,
+ 0x1f94c => true,
+ 0x1f94d...0x1f94f => true,
+ 0x1f950...0x1f95e => true,
+ 0x1f95f...0x1f96b => true,
+ 0x1f96c...0x1f970 => true,
+ 0x1f971 => true,
+ 0x1f972 => true,
+ 0x1f973...0x1f976 => true,
+ 0x1f977...0x1f978 => true,
+ 0x1f979 => true,
+ 0x1f97a => true,
+ 0x1f97b => true,
+ 0x1f97c...0x1f97f => true,
+ 0x1f980...0x1f984 => true,
+ 0x1f985...0x1f991 => true,
+ 0x1f992...0x1f997 => true,
+ 0x1f998...0x1f9a2 => true,
+ 0x1f9a3...0x1f9a4 => true,
+ 0x1f9a5...0x1f9aa => true,
+ 0x1f9ab...0x1f9ad => true,
+ 0x1f9ae...0x1f9af => true,
+ 0x1f9b0...0x1f9b9 => true,
+ 0x1f9ba...0x1f9bf => true,
+ 0x1f9c0 => true,
+ 0x1f9c1...0x1f9c2 => true,
+ 0x1f9c3...0x1f9ca => true,
+ 0x1f9cb => true,
+ 0x1f9cc => true,
+ 0x1f9cd...0x1f9cf => true,
+ 0x1f9d0...0x1f9e6 => true,
+ 0x1f9e7...0x1f9ff => true,
+ 0x1fa70...0x1fa73 => true,
+ 0x1fa74 => true,
+ 0x1fa75...0x1fa77 => true,
+ 0x1fa78...0x1fa7a => true,
+ 0x1fa7b...0x1fa7c => true,
+ 0x1fa80...0x1fa82 => true,
+ 0x1fa83...0x1fa86 => true,
+ 0x1fa87...0x1fa88 => true,
+ 0x1fa90...0x1fa95 => true,
+ 0x1fa96...0x1faa8 => true,
+ 0x1faa9...0x1faac => true,
+ 0x1faad...0x1faaf => true,
+ 0x1fab0...0x1fab6 => true,
+ 0x1fab7...0x1faba => true,
+ 0x1fabb...0x1fabd => true,
+ 0x1fabf => true,
+ 0x1fac0...0x1fac2 => true,
+ 0x1fac3...0x1fac5 => true,
+ 0x1face...0x1facf => true,
+ 0x1fad0...0x1fad6 => true,
+ 0x1fad7...0x1fad9 => true,
+ 0x1fada...0x1fadb => true,
+ 0x1fae0...0x1fae7 => true,
+ 0x1fae8 => true,
+ 0x1faf0...0x1faf6 => true,
+ 0x1faf7...0x1faf8 => true,
+ else => false,
+ };
+}
+
+pub fn isEmojiPresentation(cp: u21) bool {
+ if (cp < 0x231a or cp > 0x1faf8) return false;
+
+ return switch (cp) {
+ 0x231a...0x231b => true,
+ 0x23e9...0x23ec => true,
+ 0x23f0 => true,
+ 0x23f3 => true,
+ 0x25fd...0x25fe => true,
+ 0x2614...0x2615 => true,
+ 0x2648...0x2653 => true,
+ 0x267f => true,
+ 0x2693 => true,
+ 0x26a1 => true,
+ 0x26aa...0x26ab => true,
+ 0x26bd...0x26be => true,
+ 0x26c4...0x26c5 => true,
+ 0x26ce => true,
+ 0x26d4 => true,
+ 0x26ea => true,
+ 0x26f2...0x26f3 => true,
+ 0x26f5 => true,
+ 0x26fa => true,
+ 0x26fd => true,
+ 0x2705 => true,
+ 0x270a...0x270b => true,
+ 0x2728 => true,
+ 0x274c => true,
+ 0x274e => true,
+ 0x2753...0x2755 => true,
+ 0x2757 => true,
+ 0x2795...0x2797 => true,
+ 0x27b0 => true,
+ 0x27bf => true,
+ 0x2b1b...0x2b1c => true,
+ 0x2b50 => true,
+ 0x2b55 => true,
+ 0x1f004 => true,
+ 0x1f0cf => true,
+ 0x1f18e => true,
+ 0x1f191...0x1f19a => true,
+ 0x1f1e6...0x1f1ff => true,
+ 0x1f201 => true,
+ 0x1f21a => true,
+ 0x1f22f => true,
+ 0x1f232...0x1f236 => true,
+ 0x1f238...0x1f23a => true,
+ 0x1f250...0x1f251 => true,
+ 0x1f300...0x1f30c => true,
+ 0x1f30d...0x1f30e => true,
+ 0x1f30f => true,
+ 0x1f310 => true,
+ 0x1f311 => true,
+ 0x1f312 => true,
+ 0x1f313...0x1f315 => true,
+ 0x1f316...0x1f318 => true,
+ 0x1f319 => true,
+ 0x1f31a => true,
+ 0x1f31b => true,
+ 0x1f31c => true,
+ 0x1f31d...0x1f31e => true,
+ 0x1f31f...0x1f320 => true,
+ 0x1f32d...0x1f32f => true,
+ 0x1f330...0x1f331 => true,
+ 0x1f332...0x1f333 => true,
+ 0x1f334...0x1f335 => true,
+ 0x1f337...0x1f34a => true,
+ 0x1f34b => true,
+ 0x1f34c...0x1f34f => true,
+ 0x1f350 => true,
+ 0x1f351...0x1f37b => true,
+ 0x1f37c => true,
+ 0x1f37e...0x1f37f => true,
+ 0x1f380...0x1f393 => true,
+ 0x1f3a0...0x1f3c4 => true,
+ 0x1f3c5 => true,
+ 0x1f3c6 => true,
+ 0x1f3c7 => true,
+ 0x1f3c8 => true,
+ 0x1f3c9 => true,
+ 0x1f3ca => true,
+ 0x1f3cf...0x1f3d3 => true,
+ 0x1f3e0...0x1f3e3 => true,
+ 0x1f3e4 => true,
+ 0x1f3e5...0x1f3f0 => true,
+ 0x1f3f4 => true,
+ 0x1f3f8...0x1f407 => true,
+ 0x1f408 => true,
+ 0x1f409...0x1f40b => true,
+ 0x1f40c...0x1f40e => true,
+ 0x1f40f...0x1f410 => true,
+ 0x1f411...0x1f412 => true,
+ 0x1f413 => true,
+ 0x1f414 => true,
+ 0x1f415 => true,
+ 0x1f416 => true,
+ 0x1f417...0x1f429 => true,
+ 0x1f42a => true,
+ 0x1f42b...0x1f43e => true,
+ 0x1f440 => true,
+ 0x1f442...0x1f464 => true,
+ 0x1f465 => true,
+ 0x1f466...0x1f46b => true,
+ 0x1f46c...0x1f46d => true,
+ 0x1f46e...0x1f4ac => true,
+ 0x1f4ad => true,
+ 0x1f4ae...0x1f4b5 => true,
+ 0x1f4b6...0x1f4b7 => true,
+ 0x1f4b8...0x1f4eb => true,
+ 0x1f4ec...0x1f4ed => true,
+ 0x1f4ee => true,
+ 0x1f4ef => true,
+ 0x1f4f0...0x1f4f4 => true,
+ 0x1f4f5 => true,
+ 0x1f4f6...0x1f4f7 => true,
+ 0x1f4f8 => true,
+ 0x1f4f9...0x1f4fc => true,
+ 0x1f4ff...0x1f502 => true,
+ 0x1f503 => true,
+ 0x1f504...0x1f507 => true,
+ 0x1f508 => true,
+ 0x1f509 => true,
+ 0x1f50a...0x1f514 => true,
+ 0x1f515 => true,
+ 0x1f516...0x1f52b => true,
+ 0x1f52c...0x1f52d => true,
+ 0x1f52e...0x1f53d => true,
+ 0x1f54b...0x1f54e => true,
+ 0x1f550...0x1f55b => true,
+ 0x1f55c...0x1f567 => true,
+ 0x1f57a => true,
+ 0x1f595...0x1f596 => true,
+ 0x1f5a4 => true,
+ 0x1f5fb...0x1f5ff => true,
+ 0x1f600 => true,
+ 0x1f601...0x1f606 => true,
+ 0x1f607...0x1f608 => true,
+ 0x1f609...0x1f60d => true,
+ 0x1f60e => true,
+ 0x1f60f => true,
+ 0x1f610 => true,
+ 0x1f611 => true,
+ 0x1f612...0x1f614 => true,
+ 0x1f615 => true,
+ 0x1f616 => true,
+ 0x1f617 => true,
+ 0x1f618 => true,
+ 0x1f619 => true,
+ 0x1f61a => true,
+ 0x1f61b => true,
+ 0x1f61c...0x1f61e => true,
+ 0x1f61f => true,
+ 0x1f620...0x1f625 => true,
+ 0x1f626...0x1f627 => true,
+ 0x1f628...0x1f62b => true,
+ 0x1f62c => true,
+ 0x1f62d => true,
+ 0x1f62e...0x1f62f => true,
+ 0x1f630...0x1f633 => true,
+ 0x1f634 => true,
+ 0x1f635 => true,
+ 0x1f636 => true,
+ 0x1f637...0x1f640 => true,
+ 0x1f641...0x1f644 => true,
+ 0x1f645...0x1f64f => true,
+ 0x1f680 => true,
+ 0x1f681...0x1f682 => true,
+ 0x1f683...0x1f685 => true,
+ 0x1f686 => true,
+ 0x1f687 => true,
+ 0x1f688 => true,
+ 0x1f689 => true,
+ 0x1f68a...0x1f68b => true,
+ 0x1f68c => true,
+ 0x1f68d => true,
+ 0x1f68e => true,
+ 0x1f68f => true,
+ 0x1f690 => true,
+ 0x1f691...0x1f693 => true,
+ 0x1f694 => true,
+ 0x1f695 => true,
+ 0x1f696 => true,
+ 0x1f697 => true,
+ 0x1f698 => true,
+ 0x1f699...0x1f69a => true,
+ 0x1f69b...0x1f6a1 => true,
+ 0x1f6a2 => true,
+ 0x1f6a3 => true,
+ 0x1f6a4...0x1f6a5 => true,
+ 0x1f6a6 => true,
+ 0x1f6a7...0x1f6ad => true,
+ 0x1f6ae...0x1f6b1 => true,
+ 0x1f6b2 => true,
+ 0x1f6b3...0x1f6b5 => true,
+ 0x1f6b6 => true,
+ 0x1f6b7...0x1f6b8 => true,
+ 0x1f6b9...0x1f6be => true,
+ 0x1f6bf => true,
+ 0x1f6c0 => true,
+ 0x1f6c1...0x1f6c5 => true,
+ 0x1f6cc => true,
+ 0x1f6d0 => true,
+ 0x1f6d1...0x1f6d2 => true,
+ 0x1f6d5 => true,
+ 0x1f6d6...0x1f6d7 => true,
+ 0x1f6dc => true,
+ 0x1f6dd...0x1f6df => true,
+ 0x1f6eb...0x1f6ec => true,
+ 0x1f6f4...0x1f6f6 => true,
+ 0x1f6f7...0x1f6f8 => true,
+ 0x1f6f9 => true,
+ 0x1f6fa => true,
+ 0x1f6fb...0x1f6fc => true,
+ 0x1f7e0...0x1f7eb => true,
+ 0x1f7f0 => true,
+ 0x1f90c => true,
+ 0x1f90d...0x1f90f => true,
+ 0x1f910...0x1f918 => true,
+ 0x1f919...0x1f91e => true,
+ 0x1f91f => true,
+ 0x1f920...0x1f927 => true,
+ 0x1f928...0x1f92f => true,
+ 0x1f930 => true,
+ 0x1f931...0x1f932 => true,
+ 0x1f933...0x1f93a => true,
+ 0x1f93c...0x1f93e => true,
+ 0x1f93f => true,
+ 0x1f940...0x1f945 => true,
+ 0x1f947...0x1f94b => true,
+ 0x1f94c => true,
+ 0x1f94d...0x1f94f => true,
+ 0x1f950...0x1f95e => true,
+ 0x1f95f...0x1f96b => true,
+ 0x1f96c...0x1f970 => true,
+ 0x1f971 => true,
+ 0x1f972 => true,
+ 0x1f973...0x1f976 => true,
+ 0x1f977...0x1f978 => true,
+ 0x1f979 => true,
+ 0x1f97a => true,
+ 0x1f97b => true,
+ 0x1f97c...0x1f97f => true,
+ 0x1f980...0x1f984 => true,
+ 0x1f985...0x1f991 => true,
+ 0x1f992...0x1f997 => true,
+ 0x1f998...0x1f9a2 => true,
+ 0x1f9a3...0x1f9a4 => true,
+ 0x1f9a5...0x1f9aa => true,
+ 0x1f9ab...0x1f9ad => true,
+ 0x1f9ae...0x1f9af => true,
+ 0x1f9b0...0x1f9b9 => true,
+ 0x1f9ba...0x1f9bf => true,
+ 0x1f9c0 => true,
+ 0x1f9c1...0x1f9c2 => true,
+ 0x1f9c3...0x1f9ca => true,
+ 0x1f9cb => true,
+ 0x1f9cc => true,
+ 0x1f9cd...0x1f9cf => true,
+ 0x1f9d0...0x1f9e6 => true,
+ 0x1f9e7...0x1f9ff => true,
+ 0x1fa70...0x1fa73 => true,
+ 0x1fa74 => true,
+ 0x1fa75...0x1fa77 => true,
+ 0x1fa78...0x1fa7a => true,
+ 0x1fa7b...0x1fa7c => true,
+ 0x1fa80...0x1fa82 => true,
+ 0x1fa83...0x1fa86 => true,
+ 0x1fa87...0x1fa88 => true,
+ 0x1fa90...0x1fa95 => true,
+ 0x1fa96...0x1faa8 => true,
+ 0x1faa9...0x1faac => true,
+ 0x1faad...0x1faaf => true,
+ 0x1fab0...0x1fab6 => true,
+ 0x1fab7...0x1faba => true,
+ 0x1fabb...0x1fabd => true,
+ 0x1fabf => true,
+ 0x1fac0...0x1fac2 => true,
+ 0x1fac3...0x1fac5 => true,
+ 0x1face...0x1facf => true,
+ 0x1fad0...0x1fad6 => true,
+ 0x1fad7...0x1fad9 => true,
+ 0x1fada...0x1fadb => true,
+ 0x1fae0...0x1fae7 => true,
+ 0x1fae8 => true,
+ 0x1faf0...0x1faf6 => true,
+ 0x1faf7...0x1faf8 => true,
+ else => false,
+ };
+}
+
+pub fn isEmojiModifier(cp: u21) bool {
+ if (cp < 0x1f3fb or cp > 0x1f3ff) return false;
+
+ return switch (cp) {
+ 0x1f3fb...0x1f3ff => true,
+ else => false,
+ };
+}
+
+pub fn isEmojiModifierBase(cp: u21) bool {
+ if (cp < 0x261d or cp > 0x1faf8) return false;
+
+ return switch (cp) {
+ 0x261d => true,
+ 0x26f9 => true,
+ 0x270a...0x270c => true,
+ 0x270d => true,
+ 0x1f385 => true,
+ 0x1f3c2...0x1f3c4 => true,
+ 0x1f3c7 => true,
+ 0x1f3ca => true,
+ 0x1f3cb...0x1f3cc => true,
+ 0x1f442...0x1f443 => true,
+ 0x1f446...0x1f450 => true,
+ 0x1f466...0x1f46b => true,
+ 0x1f46c...0x1f46d => true,
+ 0x1f46e...0x1f478 => true,
+ 0x1f47c => true,
+ 0x1f481...0x1f483 => true,
+ 0x1f485...0x1f487 => true,
+ 0x1f48f => true,
+ 0x1f491 => true,
+ 0x1f4aa => true,
+ 0x1f574...0x1f575 => true,
+ 0x1f57a => true,
+ 0x1f590 => true,
+ 0x1f595...0x1f596 => true,
+ 0x1f645...0x1f647 => true,
+ 0x1f64b...0x1f64f => true,
+ 0x1f6a3 => true,
+ 0x1f6b4...0x1f6b5 => true,
+ 0x1f6b6 => true,
+ 0x1f6c0 => true,
+ 0x1f6cc => true,
+ 0x1f90c => true,
+ 0x1f90f => true,
+ 0x1f918 => true,
+ 0x1f919...0x1f91e => true,
+ 0x1f91f => true,
+ 0x1f926 => true,
+ 0x1f930 => true,
+ 0x1f931...0x1f932 => true,
+ 0x1f933...0x1f939 => true,
+ 0x1f93c...0x1f93e => true,
+ 0x1f977 => true,
+ 0x1f9b5...0x1f9b6 => true,
+ 0x1f9b8...0x1f9b9 => true,
+ 0x1f9bb => true,
+ 0x1f9cd...0x1f9cf => true,
+ 0x1f9d1...0x1f9dd => true,
+ 0x1fac3...0x1fac5 => true,
+ 0x1faf0...0x1faf6 => true,
+ 0x1faf7...0x1faf8 => true,
+ else => false,
+ };
+}
+
+pub fn isEmojiComponent(cp: u21) bool {
+ if (cp < 0x23 or cp > 0xe007f) return false;
+
+ return switch (cp) {
+ 0x23 => true,
+ 0x2a => true,
+ 0x30...0x39 => true,
+ 0x200d => true,
+ 0x20e3 => true,
+ 0xfe0f => true,
+ 0x1f1e6...0x1f1ff => true,
+ 0x1f3fb...0x1f3ff => true,
+ 0x1f9b0...0x1f9b3 => true,
+ 0xe0020...0xe007f => true,
+ else => false,
+ };
+}
+
+pub fn isExtendedPictographic(cp: u21) bool {
+ if (cp < 0xa9 or cp > 0x1fffd) return false;
+
+ return switch (cp) {
+ 0xa9 => true,
+ 0xae => true,
+ 0x203c => true,
+ 0x2049 => true,
+ 0x2122 => true,
+ 0x2139 => true,
+ 0x2194...0x2199 => true,
+ 0x21a9...0x21aa => true,
+ 0x231a...0x231b => true,
+ 0x2328 => true,
+ 0x2388 => true,
+ 0x23cf => true,
+ 0x23e9...0x23ec => true,
+ 0x23ed...0x23ee => true,
+ 0x23ef => true,
+ 0x23f0 => true,
+ 0x23f1...0x23f2 => true,
+ 0x23f3 => true,
+ 0x23f8...0x23fa => true,
+ 0x24c2 => true,
+ 0x25aa...0x25ab => true,
+ 0x25b6 => true,
+ 0x25c0 => true,
+ 0x25fb...0x25fe => true,
+ 0x2600...0x2601 => true,
+ 0x2602...0x2603 => true,
+ 0x2604 => true,
+ 0x2605 => true,
+ 0x2607...0x260d => true,
+ 0x260e => true,
+ 0x260f...0x2610 => true,
+ 0x2611 => true,
+ 0x2612 => true,
+ 0x2614...0x2615 => true,
+ 0x2616...0x2617 => true,
+ 0x2618 => true,
+ 0x2619...0x261c => true,
+ 0x261d => true,
+ 0x261e...0x261f => true,
+ 0x2620 => true,
+ 0x2621 => true,
+ 0x2622...0x2623 => true,
+ 0x2624...0x2625 => true,
+ 0x2626 => true,
+ 0x2627...0x2629 => true,
+ 0x262a => true,
+ 0x262b...0x262d => true,
+ 0x262e => true,
+ 0x262f => true,
+ 0x2630...0x2637 => true,
+ 0x2638...0x2639 => true,
+ 0x263a => true,
+ 0x263b...0x263f => true,
+ 0x2640 => true,
+ 0x2641 => true,
+ 0x2642 => true,
+ 0x2643...0x2647 => true,
+ 0x2648...0x2653 => true,
+ 0x2654...0x265e => true,
+ 0x265f => true,
+ 0x2660 => true,
+ 0x2661...0x2662 => true,
+ 0x2663 => true,
+ 0x2664 => true,
+ 0x2665...0x2666 => true,
+ 0x2667 => true,
+ 0x2668 => true,
+ 0x2669...0x267a => true,
+ 0x267b => true,
+ 0x267c...0x267d => true,
+ 0x267e => true,
+ 0x267f => true,
+ 0x2680...0x2685 => true,
+ 0x2690...0x2691 => true,
+ 0x2692 => true,
+ 0x2693 => true,
+ 0x2694 => true,
+ 0x2695 => true,
+ 0x2696...0x2697 => true,
+ 0x2698 => true,
+ 0x2699 => true,
+ 0x269a => true,
+ 0x269b...0x269c => true,
+ 0x269d...0x269f => true,
+ 0x26a0...0x26a1 => true,
+ 0x26a2...0x26a6 => true,
+ 0x26a7 => true,
+ 0x26a8...0x26a9 => true,
+ 0x26aa...0x26ab => true,
+ 0x26ac...0x26af => true,
+ 0x26b0...0x26b1 => true,
+ 0x26b2...0x26bc => true,
+ 0x26bd...0x26be => true,
+ 0x26bf...0x26c3 => true,
+ 0x26c4...0x26c5 => true,
+ 0x26c6...0x26c7 => true,
+ 0x26c8 => true,
+ 0x26c9...0x26cd => true,
+ 0x26ce => true,
+ 0x26cf => true,
+ 0x26d0 => true,
+ 0x26d1 => true,
+ 0x26d2 => true,
+ 0x26d3 => true,
+ 0x26d4 => true,
+ 0x26d5...0x26e8 => true,
+ 0x26e9 => true,
+ 0x26ea => true,
+ 0x26eb...0x26ef => true,
+ 0x26f0...0x26f1 => true,
+ 0x26f2...0x26f3 => true,
+ 0x26f4 => true,
+ 0x26f5 => true,
+ 0x26f6 => true,
+ 0x26f7...0x26f9 => true,
+ 0x26fa => true,
+ 0x26fb...0x26fc => true,
+ 0x26fd => true,
+ 0x26fe...0x2701 => true,
+ 0x2702 => true,
+ 0x2703...0x2704 => true,
+ 0x2705 => true,
+ 0x2708...0x270c => true,
+ 0x270d => true,
+ 0x270e => true,
+ 0x270f => true,
+ 0x2710...0x2711 => true,
+ 0x2712 => true,
+ 0x2714 => true,
+ 0x2716 => true,
+ 0x271d => true,
+ 0x2721 => true,
+ 0x2728 => true,
+ 0x2733...0x2734 => true,
+ 0x2744 => true,
+ 0x2747 => true,
+ 0x274c => true,
+ 0x274e => true,
+ 0x2753...0x2755 => true,
+ 0x2757 => true,
+ 0x2763 => true,
+ 0x2764 => true,
+ 0x2765...0x2767 => true,
+ 0x2795...0x2797 => true,
+ 0x27a1 => true,
+ 0x27b0 => true,
+ 0x27bf => true,
+ 0x2934...0x2935 => true,
+ 0x2b05...0x2b07 => true,
+ 0x2b1b...0x2b1c => true,
+ 0x2b50 => true,
+ 0x2b55 => true,
+ 0x3030 => true,
+ 0x303d => true,
+ 0x3297 => true,
+ 0x3299 => true,
+ 0x1f000...0x1f003 => true,
+ 0x1f004 => true,
+ 0x1f005...0x1f0ce => true,
+ 0x1f0cf => true,
+ 0x1f0d0...0x1f0ff => true,
+ 0x1f10d...0x1f10f => true,
+ 0x1f12f => true,
+ 0x1f16c...0x1f16f => true,
+ 0x1f170...0x1f171 => true,
+ 0x1f17e...0x1f17f => true,
+ 0x1f18e => true,
+ 0x1f191...0x1f19a => true,
+ 0x1f1ad...0x1f1e5 => true,
+ 0x1f201...0x1f202 => true,
+ 0x1f203...0x1f20f => true,
+ 0x1f21a => true,
+ 0x1f22f => true,
+ 0x1f232...0x1f23a => true,
+ 0x1f23c...0x1f23f => true,
+ 0x1f249...0x1f24f => true,
+ 0x1f250...0x1f251 => true,
+ 0x1f252...0x1f2ff => true,
+ 0x1f300...0x1f30c => true,
+ 0x1f30d...0x1f30e => true,
+ 0x1f30f => true,
+ 0x1f310 => true,
+ 0x1f311 => true,
+ 0x1f312 => true,
+ 0x1f313...0x1f315 => true,
+ 0x1f316...0x1f318 => true,
+ 0x1f319 => true,
+ 0x1f31a => true,
+ 0x1f31b => true,
+ 0x1f31c => true,
+ 0x1f31d...0x1f31e => true,
+ 0x1f31f...0x1f320 => true,
+ 0x1f321 => true,
+ 0x1f322...0x1f323 => true,
+ 0x1f324...0x1f32c => true,
+ 0x1f32d...0x1f32f => true,
+ 0x1f330...0x1f331 => true,
+ 0x1f332...0x1f333 => true,
+ 0x1f334...0x1f335 => true,
+ 0x1f336 => true,
+ 0x1f337...0x1f34a => true,
+ 0x1f34b => true,
+ 0x1f34c...0x1f34f => true,
+ 0x1f350 => true,
+ 0x1f351...0x1f37b => true,
+ 0x1f37c => true,
+ 0x1f37d => true,
+ 0x1f37e...0x1f37f => true,
+ 0x1f380...0x1f393 => true,
+ 0x1f394...0x1f395 => true,
+ 0x1f396...0x1f397 => true,
+ 0x1f398 => true,
+ 0x1f399...0x1f39b => true,
+ 0x1f39c...0x1f39d => true,
+ 0x1f39e...0x1f39f => true,
+ 0x1f3a0...0x1f3c4 => true,
+ 0x1f3c5 => true,
+ 0x1f3c6 => true,
+ 0x1f3c7 => true,
+ 0x1f3c8 => true,
+ 0x1f3c9 => true,
+ 0x1f3ca => true,
+ 0x1f3cb...0x1f3ce => true,
+ 0x1f3cf...0x1f3d3 => true,
+ 0x1f3d4...0x1f3df => true,
+ 0x1f3e0...0x1f3e3 => true,
+ 0x1f3e4 => true,
+ 0x1f3e5...0x1f3f0 => true,
+ 0x1f3f1...0x1f3f2 => true,
+ 0x1f3f3 => true,
+ 0x1f3f4 => true,
+ 0x1f3f5 => true,
+ 0x1f3f6 => true,
+ 0x1f3f7 => true,
+ 0x1f3f8...0x1f3fa => true,
+ 0x1f400...0x1f407 => true,
+ 0x1f408 => true,
+ 0x1f409...0x1f40b => true,
+ 0x1f40c...0x1f40e => true,
+ 0x1f40f...0x1f410 => true,
+ 0x1f411...0x1f412 => true,
+ 0x1f413 => true,
+ 0x1f414 => true,
+ 0x1f415 => true,
+ 0x1f416 => true,
+ 0x1f417...0x1f429 => true,
+ 0x1f42a => true,
+ 0x1f42b...0x1f43e => true,
+ 0x1f43f => true,
+ 0x1f440 => true,
+ 0x1f441 => true,
+ 0x1f442...0x1f464 => true,
+ 0x1f465 => true,
+ 0x1f466...0x1f46b => true,
+ 0x1f46c...0x1f46d => true,
+ 0x1f46e...0x1f4ac => true,
+ 0x1f4ad => true,
+ 0x1f4ae...0x1f4b5 => true,
+ 0x1f4b6...0x1f4b7 => true,
+ 0x1f4b8...0x1f4eb => true,
+ 0x1f4ec...0x1f4ed => true,
+ 0x1f4ee => true,
+ 0x1f4ef => true,
+ 0x1f4f0...0x1f4f4 => true,
+ 0x1f4f5 => true,
+ 0x1f4f6...0x1f4f7 => true,
+ 0x1f4f8 => true,
+ 0x1f4f9...0x1f4fc => true,
+ 0x1f4fd => true,
+ 0x1f4fe => true,
+ 0x1f4ff...0x1f502 => true,
+ 0x1f503 => true,
+ 0x1f504...0x1f507 => true,
+ 0x1f508 => true,
+ 0x1f509 => true,
+ 0x1f50a...0x1f514 => true,
+ 0x1f515 => true,
+ 0x1f516...0x1f52b => true,
+ 0x1f52c...0x1f52d => true,
+ 0x1f52e...0x1f53d => true,
+ 0x1f546...0x1f548 => true,
+ 0x1f549...0x1f54a => true,
+ 0x1f54b...0x1f54e => true,
+ 0x1f54f => true,
+ 0x1f550...0x1f55b => true,
+ 0x1f55c...0x1f567 => true,
+ 0x1f568...0x1f56e => true,
+ 0x1f56f...0x1f570 => true,
+ 0x1f571...0x1f572 => true,
+ 0x1f573...0x1f579 => true,
+ 0x1f57a => true,
+ 0x1f57b...0x1f586 => true,
+ 0x1f587 => true,
+ 0x1f588...0x1f589 => true,
+ 0x1f58a...0x1f58d => true,
+ 0x1f58e...0x1f58f => true,
+ 0x1f590 => true,
+ 0x1f591...0x1f594 => true,
+ 0x1f595...0x1f596 => true,
+ 0x1f597...0x1f5a3 => true,
+ 0x1f5a4 => true,
+ 0x1f5a5 => true,
+ 0x1f5a6...0x1f5a7 => true,
+ 0x1f5a8 => true,
+ 0x1f5a9...0x1f5b0 => true,
+ 0x1f5b1...0x1f5b2 => true,
+ 0x1f5b3...0x1f5bb => true,
+ 0x1f5bc => true,
+ 0x1f5bd...0x1f5c1 => true,
+ 0x1f5c2...0x1f5c4 => true,
+ 0x1f5c5...0x1f5d0 => true,
+ 0x1f5d1...0x1f5d3 => true,
+ 0x1f5d4...0x1f5db => true,
+ 0x1f5dc...0x1f5de => true,
+ 0x1f5df...0x1f5e0 => true,
+ 0x1f5e1 => true,
+ 0x1f5e2 => true,
+ 0x1f5e3 => true,
+ 0x1f5e4...0x1f5e7 => true,
+ 0x1f5e8 => true,
+ 0x1f5e9...0x1f5ee => true,
+ 0x1f5ef => true,
+ 0x1f5f0...0x1f5f2 => true,
+ 0x1f5f3 => true,
+ 0x1f5f4...0x1f5f9 => true,
+ 0x1f5fa => true,
+ 0x1f5fb...0x1f5ff => true,
+ 0x1f600 => true,
+ 0x1f601...0x1f606 => true,
+ 0x1f607...0x1f608 => true,
+ 0x1f609...0x1f60d => true,
+ 0x1f60e => true,
+ 0x1f60f => true,
+ 0x1f610 => true,
+ 0x1f611 => true,
+ 0x1f612...0x1f614 => true,
+ 0x1f615 => true,
+ 0x1f616 => true,
+ 0x1f617 => true,
+ 0x1f618 => true,
+ 0x1f619 => true,
+ 0x1f61a => true,
+ 0x1f61b => true,
+ 0x1f61c...0x1f61e => true,
+ 0x1f61f => true,
+ 0x1f620...0x1f625 => true,
+ 0x1f626...0x1f627 => true,
+ 0x1f628...0x1f62b => true,
+ 0x1f62c => true,
+ 0x1f62d => true,
+ 0x1f62e...0x1f62f => true,
+ 0x1f630...0x1f633 => true,
+ 0x1f634 => true,
+ 0x1f635 => true,
+ 0x1f636 => true,
+ 0x1f637...0x1f640 => true,
+ 0x1f641...0x1f644 => true,
+ 0x1f645...0x1f64f => true,
+ 0x1f680 => true,
+ 0x1f681...0x1f682 => true,
+ 0x1f683...0x1f685 => true,
+ 0x1f686 => true,
+ 0x1f687 => true,
+ 0x1f688 => true,
+ 0x1f689 => true,
+ 0x1f68a...0x1f68b => true,
+ 0x1f68c => true,
+ 0x1f68d => true,
+ 0x1f68e => true,
+ 0x1f68f => true,
+ 0x1f690 => true,
+ 0x1f691...0x1f693 => true,
+ 0x1f694 => true,
+ 0x1f695 => true,
+ 0x1f696 => true,
+ 0x1f697 => true,
+ 0x1f698 => true,
+ 0x1f699...0x1f69a => true,
+ 0x1f69b...0x1f6a1 => true,
+ 0x1f6a2 => true,
+ 0x1f6a3 => true,
+ 0x1f6a4...0x1f6a5 => true,
+ 0x1f6a6 => true,
+ 0x1f6a7...0x1f6ad => true,
+ 0x1f6ae...0x1f6b1 => true,
+ 0x1f6b2 => true,
+ 0x1f6b3...0x1f6b5 => true,
+ 0x1f6b6 => true,
+ 0x1f6b7...0x1f6b8 => true,
+ 0x1f6b9...0x1f6be => true,
+ 0x1f6bf => true,
+ 0x1f6c0 => true,
+ 0x1f6c1...0x1f6c5 => true,
+ 0x1f6c6...0x1f6ca => true,
+ 0x1f6cb => true,
+ 0x1f6cc => true,
+ 0x1f6cd...0x1f6cf => true,
+ 0x1f6d0 => true,
+ 0x1f6d1...0x1f6d2 => true,
+ 0x1f6d3...0x1f6d4 => true,
+ 0x1f6d5 => true,
+ 0x1f6d6...0x1f6d7 => true,
+ 0x1f6d8...0x1f6db => true,
+ 0x1f6dc => true,
+ 0x1f6dd...0x1f6df => true,
+ 0x1f6e0...0x1f6e5 => true,
+ 0x1f6e6...0x1f6e8 => true,
+ 0x1f6e9 => true,
+ 0x1f6ea => true,
+ 0x1f6eb...0x1f6ec => true,
+ 0x1f6ed...0x1f6ef => true,
+ 0x1f6f0 => true,
+ 0x1f6f1...0x1f6f2 => true,
+ 0x1f6f3 => true,
+ 0x1f6f4...0x1f6f6 => true,
+ 0x1f6f7...0x1f6f8 => true,
+ 0x1f6f9 => true,
+ 0x1f6fa => true,
+ 0x1f6fb...0x1f6fc => true,
+ 0x1f6fd...0x1f6ff => true,
+ 0x1f774...0x1f77f => true,
+ 0x1f7d5...0x1f7df => true,
+ 0x1f7e0...0x1f7eb => true,
+ 0x1f7ec...0x1f7ef => true,
+ 0x1f7f0 => true,
+ 0x1f7f1...0x1f7ff => true,
+ 0x1f80c...0x1f80f => true,
+ 0x1f848...0x1f84f => true,
+ 0x1f85a...0x1f85f => true,
+ 0x1f888...0x1f88f => true,
+ 0x1f8ae...0x1f8ff => true,
+ 0x1f90c => true,
+ 0x1f90d...0x1f90f => true,
+ 0x1f910...0x1f918 => true,
+ 0x1f919...0x1f91e => true,
+ 0x1f91f => true,
+ 0x1f920...0x1f927 => true,
+ 0x1f928...0x1f92f => true,
+ 0x1f930 => true,
+ 0x1f931...0x1f932 => true,
+ 0x1f933...0x1f93a => true,
+ 0x1f93c...0x1f93e => true,
+ 0x1f93f => true,
+ 0x1f940...0x1f945 => true,
+ 0x1f947...0x1f94b => true,
+ 0x1f94c => true,
+ 0x1f94d...0x1f94f => true,
+ 0x1f950...0x1f95e => true,
+ 0x1f95f...0x1f96b => true,
+ 0x1f96c...0x1f970 => true,
+ 0x1f971 => true,
+ 0x1f972 => true,
+ 0x1f973...0x1f976 => true,
+ 0x1f977...0x1f978 => true,
+ 0x1f979 => true,
+ 0x1f97a => true,
+ 0x1f97b => true,
+ 0x1f97c...0x1f97f => true,
+ 0x1f980...0x1f984 => true,
+ 0x1f985...0x1f991 => true,
+ 0x1f992...0x1f997 => true,
+ 0x1f998...0x1f9a2 => true,
+ 0x1f9a3...0x1f9a4 => true,
+ 0x1f9a5...0x1f9aa => true,
+ 0x1f9ab...0x1f9ad => true,
+ 0x1f9ae...0x1f9af => true,
+ 0x1f9b0...0x1f9b9 => true,
+ 0x1f9ba...0x1f9bf => true,
+ 0x1f9c0 => true,
+ 0x1f9c1...0x1f9c2 => true,
+ 0x1f9c3...0x1f9ca => true,
+ 0x1f9cb => true,
+ 0x1f9cc => true,
+ 0x1f9cd...0x1f9cf => true,
+ 0x1f9d0...0x1f9e6 => true,
+ 0x1f9e7...0x1f9ff => true,
+ 0x1fa00...0x1fa6f => true,
+ 0x1fa70...0x1fa73 => true,
+ 0x1fa74 => true,
+ 0x1fa75...0x1fa77 => true,
+ 0x1fa78...0x1fa7a => true,
+ 0x1fa7b...0x1fa7c => true,
+ 0x1fa7d...0x1fa7f => true,
+ 0x1fa80...0x1fa82 => true,
+ 0x1fa83...0x1fa86 => true,
+ 0x1fa87...0x1fa88 => true,
+ 0x1fa89...0x1fa8f => true,
+ 0x1fa90...0x1fa95 => true,
+ 0x1fa96...0x1faa8 => true,
+ 0x1faa9...0x1faac => true,
+ 0x1faad...0x1faaf => true,
+ 0x1fab0...0x1fab6 => true,
+ 0x1fab7...0x1faba => true,
+ 0x1fabb...0x1fabd => true,
+ 0x1fabe => true,
+ 0x1fabf => true,
+ 0x1fac0...0x1fac2 => true,
+ 0x1fac3...0x1fac5 => true,
+ 0x1fac6...0x1facd => true,
+ 0x1face...0x1facf => true,
+ 0x1fad0...0x1fad6 => true,
+ 0x1fad7...0x1fad9 => true,
+ 0x1fada...0x1fadb => true,
+ 0x1fadc...0x1fadf => true,
+ 0x1fae0...0x1fae7 => true,
+ 0x1fae8 => true,
+ 0x1fae9...0x1faef => true,
+ 0x1faf0...0x1faf6 => true,
+ 0x1faf7...0x1faf8 => true,
+ 0x1faf9...0x1faff => true,
+ 0x1fc00...0x1fffd => true,
+ else => false,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/grapheme_break_property.zig.html b/docs/src/ziglyph/autogen/grapheme_break_property.zig.html
new file mode 100644
index 0000000..08878ff
--- /dev/null
+++ b/docs/src/ziglyph/autogen/grapheme_break_property.zig.html
@@ -0,0 +1,1599 @@
+
+
+
+
+
autogen/grapheme_break_property.zig - source view
+
+
+
+
+
+
+
+
+pub fn isPrepend(cp: u21) bool {
+ if (cp < 0x600 or cp > 0x11f02) return false;
+
+ return switch (cp) {
+ 0x600...0x605 => true,
+ 0x6dd => true,
+ 0x70f => true,
+ 0x890...0x891 => true,
+ 0x8e2 => true,
+ 0xd4e => true,
+ 0x110bd => true,
+ 0x110cd => true,
+ 0x111c2...0x111c3 => true,
+ 0x1193f => true,
+ 0x11941 => true,
+ 0x11a3a => true,
+ 0x11a84...0x11a89 => true,
+ 0x11d46 => true,
+ 0x11f02 => true,
+ else => false,
+ };
+}
+
+pub fn isCr(cp: u21) bool {
+ return cp == 0xd;
+}
+
+pub fn isLf(cp: u21) bool {
+ return cp == 0xa;
+}
+
+pub fn isControl(cp: u21) bool {
+ if (cp > 0xe0fff) return false;
+
+ return switch (cp) {
+ 0x0...0x9 => true,
+ 0xb...0xc => true,
+ 0xe...0x1f => true,
+ 0x7f...0x9f => true,
+ 0xad => true,
+ 0x61c => true,
+ 0x180e => true,
+ 0x200b => true,
+ 0x200e...0x200f => true,
+ 0x2028 => true,
+ 0x2029 => true,
+ 0x202a...0x202e => true,
+ 0x2060...0x2064 => true,
+ 0x2065 => true,
+ 0x2066...0x206f => true,
+ 0xfeff => true,
+ 0xfff0...0xfff8 => true,
+ 0xfff9...0xfffb => true,
+ 0x13430...0x1343f => true,
+ 0x1bca0...0x1bca3 => true,
+ 0x1d173...0x1d17a => true,
+ 0xe0000 => true,
+ 0xe0001 => true,
+ 0xe0002...0xe001f => true,
+ 0xe0080...0xe00ff => true,
+ 0xe01f0...0xe0fff => true,
+ else => false,
+ };
+}
+
+pub fn isExtend(cp: u21) bool {
+ if (cp < 0x300 or cp > 0xe01ef) return false;
+
+ return switch (cp) {
+ 0x300...0x36f => true,
+ 0x483...0x487 => true,
+ 0x488...0x489 => true,
+ 0x591...0x5bd => true,
+ 0x5bf => true,
+ 0x5c1...0x5c2 => true,
+ 0x5c4...0x5c5 => true,
+ 0x5c7 => true,
+ 0x610...0x61a => true,
+ 0x64b...0x65f => true,
+ 0x670 => true,
+ 0x6d6...0x6dc => true,
+ 0x6df...0x6e4 => true,
+ 0x6e7...0x6e8 => true,
+ 0x6ea...0x6ed => true,
+ 0x711 => true,
+ 0x730...0x74a => true,
+ 0x7a6...0x7b0 => true,
+ 0x7eb...0x7f3 => true,
+ 0x7fd => true,
+ 0x816...0x819 => true,
+ 0x81b...0x823 => true,
+ 0x825...0x827 => true,
+ 0x829...0x82d => true,
+ 0x859...0x85b => true,
+ 0x898...0x89f => true,
+ 0x8ca...0x8e1 => true,
+ 0x8e3...0x902 => true,
+ 0x93a => true,
+ 0x93c => true,
+ 0x941...0x948 => true,
+ 0x94d => true,
+ 0x951...0x957 => true,
+ 0x962...0x963 => true,
+ 0x981 => true,
+ 0x9bc => true,
+ 0x9be => true,
+ 0x9c1...0x9c4 => true,
+ 0x9cd => true,
+ 0x9d7 => true,
+ 0x9e2...0x9e3 => true,
+ 0x9fe => true,
+ 0xa01...0xa02 => true,
+ 0xa3c => true,
+ 0xa41...0xa42 => true,
+ 0xa47...0xa48 => true,
+ 0xa4b...0xa4d => true,
+ 0xa51 => true,
+ 0xa70...0xa71 => true,
+ 0xa75 => true,
+ 0xa81...0xa82 => true,
+ 0xabc => true,
+ 0xac1...0xac5 => true,
+ 0xac7...0xac8 => true,
+ 0xacd => true,
+ 0xae2...0xae3 => true,
+ 0xafa...0xaff => true,
+ 0xb01 => true,
+ 0xb3c => true,
+ 0xb3e => true,
+ 0xb3f => true,
+ 0xb41...0xb44 => true,
+ 0xb4d => true,
+ 0xb55...0xb56 => true,
+ 0xb57 => true,
+ 0xb62...0xb63 => true,
+ 0xb82 => true,
+ 0xbbe => true,
+ 0xbc0 => true,
+ 0xbcd => true,
+ 0xbd7 => true,
+ 0xc00 => true,
+ 0xc04 => true,
+ 0xc3c => true,
+ 0xc3e...0xc40 => true,
+ 0xc46...0xc48 => true,
+ 0xc4a...0xc4d => true,
+ 0xc55...0xc56 => true,
+ 0xc62...0xc63 => true,
+ 0xc81 => true,
+ 0xcbc => true,
+ 0xcbf => true,
+ 0xcc2 => true,
+ 0xcc6 => true,
+ 0xccc...0xccd => true,
+ 0xcd5...0xcd6 => true,
+ 0xce2...0xce3 => true,
+ 0xd00...0xd01 => true,
+ 0xd3b...0xd3c => true,
+ 0xd3e => true,
+ 0xd41...0xd44 => true,
+ 0xd4d => true,
+ 0xd57 => true,
+ 0xd62...0xd63 => true,
+ 0xd81 => true,
+ 0xdca => true,
+ 0xdcf => true,
+ 0xdd2...0xdd4 => true,
+ 0xdd6 => true,
+ 0xddf => true,
+ 0xe31 => true,
+ 0xe34...0xe3a => true,
+ 0xe47...0xe4e => true,
+ 0xeb1 => true,
+ 0xeb4...0xebc => true,
+ 0xec8...0xece => true,
+ 0xf18...0xf19 => true,
+ 0xf35 => true,
+ 0xf37 => true,
+ 0xf39 => true,
+ 0xf71...0xf7e => true,
+ 0xf80...0xf84 => true,
+ 0xf86...0xf87 => true,
+ 0xf8d...0xf97 => true,
+ 0xf99...0xfbc => true,
+ 0xfc6 => true,
+ 0x102d...0x1030 => true,
+ 0x1032...0x1037 => true,
+ 0x1039...0x103a => true,
+ 0x103d...0x103e => true,
+ 0x1058...0x1059 => true,
+ 0x105e...0x1060 => true,
+ 0x1071...0x1074 => true,
+ 0x1082 => true,
+ 0x1085...0x1086 => true,
+ 0x108d => true,
+ 0x109d => true,
+ 0x135d...0x135f => true,
+ 0x1712...0x1714 => true,
+ 0x1732...0x1733 => true,
+ 0x1752...0x1753 => true,
+ 0x1772...0x1773 => true,
+ 0x17b4...0x17b5 => true,
+ 0x17b7...0x17bd => true,
+ 0x17c6 => true,
+ 0x17c9...0x17d3 => true,
+ 0x17dd => true,
+ 0x180b...0x180d => true,
+ 0x180f => true,
+ 0x1885...0x1886 => true,
+ 0x18a9 => true,
+ 0x1920...0x1922 => true,
+ 0x1927...0x1928 => true,
+ 0x1932 => true,
+ 0x1939...0x193b => true,
+ 0x1a17...0x1a18 => true,
+ 0x1a1b => true,
+ 0x1a56 => true,
+ 0x1a58...0x1a5e => true,
+ 0x1a60 => true,
+ 0x1a62 => true,
+ 0x1a65...0x1a6c => true,
+ 0x1a73...0x1a7c => true,
+ 0x1a7f => true,
+ 0x1ab0...0x1abd => true,
+ 0x1abe => true,
+ 0x1abf...0x1ace => true,
+ 0x1b00...0x1b03 => true,
+ 0x1b34 => true,
+ 0x1b35 => true,
+ 0x1b36...0x1b3a => true,
+ 0x1b3c => true,
+ 0x1b42 => true,
+ 0x1b6b...0x1b73 => true,
+ 0x1b80...0x1b81 => true,
+ 0x1ba2...0x1ba5 => true,
+ 0x1ba8...0x1ba9 => true,
+ 0x1bab...0x1bad => true,
+ 0x1be6 => true,
+ 0x1be8...0x1be9 => true,
+ 0x1bed => true,
+ 0x1bef...0x1bf1 => true,
+ 0x1c2c...0x1c33 => true,
+ 0x1c36...0x1c37 => true,
+ 0x1cd0...0x1cd2 => true,
+ 0x1cd4...0x1ce0 => true,
+ 0x1ce2...0x1ce8 => true,
+ 0x1ced => true,
+ 0x1cf4 => true,
+ 0x1cf8...0x1cf9 => true,
+ 0x1dc0...0x1dff => true,
+ 0x200c => true,
+ 0x20d0...0x20dc => true,
+ 0x20dd...0x20e0 => true,
+ 0x20e1 => true,
+ 0x20e2...0x20e4 => true,
+ 0x20e5...0x20f0 => true,
+ 0x2cef...0x2cf1 => true,
+ 0x2d7f => true,
+ 0x2de0...0x2dff => true,
+ 0x302a...0x302d => true,
+ 0x302e...0x302f => true,
+ 0x3099...0x309a => true,
+ 0xa66f => true,
+ 0xa670...0xa672 => true,
+ 0xa674...0xa67d => true,
+ 0xa69e...0xa69f => true,
+ 0xa6f0...0xa6f1 => true,
+ 0xa802 => true,
+ 0xa806 => true,
+ 0xa80b => true,
+ 0xa825...0xa826 => true,
+ 0xa82c => true,
+ 0xa8c4...0xa8c5 => true,
+ 0xa8e0...0xa8f1 => true,
+ 0xa8ff => true,
+ 0xa926...0xa92d => true,
+ 0xa947...0xa951 => true,
+ 0xa980...0xa982 => true,
+ 0xa9b3 => true,
+ 0xa9b6...0xa9b9 => true,
+ 0xa9bc...0xa9bd => true,
+ 0xa9e5 => true,
+ 0xaa29...0xaa2e => true,
+ 0xaa31...0xaa32 => true,
+ 0xaa35...0xaa36 => true,
+ 0xaa43 => true,
+ 0xaa4c => true,
+ 0xaa7c => true,
+ 0xaab0 => true,
+ 0xaab2...0xaab4 => true,
+ 0xaab7...0xaab8 => true,
+ 0xaabe...0xaabf => true,
+ 0xaac1 => true,
+ 0xaaec...0xaaed => true,
+ 0xaaf6 => true,
+ 0xabe5 => true,
+ 0xabe8 => true,
+ 0xabed => true,
+ 0xfb1e => true,
+ 0xfe00...0xfe0f => true,
+ 0xfe20...0xfe2f => true,
+ 0xff9e...0xff9f => true,
+ 0x101fd => true,
+ 0x102e0 => true,
+ 0x10376...0x1037a => true,
+ 0x10a01...0x10a03 => true,
+ 0x10a05...0x10a06 => true,
+ 0x10a0c...0x10a0f => true,
+ 0x10a38...0x10a3a => true,
+ 0x10a3f => true,
+ 0x10ae5...0x10ae6 => true,
+ 0x10d24...0x10d27 => true,
+ 0x10eab...0x10eac => true,
+ 0x10efd...0x10eff => true,
+ 0x10f46...0x10f50 => true,
+ 0x10f82...0x10f85 => true,
+ 0x11001 => true,
+ 0x11038...0x11046 => true,
+ 0x11070 => true,
+ 0x11073...0x11074 => true,
+ 0x1107f...0x11081 => true,
+ 0x110b3...0x110b6 => true,
+ 0x110b9...0x110ba => true,
+ 0x110c2 => true,
+ 0x11100...0x11102 => true,
+ 0x11127...0x1112b => true,
+ 0x1112d...0x11134 => true,
+ 0x11173 => true,
+ 0x11180...0x11181 => true,
+ 0x111b6...0x111be => true,
+ 0x111c9...0x111cc => true,
+ 0x111cf => true,
+ 0x1122f...0x11231 => true,
+ 0x11234 => true,
+ 0x11236...0x11237 => true,
+ 0x1123e => true,
+ 0x11241 => true,
+ 0x112df => true,
+ 0x112e3...0x112ea => true,
+ 0x11300...0x11301 => true,
+ 0x1133b...0x1133c => true,
+ 0x1133e => true,
+ 0x11340 => true,
+ 0x11357 => true,
+ 0x11366...0x1136c => true,
+ 0x11370...0x11374 => true,
+ 0x11438...0x1143f => true,
+ 0x11442...0x11444 => true,
+ 0x11446 => true,
+ 0x1145e => true,
+ 0x114b0 => true,
+ 0x114b3...0x114b8 => true,
+ 0x114ba => true,
+ 0x114bd => true,
+ 0x114bf...0x114c0 => true,
+ 0x114c2...0x114c3 => true,
+ 0x115af => true,
+ 0x115b2...0x115b5 => true,
+ 0x115bc...0x115bd => true,
+ 0x115bf...0x115c0 => true,
+ 0x115dc...0x115dd => true,
+ 0x11633...0x1163a => true,
+ 0x1163d => true,
+ 0x1163f...0x11640 => true,
+ 0x116ab => true,
+ 0x116ad => true,
+ 0x116b0...0x116b5 => true,
+ 0x116b7 => true,
+ 0x1171d...0x1171f => true,
+ 0x11722...0x11725 => true,
+ 0x11727...0x1172b => true,
+ 0x1182f...0x11837 => true,
+ 0x11839...0x1183a => true,
+ 0x11930 => true,
+ 0x1193b...0x1193c => true,
+ 0x1193e => true,
+ 0x11943 => true,
+ 0x119d4...0x119d7 => true,
+ 0x119da...0x119db => true,
+ 0x119e0 => true,
+ 0x11a01...0x11a0a => true,
+ 0x11a33...0x11a38 => true,
+ 0x11a3b...0x11a3e => true,
+ 0x11a47 => true,
+ 0x11a51...0x11a56 => true,
+ 0x11a59...0x11a5b => true,
+ 0x11a8a...0x11a96 => true,
+ 0x11a98...0x11a99 => true,
+ 0x11c30...0x11c36 => true,
+ 0x11c38...0x11c3d => true,
+ 0x11c3f => true,
+ 0x11c92...0x11ca7 => true,
+ 0x11caa...0x11cb0 => true,
+ 0x11cb2...0x11cb3 => true,
+ 0x11cb5...0x11cb6 => true,
+ 0x11d31...0x11d36 => true,
+ 0x11d3a => true,
+ 0x11d3c...0x11d3d => true,
+ 0x11d3f...0x11d45 => true,
+ 0x11d47 => true,
+ 0x11d90...0x11d91 => true,
+ 0x11d95 => true,
+ 0x11d97 => true,
+ 0x11ef3...0x11ef4 => true,
+ 0x11f00...0x11f01 => true,
+ 0x11f36...0x11f3a => true,
+ 0x11f40 => true,
+ 0x11f42 => true,
+ 0x13440 => true,
+ 0x13447...0x13455 => true,
+ 0x16af0...0x16af4 => true,
+ 0x16b30...0x16b36 => true,
+ 0x16f4f => true,
+ 0x16f8f...0x16f92 => true,
+ 0x16fe4 => true,
+ 0x1bc9d...0x1bc9e => true,
+ 0x1cf00...0x1cf2d => true,
+ 0x1cf30...0x1cf46 => true,
+ 0x1d165 => true,
+ 0x1d167...0x1d169 => true,
+ 0x1d16e...0x1d172 => true,
+ 0x1d17b...0x1d182 => true,
+ 0x1d185...0x1d18b => true,
+ 0x1d1aa...0x1d1ad => true,
+ 0x1d242...0x1d244 => true,
+ 0x1da00...0x1da36 => true,
+ 0x1da3b...0x1da6c => true,
+ 0x1da75 => true,
+ 0x1da84 => true,
+ 0x1da9b...0x1da9f => true,
+ 0x1daa1...0x1daaf => true,
+ 0x1e000...0x1e006 => true,
+ 0x1e008...0x1e018 => true,
+ 0x1e01b...0x1e021 => true,
+ 0x1e023...0x1e024 => true,
+ 0x1e026...0x1e02a => true,
+ 0x1e08f => true,
+ 0x1e130...0x1e136 => true,
+ 0x1e2ae => true,
+ 0x1e2ec...0x1e2ef => true,
+ 0x1e4ec...0x1e4ef => true,
+ 0x1e8d0...0x1e8d6 => true,
+ 0x1e944...0x1e94a => true,
+ 0x1f3fb...0x1f3ff => true,
+ 0xe0020...0xe007f => true,
+ 0xe0100...0xe01ef => true,
+ else => false,
+ };
+}
+
+pub fn isRegionalIndicator(cp: u21) bool {
+ if (cp < 0x1f1e6 or cp > 0x1f1ff) return false;
+
+ return switch (cp) {
+ 0x1f1e6...0x1f1ff => true,
+ else => false,
+ };
+}
+
+pub fn isSpacingmark(cp: u21) bool {
+ if (cp < 0x903 or cp > 0x1d16d) return false;
+
+ return switch (cp) {
+ 0x903 => true,
+ 0x93b => true,
+ 0x93e...0x940 => true,
+ 0x949...0x94c => true,
+ 0x94e...0x94f => true,
+ 0x982...0x983 => true,
+ 0x9bf...0x9c0 => true,
+ 0x9c7...0x9c8 => true,
+ 0x9cb...0x9cc => true,
+ 0xa03 => true,
+ 0xa3e...0xa40 => true,
+ 0xa83 => true,
+ 0xabe...0xac0 => true,
+ 0xac9 => true,
+ 0xacb...0xacc => true,
+ 0xb02...0xb03 => true,
+ 0xb40 => true,
+ 0xb47...0xb48 => true,
+ 0xb4b...0xb4c => true,
+ 0xbbf => true,
+ 0xbc1...0xbc2 => true,
+ 0xbc6...0xbc8 => true,
+ 0xbca...0xbcc => true,
+ 0xc01...0xc03 => true,
+ 0xc41...0xc44 => true,
+ 0xc82...0xc83 => true,
+ 0xcbe => true,
+ 0xcc0...0xcc1 => true,
+ 0xcc3...0xcc4 => true,
+ 0xcc7...0xcc8 => true,
+ 0xcca...0xccb => true,
+ 0xcf3 => true,
+ 0xd02...0xd03 => true,
+ 0xd3f...0xd40 => true,
+ 0xd46...0xd48 => true,
+ 0xd4a...0xd4c => true,
+ 0xd82...0xd83 => true,
+ 0xdd0...0xdd1 => true,
+ 0xdd8...0xdde => true,
+ 0xdf2...0xdf3 => true,
+ 0xe33 => true,
+ 0xeb3 => true,
+ 0xf3e...0xf3f => true,
+ 0xf7f => true,
+ 0x1031 => true,
+ 0x103b...0x103c => true,
+ 0x1056...0x1057 => true,
+ 0x1084 => true,
+ 0x1715 => true,
+ 0x1734 => true,
+ 0x17b6 => true,
+ 0x17be...0x17c5 => true,
+ 0x17c7...0x17c8 => true,
+ 0x1923...0x1926 => true,
+ 0x1929...0x192b => true,
+ 0x1930...0x1931 => true,
+ 0x1933...0x1938 => true,
+ 0x1a19...0x1a1a => true,
+ 0x1a55 => true,
+ 0x1a57 => true,
+ 0x1a6d...0x1a72 => true,
+ 0x1b04 => true,
+ 0x1b3b => true,
+ 0x1b3d...0x1b41 => true,
+ 0x1b43...0x1b44 => true,
+ 0x1b82 => true,
+ 0x1ba1 => true,
+ 0x1ba6...0x1ba7 => true,
+ 0x1baa => true,
+ 0x1be7 => true,
+ 0x1bea...0x1bec => true,
+ 0x1bee => true,
+ 0x1bf2...0x1bf3 => true,
+ 0x1c24...0x1c2b => true,
+ 0x1c34...0x1c35 => true,
+ 0x1ce1 => true,
+ 0x1cf7 => true,
+ 0xa823...0xa824 => true,
+ 0xa827 => true,
+ 0xa880...0xa881 => true,
+ 0xa8b4...0xa8c3 => true,
+ 0xa952...0xa953 => true,
+ 0xa983 => true,
+ 0xa9b4...0xa9b5 => true,
+ 0xa9ba...0xa9bb => true,
+ 0xa9be...0xa9c0 => true,
+ 0xaa2f...0xaa30 => true,
+ 0xaa33...0xaa34 => true,
+ 0xaa4d => true,
+ 0xaaeb => true,
+ 0xaaee...0xaaef => true,
+ 0xaaf5 => true,
+ 0xabe3...0xabe4 => true,
+ 0xabe6...0xabe7 => true,
+ 0xabe9...0xabea => true,
+ 0xabec => true,
+ 0x11000 => true,
+ 0x11002 => true,
+ 0x11082 => true,
+ 0x110b0...0x110b2 => true,
+ 0x110b7...0x110b8 => true,
+ 0x1112c => true,
+ 0x11145...0x11146 => true,
+ 0x11182 => true,
+ 0x111b3...0x111b5 => true,
+ 0x111bf...0x111c0 => true,
+ 0x111ce => true,
+ 0x1122c...0x1122e => true,
+ 0x11232...0x11233 => true,
+ 0x11235 => true,
+ 0x112e0...0x112e2 => true,
+ 0x11302...0x11303 => true,
+ 0x1133f => true,
+ 0x11341...0x11344 => true,
+ 0x11347...0x11348 => true,
+ 0x1134b...0x1134d => true,
+ 0x11362...0x11363 => true,
+ 0x11435...0x11437 => true,
+ 0x11440...0x11441 => true,
+ 0x11445 => true,
+ 0x114b1...0x114b2 => true,
+ 0x114b9 => true,
+ 0x114bb...0x114bc => true,
+ 0x114be => true,
+ 0x114c1 => true,
+ 0x115b0...0x115b1 => true,
+ 0x115b8...0x115bb => true,
+ 0x115be => true,
+ 0x11630...0x11632 => true,
+ 0x1163b...0x1163c => true,
+ 0x1163e => true,
+ 0x116ac => true,
+ 0x116ae...0x116af => true,
+ 0x116b6 => true,
+ 0x11726 => true,
+ 0x1182c...0x1182e => true,
+ 0x11838 => true,
+ 0x11931...0x11935 => true,
+ 0x11937...0x11938 => true,
+ 0x1193d => true,
+ 0x11940 => true,
+ 0x11942 => true,
+ 0x119d1...0x119d3 => true,
+ 0x119dc...0x119df => true,
+ 0x119e4 => true,
+ 0x11a39 => true,
+ 0x11a57...0x11a58 => true,
+ 0x11a97 => true,
+ 0x11c2f => true,
+ 0x11c3e => true,
+ 0x11ca9 => true,
+ 0x11cb1 => true,
+ 0x11cb4 => true,
+ 0x11d8a...0x11d8e => true,
+ 0x11d93...0x11d94 => true,
+ 0x11d96 => true,
+ 0x11ef5...0x11ef6 => true,
+ 0x11f03 => true,
+ 0x11f34...0x11f35 => true,
+ 0x11f3e...0x11f3f => true,
+ 0x11f41 => true,
+ 0x16f51...0x16f87 => true,
+ 0x16ff0...0x16ff1 => true,
+ 0x1d166 => true,
+ 0x1d16d => true,
+ else => false,
+ };
+}
+
+pub fn isL(cp: u21) bool {
+ if (cp < 0x1100 or cp > 0xa97c) return false;
+
+ return switch (cp) {
+ 0x1100...0x115f => true,
+ 0xa960...0xa97c => true,
+ else => false,
+ };
+}
+
+pub fn isV(cp: u21) bool {
+ if (cp < 0x1160 or cp > 0xd7c6) return false;
+
+ return switch (cp) {
+ 0x1160...0x11a7 => true,
+ 0xd7b0...0xd7c6 => true,
+ else => false,
+ };
+}
+
+pub fn isT(cp: u21) bool {
+ if (cp < 0x11a8 or cp > 0xd7fb) return false;
+
+ return switch (cp) {
+ 0x11a8...0x11ff => true,
+ 0xd7cb...0xd7fb => true,
+ else => false,
+ };
+}
+
+pub fn isLv(cp: u21) bool {
+ if (cp < 0xac00 or cp > 0xd788) return false;
+
+ return switch (cp) {
+ 0xac00 => true,
+ 0xac1c => true,
+ 0xac38 => true,
+ 0xac54 => true,
+ 0xac70 => true,
+ 0xac8c => true,
+ 0xaca8 => true,
+ 0xacc4 => true,
+ 0xace0 => true,
+ 0xacfc => true,
+ 0xad18 => true,
+ 0xad34 => true,
+ 0xad50 => true,
+ 0xad6c => true,
+ 0xad88 => true,
+ 0xada4 => true,
+ 0xadc0 => true,
+ 0xaddc => true,
+ 0xadf8 => true,
+ 0xae14 => true,
+ 0xae30 => true,
+ 0xae4c => true,
+ 0xae68 => true,
+ 0xae84 => true,
+ 0xaea0 => true,
+ 0xaebc => true,
+ 0xaed8 => true,
+ 0xaef4 => true,
+ 0xaf10 => true,
+ 0xaf2c => true,
+ 0xaf48 => true,
+ 0xaf64 => true,
+ 0xaf80 => true,
+ 0xaf9c => true,
+ 0xafb8 => true,
+ 0xafd4 => true,
+ 0xaff0 => true,
+ 0xb00c => true,
+ 0xb028 => true,
+ 0xb044 => true,
+ 0xb060 => true,
+ 0xb07c => true,
+ 0xb098 => true,
+ 0xb0b4 => true,
+ 0xb0d0 => true,
+ 0xb0ec => true,
+ 0xb108 => true,
+ 0xb124 => true,
+ 0xb140 => true,
+ 0xb15c => true,
+ 0xb178 => true,
+ 0xb194 => true,
+ 0xb1b0 => true,
+ 0xb1cc => true,
+ 0xb1e8 => true,
+ 0xb204 => true,
+ 0xb220 => true,
+ 0xb23c => true,
+ 0xb258 => true,
+ 0xb274 => true,
+ 0xb290 => true,
+ 0xb2ac => true,
+ 0xb2c8 => true,
+ 0xb2e4 => true,
+ 0xb300 => true,
+ 0xb31c => true,
+ 0xb338 => true,
+ 0xb354 => true,
+ 0xb370 => true,
+ 0xb38c => true,
+ 0xb3a8 => true,
+ 0xb3c4 => true,
+ 0xb3e0 => true,
+ 0xb3fc => true,
+ 0xb418 => true,
+ 0xb434 => true,
+ 0xb450 => true,
+ 0xb46c => true,
+ 0xb488 => true,
+ 0xb4a4 => true,
+ 0xb4c0 => true,
+ 0xb4dc => true,
+ 0xb4f8 => true,
+ 0xb514 => true,
+ 0xb530 => true,
+ 0xb54c => true,
+ 0xb568 => true,
+ 0xb584 => true,
+ 0xb5a0 => true,
+ 0xb5bc => true,
+ 0xb5d8 => true,
+ 0xb5f4 => true,
+ 0xb610 => true,
+ 0xb62c => true,
+ 0xb648 => true,
+ 0xb664 => true,
+ 0xb680 => true,
+ 0xb69c => true,
+ 0xb6b8 => true,
+ 0xb6d4 => true,
+ 0xb6f0 => true,
+ 0xb70c => true,
+ 0xb728 => true,
+ 0xb744 => true,
+ 0xb760 => true,
+ 0xb77c => true,
+ 0xb798 => true,
+ 0xb7b4 => true,
+ 0xb7d0 => true,
+ 0xb7ec => true,
+ 0xb808 => true,
+ 0xb824 => true,
+ 0xb840 => true,
+ 0xb85c => true,
+ 0xb878 => true,
+ 0xb894 => true,
+ 0xb8b0 => true,
+ 0xb8cc => true,
+ 0xb8e8 => true,
+ 0xb904 => true,
+ 0xb920 => true,
+ 0xb93c => true,
+ 0xb958 => true,
+ 0xb974 => true,
+ 0xb990 => true,
+ 0xb9ac => true,
+ 0xb9c8 => true,
+ 0xb9e4 => true,
+ 0xba00 => true,
+ 0xba1c => true,
+ 0xba38 => true,
+ 0xba54 => true,
+ 0xba70 => true,
+ 0xba8c => true,
+ 0xbaa8 => true,
+ 0xbac4 => true,
+ 0xbae0 => true,
+ 0xbafc => true,
+ 0xbb18 => true,
+ 0xbb34 => true,
+ 0xbb50 => true,
+ 0xbb6c => true,
+ 0xbb88 => true,
+ 0xbba4 => true,
+ 0xbbc0 => true,
+ 0xbbdc => true,
+ 0xbbf8 => true,
+ 0xbc14 => true,
+ 0xbc30 => true,
+ 0xbc4c => true,
+ 0xbc68 => true,
+ 0xbc84 => true,
+ 0xbca0 => true,
+ 0xbcbc => true,
+ 0xbcd8 => true,
+ 0xbcf4 => true,
+ 0xbd10 => true,
+ 0xbd2c => true,
+ 0xbd48 => true,
+ 0xbd64 => true,
+ 0xbd80 => true,
+ 0xbd9c => true,
+ 0xbdb8 => true,
+ 0xbdd4 => true,
+ 0xbdf0 => true,
+ 0xbe0c => true,
+ 0xbe28 => true,
+ 0xbe44 => true,
+ 0xbe60 => true,
+ 0xbe7c => true,
+ 0xbe98 => true,
+ 0xbeb4 => true,
+ 0xbed0 => true,
+ 0xbeec => true,
+ 0xbf08 => true,
+ 0xbf24 => true,
+ 0xbf40 => true,
+ 0xbf5c => true,
+ 0xbf78 => true,
+ 0xbf94 => true,
+ 0xbfb0 => true,
+ 0xbfcc => true,
+ 0xbfe8 => true,
+ 0xc004 => true,
+ 0xc020 => true,
+ 0xc03c => true,
+ 0xc058 => true,
+ 0xc074 => true,
+ 0xc090 => true,
+ 0xc0ac => true,
+ 0xc0c8 => true,
+ 0xc0e4 => true,
+ 0xc100 => true,
+ 0xc11c => true,
+ 0xc138 => true,
+ 0xc154 => true,
+ 0xc170 => true,
+ 0xc18c => true,
+ 0xc1a8 => true,
+ 0xc1c4 => true,
+ 0xc1e0 => true,
+ 0xc1fc => true,
+ 0xc218 => true,
+ 0xc234 => true,
+ 0xc250 => true,
+ 0xc26c => true,
+ 0xc288 => true,
+ 0xc2a4 => true,
+ 0xc2c0 => true,
+ 0xc2dc => true,
+ 0xc2f8 => true,
+ 0xc314 => true,
+ 0xc330 => true,
+ 0xc34c => true,
+ 0xc368 => true,
+ 0xc384 => true,
+ 0xc3a0 => true,
+ 0xc3bc => true,
+ 0xc3d8 => true,
+ 0xc3f4 => true,
+ 0xc410 => true,
+ 0xc42c => true,
+ 0xc448 => true,
+ 0xc464 => true,
+ 0xc480 => true,
+ 0xc49c => true,
+ 0xc4b8 => true,
+ 0xc4d4 => true,
+ 0xc4f0 => true,
+ 0xc50c => true,
+ 0xc528 => true,
+ 0xc544 => true,
+ 0xc560 => true,
+ 0xc57c => true,
+ 0xc598 => true,
+ 0xc5b4 => true,
+ 0xc5d0 => true,
+ 0xc5ec => true,
+ 0xc608 => true,
+ 0xc624 => true,
+ 0xc640 => true,
+ 0xc65c => true,
+ 0xc678 => true,
+ 0xc694 => true,
+ 0xc6b0 => true,
+ 0xc6cc => true,
+ 0xc6e8 => true,
+ 0xc704 => true,
+ 0xc720 => true,
+ 0xc73c => true,
+ 0xc758 => true,
+ 0xc774 => true,
+ 0xc790 => true,
+ 0xc7ac => true,
+ 0xc7c8 => true,
+ 0xc7e4 => true,
+ 0xc800 => true,
+ 0xc81c => true,
+ 0xc838 => true,
+ 0xc854 => true,
+ 0xc870 => true,
+ 0xc88c => true,
+ 0xc8a8 => true,
+ 0xc8c4 => true,
+ 0xc8e0 => true,
+ 0xc8fc => true,
+ 0xc918 => true,
+ 0xc934 => true,
+ 0xc950 => true,
+ 0xc96c => true,
+ 0xc988 => true,
+ 0xc9a4 => true,
+ 0xc9c0 => true,
+ 0xc9dc => true,
+ 0xc9f8 => true,
+ 0xca14 => true,
+ 0xca30 => true,
+ 0xca4c => true,
+ 0xca68 => true,
+ 0xca84 => true,
+ 0xcaa0 => true,
+ 0xcabc => true,
+ 0xcad8 => true,
+ 0xcaf4 => true,
+ 0xcb10 => true,
+ 0xcb2c => true,
+ 0xcb48 => true,
+ 0xcb64 => true,
+ 0xcb80 => true,
+ 0xcb9c => true,
+ 0xcbb8 => true,
+ 0xcbd4 => true,
+ 0xcbf0 => true,
+ 0xcc0c => true,
+ 0xcc28 => true,
+ 0xcc44 => true,
+ 0xcc60 => true,
+ 0xcc7c => true,
+ 0xcc98 => true,
+ 0xccb4 => true,
+ 0xccd0 => true,
+ 0xccec => true,
+ 0xcd08 => true,
+ 0xcd24 => true,
+ 0xcd40 => true,
+ 0xcd5c => true,
+ 0xcd78 => true,
+ 0xcd94 => true,
+ 0xcdb0 => true,
+ 0xcdcc => true,
+ 0xcde8 => true,
+ 0xce04 => true,
+ 0xce20 => true,
+ 0xce3c => true,
+ 0xce58 => true,
+ 0xce74 => true,
+ 0xce90 => true,
+ 0xceac => true,
+ 0xcec8 => true,
+ 0xcee4 => true,
+ 0xcf00 => true,
+ 0xcf1c => true,
+ 0xcf38 => true,
+ 0xcf54 => true,
+ 0xcf70 => true,
+ 0xcf8c => true,
+ 0xcfa8 => true,
+ 0xcfc4 => true,
+ 0xcfe0 => true,
+ 0xcffc => true,
+ 0xd018 => true,
+ 0xd034 => true,
+ 0xd050 => true,
+ 0xd06c => true,
+ 0xd088 => true,
+ 0xd0a4 => true,
+ 0xd0c0 => true,
+ 0xd0dc => true,
+ 0xd0f8 => true,
+ 0xd114 => true,
+ 0xd130 => true,
+ 0xd14c => true,
+ 0xd168 => true,
+ 0xd184 => true,
+ 0xd1a0 => true,
+ 0xd1bc => true,
+ 0xd1d8 => true,
+ 0xd1f4 => true,
+ 0xd210 => true,
+ 0xd22c => true,
+ 0xd248 => true,
+ 0xd264 => true,
+ 0xd280 => true,
+ 0xd29c => true,
+ 0xd2b8 => true,
+ 0xd2d4 => true,
+ 0xd2f0 => true,
+ 0xd30c => true,
+ 0xd328 => true,
+ 0xd344 => true,
+ 0xd360 => true,
+ 0xd37c => true,
+ 0xd398 => true,
+ 0xd3b4 => true,
+ 0xd3d0 => true,
+ 0xd3ec => true,
+ 0xd408 => true,
+ 0xd424 => true,
+ 0xd440 => true,
+ 0xd45c => true,
+ 0xd478 => true,
+ 0xd494 => true,
+ 0xd4b0 => true,
+ 0xd4cc => true,
+ 0xd4e8 => true,
+ 0xd504 => true,
+ 0xd520 => true,
+ 0xd53c => true,
+ 0xd558 => true,
+ 0xd574 => true,
+ 0xd590 => true,
+ 0xd5ac => true,
+ 0xd5c8 => true,
+ 0xd5e4 => true,
+ 0xd600 => true,
+ 0xd61c => true,
+ 0xd638 => true,
+ 0xd654 => true,
+ 0xd670 => true,
+ 0xd68c => true,
+ 0xd6a8 => true,
+ 0xd6c4 => true,
+ 0xd6e0 => true,
+ 0xd6fc => true,
+ 0xd718 => true,
+ 0xd734 => true,
+ 0xd750 => true,
+ 0xd76c => true,
+ 0xd788 => true,
+ else => false,
+ };
+}
+
+pub fn isLvt(cp: u21) bool {
+ if (cp < 0xac01 or cp > 0xd7a3) return false;
+
+ return switch (cp) {
+ 0xac01...0xac1b => true,
+ 0xac1d...0xac37 => true,
+ 0xac39...0xac53 => true,
+ 0xac55...0xac6f => true,
+ 0xac71...0xac8b => true,
+ 0xac8d...0xaca7 => true,
+ 0xaca9...0xacc3 => true,
+ 0xacc5...0xacdf => true,
+ 0xace1...0xacfb => true,
+ 0xacfd...0xad17 => true,
+ 0xad19...0xad33 => true,
+ 0xad35...0xad4f => true,
+ 0xad51...0xad6b => true,
+ 0xad6d...0xad87 => true,
+ 0xad89...0xada3 => true,
+ 0xada5...0xadbf => true,
+ 0xadc1...0xaddb => true,
+ 0xaddd...0xadf7 => true,
+ 0xadf9...0xae13 => true,
+ 0xae15...0xae2f => true,
+ 0xae31...0xae4b => true,
+ 0xae4d...0xae67 => true,
+ 0xae69...0xae83 => true,
+ 0xae85...0xae9f => true,
+ 0xaea1...0xaebb => true,
+ 0xaebd...0xaed7 => true,
+ 0xaed9...0xaef3 => true,
+ 0xaef5...0xaf0f => true,
+ 0xaf11...0xaf2b => true,
+ 0xaf2d...0xaf47 => true,
+ 0xaf49...0xaf63 => true,
+ 0xaf65...0xaf7f => true,
+ 0xaf81...0xaf9b => true,
+ 0xaf9d...0xafb7 => true,
+ 0xafb9...0xafd3 => true,
+ 0xafd5...0xafef => true,
+ 0xaff1...0xb00b => true,
+ 0xb00d...0xb027 => true,
+ 0xb029...0xb043 => true,
+ 0xb045...0xb05f => true,
+ 0xb061...0xb07b => true,
+ 0xb07d...0xb097 => true,
+ 0xb099...0xb0b3 => true,
+ 0xb0b5...0xb0cf => true,
+ 0xb0d1...0xb0eb => true,
+ 0xb0ed...0xb107 => true,
+ 0xb109...0xb123 => true,
+ 0xb125...0xb13f => true,
+ 0xb141...0xb15b => true,
+ 0xb15d...0xb177 => true,
+ 0xb179...0xb193 => true,
+ 0xb195...0xb1af => true,
+ 0xb1b1...0xb1cb => true,
+ 0xb1cd...0xb1e7 => true,
+ 0xb1e9...0xb203 => true,
+ 0xb205...0xb21f => true,
+ 0xb221...0xb23b => true,
+ 0xb23d...0xb257 => true,
+ 0xb259...0xb273 => true,
+ 0xb275...0xb28f => true,
+ 0xb291...0xb2ab => true,
+ 0xb2ad...0xb2c7 => true,
+ 0xb2c9...0xb2e3 => true,
+ 0xb2e5...0xb2ff => true,
+ 0xb301...0xb31b => true,
+ 0xb31d...0xb337 => true,
+ 0xb339...0xb353 => true,
+ 0xb355...0xb36f => true,
+ 0xb371...0xb38b => true,
+ 0xb38d...0xb3a7 => true,
+ 0xb3a9...0xb3c3 => true,
+ 0xb3c5...0xb3df => true,
+ 0xb3e1...0xb3fb => true,
+ 0xb3fd...0xb417 => true,
+ 0xb419...0xb433 => true,
+ 0xb435...0xb44f => true,
+ 0xb451...0xb46b => true,
+ 0xb46d...0xb487 => true,
+ 0xb489...0xb4a3 => true,
+ 0xb4a5...0xb4bf => true,
+ 0xb4c1...0xb4db => true,
+ 0xb4dd...0xb4f7 => true,
+ 0xb4f9...0xb513 => true,
+ 0xb515...0xb52f => true,
+ 0xb531...0xb54b => true,
+ 0xb54d...0xb567 => true,
+ 0xb569...0xb583 => true,
+ 0xb585...0xb59f => true,
+ 0xb5a1...0xb5bb => true,
+ 0xb5bd...0xb5d7 => true,
+ 0xb5d9...0xb5f3 => true,
+ 0xb5f5...0xb60f => true,
+ 0xb611...0xb62b => true,
+ 0xb62d...0xb647 => true,
+ 0xb649...0xb663 => true,
+ 0xb665...0xb67f => true,
+ 0xb681...0xb69b => true,
+ 0xb69d...0xb6b7 => true,
+ 0xb6b9...0xb6d3 => true,
+ 0xb6d5...0xb6ef => true,
+ 0xb6f1...0xb70b => true,
+ 0xb70d...0xb727 => true,
+ 0xb729...0xb743 => true,
+ 0xb745...0xb75f => true,
+ 0xb761...0xb77b => true,
+ 0xb77d...0xb797 => true,
+ 0xb799...0xb7b3 => true,
+ 0xb7b5...0xb7cf => true,
+ 0xb7d1...0xb7eb => true,
+ 0xb7ed...0xb807 => true,
+ 0xb809...0xb823 => true,
+ 0xb825...0xb83f => true,
+ 0xb841...0xb85b => true,
+ 0xb85d...0xb877 => true,
+ 0xb879...0xb893 => true,
+ 0xb895...0xb8af => true,
+ 0xb8b1...0xb8cb => true,
+ 0xb8cd...0xb8e7 => true,
+ 0xb8e9...0xb903 => true,
+ 0xb905...0xb91f => true,
+ 0xb921...0xb93b => true,
+ 0xb93d...0xb957 => true,
+ 0xb959...0xb973 => true,
+ 0xb975...0xb98f => true,
+ 0xb991...0xb9ab => true,
+ 0xb9ad...0xb9c7 => true,
+ 0xb9c9...0xb9e3 => true,
+ 0xb9e5...0xb9ff => true,
+ 0xba01...0xba1b => true,
+ 0xba1d...0xba37 => true,
+ 0xba39...0xba53 => true,
+ 0xba55...0xba6f => true,
+ 0xba71...0xba8b => true,
+ 0xba8d...0xbaa7 => true,
+ 0xbaa9...0xbac3 => true,
+ 0xbac5...0xbadf => true,
+ 0xbae1...0xbafb => true,
+ 0xbafd...0xbb17 => true,
+ 0xbb19...0xbb33 => true,
+ 0xbb35...0xbb4f => true,
+ 0xbb51...0xbb6b => true,
+ 0xbb6d...0xbb87 => true,
+ 0xbb89...0xbba3 => true,
+ 0xbba5...0xbbbf => true,
+ 0xbbc1...0xbbdb => true,
+ 0xbbdd...0xbbf7 => true,
+ 0xbbf9...0xbc13 => true,
+ 0xbc15...0xbc2f => true,
+ 0xbc31...0xbc4b => true,
+ 0xbc4d...0xbc67 => true,
+ 0xbc69...0xbc83 => true,
+ 0xbc85...0xbc9f => true,
+ 0xbca1...0xbcbb => true,
+ 0xbcbd...0xbcd7 => true,
+ 0xbcd9...0xbcf3 => true,
+ 0xbcf5...0xbd0f => true,
+ 0xbd11...0xbd2b => true,
+ 0xbd2d...0xbd47 => true,
+ 0xbd49...0xbd63 => true,
+ 0xbd65...0xbd7f => true,
+ 0xbd81...0xbd9b => true,
+ 0xbd9d...0xbdb7 => true,
+ 0xbdb9...0xbdd3 => true,
+ 0xbdd5...0xbdef => true,
+ 0xbdf1...0xbe0b => true,
+ 0xbe0d...0xbe27 => true,
+ 0xbe29...0xbe43 => true,
+ 0xbe45...0xbe5f => true,
+ 0xbe61...0xbe7b => true,
+ 0xbe7d...0xbe97 => true,
+ 0xbe99...0xbeb3 => true,
+ 0xbeb5...0xbecf => true,
+ 0xbed1...0xbeeb => true,
+ 0xbeed...0xbf07 => true,
+ 0xbf09...0xbf23 => true,
+ 0xbf25...0xbf3f => true,
+ 0xbf41...0xbf5b => true,
+ 0xbf5d...0xbf77 => true,
+ 0xbf79...0xbf93 => true,
+ 0xbf95...0xbfaf => true,
+ 0xbfb1...0xbfcb => true,
+ 0xbfcd...0xbfe7 => true,
+ 0xbfe9...0xc003 => true,
+ 0xc005...0xc01f => true,
+ 0xc021...0xc03b => true,
+ 0xc03d...0xc057 => true,
+ 0xc059...0xc073 => true,
+ 0xc075...0xc08f => true,
+ 0xc091...0xc0ab => true,
+ 0xc0ad...0xc0c7 => true,
+ 0xc0c9...0xc0e3 => true,
+ 0xc0e5...0xc0ff => true,
+ 0xc101...0xc11b => true,
+ 0xc11d...0xc137 => true,
+ 0xc139...0xc153 => true,
+ 0xc155...0xc16f => true,
+ 0xc171...0xc18b => true,
+ 0xc18d...0xc1a7 => true,
+ 0xc1a9...0xc1c3 => true,
+ 0xc1c5...0xc1df => true,
+ 0xc1e1...0xc1fb => true,
+ 0xc1fd...0xc217 => true,
+ 0xc219...0xc233 => true,
+ 0xc235...0xc24f => true,
+ 0xc251...0xc26b => true,
+ 0xc26d...0xc287 => true,
+ 0xc289...0xc2a3 => true,
+ 0xc2a5...0xc2bf => true,
+ 0xc2c1...0xc2db => true,
+ 0xc2dd...0xc2f7 => true,
+ 0xc2f9...0xc313 => true,
+ 0xc315...0xc32f => true,
+ 0xc331...0xc34b => true,
+ 0xc34d...0xc367 => true,
+ 0xc369...0xc383 => true,
+ 0xc385...0xc39f => true,
+ 0xc3a1...0xc3bb => true,
+ 0xc3bd...0xc3d7 => true,
+ 0xc3d9...0xc3f3 => true,
+ 0xc3f5...0xc40f => true,
+ 0xc411...0xc42b => true,
+ 0xc42d...0xc447 => true,
+ 0xc449...0xc463 => true,
+ 0xc465...0xc47f => true,
+ 0xc481...0xc49b => true,
+ 0xc49d...0xc4b7 => true,
+ 0xc4b9...0xc4d3 => true,
+ 0xc4d5...0xc4ef => true,
+ 0xc4f1...0xc50b => true,
+ 0xc50d...0xc527 => true,
+ 0xc529...0xc543 => true,
+ 0xc545...0xc55f => true,
+ 0xc561...0xc57b => true,
+ 0xc57d...0xc597 => true,
+ 0xc599...0xc5b3 => true,
+ 0xc5b5...0xc5cf => true,
+ 0xc5d1...0xc5eb => true,
+ 0xc5ed...0xc607 => true,
+ 0xc609...0xc623 => true,
+ 0xc625...0xc63f => true,
+ 0xc641...0xc65b => true,
+ 0xc65d...0xc677 => true,
+ 0xc679...0xc693 => true,
+ 0xc695...0xc6af => true,
+ 0xc6b1...0xc6cb => true,
+ 0xc6cd...0xc6e7 => true,
+ 0xc6e9...0xc703 => true,
+ 0xc705...0xc71f => true,
+ 0xc721...0xc73b => true,
+ 0xc73d...0xc757 => true,
+ 0xc759...0xc773 => true,
+ 0xc775...0xc78f => true,
+ 0xc791...0xc7ab => true,
+ 0xc7ad...0xc7c7 => true,
+ 0xc7c9...0xc7e3 => true,
+ 0xc7e5...0xc7ff => true,
+ 0xc801...0xc81b => true,
+ 0xc81d...0xc837 => true,
+ 0xc839...0xc853 => true,
+ 0xc855...0xc86f => true,
+ 0xc871...0xc88b => true,
+ 0xc88d...0xc8a7 => true,
+ 0xc8a9...0xc8c3 => true,
+ 0xc8c5...0xc8df => true,
+ 0xc8e1...0xc8fb => true,
+ 0xc8fd...0xc917 => true,
+ 0xc919...0xc933 => true,
+ 0xc935...0xc94f => true,
+ 0xc951...0xc96b => true,
+ 0xc96d...0xc987 => true,
+ 0xc989...0xc9a3 => true,
+ 0xc9a5...0xc9bf => true,
+ 0xc9c1...0xc9db => true,
+ 0xc9dd...0xc9f7 => true,
+ 0xc9f9...0xca13 => true,
+ 0xca15...0xca2f => true,
+ 0xca31...0xca4b => true,
+ 0xca4d...0xca67 => true,
+ 0xca69...0xca83 => true,
+ 0xca85...0xca9f => true,
+ 0xcaa1...0xcabb => true,
+ 0xcabd...0xcad7 => true,
+ 0xcad9...0xcaf3 => true,
+ 0xcaf5...0xcb0f => true,
+ 0xcb11...0xcb2b => true,
+ 0xcb2d...0xcb47 => true,
+ 0xcb49...0xcb63 => true,
+ 0xcb65...0xcb7f => true,
+ 0xcb81...0xcb9b => true,
+ 0xcb9d...0xcbb7 => true,
+ 0xcbb9...0xcbd3 => true,
+ 0xcbd5...0xcbef => true,
+ 0xcbf1...0xcc0b => true,
+ 0xcc0d...0xcc27 => true,
+ 0xcc29...0xcc43 => true,
+ 0xcc45...0xcc5f => true,
+ 0xcc61...0xcc7b => true,
+ 0xcc7d...0xcc97 => true,
+ 0xcc99...0xccb3 => true,
+ 0xccb5...0xcccf => true,
+ 0xccd1...0xcceb => true,
+ 0xcced...0xcd07 => true,
+ 0xcd09...0xcd23 => true,
+ 0xcd25...0xcd3f => true,
+ 0xcd41...0xcd5b => true,
+ 0xcd5d...0xcd77 => true,
+ 0xcd79...0xcd93 => true,
+ 0xcd95...0xcdaf => true,
+ 0xcdb1...0xcdcb => true,
+ 0xcdcd...0xcde7 => true,
+ 0xcde9...0xce03 => true,
+ 0xce05...0xce1f => true,
+ 0xce21...0xce3b => true,
+ 0xce3d...0xce57 => true,
+ 0xce59...0xce73 => true,
+ 0xce75...0xce8f => true,
+ 0xce91...0xceab => true,
+ 0xcead...0xcec7 => true,
+ 0xcec9...0xcee3 => true,
+ 0xcee5...0xceff => true,
+ 0xcf01...0xcf1b => true,
+ 0xcf1d...0xcf37 => true,
+ 0xcf39...0xcf53 => true,
+ 0xcf55...0xcf6f => true,
+ 0xcf71...0xcf8b => true,
+ 0xcf8d...0xcfa7 => true,
+ 0xcfa9...0xcfc3 => true,
+ 0xcfc5...0xcfdf => true,
+ 0xcfe1...0xcffb => true,
+ 0xcffd...0xd017 => true,
+ 0xd019...0xd033 => true,
+ 0xd035...0xd04f => true,
+ 0xd051...0xd06b => true,
+ 0xd06d...0xd087 => true,
+ 0xd089...0xd0a3 => true,
+ 0xd0a5...0xd0bf => true,
+ 0xd0c1...0xd0db => true,
+ 0xd0dd...0xd0f7 => true,
+ 0xd0f9...0xd113 => true,
+ 0xd115...0xd12f => true,
+ 0xd131...0xd14b => true,
+ 0xd14d...0xd167 => true,
+ 0xd169...0xd183 => true,
+ 0xd185...0xd19f => true,
+ 0xd1a1...0xd1bb => true,
+ 0xd1bd...0xd1d7 => true,
+ 0xd1d9...0xd1f3 => true,
+ 0xd1f5...0xd20f => true,
+ 0xd211...0xd22b => true,
+ 0xd22d...0xd247 => true,
+ 0xd249...0xd263 => true,
+ 0xd265...0xd27f => true,
+ 0xd281...0xd29b => true,
+ 0xd29d...0xd2b7 => true,
+ 0xd2b9...0xd2d3 => true,
+ 0xd2d5...0xd2ef => true,
+ 0xd2f1...0xd30b => true,
+ 0xd30d...0xd327 => true,
+ 0xd329...0xd343 => true,
+ 0xd345...0xd35f => true,
+ 0xd361...0xd37b => true,
+ 0xd37d...0xd397 => true,
+ 0xd399...0xd3b3 => true,
+ 0xd3b5...0xd3cf => true,
+ 0xd3d1...0xd3eb => true,
+ 0xd3ed...0xd407 => true,
+ 0xd409...0xd423 => true,
+ 0xd425...0xd43f => true,
+ 0xd441...0xd45b => true,
+ 0xd45d...0xd477 => true,
+ 0xd479...0xd493 => true,
+ 0xd495...0xd4af => true,
+ 0xd4b1...0xd4cb => true,
+ 0xd4cd...0xd4e7 => true,
+ 0xd4e9...0xd503 => true,
+ 0xd505...0xd51f => true,
+ 0xd521...0xd53b => true,
+ 0xd53d...0xd557 => true,
+ 0xd559...0xd573 => true,
+ 0xd575...0xd58f => true,
+ 0xd591...0xd5ab => true,
+ 0xd5ad...0xd5c7 => true,
+ 0xd5c9...0xd5e3 => true,
+ 0xd5e5...0xd5ff => true,
+ 0xd601...0xd61b => true,
+ 0xd61d...0xd637 => true,
+ 0xd639...0xd653 => true,
+ 0xd655...0xd66f => true,
+ 0xd671...0xd68b => true,
+ 0xd68d...0xd6a7 => true,
+ 0xd6a9...0xd6c3 => true,
+ 0xd6c5...0xd6df => true,
+ 0xd6e1...0xd6fb => true,
+ 0xd6fd...0xd717 => true,
+ 0xd719...0xd733 => true,
+ 0xd735...0xd74f => true,
+ 0xd751...0xd76b => true,
+ 0xd76d...0xd787 => true,
+ 0xd789...0xd7a3 => true,
+ else => false,
+ };
+}
+
+pub fn isZwj(cp: u21) bool {
+ return cp == 0x200d;
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/hangul_syllable_type.zig.html b/docs/src/ziglyph/autogen/hangul_syllable_type.zig.html
new file mode 100644
index 0000000..e5ee15e
--- /dev/null
+++ b/docs/src/ziglyph/autogen/hangul_syllable_type.zig.html
@@ -0,0 +1,938 @@
+
+
+
+
+
autogen/hangul_syllable_type.zig - source view
+
+
+
+
+
+
+
+
+pub const Kind = enum {
+ L,
+ LV,
+ LVT,
+ T,
+ V,
+};
+
+
+pub fn syllableType(cp: u21) ?Kind {
+ return switch (cp) {
+ 0x1100...0x115F => .L,
+ 0xA960...0xA97C => .L,
+ 0x1160...0x11A7 => .V,
+ 0xD7B0...0xD7C6 => .V,
+ 0x11A8...0x11FF => .T,
+ 0xD7CB...0xD7FB => .T,
+ 0xAC00 => .LV,
+ 0xAC1C => .LV,
+ 0xAC38 => .LV,
+ 0xAC54 => .LV,
+ 0xAC70 => .LV,
+ 0xAC8C => .LV,
+ 0xACA8 => .LV,
+ 0xACC4 => .LV,
+ 0xACE0 => .LV,
+ 0xACFC => .LV,
+ 0xAD18 => .LV,
+ 0xAD34 => .LV,
+ 0xAD50 => .LV,
+ 0xAD6C => .LV,
+ 0xAD88 => .LV,
+ 0xADA4 => .LV,
+ 0xADC0 => .LV,
+ 0xADDC => .LV,
+ 0xADF8 => .LV,
+ 0xAE14 => .LV,
+ 0xAE30 => .LV,
+ 0xAE4C => .LV,
+ 0xAE68 => .LV,
+ 0xAE84 => .LV,
+ 0xAEA0 => .LV,
+ 0xAEBC => .LV,
+ 0xAED8 => .LV,
+ 0xAEF4 => .LV,
+ 0xAF10 => .LV,
+ 0xAF2C => .LV,
+ 0xAF48 => .LV,
+ 0xAF64 => .LV,
+ 0xAF80 => .LV,
+ 0xAF9C => .LV,
+ 0xAFB8 => .LV,
+ 0xAFD4 => .LV,
+ 0xAFF0 => .LV,
+ 0xB00C => .LV,
+ 0xB028 => .LV,
+ 0xB044 => .LV,
+ 0xB060 => .LV,
+ 0xB07C => .LV,
+ 0xB098 => .LV,
+ 0xB0B4 => .LV,
+ 0xB0D0 => .LV,
+ 0xB0EC => .LV,
+ 0xB108 => .LV,
+ 0xB124 => .LV,
+ 0xB140 => .LV,
+ 0xB15C => .LV,
+ 0xB178 => .LV,
+ 0xB194 => .LV,
+ 0xB1B0 => .LV,
+ 0xB1CC => .LV,
+ 0xB1E8 => .LV,
+ 0xB204 => .LV,
+ 0xB220 => .LV,
+ 0xB23C => .LV,
+ 0xB258 => .LV,
+ 0xB274 => .LV,
+ 0xB290 => .LV,
+ 0xB2AC => .LV,
+ 0xB2C8 => .LV,
+ 0xB2E4 => .LV,
+ 0xB300 => .LV,
+ 0xB31C => .LV,
+ 0xB338 => .LV,
+ 0xB354 => .LV,
+ 0xB370 => .LV,
+ 0xB38C => .LV,
+ 0xB3A8 => .LV,
+ 0xB3C4 => .LV,
+ 0xB3E0 => .LV,
+ 0xB3FC => .LV,
+ 0xB418 => .LV,
+ 0xB434 => .LV,
+ 0xB450 => .LV,
+ 0xB46C => .LV,
+ 0xB488 => .LV,
+ 0xB4A4 => .LV,
+ 0xB4C0 => .LV,
+ 0xB4DC => .LV,
+ 0xB4F8 => .LV,
+ 0xB514 => .LV,
+ 0xB530 => .LV,
+ 0xB54C => .LV,
+ 0xB568 => .LV,
+ 0xB584 => .LV,
+ 0xB5A0 => .LV,
+ 0xB5BC => .LV,
+ 0xB5D8 => .LV,
+ 0xB5F4 => .LV,
+ 0xB610 => .LV,
+ 0xB62C => .LV,
+ 0xB648 => .LV,
+ 0xB664 => .LV,
+ 0xB680 => .LV,
+ 0xB69C => .LV,
+ 0xB6B8 => .LV,
+ 0xB6D4 => .LV,
+ 0xB6F0 => .LV,
+ 0xB70C => .LV,
+ 0xB728 => .LV,
+ 0xB744 => .LV,
+ 0xB760 => .LV,
+ 0xB77C => .LV,
+ 0xB798 => .LV,
+ 0xB7B4 => .LV,
+ 0xB7D0 => .LV,
+ 0xB7EC => .LV,
+ 0xB808 => .LV,
+ 0xB824 => .LV,
+ 0xB840 => .LV,
+ 0xB85C => .LV,
+ 0xB878 => .LV,
+ 0xB894 => .LV,
+ 0xB8B0 => .LV,
+ 0xB8CC => .LV,
+ 0xB8E8 => .LV,
+ 0xB904 => .LV,
+ 0xB920 => .LV,
+ 0xB93C => .LV,
+ 0xB958 => .LV,
+ 0xB974 => .LV,
+ 0xB990 => .LV,
+ 0xB9AC => .LV,
+ 0xB9C8 => .LV,
+ 0xB9E4 => .LV,
+ 0xBA00 => .LV,
+ 0xBA1C => .LV,
+ 0xBA38 => .LV,
+ 0xBA54 => .LV,
+ 0xBA70 => .LV,
+ 0xBA8C => .LV,
+ 0xBAA8 => .LV,
+ 0xBAC4 => .LV,
+ 0xBAE0 => .LV,
+ 0xBAFC => .LV,
+ 0xBB18 => .LV,
+ 0xBB34 => .LV,
+ 0xBB50 => .LV,
+ 0xBB6C => .LV,
+ 0xBB88 => .LV,
+ 0xBBA4 => .LV,
+ 0xBBC0 => .LV,
+ 0xBBDC => .LV,
+ 0xBBF8 => .LV,
+ 0xBC14 => .LV,
+ 0xBC30 => .LV,
+ 0xBC4C => .LV,
+ 0xBC68 => .LV,
+ 0xBC84 => .LV,
+ 0xBCA0 => .LV,
+ 0xBCBC => .LV,
+ 0xBCD8 => .LV,
+ 0xBCF4 => .LV,
+ 0xBD10 => .LV,
+ 0xBD2C => .LV,
+ 0xBD48 => .LV,
+ 0xBD64 => .LV,
+ 0xBD80 => .LV,
+ 0xBD9C => .LV,
+ 0xBDB8 => .LV,
+ 0xBDD4 => .LV,
+ 0xBDF0 => .LV,
+ 0xBE0C => .LV,
+ 0xBE28 => .LV,
+ 0xBE44 => .LV,
+ 0xBE60 => .LV,
+ 0xBE7C => .LV,
+ 0xBE98 => .LV,
+ 0xBEB4 => .LV,
+ 0xBED0 => .LV,
+ 0xBEEC => .LV,
+ 0xBF08 => .LV,
+ 0xBF24 => .LV,
+ 0xBF40 => .LV,
+ 0xBF5C => .LV,
+ 0xBF78 => .LV,
+ 0xBF94 => .LV,
+ 0xBFB0 => .LV,
+ 0xBFCC => .LV,
+ 0xBFE8 => .LV,
+ 0xC004 => .LV,
+ 0xC020 => .LV,
+ 0xC03C => .LV,
+ 0xC058 => .LV,
+ 0xC074 => .LV,
+ 0xC090 => .LV,
+ 0xC0AC => .LV,
+ 0xC0C8 => .LV,
+ 0xC0E4 => .LV,
+ 0xC100 => .LV,
+ 0xC11C => .LV,
+ 0xC138 => .LV,
+ 0xC154 => .LV,
+ 0xC170 => .LV,
+ 0xC18C => .LV,
+ 0xC1A8 => .LV,
+ 0xC1C4 => .LV,
+ 0xC1E0 => .LV,
+ 0xC1FC => .LV,
+ 0xC218 => .LV,
+ 0xC234 => .LV,
+ 0xC250 => .LV,
+ 0xC26C => .LV,
+ 0xC288 => .LV,
+ 0xC2A4 => .LV,
+ 0xC2C0 => .LV,
+ 0xC2DC => .LV,
+ 0xC2F8 => .LV,
+ 0xC314 => .LV,
+ 0xC330 => .LV,
+ 0xC34C => .LV,
+ 0xC368 => .LV,
+ 0xC384 => .LV,
+ 0xC3A0 => .LV,
+ 0xC3BC => .LV,
+ 0xC3D8 => .LV,
+ 0xC3F4 => .LV,
+ 0xC410 => .LV,
+ 0xC42C => .LV,
+ 0xC448 => .LV,
+ 0xC464 => .LV,
+ 0xC480 => .LV,
+ 0xC49C => .LV,
+ 0xC4B8 => .LV,
+ 0xC4D4 => .LV,
+ 0xC4F0 => .LV,
+ 0xC50C => .LV,
+ 0xC528 => .LV,
+ 0xC544 => .LV,
+ 0xC560 => .LV,
+ 0xC57C => .LV,
+ 0xC598 => .LV,
+ 0xC5B4 => .LV,
+ 0xC5D0 => .LV,
+ 0xC5EC => .LV,
+ 0xC608 => .LV,
+ 0xC624 => .LV,
+ 0xC640 => .LV,
+ 0xC65C => .LV,
+ 0xC678 => .LV,
+ 0xC694 => .LV,
+ 0xC6B0 => .LV,
+ 0xC6CC => .LV,
+ 0xC6E8 => .LV,
+ 0xC704 => .LV,
+ 0xC720 => .LV,
+ 0xC73C => .LV,
+ 0xC758 => .LV,
+ 0xC774 => .LV,
+ 0xC790 => .LV,
+ 0xC7AC => .LV,
+ 0xC7C8 => .LV,
+ 0xC7E4 => .LV,
+ 0xC800 => .LV,
+ 0xC81C => .LV,
+ 0xC838 => .LV,
+ 0xC854 => .LV,
+ 0xC870 => .LV,
+ 0xC88C => .LV,
+ 0xC8A8 => .LV,
+ 0xC8C4 => .LV,
+ 0xC8E0 => .LV,
+ 0xC8FC => .LV,
+ 0xC918 => .LV,
+ 0xC934 => .LV,
+ 0xC950 => .LV,
+ 0xC96C => .LV,
+ 0xC988 => .LV,
+ 0xC9A4 => .LV,
+ 0xC9C0 => .LV,
+ 0xC9DC => .LV,
+ 0xC9F8 => .LV,
+ 0xCA14 => .LV,
+ 0xCA30 => .LV,
+ 0xCA4C => .LV,
+ 0xCA68 => .LV,
+ 0xCA84 => .LV,
+ 0xCAA0 => .LV,
+ 0xCABC => .LV,
+ 0xCAD8 => .LV,
+ 0xCAF4 => .LV,
+ 0xCB10 => .LV,
+ 0xCB2C => .LV,
+ 0xCB48 => .LV,
+ 0xCB64 => .LV,
+ 0xCB80 => .LV,
+ 0xCB9C => .LV,
+ 0xCBB8 => .LV,
+ 0xCBD4 => .LV,
+ 0xCBF0 => .LV,
+ 0xCC0C => .LV,
+ 0xCC28 => .LV,
+ 0xCC44 => .LV,
+ 0xCC60 => .LV,
+ 0xCC7C => .LV,
+ 0xCC98 => .LV,
+ 0xCCB4 => .LV,
+ 0xCCD0 => .LV,
+ 0xCCEC => .LV,
+ 0xCD08 => .LV,
+ 0xCD24 => .LV,
+ 0xCD40 => .LV,
+ 0xCD5C => .LV,
+ 0xCD78 => .LV,
+ 0xCD94 => .LV,
+ 0xCDB0 => .LV,
+ 0xCDCC => .LV,
+ 0xCDE8 => .LV,
+ 0xCE04 => .LV,
+ 0xCE20 => .LV,
+ 0xCE3C => .LV,
+ 0xCE58 => .LV,
+ 0xCE74 => .LV,
+ 0xCE90 => .LV,
+ 0xCEAC => .LV,
+ 0xCEC8 => .LV,
+ 0xCEE4 => .LV,
+ 0xCF00 => .LV,
+ 0xCF1C => .LV,
+ 0xCF38 => .LV,
+ 0xCF54 => .LV,
+ 0xCF70 => .LV,
+ 0xCF8C => .LV,
+ 0xCFA8 => .LV,
+ 0xCFC4 => .LV,
+ 0xCFE0 => .LV,
+ 0xCFFC => .LV,
+ 0xD018 => .LV,
+ 0xD034 => .LV,
+ 0xD050 => .LV,
+ 0xD06C => .LV,
+ 0xD088 => .LV,
+ 0xD0A4 => .LV,
+ 0xD0C0 => .LV,
+ 0xD0DC => .LV,
+ 0xD0F8 => .LV,
+ 0xD114 => .LV,
+ 0xD130 => .LV,
+ 0xD14C => .LV,
+ 0xD168 => .LV,
+ 0xD184 => .LV,
+ 0xD1A0 => .LV,
+ 0xD1BC => .LV,
+ 0xD1D8 => .LV,
+ 0xD1F4 => .LV,
+ 0xD210 => .LV,
+ 0xD22C => .LV,
+ 0xD248 => .LV,
+ 0xD264 => .LV,
+ 0xD280 => .LV,
+ 0xD29C => .LV,
+ 0xD2B8 => .LV,
+ 0xD2D4 => .LV,
+ 0xD2F0 => .LV,
+ 0xD30C => .LV,
+ 0xD328 => .LV,
+ 0xD344 => .LV,
+ 0xD360 => .LV,
+ 0xD37C => .LV,
+ 0xD398 => .LV,
+ 0xD3B4 => .LV,
+ 0xD3D0 => .LV,
+ 0xD3EC => .LV,
+ 0xD408 => .LV,
+ 0xD424 => .LV,
+ 0xD440 => .LV,
+ 0xD45C => .LV,
+ 0xD478 => .LV,
+ 0xD494 => .LV,
+ 0xD4B0 => .LV,
+ 0xD4CC => .LV,
+ 0xD4E8 => .LV,
+ 0xD504 => .LV,
+ 0xD520 => .LV,
+ 0xD53C => .LV,
+ 0xD558 => .LV,
+ 0xD574 => .LV,
+ 0xD590 => .LV,
+ 0xD5AC => .LV,
+ 0xD5C8 => .LV,
+ 0xD5E4 => .LV,
+ 0xD600 => .LV,
+ 0xD61C => .LV,
+ 0xD638 => .LV,
+ 0xD654 => .LV,
+ 0xD670 => .LV,
+ 0xD68C => .LV,
+ 0xD6A8 => .LV,
+ 0xD6C4 => .LV,
+ 0xD6E0 => .LV,
+ 0xD6FC => .LV,
+ 0xD718 => .LV,
+ 0xD734 => .LV,
+ 0xD750 => .LV,
+ 0xD76C => .LV,
+ 0xD788 => .LV,
+ 0xAC01...0xAC1B => .LVT,
+ 0xAC1D...0xAC37 => .LVT,
+ 0xAC39...0xAC53 => .LVT,
+ 0xAC55...0xAC6F => .LVT,
+ 0xAC71...0xAC8B => .LVT,
+ 0xAC8D...0xACA7 => .LVT,
+ 0xACA9...0xACC3 => .LVT,
+ 0xACC5...0xACDF => .LVT,
+ 0xACE1...0xACFB => .LVT,
+ 0xACFD...0xAD17 => .LVT,
+ 0xAD19...0xAD33 => .LVT,
+ 0xAD35...0xAD4F => .LVT,
+ 0xAD51...0xAD6B => .LVT,
+ 0xAD6D...0xAD87 => .LVT,
+ 0xAD89...0xADA3 => .LVT,
+ 0xADA5...0xADBF => .LVT,
+ 0xADC1...0xADDB => .LVT,
+ 0xADDD...0xADF7 => .LVT,
+ 0xADF9...0xAE13 => .LVT,
+ 0xAE15...0xAE2F => .LVT,
+ 0xAE31...0xAE4B => .LVT,
+ 0xAE4D...0xAE67 => .LVT,
+ 0xAE69...0xAE83 => .LVT,
+ 0xAE85...0xAE9F => .LVT,
+ 0xAEA1...0xAEBB => .LVT,
+ 0xAEBD...0xAED7 => .LVT,
+ 0xAED9...0xAEF3 => .LVT,
+ 0xAEF5...0xAF0F => .LVT,
+ 0xAF11...0xAF2B => .LVT,
+ 0xAF2D...0xAF47 => .LVT,
+ 0xAF49...0xAF63 => .LVT,
+ 0xAF65...0xAF7F => .LVT,
+ 0xAF81...0xAF9B => .LVT,
+ 0xAF9D...0xAFB7 => .LVT,
+ 0xAFB9...0xAFD3 => .LVT,
+ 0xAFD5...0xAFEF => .LVT,
+ 0xAFF1...0xB00B => .LVT,
+ 0xB00D...0xB027 => .LVT,
+ 0xB029...0xB043 => .LVT,
+ 0xB045...0xB05F => .LVT,
+ 0xB061...0xB07B => .LVT,
+ 0xB07D...0xB097 => .LVT,
+ 0xB099...0xB0B3 => .LVT,
+ 0xB0B5...0xB0CF => .LVT,
+ 0xB0D1...0xB0EB => .LVT,
+ 0xB0ED...0xB107 => .LVT,
+ 0xB109...0xB123 => .LVT,
+ 0xB125...0xB13F => .LVT,
+ 0xB141...0xB15B => .LVT,
+ 0xB15D...0xB177 => .LVT,
+ 0xB179...0xB193 => .LVT,
+ 0xB195...0xB1AF => .LVT,
+ 0xB1B1...0xB1CB => .LVT,
+ 0xB1CD...0xB1E7 => .LVT,
+ 0xB1E9...0xB203 => .LVT,
+ 0xB205...0xB21F => .LVT,
+ 0xB221...0xB23B => .LVT,
+ 0xB23D...0xB257 => .LVT,
+ 0xB259...0xB273 => .LVT,
+ 0xB275...0xB28F => .LVT,
+ 0xB291...0xB2AB => .LVT,
+ 0xB2AD...0xB2C7 => .LVT,
+ 0xB2C9...0xB2E3 => .LVT,
+ 0xB2E5...0xB2FF => .LVT,
+ 0xB301...0xB31B => .LVT,
+ 0xB31D...0xB337 => .LVT,
+ 0xB339...0xB353 => .LVT,
+ 0xB355...0xB36F => .LVT,
+ 0xB371...0xB38B => .LVT,
+ 0xB38D...0xB3A7 => .LVT,
+ 0xB3A9...0xB3C3 => .LVT,
+ 0xB3C5...0xB3DF => .LVT,
+ 0xB3E1...0xB3FB => .LVT,
+ 0xB3FD...0xB417 => .LVT,
+ 0xB419...0xB433 => .LVT,
+ 0xB435...0xB44F => .LVT,
+ 0xB451...0xB46B => .LVT,
+ 0xB46D...0xB487 => .LVT,
+ 0xB489...0xB4A3 => .LVT,
+ 0xB4A5...0xB4BF => .LVT,
+ 0xB4C1...0xB4DB => .LVT,
+ 0xB4DD...0xB4F7 => .LVT,
+ 0xB4F9...0xB513 => .LVT,
+ 0xB515...0xB52F => .LVT,
+ 0xB531...0xB54B => .LVT,
+ 0xB54D...0xB567 => .LVT,
+ 0xB569...0xB583 => .LVT,
+ 0xB585...0xB59F => .LVT,
+ 0xB5A1...0xB5BB => .LVT,
+ 0xB5BD...0xB5D7 => .LVT,
+ 0xB5D9...0xB5F3 => .LVT,
+ 0xB5F5...0xB60F => .LVT,
+ 0xB611...0xB62B => .LVT,
+ 0xB62D...0xB647 => .LVT,
+ 0xB649...0xB663 => .LVT,
+ 0xB665...0xB67F => .LVT,
+ 0xB681...0xB69B => .LVT,
+ 0xB69D...0xB6B7 => .LVT,
+ 0xB6B9...0xB6D3 => .LVT,
+ 0xB6D5...0xB6EF => .LVT,
+ 0xB6F1...0xB70B => .LVT,
+ 0xB70D...0xB727 => .LVT,
+ 0xB729...0xB743 => .LVT,
+ 0xB745...0xB75F => .LVT,
+ 0xB761...0xB77B => .LVT,
+ 0xB77D...0xB797 => .LVT,
+ 0xB799...0xB7B3 => .LVT,
+ 0xB7B5...0xB7CF => .LVT,
+ 0xB7D1...0xB7EB => .LVT,
+ 0xB7ED...0xB807 => .LVT,
+ 0xB809...0xB823 => .LVT,
+ 0xB825...0xB83F => .LVT,
+ 0xB841...0xB85B => .LVT,
+ 0xB85D...0xB877 => .LVT,
+ 0xB879...0xB893 => .LVT,
+ 0xB895...0xB8AF => .LVT,
+ 0xB8B1...0xB8CB => .LVT,
+ 0xB8CD...0xB8E7 => .LVT,
+ 0xB8E9...0xB903 => .LVT,
+ 0xB905...0xB91F => .LVT,
+ 0xB921...0xB93B => .LVT,
+ 0xB93D...0xB957 => .LVT,
+ 0xB959...0xB973 => .LVT,
+ 0xB975...0xB98F => .LVT,
+ 0xB991...0xB9AB => .LVT,
+ 0xB9AD...0xB9C7 => .LVT,
+ 0xB9C9...0xB9E3 => .LVT,
+ 0xB9E5...0xB9FF => .LVT,
+ 0xBA01...0xBA1B => .LVT,
+ 0xBA1D...0xBA37 => .LVT,
+ 0xBA39...0xBA53 => .LVT,
+ 0xBA55...0xBA6F => .LVT,
+ 0xBA71...0xBA8B => .LVT,
+ 0xBA8D...0xBAA7 => .LVT,
+ 0xBAA9...0xBAC3 => .LVT,
+ 0xBAC5...0xBADF => .LVT,
+ 0xBAE1...0xBAFB => .LVT,
+ 0xBAFD...0xBB17 => .LVT,
+ 0xBB19...0xBB33 => .LVT,
+ 0xBB35...0xBB4F => .LVT,
+ 0xBB51...0xBB6B => .LVT,
+ 0xBB6D...0xBB87 => .LVT,
+ 0xBB89...0xBBA3 => .LVT,
+ 0xBBA5...0xBBBF => .LVT,
+ 0xBBC1...0xBBDB => .LVT,
+ 0xBBDD...0xBBF7 => .LVT,
+ 0xBBF9...0xBC13 => .LVT,
+ 0xBC15...0xBC2F => .LVT,
+ 0xBC31...0xBC4B => .LVT,
+ 0xBC4D...0xBC67 => .LVT,
+ 0xBC69...0xBC83 => .LVT,
+ 0xBC85...0xBC9F => .LVT,
+ 0xBCA1...0xBCBB => .LVT,
+ 0xBCBD...0xBCD7 => .LVT,
+ 0xBCD9...0xBCF3 => .LVT,
+ 0xBCF5...0xBD0F => .LVT,
+ 0xBD11...0xBD2B => .LVT,
+ 0xBD2D...0xBD47 => .LVT,
+ 0xBD49...0xBD63 => .LVT,
+ 0xBD65...0xBD7F => .LVT,
+ 0xBD81...0xBD9B => .LVT,
+ 0xBD9D...0xBDB7 => .LVT,
+ 0xBDB9...0xBDD3 => .LVT,
+ 0xBDD5...0xBDEF => .LVT,
+ 0xBDF1...0xBE0B => .LVT,
+ 0xBE0D...0xBE27 => .LVT,
+ 0xBE29...0xBE43 => .LVT,
+ 0xBE45...0xBE5F => .LVT,
+ 0xBE61...0xBE7B => .LVT,
+ 0xBE7D...0xBE97 => .LVT,
+ 0xBE99...0xBEB3 => .LVT,
+ 0xBEB5...0xBECF => .LVT,
+ 0xBED1...0xBEEB => .LVT,
+ 0xBEED...0xBF07 => .LVT,
+ 0xBF09...0xBF23 => .LVT,
+ 0xBF25...0xBF3F => .LVT,
+ 0xBF41...0xBF5B => .LVT,
+ 0xBF5D...0xBF77 => .LVT,
+ 0xBF79...0xBF93 => .LVT,
+ 0xBF95...0xBFAF => .LVT,
+ 0xBFB1...0xBFCB => .LVT,
+ 0xBFCD...0xBFE7 => .LVT,
+ 0xBFE9...0xC003 => .LVT,
+ 0xC005...0xC01F => .LVT,
+ 0xC021...0xC03B => .LVT,
+ 0xC03D...0xC057 => .LVT,
+ 0xC059...0xC073 => .LVT,
+ 0xC075...0xC08F => .LVT,
+ 0xC091...0xC0AB => .LVT,
+ 0xC0AD...0xC0C7 => .LVT,
+ 0xC0C9...0xC0E3 => .LVT,
+ 0xC0E5...0xC0FF => .LVT,
+ 0xC101...0xC11B => .LVT,
+ 0xC11D...0xC137 => .LVT,
+ 0xC139...0xC153 => .LVT,
+ 0xC155...0xC16F => .LVT,
+ 0xC171...0xC18B => .LVT,
+ 0xC18D...0xC1A7 => .LVT,
+ 0xC1A9...0xC1C3 => .LVT,
+ 0xC1C5...0xC1DF => .LVT,
+ 0xC1E1...0xC1FB => .LVT,
+ 0xC1FD...0xC217 => .LVT,
+ 0xC219...0xC233 => .LVT,
+ 0xC235...0xC24F => .LVT,
+ 0xC251...0xC26B => .LVT,
+ 0xC26D...0xC287 => .LVT,
+ 0xC289...0xC2A3 => .LVT,
+ 0xC2A5...0xC2BF => .LVT,
+ 0xC2C1...0xC2DB => .LVT,
+ 0xC2DD...0xC2F7 => .LVT,
+ 0xC2F9...0xC313 => .LVT,
+ 0xC315...0xC32F => .LVT,
+ 0xC331...0xC34B => .LVT,
+ 0xC34D...0xC367 => .LVT,
+ 0xC369...0xC383 => .LVT,
+ 0xC385...0xC39F => .LVT,
+ 0xC3A1...0xC3BB => .LVT,
+ 0xC3BD...0xC3D7 => .LVT,
+ 0xC3D9...0xC3F3 => .LVT,
+ 0xC3F5...0xC40F => .LVT,
+ 0xC411...0xC42B => .LVT,
+ 0xC42D...0xC447 => .LVT,
+ 0xC449...0xC463 => .LVT,
+ 0xC465...0xC47F => .LVT,
+ 0xC481...0xC49B => .LVT,
+ 0xC49D...0xC4B7 => .LVT,
+ 0xC4B9...0xC4D3 => .LVT,
+ 0xC4D5...0xC4EF => .LVT,
+ 0xC4F1...0xC50B => .LVT,
+ 0xC50D...0xC527 => .LVT,
+ 0xC529...0xC543 => .LVT,
+ 0xC545...0xC55F => .LVT,
+ 0xC561...0xC57B => .LVT,
+ 0xC57D...0xC597 => .LVT,
+ 0xC599...0xC5B3 => .LVT,
+ 0xC5B5...0xC5CF => .LVT,
+ 0xC5D1...0xC5EB => .LVT,
+ 0xC5ED...0xC607 => .LVT,
+ 0xC609...0xC623 => .LVT,
+ 0xC625...0xC63F => .LVT,
+ 0xC641...0xC65B => .LVT,
+ 0xC65D...0xC677 => .LVT,
+ 0xC679...0xC693 => .LVT,
+ 0xC695...0xC6AF => .LVT,
+ 0xC6B1...0xC6CB => .LVT,
+ 0xC6CD...0xC6E7 => .LVT,
+ 0xC6E9...0xC703 => .LVT,
+ 0xC705...0xC71F => .LVT,
+ 0xC721...0xC73B => .LVT,
+ 0xC73D...0xC757 => .LVT,
+ 0xC759...0xC773 => .LVT,
+ 0xC775...0xC78F => .LVT,
+ 0xC791...0xC7AB => .LVT,
+ 0xC7AD...0xC7C7 => .LVT,
+ 0xC7C9...0xC7E3 => .LVT,
+ 0xC7E5...0xC7FF => .LVT,
+ 0xC801...0xC81B => .LVT,
+ 0xC81D...0xC837 => .LVT,
+ 0xC839...0xC853 => .LVT,
+ 0xC855...0xC86F => .LVT,
+ 0xC871...0xC88B => .LVT,
+ 0xC88D...0xC8A7 => .LVT,
+ 0xC8A9...0xC8C3 => .LVT,
+ 0xC8C5...0xC8DF => .LVT,
+ 0xC8E1...0xC8FB => .LVT,
+ 0xC8FD...0xC917 => .LVT,
+ 0xC919...0xC933 => .LVT,
+ 0xC935...0xC94F => .LVT,
+ 0xC951...0xC96B => .LVT,
+ 0xC96D...0xC987 => .LVT,
+ 0xC989...0xC9A3 => .LVT,
+ 0xC9A5...0xC9BF => .LVT,
+ 0xC9C1...0xC9DB => .LVT,
+ 0xC9DD...0xC9F7 => .LVT,
+ 0xC9F9...0xCA13 => .LVT,
+ 0xCA15...0xCA2F => .LVT,
+ 0xCA31...0xCA4B => .LVT,
+ 0xCA4D...0xCA67 => .LVT,
+ 0xCA69...0xCA83 => .LVT,
+ 0xCA85...0xCA9F => .LVT,
+ 0xCAA1...0xCABB => .LVT,
+ 0xCABD...0xCAD7 => .LVT,
+ 0xCAD9...0xCAF3 => .LVT,
+ 0xCAF5...0xCB0F => .LVT,
+ 0xCB11...0xCB2B => .LVT,
+ 0xCB2D...0xCB47 => .LVT,
+ 0xCB49...0xCB63 => .LVT,
+ 0xCB65...0xCB7F => .LVT,
+ 0xCB81...0xCB9B => .LVT,
+ 0xCB9D...0xCBB7 => .LVT,
+ 0xCBB9...0xCBD3 => .LVT,
+ 0xCBD5...0xCBEF => .LVT,
+ 0xCBF1...0xCC0B => .LVT,
+ 0xCC0D...0xCC27 => .LVT,
+ 0xCC29...0xCC43 => .LVT,
+ 0xCC45...0xCC5F => .LVT,
+ 0xCC61...0xCC7B => .LVT,
+ 0xCC7D...0xCC97 => .LVT,
+ 0xCC99...0xCCB3 => .LVT,
+ 0xCCB5...0xCCCF => .LVT,
+ 0xCCD1...0xCCEB => .LVT,
+ 0xCCED...0xCD07 => .LVT,
+ 0xCD09...0xCD23 => .LVT,
+ 0xCD25...0xCD3F => .LVT,
+ 0xCD41...0xCD5B => .LVT,
+ 0xCD5D...0xCD77 => .LVT,
+ 0xCD79...0xCD93 => .LVT,
+ 0xCD95...0xCDAF => .LVT,
+ 0xCDB1...0xCDCB => .LVT,
+ 0xCDCD...0xCDE7 => .LVT,
+ 0xCDE9...0xCE03 => .LVT,
+ 0xCE05...0xCE1F => .LVT,
+ 0xCE21...0xCE3B => .LVT,
+ 0xCE3D...0xCE57 => .LVT,
+ 0xCE59...0xCE73 => .LVT,
+ 0xCE75...0xCE8F => .LVT,
+ 0xCE91...0xCEAB => .LVT,
+ 0xCEAD...0xCEC7 => .LVT,
+ 0xCEC9...0xCEE3 => .LVT,
+ 0xCEE5...0xCEFF => .LVT,
+ 0xCF01...0xCF1B => .LVT,
+ 0xCF1D...0xCF37 => .LVT,
+ 0xCF39...0xCF53 => .LVT,
+ 0xCF55...0xCF6F => .LVT,
+ 0xCF71...0xCF8B => .LVT,
+ 0xCF8D...0xCFA7 => .LVT,
+ 0xCFA9...0xCFC3 => .LVT,
+ 0xCFC5...0xCFDF => .LVT,
+ 0xCFE1...0xCFFB => .LVT,
+ 0xCFFD...0xD017 => .LVT,
+ 0xD019...0xD033 => .LVT,
+ 0xD035...0xD04F => .LVT,
+ 0xD051...0xD06B => .LVT,
+ 0xD06D...0xD087 => .LVT,
+ 0xD089...0xD0A3 => .LVT,
+ 0xD0A5...0xD0BF => .LVT,
+ 0xD0C1...0xD0DB => .LVT,
+ 0xD0DD...0xD0F7 => .LVT,
+ 0xD0F9...0xD113 => .LVT,
+ 0xD115...0xD12F => .LVT,
+ 0xD131...0xD14B => .LVT,
+ 0xD14D...0xD167 => .LVT,
+ 0xD169...0xD183 => .LVT,
+ 0xD185...0xD19F => .LVT,
+ 0xD1A1...0xD1BB => .LVT,
+ 0xD1BD...0xD1D7 => .LVT,
+ 0xD1D9...0xD1F3 => .LVT,
+ 0xD1F5...0xD20F => .LVT,
+ 0xD211...0xD22B => .LVT,
+ 0xD22D...0xD247 => .LVT,
+ 0xD249...0xD263 => .LVT,
+ 0xD265...0xD27F => .LVT,
+ 0xD281...0xD29B => .LVT,
+ 0xD29D...0xD2B7 => .LVT,
+ 0xD2B9...0xD2D3 => .LVT,
+ 0xD2D5...0xD2EF => .LVT,
+ 0xD2F1...0xD30B => .LVT,
+ 0xD30D...0xD327 => .LVT,
+ 0xD329...0xD343 => .LVT,
+ 0xD345...0xD35F => .LVT,
+ 0xD361...0xD37B => .LVT,
+ 0xD37D...0xD397 => .LVT,
+ 0xD399...0xD3B3 => .LVT,
+ 0xD3B5...0xD3CF => .LVT,
+ 0xD3D1...0xD3EB => .LVT,
+ 0xD3ED...0xD407 => .LVT,
+ 0xD409...0xD423 => .LVT,
+ 0xD425...0xD43F => .LVT,
+ 0xD441...0xD45B => .LVT,
+ 0xD45D...0xD477 => .LVT,
+ 0xD479...0xD493 => .LVT,
+ 0xD495...0xD4AF => .LVT,
+ 0xD4B1...0xD4CB => .LVT,
+ 0xD4CD...0xD4E7 => .LVT,
+ 0xD4E9...0xD503 => .LVT,
+ 0xD505...0xD51F => .LVT,
+ 0xD521...0xD53B => .LVT,
+ 0xD53D...0xD557 => .LVT,
+ 0xD559...0xD573 => .LVT,
+ 0xD575...0xD58F => .LVT,
+ 0xD591...0xD5AB => .LVT,
+ 0xD5AD...0xD5C7 => .LVT,
+ 0xD5C9...0xD5E3 => .LVT,
+ 0xD5E5...0xD5FF => .LVT,
+ 0xD601...0xD61B => .LVT,
+ 0xD61D...0xD637 => .LVT,
+ 0xD639...0xD653 => .LVT,
+ 0xD655...0xD66F => .LVT,
+ 0xD671...0xD68B => .LVT,
+ 0xD68D...0xD6A7 => .LVT,
+ 0xD6A9...0xD6C3 => .LVT,
+ 0xD6C5...0xD6DF => .LVT,
+ 0xD6E1...0xD6FB => .LVT,
+ 0xD6FD...0xD717 => .LVT,
+ 0xD719...0xD733 => .LVT,
+ 0xD735...0xD74F => .LVT,
+ 0xD751...0xD76B => .LVT,
+ 0xD76D...0xD787 => .LVT,
+ 0xD789...0xD7A3 => .LVT,
+ else => null,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/lower_map.zig.html b/docs/src/ziglyph/autogen/lower_map.zig.html
new file mode 100644
index 0000000..4c5f6eb
--- /dev/null
+++ b/docs/src/ziglyph/autogen/lower_map.zig.html
@@ -0,0 +1,1558 @@
+
+
+
+
+
autogen/lower_map.zig - source view
+
+
+
+
+
+
+
+
+pub fn toLower(cp: u21) u21 {
+ return switch (cp) {
+ 0x41 => 0x61,
+ 0x42 => 0x62,
+ 0x43 => 0x63,
+ 0x44 => 0x64,
+ 0x45 => 0x65,
+ 0x46 => 0x66,
+ 0x47 => 0x67,
+ 0x48 => 0x68,
+ 0x49 => 0x69,
+ 0x4A => 0x6A,
+ 0x4B => 0x6B,
+ 0x4C => 0x6C,
+ 0x4D => 0x6D,
+ 0x4E => 0x6E,
+ 0x4F => 0x6F,
+ 0x50 => 0x70,
+ 0x51 => 0x71,
+ 0x52 => 0x72,
+ 0x53 => 0x73,
+ 0x54 => 0x74,
+ 0x55 => 0x75,
+ 0x56 => 0x76,
+ 0x57 => 0x77,
+ 0x58 => 0x78,
+ 0x59 => 0x79,
+ 0x5A => 0x7A,
+ 0xC0 => 0xE0,
+ 0xC1 => 0xE1,
+ 0xC2 => 0xE2,
+ 0xC3 => 0xE3,
+ 0xC4 => 0xE4,
+ 0xC5 => 0xE5,
+ 0xC6 => 0xE6,
+ 0xC7 => 0xE7,
+ 0xC8 => 0xE8,
+ 0xC9 => 0xE9,
+ 0xCA => 0xEA,
+ 0xCB => 0xEB,
+ 0xCC => 0xEC,
+ 0xCD => 0xED,
+ 0xCE => 0xEE,
+ 0xCF => 0xEF,
+ 0xD0 => 0xF0,
+ 0xD1 => 0xF1,
+ 0xD2 => 0xF2,
+ 0xD3 => 0xF3,
+ 0xD4 => 0xF4,
+ 0xD5 => 0xF5,
+ 0xD6 => 0xF6,
+ 0xD8 => 0xF8,
+ 0xD9 => 0xF9,
+ 0xDA => 0xFA,
+ 0xDB => 0xFB,
+ 0xDC => 0xFC,
+ 0xDD => 0xFD,
+ 0xDE => 0xFE,
+ 0x100 => 0x101,
+ 0x102 => 0x103,
+ 0x104 => 0x105,
+ 0x106 => 0x107,
+ 0x108 => 0x109,
+ 0x10A => 0x10B,
+ 0x10C => 0x10D,
+ 0x10E => 0x10F,
+ 0x110 => 0x111,
+ 0x112 => 0x113,
+ 0x114 => 0x115,
+ 0x116 => 0x117,
+ 0x118 => 0x119,
+ 0x11A => 0x11B,
+ 0x11C => 0x11D,
+ 0x11E => 0x11F,
+ 0x120 => 0x121,
+ 0x122 => 0x123,
+ 0x124 => 0x125,
+ 0x126 => 0x127,
+ 0x128 => 0x129,
+ 0x12A => 0x12B,
+ 0x12C => 0x12D,
+ 0x12E => 0x12F,
+ 0x130 => 0x69,
+ 0x132 => 0x133,
+ 0x134 => 0x135,
+ 0x136 => 0x137,
+ 0x139 => 0x13A,
+ 0x13B => 0x13C,
+ 0x13D => 0x13E,
+ 0x13F => 0x140,
+ 0x141 => 0x142,
+ 0x143 => 0x144,
+ 0x145 => 0x146,
+ 0x147 => 0x148,
+ 0x14A => 0x14B,
+ 0x14C => 0x14D,
+ 0x14E => 0x14F,
+ 0x150 => 0x151,
+ 0x152 => 0x153,
+ 0x154 => 0x155,
+ 0x156 => 0x157,
+ 0x158 => 0x159,
+ 0x15A => 0x15B,
+ 0x15C => 0x15D,
+ 0x15E => 0x15F,
+ 0x160 => 0x161,
+ 0x162 => 0x163,
+ 0x164 => 0x165,
+ 0x166 => 0x167,
+ 0x168 => 0x169,
+ 0x16A => 0x16B,
+ 0x16C => 0x16D,
+ 0x16E => 0x16F,
+ 0x170 => 0x171,
+ 0x172 => 0x173,
+ 0x174 => 0x175,
+ 0x176 => 0x177,
+ 0x178 => 0xFF,
+ 0x179 => 0x17A,
+ 0x17B => 0x17C,
+ 0x17D => 0x17E,
+ 0x181 => 0x253,
+ 0x182 => 0x183,
+ 0x184 => 0x185,
+ 0x186 => 0x254,
+ 0x187 => 0x188,
+ 0x189 => 0x256,
+ 0x18A => 0x257,
+ 0x18B => 0x18C,
+ 0x18E => 0x1DD,
+ 0x18F => 0x259,
+ 0x190 => 0x25B,
+ 0x191 => 0x192,
+ 0x193 => 0x260,
+ 0x194 => 0x263,
+ 0x196 => 0x269,
+ 0x197 => 0x268,
+ 0x198 => 0x199,
+ 0x19C => 0x26F,
+ 0x19D => 0x272,
+ 0x19F => 0x275,
+ 0x1A0 => 0x1A1,
+ 0x1A2 => 0x1A3,
+ 0x1A4 => 0x1A5,
+ 0x1A6 => 0x280,
+ 0x1A7 => 0x1A8,
+ 0x1A9 => 0x283,
+ 0x1AC => 0x1AD,
+ 0x1AE => 0x288,
+ 0x1AF => 0x1B0,
+ 0x1B1 => 0x28A,
+ 0x1B2 => 0x28B,
+ 0x1B3 => 0x1B4,
+ 0x1B5 => 0x1B6,
+ 0x1B7 => 0x292,
+ 0x1B8 => 0x1B9,
+ 0x1BC => 0x1BD,
+ 0x1C4 => 0x1C6,
+ 0x1C5 => 0x1C6,
+ 0x1C7 => 0x1C9,
+ 0x1C8 => 0x1C9,
+ 0x1CA => 0x1CC,
+ 0x1CB => 0x1CC,
+ 0x1CD => 0x1CE,
+ 0x1CF => 0x1D0,
+ 0x1D1 => 0x1D2,
+ 0x1D3 => 0x1D4,
+ 0x1D5 => 0x1D6,
+ 0x1D7 => 0x1D8,
+ 0x1D9 => 0x1DA,
+ 0x1DB => 0x1DC,
+ 0x1DE => 0x1DF,
+ 0x1E0 => 0x1E1,
+ 0x1E2 => 0x1E3,
+ 0x1E4 => 0x1E5,
+ 0x1E6 => 0x1E7,
+ 0x1E8 => 0x1E9,
+ 0x1EA => 0x1EB,
+ 0x1EC => 0x1ED,
+ 0x1EE => 0x1EF,
+ 0x1F1 => 0x1F3,
+ 0x1F2 => 0x1F3,
+ 0x1F4 => 0x1F5,
+ 0x1F6 => 0x195,
+ 0x1F7 => 0x1BF,
+ 0x1F8 => 0x1F9,
+ 0x1FA => 0x1FB,
+ 0x1FC => 0x1FD,
+ 0x1FE => 0x1FF,
+ 0x200 => 0x201,
+ 0x202 => 0x203,
+ 0x204 => 0x205,
+ 0x206 => 0x207,
+ 0x208 => 0x209,
+ 0x20A => 0x20B,
+ 0x20C => 0x20D,
+ 0x20E => 0x20F,
+ 0x210 => 0x211,
+ 0x212 => 0x213,
+ 0x214 => 0x215,
+ 0x216 => 0x217,
+ 0x218 => 0x219,
+ 0x21A => 0x21B,
+ 0x21C => 0x21D,
+ 0x21E => 0x21F,
+ 0x220 => 0x19E,
+ 0x222 => 0x223,
+ 0x224 => 0x225,
+ 0x226 => 0x227,
+ 0x228 => 0x229,
+ 0x22A => 0x22B,
+ 0x22C => 0x22D,
+ 0x22E => 0x22F,
+ 0x230 => 0x231,
+ 0x232 => 0x233,
+ 0x23A => 0x2C65,
+ 0x23B => 0x23C,
+ 0x23D => 0x19A,
+ 0x23E => 0x2C66,
+ 0x241 => 0x242,
+ 0x243 => 0x180,
+ 0x244 => 0x289,
+ 0x245 => 0x28C,
+ 0x246 => 0x247,
+ 0x248 => 0x249,
+ 0x24A => 0x24B,
+ 0x24C => 0x24D,
+ 0x24E => 0x24F,
+ 0x370 => 0x371,
+ 0x372 => 0x373,
+ 0x376 => 0x377,
+ 0x37F => 0x3F3,
+ 0x386 => 0x3AC,
+ 0x388 => 0x3AD,
+ 0x389 => 0x3AE,
+ 0x38A => 0x3AF,
+ 0x38C => 0x3CC,
+ 0x38E => 0x3CD,
+ 0x38F => 0x3CE,
+ 0x391 => 0x3B1,
+ 0x392 => 0x3B2,
+ 0x393 => 0x3B3,
+ 0x394 => 0x3B4,
+ 0x395 => 0x3B5,
+ 0x396 => 0x3B6,
+ 0x397 => 0x3B7,
+ 0x398 => 0x3B8,
+ 0x399 => 0x3B9,
+ 0x39A => 0x3BA,
+ 0x39B => 0x3BB,
+ 0x39C => 0x3BC,
+ 0x39D => 0x3BD,
+ 0x39E => 0x3BE,
+ 0x39F => 0x3BF,
+ 0x3A0 => 0x3C0,
+ 0x3A1 => 0x3C1,
+ 0x3A3 => 0x3C3,
+ 0x3A4 => 0x3C4,
+ 0x3A5 => 0x3C5,
+ 0x3A6 => 0x3C6,
+ 0x3A7 => 0x3C7,
+ 0x3A8 => 0x3C8,
+ 0x3A9 => 0x3C9,
+ 0x3AA => 0x3CA,
+ 0x3AB => 0x3CB,
+ 0x3CF => 0x3D7,
+ 0x3D8 => 0x3D9,
+ 0x3DA => 0x3DB,
+ 0x3DC => 0x3DD,
+ 0x3DE => 0x3DF,
+ 0x3E0 => 0x3E1,
+ 0x3E2 => 0x3E3,
+ 0x3E4 => 0x3E5,
+ 0x3E6 => 0x3E7,
+ 0x3E8 => 0x3E9,
+ 0x3EA => 0x3EB,
+ 0x3EC => 0x3ED,
+ 0x3EE => 0x3EF,
+ 0x3F4 => 0x3B8,
+ 0x3F7 => 0x3F8,
+ 0x3F9 => 0x3F2,
+ 0x3FA => 0x3FB,
+ 0x3FD => 0x37B,
+ 0x3FE => 0x37C,
+ 0x3FF => 0x37D,
+ 0x400 => 0x450,
+ 0x401 => 0x451,
+ 0x402 => 0x452,
+ 0x403 => 0x453,
+ 0x404 => 0x454,
+ 0x405 => 0x455,
+ 0x406 => 0x456,
+ 0x407 => 0x457,
+ 0x408 => 0x458,
+ 0x409 => 0x459,
+ 0x40A => 0x45A,
+ 0x40B => 0x45B,
+ 0x40C => 0x45C,
+ 0x40D => 0x45D,
+ 0x40E => 0x45E,
+ 0x40F => 0x45F,
+ 0x410 => 0x430,
+ 0x411 => 0x431,
+ 0x412 => 0x432,
+ 0x413 => 0x433,
+ 0x414 => 0x434,
+ 0x415 => 0x435,
+ 0x416 => 0x436,
+ 0x417 => 0x437,
+ 0x418 => 0x438,
+ 0x419 => 0x439,
+ 0x41A => 0x43A,
+ 0x41B => 0x43B,
+ 0x41C => 0x43C,
+ 0x41D => 0x43D,
+ 0x41E => 0x43E,
+ 0x41F => 0x43F,
+ 0x420 => 0x440,
+ 0x421 => 0x441,
+ 0x422 => 0x442,
+ 0x423 => 0x443,
+ 0x424 => 0x444,
+ 0x425 => 0x445,
+ 0x426 => 0x446,
+ 0x427 => 0x447,
+ 0x428 => 0x448,
+ 0x429 => 0x449,
+ 0x42A => 0x44A,
+ 0x42B => 0x44B,
+ 0x42C => 0x44C,
+ 0x42D => 0x44D,
+ 0x42E => 0x44E,
+ 0x42F => 0x44F,
+ 0x460 => 0x461,
+ 0x462 => 0x463,
+ 0x464 => 0x465,
+ 0x466 => 0x467,
+ 0x468 => 0x469,
+ 0x46A => 0x46B,
+ 0x46C => 0x46D,
+ 0x46E => 0x46F,
+ 0x470 => 0x471,
+ 0x472 => 0x473,
+ 0x474 => 0x475,
+ 0x476 => 0x477,
+ 0x478 => 0x479,
+ 0x47A => 0x47B,
+ 0x47C => 0x47D,
+ 0x47E => 0x47F,
+ 0x480 => 0x481,
+ 0x48A => 0x48B,
+ 0x48C => 0x48D,
+ 0x48E => 0x48F,
+ 0x490 => 0x491,
+ 0x492 => 0x493,
+ 0x494 => 0x495,
+ 0x496 => 0x497,
+ 0x498 => 0x499,
+ 0x49A => 0x49B,
+ 0x49C => 0x49D,
+ 0x49E => 0x49F,
+ 0x4A0 => 0x4A1,
+ 0x4A2 => 0x4A3,
+ 0x4A4 => 0x4A5,
+ 0x4A6 => 0x4A7,
+ 0x4A8 => 0x4A9,
+ 0x4AA => 0x4AB,
+ 0x4AC => 0x4AD,
+ 0x4AE => 0x4AF,
+ 0x4B0 => 0x4B1,
+ 0x4B2 => 0x4B3,
+ 0x4B4 => 0x4B5,
+ 0x4B6 => 0x4B7,
+ 0x4B8 => 0x4B9,
+ 0x4BA => 0x4BB,
+ 0x4BC => 0x4BD,
+ 0x4BE => 0x4BF,
+ 0x4C0 => 0x4CF,
+ 0x4C1 => 0x4C2,
+ 0x4C3 => 0x4C4,
+ 0x4C5 => 0x4C6,
+ 0x4C7 => 0x4C8,
+ 0x4C9 => 0x4CA,
+ 0x4CB => 0x4CC,
+ 0x4CD => 0x4CE,
+ 0x4D0 => 0x4D1,
+ 0x4D2 => 0x4D3,
+ 0x4D4 => 0x4D5,
+ 0x4D6 => 0x4D7,
+ 0x4D8 => 0x4D9,
+ 0x4DA => 0x4DB,
+ 0x4DC => 0x4DD,
+ 0x4DE => 0x4DF,
+ 0x4E0 => 0x4E1,
+ 0x4E2 => 0x4E3,
+ 0x4E4 => 0x4E5,
+ 0x4E6 => 0x4E7,
+ 0x4E8 => 0x4E9,
+ 0x4EA => 0x4EB,
+ 0x4EC => 0x4ED,
+ 0x4EE => 0x4EF,
+ 0x4F0 => 0x4F1,
+ 0x4F2 => 0x4F3,
+ 0x4F4 => 0x4F5,
+ 0x4F6 => 0x4F7,
+ 0x4F8 => 0x4F9,
+ 0x4FA => 0x4FB,
+ 0x4FC => 0x4FD,
+ 0x4FE => 0x4FF,
+ 0x500 => 0x501,
+ 0x502 => 0x503,
+ 0x504 => 0x505,
+ 0x506 => 0x507,
+ 0x508 => 0x509,
+ 0x50A => 0x50B,
+ 0x50C => 0x50D,
+ 0x50E => 0x50F,
+ 0x510 => 0x511,
+ 0x512 => 0x513,
+ 0x514 => 0x515,
+ 0x516 => 0x517,
+ 0x518 => 0x519,
+ 0x51A => 0x51B,
+ 0x51C => 0x51D,
+ 0x51E => 0x51F,
+ 0x520 => 0x521,
+ 0x522 => 0x523,
+ 0x524 => 0x525,
+ 0x526 => 0x527,
+ 0x528 => 0x529,
+ 0x52A => 0x52B,
+ 0x52C => 0x52D,
+ 0x52E => 0x52F,
+ 0x531 => 0x561,
+ 0x532 => 0x562,
+ 0x533 => 0x563,
+ 0x534 => 0x564,
+ 0x535 => 0x565,
+ 0x536 => 0x566,
+ 0x537 => 0x567,
+ 0x538 => 0x568,
+ 0x539 => 0x569,
+ 0x53A => 0x56A,
+ 0x53B => 0x56B,
+ 0x53C => 0x56C,
+ 0x53D => 0x56D,
+ 0x53E => 0x56E,
+ 0x53F => 0x56F,
+ 0x540 => 0x570,
+ 0x541 => 0x571,
+ 0x542 => 0x572,
+ 0x543 => 0x573,
+ 0x544 => 0x574,
+ 0x545 => 0x575,
+ 0x546 => 0x576,
+ 0x547 => 0x577,
+ 0x548 => 0x578,
+ 0x549 => 0x579,
+ 0x54A => 0x57A,
+ 0x54B => 0x57B,
+ 0x54C => 0x57C,
+ 0x54D => 0x57D,
+ 0x54E => 0x57E,
+ 0x54F => 0x57F,
+ 0x550 => 0x580,
+ 0x551 => 0x581,
+ 0x552 => 0x582,
+ 0x553 => 0x583,
+ 0x554 => 0x584,
+ 0x555 => 0x585,
+ 0x556 => 0x586,
+ 0x10A0 => 0x2D00,
+ 0x10A1 => 0x2D01,
+ 0x10A2 => 0x2D02,
+ 0x10A3 => 0x2D03,
+ 0x10A4 => 0x2D04,
+ 0x10A5 => 0x2D05,
+ 0x10A6 => 0x2D06,
+ 0x10A7 => 0x2D07,
+ 0x10A8 => 0x2D08,
+ 0x10A9 => 0x2D09,
+ 0x10AA => 0x2D0A,
+ 0x10AB => 0x2D0B,
+ 0x10AC => 0x2D0C,
+ 0x10AD => 0x2D0D,
+ 0x10AE => 0x2D0E,
+ 0x10AF => 0x2D0F,
+ 0x10B0 => 0x2D10,
+ 0x10B1 => 0x2D11,
+ 0x10B2 => 0x2D12,
+ 0x10B3 => 0x2D13,
+ 0x10B4 => 0x2D14,
+ 0x10B5 => 0x2D15,
+ 0x10B6 => 0x2D16,
+ 0x10B7 => 0x2D17,
+ 0x10B8 => 0x2D18,
+ 0x10B9 => 0x2D19,
+ 0x10BA => 0x2D1A,
+ 0x10BB => 0x2D1B,
+ 0x10BC => 0x2D1C,
+ 0x10BD => 0x2D1D,
+ 0x10BE => 0x2D1E,
+ 0x10BF => 0x2D1F,
+ 0x10C0 => 0x2D20,
+ 0x10C1 => 0x2D21,
+ 0x10C2 => 0x2D22,
+ 0x10C3 => 0x2D23,
+ 0x10C4 => 0x2D24,
+ 0x10C5 => 0x2D25,
+ 0x10C7 => 0x2D27,
+ 0x10CD => 0x2D2D,
+ 0x13A0 => 0xAB70,
+ 0x13A1 => 0xAB71,
+ 0x13A2 => 0xAB72,
+ 0x13A3 => 0xAB73,
+ 0x13A4 => 0xAB74,
+ 0x13A5 => 0xAB75,
+ 0x13A6 => 0xAB76,
+ 0x13A7 => 0xAB77,
+ 0x13A8 => 0xAB78,
+ 0x13A9 => 0xAB79,
+ 0x13AA => 0xAB7A,
+ 0x13AB => 0xAB7B,
+ 0x13AC => 0xAB7C,
+ 0x13AD => 0xAB7D,
+ 0x13AE => 0xAB7E,
+ 0x13AF => 0xAB7F,
+ 0x13B0 => 0xAB80,
+ 0x13B1 => 0xAB81,
+ 0x13B2 => 0xAB82,
+ 0x13B3 => 0xAB83,
+ 0x13B4 => 0xAB84,
+ 0x13B5 => 0xAB85,
+ 0x13B6 => 0xAB86,
+ 0x13B7 => 0xAB87,
+ 0x13B8 => 0xAB88,
+ 0x13B9 => 0xAB89,
+ 0x13BA => 0xAB8A,
+ 0x13BB => 0xAB8B,
+ 0x13BC => 0xAB8C,
+ 0x13BD => 0xAB8D,
+ 0x13BE => 0xAB8E,
+ 0x13BF => 0xAB8F,
+ 0x13C0 => 0xAB90,
+ 0x13C1 => 0xAB91,
+ 0x13C2 => 0xAB92,
+ 0x13C3 => 0xAB93,
+ 0x13C4 => 0xAB94,
+ 0x13C5 => 0xAB95,
+ 0x13C6 => 0xAB96,
+ 0x13C7 => 0xAB97,
+ 0x13C8 => 0xAB98,
+ 0x13C9 => 0xAB99,
+ 0x13CA => 0xAB9A,
+ 0x13CB => 0xAB9B,
+ 0x13CC => 0xAB9C,
+ 0x13CD => 0xAB9D,
+ 0x13CE => 0xAB9E,
+ 0x13CF => 0xAB9F,
+ 0x13D0 => 0xABA0,
+ 0x13D1 => 0xABA1,
+ 0x13D2 => 0xABA2,
+ 0x13D3 => 0xABA3,
+ 0x13D4 => 0xABA4,
+ 0x13D5 => 0xABA5,
+ 0x13D6 => 0xABA6,
+ 0x13D7 => 0xABA7,
+ 0x13D8 => 0xABA8,
+ 0x13D9 => 0xABA9,
+ 0x13DA => 0xABAA,
+ 0x13DB => 0xABAB,
+ 0x13DC => 0xABAC,
+ 0x13DD => 0xABAD,
+ 0x13DE => 0xABAE,
+ 0x13DF => 0xABAF,
+ 0x13E0 => 0xABB0,
+ 0x13E1 => 0xABB1,
+ 0x13E2 => 0xABB2,
+ 0x13E3 => 0xABB3,
+ 0x13E4 => 0xABB4,
+ 0x13E5 => 0xABB5,
+ 0x13E6 => 0xABB6,
+ 0x13E7 => 0xABB7,
+ 0x13E8 => 0xABB8,
+ 0x13E9 => 0xABB9,
+ 0x13EA => 0xABBA,
+ 0x13EB => 0xABBB,
+ 0x13EC => 0xABBC,
+ 0x13ED => 0xABBD,
+ 0x13EE => 0xABBE,
+ 0x13EF => 0xABBF,
+ 0x13F0 => 0x13F8,
+ 0x13F1 => 0x13F9,
+ 0x13F2 => 0x13FA,
+ 0x13F3 => 0x13FB,
+ 0x13F4 => 0x13FC,
+ 0x13F5 => 0x13FD,
+ 0x1C90 => 0x10D0,
+ 0x1C91 => 0x10D1,
+ 0x1C92 => 0x10D2,
+ 0x1C93 => 0x10D3,
+ 0x1C94 => 0x10D4,
+ 0x1C95 => 0x10D5,
+ 0x1C96 => 0x10D6,
+ 0x1C97 => 0x10D7,
+ 0x1C98 => 0x10D8,
+ 0x1C99 => 0x10D9,
+ 0x1C9A => 0x10DA,
+ 0x1C9B => 0x10DB,
+ 0x1C9C => 0x10DC,
+ 0x1C9D => 0x10DD,
+ 0x1C9E => 0x10DE,
+ 0x1C9F => 0x10DF,
+ 0x1CA0 => 0x10E0,
+ 0x1CA1 => 0x10E1,
+ 0x1CA2 => 0x10E2,
+ 0x1CA3 => 0x10E3,
+ 0x1CA4 => 0x10E4,
+ 0x1CA5 => 0x10E5,
+ 0x1CA6 => 0x10E6,
+ 0x1CA7 => 0x10E7,
+ 0x1CA8 => 0x10E8,
+ 0x1CA9 => 0x10E9,
+ 0x1CAA => 0x10EA,
+ 0x1CAB => 0x10EB,
+ 0x1CAC => 0x10EC,
+ 0x1CAD => 0x10ED,
+ 0x1CAE => 0x10EE,
+ 0x1CAF => 0x10EF,
+ 0x1CB0 => 0x10F0,
+ 0x1CB1 => 0x10F1,
+ 0x1CB2 => 0x10F2,
+ 0x1CB3 => 0x10F3,
+ 0x1CB4 => 0x10F4,
+ 0x1CB5 => 0x10F5,
+ 0x1CB6 => 0x10F6,
+ 0x1CB7 => 0x10F7,
+ 0x1CB8 => 0x10F8,
+ 0x1CB9 => 0x10F9,
+ 0x1CBA => 0x10FA,
+ 0x1CBD => 0x10FD,
+ 0x1CBE => 0x10FE,
+ 0x1CBF => 0x10FF,
+ 0x1E00 => 0x1E01,
+ 0x1E02 => 0x1E03,
+ 0x1E04 => 0x1E05,
+ 0x1E06 => 0x1E07,
+ 0x1E08 => 0x1E09,
+ 0x1E0A => 0x1E0B,
+ 0x1E0C => 0x1E0D,
+ 0x1E0E => 0x1E0F,
+ 0x1E10 => 0x1E11,
+ 0x1E12 => 0x1E13,
+ 0x1E14 => 0x1E15,
+ 0x1E16 => 0x1E17,
+ 0x1E18 => 0x1E19,
+ 0x1E1A => 0x1E1B,
+ 0x1E1C => 0x1E1D,
+ 0x1E1E => 0x1E1F,
+ 0x1E20 => 0x1E21,
+ 0x1E22 => 0x1E23,
+ 0x1E24 => 0x1E25,
+ 0x1E26 => 0x1E27,
+ 0x1E28 => 0x1E29,
+ 0x1E2A => 0x1E2B,
+ 0x1E2C => 0x1E2D,
+ 0x1E2E => 0x1E2F,
+ 0x1E30 => 0x1E31,
+ 0x1E32 => 0x1E33,
+ 0x1E34 => 0x1E35,
+ 0x1E36 => 0x1E37,
+ 0x1E38 => 0x1E39,
+ 0x1E3A => 0x1E3B,
+ 0x1E3C => 0x1E3D,
+ 0x1E3E => 0x1E3F,
+ 0x1E40 => 0x1E41,
+ 0x1E42 => 0x1E43,
+ 0x1E44 => 0x1E45,
+ 0x1E46 => 0x1E47,
+ 0x1E48 => 0x1E49,
+ 0x1E4A => 0x1E4B,
+ 0x1E4C => 0x1E4D,
+ 0x1E4E => 0x1E4F,
+ 0x1E50 => 0x1E51,
+ 0x1E52 => 0x1E53,
+ 0x1E54 => 0x1E55,
+ 0x1E56 => 0x1E57,
+ 0x1E58 => 0x1E59,
+ 0x1E5A => 0x1E5B,
+ 0x1E5C => 0x1E5D,
+ 0x1E5E => 0x1E5F,
+ 0x1E60 => 0x1E61,
+ 0x1E62 => 0x1E63,
+ 0x1E64 => 0x1E65,
+ 0x1E66 => 0x1E67,
+ 0x1E68 => 0x1E69,
+ 0x1E6A => 0x1E6B,
+ 0x1E6C => 0x1E6D,
+ 0x1E6E => 0x1E6F,
+ 0x1E70 => 0x1E71,
+ 0x1E72 => 0x1E73,
+ 0x1E74 => 0x1E75,
+ 0x1E76 => 0x1E77,
+ 0x1E78 => 0x1E79,
+ 0x1E7A => 0x1E7B,
+ 0x1E7C => 0x1E7D,
+ 0x1E7E => 0x1E7F,
+ 0x1E80 => 0x1E81,
+ 0x1E82 => 0x1E83,
+ 0x1E84 => 0x1E85,
+ 0x1E86 => 0x1E87,
+ 0x1E88 => 0x1E89,
+ 0x1E8A => 0x1E8B,
+ 0x1E8C => 0x1E8D,
+ 0x1E8E => 0x1E8F,
+ 0x1E90 => 0x1E91,
+ 0x1E92 => 0x1E93,
+ 0x1E94 => 0x1E95,
+ 0x1E9E => 0xDF,
+ 0x1EA0 => 0x1EA1,
+ 0x1EA2 => 0x1EA3,
+ 0x1EA4 => 0x1EA5,
+ 0x1EA6 => 0x1EA7,
+ 0x1EA8 => 0x1EA9,
+ 0x1EAA => 0x1EAB,
+ 0x1EAC => 0x1EAD,
+ 0x1EAE => 0x1EAF,
+ 0x1EB0 => 0x1EB1,
+ 0x1EB2 => 0x1EB3,
+ 0x1EB4 => 0x1EB5,
+ 0x1EB6 => 0x1EB7,
+ 0x1EB8 => 0x1EB9,
+ 0x1EBA => 0x1EBB,
+ 0x1EBC => 0x1EBD,
+ 0x1EBE => 0x1EBF,
+ 0x1EC0 => 0x1EC1,
+ 0x1EC2 => 0x1EC3,
+ 0x1EC4 => 0x1EC5,
+ 0x1EC6 => 0x1EC7,
+ 0x1EC8 => 0x1EC9,
+ 0x1ECA => 0x1ECB,
+ 0x1ECC => 0x1ECD,
+ 0x1ECE => 0x1ECF,
+ 0x1ED0 => 0x1ED1,
+ 0x1ED2 => 0x1ED3,
+ 0x1ED4 => 0x1ED5,
+ 0x1ED6 => 0x1ED7,
+ 0x1ED8 => 0x1ED9,
+ 0x1EDA => 0x1EDB,
+ 0x1EDC => 0x1EDD,
+ 0x1EDE => 0x1EDF,
+ 0x1EE0 => 0x1EE1,
+ 0x1EE2 => 0x1EE3,
+ 0x1EE4 => 0x1EE5,
+ 0x1EE6 => 0x1EE7,
+ 0x1EE8 => 0x1EE9,
+ 0x1EEA => 0x1EEB,
+ 0x1EEC => 0x1EED,
+ 0x1EEE => 0x1EEF,
+ 0x1EF0 => 0x1EF1,
+ 0x1EF2 => 0x1EF3,
+ 0x1EF4 => 0x1EF5,
+ 0x1EF6 => 0x1EF7,
+ 0x1EF8 => 0x1EF9,
+ 0x1EFA => 0x1EFB,
+ 0x1EFC => 0x1EFD,
+ 0x1EFE => 0x1EFF,
+ 0x1F08 => 0x1F00,
+ 0x1F09 => 0x1F01,
+ 0x1F0A => 0x1F02,
+ 0x1F0B => 0x1F03,
+ 0x1F0C => 0x1F04,
+ 0x1F0D => 0x1F05,
+ 0x1F0E => 0x1F06,
+ 0x1F0F => 0x1F07,
+ 0x1F18 => 0x1F10,
+ 0x1F19 => 0x1F11,
+ 0x1F1A => 0x1F12,
+ 0x1F1B => 0x1F13,
+ 0x1F1C => 0x1F14,
+ 0x1F1D => 0x1F15,
+ 0x1F28 => 0x1F20,
+ 0x1F29 => 0x1F21,
+ 0x1F2A => 0x1F22,
+ 0x1F2B => 0x1F23,
+ 0x1F2C => 0x1F24,
+ 0x1F2D => 0x1F25,
+ 0x1F2E => 0x1F26,
+ 0x1F2F => 0x1F27,
+ 0x1F38 => 0x1F30,
+ 0x1F39 => 0x1F31,
+ 0x1F3A => 0x1F32,
+ 0x1F3B => 0x1F33,
+ 0x1F3C => 0x1F34,
+ 0x1F3D => 0x1F35,
+ 0x1F3E => 0x1F36,
+ 0x1F3F => 0x1F37,
+ 0x1F48 => 0x1F40,
+ 0x1F49 => 0x1F41,
+ 0x1F4A => 0x1F42,
+ 0x1F4B => 0x1F43,
+ 0x1F4C => 0x1F44,
+ 0x1F4D => 0x1F45,
+ 0x1F59 => 0x1F51,
+ 0x1F5B => 0x1F53,
+ 0x1F5D => 0x1F55,
+ 0x1F5F => 0x1F57,
+ 0x1F68 => 0x1F60,
+ 0x1F69 => 0x1F61,
+ 0x1F6A => 0x1F62,
+ 0x1F6B => 0x1F63,
+ 0x1F6C => 0x1F64,
+ 0x1F6D => 0x1F65,
+ 0x1F6E => 0x1F66,
+ 0x1F6F => 0x1F67,
+ 0x1F88 => 0x1F80,
+ 0x1F89 => 0x1F81,
+ 0x1F8A => 0x1F82,
+ 0x1F8B => 0x1F83,
+ 0x1F8C => 0x1F84,
+ 0x1F8D => 0x1F85,
+ 0x1F8E => 0x1F86,
+ 0x1F8F => 0x1F87,
+ 0x1F98 => 0x1F90,
+ 0x1F99 => 0x1F91,
+ 0x1F9A => 0x1F92,
+ 0x1F9B => 0x1F93,
+ 0x1F9C => 0x1F94,
+ 0x1F9D => 0x1F95,
+ 0x1F9E => 0x1F96,
+ 0x1F9F => 0x1F97,
+ 0x1FA8 => 0x1FA0,
+ 0x1FA9 => 0x1FA1,
+ 0x1FAA => 0x1FA2,
+ 0x1FAB => 0x1FA3,
+ 0x1FAC => 0x1FA4,
+ 0x1FAD => 0x1FA5,
+ 0x1FAE => 0x1FA6,
+ 0x1FAF => 0x1FA7,
+ 0x1FB8 => 0x1FB0,
+ 0x1FB9 => 0x1FB1,
+ 0x1FBA => 0x1F70,
+ 0x1FBB => 0x1F71,
+ 0x1FBC => 0x1FB3,
+ 0x1FC8 => 0x1F72,
+ 0x1FC9 => 0x1F73,
+ 0x1FCA => 0x1F74,
+ 0x1FCB => 0x1F75,
+ 0x1FCC => 0x1FC3,
+ 0x1FD8 => 0x1FD0,
+ 0x1FD9 => 0x1FD1,
+ 0x1FDA => 0x1F76,
+ 0x1FDB => 0x1F77,
+ 0x1FE8 => 0x1FE0,
+ 0x1FE9 => 0x1FE1,
+ 0x1FEA => 0x1F7A,
+ 0x1FEB => 0x1F7B,
+ 0x1FEC => 0x1FE5,
+ 0x1FF8 => 0x1F78,
+ 0x1FF9 => 0x1F79,
+ 0x1FFA => 0x1F7C,
+ 0x1FFB => 0x1F7D,
+ 0x1FFC => 0x1FF3,
+ 0x2126 => 0x3C9,
+ 0x212A => 0x6B,
+ 0x212B => 0xE5,
+ 0x2132 => 0x214E,
+ 0x2160 => 0x2170,
+ 0x2161 => 0x2171,
+ 0x2162 => 0x2172,
+ 0x2163 => 0x2173,
+ 0x2164 => 0x2174,
+ 0x2165 => 0x2175,
+ 0x2166 => 0x2176,
+ 0x2167 => 0x2177,
+ 0x2168 => 0x2178,
+ 0x2169 => 0x2179,
+ 0x216A => 0x217A,
+ 0x216B => 0x217B,
+ 0x216C => 0x217C,
+ 0x216D => 0x217D,
+ 0x216E => 0x217E,
+ 0x216F => 0x217F,
+ 0x2183 => 0x2184,
+ 0x24B6 => 0x24D0,
+ 0x24B7 => 0x24D1,
+ 0x24B8 => 0x24D2,
+ 0x24B9 => 0x24D3,
+ 0x24BA => 0x24D4,
+ 0x24BB => 0x24D5,
+ 0x24BC => 0x24D6,
+ 0x24BD => 0x24D7,
+ 0x24BE => 0x24D8,
+ 0x24BF => 0x24D9,
+ 0x24C0 => 0x24DA,
+ 0x24C1 => 0x24DB,
+ 0x24C2 => 0x24DC,
+ 0x24C3 => 0x24DD,
+ 0x24C4 => 0x24DE,
+ 0x24C5 => 0x24DF,
+ 0x24C6 => 0x24E0,
+ 0x24C7 => 0x24E1,
+ 0x24C8 => 0x24E2,
+ 0x24C9 => 0x24E3,
+ 0x24CA => 0x24E4,
+ 0x24CB => 0x24E5,
+ 0x24CC => 0x24E6,
+ 0x24CD => 0x24E7,
+ 0x24CE => 0x24E8,
+ 0x24CF => 0x24E9,
+ 0x2C00 => 0x2C30,
+ 0x2C01 => 0x2C31,
+ 0x2C02 => 0x2C32,
+ 0x2C03 => 0x2C33,
+ 0x2C04 => 0x2C34,
+ 0x2C05 => 0x2C35,
+ 0x2C06 => 0x2C36,
+ 0x2C07 => 0x2C37,
+ 0x2C08 => 0x2C38,
+ 0x2C09 => 0x2C39,
+ 0x2C0A => 0x2C3A,
+ 0x2C0B => 0x2C3B,
+ 0x2C0C => 0x2C3C,
+ 0x2C0D => 0x2C3D,
+ 0x2C0E => 0x2C3E,
+ 0x2C0F => 0x2C3F,
+ 0x2C10 => 0x2C40,
+ 0x2C11 => 0x2C41,
+ 0x2C12 => 0x2C42,
+ 0x2C13 => 0x2C43,
+ 0x2C14 => 0x2C44,
+ 0x2C15 => 0x2C45,
+ 0x2C16 => 0x2C46,
+ 0x2C17 => 0x2C47,
+ 0x2C18 => 0x2C48,
+ 0x2C19 => 0x2C49,
+ 0x2C1A => 0x2C4A,
+ 0x2C1B => 0x2C4B,
+ 0x2C1C => 0x2C4C,
+ 0x2C1D => 0x2C4D,
+ 0x2C1E => 0x2C4E,
+ 0x2C1F => 0x2C4F,
+ 0x2C20 => 0x2C50,
+ 0x2C21 => 0x2C51,
+ 0x2C22 => 0x2C52,
+ 0x2C23 => 0x2C53,
+ 0x2C24 => 0x2C54,
+ 0x2C25 => 0x2C55,
+ 0x2C26 => 0x2C56,
+ 0x2C27 => 0x2C57,
+ 0x2C28 => 0x2C58,
+ 0x2C29 => 0x2C59,
+ 0x2C2A => 0x2C5A,
+ 0x2C2B => 0x2C5B,
+ 0x2C2C => 0x2C5C,
+ 0x2C2D => 0x2C5D,
+ 0x2C2E => 0x2C5E,
+ 0x2C2F => 0x2C5F,
+ 0x2C60 => 0x2C61,
+ 0x2C62 => 0x26B,
+ 0x2C63 => 0x1D7D,
+ 0x2C64 => 0x27D,
+ 0x2C67 => 0x2C68,
+ 0x2C69 => 0x2C6A,
+ 0x2C6B => 0x2C6C,
+ 0x2C6D => 0x251,
+ 0x2C6E => 0x271,
+ 0x2C6F => 0x250,
+ 0x2C70 => 0x252,
+ 0x2C72 => 0x2C73,
+ 0x2C75 => 0x2C76,
+ 0x2C7E => 0x23F,
+ 0x2C7F => 0x240,
+ 0x2C80 => 0x2C81,
+ 0x2C82 => 0x2C83,
+ 0x2C84 => 0x2C85,
+ 0x2C86 => 0x2C87,
+ 0x2C88 => 0x2C89,
+ 0x2C8A => 0x2C8B,
+ 0x2C8C => 0x2C8D,
+ 0x2C8E => 0x2C8F,
+ 0x2C90 => 0x2C91,
+ 0x2C92 => 0x2C93,
+ 0x2C94 => 0x2C95,
+ 0x2C96 => 0x2C97,
+ 0x2C98 => 0x2C99,
+ 0x2C9A => 0x2C9B,
+ 0x2C9C => 0x2C9D,
+ 0x2C9E => 0x2C9F,
+ 0x2CA0 => 0x2CA1,
+ 0x2CA2 => 0x2CA3,
+ 0x2CA4 => 0x2CA5,
+ 0x2CA6 => 0x2CA7,
+ 0x2CA8 => 0x2CA9,
+ 0x2CAA => 0x2CAB,
+ 0x2CAC => 0x2CAD,
+ 0x2CAE => 0x2CAF,
+ 0x2CB0 => 0x2CB1,
+ 0x2CB2 => 0x2CB3,
+ 0x2CB4 => 0x2CB5,
+ 0x2CB6 => 0x2CB7,
+ 0x2CB8 => 0x2CB9,
+ 0x2CBA => 0x2CBB,
+ 0x2CBC => 0x2CBD,
+ 0x2CBE => 0x2CBF,
+ 0x2CC0 => 0x2CC1,
+ 0x2CC2 => 0x2CC3,
+ 0x2CC4 => 0x2CC5,
+ 0x2CC6 => 0x2CC7,
+ 0x2CC8 => 0x2CC9,
+ 0x2CCA => 0x2CCB,
+ 0x2CCC => 0x2CCD,
+ 0x2CCE => 0x2CCF,
+ 0x2CD0 => 0x2CD1,
+ 0x2CD2 => 0x2CD3,
+ 0x2CD4 => 0x2CD5,
+ 0x2CD6 => 0x2CD7,
+ 0x2CD8 => 0x2CD9,
+ 0x2CDA => 0x2CDB,
+ 0x2CDC => 0x2CDD,
+ 0x2CDE => 0x2CDF,
+ 0x2CE0 => 0x2CE1,
+ 0x2CE2 => 0x2CE3,
+ 0x2CEB => 0x2CEC,
+ 0x2CED => 0x2CEE,
+ 0x2CF2 => 0x2CF3,
+ 0xA640 => 0xA641,
+ 0xA642 => 0xA643,
+ 0xA644 => 0xA645,
+ 0xA646 => 0xA647,
+ 0xA648 => 0xA649,
+ 0xA64A => 0xA64B,
+ 0xA64C => 0xA64D,
+ 0xA64E => 0xA64F,
+ 0xA650 => 0xA651,
+ 0xA652 => 0xA653,
+ 0xA654 => 0xA655,
+ 0xA656 => 0xA657,
+ 0xA658 => 0xA659,
+ 0xA65A => 0xA65B,
+ 0xA65C => 0xA65D,
+ 0xA65E => 0xA65F,
+ 0xA660 => 0xA661,
+ 0xA662 => 0xA663,
+ 0xA664 => 0xA665,
+ 0xA666 => 0xA667,
+ 0xA668 => 0xA669,
+ 0xA66A => 0xA66B,
+ 0xA66C => 0xA66D,
+ 0xA680 => 0xA681,
+ 0xA682 => 0xA683,
+ 0xA684 => 0xA685,
+ 0xA686 => 0xA687,
+ 0xA688 => 0xA689,
+ 0xA68A => 0xA68B,
+ 0xA68C => 0xA68D,
+ 0xA68E => 0xA68F,
+ 0xA690 => 0xA691,
+ 0xA692 => 0xA693,
+ 0xA694 => 0xA695,
+ 0xA696 => 0xA697,
+ 0xA698 => 0xA699,
+ 0xA69A => 0xA69B,
+ 0xA722 => 0xA723,
+ 0xA724 => 0xA725,
+ 0xA726 => 0xA727,
+ 0xA728 => 0xA729,
+ 0xA72A => 0xA72B,
+ 0xA72C => 0xA72D,
+ 0xA72E => 0xA72F,
+ 0xA732 => 0xA733,
+ 0xA734 => 0xA735,
+ 0xA736 => 0xA737,
+ 0xA738 => 0xA739,
+ 0xA73A => 0xA73B,
+ 0xA73C => 0xA73D,
+ 0xA73E => 0xA73F,
+ 0xA740 => 0xA741,
+ 0xA742 => 0xA743,
+ 0xA744 => 0xA745,
+ 0xA746 => 0xA747,
+ 0xA748 => 0xA749,
+ 0xA74A => 0xA74B,
+ 0xA74C => 0xA74D,
+ 0xA74E => 0xA74F,
+ 0xA750 => 0xA751,
+ 0xA752 => 0xA753,
+ 0xA754 => 0xA755,
+ 0xA756 => 0xA757,
+ 0xA758 => 0xA759,
+ 0xA75A => 0xA75B,
+ 0xA75C => 0xA75D,
+ 0xA75E => 0xA75F,
+ 0xA760 => 0xA761,
+ 0xA762 => 0xA763,
+ 0xA764 => 0xA765,
+ 0xA766 => 0xA767,
+ 0xA768 => 0xA769,
+ 0xA76A => 0xA76B,
+ 0xA76C => 0xA76D,
+ 0xA76E => 0xA76F,
+ 0xA779 => 0xA77A,
+ 0xA77B => 0xA77C,
+ 0xA77D => 0x1D79,
+ 0xA77E => 0xA77F,
+ 0xA780 => 0xA781,
+ 0xA782 => 0xA783,
+ 0xA784 => 0xA785,
+ 0xA786 => 0xA787,
+ 0xA78B => 0xA78C,
+ 0xA78D => 0x265,
+ 0xA790 => 0xA791,
+ 0xA792 => 0xA793,
+ 0xA796 => 0xA797,
+ 0xA798 => 0xA799,
+ 0xA79A => 0xA79B,
+ 0xA79C => 0xA79D,
+ 0xA79E => 0xA79F,
+ 0xA7A0 => 0xA7A1,
+ 0xA7A2 => 0xA7A3,
+ 0xA7A4 => 0xA7A5,
+ 0xA7A6 => 0xA7A7,
+ 0xA7A8 => 0xA7A9,
+ 0xA7AA => 0x266,
+ 0xA7AB => 0x25C,
+ 0xA7AC => 0x261,
+ 0xA7AD => 0x26C,
+ 0xA7AE => 0x26A,
+ 0xA7B0 => 0x29E,
+ 0xA7B1 => 0x287,
+ 0xA7B2 => 0x29D,
+ 0xA7B3 => 0xAB53,
+ 0xA7B4 => 0xA7B5,
+ 0xA7B6 => 0xA7B7,
+ 0xA7B8 => 0xA7B9,
+ 0xA7BA => 0xA7BB,
+ 0xA7BC => 0xA7BD,
+ 0xA7BE => 0xA7BF,
+ 0xA7C0 => 0xA7C1,
+ 0xA7C2 => 0xA7C3,
+ 0xA7C4 => 0xA794,
+ 0xA7C5 => 0x282,
+ 0xA7C6 => 0x1D8E,
+ 0xA7C7 => 0xA7C8,
+ 0xA7C9 => 0xA7CA,
+ 0xA7D0 => 0xA7D1,
+ 0xA7D6 => 0xA7D7,
+ 0xA7D8 => 0xA7D9,
+ 0xA7F5 => 0xA7F6,
+ 0xFF21 => 0xFF41,
+ 0xFF22 => 0xFF42,
+ 0xFF23 => 0xFF43,
+ 0xFF24 => 0xFF44,
+ 0xFF25 => 0xFF45,
+ 0xFF26 => 0xFF46,
+ 0xFF27 => 0xFF47,
+ 0xFF28 => 0xFF48,
+ 0xFF29 => 0xFF49,
+ 0xFF2A => 0xFF4A,
+ 0xFF2B => 0xFF4B,
+ 0xFF2C => 0xFF4C,
+ 0xFF2D => 0xFF4D,
+ 0xFF2E => 0xFF4E,
+ 0xFF2F => 0xFF4F,
+ 0xFF30 => 0xFF50,
+ 0xFF31 => 0xFF51,
+ 0xFF32 => 0xFF52,
+ 0xFF33 => 0xFF53,
+ 0xFF34 => 0xFF54,
+ 0xFF35 => 0xFF55,
+ 0xFF36 => 0xFF56,
+ 0xFF37 => 0xFF57,
+ 0xFF38 => 0xFF58,
+ 0xFF39 => 0xFF59,
+ 0xFF3A => 0xFF5A,
+ 0x10400 => 0x10428,
+ 0x10401 => 0x10429,
+ 0x10402 => 0x1042A,
+ 0x10403 => 0x1042B,
+ 0x10404 => 0x1042C,
+ 0x10405 => 0x1042D,
+ 0x10406 => 0x1042E,
+ 0x10407 => 0x1042F,
+ 0x10408 => 0x10430,
+ 0x10409 => 0x10431,
+ 0x1040A => 0x10432,
+ 0x1040B => 0x10433,
+ 0x1040C => 0x10434,
+ 0x1040D => 0x10435,
+ 0x1040E => 0x10436,
+ 0x1040F => 0x10437,
+ 0x10410 => 0x10438,
+ 0x10411 => 0x10439,
+ 0x10412 => 0x1043A,
+ 0x10413 => 0x1043B,
+ 0x10414 => 0x1043C,
+ 0x10415 => 0x1043D,
+ 0x10416 => 0x1043E,
+ 0x10417 => 0x1043F,
+ 0x10418 => 0x10440,
+ 0x10419 => 0x10441,
+ 0x1041A => 0x10442,
+ 0x1041B => 0x10443,
+ 0x1041C => 0x10444,
+ 0x1041D => 0x10445,
+ 0x1041E => 0x10446,
+ 0x1041F => 0x10447,
+ 0x10420 => 0x10448,
+ 0x10421 => 0x10449,
+ 0x10422 => 0x1044A,
+ 0x10423 => 0x1044B,
+ 0x10424 => 0x1044C,
+ 0x10425 => 0x1044D,
+ 0x10426 => 0x1044E,
+ 0x10427 => 0x1044F,
+ 0x104B0 => 0x104D8,
+ 0x104B1 => 0x104D9,
+ 0x104B2 => 0x104DA,
+ 0x104B3 => 0x104DB,
+ 0x104B4 => 0x104DC,
+ 0x104B5 => 0x104DD,
+ 0x104B6 => 0x104DE,
+ 0x104B7 => 0x104DF,
+ 0x104B8 => 0x104E0,
+ 0x104B9 => 0x104E1,
+ 0x104BA => 0x104E2,
+ 0x104BB => 0x104E3,
+ 0x104BC => 0x104E4,
+ 0x104BD => 0x104E5,
+ 0x104BE => 0x104E6,
+ 0x104BF => 0x104E7,
+ 0x104C0 => 0x104E8,
+ 0x104C1 => 0x104E9,
+ 0x104C2 => 0x104EA,
+ 0x104C3 => 0x104EB,
+ 0x104C4 => 0x104EC,
+ 0x104C5 => 0x104ED,
+ 0x104C6 => 0x104EE,
+ 0x104C7 => 0x104EF,
+ 0x104C8 => 0x104F0,
+ 0x104C9 => 0x104F1,
+ 0x104CA => 0x104F2,
+ 0x104CB => 0x104F3,
+ 0x104CC => 0x104F4,
+ 0x104CD => 0x104F5,
+ 0x104CE => 0x104F6,
+ 0x104CF => 0x104F7,
+ 0x104D0 => 0x104F8,
+ 0x104D1 => 0x104F9,
+ 0x104D2 => 0x104FA,
+ 0x104D3 => 0x104FB,
+ 0x10570 => 0x10597,
+ 0x10571 => 0x10598,
+ 0x10572 => 0x10599,
+ 0x10573 => 0x1059A,
+ 0x10574 => 0x1059B,
+ 0x10575 => 0x1059C,
+ 0x10576 => 0x1059D,
+ 0x10577 => 0x1059E,
+ 0x10578 => 0x1059F,
+ 0x10579 => 0x105A0,
+ 0x1057A => 0x105A1,
+ 0x1057C => 0x105A3,
+ 0x1057D => 0x105A4,
+ 0x1057E => 0x105A5,
+ 0x1057F => 0x105A6,
+ 0x10580 => 0x105A7,
+ 0x10581 => 0x105A8,
+ 0x10582 => 0x105A9,
+ 0x10583 => 0x105AA,
+ 0x10584 => 0x105AB,
+ 0x10585 => 0x105AC,
+ 0x10586 => 0x105AD,
+ 0x10587 => 0x105AE,
+ 0x10588 => 0x105AF,
+ 0x10589 => 0x105B0,
+ 0x1058A => 0x105B1,
+ 0x1058C => 0x105B3,
+ 0x1058D => 0x105B4,
+ 0x1058E => 0x105B5,
+ 0x1058F => 0x105B6,
+ 0x10590 => 0x105B7,
+ 0x10591 => 0x105B8,
+ 0x10592 => 0x105B9,
+ 0x10594 => 0x105BB,
+ 0x10595 => 0x105BC,
+ 0x10C80 => 0x10CC0,
+ 0x10C81 => 0x10CC1,
+ 0x10C82 => 0x10CC2,
+ 0x10C83 => 0x10CC3,
+ 0x10C84 => 0x10CC4,
+ 0x10C85 => 0x10CC5,
+ 0x10C86 => 0x10CC6,
+ 0x10C87 => 0x10CC7,
+ 0x10C88 => 0x10CC8,
+ 0x10C89 => 0x10CC9,
+ 0x10C8A => 0x10CCA,
+ 0x10C8B => 0x10CCB,
+ 0x10C8C => 0x10CCC,
+ 0x10C8D => 0x10CCD,
+ 0x10C8E => 0x10CCE,
+ 0x10C8F => 0x10CCF,
+ 0x10C90 => 0x10CD0,
+ 0x10C91 => 0x10CD1,
+ 0x10C92 => 0x10CD2,
+ 0x10C93 => 0x10CD3,
+ 0x10C94 => 0x10CD4,
+ 0x10C95 => 0x10CD5,
+ 0x10C96 => 0x10CD6,
+ 0x10C97 => 0x10CD7,
+ 0x10C98 => 0x10CD8,
+ 0x10C99 => 0x10CD9,
+ 0x10C9A => 0x10CDA,
+ 0x10C9B => 0x10CDB,
+ 0x10C9C => 0x10CDC,
+ 0x10C9D => 0x10CDD,
+ 0x10C9E => 0x10CDE,
+ 0x10C9F => 0x10CDF,
+ 0x10CA0 => 0x10CE0,
+ 0x10CA1 => 0x10CE1,
+ 0x10CA2 => 0x10CE2,
+ 0x10CA3 => 0x10CE3,
+ 0x10CA4 => 0x10CE4,
+ 0x10CA5 => 0x10CE5,
+ 0x10CA6 => 0x10CE6,
+ 0x10CA7 => 0x10CE7,
+ 0x10CA8 => 0x10CE8,
+ 0x10CA9 => 0x10CE9,
+ 0x10CAA => 0x10CEA,
+ 0x10CAB => 0x10CEB,
+ 0x10CAC => 0x10CEC,
+ 0x10CAD => 0x10CED,
+ 0x10CAE => 0x10CEE,
+ 0x10CAF => 0x10CEF,
+ 0x10CB0 => 0x10CF0,
+ 0x10CB1 => 0x10CF1,
+ 0x10CB2 => 0x10CF2,
+ 0x118A0 => 0x118C0,
+ 0x118A1 => 0x118C1,
+ 0x118A2 => 0x118C2,
+ 0x118A3 => 0x118C3,
+ 0x118A4 => 0x118C4,
+ 0x118A5 => 0x118C5,
+ 0x118A6 => 0x118C6,
+ 0x118A7 => 0x118C7,
+ 0x118A8 => 0x118C8,
+ 0x118A9 => 0x118C9,
+ 0x118AA => 0x118CA,
+ 0x118AB => 0x118CB,
+ 0x118AC => 0x118CC,
+ 0x118AD => 0x118CD,
+ 0x118AE => 0x118CE,
+ 0x118AF => 0x118CF,
+ 0x118B0 => 0x118D0,
+ 0x118B1 => 0x118D1,
+ 0x118B2 => 0x118D2,
+ 0x118B3 => 0x118D3,
+ 0x118B4 => 0x118D4,
+ 0x118B5 => 0x118D5,
+ 0x118B6 => 0x118D6,
+ 0x118B7 => 0x118D7,
+ 0x118B8 => 0x118D8,
+ 0x118B9 => 0x118D9,
+ 0x118BA => 0x118DA,
+ 0x118BB => 0x118DB,
+ 0x118BC => 0x118DC,
+ 0x118BD => 0x118DD,
+ 0x118BE => 0x118DE,
+ 0x118BF => 0x118DF,
+ 0x16E40 => 0x16E60,
+ 0x16E41 => 0x16E61,
+ 0x16E42 => 0x16E62,
+ 0x16E43 => 0x16E63,
+ 0x16E44 => 0x16E64,
+ 0x16E45 => 0x16E65,
+ 0x16E46 => 0x16E66,
+ 0x16E47 => 0x16E67,
+ 0x16E48 => 0x16E68,
+ 0x16E49 => 0x16E69,
+ 0x16E4A => 0x16E6A,
+ 0x16E4B => 0x16E6B,
+ 0x16E4C => 0x16E6C,
+ 0x16E4D => 0x16E6D,
+ 0x16E4E => 0x16E6E,
+ 0x16E4F => 0x16E6F,
+ 0x16E50 => 0x16E70,
+ 0x16E51 => 0x16E71,
+ 0x16E52 => 0x16E72,
+ 0x16E53 => 0x16E73,
+ 0x16E54 => 0x16E74,
+ 0x16E55 => 0x16E75,
+ 0x16E56 => 0x16E76,
+ 0x16E57 => 0x16E77,
+ 0x16E58 => 0x16E78,
+ 0x16E59 => 0x16E79,
+ 0x16E5A => 0x16E7A,
+ 0x16E5B => 0x16E7B,
+ 0x16E5C => 0x16E7C,
+ 0x16E5D => 0x16E7D,
+ 0x16E5E => 0x16E7E,
+ 0x16E5F => 0x16E7F,
+ 0x1E900 => 0x1E922,
+ 0x1E901 => 0x1E923,
+ 0x1E902 => 0x1E924,
+ 0x1E903 => 0x1E925,
+ 0x1E904 => 0x1E926,
+ 0x1E905 => 0x1E927,
+ 0x1E906 => 0x1E928,
+ 0x1E907 => 0x1E929,
+ 0x1E908 => 0x1E92A,
+ 0x1E909 => 0x1E92B,
+ 0x1E90A => 0x1E92C,
+ 0x1E90B => 0x1E92D,
+ 0x1E90C => 0x1E92E,
+ 0x1E90D => 0x1E92F,
+ 0x1E90E => 0x1E930,
+ 0x1E90F => 0x1E931,
+ 0x1E910 => 0x1E932,
+ 0x1E911 => 0x1E933,
+ 0x1E912 => 0x1E934,
+ 0x1E913 => 0x1E935,
+ 0x1E914 => 0x1E936,
+ 0x1E915 => 0x1E937,
+ 0x1E916 => 0x1E938,
+ 0x1E917 => 0x1E939,
+ 0x1E918 => 0x1E93A,
+ 0x1E919 => 0x1E93B,
+ 0x1E91A => 0x1E93C,
+ 0x1E91B => 0x1E93D,
+ 0x1E91C => 0x1E93E,
+ 0x1E91D => 0x1E93F,
+ 0x1E91E => 0x1E940,
+ 0x1E91F => 0x1E941,
+ 0x1E920 => 0x1E942,
+ 0x1E921 => 0x1E943,
+ else => cp,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/prop_list.zig.html b/docs/src/ziglyph/autogen/prop_list.zig.html
new file mode 100644
index 0000000..84c12a1
--- /dev/null
+++ b/docs/src/ziglyph/autogen/prop_list.zig.html
@@ -0,0 +1,1978 @@
+
+
+
+
+
autogen/prop_list.zig - source view
+
+
+
+
+
+
+
+
+pub fn isWhiteSpace(cp: u21) bool {
+ if (cp < 0x9 or cp > 0x3000) return false;
+
+ return switch (cp) {
+ 0x9...0xd => true,
+ 0x20 => true,
+ 0x85 => true,
+ 0xa0 => true,
+ 0x1680 => true,
+ 0x2000...0x200a => true,
+ 0x2028 => true,
+ 0x2029 => true,
+ 0x202f => true,
+ 0x205f => true,
+ 0x3000 => true,
+ else => false,
+ };
+}
+
+pub fn isBidiControl(cp: u21) bool {
+ if (cp < 0x61c or cp > 0x2069) return false;
+
+ return switch (cp) {
+ 0x61c => true,
+ 0x200e...0x200f => true,
+ 0x202a...0x202e => true,
+ 0x2066...0x2069 => true,
+ else => false,
+ };
+}
+
+pub fn isJoinControl(cp: u21) bool {
+ if (cp < 0x200c or cp > 0x200d) return false;
+
+ return switch (cp) {
+ 0x200c...0x200d => true,
+ else => false,
+ };
+}
+
+pub fn isDash(cp: u21) bool {
+ if (cp < 0x2d or cp > 0x10ead) return false;
+
+ return switch (cp) {
+ 0x2d => true,
+ 0x58a => true,
+ 0x5be => true,
+ 0x1400 => true,
+ 0x1806 => true,
+ 0x2010...0x2015 => true,
+ 0x2053 => true,
+ 0x207b => true,
+ 0x208b => true,
+ 0x2212 => true,
+ 0x2e17 => true,
+ 0x2e1a => true,
+ 0x2e3a...0x2e3b => true,
+ 0x2e40 => true,
+ 0x2e5d => true,
+ 0x301c => true,
+ 0x3030 => true,
+ 0x30a0 => true,
+ 0xfe31...0xfe32 => true,
+ 0xfe58 => true,
+ 0xfe63 => true,
+ 0xff0d => true,
+ 0x10ead => true,
+ else => false,
+ };
+}
+
+pub fn isHyphen(cp: u21) bool {
+ if (cp < 0x2d or cp > 0xff65) return false;
+
+ return switch (cp) {
+ 0x2d => true,
+ 0xad => true,
+ 0x58a => true,
+ 0x1806 => true,
+ 0x2010...0x2011 => true,
+ 0x2e17 => true,
+ 0x30fb => true,
+ 0xfe63 => true,
+ 0xff0d => true,
+ 0xff65 => true,
+ else => false,
+ };
+}
+
+pub fn isQuotationMark(cp: u21) bool {
+ if (cp < 0x22 or cp > 0xff63) return false;
+
+ return switch (cp) {
+ 0x22 => true,
+ 0x27 => true,
+ 0xab => true,
+ 0xbb => true,
+ 0x2018 => true,
+ 0x2019 => true,
+ 0x201a => true,
+ 0x201b...0x201c => true,
+ 0x201d => true,
+ 0x201e => true,
+ 0x201f => true,
+ 0x2039 => true,
+ 0x203a => true,
+ 0x2e42 => true,
+ 0x300c => true,
+ 0x300d => true,
+ 0x300e => true,
+ 0x300f => true,
+ 0x301d => true,
+ 0x301e...0x301f => true,
+ 0xfe41 => true,
+ 0xfe42 => true,
+ 0xfe43 => true,
+ 0xfe44 => true,
+ 0xff02 => true,
+ 0xff07 => true,
+ 0xff62 => true,
+ 0xff63 => true,
+ else => false,
+ };
+}
+
+pub fn isTerminalPunctuation(cp: u21) bool {
+ if (cp < 0x21 or cp > 0x1da8a) return false;
+
+ return switch (cp) {
+ 0x21 => true,
+ 0x2c => true,
+ 0x2e => true,
+ 0x3a...0x3b => true,
+ 0x3f => true,
+ 0x37e => true,
+ 0x387 => true,
+ 0x589 => true,
+ 0x5c3 => true,
+ 0x60c => true,
+ 0x61b => true,
+ 0x61d...0x61f => true,
+ 0x6d4 => true,
+ 0x700...0x70a => true,
+ 0x70c => true,
+ 0x7f8...0x7f9 => true,
+ 0x830...0x83e => true,
+ 0x85e => true,
+ 0x964...0x965 => true,
+ 0xe5a...0xe5b => true,
+ 0xf08 => true,
+ 0xf0d...0xf12 => true,
+ 0x104a...0x104b => true,
+ 0x1361...0x1368 => true,
+ 0x166e => true,
+ 0x16eb...0x16ed => true,
+ 0x1735...0x1736 => true,
+ 0x17d4...0x17d6 => true,
+ 0x17da => true,
+ 0x1802...0x1805 => true,
+ 0x1808...0x1809 => true,
+ 0x1944...0x1945 => true,
+ 0x1aa8...0x1aab => true,
+ 0x1b5a...0x1b5b => true,
+ 0x1b5d...0x1b5f => true,
+ 0x1b7d...0x1b7e => true,
+ 0x1c3b...0x1c3f => true,
+ 0x1c7e...0x1c7f => true,
+ 0x203c...0x203d => true,
+ 0x2047...0x2049 => true,
+ 0x2e2e => true,
+ 0x2e3c => true,
+ 0x2e41 => true,
+ 0x2e4c => true,
+ 0x2e4e...0x2e4f => true,
+ 0x2e53...0x2e54 => true,
+ 0x3001...0x3002 => true,
+ 0xa4fe...0xa4ff => true,
+ 0xa60d...0xa60f => true,
+ 0xa6f3...0xa6f7 => true,
+ 0xa876...0xa877 => true,
+ 0xa8ce...0xa8cf => true,
+ 0xa92f => true,
+ 0xa9c7...0xa9c9 => true,
+ 0xaa5d...0xaa5f => true,
+ 0xaadf => true,
+ 0xaaf0...0xaaf1 => true,
+ 0xabeb => true,
+ 0xfe50...0xfe52 => true,
+ 0xfe54...0xfe57 => true,
+ 0xff01 => true,
+ 0xff0c => true,
+ 0xff0e => true,
+ 0xff1a...0xff1b => true,
+ 0xff1f => true,
+ 0xff61 => true,
+ 0xff64 => true,
+ 0x1039f => true,
+ 0x103d0 => true,
+ 0x10857 => true,
+ 0x1091f => true,
+ 0x10a56...0x10a57 => true,
+ 0x10af0...0x10af5 => true,
+ 0x10b3a...0x10b3f => true,
+ 0x10b99...0x10b9c => true,
+ 0x10f55...0x10f59 => true,
+ 0x10f86...0x10f89 => true,
+ 0x11047...0x1104d => true,
+ 0x110be...0x110c1 => true,
+ 0x11141...0x11143 => true,
+ 0x111c5...0x111c6 => true,
+ 0x111cd => true,
+ 0x111de...0x111df => true,
+ 0x11238...0x1123c => true,
+ 0x112a9 => true,
+ 0x1144b...0x1144d => true,
+ 0x1145a...0x1145b => true,
+ 0x115c2...0x115c5 => true,
+ 0x115c9...0x115d7 => true,
+ 0x11641...0x11642 => true,
+ 0x1173c...0x1173e => true,
+ 0x11944 => true,
+ 0x11946 => true,
+ 0x11a42...0x11a43 => true,
+ 0x11a9b...0x11a9c => true,
+ 0x11aa1...0x11aa2 => true,
+ 0x11c41...0x11c43 => true,
+ 0x11c71 => true,
+ 0x11ef7...0x11ef8 => true,
+ 0x11f43...0x11f44 => true,
+ 0x12470...0x12474 => true,
+ 0x16a6e...0x16a6f => true,
+ 0x16af5 => true,
+ 0x16b37...0x16b39 => true,
+ 0x16b44 => true,
+ 0x16e97...0x16e98 => true,
+ 0x1bc9f => true,
+ 0x1da87...0x1da8a => true,
+ else => false,
+ };
+}
+
+pub fn isOtherMath(cp: u21) bool {
+ if (cp < 0x5e or cp > 0x1eebb) return false;
+
+ return switch (cp) {
+ 0x5e => true,
+ 0x3d0...0x3d2 => true,
+ 0x3d5 => true,
+ 0x3f0...0x3f1 => true,
+ 0x3f4...0x3f5 => true,
+ 0x2016 => true,
+ 0x2032...0x2034 => true,
+ 0x2040 => true,
+ 0x2061...0x2064 => true,
+ 0x207d => true,
+ 0x207e => true,
+ 0x208d => true,
+ 0x208e => true,
+ 0x20d0...0x20dc => true,
+ 0x20e1 => true,
+ 0x20e5...0x20e6 => true,
+ 0x20eb...0x20ef => true,
+ 0x2102 => true,
+ 0x2107 => true,
+ 0x210a...0x2113 => true,
+ 0x2115 => true,
+ 0x2119...0x211d => true,
+ 0x2124 => true,
+ 0x2128 => true,
+ 0x2129 => true,
+ 0x212c...0x212d => true,
+ 0x212f...0x2131 => true,
+ 0x2133...0x2134 => true,
+ 0x2135...0x2138 => true,
+ 0x213c...0x213f => true,
+ 0x2145...0x2149 => true,
+ 0x2195...0x2199 => true,
+ 0x219c...0x219f => true,
+ 0x21a1...0x21a2 => true,
+ 0x21a4...0x21a5 => true,
+ 0x21a7 => true,
+ 0x21a9...0x21ad => true,
+ 0x21b0...0x21b1 => true,
+ 0x21b6...0x21b7 => true,
+ 0x21bc...0x21cd => true,
+ 0x21d0...0x21d1 => true,
+ 0x21d3 => true,
+ 0x21d5...0x21db => true,
+ 0x21dd => true,
+ 0x21e4...0x21e5 => true,
+ 0x2308 => true,
+ 0x2309 => true,
+ 0x230a => true,
+ 0x230b => true,
+ 0x23b4...0x23b5 => true,
+ 0x23b7 => true,
+ 0x23d0 => true,
+ 0x23e2 => true,
+ 0x25a0...0x25a1 => true,
+ 0x25ae...0x25b6 => true,
+ 0x25bc...0x25c0 => true,
+ 0x25c6...0x25c7 => true,
+ 0x25ca...0x25cb => true,
+ 0x25cf...0x25d3 => true,
+ 0x25e2 => true,
+ 0x25e4 => true,
+ 0x25e7...0x25ec => true,
+ 0x2605...0x2606 => true,
+ 0x2640 => true,
+ 0x2642 => true,
+ 0x2660...0x2663 => true,
+ 0x266d...0x266e => true,
+ 0x27c5 => true,
+ 0x27c6 => true,
+ 0x27e6 => true,
+ 0x27e7 => true,
+ 0x27e8 => true,
+ 0x27e9 => true,
+ 0x27ea => true,
+ 0x27eb => true,
+ 0x27ec => true,
+ 0x27ed => true,
+ 0x27ee => true,
+ 0x27ef => true,
+ 0x2983 => true,
+ 0x2984 => true,
+ 0x2985 => true,
+ 0x2986 => true,
+ 0x2987 => true,
+ 0x2988 => true,
+ 0x2989 => true,
+ 0x298a => true,
+ 0x298b => true,
+ 0x298c => true,
+ 0x298d => true,
+ 0x298e => true,
+ 0x298f => true,
+ 0x2990 => true,
+ 0x2991 => true,
+ 0x2992 => true,
+ 0x2993 => true,
+ 0x2994 => true,
+ 0x2995 => true,
+ 0x2996 => true,
+ 0x2997 => true,
+ 0x2998 => true,
+ 0x29d8 => true,
+ 0x29d9 => true,
+ 0x29da => true,
+ 0x29db => true,
+ 0x29fc => true,
+ 0x29fd => true,
+ 0xfe61 => true,
+ 0xfe63 => true,
+ 0xfe68 => true,
+ 0xff3c => true,
+ 0xff3e => true,
+ 0x1d400...0x1d454 => true,
+ 0x1d456...0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d51e...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d552...0x1d6a5 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6dc...0x1d6fa => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d716...0x1d734 => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d750...0x1d76e => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d78a...0x1d7a8 => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c4...0x1d7cb => true,
+ 0x1d7ce...0x1d7ff => true,
+ 0x1ee00...0x1ee03 => true,
+ 0x1ee05...0x1ee1f => true,
+ 0x1ee21...0x1ee22 => true,
+ 0x1ee24 => true,
+ 0x1ee27 => true,
+ 0x1ee29...0x1ee32 => true,
+ 0x1ee34...0x1ee37 => true,
+ 0x1ee39 => true,
+ 0x1ee3b => true,
+ 0x1ee42 => true,
+ 0x1ee47 => true,
+ 0x1ee49 => true,
+ 0x1ee4b => true,
+ 0x1ee4d...0x1ee4f => true,
+ 0x1ee51...0x1ee52 => true,
+ 0x1ee54 => true,
+ 0x1ee57 => true,
+ 0x1ee59 => true,
+ 0x1ee5b => true,
+ 0x1ee5d => true,
+ 0x1ee5f => true,
+ 0x1ee61...0x1ee62 => true,
+ 0x1ee64 => true,
+ 0x1ee67...0x1ee6a => true,
+ 0x1ee6c...0x1ee72 => true,
+ 0x1ee74...0x1ee77 => true,
+ 0x1ee79...0x1ee7c => true,
+ 0x1ee7e => true,
+ 0x1ee80...0x1ee89 => true,
+ 0x1ee8b...0x1ee9b => true,
+ 0x1eea1...0x1eea3 => true,
+ 0x1eea5...0x1eea9 => true,
+ 0x1eeab...0x1eebb => true,
+ else => false,
+ };
+}
+
+pub fn isHexDigit(cp: u21) bool {
+ if (cp < 0x30 or cp > 0xff46) return false;
+
+ return switch (cp) {
+ 0x30...0x39 => true,
+ 0x41...0x46 => true,
+ 0x61...0x66 => true,
+ 0xff10...0xff19 => true,
+ 0xff21...0xff26 => true,
+ 0xff41...0xff46 => true,
+ else => false,
+ };
+}
+
+pub fn isAsciiHexDigit(cp: u21) bool {
+ if (cp < 0x30 or cp > 0x66) return false;
+
+ return switch (cp) {
+ 0x30...0x39 => true,
+ 0x41...0x46 => true,
+ 0x61...0x66 => true,
+ else => false,
+ };
+}
+
+pub fn isOtherAlphabetic(cp: u21) bool {
+ if (cp < 0x345 or cp > 0x1f189) return false;
+
+ return switch (cp) {
+ 0x345 => true,
+ 0x5b0...0x5bd => true,
+ 0x5bf => true,
+ 0x5c1...0x5c2 => true,
+ 0x5c4...0x5c5 => true,
+ 0x5c7 => true,
+ 0x610...0x61a => true,
+ 0x64b...0x657 => true,
+ 0x659...0x65f => true,
+ 0x670 => true,
+ 0x6d6...0x6dc => true,
+ 0x6e1...0x6e4 => true,
+ 0x6e7...0x6e8 => true,
+ 0x6ed => true,
+ 0x711 => true,
+ 0x730...0x73f => true,
+ 0x7a6...0x7b0 => true,
+ 0x816...0x817 => true,
+ 0x81b...0x823 => true,
+ 0x825...0x827 => true,
+ 0x829...0x82c => true,
+ 0x8d4...0x8df => true,
+ 0x8e3...0x8e9 => true,
+ 0x8f0...0x902 => true,
+ 0x903 => true,
+ 0x93a => true,
+ 0x93b => true,
+ 0x93e...0x940 => true,
+ 0x941...0x948 => true,
+ 0x949...0x94c => true,
+ 0x94e...0x94f => true,
+ 0x955...0x957 => true,
+ 0x962...0x963 => true,
+ 0x981 => true,
+ 0x982...0x983 => true,
+ 0x9be...0x9c0 => true,
+ 0x9c1...0x9c4 => true,
+ 0x9c7...0x9c8 => true,
+ 0x9cb...0x9cc => true,
+ 0x9d7 => true,
+ 0x9e2...0x9e3 => true,
+ 0xa01...0xa02 => true,
+ 0xa03 => true,
+ 0xa3e...0xa40 => true,
+ 0xa41...0xa42 => true,
+ 0xa47...0xa48 => true,
+ 0xa4b...0xa4c => true,
+ 0xa51 => true,
+ 0xa70...0xa71 => true,
+ 0xa75 => true,
+ 0xa81...0xa82 => true,
+ 0xa83 => true,
+ 0xabe...0xac0 => true,
+ 0xac1...0xac5 => true,
+ 0xac7...0xac8 => true,
+ 0xac9 => true,
+ 0xacb...0xacc => true,
+ 0xae2...0xae3 => true,
+ 0xafa...0xafc => true,
+ 0xb01 => true,
+ 0xb02...0xb03 => true,
+ 0xb3e => true,
+ 0xb3f => true,
+ 0xb40 => true,
+ 0xb41...0xb44 => true,
+ 0xb47...0xb48 => true,
+ 0xb4b...0xb4c => true,
+ 0xb56 => true,
+ 0xb57 => true,
+ 0xb62...0xb63 => true,
+ 0xb82 => true,
+ 0xbbe...0xbbf => true,
+ 0xbc0 => true,
+ 0xbc1...0xbc2 => true,
+ 0xbc6...0xbc8 => true,
+ 0xbca...0xbcc => true,
+ 0xbd7 => true,
+ 0xc00 => true,
+ 0xc01...0xc03 => true,
+ 0xc04 => true,
+ 0xc3e...0xc40 => true,
+ 0xc41...0xc44 => true,
+ 0xc46...0xc48 => true,
+ 0xc4a...0xc4c => true,
+ 0xc55...0xc56 => true,
+ 0xc62...0xc63 => true,
+ 0xc81 => true,
+ 0xc82...0xc83 => true,
+ 0xcbe => true,
+ 0xcbf => true,
+ 0xcc0...0xcc4 => true,
+ 0xcc6 => true,
+ 0xcc7...0xcc8 => true,
+ 0xcca...0xccb => true,
+ 0xccc => true,
+ 0xcd5...0xcd6 => true,
+ 0xce2...0xce3 => true,
+ 0xcf3 => true,
+ 0xd00...0xd01 => true,
+ 0xd02...0xd03 => true,
+ 0xd3e...0xd40 => true,
+ 0xd41...0xd44 => true,
+ 0xd46...0xd48 => true,
+ 0xd4a...0xd4c => true,
+ 0xd57 => true,
+ 0xd62...0xd63 => true,
+ 0xd81 => true,
+ 0xd82...0xd83 => true,
+ 0xdcf...0xdd1 => true,
+ 0xdd2...0xdd4 => true,
+ 0xdd6 => true,
+ 0xdd8...0xddf => true,
+ 0xdf2...0xdf3 => true,
+ 0xe31 => true,
+ 0xe34...0xe3a => true,
+ 0xe4d => true,
+ 0xeb1 => true,
+ 0xeb4...0xeb9 => true,
+ 0xebb...0xebc => true,
+ 0xecd => true,
+ 0xf71...0xf7e => true,
+ 0xf7f => true,
+ 0xf80...0xf83 => true,
+ 0xf8d...0xf97 => true,
+ 0xf99...0xfbc => true,
+ 0x102b...0x102c => true,
+ 0x102d...0x1030 => true,
+ 0x1031 => true,
+ 0x1032...0x1036 => true,
+ 0x1038 => true,
+ 0x103b...0x103c => true,
+ 0x103d...0x103e => true,
+ 0x1056...0x1057 => true,
+ 0x1058...0x1059 => true,
+ 0x105e...0x1060 => true,
+ 0x1062...0x1064 => true,
+ 0x1067...0x106d => true,
+ 0x1071...0x1074 => true,
+ 0x1082 => true,
+ 0x1083...0x1084 => true,
+ 0x1085...0x1086 => true,
+ 0x1087...0x108c => true,
+ 0x108d => true,
+ 0x108f => true,
+ 0x109a...0x109c => true,
+ 0x109d => true,
+ 0x1712...0x1713 => true,
+ 0x1732...0x1733 => true,
+ 0x1752...0x1753 => true,
+ 0x1772...0x1773 => true,
+ 0x17b6 => true,
+ 0x17b7...0x17bd => true,
+ 0x17be...0x17c5 => true,
+ 0x17c6 => true,
+ 0x17c7...0x17c8 => true,
+ 0x1885...0x1886 => true,
+ 0x18a9 => true,
+ 0x1920...0x1922 => true,
+ 0x1923...0x1926 => true,
+ 0x1927...0x1928 => true,
+ 0x1929...0x192b => true,
+ 0x1930...0x1931 => true,
+ 0x1932 => true,
+ 0x1933...0x1938 => true,
+ 0x1a17...0x1a18 => true,
+ 0x1a19...0x1a1a => true,
+ 0x1a1b => true,
+ 0x1a55 => true,
+ 0x1a56 => true,
+ 0x1a57 => true,
+ 0x1a58...0x1a5e => true,
+ 0x1a61 => true,
+ 0x1a62 => true,
+ 0x1a63...0x1a64 => true,
+ 0x1a65...0x1a6c => true,
+ 0x1a6d...0x1a72 => true,
+ 0x1a73...0x1a74 => true,
+ 0x1abf...0x1ac0 => true,
+ 0x1acc...0x1ace => true,
+ 0x1b00...0x1b03 => true,
+ 0x1b04 => true,
+ 0x1b35 => true,
+ 0x1b36...0x1b3a => true,
+ 0x1b3b => true,
+ 0x1b3c => true,
+ 0x1b3d...0x1b41 => true,
+ 0x1b42 => true,
+ 0x1b43 => true,
+ 0x1b80...0x1b81 => true,
+ 0x1b82 => true,
+ 0x1ba1 => true,
+ 0x1ba2...0x1ba5 => true,
+ 0x1ba6...0x1ba7 => true,
+ 0x1ba8...0x1ba9 => true,
+ 0x1bac...0x1bad => true,
+ 0x1be7 => true,
+ 0x1be8...0x1be9 => true,
+ 0x1bea...0x1bec => true,
+ 0x1bed => true,
+ 0x1bee => true,
+ 0x1bef...0x1bf1 => true,
+ 0x1c24...0x1c2b => true,
+ 0x1c2c...0x1c33 => true,
+ 0x1c34...0x1c35 => true,
+ 0x1c36 => true,
+ 0x1de7...0x1df4 => true,
+ 0x24b6...0x24e9 => true,
+ 0x2de0...0x2dff => true,
+ 0xa674...0xa67b => true,
+ 0xa69e...0xa69f => true,
+ 0xa802 => true,
+ 0xa80b => true,
+ 0xa823...0xa824 => true,
+ 0xa825...0xa826 => true,
+ 0xa827 => true,
+ 0xa880...0xa881 => true,
+ 0xa8b4...0xa8c3 => true,
+ 0xa8c5 => true,
+ 0xa8ff => true,
+ 0xa926...0xa92a => true,
+ 0xa947...0xa951 => true,
+ 0xa952 => true,
+ 0xa980...0xa982 => true,
+ 0xa983 => true,
+ 0xa9b4...0xa9b5 => true,
+ 0xa9b6...0xa9b9 => true,
+ 0xa9ba...0xa9bb => true,
+ 0xa9bc...0xa9bd => true,
+ 0xa9be...0xa9bf => true,
+ 0xa9e5 => true,
+ 0xaa29...0xaa2e => true,
+ 0xaa2f...0xaa30 => true,
+ 0xaa31...0xaa32 => true,
+ 0xaa33...0xaa34 => true,
+ 0xaa35...0xaa36 => true,
+ 0xaa43 => true,
+ 0xaa4c => true,
+ 0xaa4d => true,
+ 0xaa7b => true,
+ 0xaa7c => true,
+ 0xaa7d => true,
+ 0xaab0 => true,
+ 0xaab2...0xaab4 => true,
+ 0xaab7...0xaab8 => true,
+ 0xaabe => true,
+ 0xaaeb => true,
+ 0xaaec...0xaaed => true,
+ 0xaaee...0xaaef => true,
+ 0xaaf5 => true,
+ 0xabe3...0xabe4 => true,
+ 0xabe5 => true,
+ 0xabe6...0xabe7 => true,
+ 0xabe8 => true,
+ 0xabe9...0xabea => true,
+ 0xfb1e => true,
+ 0x10376...0x1037a => true,
+ 0x10a01...0x10a03 => true,
+ 0x10a05...0x10a06 => true,
+ 0x10a0c...0x10a0f => true,
+ 0x10d24...0x10d27 => true,
+ 0x10eab...0x10eac => true,
+ 0x11000 => true,
+ 0x11001 => true,
+ 0x11002 => true,
+ 0x11038...0x11045 => true,
+ 0x11073...0x11074 => true,
+ 0x11080...0x11081 => true,
+ 0x11082 => true,
+ 0x110b0...0x110b2 => true,
+ 0x110b3...0x110b6 => true,
+ 0x110b7...0x110b8 => true,
+ 0x110c2 => true,
+ 0x11100...0x11102 => true,
+ 0x11127...0x1112b => true,
+ 0x1112c => true,
+ 0x1112d...0x11132 => true,
+ 0x11145...0x11146 => true,
+ 0x11180...0x11181 => true,
+ 0x11182 => true,
+ 0x111b3...0x111b5 => true,
+ 0x111b6...0x111be => true,
+ 0x111bf => true,
+ 0x111ce => true,
+ 0x111cf => true,
+ 0x1122c...0x1122e => true,
+ 0x1122f...0x11231 => true,
+ 0x11232...0x11233 => true,
+ 0x11234 => true,
+ 0x11237 => true,
+ 0x1123e => true,
+ 0x11241 => true,
+ 0x112df => true,
+ 0x112e0...0x112e2 => true,
+ 0x112e3...0x112e8 => true,
+ 0x11300...0x11301 => true,
+ 0x11302...0x11303 => true,
+ 0x1133e...0x1133f => true,
+ 0x11340 => true,
+ 0x11341...0x11344 => true,
+ 0x11347...0x11348 => true,
+ 0x1134b...0x1134c => true,
+ 0x11357 => true,
+ 0x11362...0x11363 => true,
+ 0x11435...0x11437 => true,
+ 0x11438...0x1143f => true,
+ 0x11440...0x11441 => true,
+ 0x11443...0x11444 => true,
+ 0x11445 => true,
+ 0x114b0...0x114b2 => true,
+ 0x114b3...0x114b8 => true,
+ 0x114b9 => true,
+ 0x114ba => true,
+ 0x114bb...0x114be => true,
+ 0x114bf...0x114c0 => true,
+ 0x114c1 => true,
+ 0x115af...0x115b1 => true,
+ 0x115b2...0x115b5 => true,
+ 0x115b8...0x115bb => true,
+ 0x115bc...0x115bd => true,
+ 0x115be => true,
+ 0x115dc...0x115dd => true,
+ 0x11630...0x11632 => true,
+ 0x11633...0x1163a => true,
+ 0x1163b...0x1163c => true,
+ 0x1163d => true,
+ 0x1163e => true,
+ 0x11640 => true,
+ 0x116ab => true,
+ 0x116ac => true,
+ 0x116ad => true,
+ 0x116ae...0x116af => true,
+ 0x116b0...0x116b5 => true,
+ 0x1171d...0x1171f => true,
+ 0x11720...0x11721 => true,
+ 0x11722...0x11725 => true,
+ 0x11726 => true,
+ 0x11727...0x1172a => true,
+ 0x1182c...0x1182e => true,
+ 0x1182f...0x11837 => true,
+ 0x11838 => true,
+ 0x11930...0x11935 => true,
+ 0x11937...0x11938 => true,
+ 0x1193b...0x1193c => true,
+ 0x11940 => true,
+ 0x11942 => true,
+ 0x119d1...0x119d3 => true,
+ 0x119d4...0x119d7 => true,
+ 0x119da...0x119db => true,
+ 0x119dc...0x119df => true,
+ 0x119e4 => true,
+ 0x11a01...0x11a0a => true,
+ 0x11a35...0x11a38 => true,
+ 0x11a39 => true,
+ 0x11a3b...0x11a3e => true,
+ 0x11a51...0x11a56 => true,
+ 0x11a57...0x11a58 => true,
+ 0x11a59...0x11a5b => true,
+ 0x11a8a...0x11a96 => true,
+ 0x11a97 => true,
+ 0x11c2f => true,
+ 0x11c30...0x11c36 => true,
+ 0x11c38...0x11c3d => true,
+ 0x11c3e => true,
+ 0x11c92...0x11ca7 => true,
+ 0x11ca9 => true,
+ 0x11caa...0x11cb0 => true,
+ 0x11cb1 => true,
+ 0x11cb2...0x11cb3 => true,
+ 0x11cb4 => true,
+ 0x11cb5...0x11cb6 => true,
+ 0x11d31...0x11d36 => true,
+ 0x11d3a => true,
+ 0x11d3c...0x11d3d => true,
+ 0x11d3f...0x11d41 => true,
+ 0x11d43 => true,
+ 0x11d47 => true,
+ 0x11d8a...0x11d8e => true,
+ 0x11d90...0x11d91 => true,
+ 0x11d93...0x11d94 => true,
+ 0x11d95 => true,
+ 0x11d96 => true,
+ 0x11ef3...0x11ef4 => true,
+ 0x11ef5...0x11ef6 => true,
+ 0x11f00...0x11f01 => true,
+ 0x11f03 => true,
+ 0x11f34...0x11f35 => true,
+ 0x11f36...0x11f3a => true,
+ 0x11f3e...0x11f3f => true,
+ 0x11f40 => true,
+ 0x16f4f => true,
+ 0x16f51...0x16f87 => true,
+ 0x16f8f...0x16f92 => true,
+ 0x16ff0...0x16ff1 => true,
+ 0x1bc9e => true,
+ 0x1e000...0x1e006 => true,
+ 0x1e008...0x1e018 => true,
+ 0x1e01b...0x1e021 => true,
+ 0x1e023...0x1e024 => true,
+ 0x1e026...0x1e02a => true,
+ 0x1e08f => true,
+ 0x1e947 => true,
+ 0x1f130...0x1f149 => true,
+ 0x1f150...0x1f169 => true,
+ 0x1f170...0x1f189 => true,
+ else => false,
+ };
+}
+
+pub fn isIdeographic(cp: u21) bool {
+ if (cp < 0x3006 or cp > 0x323af) return false;
+
+ return switch (cp) {
+ 0x3006 => true,
+ 0x3007 => true,
+ 0x3021...0x3029 => true,
+ 0x3038...0x303a => true,
+ 0x3400...0x4dbf => true,
+ 0x4e00...0x9fff => true,
+ 0xf900...0xfa6d => true,
+ 0xfa70...0xfad9 => true,
+ 0x16fe4 => true,
+ 0x17000...0x187f7 => true,
+ 0x18800...0x18cd5 => true,
+ 0x18d00...0x18d08 => true,
+ 0x1b170...0x1b2fb => true,
+ 0x20000...0x2a6df => true,
+ 0x2a700...0x2b739 => true,
+ 0x2b740...0x2b81d => true,
+ 0x2b820...0x2cea1 => true,
+ 0x2ceb0...0x2ebe0 => true,
+ 0x2f800...0x2fa1d => true,
+ 0x30000...0x3134a => true,
+ 0x31350...0x323af => true,
+ else => false,
+ };
+}
+
+pub fn isDiacritic(cp: u21) bool {
+ if (cp < 0x5e or cp > 0x1e94a) return false;
+
+ return switch (cp) {
+ 0x5e => true,
+ 0x60 => true,
+ 0xa8 => true,
+ 0xaf => true,
+ 0xb4 => true,
+ 0xb7 => true,
+ 0xb8 => true,
+ 0x2b0...0x2c1 => true,
+ 0x2c2...0x2c5 => true,
+ 0x2c6...0x2d1 => true,
+ 0x2d2...0x2df => true,
+ 0x2e0...0x2e4 => true,
+ 0x2e5...0x2eb => true,
+ 0x2ec => true,
+ 0x2ed => true,
+ 0x2ee => true,
+ 0x2ef...0x2ff => true,
+ 0x300...0x34e => true,
+ 0x350...0x357 => true,
+ 0x35d...0x362 => true,
+ 0x374 => true,
+ 0x375 => true,
+ 0x37a => true,
+ 0x384...0x385 => true,
+ 0x483...0x487 => true,
+ 0x559 => true,
+ 0x591...0x5a1 => true,
+ 0x5a3...0x5bd => true,
+ 0x5bf => true,
+ 0x5c1...0x5c2 => true,
+ 0x5c4 => true,
+ 0x64b...0x652 => true,
+ 0x657...0x658 => true,
+ 0x6df...0x6e0 => true,
+ 0x6e5...0x6e6 => true,
+ 0x6ea...0x6ec => true,
+ 0x730...0x74a => true,
+ 0x7a6...0x7b0 => true,
+ 0x7eb...0x7f3 => true,
+ 0x7f4...0x7f5 => true,
+ 0x818...0x819 => true,
+ 0x898...0x89f => true,
+ 0x8c9 => true,
+ 0x8ca...0x8d2 => true,
+ 0x8e3...0x8fe => true,
+ 0x93c => true,
+ 0x94d => true,
+ 0x951...0x954 => true,
+ 0x971 => true,
+ 0x9bc => true,
+ 0x9cd => true,
+ 0xa3c => true,
+ 0xa4d => true,
+ 0xabc => true,
+ 0xacd => true,
+ 0xafd...0xaff => true,
+ 0xb3c => true,
+ 0xb4d => true,
+ 0xb55 => true,
+ 0xbcd => true,
+ 0xc3c => true,
+ 0xc4d => true,
+ 0xcbc => true,
+ 0xccd => true,
+ 0xd3b...0xd3c => true,
+ 0xd4d => true,
+ 0xdca => true,
+ 0xe47...0xe4c => true,
+ 0xe4e => true,
+ 0xeba => true,
+ 0xec8...0xecc => true,
+ 0xf18...0xf19 => true,
+ 0xf35 => true,
+ 0xf37 => true,
+ 0xf39 => true,
+ 0xf3e...0xf3f => true,
+ 0xf82...0xf84 => true,
+ 0xf86...0xf87 => true,
+ 0xfc6 => true,
+ 0x1037 => true,
+ 0x1039...0x103a => true,
+ 0x1063...0x1064 => true,
+ 0x1069...0x106d => true,
+ 0x1087...0x108c => true,
+ 0x108d => true,
+ 0x108f => true,
+ 0x109a...0x109b => true,
+ 0x135d...0x135f => true,
+ 0x1714 => true,
+ 0x1715 => true,
+ 0x17c9...0x17d3 => true,
+ 0x17dd => true,
+ 0x1939...0x193b => true,
+ 0x1a75...0x1a7c => true,
+ 0x1a7f => true,
+ 0x1ab0...0x1abd => true,
+ 0x1abe => true,
+ 0x1ac1...0x1acb => true,
+ 0x1b34 => true,
+ 0x1b44 => true,
+ 0x1b6b...0x1b73 => true,
+ 0x1baa => true,
+ 0x1bab => true,
+ 0x1c36...0x1c37 => true,
+ 0x1c78...0x1c7d => true,
+ 0x1cd0...0x1cd2 => true,
+ 0x1cd3 => true,
+ 0x1cd4...0x1ce0 => true,
+ 0x1ce1 => true,
+ 0x1ce2...0x1ce8 => true,
+ 0x1ced => true,
+ 0x1cf4 => true,
+ 0x1cf7 => true,
+ 0x1cf8...0x1cf9 => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1dc4...0x1dcf => true,
+ 0x1df5...0x1dff => true,
+ 0x1fbd => true,
+ 0x1fbf...0x1fc1 => true,
+ 0x1fcd...0x1fcf => true,
+ 0x1fdd...0x1fdf => true,
+ 0x1fed...0x1fef => true,
+ 0x1ffd...0x1ffe => true,
+ 0x2cef...0x2cf1 => true,
+ 0x2e2f => true,
+ 0x302a...0x302d => true,
+ 0x302e...0x302f => true,
+ 0x3099...0x309a => true,
+ 0x309b...0x309c => true,
+ 0x30fc => true,
+ 0xa66f => true,
+ 0xa67c...0xa67d => true,
+ 0xa67f => true,
+ 0xa69c...0xa69d => true,
+ 0xa6f0...0xa6f1 => true,
+ 0xa700...0xa716 => true,
+ 0xa717...0xa71f => true,
+ 0xa720...0xa721 => true,
+ 0xa788 => true,
+ 0xa789...0xa78a => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa8c4 => true,
+ 0xa8e0...0xa8f1 => true,
+ 0xa92b...0xa92d => true,
+ 0xa92e => true,
+ 0xa953 => true,
+ 0xa9b3 => true,
+ 0xa9c0 => true,
+ 0xa9e5 => true,
+ 0xaa7b => true,
+ 0xaa7c => true,
+ 0xaa7d => true,
+ 0xaabf => true,
+ 0xaac0 => true,
+ 0xaac1 => true,
+ 0xaac2 => true,
+ 0xaaf6 => true,
+ 0xab5b => true,
+ 0xab5c...0xab5f => true,
+ 0xab69 => true,
+ 0xab6a...0xab6b => true,
+ 0xabec => true,
+ 0xabed => true,
+ 0xfb1e => true,
+ 0xfe20...0xfe2f => true,
+ 0xff3e => true,
+ 0xff40 => true,
+ 0xff70 => true,
+ 0xff9e...0xff9f => true,
+ 0xffe3 => true,
+ 0x102e0 => true,
+ 0x10780...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x10ae5...0x10ae6 => true,
+ 0x10d22...0x10d23 => true,
+ 0x10d24...0x10d27 => true,
+ 0x10efd...0x10eff => true,
+ 0x10f46...0x10f50 => true,
+ 0x10f82...0x10f85 => true,
+ 0x11046 => true,
+ 0x11070 => true,
+ 0x110b9...0x110ba => true,
+ 0x11133...0x11134 => true,
+ 0x11173 => true,
+ 0x111c0 => true,
+ 0x111ca...0x111cc => true,
+ 0x11235 => true,
+ 0x11236 => true,
+ 0x112e9...0x112ea => true,
+ 0x1133c => true,
+ 0x1134d => true,
+ 0x11366...0x1136c => true,
+ 0x11370...0x11374 => true,
+ 0x11442 => true,
+ 0x11446 => true,
+ 0x114c2...0x114c3 => true,
+ 0x115bf...0x115c0 => true,
+ 0x1163f => true,
+ 0x116b6 => true,
+ 0x116b7 => true,
+ 0x1172b => true,
+ 0x11839...0x1183a => true,
+ 0x1193d => true,
+ 0x1193e => true,
+ 0x11943 => true,
+ 0x119e0 => true,
+ 0x11a34 => true,
+ 0x11a47 => true,
+ 0x11a99 => true,
+ 0x11c3f => true,
+ 0x11d42 => true,
+ 0x11d44...0x11d45 => true,
+ 0x11d97 => true,
+ 0x13447...0x13455 => true,
+ 0x16af0...0x16af4 => true,
+ 0x16b30...0x16b36 => true,
+ 0x16f8f...0x16f92 => true,
+ 0x16f93...0x16f9f => true,
+ 0x16ff0...0x16ff1 => true,
+ 0x1aff0...0x1aff3 => true,
+ 0x1aff5...0x1affb => true,
+ 0x1affd...0x1affe => true,
+ 0x1cf00...0x1cf2d => true,
+ 0x1cf30...0x1cf46 => true,
+ 0x1d167...0x1d169 => true,
+ 0x1d16d...0x1d172 => true,
+ 0x1d17b...0x1d182 => true,
+ 0x1d185...0x1d18b => true,
+ 0x1d1aa...0x1d1ad => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e130...0x1e136 => true,
+ 0x1e2ae => true,
+ 0x1e2ec...0x1e2ef => true,
+ 0x1e8d0...0x1e8d6 => true,
+ 0x1e944...0x1e946 => true,
+ 0x1e948...0x1e94a => true,
+ else => false,
+ };
+}
+
+pub fn isExtender(cp: u21) bool {
+ if (cp < 0xb7 or cp > 0x1e946) return false;
+
+ return switch (cp) {
+ 0xb7 => true,
+ 0x2d0...0x2d1 => true,
+ 0x640 => true,
+ 0x7fa => true,
+ 0xb55 => true,
+ 0xe46 => true,
+ 0xec6 => true,
+ 0x180a => true,
+ 0x1843 => true,
+ 0x1aa7 => true,
+ 0x1c36 => true,
+ 0x1c7b => true,
+ 0x3005 => true,
+ 0x3031...0x3035 => true,
+ 0x309d...0x309e => true,
+ 0x30fc...0x30fe => true,
+ 0xa015 => true,
+ 0xa60c => true,
+ 0xa9cf => true,
+ 0xa9e6 => true,
+ 0xaa70 => true,
+ 0xaadd => true,
+ 0xaaf3...0xaaf4 => true,
+ 0xff70 => true,
+ 0x10781...0x10782 => true,
+ 0x1135d => true,
+ 0x115c6...0x115c8 => true,
+ 0x11a98 => true,
+ 0x16b42...0x16b43 => true,
+ 0x16fe0...0x16fe1 => true,
+ 0x16fe3 => true,
+ 0x1e13c...0x1e13d => true,
+ 0x1e944...0x1e946 => true,
+ else => false,
+ };
+}
+
+pub fn isOtherLowercase(cp: u21) bool {
+ if (cp < 0xaa or cp > 0x1e06d) return false;
+
+ return switch (cp) {
+ 0xaa => true,
+ 0xba => true,
+ 0x2b0...0x2b8 => true,
+ 0x2c0...0x2c1 => true,
+ 0x2e0...0x2e4 => true,
+ 0x345 => true,
+ 0x37a => true,
+ 0x10fc => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d78 => true,
+ 0x1d9b...0x1dbf => true,
+ 0x2071 => true,
+ 0x207f => true,
+ 0x2090...0x209c => true,
+ 0x2170...0x217f => true,
+ 0x24d0...0x24e9 => true,
+ 0x2c7c...0x2c7d => true,
+ 0xa69c...0xa69d => true,
+ 0xa770 => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xab5c...0xab5f => true,
+ 0xab69 => true,
+ 0x10780 => true,
+ 0x10783...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x1e030...0x1e06d => true,
+ else => false,
+ };
+}
+
+pub fn isOtherUppercase(cp: u21) bool {
+ if (cp < 0x2160 or cp > 0x1f189) return false;
+
+ return switch (cp) {
+ 0x2160...0x216f => true,
+ 0x24b6...0x24cf => true,
+ 0x1f130...0x1f149 => true,
+ 0x1f150...0x1f169 => true,
+ 0x1f170...0x1f189 => true,
+ else => false,
+ };
+}
+
+pub fn isNoncharacterCodePoint(cp: u21) bool {
+ if (cp < 0xfdd0 or cp > 0x10ffff) return false;
+
+ return switch (cp) {
+ 0xfdd0...0xfdef => true,
+ 0xfffe...0xffff => true,
+ 0x1fffe...0x1ffff => true,
+ 0x2fffe...0x2ffff => true,
+ 0x3fffe...0x3ffff => true,
+ 0x4fffe...0x4ffff => true,
+ 0x5fffe...0x5ffff => true,
+ 0x6fffe...0x6ffff => true,
+ 0x7fffe...0x7ffff => true,
+ 0x8fffe...0x8ffff => true,
+ 0x9fffe...0x9ffff => true,
+ 0xafffe...0xaffff => true,
+ 0xbfffe...0xbffff => true,
+ 0xcfffe...0xcffff => true,
+ 0xdfffe...0xdffff => true,
+ 0xefffe...0xeffff => true,
+ 0xffffe...0xfffff => true,
+ 0x10fffe...0x10ffff => true,
+ else => false,
+ };
+}
+
+pub fn isOtherGraphemeExtend(cp: u21) bool {
+ if (cp < 0x9be or cp > 0xe007f) return false;
+
+ return switch (cp) {
+ 0x9be => true,
+ 0x9d7 => true,
+ 0xb3e => true,
+ 0xb57 => true,
+ 0xbbe => true,
+ 0xbd7 => true,
+ 0xcc2 => true,
+ 0xcd5...0xcd6 => true,
+ 0xd3e => true,
+ 0xd57 => true,
+ 0xdcf => true,
+ 0xddf => true,
+ 0x1b35 => true,
+ 0x200c => true,
+ 0x302e...0x302f => true,
+ 0xff9e...0xff9f => true,
+ 0x1133e => true,
+ 0x11357 => true,
+ 0x114b0 => true,
+ 0x114bd => true,
+ 0x115af => true,
+ 0x11930 => true,
+ 0x1d165 => true,
+ 0x1d16e...0x1d172 => true,
+ 0xe0020...0xe007f => true,
+ else => false,
+ };
+}
+
+pub fn isIdsBinaryOperator(cp: u21) bool {
+ if (cp < 0x2ff0 or cp > 0x2ffb) return false;
+
+ return switch (cp) {
+ 0x2ff0...0x2ff1 => true,
+ 0x2ff4...0x2ffb => true,
+ else => false,
+ };
+}
+
+pub fn isIdsTrinaryOperator(cp: u21) bool {
+ if (cp < 0x2ff2 or cp > 0x2ff3) return false;
+
+ return switch (cp) {
+ 0x2ff2...0x2ff3 => true,
+ else => false,
+ };
+}
+
+pub fn isRadical(cp: u21) bool {
+ if (cp < 0x2e80 or cp > 0x2fd5) return false;
+
+ return switch (cp) {
+ 0x2e80...0x2e99 => true,
+ 0x2e9b...0x2ef3 => true,
+ 0x2f00...0x2fd5 => true,
+ else => false,
+ };
+}
+
+pub fn isUnifiedIdeograph(cp: u21) bool {
+ if (cp < 0x3400 or cp > 0x323af) return false;
+
+ return switch (cp) {
+ 0x3400...0x4dbf => true,
+ 0x4e00...0x9fff => true,
+ 0xfa0e...0xfa0f => true,
+ 0xfa11 => true,
+ 0xfa13...0xfa14 => true,
+ 0xfa1f => true,
+ 0xfa21 => true,
+ 0xfa23...0xfa24 => true,
+ 0xfa27...0xfa29 => true,
+ 0x20000...0x2a6df => true,
+ 0x2a700...0x2b739 => true,
+ 0x2b740...0x2b81d => true,
+ 0x2b820...0x2cea1 => true,
+ 0x2ceb0...0x2ebe0 => true,
+ 0x30000...0x3134a => true,
+ 0x31350...0x323af => true,
+ else => false,
+ };
+}
+
+pub fn isOtherDefaultIgnorableCodePoint(cp: u21) bool {
+ if (cp < 0x34f or cp > 0xe0fff) return false;
+
+ return switch (cp) {
+ 0x34f => true,
+ 0x115f...0x1160 => true,
+ 0x17b4...0x17b5 => true,
+ 0x2065 => true,
+ 0x3164 => true,
+ 0xffa0 => true,
+ 0xfff0...0xfff8 => true,
+ 0xe0000 => true,
+ 0xe0002...0xe001f => true,
+ 0xe0080...0xe00ff => true,
+ 0xe01f0...0xe0fff => true,
+ else => false,
+ };
+}
+
+pub fn isDeprecated(cp: u21) bool {
+ if (cp < 0x149 or cp > 0xe0001) return false;
+
+ return switch (cp) {
+ 0x149 => true,
+ 0x673 => true,
+ 0xf77 => true,
+ 0xf79 => true,
+ 0x17a3...0x17a4 => true,
+ 0x206a...0x206f => true,
+ 0x2329 => true,
+ 0x232a => true,
+ 0xe0001 => true,
+ else => false,
+ };
+}
+
+pub fn isSoftDotted(cp: u21) bool {
+ if (cp < 0x69 or cp > 0x1e068) return false;
+
+ return switch (cp) {
+ 0x69...0x6a => true,
+ 0x12f => true,
+ 0x249 => true,
+ 0x268 => true,
+ 0x29d => true,
+ 0x2b2 => true,
+ 0x3f3 => true,
+ 0x456 => true,
+ 0x458 => true,
+ 0x1d62 => true,
+ 0x1d96 => true,
+ 0x1da4 => true,
+ 0x1da8 => true,
+ 0x1e2d => true,
+ 0x1ecb => true,
+ 0x2071 => true,
+ 0x2148...0x2149 => true,
+ 0x2c7c => true,
+ 0x1d422...0x1d423 => true,
+ 0x1d456...0x1d457 => true,
+ 0x1d48a...0x1d48b => true,
+ 0x1d4be...0x1d4bf => true,
+ 0x1d4f2...0x1d4f3 => true,
+ 0x1d526...0x1d527 => true,
+ 0x1d55a...0x1d55b => true,
+ 0x1d58e...0x1d58f => true,
+ 0x1d5c2...0x1d5c3 => true,
+ 0x1d5f6...0x1d5f7 => true,
+ 0x1d62a...0x1d62b => true,
+ 0x1d65e...0x1d65f => true,
+ 0x1d692...0x1d693 => true,
+ 0x1df1a => true,
+ 0x1e04c...0x1e04d => true,
+ 0x1e068 => true,
+ else => false,
+ };
+}
+
+pub fn isLogicalOrderException(cp: u21) bool {
+ if (cp < 0xe40 or cp > 0xaabc) return false;
+
+ return switch (cp) {
+ 0xe40...0xe44 => true,
+ 0xec0...0xec4 => true,
+ 0x19b5...0x19b7 => true,
+ 0x19ba => true,
+ 0xaab5...0xaab6 => true,
+ 0xaab9 => true,
+ 0xaabb...0xaabc => true,
+ else => false,
+ };
+}
+
+pub fn isOtherIdStart(cp: u21) bool {
+ if (cp < 0x1885 or cp > 0x309c) return false;
+
+ return switch (cp) {
+ 0x1885...0x1886 => true,
+ 0x2118 => true,
+ 0x212e => true,
+ 0x309b...0x309c => true,
+ else => false,
+ };
+}
+
+pub fn isOtherIdContinue(cp: u21) bool {
+ if (cp < 0xb7 or cp > 0x19da) return false;
+
+ return switch (cp) {
+ 0xb7 => true,
+ 0x387 => true,
+ 0x1369...0x1371 => true,
+ 0x19da => true,
+ else => false,
+ };
+}
+
+pub fn isSentenceTerminal(cp: u21) bool {
+ if (cp < 0x21 or cp > 0x1da88) return false;
+
+ return switch (cp) {
+ 0x21 => true,
+ 0x2e => true,
+ 0x3f => true,
+ 0x589 => true,
+ 0x61d...0x61f => true,
+ 0x6d4 => true,
+ 0x700...0x702 => true,
+ 0x7f9 => true,
+ 0x837 => true,
+ 0x839 => true,
+ 0x83d...0x83e => true,
+ 0x964...0x965 => true,
+ 0x104a...0x104b => true,
+ 0x1362 => true,
+ 0x1367...0x1368 => true,
+ 0x166e => true,
+ 0x1735...0x1736 => true,
+ 0x1803 => true,
+ 0x1809 => true,
+ 0x1944...0x1945 => true,
+ 0x1aa8...0x1aab => true,
+ 0x1b5a...0x1b5b => true,
+ 0x1b5e...0x1b5f => true,
+ 0x1b7d...0x1b7e => true,
+ 0x1c3b...0x1c3c => true,
+ 0x1c7e...0x1c7f => true,
+ 0x203c...0x203d => true,
+ 0x2047...0x2049 => true,
+ 0x2e2e => true,
+ 0x2e3c => true,
+ 0x2e53...0x2e54 => true,
+ 0x3002 => true,
+ 0xa4ff => true,
+ 0xa60e...0xa60f => true,
+ 0xa6f3 => true,
+ 0xa6f7 => true,
+ 0xa876...0xa877 => true,
+ 0xa8ce...0xa8cf => true,
+ 0xa92f => true,
+ 0xa9c8...0xa9c9 => true,
+ 0xaa5d...0xaa5f => true,
+ 0xaaf0...0xaaf1 => true,
+ 0xabeb => true,
+ 0xfe52 => true,
+ 0xfe56...0xfe57 => true,
+ 0xff01 => true,
+ 0xff0e => true,
+ 0xff1f => true,
+ 0xff61 => true,
+ 0x10a56...0x10a57 => true,
+ 0x10f55...0x10f59 => true,
+ 0x10f86...0x10f89 => true,
+ 0x11047...0x11048 => true,
+ 0x110be...0x110c1 => true,
+ 0x11141...0x11143 => true,
+ 0x111c5...0x111c6 => true,
+ 0x111cd => true,
+ 0x111de...0x111df => true,
+ 0x11238...0x11239 => true,
+ 0x1123b...0x1123c => true,
+ 0x112a9 => true,
+ 0x1144b...0x1144c => true,
+ 0x115c2...0x115c3 => true,
+ 0x115c9...0x115d7 => true,
+ 0x11641...0x11642 => true,
+ 0x1173c...0x1173e => true,
+ 0x11944 => true,
+ 0x11946 => true,
+ 0x11a42...0x11a43 => true,
+ 0x11a9b...0x11a9c => true,
+ 0x11c41...0x11c42 => true,
+ 0x11ef7...0x11ef8 => true,
+ 0x11f43...0x11f44 => true,
+ 0x16a6e...0x16a6f => true,
+ 0x16af5 => true,
+ 0x16b37...0x16b38 => true,
+ 0x16b44 => true,
+ 0x16e98 => true,
+ 0x1bc9f => true,
+ 0x1da88 => true,
+ else => false,
+ };
+}
+
+pub fn isVariationSelector(cp: u21) bool {
+ if (cp < 0x180b or cp > 0xe01ef) return false;
+
+ return switch (cp) {
+ 0x180b...0x180d => true,
+ 0x180f => true,
+ 0xfe00...0xfe0f => true,
+ 0xe0100...0xe01ef => true,
+ else => false,
+ };
+}
+
+pub fn isPatternWhiteSpace(cp: u21) bool {
+ if (cp < 0x9 or cp > 0x2029) return false;
+
+ return switch (cp) {
+ 0x9...0xd => true,
+ 0x20 => true,
+ 0x85 => true,
+ 0x200e...0x200f => true,
+ 0x2028 => true,
+ 0x2029 => true,
+ else => false,
+ };
+}
+
+pub fn isPatternSyntax(cp: u21) bool {
+ if (cp < 0x21 or cp > 0xfe46) return false;
+
+ return switch (cp) {
+ 0x21...0x23 => true,
+ 0x24 => true,
+ 0x25...0x27 => true,
+ 0x28 => true,
+ 0x29 => true,
+ 0x2a => true,
+ 0x2b => true,
+ 0x2c => true,
+ 0x2d => true,
+ 0x2e...0x2f => true,
+ 0x3a...0x3b => true,
+ 0x3c...0x3e => true,
+ 0x3f...0x40 => true,
+ 0x5b => true,
+ 0x5c => true,
+ 0x5d => true,
+ 0x5e => true,
+ 0x60 => true,
+ 0x7b => true,
+ 0x7c => true,
+ 0x7d => true,
+ 0x7e => true,
+ 0xa1 => true,
+ 0xa2...0xa5 => true,
+ 0xa6 => true,
+ 0xa7 => true,
+ 0xa9 => true,
+ 0xab => true,
+ 0xac => true,
+ 0xae => true,
+ 0xb0 => true,
+ 0xb1 => true,
+ 0xb6 => true,
+ 0xbb => true,
+ 0xbf => true,
+ 0xd7 => true,
+ 0xf7 => true,
+ 0x2010...0x2015 => true,
+ 0x2016...0x2017 => true,
+ 0x2018 => true,
+ 0x2019 => true,
+ 0x201a => true,
+ 0x201b...0x201c => true,
+ 0x201d => true,
+ 0x201e => true,
+ 0x201f => true,
+ 0x2020...0x2027 => true,
+ 0x2030...0x2038 => true,
+ 0x2039 => true,
+ 0x203a => true,
+ 0x203b...0x203e => true,
+ 0x2041...0x2043 => true,
+ 0x2044 => true,
+ 0x2045 => true,
+ 0x2046 => true,
+ 0x2047...0x2051 => true,
+ 0x2052 => true,
+ 0x2053 => true,
+ 0x2055...0x205e => true,
+ 0x2190...0x2194 => true,
+ 0x2195...0x2199 => true,
+ 0x219a...0x219b => true,
+ 0x219c...0x219f => true,
+ 0x21a0 => true,
+ 0x21a1...0x21a2 => true,
+ 0x21a3 => true,
+ 0x21a4...0x21a5 => true,
+ 0x21a6 => true,
+ 0x21a7...0x21ad => true,
+ 0x21ae => true,
+ 0x21af...0x21cd => true,
+ 0x21ce...0x21cf => true,
+ 0x21d0...0x21d1 => true,
+ 0x21d2 => true,
+ 0x21d3 => true,
+ 0x21d4 => true,
+ 0x21d5...0x21f3 => true,
+ 0x21f4...0x22ff => true,
+ 0x2300...0x2307 => true,
+ 0x2308 => true,
+ 0x2309 => true,
+ 0x230a => true,
+ 0x230b => true,
+ 0x230c...0x231f => true,
+ 0x2320...0x2321 => true,
+ 0x2322...0x2328 => true,
+ 0x2329 => true,
+ 0x232a => true,
+ 0x232b...0x237b => true,
+ 0x237c => true,
+ 0x237d...0x239a => true,
+ 0x239b...0x23b3 => true,
+ 0x23b4...0x23db => true,
+ 0x23dc...0x23e1 => true,
+ 0x23e2...0x2426 => true,
+ 0x2427...0x243f => true,
+ 0x2440...0x244a => true,
+ 0x244b...0x245f => true,
+ 0x2500...0x25b6 => true,
+ 0x25b7 => true,
+ 0x25b8...0x25c0 => true,
+ 0x25c1 => true,
+ 0x25c2...0x25f7 => true,
+ 0x25f8...0x25ff => true,
+ 0x2600...0x266e => true,
+ 0x266f => true,
+ 0x2670...0x2767 => true,
+ 0x2768 => true,
+ 0x2769 => true,
+ 0x276a => true,
+ 0x276b => true,
+ 0x276c => true,
+ 0x276d => true,
+ 0x276e => true,
+ 0x276f => true,
+ 0x2770 => true,
+ 0x2771 => true,
+ 0x2772 => true,
+ 0x2773 => true,
+ 0x2774 => true,
+ 0x2775 => true,
+ 0x2794...0x27bf => true,
+ 0x27c0...0x27c4 => true,
+ 0x27c5 => true,
+ 0x27c6 => true,
+ 0x27c7...0x27e5 => true,
+ 0x27e6 => true,
+ 0x27e7 => true,
+ 0x27e8 => true,
+ 0x27e9 => true,
+ 0x27ea => true,
+ 0x27eb => true,
+ 0x27ec => true,
+ 0x27ed => true,
+ 0x27ee => true,
+ 0x27ef => true,
+ 0x27f0...0x27ff => true,
+ 0x2800...0x28ff => true,
+ 0x2900...0x2982 => true,
+ 0x2983 => true,
+ 0x2984 => true,
+ 0x2985 => true,
+ 0x2986 => true,
+ 0x2987 => true,
+ 0x2988 => true,
+ 0x2989 => true,
+ 0x298a => true,
+ 0x298b => true,
+ 0x298c => true,
+ 0x298d => true,
+ 0x298e => true,
+ 0x298f => true,
+ 0x2990 => true,
+ 0x2991 => true,
+ 0x2992 => true,
+ 0x2993 => true,
+ 0x2994 => true,
+ 0x2995 => true,
+ 0x2996 => true,
+ 0x2997 => true,
+ 0x2998 => true,
+ 0x2999...0x29d7 => true,
+ 0x29d8 => true,
+ 0x29d9 => true,
+ 0x29da => true,
+ 0x29db => true,
+ 0x29dc...0x29fb => true,
+ 0x29fc => true,
+ 0x29fd => true,
+ 0x29fe...0x2aff => true,
+ 0x2b00...0x2b2f => true,
+ 0x2b30...0x2b44 => true,
+ 0x2b45...0x2b46 => true,
+ 0x2b47...0x2b4c => true,
+ 0x2b4d...0x2b73 => true,
+ 0x2b74...0x2b75 => true,
+ 0x2b76...0x2b95 => true,
+ 0x2b96 => true,
+ 0x2b97...0x2bff => true,
+ 0x2e00...0x2e01 => true,
+ 0x2e02 => true,
+ 0x2e03 => true,
+ 0x2e04 => true,
+ 0x2e05 => true,
+ 0x2e06...0x2e08 => true,
+ 0x2e09 => true,
+ 0x2e0a => true,
+ 0x2e0b => true,
+ 0x2e0c => true,
+ 0x2e0d => true,
+ 0x2e0e...0x2e16 => true,
+ 0x2e17 => true,
+ 0x2e18...0x2e19 => true,
+ 0x2e1a => true,
+ 0x2e1b => true,
+ 0x2e1c => true,
+ 0x2e1d => true,
+ 0x2e1e...0x2e1f => true,
+ 0x2e20 => true,
+ 0x2e21 => true,
+ 0x2e22 => true,
+ 0x2e23 => true,
+ 0x2e24 => true,
+ 0x2e25 => true,
+ 0x2e26 => true,
+ 0x2e27 => true,
+ 0x2e28 => true,
+ 0x2e29 => true,
+ 0x2e2a...0x2e2e => true,
+ 0x2e2f => true,
+ 0x2e30...0x2e39 => true,
+ 0x2e3a...0x2e3b => true,
+ 0x2e3c...0x2e3f => true,
+ 0x2e40 => true,
+ 0x2e41 => true,
+ 0x2e42 => true,
+ 0x2e43...0x2e4f => true,
+ 0x2e50...0x2e51 => true,
+ 0x2e52...0x2e54 => true,
+ 0x2e55 => true,
+ 0x2e56 => true,
+ 0x2e57 => true,
+ 0x2e58 => true,
+ 0x2e59 => true,
+ 0x2e5a => true,
+ 0x2e5b => true,
+ 0x2e5c => true,
+ 0x2e5d => true,
+ 0x2e5e...0x2e7f => true,
+ 0x3001...0x3003 => true,
+ 0x3008 => true,
+ 0x3009 => true,
+ 0x300a => true,
+ 0x300b => true,
+ 0x300c => true,
+ 0x300d => true,
+ 0x300e => true,
+ 0x300f => true,
+ 0x3010 => true,
+ 0x3011 => true,
+ 0x3012...0x3013 => true,
+ 0x3014 => true,
+ 0x3015 => true,
+ 0x3016 => true,
+ 0x3017 => true,
+ 0x3018 => true,
+ 0x3019 => true,
+ 0x301a => true,
+ 0x301b => true,
+ 0x301c => true,
+ 0x301d => true,
+ 0x301e...0x301f => true,
+ 0x3020 => true,
+ 0x3030 => true,
+ 0xfd3e => true,
+ 0xfd3f => true,
+ 0xfe45...0xfe46 => true,
+ else => false,
+ };
+}
+
+pub fn isPrependedConcatenationMark(cp: u21) bool {
+ if (cp < 0x600 or cp > 0x110cd) return false;
+
+ return switch (cp) {
+ 0x600...0x605 => true,
+ 0x6dd => true,
+ 0x70f => true,
+ 0x890...0x891 => true,
+ 0x8e2 => true,
+ 0x110bd => true,
+ 0x110cd => true,
+ else => false,
+ };
+}
+
+pub fn isRegionalIndicator(cp: u21) bool {
+ if (cp < 0x1f1e6 or cp > 0x1f1ff) return false;
+
+ return switch (cp) {
+ 0x1f1e6...0x1f1ff => true,
+ else => false,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/sentence_break_property.zig.html b/docs/src/ziglyph/autogen/sentence_break_property.zig.html
new file mode 100644
index 0000000..c545bb9
--- /dev/null
+++ b/docs/src/ziglyph/autogen/sentence_break_property.zig.html
@@ -0,0 +1,3053 @@
+
+
+
+
+
autogen/sentence_break_property.zig - source view
+
+
+
+
+
+
+
+
+pub fn isCr(cp: u21) bool {
+ return cp == 0xd;
+}
+
+pub fn isLf(cp: u21) bool {
+ return cp == 0xa;
+}
+
+pub fn isExtend(cp: u21) bool {
+ if (cp < 0x300 or cp > 0xe01ef) return false;
+
+ return switch (cp) {
+ 0x300...0x36f => true,
+ 0x483...0x487 => true,
+ 0x488...0x489 => true,
+ 0x591...0x5bd => true,
+ 0x5bf => true,
+ 0x5c1...0x5c2 => true,
+ 0x5c4...0x5c5 => true,
+ 0x5c7 => true,
+ 0x610...0x61a => true,
+ 0x64b...0x65f => true,
+ 0x670 => true,
+ 0x6d6...0x6dc => true,
+ 0x6df...0x6e4 => true,
+ 0x6e7...0x6e8 => true,
+ 0x6ea...0x6ed => true,
+ 0x711 => true,
+ 0x730...0x74a => true,
+ 0x7a6...0x7b0 => true,
+ 0x7eb...0x7f3 => true,
+ 0x7fd => true,
+ 0x816...0x819 => true,
+ 0x81b...0x823 => true,
+ 0x825...0x827 => true,
+ 0x829...0x82d => true,
+ 0x859...0x85b => true,
+ 0x898...0x89f => true,
+ 0x8ca...0x8e1 => true,
+ 0x8e3...0x902 => true,
+ 0x903 => true,
+ 0x93a => true,
+ 0x93b => true,
+ 0x93c => true,
+ 0x93e...0x940 => true,
+ 0x941...0x948 => true,
+ 0x949...0x94c => true,
+ 0x94d => true,
+ 0x94e...0x94f => true,
+ 0x951...0x957 => true,
+ 0x962...0x963 => true,
+ 0x981 => true,
+ 0x982...0x983 => true,
+ 0x9bc => true,
+ 0x9be...0x9c0 => true,
+ 0x9c1...0x9c4 => true,
+ 0x9c7...0x9c8 => true,
+ 0x9cb...0x9cc => true,
+ 0x9cd => true,
+ 0x9d7 => true,
+ 0x9e2...0x9e3 => true,
+ 0x9fe => true,
+ 0xa01...0xa02 => true,
+ 0xa03 => true,
+ 0xa3c => true,
+ 0xa3e...0xa40 => true,
+ 0xa41...0xa42 => true,
+ 0xa47...0xa48 => true,
+ 0xa4b...0xa4d => true,
+ 0xa51 => true,
+ 0xa70...0xa71 => true,
+ 0xa75 => true,
+ 0xa81...0xa82 => true,
+ 0xa83 => true,
+ 0xabc => true,
+ 0xabe...0xac0 => true,
+ 0xac1...0xac5 => true,
+ 0xac7...0xac8 => true,
+ 0xac9 => true,
+ 0xacb...0xacc => true,
+ 0xacd => true,
+ 0xae2...0xae3 => true,
+ 0xafa...0xaff => true,
+ 0xb01 => true,
+ 0xb02...0xb03 => true,
+ 0xb3c => true,
+ 0xb3e => true,
+ 0xb3f => true,
+ 0xb40 => true,
+ 0xb41...0xb44 => true,
+ 0xb47...0xb48 => true,
+ 0xb4b...0xb4c => true,
+ 0xb4d => true,
+ 0xb55...0xb56 => true,
+ 0xb57 => true,
+ 0xb62...0xb63 => true,
+ 0xb82 => true,
+ 0xbbe...0xbbf => true,
+ 0xbc0 => true,
+ 0xbc1...0xbc2 => true,
+ 0xbc6...0xbc8 => true,
+ 0xbca...0xbcc => true,
+ 0xbcd => true,
+ 0xbd7 => true,
+ 0xc00 => true,
+ 0xc01...0xc03 => true,
+ 0xc04 => true,
+ 0xc3c => true,
+ 0xc3e...0xc40 => true,
+ 0xc41...0xc44 => true,
+ 0xc46...0xc48 => true,
+ 0xc4a...0xc4d => true,
+ 0xc55...0xc56 => true,
+ 0xc62...0xc63 => true,
+ 0xc81 => true,
+ 0xc82...0xc83 => true,
+ 0xcbc => true,
+ 0xcbe => true,
+ 0xcbf => true,
+ 0xcc0...0xcc4 => true,
+ 0xcc6 => true,
+ 0xcc7...0xcc8 => true,
+ 0xcca...0xccb => true,
+ 0xccc...0xccd => true,
+ 0xcd5...0xcd6 => true,
+ 0xce2...0xce3 => true,
+ 0xcf3 => true,
+ 0xd00...0xd01 => true,
+ 0xd02...0xd03 => true,
+ 0xd3b...0xd3c => true,
+ 0xd3e...0xd40 => true,
+ 0xd41...0xd44 => true,
+ 0xd46...0xd48 => true,
+ 0xd4a...0xd4c => true,
+ 0xd4d => true,
+ 0xd57 => true,
+ 0xd62...0xd63 => true,
+ 0xd81 => true,
+ 0xd82...0xd83 => true,
+ 0xdca => true,
+ 0xdcf...0xdd1 => true,
+ 0xdd2...0xdd4 => true,
+ 0xdd6 => true,
+ 0xdd8...0xddf => true,
+ 0xdf2...0xdf3 => true,
+ 0xe31 => true,
+ 0xe34...0xe3a => true,
+ 0xe47...0xe4e => true,
+ 0xeb1 => true,
+ 0xeb4...0xebc => true,
+ 0xec8...0xece => true,
+ 0xf18...0xf19 => true,
+ 0xf35 => true,
+ 0xf37 => true,
+ 0xf39 => true,
+ 0xf3e...0xf3f => true,
+ 0xf71...0xf7e => true,
+ 0xf7f => true,
+ 0xf80...0xf84 => true,
+ 0xf86...0xf87 => true,
+ 0xf8d...0xf97 => true,
+ 0xf99...0xfbc => true,
+ 0xfc6 => true,
+ 0x102b...0x102c => true,
+ 0x102d...0x1030 => true,
+ 0x1031 => true,
+ 0x1032...0x1037 => true,
+ 0x1038 => true,
+ 0x1039...0x103a => true,
+ 0x103b...0x103c => true,
+ 0x103d...0x103e => true,
+ 0x1056...0x1057 => true,
+ 0x1058...0x1059 => true,
+ 0x105e...0x1060 => true,
+ 0x1062...0x1064 => true,
+ 0x1067...0x106d => true,
+ 0x1071...0x1074 => true,
+ 0x1082 => true,
+ 0x1083...0x1084 => true,
+ 0x1085...0x1086 => true,
+ 0x1087...0x108c => true,
+ 0x108d => true,
+ 0x108f => true,
+ 0x109a...0x109c => true,
+ 0x109d => true,
+ 0x135d...0x135f => true,
+ 0x1712...0x1714 => true,
+ 0x1715 => true,
+ 0x1732...0x1733 => true,
+ 0x1734 => true,
+ 0x1752...0x1753 => true,
+ 0x1772...0x1773 => true,
+ 0x17b4...0x17b5 => true,
+ 0x17b6 => true,
+ 0x17b7...0x17bd => true,
+ 0x17be...0x17c5 => true,
+ 0x17c6 => true,
+ 0x17c7...0x17c8 => true,
+ 0x17c9...0x17d3 => true,
+ 0x17dd => true,
+ 0x180b...0x180d => true,
+ 0x180f => true,
+ 0x1885...0x1886 => true,
+ 0x18a9 => true,
+ 0x1920...0x1922 => true,
+ 0x1923...0x1926 => true,
+ 0x1927...0x1928 => true,
+ 0x1929...0x192b => true,
+ 0x1930...0x1931 => true,
+ 0x1932 => true,
+ 0x1933...0x1938 => true,
+ 0x1939...0x193b => true,
+ 0x1a17...0x1a18 => true,
+ 0x1a19...0x1a1a => true,
+ 0x1a1b => true,
+ 0x1a55 => true,
+ 0x1a56 => true,
+ 0x1a57 => true,
+ 0x1a58...0x1a5e => true,
+ 0x1a60 => true,
+ 0x1a61 => true,
+ 0x1a62 => true,
+ 0x1a63...0x1a64 => true,
+ 0x1a65...0x1a6c => true,
+ 0x1a6d...0x1a72 => true,
+ 0x1a73...0x1a7c => true,
+ 0x1a7f => true,
+ 0x1ab0...0x1abd => true,
+ 0x1abe => true,
+ 0x1abf...0x1ace => true,
+ 0x1b00...0x1b03 => true,
+ 0x1b04 => true,
+ 0x1b34 => true,
+ 0x1b35 => true,
+ 0x1b36...0x1b3a => true,
+ 0x1b3b => true,
+ 0x1b3c => true,
+ 0x1b3d...0x1b41 => true,
+ 0x1b42 => true,
+ 0x1b43...0x1b44 => true,
+ 0x1b6b...0x1b73 => true,
+ 0x1b80...0x1b81 => true,
+ 0x1b82 => true,
+ 0x1ba1 => true,
+ 0x1ba2...0x1ba5 => true,
+ 0x1ba6...0x1ba7 => true,
+ 0x1ba8...0x1ba9 => true,
+ 0x1baa => true,
+ 0x1bab...0x1bad => true,
+ 0x1be6 => true,
+ 0x1be7 => true,
+ 0x1be8...0x1be9 => true,
+ 0x1bea...0x1bec => true,
+ 0x1bed => true,
+ 0x1bee => true,
+ 0x1bef...0x1bf1 => true,
+ 0x1bf2...0x1bf3 => true,
+ 0x1c24...0x1c2b => true,
+ 0x1c2c...0x1c33 => true,
+ 0x1c34...0x1c35 => true,
+ 0x1c36...0x1c37 => true,
+ 0x1cd0...0x1cd2 => true,
+ 0x1cd4...0x1ce0 => true,
+ 0x1ce1 => true,
+ 0x1ce2...0x1ce8 => true,
+ 0x1ced => true,
+ 0x1cf4 => true,
+ 0x1cf7 => true,
+ 0x1cf8...0x1cf9 => true,
+ 0x1dc0...0x1dff => true,
+ 0x200c...0x200d => true,
+ 0x20d0...0x20dc => true,
+ 0x20dd...0x20e0 => true,
+ 0x20e1 => true,
+ 0x20e2...0x20e4 => true,
+ 0x20e5...0x20f0 => true,
+ 0x2cef...0x2cf1 => true,
+ 0x2d7f => true,
+ 0x2de0...0x2dff => true,
+ 0x302a...0x302d => true,
+ 0x302e...0x302f => true,
+ 0x3099...0x309a => true,
+ 0xa66f => true,
+ 0xa670...0xa672 => true,
+ 0xa674...0xa67d => true,
+ 0xa69e...0xa69f => true,
+ 0xa6f0...0xa6f1 => true,
+ 0xa802 => true,
+ 0xa806 => true,
+ 0xa80b => true,
+ 0xa823...0xa824 => true,
+ 0xa825...0xa826 => true,
+ 0xa827 => true,
+ 0xa82c => true,
+ 0xa880...0xa881 => true,
+ 0xa8b4...0xa8c3 => true,
+ 0xa8c4...0xa8c5 => true,
+ 0xa8e0...0xa8f1 => true,
+ 0xa8ff => true,
+ 0xa926...0xa92d => true,
+ 0xa947...0xa951 => true,
+ 0xa952...0xa953 => true,
+ 0xa980...0xa982 => true,
+ 0xa983 => true,
+ 0xa9b3 => true,
+ 0xa9b4...0xa9b5 => true,
+ 0xa9b6...0xa9b9 => true,
+ 0xa9ba...0xa9bb => true,
+ 0xa9bc...0xa9bd => true,
+ 0xa9be...0xa9c0 => true,
+ 0xa9e5 => true,
+ 0xaa29...0xaa2e => true,
+ 0xaa2f...0xaa30 => true,
+ 0xaa31...0xaa32 => true,
+ 0xaa33...0xaa34 => true,
+ 0xaa35...0xaa36 => true,
+ 0xaa43 => true,
+ 0xaa4c => true,
+ 0xaa4d => true,
+ 0xaa7b => true,
+ 0xaa7c => true,
+ 0xaa7d => true,
+ 0xaab0 => true,
+ 0xaab2...0xaab4 => true,
+ 0xaab7...0xaab8 => true,
+ 0xaabe...0xaabf => true,
+ 0xaac1 => true,
+ 0xaaeb => true,
+ 0xaaec...0xaaed => true,
+ 0xaaee...0xaaef => true,
+ 0xaaf5 => true,
+ 0xaaf6 => true,
+ 0xabe3...0xabe4 => true,
+ 0xabe5 => true,
+ 0xabe6...0xabe7 => true,
+ 0xabe8 => true,
+ 0xabe9...0xabea => true,
+ 0xabec => true,
+ 0xabed => true,
+ 0xfb1e => true,
+ 0xfe00...0xfe0f => true,
+ 0xfe20...0xfe2f => true,
+ 0xff9e...0xff9f => true,
+ 0x101fd => true,
+ 0x102e0 => true,
+ 0x10376...0x1037a => true,
+ 0x10a01...0x10a03 => true,
+ 0x10a05...0x10a06 => true,
+ 0x10a0c...0x10a0f => true,
+ 0x10a38...0x10a3a => true,
+ 0x10a3f => true,
+ 0x10ae5...0x10ae6 => true,
+ 0x10d24...0x10d27 => true,
+ 0x10eab...0x10eac => true,
+ 0x10efd...0x10eff => true,
+ 0x10f46...0x10f50 => true,
+ 0x10f82...0x10f85 => true,
+ 0x11000 => true,
+ 0x11001 => true,
+ 0x11002 => true,
+ 0x11038...0x11046 => true,
+ 0x11070 => true,
+ 0x11073...0x11074 => true,
+ 0x1107f...0x11081 => true,
+ 0x11082 => true,
+ 0x110b0...0x110b2 => true,
+ 0x110b3...0x110b6 => true,
+ 0x110b7...0x110b8 => true,
+ 0x110b9...0x110ba => true,
+ 0x110c2 => true,
+ 0x11100...0x11102 => true,
+ 0x11127...0x1112b => true,
+ 0x1112c => true,
+ 0x1112d...0x11134 => true,
+ 0x11145...0x11146 => true,
+ 0x11173 => true,
+ 0x11180...0x11181 => true,
+ 0x11182 => true,
+ 0x111b3...0x111b5 => true,
+ 0x111b6...0x111be => true,
+ 0x111bf...0x111c0 => true,
+ 0x111c9...0x111cc => true,
+ 0x111ce => true,
+ 0x111cf => true,
+ 0x1122c...0x1122e => true,
+ 0x1122f...0x11231 => true,
+ 0x11232...0x11233 => true,
+ 0x11234 => true,
+ 0x11235 => true,
+ 0x11236...0x11237 => true,
+ 0x1123e => true,
+ 0x11241 => true,
+ 0x112df => true,
+ 0x112e0...0x112e2 => true,
+ 0x112e3...0x112ea => true,
+ 0x11300...0x11301 => true,
+ 0x11302...0x11303 => true,
+ 0x1133b...0x1133c => true,
+ 0x1133e...0x1133f => true,
+ 0x11340 => true,
+ 0x11341...0x11344 => true,
+ 0x11347...0x11348 => true,
+ 0x1134b...0x1134d => true,
+ 0x11357 => true,
+ 0x11362...0x11363 => true,
+ 0x11366...0x1136c => true,
+ 0x11370...0x11374 => true,
+ 0x11435...0x11437 => true,
+ 0x11438...0x1143f => true,
+ 0x11440...0x11441 => true,
+ 0x11442...0x11444 => true,
+ 0x11445 => true,
+ 0x11446 => true,
+ 0x1145e => true,
+ 0x114b0...0x114b2 => true,
+ 0x114b3...0x114b8 => true,
+ 0x114b9 => true,
+ 0x114ba => true,
+ 0x114bb...0x114be => true,
+ 0x114bf...0x114c0 => true,
+ 0x114c1 => true,
+ 0x114c2...0x114c3 => true,
+ 0x115af...0x115b1 => true,
+ 0x115b2...0x115b5 => true,
+ 0x115b8...0x115bb => true,
+ 0x115bc...0x115bd => true,
+ 0x115be => true,
+ 0x115bf...0x115c0 => true,
+ 0x115dc...0x115dd => true,
+ 0x11630...0x11632 => true,
+ 0x11633...0x1163a => true,
+ 0x1163b...0x1163c => true,
+ 0x1163d => true,
+ 0x1163e => true,
+ 0x1163f...0x11640 => true,
+ 0x116ab => true,
+ 0x116ac => true,
+ 0x116ad => true,
+ 0x116ae...0x116af => true,
+ 0x116b0...0x116b5 => true,
+ 0x116b6 => true,
+ 0x116b7 => true,
+ 0x1171d...0x1171f => true,
+ 0x11720...0x11721 => true,
+ 0x11722...0x11725 => true,
+ 0x11726 => true,
+ 0x11727...0x1172b => true,
+ 0x1182c...0x1182e => true,
+ 0x1182f...0x11837 => true,
+ 0x11838 => true,
+ 0x11839...0x1183a => true,
+ 0x11930...0x11935 => true,
+ 0x11937...0x11938 => true,
+ 0x1193b...0x1193c => true,
+ 0x1193d => true,
+ 0x1193e => true,
+ 0x11940 => true,
+ 0x11942 => true,
+ 0x11943 => true,
+ 0x119d1...0x119d3 => true,
+ 0x119d4...0x119d7 => true,
+ 0x119da...0x119db => true,
+ 0x119dc...0x119df => true,
+ 0x119e0 => true,
+ 0x119e4 => true,
+ 0x11a01...0x11a0a => true,
+ 0x11a33...0x11a38 => true,
+ 0x11a39 => true,
+ 0x11a3b...0x11a3e => true,
+ 0x11a47 => true,
+ 0x11a51...0x11a56 => true,
+ 0x11a57...0x11a58 => true,
+ 0x11a59...0x11a5b => true,
+ 0x11a8a...0x11a96 => true,
+ 0x11a97 => true,
+ 0x11a98...0x11a99 => true,
+ 0x11c2f => true,
+ 0x11c30...0x11c36 => true,
+ 0x11c38...0x11c3d => true,
+ 0x11c3e => true,
+ 0x11c3f => true,
+ 0x11c92...0x11ca7 => true,
+ 0x11ca9 => true,
+ 0x11caa...0x11cb0 => true,
+ 0x11cb1 => true,
+ 0x11cb2...0x11cb3 => true,
+ 0x11cb4 => true,
+ 0x11cb5...0x11cb6 => true,
+ 0x11d31...0x11d36 => true,
+ 0x11d3a => true,
+ 0x11d3c...0x11d3d => true,
+ 0x11d3f...0x11d45 => true,
+ 0x11d47 => true,
+ 0x11d8a...0x11d8e => true,
+ 0x11d90...0x11d91 => true,
+ 0x11d93...0x11d94 => true,
+ 0x11d95 => true,
+ 0x11d96 => true,
+ 0x11d97 => true,
+ 0x11ef3...0x11ef4 => true,
+ 0x11ef5...0x11ef6 => true,
+ 0x11f00...0x11f01 => true,
+ 0x11f03 => true,
+ 0x11f34...0x11f35 => true,
+ 0x11f36...0x11f3a => true,
+ 0x11f3e...0x11f3f => true,
+ 0x11f40 => true,
+ 0x11f41 => true,
+ 0x11f42 => true,
+ 0x13440 => true,
+ 0x13447...0x13455 => true,
+ 0x16af0...0x16af4 => true,
+ 0x16b30...0x16b36 => true,
+ 0x16f4f => true,
+ 0x16f51...0x16f87 => true,
+ 0x16f8f...0x16f92 => true,
+ 0x16fe4 => true,
+ 0x16ff0...0x16ff1 => true,
+ 0x1bc9d...0x1bc9e => true,
+ 0x1cf00...0x1cf2d => true,
+ 0x1cf30...0x1cf46 => true,
+ 0x1d165...0x1d166 => true,
+ 0x1d167...0x1d169 => true,
+ 0x1d16d...0x1d172 => true,
+ 0x1d17b...0x1d182 => true,
+ 0x1d185...0x1d18b => true,
+ 0x1d1aa...0x1d1ad => true,
+ 0x1d242...0x1d244 => true,
+ 0x1da00...0x1da36 => true,
+ 0x1da3b...0x1da6c => true,
+ 0x1da75 => true,
+ 0x1da84 => true,
+ 0x1da9b...0x1da9f => true,
+ 0x1daa1...0x1daaf => true,
+ 0x1e000...0x1e006 => true,
+ 0x1e008...0x1e018 => true,
+ 0x1e01b...0x1e021 => true,
+ 0x1e023...0x1e024 => true,
+ 0x1e026...0x1e02a => true,
+ 0x1e08f => true,
+ 0x1e130...0x1e136 => true,
+ 0x1e2ae => true,
+ 0x1e2ec...0x1e2ef => true,
+ 0x1e4ec...0x1e4ef => true,
+ 0x1e8d0...0x1e8d6 => true,
+ 0x1e944...0x1e94a => true,
+ 0xe0020...0xe007f => true,
+ 0xe0100...0xe01ef => true,
+ else => false,
+ };
+}
+
+pub fn isSep(cp: u21) bool {
+ if (cp < 0x85 or cp > 0x2029) return false;
+
+ return switch (cp) {
+ 0x85 => true,
+ 0x2028 => true,
+ 0x2029 => true,
+ else => false,
+ };
+}
+
+pub fn isFormat(cp: u21) bool {
+ if (cp < 0xad or cp > 0xe0001) return false;
+
+ return switch (cp) {
+ 0xad => true,
+ 0x600...0x605 => true,
+ 0x61c => true,
+ 0x6dd => true,
+ 0x70f => true,
+ 0x890...0x891 => true,
+ 0x8e2 => true,
+ 0x180e => true,
+ 0x200b => true,
+ 0x200e...0x200f => true,
+ 0x202a...0x202e => true,
+ 0x2060...0x2064 => true,
+ 0x2066...0x206f => true,
+ 0xfeff => true,
+ 0xfff9...0xfffb => true,
+ 0x110bd => true,
+ 0x110cd => true,
+ 0x13430...0x1343f => true,
+ 0x1bca0...0x1bca3 => true,
+ 0x1d173...0x1d17a => true,
+ 0xe0001 => true,
+ else => false,
+ };
+}
+
+pub fn isSp(cp: u21) bool {
+ if (cp < 0x9 or cp > 0x3000) return false;
+
+ return switch (cp) {
+ 0x9 => true,
+ 0xb...0xc => true,
+ 0x20 => true,
+ 0xa0 => true,
+ 0x1680 => true,
+ 0x2000...0x200a => true,
+ 0x202f => true,
+ 0x205f => true,
+ 0x3000 => true,
+ else => false,
+ };
+}
+
+pub fn isLower(cp: u21) bool {
+ if (cp < 0x61 or cp > 0x1e943) return false;
+
+ return switch (cp) {
+ 0x61...0x7a => true,
+ 0xaa => true,
+ 0xb5 => true,
+ 0xba => true,
+ 0xdf...0xf6 => true,
+ 0xf8...0xff => true,
+ 0x101 => true,
+ 0x103 => true,
+ 0x105 => true,
+ 0x107 => true,
+ 0x109 => true,
+ 0x10b => true,
+ 0x10d => true,
+ 0x10f => true,
+ 0x111 => true,
+ 0x113 => true,
+ 0x115 => true,
+ 0x117 => true,
+ 0x119 => true,
+ 0x11b => true,
+ 0x11d => true,
+ 0x11f => true,
+ 0x121 => true,
+ 0x123 => true,
+ 0x125 => true,
+ 0x127 => true,
+ 0x129 => true,
+ 0x12b => true,
+ 0x12d => true,
+ 0x12f => true,
+ 0x131 => true,
+ 0x133 => true,
+ 0x135 => true,
+ 0x137...0x138 => true,
+ 0x13a => true,
+ 0x13c => true,
+ 0x13e => true,
+ 0x140 => true,
+ 0x142 => true,
+ 0x144 => true,
+ 0x146 => true,
+ 0x148...0x149 => true,
+ 0x14b => true,
+ 0x14d => true,
+ 0x14f => true,
+ 0x151 => true,
+ 0x153 => true,
+ 0x155 => true,
+ 0x157 => true,
+ 0x159 => true,
+ 0x15b => true,
+ 0x15d => true,
+ 0x15f => true,
+ 0x161 => true,
+ 0x163 => true,
+ 0x165 => true,
+ 0x167 => true,
+ 0x169 => true,
+ 0x16b => true,
+ 0x16d => true,
+ 0x16f => true,
+ 0x171 => true,
+ 0x173 => true,
+ 0x175 => true,
+ 0x177 => true,
+ 0x17a => true,
+ 0x17c => true,
+ 0x17e...0x180 => true,
+ 0x183 => true,
+ 0x185 => true,
+ 0x188 => true,
+ 0x18c...0x18d => true,
+ 0x192 => true,
+ 0x195 => true,
+ 0x199...0x19b => true,
+ 0x19e => true,
+ 0x1a1 => true,
+ 0x1a3 => true,
+ 0x1a5 => true,
+ 0x1a8 => true,
+ 0x1aa...0x1ab => true,
+ 0x1ad => true,
+ 0x1b0 => true,
+ 0x1b4 => true,
+ 0x1b6 => true,
+ 0x1b9...0x1ba => true,
+ 0x1bd...0x1bf => true,
+ 0x1c6 => true,
+ 0x1c9 => true,
+ 0x1cc => true,
+ 0x1ce => true,
+ 0x1d0 => true,
+ 0x1d2 => true,
+ 0x1d4 => true,
+ 0x1d6 => true,
+ 0x1d8 => true,
+ 0x1da => true,
+ 0x1dc...0x1dd => true,
+ 0x1df => true,
+ 0x1e1 => true,
+ 0x1e3 => true,
+ 0x1e5 => true,
+ 0x1e7 => true,
+ 0x1e9 => true,
+ 0x1eb => true,
+ 0x1ed => true,
+ 0x1ef...0x1f0 => true,
+ 0x1f3 => true,
+ 0x1f5 => true,
+ 0x1f9 => true,
+ 0x1fb => true,
+ 0x1fd => true,
+ 0x1ff => true,
+ 0x201 => true,
+ 0x203 => true,
+ 0x205 => true,
+ 0x207 => true,
+ 0x209 => true,
+ 0x20b => true,
+ 0x20d => true,
+ 0x20f => true,
+ 0x211 => true,
+ 0x213 => true,
+ 0x215 => true,
+ 0x217 => true,
+ 0x219 => true,
+ 0x21b => true,
+ 0x21d => true,
+ 0x21f => true,
+ 0x221 => true,
+ 0x223 => true,
+ 0x225 => true,
+ 0x227 => true,
+ 0x229 => true,
+ 0x22b => true,
+ 0x22d => true,
+ 0x22f => true,
+ 0x231 => true,
+ 0x233...0x239 => true,
+ 0x23c => true,
+ 0x23f...0x240 => true,
+ 0x242 => true,
+ 0x247 => true,
+ 0x249 => true,
+ 0x24b => true,
+ 0x24d => true,
+ 0x24f...0x293 => true,
+ 0x295...0x2af => true,
+ 0x2b0...0x2b8 => true,
+ 0x2c0...0x2c1 => true,
+ 0x2e0...0x2e4 => true,
+ 0x371 => true,
+ 0x373 => true,
+ 0x377 => true,
+ 0x37a => true,
+ 0x37b...0x37d => true,
+ 0x390 => true,
+ 0x3ac...0x3ce => true,
+ 0x3d0...0x3d1 => true,
+ 0x3d5...0x3d7 => true,
+ 0x3d9 => true,
+ 0x3db => true,
+ 0x3dd => true,
+ 0x3df => true,
+ 0x3e1 => true,
+ 0x3e3 => true,
+ 0x3e5 => true,
+ 0x3e7 => true,
+ 0x3e9 => true,
+ 0x3eb => true,
+ 0x3ed => true,
+ 0x3ef...0x3f3 => true,
+ 0x3f5 => true,
+ 0x3f8 => true,
+ 0x3fb...0x3fc => true,
+ 0x430...0x45f => true,
+ 0x461 => true,
+ 0x463 => true,
+ 0x465 => true,
+ 0x467 => true,
+ 0x469 => true,
+ 0x46b => true,
+ 0x46d => true,
+ 0x46f => true,
+ 0x471 => true,
+ 0x473 => true,
+ 0x475 => true,
+ 0x477 => true,
+ 0x479 => true,
+ 0x47b => true,
+ 0x47d => true,
+ 0x47f => true,
+ 0x481 => true,
+ 0x48b => true,
+ 0x48d => true,
+ 0x48f => true,
+ 0x491 => true,
+ 0x493 => true,
+ 0x495 => true,
+ 0x497 => true,
+ 0x499 => true,
+ 0x49b => true,
+ 0x49d => true,
+ 0x49f => true,
+ 0x4a1 => true,
+ 0x4a3 => true,
+ 0x4a5 => true,
+ 0x4a7 => true,
+ 0x4a9 => true,
+ 0x4ab => true,
+ 0x4ad => true,
+ 0x4af => true,
+ 0x4b1 => true,
+ 0x4b3 => true,
+ 0x4b5 => true,
+ 0x4b7 => true,
+ 0x4b9 => true,
+ 0x4bb => true,
+ 0x4bd => true,
+ 0x4bf => true,
+ 0x4c2 => true,
+ 0x4c4 => true,
+ 0x4c6 => true,
+ 0x4c8 => true,
+ 0x4ca => true,
+ 0x4cc => true,
+ 0x4ce...0x4cf => true,
+ 0x4d1 => true,
+ 0x4d3 => true,
+ 0x4d5 => true,
+ 0x4d7 => true,
+ 0x4d9 => true,
+ 0x4db => true,
+ 0x4dd => true,
+ 0x4df => true,
+ 0x4e1 => true,
+ 0x4e3 => true,
+ 0x4e5 => true,
+ 0x4e7 => true,
+ 0x4e9 => true,
+ 0x4eb => true,
+ 0x4ed => true,
+ 0x4ef => true,
+ 0x4f1 => true,
+ 0x4f3 => true,
+ 0x4f5 => true,
+ 0x4f7 => true,
+ 0x4f9 => true,
+ 0x4fb => true,
+ 0x4fd => true,
+ 0x4ff => true,
+ 0x501 => true,
+ 0x503 => true,
+ 0x505 => true,
+ 0x507 => true,
+ 0x509 => true,
+ 0x50b => true,
+ 0x50d => true,
+ 0x50f => true,
+ 0x511 => true,
+ 0x513 => true,
+ 0x515 => true,
+ 0x517 => true,
+ 0x519 => true,
+ 0x51b => true,
+ 0x51d => true,
+ 0x51f => true,
+ 0x521 => true,
+ 0x523 => true,
+ 0x525 => true,
+ 0x527 => true,
+ 0x529 => true,
+ 0x52b => true,
+ 0x52d => true,
+ 0x52f => true,
+ 0x560...0x588 => true,
+ 0x10fc => true,
+ 0x13f8...0x13fd => true,
+ 0x1c80...0x1c88 => true,
+ 0x1d00...0x1d2b => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d6b...0x1d77 => true,
+ 0x1d78 => true,
+ 0x1d79...0x1d9a => true,
+ 0x1d9b...0x1dbf => true,
+ 0x1e01 => true,
+ 0x1e03 => true,
+ 0x1e05 => true,
+ 0x1e07 => true,
+ 0x1e09 => true,
+ 0x1e0b => true,
+ 0x1e0d => true,
+ 0x1e0f => true,
+ 0x1e11 => true,
+ 0x1e13 => true,
+ 0x1e15 => true,
+ 0x1e17 => true,
+ 0x1e19 => true,
+ 0x1e1b => true,
+ 0x1e1d => true,
+ 0x1e1f => true,
+ 0x1e21 => true,
+ 0x1e23 => true,
+ 0x1e25 => true,
+ 0x1e27 => true,
+ 0x1e29 => true,
+ 0x1e2b => true,
+ 0x1e2d => true,
+ 0x1e2f => true,
+ 0x1e31 => true,
+ 0x1e33 => true,
+ 0x1e35 => true,
+ 0x1e37 => true,
+ 0x1e39 => true,
+ 0x1e3b => true,
+ 0x1e3d => true,
+ 0x1e3f => true,
+ 0x1e41 => true,
+ 0x1e43 => true,
+ 0x1e45 => true,
+ 0x1e47 => true,
+ 0x1e49 => true,
+ 0x1e4b => true,
+ 0x1e4d => true,
+ 0x1e4f => true,
+ 0x1e51 => true,
+ 0x1e53 => true,
+ 0x1e55 => true,
+ 0x1e57 => true,
+ 0x1e59 => true,
+ 0x1e5b => true,
+ 0x1e5d => true,
+ 0x1e5f => true,
+ 0x1e61 => true,
+ 0x1e63 => true,
+ 0x1e65 => true,
+ 0x1e67 => true,
+ 0x1e69 => true,
+ 0x1e6b => true,
+ 0x1e6d => true,
+ 0x1e6f => true,
+ 0x1e71 => true,
+ 0x1e73 => true,
+ 0x1e75 => true,
+ 0x1e77 => true,
+ 0x1e79 => true,
+ 0x1e7b => true,
+ 0x1e7d => true,
+ 0x1e7f => true,
+ 0x1e81 => true,
+ 0x1e83 => true,
+ 0x1e85 => true,
+ 0x1e87 => true,
+ 0x1e89 => true,
+ 0x1e8b => true,
+ 0x1e8d => true,
+ 0x1e8f => true,
+ 0x1e91 => true,
+ 0x1e93 => true,
+ 0x1e95...0x1e9d => true,
+ 0x1e9f => true,
+ 0x1ea1 => true,
+ 0x1ea3 => true,
+ 0x1ea5 => true,
+ 0x1ea7 => true,
+ 0x1ea9 => true,
+ 0x1eab => true,
+ 0x1ead => true,
+ 0x1eaf => true,
+ 0x1eb1 => true,
+ 0x1eb3 => true,
+ 0x1eb5 => true,
+ 0x1eb7 => true,
+ 0x1eb9 => true,
+ 0x1ebb => true,
+ 0x1ebd => true,
+ 0x1ebf => true,
+ 0x1ec1 => true,
+ 0x1ec3 => true,
+ 0x1ec5 => true,
+ 0x1ec7 => true,
+ 0x1ec9 => true,
+ 0x1ecb => true,
+ 0x1ecd => true,
+ 0x1ecf => true,
+ 0x1ed1 => true,
+ 0x1ed3 => true,
+ 0x1ed5 => true,
+ 0x1ed7 => true,
+ 0x1ed9 => true,
+ 0x1edb => true,
+ 0x1edd => true,
+ 0x1edf => true,
+ 0x1ee1 => true,
+ 0x1ee3 => true,
+ 0x1ee5 => true,
+ 0x1ee7 => true,
+ 0x1ee9 => true,
+ 0x1eeb => true,
+ 0x1eed => true,
+ 0x1eef => true,
+ 0x1ef1 => true,
+ 0x1ef3 => true,
+ 0x1ef5 => true,
+ 0x1ef7 => true,
+ 0x1ef9 => true,
+ 0x1efb => true,
+ 0x1efd => true,
+ 0x1eff...0x1f07 => true,
+ 0x1f10...0x1f15 => true,
+ 0x1f20...0x1f27 => true,
+ 0x1f30...0x1f37 => true,
+ 0x1f40...0x1f45 => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f60...0x1f67 => true,
+ 0x1f70...0x1f7d => true,
+ 0x1f80...0x1f87 => true,
+ 0x1f90...0x1f97 => true,
+ 0x1fa0...0x1fa7 => true,
+ 0x1fb0...0x1fb4 => true,
+ 0x1fb6...0x1fb7 => true,
+ 0x1fbe => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fc7 => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fd7 => true,
+ 0x1fe0...0x1fe7 => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ff7 => true,
+ 0x2071 => true,
+ 0x207f => true,
+ 0x2090...0x209c => true,
+ 0x210a => true,
+ 0x210e...0x210f => true,
+ 0x2113 => true,
+ 0x212f => true,
+ 0x2134 => true,
+ 0x2139 => true,
+ 0x213c...0x213d => true,
+ 0x2146...0x2149 => true,
+ 0x214e => true,
+ 0x2170...0x217f => true,
+ 0x2184 => true,
+ 0x24d0...0x24e9 => true,
+ 0x2c30...0x2c5f => true,
+ 0x2c61 => true,
+ 0x2c65...0x2c66 => true,
+ 0x2c68 => true,
+ 0x2c6a => true,
+ 0x2c6c => true,
+ 0x2c71 => true,
+ 0x2c73...0x2c74 => true,
+ 0x2c76...0x2c7b => true,
+ 0x2c7c...0x2c7d => true,
+ 0x2c81 => true,
+ 0x2c83 => true,
+ 0x2c85 => true,
+ 0x2c87 => true,
+ 0x2c89 => true,
+ 0x2c8b => true,
+ 0x2c8d => true,
+ 0x2c8f => true,
+ 0x2c91 => true,
+ 0x2c93 => true,
+ 0x2c95 => true,
+ 0x2c97 => true,
+ 0x2c99 => true,
+ 0x2c9b => true,
+ 0x2c9d => true,
+ 0x2c9f => true,
+ 0x2ca1 => true,
+ 0x2ca3 => true,
+ 0x2ca5 => true,
+ 0x2ca7 => true,
+ 0x2ca9 => true,
+ 0x2cab => true,
+ 0x2cad => true,
+ 0x2caf => true,
+ 0x2cb1 => true,
+ 0x2cb3 => true,
+ 0x2cb5 => true,
+ 0x2cb7 => true,
+ 0x2cb9 => true,
+ 0x2cbb => true,
+ 0x2cbd => true,
+ 0x2cbf => true,
+ 0x2cc1 => true,
+ 0x2cc3 => true,
+ 0x2cc5 => true,
+ 0x2cc7 => true,
+ 0x2cc9 => true,
+ 0x2ccb => true,
+ 0x2ccd => true,
+ 0x2ccf => true,
+ 0x2cd1 => true,
+ 0x2cd3 => true,
+ 0x2cd5 => true,
+ 0x2cd7 => true,
+ 0x2cd9 => true,
+ 0x2cdb => true,
+ 0x2cdd => true,
+ 0x2cdf => true,
+ 0x2ce1 => true,
+ 0x2ce3...0x2ce4 => true,
+ 0x2cec => true,
+ 0x2cee => true,
+ 0x2cf3 => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0xa641 => true,
+ 0xa643 => true,
+ 0xa645 => true,
+ 0xa647 => true,
+ 0xa649 => true,
+ 0xa64b => true,
+ 0xa64d => true,
+ 0xa64f => true,
+ 0xa651 => true,
+ 0xa653 => true,
+ 0xa655 => true,
+ 0xa657 => true,
+ 0xa659 => true,
+ 0xa65b => true,
+ 0xa65d => true,
+ 0xa65f => true,
+ 0xa661 => true,
+ 0xa663 => true,
+ 0xa665 => true,
+ 0xa667 => true,
+ 0xa669 => true,
+ 0xa66b => true,
+ 0xa66d => true,
+ 0xa681 => true,
+ 0xa683 => true,
+ 0xa685 => true,
+ 0xa687 => true,
+ 0xa689 => true,
+ 0xa68b => true,
+ 0xa68d => true,
+ 0xa68f => true,
+ 0xa691 => true,
+ 0xa693 => true,
+ 0xa695 => true,
+ 0xa697 => true,
+ 0xa699 => true,
+ 0xa69b => true,
+ 0xa69c...0xa69d => true,
+ 0xa723 => true,
+ 0xa725 => true,
+ 0xa727 => true,
+ 0xa729 => true,
+ 0xa72b => true,
+ 0xa72d => true,
+ 0xa72f...0xa731 => true,
+ 0xa733 => true,
+ 0xa735 => true,
+ 0xa737 => true,
+ 0xa739 => true,
+ 0xa73b => true,
+ 0xa73d => true,
+ 0xa73f => true,
+ 0xa741 => true,
+ 0xa743 => true,
+ 0xa745 => true,
+ 0xa747 => true,
+ 0xa749 => true,
+ 0xa74b => true,
+ 0xa74d => true,
+ 0xa74f => true,
+ 0xa751 => true,
+ 0xa753 => true,
+ 0xa755 => true,
+ 0xa757 => true,
+ 0xa759 => true,
+ 0xa75b => true,
+ 0xa75d => true,
+ 0xa75f => true,
+ 0xa761 => true,
+ 0xa763 => true,
+ 0xa765 => true,
+ 0xa767 => true,
+ 0xa769 => true,
+ 0xa76b => true,
+ 0xa76d => true,
+ 0xa76f => true,
+ 0xa770 => true,
+ 0xa771...0xa778 => true,
+ 0xa77a => true,
+ 0xa77c => true,
+ 0xa77f => true,
+ 0xa781 => true,
+ 0xa783 => true,
+ 0xa785 => true,
+ 0xa787 => true,
+ 0xa78c => true,
+ 0xa78e => true,
+ 0xa791 => true,
+ 0xa793...0xa795 => true,
+ 0xa797 => true,
+ 0xa799 => true,
+ 0xa79b => true,
+ 0xa79d => true,
+ 0xa79f => true,
+ 0xa7a1 => true,
+ 0xa7a3 => true,
+ 0xa7a5 => true,
+ 0xa7a7 => true,
+ 0xa7a9 => true,
+ 0xa7af => true,
+ 0xa7b5 => true,
+ 0xa7b7 => true,
+ 0xa7b9 => true,
+ 0xa7bb => true,
+ 0xa7bd => true,
+ 0xa7bf => true,
+ 0xa7c1 => true,
+ 0xa7c3 => true,
+ 0xa7c8 => true,
+ 0xa7ca => true,
+ 0xa7d1 => true,
+ 0xa7d3 => true,
+ 0xa7d5 => true,
+ 0xa7d7 => true,
+ 0xa7d9 => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f6 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa7fa => true,
+ 0xab30...0xab5a => true,
+ 0xab5c...0xab5f => true,
+ 0xab60...0xab68 => true,
+ 0xab69 => true,
+ 0xab70...0xabbf => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xff41...0xff5a => true,
+ 0x10428...0x1044f => true,
+ 0x104d8...0x104fb => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10780 => true,
+ 0x10783...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x118c0...0x118df => true,
+ 0x16e60...0x16e7f => true,
+ 0x1d41a...0x1d433 => true,
+ 0x1d44e...0x1d454 => true,
+ 0x1d456...0x1d467 => true,
+ 0x1d482...0x1d49b => true,
+ 0x1d4b6...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d4cf => true,
+ 0x1d4ea...0x1d503 => true,
+ 0x1d51e...0x1d537 => true,
+ 0x1d552...0x1d56b => true,
+ 0x1d586...0x1d59f => true,
+ 0x1d5ba...0x1d5d3 => true,
+ 0x1d5ee...0x1d607 => true,
+ 0x1d622...0x1d63b => true,
+ 0x1d656...0x1d66f => true,
+ 0x1d68a...0x1d6a5 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6dc...0x1d6e1 => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d716...0x1d71b => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d750...0x1d755 => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d78a...0x1d78f => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c4...0x1d7c9 => true,
+ 0x1d7cb => true,
+ 0x1df00...0x1df09 => true,
+ 0x1df0b...0x1df1e => true,
+ 0x1df25...0x1df2a => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e922...0x1e943 => true,
+ else => false,
+ };
+}
+
+pub fn isUpper(cp: u21) bool {
+ if (cp < 0x41 or cp > 0x1f189) return false;
+
+ return switch (cp) {
+ 0x41...0x5a => true,
+ 0xc0...0xd6 => true,
+ 0xd8...0xde => true,
+ 0x100 => true,
+ 0x102 => true,
+ 0x104 => true,
+ 0x106 => true,
+ 0x108 => true,
+ 0x10a => true,
+ 0x10c => true,
+ 0x10e => true,
+ 0x110 => true,
+ 0x112 => true,
+ 0x114 => true,
+ 0x116 => true,
+ 0x118 => true,
+ 0x11a => true,
+ 0x11c => true,
+ 0x11e => true,
+ 0x120 => true,
+ 0x122 => true,
+ 0x124 => true,
+ 0x126 => true,
+ 0x128 => true,
+ 0x12a => true,
+ 0x12c => true,
+ 0x12e => true,
+ 0x130 => true,
+ 0x132 => true,
+ 0x134 => true,
+ 0x136 => true,
+ 0x139 => true,
+ 0x13b => true,
+ 0x13d => true,
+ 0x13f => true,
+ 0x141 => true,
+ 0x143 => true,
+ 0x145 => true,
+ 0x147 => true,
+ 0x14a => true,
+ 0x14c => true,
+ 0x14e => true,
+ 0x150 => true,
+ 0x152 => true,
+ 0x154 => true,
+ 0x156 => true,
+ 0x158 => true,
+ 0x15a => true,
+ 0x15c => true,
+ 0x15e => true,
+ 0x160 => true,
+ 0x162 => true,
+ 0x164 => true,
+ 0x166 => true,
+ 0x168 => true,
+ 0x16a => true,
+ 0x16c => true,
+ 0x16e => true,
+ 0x170 => true,
+ 0x172 => true,
+ 0x174 => true,
+ 0x176 => true,
+ 0x178...0x179 => true,
+ 0x17b => true,
+ 0x17d => true,
+ 0x181...0x182 => true,
+ 0x184 => true,
+ 0x186...0x187 => true,
+ 0x189...0x18b => true,
+ 0x18e...0x191 => true,
+ 0x193...0x194 => true,
+ 0x196...0x198 => true,
+ 0x19c...0x19d => true,
+ 0x19f...0x1a0 => true,
+ 0x1a2 => true,
+ 0x1a4 => true,
+ 0x1a6...0x1a7 => true,
+ 0x1a9 => true,
+ 0x1ac => true,
+ 0x1ae...0x1af => true,
+ 0x1b1...0x1b3 => true,
+ 0x1b5 => true,
+ 0x1b7...0x1b8 => true,
+ 0x1bc => true,
+ 0x1c4...0x1c5 => true,
+ 0x1c7...0x1c8 => true,
+ 0x1ca...0x1cb => true,
+ 0x1cd => true,
+ 0x1cf => true,
+ 0x1d1 => true,
+ 0x1d3 => true,
+ 0x1d5 => true,
+ 0x1d7 => true,
+ 0x1d9 => true,
+ 0x1db => true,
+ 0x1de => true,
+ 0x1e0 => true,
+ 0x1e2 => true,
+ 0x1e4 => true,
+ 0x1e6 => true,
+ 0x1e8 => true,
+ 0x1ea => true,
+ 0x1ec => true,
+ 0x1ee => true,
+ 0x1f1...0x1f2 => true,
+ 0x1f4 => true,
+ 0x1f6...0x1f8 => true,
+ 0x1fa => true,
+ 0x1fc => true,
+ 0x1fe => true,
+ 0x200 => true,
+ 0x202 => true,
+ 0x204 => true,
+ 0x206 => true,
+ 0x208 => true,
+ 0x20a => true,
+ 0x20c => true,
+ 0x20e => true,
+ 0x210 => true,
+ 0x212 => true,
+ 0x214 => true,
+ 0x216 => true,
+ 0x218 => true,
+ 0x21a => true,
+ 0x21c => true,
+ 0x21e => true,
+ 0x220 => true,
+ 0x222 => true,
+ 0x224 => true,
+ 0x226 => true,
+ 0x228 => true,
+ 0x22a => true,
+ 0x22c => true,
+ 0x22e => true,
+ 0x230 => true,
+ 0x232 => true,
+ 0x23a...0x23b => true,
+ 0x23d...0x23e => true,
+ 0x241 => true,
+ 0x243...0x246 => true,
+ 0x248 => true,
+ 0x24a => true,
+ 0x24c => true,
+ 0x24e => true,
+ 0x370 => true,
+ 0x372 => true,
+ 0x376 => true,
+ 0x37f => true,
+ 0x386 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x38f => true,
+ 0x391...0x3a1 => true,
+ 0x3a3...0x3ab => true,
+ 0x3cf => true,
+ 0x3d2...0x3d4 => true,
+ 0x3d8 => true,
+ 0x3da => true,
+ 0x3dc => true,
+ 0x3de => true,
+ 0x3e0 => true,
+ 0x3e2 => true,
+ 0x3e4 => true,
+ 0x3e6 => true,
+ 0x3e8 => true,
+ 0x3ea => true,
+ 0x3ec => true,
+ 0x3ee => true,
+ 0x3f4 => true,
+ 0x3f7 => true,
+ 0x3f9...0x3fa => true,
+ 0x3fd...0x42f => true,
+ 0x460 => true,
+ 0x462 => true,
+ 0x464 => true,
+ 0x466 => true,
+ 0x468 => true,
+ 0x46a => true,
+ 0x46c => true,
+ 0x46e => true,
+ 0x470 => true,
+ 0x472 => true,
+ 0x474 => true,
+ 0x476 => true,
+ 0x478 => true,
+ 0x47a => true,
+ 0x47c => true,
+ 0x47e => true,
+ 0x480 => true,
+ 0x48a => true,
+ 0x48c => true,
+ 0x48e => true,
+ 0x490 => true,
+ 0x492 => true,
+ 0x494 => true,
+ 0x496 => true,
+ 0x498 => true,
+ 0x49a => true,
+ 0x49c => true,
+ 0x49e => true,
+ 0x4a0 => true,
+ 0x4a2 => true,
+ 0x4a4 => true,
+ 0x4a6 => true,
+ 0x4a8 => true,
+ 0x4aa => true,
+ 0x4ac => true,
+ 0x4ae => true,
+ 0x4b0 => true,
+ 0x4b2 => true,
+ 0x4b4 => true,
+ 0x4b6 => true,
+ 0x4b8 => true,
+ 0x4ba => true,
+ 0x4bc => true,
+ 0x4be => true,
+ 0x4c0...0x4c1 => true,
+ 0x4c3 => true,
+ 0x4c5 => true,
+ 0x4c7 => true,
+ 0x4c9 => true,
+ 0x4cb => true,
+ 0x4cd => true,
+ 0x4d0 => true,
+ 0x4d2 => true,
+ 0x4d4 => true,
+ 0x4d6 => true,
+ 0x4d8 => true,
+ 0x4da => true,
+ 0x4dc => true,
+ 0x4de => true,
+ 0x4e0 => true,
+ 0x4e2 => true,
+ 0x4e4 => true,
+ 0x4e6 => true,
+ 0x4e8 => true,
+ 0x4ea => true,
+ 0x4ec => true,
+ 0x4ee => true,
+ 0x4f0 => true,
+ 0x4f2 => true,
+ 0x4f4 => true,
+ 0x4f6 => true,
+ 0x4f8 => true,
+ 0x4fa => true,
+ 0x4fc => true,
+ 0x4fe => true,
+ 0x500 => true,
+ 0x502 => true,
+ 0x504 => true,
+ 0x506 => true,
+ 0x508 => true,
+ 0x50a => true,
+ 0x50c => true,
+ 0x50e => true,
+ 0x510 => true,
+ 0x512 => true,
+ 0x514 => true,
+ 0x516 => true,
+ 0x518 => true,
+ 0x51a => true,
+ 0x51c => true,
+ 0x51e => true,
+ 0x520 => true,
+ 0x522 => true,
+ 0x524 => true,
+ 0x526 => true,
+ 0x528 => true,
+ 0x52a => true,
+ 0x52c => true,
+ 0x52e => true,
+ 0x531...0x556 => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x13a0...0x13f5 => true,
+ 0x1e00 => true,
+ 0x1e02 => true,
+ 0x1e04 => true,
+ 0x1e06 => true,
+ 0x1e08 => true,
+ 0x1e0a => true,
+ 0x1e0c => true,
+ 0x1e0e => true,
+ 0x1e10 => true,
+ 0x1e12 => true,
+ 0x1e14 => true,
+ 0x1e16 => true,
+ 0x1e18 => true,
+ 0x1e1a => true,
+ 0x1e1c => true,
+ 0x1e1e => true,
+ 0x1e20 => true,
+ 0x1e22 => true,
+ 0x1e24 => true,
+ 0x1e26 => true,
+ 0x1e28 => true,
+ 0x1e2a => true,
+ 0x1e2c => true,
+ 0x1e2e => true,
+ 0x1e30 => true,
+ 0x1e32 => true,
+ 0x1e34 => true,
+ 0x1e36 => true,
+ 0x1e38 => true,
+ 0x1e3a => true,
+ 0x1e3c => true,
+ 0x1e3e => true,
+ 0x1e40 => true,
+ 0x1e42 => true,
+ 0x1e44 => true,
+ 0x1e46 => true,
+ 0x1e48 => true,
+ 0x1e4a => true,
+ 0x1e4c => true,
+ 0x1e4e => true,
+ 0x1e50 => true,
+ 0x1e52 => true,
+ 0x1e54 => true,
+ 0x1e56 => true,
+ 0x1e58 => true,
+ 0x1e5a => true,
+ 0x1e5c => true,
+ 0x1e5e => true,
+ 0x1e60 => true,
+ 0x1e62 => true,
+ 0x1e64 => true,
+ 0x1e66 => true,
+ 0x1e68 => true,
+ 0x1e6a => true,
+ 0x1e6c => true,
+ 0x1e6e => true,
+ 0x1e70 => true,
+ 0x1e72 => true,
+ 0x1e74 => true,
+ 0x1e76 => true,
+ 0x1e78 => true,
+ 0x1e7a => true,
+ 0x1e7c => true,
+ 0x1e7e => true,
+ 0x1e80 => true,
+ 0x1e82 => true,
+ 0x1e84 => true,
+ 0x1e86 => true,
+ 0x1e88 => true,
+ 0x1e8a => true,
+ 0x1e8c => true,
+ 0x1e8e => true,
+ 0x1e90 => true,
+ 0x1e92 => true,
+ 0x1e94 => true,
+ 0x1e9e => true,
+ 0x1ea0 => true,
+ 0x1ea2 => true,
+ 0x1ea4 => true,
+ 0x1ea6 => true,
+ 0x1ea8 => true,
+ 0x1eaa => true,
+ 0x1eac => true,
+ 0x1eae => true,
+ 0x1eb0 => true,
+ 0x1eb2 => true,
+ 0x1eb4 => true,
+ 0x1eb6 => true,
+ 0x1eb8 => true,
+ 0x1eba => true,
+ 0x1ebc => true,
+ 0x1ebe => true,
+ 0x1ec0 => true,
+ 0x1ec2 => true,
+ 0x1ec4 => true,
+ 0x1ec6 => true,
+ 0x1ec8 => true,
+ 0x1eca => true,
+ 0x1ecc => true,
+ 0x1ece => true,
+ 0x1ed0 => true,
+ 0x1ed2 => true,
+ 0x1ed4 => true,
+ 0x1ed6 => true,
+ 0x1ed8 => true,
+ 0x1eda => true,
+ 0x1edc => true,
+ 0x1ede => true,
+ 0x1ee0 => true,
+ 0x1ee2 => true,
+ 0x1ee4 => true,
+ 0x1ee6 => true,
+ 0x1ee8 => true,
+ 0x1eea => true,
+ 0x1eec => true,
+ 0x1eee => true,
+ 0x1ef0 => true,
+ 0x1ef2 => true,
+ 0x1ef4 => true,
+ 0x1ef6 => true,
+ 0x1ef8 => true,
+ 0x1efa => true,
+ 0x1efc => true,
+ 0x1efe => true,
+ 0x1f08...0x1f0f => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f28...0x1f2f => true,
+ 0x1f38...0x1f3f => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f => true,
+ 0x1f68...0x1f6f => true,
+ 0x1f88...0x1f8f => true,
+ 0x1f98...0x1f9f => true,
+ 0x1fa8...0x1faf => true,
+ 0x1fb8...0x1fbc => true,
+ 0x1fc8...0x1fcc => true,
+ 0x1fd8...0x1fdb => true,
+ 0x1fe8...0x1fec => true,
+ 0x1ff8...0x1ffc => true,
+ 0x2102 => true,
+ 0x2107 => true,
+ 0x210b...0x210d => true,
+ 0x2110...0x2112 => true,
+ 0x2115 => true,
+ 0x2119...0x211d => true,
+ 0x2124 => true,
+ 0x2126 => true,
+ 0x2128 => true,
+ 0x212a...0x212d => true,
+ 0x2130...0x2133 => true,
+ 0x213e...0x213f => true,
+ 0x2145 => true,
+ 0x2160...0x216f => true,
+ 0x2183 => true,
+ 0x24b6...0x24cf => true,
+ 0x2c00...0x2c2f => true,
+ 0x2c60 => true,
+ 0x2c62...0x2c64 => true,
+ 0x2c67 => true,
+ 0x2c69 => true,
+ 0x2c6b => true,
+ 0x2c6d...0x2c70 => true,
+ 0x2c72 => true,
+ 0x2c75 => true,
+ 0x2c7e...0x2c80 => true,
+ 0x2c82 => true,
+ 0x2c84 => true,
+ 0x2c86 => true,
+ 0x2c88 => true,
+ 0x2c8a => true,
+ 0x2c8c => true,
+ 0x2c8e => true,
+ 0x2c90 => true,
+ 0x2c92 => true,
+ 0x2c94 => true,
+ 0x2c96 => true,
+ 0x2c98 => true,
+ 0x2c9a => true,
+ 0x2c9c => true,
+ 0x2c9e => true,
+ 0x2ca0 => true,
+ 0x2ca2 => true,
+ 0x2ca4 => true,
+ 0x2ca6 => true,
+ 0x2ca8 => true,
+ 0x2caa => true,
+ 0x2cac => true,
+ 0x2cae => true,
+ 0x2cb0 => true,
+ 0x2cb2 => true,
+ 0x2cb4 => true,
+ 0x2cb6 => true,
+ 0x2cb8 => true,
+ 0x2cba => true,
+ 0x2cbc => true,
+ 0x2cbe => true,
+ 0x2cc0 => true,
+ 0x2cc2 => true,
+ 0x2cc4 => true,
+ 0x2cc6 => true,
+ 0x2cc8 => true,
+ 0x2cca => true,
+ 0x2ccc => true,
+ 0x2cce => true,
+ 0x2cd0 => true,
+ 0x2cd2 => true,
+ 0x2cd4 => true,
+ 0x2cd6 => true,
+ 0x2cd8 => true,
+ 0x2cda => true,
+ 0x2cdc => true,
+ 0x2cde => true,
+ 0x2ce0 => true,
+ 0x2ce2 => true,
+ 0x2ceb => true,
+ 0x2ced => true,
+ 0x2cf2 => true,
+ 0xa640 => true,
+ 0xa642 => true,
+ 0xa644 => true,
+ 0xa646 => true,
+ 0xa648 => true,
+ 0xa64a => true,
+ 0xa64c => true,
+ 0xa64e => true,
+ 0xa650 => true,
+ 0xa652 => true,
+ 0xa654 => true,
+ 0xa656 => true,
+ 0xa658 => true,
+ 0xa65a => true,
+ 0xa65c => true,
+ 0xa65e => true,
+ 0xa660 => true,
+ 0xa662 => true,
+ 0xa664 => true,
+ 0xa666 => true,
+ 0xa668 => true,
+ 0xa66a => true,
+ 0xa66c => true,
+ 0xa680 => true,
+ 0xa682 => true,
+ 0xa684 => true,
+ 0xa686 => true,
+ 0xa688 => true,
+ 0xa68a => true,
+ 0xa68c => true,
+ 0xa68e => true,
+ 0xa690 => true,
+ 0xa692 => true,
+ 0xa694 => true,
+ 0xa696 => true,
+ 0xa698 => true,
+ 0xa69a => true,
+ 0xa722 => true,
+ 0xa724 => true,
+ 0xa726 => true,
+ 0xa728 => true,
+ 0xa72a => true,
+ 0xa72c => true,
+ 0xa72e => true,
+ 0xa732 => true,
+ 0xa734 => true,
+ 0xa736 => true,
+ 0xa738 => true,
+ 0xa73a => true,
+ 0xa73c => true,
+ 0xa73e => true,
+ 0xa740 => true,
+ 0xa742 => true,
+ 0xa744 => true,
+ 0xa746 => true,
+ 0xa748 => true,
+ 0xa74a => true,
+ 0xa74c => true,
+ 0xa74e => true,
+ 0xa750 => true,
+ 0xa752 => true,
+ 0xa754 => true,
+ 0xa756 => true,
+ 0xa758 => true,
+ 0xa75a => true,
+ 0xa75c => true,
+ 0xa75e => true,
+ 0xa760 => true,
+ 0xa762 => true,
+ 0xa764 => true,
+ 0xa766 => true,
+ 0xa768 => true,
+ 0xa76a => true,
+ 0xa76c => true,
+ 0xa76e => true,
+ 0xa779 => true,
+ 0xa77b => true,
+ 0xa77d...0xa77e => true,
+ 0xa780 => true,
+ 0xa782 => true,
+ 0xa784 => true,
+ 0xa786 => true,
+ 0xa78b => true,
+ 0xa78d => true,
+ 0xa790 => true,
+ 0xa792 => true,
+ 0xa796 => true,
+ 0xa798 => true,
+ 0xa79a => true,
+ 0xa79c => true,
+ 0xa79e => true,
+ 0xa7a0 => true,
+ 0xa7a2 => true,
+ 0xa7a4 => true,
+ 0xa7a6 => true,
+ 0xa7a8 => true,
+ 0xa7aa...0xa7ae => true,
+ 0xa7b0...0xa7b4 => true,
+ 0xa7b6 => true,
+ 0xa7b8 => true,
+ 0xa7ba => true,
+ 0xa7bc => true,
+ 0xa7be => true,
+ 0xa7c0 => true,
+ 0xa7c2 => true,
+ 0xa7c4...0xa7c7 => true,
+ 0xa7c9 => true,
+ 0xa7d0 => true,
+ 0xa7d6 => true,
+ 0xa7d8 => true,
+ 0xa7f5 => true,
+ 0xff21...0xff3a => true,
+ 0x10400...0x10427 => true,
+ 0x104b0...0x104d3 => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10c80...0x10cb2 => true,
+ 0x118a0...0x118bf => true,
+ 0x16e40...0x16e5f => true,
+ 0x1d400...0x1d419 => true,
+ 0x1d434...0x1d44d => true,
+ 0x1d468...0x1d481 => true,
+ 0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b5 => true,
+ 0x1d4d0...0x1d4e9 => true,
+ 0x1d504...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d538...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d56c...0x1d585 => true,
+ 0x1d5a0...0x1d5b9 => true,
+ 0x1d5d4...0x1d5ed => true,
+ 0x1d608...0x1d621 => true,
+ 0x1d63c...0x1d655 => true,
+ 0x1d670...0x1d689 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6e2...0x1d6fa => true,
+ 0x1d71c...0x1d734 => true,
+ 0x1d756...0x1d76e => true,
+ 0x1d790...0x1d7a8 => true,
+ 0x1d7ca => true,
+ 0x1e900...0x1e921 => true,
+ 0x1f130...0x1f149 => true,
+ 0x1f150...0x1f169 => true,
+ 0x1f170...0x1f189 => true,
+ else => false,
+ };
+}
+
+pub fn isOletter(cp: u21) bool {
+ if (cp < 0x1bb or cp > 0x323af) return false;
+
+ return switch (cp) {
+ 0x1bb => true,
+ 0x1c0...0x1c3 => true,
+ 0x294 => true,
+ 0x2b9...0x2bf => true,
+ 0x2c6...0x2d1 => true,
+ 0x2ec => true,
+ 0x2ee => true,
+ 0x374 => true,
+ 0x559 => true,
+ 0x5d0...0x5ea => true,
+ 0x5ef...0x5f2 => true,
+ 0x5f3 => true,
+ 0x620...0x63f => true,
+ 0x640 => true,
+ 0x641...0x64a => true,
+ 0x66e...0x66f => true,
+ 0x671...0x6d3 => true,
+ 0x6d5 => true,
+ 0x6e5...0x6e6 => true,
+ 0x6ee...0x6ef => true,
+ 0x6fa...0x6fc => true,
+ 0x6ff => true,
+ 0x710 => true,
+ 0x712...0x72f => true,
+ 0x74d...0x7a5 => true,
+ 0x7b1 => true,
+ 0x7ca...0x7ea => true,
+ 0x7f4...0x7f5 => true,
+ 0x7fa => true,
+ 0x800...0x815 => true,
+ 0x81a => true,
+ 0x824 => true,
+ 0x828 => true,
+ 0x840...0x858 => true,
+ 0x860...0x86a => true,
+ 0x870...0x887 => true,
+ 0x889...0x88e => true,
+ 0x8a0...0x8c8 => true,
+ 0x8c9 => true,
+ 0x904...0x939 => true,
+ 0x93d => true,
+ 0x950 => true,
+ 0x958...0x961 => true,
+ 0x971 => true,
+ 0x972...0x980 => true,
+ 0x985...0x98c => true,
+ 0x98f...0x990 => true,
+ 0x993...0x9a8 => true,
+ 0x9aa...0x9b0 => true,
+ 0x9b2 => true,
+ 0x9b6...0x9b9 => true,
+ 0x9bd => true,
+ 0x9ce => true,
+ 0x9dc...0x9dd => true,
+ 0x9df...0x9e1 => true,
+ 0x9f0...0x9f1 => true,
+ 0x9fc => true,
+ 0xa05...0xa0a => true,
+ 0xa0f...0xa10 => true,
+ 0xa13...0xa28 => true,
+ 0xa2a...0xa30 => true,
+ 0xa32...0xa33 => true,
+ 0xa35...0xa36 => true,
+ 0xa38...0xa39 => true,
+ 0xa59...0xa5c => true,
+ 0xa5e => true,
+ 0xa72...0xa74 => true,
+ 0xa85...0xa8d => true,
+ 0xa8f...0xa91 => true,
+ 0xa93...0xaa8 => true,
+ 0xaaa...0xab0 => true,
+ 0xab2...0xab3 => true,
+ 0xab5...0xab9 => true,
+ 0xabd => true,
+ 0xad0 => true,
+ 0xae0...0xae1 => true,
+ 0xaf9 => true,
+ 0xb05...0xb0c => true,
+ 0xb0f...0xb10 => true,
+ 0xb13...0xb28 => true,
+ 0xb2a...0xb30 => true,
+ 0xb32...0xb33 => true,
+ 0xb35...0xb39 => true,
+ 0xb3d => true,
+ 0xb5c...0xb5d => true,
+ 0xb5f...0xb61 => true,
+ 0xb71 => true,
+ 0xb83 => true,
+ 0xb85...0xb8a => true,
+ 0xb8e...0xb90 => true,
+ 0xb92...0xb95 => true,
+ 0xb99...0xb9a => true,
+ 0xb9c => true,
+ 0xb9e...0xb9f => true,
+ 0xba3...0xba4 => true,
+ 0xba8...0xbaa => true,
+ 0xbae...0xbb9 => true,
+ 0xbd0 => true,
+ 0xc05...0xc0c => true,
+ 0xc0e...0xc10 => true,
+ 0xc12...0xc28 => true,
+ 0xc2a...0xc39 => true,
+ 0xc3d => true,
+ 0xc58...0xc5a => true,
+ 0xc5d => true,
+ 0xc60...0xc61 => true,
+ 0xc80 => true,
+ 0xc85...0xc8c => true,
+ 0xc8e...0xc90 => true,
+ 0xc92...0xca8 => true,
+ 0xcaa...0xcb3 => true,
+ 0xcb5...0xcb9 => true,
+ 0xcbd => true,
+ 0xcdd...0xcde => true,
+ 0xce0...0xce1 => true,
+ 0xcf1...0xcf2 => true,
+ 0xd04...0xd0c => true,
+ 0xd0e...0xd10 => true,
+ 0xd12...0xd3a => true,
+ 0xd3d => true,
+ 0xd4e => true,
+ 0xd54...0xd56 => true,
+ 0xd5f...0xd61 => true,
+ 0xd7a...0xd7f => true,
+ 0xd85...0xd96 => true,
+ 0xd9a...0xdb1 => true,
+ 0xdb3...0xdbb => true,
+ 0xdbd => true,
+ 0xdc0...0xdc6 => true,
+ 0xe01...0xe30 => true,
+ 0xe32...0xe33 => true,
+ 0xe40...0xe45 => true,
+ 0xe46 => true,
+ 0xe81...0xe82 => true,
+ 0xe84 => true,
+ 0xe86...0xe8a => true,
+ 0xe8c...0xea3 => true,
+ 0xea5 => true,
+ 0xea7...0xeb0 => true,
+ 0xeb2...0xeb3 => true,
+ 0xebd => true,
+ 0xec0...0xec4 => true,
+ 0xec6 => true,
+ 0xedc...0xedf => true,
+ 0xf00 => true,
+ 0xf40...0xf47 => true,
+ 0xf49...0xf6c => true,
+ 0xf88...0xf8c => true,
+ 0x1000...0x102a => true,
+ 0x103f => true,
+ 0x1050...0x1055 => true,
+ 0x105a...0x105d => true,
+ 0x1061 => true,
+ 0x1065...0x1066 => true,
+ 0x106e...0x1070 => true,
+ 0x1075...0x1081 => true,
+ 0x108e => true,
+ 0x10d0...0x10fa => true,
+ 0x10fd...0x10ff => true,
+ 0x1100...0x1248 => true,
+ 0x124a...0x124d => true,
+ 0x1250...0x1256 => true,
+ 0x1258 => true,
+ 0x125a...0x125d => true,
+ 0x1260...0x1288 => true,
+ 0x128a...0x128d => true,
+ 0x1290...0x12b0 => true,
+ 0x12b2...0x12b5 => true,
+ 0x12b8...0x12be => true,
+ 0x12c0 => true,
+ 0x12c2...0x12c5 => true,
+ 0x12c8...0x12d6 => true,
+ 0x12d8...0x1310 => true,
+ 0x1312...0x1315 => true,
+ 0x1318...0x135a => true,
+ 0x1380...0x138f => true,
+ 0x1401...0x166c => true,
+ 0x166f...0x167f => true,
+ 0x1681...0x169a => true,
+ 0x16a0...0x16ea => true,
+ 0x16ee...0x16f0 => true,
+ 0x16f1...0x16f8 => true,
+ 0x1700...0x1711 => true,
+ 0x171f...0x1731 => true,
+ 0x1740...0x1751 => true,
+ 0x1760...0x176c => true,
+ 0x176e...0x1770 => true,
+ 0x1780...0x17b3 => true,
+ 0x17d7 => true,
+ 0x17dc => true,
+ 0x1820...0x1842 => true,
+ 0x1843 => true,
+ 0x1844...0x1878 => true,
+ 0x1880...0x1884 => true,
+ 0x1887...0x18a8 => true,
+ 0x18aa => true,
+ 0x18b0...0x18f5 => true,
+ 0x1900...0x191e => true,
+ 0x1950...0x196d => true,
+ 0x1970...0x1974 => true,
+ 0x1980...0x19ab => true,
+ 0x19b0...0x19c9 => true,
+ 0x1a00...0x1a16 => true,
+ 0x1a20...0x1a54 => true,
+ 0x1aa7 => true,
+ 0x1b05...0x1b33 => true,
+ 0x1b45...0x1b4c => true,
+ 0x1b83...0x1ba0 => true,
+ 0x1bae...0x1baf => true,
+ 0x1bba...0x1be5 => true,
+ 0x1c00...0x1c23 => true,
+ 0x1c4d...0x1c4f => true,
+ 0x1c5a...0x1c77 => true,
+ 0x1c78...0x1c7d => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1ce9...0x1cec => true,
+ 0x1cee...0x1cf3 => true,
+ 0x1cf5...0x1cf6 => true,
+ 0x1cfa => true,
+ 0x2135...0x2138 => true,
+ 0x2180...0x2182 => true,
+ 0x2185...0x2188 => true,
+ 0x2d30...0x2d67 => true,
+ 0x2d6f => true,
+ 0x2d80...0x2d96 => true,
+ 0x2da0...0x2da6 => true,
+ 0x2da8...0x2dae => true,
+ 0x2db0...0x2db6 => true,
+ 0x2db8...0x2dbe => true,
+ 0x2dc0...0x2dc6 => true,
+ 0x2dc8...0x2dce => true,
+ 0x2dd0...0x2dd6 => true,
+ 0x2dd8...0x2dde => true,
+ 0x2e2f => true,
+ 0x3005 => true,
+ 0x3006 => true,
+ 0x3007 => true,
+ 0x3021...0x3029 => true,
+ 0x3031...0x3035 => true,
+ 0x3038...0x303a => true,
+ 0x303b => true,
+ 0x303c => true,
+ 0x3041...0x3096 => true,
+ 0x309d...0x309e => true,
+ 0x309f => true,
+ 0x30a1...0x30fa => true,
+ 0x30fc...0x30fe => true,
+ 0x30ff => true,
+ 0x3105...0x312f => true,
+ 0x3131...0x318e => true,
+ 0x31a0...0x31bf => true,
+ 0x31f0...0x31ff => true,
+ 0x3400...0x4dbf => true,
+ 0x4e00...0xa014 => true,
+ 0xa015 => true,
+ 0xa016...0xa48c => true,
+ 0xa4d0...0xa4f7 => true,
+ 0xa4f8...0xa4fd => true,
+ 0xa500...0xa60b => true,
+ 0xa60c => true,
+ 0xa610...0xa61f => true,
+ 0xa62a...0xa62b => true,
+ 0xa66e => true,
+ 0xa67f => true,
+ 0xa6a0...0xa6e5 => true,
+ 0xa6e6...0xa6ef => true,
+ 0xa717...0xa71f => true,
+ 0xa788 => true,
+ 0xa78f => true,
+ 0xa7f7 => true,
+ 0xa7fb...0xa801 => true,
+ 0xa803...0xa805 => true,
+ 0xa807...0xa80a => true,
+ 0xa80c...0xa822 => true,
+ 0xa840...0xa873 => true,
+ 0xa882...0xa8b3 => true,
+ 0xa8f2...0xa8f7 => true,
+ 0xa8fb => true,
+ 0xa8fd...0xa8fe => true,
+ 0xa90a...0xa925 => true,
+ 0xa930...0xa946 => true,
+ 0xa960...0xa97c => true,
+ 0xa984...0xa9b2 => true,
+ 0xa9cf => true,
+ 0xa9e0...0xa9e4 => true,
+ 0xa9e6 => true,
+ 0xa9e7...0xa9ef => true,
+ 0xa9fa...0xa9fe => true,
+ 0xaa00...0xaa28 => true,
+ 0xaa40...0xaa42 => true,
+ 0xaa44...0xaa4b => true,
+ 0xaa60...0xaa6f => true,
+ 0xaa70 => true,
+ 0xaa71...0xaa76 => true,
+ 0xaa7a => true,
+ 0xaa7e...0xaaaf => true,
+ 0xaab1 => true,
+ 0xaab5...0xaab6 => true,
+ 0xaab9...0xaabd => true,
+ 0xaac0 => true,
+ 0xaac2 => true,
+ 0xaadb...0xaadc => true,
+ 0xaadd => true,
+ 0xaae0...0xaaea => true,
+ 0xaaf2 => true,
+ 0xaaf3...0xaaf4 => true,
+ 0xab01...0xab06 => true,
+ 0xab09...0xab0e => true,
+ 0xab11...0xab16 => true,
+ 0xab20...0xab26 => true,
+ 0xab28...0xab2e => true,
+ 0xabc0...0xabe2 => true,
+ 0xac00...0xd7a3 => true,
+ 0xd7b0...0xd7c6 => true,
+ 0xd7cb...0xd7fb => true,
+ 0xf900...0xfa6d => true,
+ 0xfa70...0xfad9 => true,
+ 0xfb1d => true,
+ 0xfb1f...0xfb28 => true,
+ 0xfb2a...0xfb36 => true,
+ 0xfb38...0xfb3c => true,
+ 0xfb3e => true,
+ 0xfb40...0xfb41 => true,
+ 0xfb43...0xfb44 => true,
+ 0xfb46...0xfbb1 => true,
+ 0xfbd3...0xfd3d => true,
+ 0xfd50...0xfd8f => true,
+ 0xfd92...0xfdc7 => true,
+ 0xfdf0...0xfdfb => true,
+ 0xfe70...0xfe74 => true,
+ 0xfe76...0xfefc => true,
+ 0xff66...0xff6f => true,
+ 0xff70 => true,
+ 0xff71...0xff9d => true,
+ 0xffa0...0xffbe => true,
+ 0xffc2...0xffc7 => true,
+ 0xffca...0xffcf => true,
+ 0xffd2...0xffd7 => true,
+ 0xffda...0xffdc => true,
+ 0x10000...0x1000b => true,
+ 0x1000d...0x10026 => true,
+ 0x10028...0x1003a => true,
+ 0x1003c...0x1003d => true,
+ 0x1003f...0x1004d => true,
+ 0x10050...0x1005d => true,
+ 0x10080...0x100fa => true,
+ 0x10140...0x10174 => true,
+ 0x10280...0x1029c => true,
+ 0x102a0...0x102d0 => true,
+ 0x10300...0x1031f => true,
+ 0x1032d...0x10340 => true,
+ 0x10341 => true,
+ 0x10342...0x10349 => true,
+ 0x1034a => true,
+ 0x10350...0x10375 => true,
+ 0x10380...0x1039d => true,
+ 0x103a0...0x103c3 => true,
+ 0x103c8...0x103cf => true,
+ 0x103d1...0x103d5 => true,
+ 0x10450...0x1049d => true,
+ 0x10500...0x10527 => true,
+ 0x10530...0x10563 => true,
+ 0x10600...0x10736 => true,
+ 0x10740...0x10755 => true,
+ 0x10760...0x10767 => true,
+ 0x10781...0x10782 => true,
+ 0x10800...0x10805 => true,
+ 0x10808 => true,
+ 0x1080a...0x10835 => true,
+ 0x10837...0x10838 => true,
+ 0x1083c => true,
+ 0x1083f...0x10855 => true,
+ 0x10860...0x10876 => true,
+ 0x10880...0x1089e => true,
+ 0x108e0...0x108f2 => true,
+ 0x108f4...0x108f5 => true,
+ 0x10900...0x10915 => true,
+ 0x10920...0x10939 => true,
+ 0x10980...0x109b7 => true,
+ 0x109be...0x109bf => true,
+ 0x10a00 => true,
+ 0x10a10...0x10a13 => true,
+ 0x10a15...0x10a17 => true,
+ 0x10a19...0x10a35 => true,
+ 0x10a60...0x10a7c => true,
+ 0x10a80...0x10a9c => true,
+ 0x10ac0...0x10ac7 => true,
+ 0x10ac9...0x10ae4 => true,
+ 0x10b00...0x10b35 => true,
+ 0x10b40...0x10b55 => true,
+ 0x10b60...0x10b72 => true,
+ 0x10b80...0x10b91 => true,
+ 0x10c00...0x10c48 => true,
+ 0x10d00...0x10d23 => true,
+ 0x10e80...0x10ea9 => true,
+ 0x10eb0...0x10eb1 => true,
+ 0x10f00...0x10f1c => true,
+ 0x10f27 => true,
+ 0x10f30...0x10f45 => true,
+ 0x10f70...0x10f81 => true,
+ 0x10fb0...0x10fc4 => true,
+ 0x10fe0...0x10ff6 => true,
+ 0x11003...0x11037 => true,
+ 0x11071...0x11072 => true,
+ 0x11075 => true,
+ 0x11083...0x110af => true,
+ 0x110d0...0x110e8 => true,
+ 0x11103...0x11126 => true,
+ 0x11144 => true,
+ 0x11147 => true,
+ 0x11150...0x11172 => true,
+ 0x11176 => true,
+ 0x11183...0x111b2 => true,
+ 0x111c1...0x111c4 => true,
+ 0x111da => true,
+ 0x111dc => true,
+ 0x11200...0x11211 => true,
+ 0x11213...0x1122b => true,
+ 0x1123f...0x11240 => true,
+ 0x11280...0x11286 => true,
+ 0x11288 => true,
+ 0x1128a...0x1128d => true,
+ 0x1128f...0x1129d => true,
+ 0x1129f...0x112a8 => true,
+ 0x112b0...0x112de => true,
+ 0x11305...0x1130c => true,
+ 0x1130f...0x11310 => true,
+ 0x11313...0x11328 => true,
+ 0x1132a...0x11330 => true,
+ 0x11332...0x11333 => true,
+ 0x11335...0x11339 => true,
+ 0x1133d => true,
+ 0x11350 => true,
+ 0x1135d...0x11361 => true,
+ 0x11400...0x11434 => true,
+ 0x11447...0x1144a => true,
+ 0x1145f...0x11461 => true,
+ 0x11480...0x114af => true,
+ 0x114c4...0x114c5 => true,
+ 0x114c7 => true,
+ 0x11580...0x115ae => true,
+ 0x115d8...0x115db => true,
+ 0x11600...0x1162f => true,
+ 0x11644 => true,
+ 0x11680...0x116aa => true,
+ 0x116b8 => true,
+ 0x11700...0x1171a => true,
+ 0x11740...0x11746 => true,
+ 0x11800...0x1182b => true,
+ 0x118ff...0x11906 => true,
+ 0x11909 => true,
+ 0x1190c...0x11913 => true,
+ 0x11915...0x11916 => true,
+ 0x11918...0x1192f => true,
+ 0x1193f => true,
+ 0x11941 => true,
+ 0x119a0...0x119a7 => true,
+ 0x119aa...0x119d0 => true,
+ 0x119e1 => true,
+ 0x119e3 => true,
+ 0x11a00 => true,
+ 0x11a0b...0x11a32 => true,
+ 0x11a3a => true,
+ 0x11a50 => true,
+ 0x11a5c...0x11a89 => true,
+ 0x11a9d => true,
+ 0x11ab0...0x11af8 => true,
+ 0x11c00...0x11c08 => true,
+ 0x11c0a...0x11c2e => true,
+ 0x11c40 => true,
+ 0x11c72...0x11c8f => true,
+ 0x11d00...0x11d06 => true,
+ 0x11d08...0x11d09 => true,
+ 0x11d0b...0x11d30 => true,
+ 0x11d46 => true,
+ 0x11d60...0x11d65 => true,
+ 0x11d67...0x11d68 => true,
+ 0x11d6a...0x11d89 => true,
+ 0x11d98 => true,
+ 0x11ee0...0x11ef2 => true,
+ 0x11f02 => true,
+ 0x11f04...0x11f10 => true,
+ 0x11f12...0x11f33 => true,
+ 0x11fb0 => true,
+ 0x12000...0x12399 => true,
+ 0x12400...0x1246e => true,
+ 0x12480...0x12543 => true,
+ 0x12f90...0x12ff0 => true,
+ 0x13000...0x1342f => true,
+ 0x13441...0x13446 => true,
+ 0x14400...0x14646 => true,
+ 0x16800...0x16a38 => true,
+ 0x16a40...0x16a5e => true,
+ 0x16a70...0x16abe => true,
+ 0x16ad0...0x16aed => true,
+ 0x16b00...0x16b2f => true,
+ 0x16b40...0x16b43 => true,
+ 0x16b63...0x16b77 => true,
+ 0x16b7d...0x16b8f => true,
+ 0x16f00...0x16f4a => true,
+ 0x16f50 => true,
+ 0x16f93...0x16f9f => true,
+ 0x16fe0...0x16fe1 => true,
+ 0x16fe3 => true,
+ 0x17000...0x187f7 => true,
+ 0x18800...0x18cd5 => true,
+ 0x18d00...0x18d08 => true,
+ 0x1aff0...0x1aff3 => true,
+ 0x1aff5...0x1affb => true,
+ 0x1affd...0x1affe => true,
+ 0x1b000...0x1b122 => true,
+ 0x1b132 => true,
+ 0x1b150...0x1b152 => true,
+ 0x1b155 => true,
+ 0x1b164...0x1b167 => true,
+ 0x1b170...0x1b2fb => true,
+ 0x1bc00...0x1bc6a => true,
+ 0x1bc70...0x1bc7c => true,
+ 0x1bc80...0x1bc88 => true,
+ 0x1bc90...0x1bc99 => true,
+ 0x1df0a => true,
+ 0x1e100...0x1e12c => true,
+ 0x1e137...0x1e13d => true,
+ 0x1e14e => true,
+ 0x1e290...0x1e2ad => true,
+ 0x1e2c0...0x1e2eb => true,
+ 0x1e4d0...0x1e4ea => true,
+ 0x1e4eb => true,
+ 0x1e7e0...0x1e7e6 => true,
+ 0x1e7e8...0x1e7eb => true,
+ 0x1e7ed...0x1e7ee => true,
+ 0x1e7f0...0x1e7fe => true,
+ 0x1e800...0x1e8c4 => true,
+ 0x1e94b => true,
+ 0x1ee00...0x1ee03 => true,
+ 0x1ee05...0x1ee1f => true,
+ 0x1ee21...0x1ee22 => true,
+ 0x1ee24 => true,
+ 0x1ee27 => true,
+ 0x1ee29...0x1ee32 => true,
+ 0x1ee34...0x1ee37 => true,
+ 0x1ee39 => true,
+ 0x1ee3b => true,
+ 0x1ee42 => true,
+ 0x1ee47 => true,
+ 0x1ee49 => true,
+ 0x1ee4b => true,
+ 0x1ee4d...0x1ee4f => true,
+ 0x1ee51...0x1ee52 => true,
+ 0x1ee54 => true,
+ 0x1ee57 => true,
+ 0x1ee59 => true,
+ 0x1ee5b => true,
+ 0x1ee5d => true,
+ 0x1ee5f => true,
+ 0x1ee61...0x1ee62 => true,
+ 0x1ee64 => true,
+ 0x1ee67...0x1ee6a => true,
+ 0x1ee6c...0x1ee72 => true,
+ 0x1ee74...0x1ee77 => true,
+ 0x1ee79...0x1ee7c => true,
+ 0x1ee7e => true,
+ 0x1ee80...0x1ee89 => true,
+ 0x1ee8b...0x1ee9b => true,
+ 0x1eea1...0x1eea3 => true,
+ 0x1eea5...0x1eea9 => true,
+ 0x1eeab...0x1eebb => true,
+ 0x20000...0x2a6df => true,
+ 0x2a700...0x2b739 => true,
+ 0x2b740...0x2b81d => true,
+ 0x2b820...0x2cea1 => true,
+ 0x2ceb0...0x2ebe0 => true,
+ 0x2f800...0x2fa1d => true,
+ 0x30000...0x3134a => true,
+ 0x31350...0x323af => true,
+ else => false,
+ };
+}
+
+pub fn isNumeric(cp: u21) bool {
+ if (cp < 0x30 or cp > 0x1fbf9) return false;
+
+ return switch (cp) {
+ 0x30...0x39 => true,
+ 0x660...0x669 => true,
+ 0x66b...0x66c => true,
+ 0x6f0...0x6f9 => true,
+ 0x7c0...0x7c9 => true,
+ 0x966...0x96f => true,
+ 0x9e6...0x9ef => true,
+ 0xa66...0xa6f => true,
+ 0xae6...0xaef => true,
+ 0xb66...0xb6f => true,
+ 0xbe6...0xbef => true,
+ 0xc66...0xc6f => true,
+ 0xce6...0xcef => true,
+ 0xd66...0xd6f => true,
+ 0xde6...0xdef => true,
+ 0xe50...0xe59 => true,
+ 0xed0...0xed9 => true,
+ 0xf20...0xf29 => true,
+ 0x1040...0x1049 => true,
+ 0x1090...0x1099 => true,
+ 0x17e0...0x17e9 => true,
+ 0x1810...0x1819 => true,
+ 0x1946...0x194f => true,
+ 0x19d0...0x19d9 => true,
+ 0x1a80...0x1a89 => true,
+ 0x1a90...0x1a99 => true,
+ 0x1b50...0x1b59 => true,
+ 0x1bb0...0x1bb9 => true,
+ 0x1c40...0x1c49 => true,
+ 0x1c50...0x1c59 => true,
+ 0xa620...0xa629 => true,
+ 0xa8d0...0xa8d9 => true,
+ 0xa900...0xa909 => true,
+ 0xa9d0...0xa9d9 => true,
+ 0xa9f0...0xa9f9 => true,
+ 0xaa50...0xaa59 => true,
+ 0xabf0...0xabf9 => true,
+ 0xff10...0xff19 => true,
+ 0x104a0...0x104a9 => true,
+ 0x10d30...0x10d39 => true,
+ 0x11066...0x1106f => true,
+ 0x110f0...0x110f9 => true,
+ 0x11136...0x1113f => true,
+ 0x111d0...0x111d9 => true,
+ 0x112f0...0x112f9 => true,
+ 0x11450...0x11459 => true,
+ 0x114d0...0x114d9 => true,
+ 0x11650...0x11659 => true,
+ 0x116c0...0x116c9 => true,
+ 0x11730...0x11739 => true,
+ 0x118e0...0x118e9 => true,
+ 0x11950...0x11959 => true,
+ 0x11c50...0x11c59 => true,
+ 0x11d50...0x11d59 => true,
+ 0x11da0...0x11da9 => true,
+ 0x11f50...0x11f59 => true,
+ 0x16a60...0x16a69 => true,
+ 0x16ac0...0x16ac9 => true,
+ 0x16b50...0x16b59 => true,
+ 0x1d7ce...0x1d7ff => true,
+ 0x1e140...0x1e149 => true,
+ 0x1e2f0...0x1e2f9 => true,
+ 0x1e4f0...0x1e4f9 => true,
+ 0x1e950...0x1e959 => true,
+ 0x1fbf0...0x1fbf9 => true,
+ else => false,
+ };
+}
+
+pub fn isAterm(cp: u21) bool {
+ if (cp < 0x2e or cp > 0xff0e) return false;
+
+ return switch (cp) {
+ 0x2e => true,
+ 0x2024 => true,
+ 0xfe52 => true,
+ 0xff0e => true,
+ else => false,
+ };
+}
+
+pub fn isSterm(cp: u21) bool {
+ if (cp < 0x21 or cp > 0x1da88) return false;
+
+ return switch (cp) {
+ 0x21 => true,
+ 0x3f => true,
+ 0x589 => true,
+ 0x61d...0x61f => true,
+ 0x6d4 => true,
+ 0x700...0x702 => true,
+ 0x7f9 => true,
+ 0x837 => true,
+ 0x839 => true,
+ 0x83d...0x83e => true,
+ 0x964...0x965 => true,
+ 0x104a...0x104b => true,
+ 0x1362 => true,
+ 0x1367...0x1368 => true,
+ 0x166e => true,
+ 0x1735...0x1736 => true,
+ 0x1803 => true,
+ 0x1809 => true,
+ 0x1944...0x1945 => true,
+ 0x1aa8...0x1aab => true,
+ 0x1b5a...0x1b5b => true,
+ 0x1b5e...0x1b5f => true,
+ 0x1b7d...0x1b7e => true,
+ 0x1c3b...0x1c3c => true,
+ 0x1c7e...0x1c7f => true,
+ 0x203c...0x203d => true,
+ 0x2047...0x2049 => true,
+ 0x2e2e => true,
+ 0x2e3c => true,
+ 0x2e53...0x2e54 => true,
+ 0x3002 => true,
+ 0xa4ff => true,
+ 0xa60e...0xa60f => true,
+ 0xa6f3 => true,
+ 0xa6f7 => true,
+ 0xa876...0xa877 => true,
+ 0xa8ce...0xa8cf => true,
+ 0xa92f => true,
+ 0xa9c8...0xa9c9 => true,
+ 0xaa5d...0xaa5f => true,
+ 0xaaf0...0xaaf1 => true,
+ 0xabeb => true,
+ 0xfe56...0xfe57 => true,
+ 0xff01 => true,
+ 0xff1f => true,
+ 0xff61 => true,
+ 0x10a56...0x10a57 => true,
+ 0x10f55...0x10f59 => true,
+ 0x10f86...0x10f89 => true,
+ 0x11047...0x11048 => true,
+ 0x110be...0x110c1 => true,
+ 0x11141...0x11143 => true,
+ 0x111c5...0x111c6 => true,
+ 0x111cd => true,
+ 0x111de...0x111df => true,
+ 0x11238...0x11239 => true,
+ 0x1123b...0x1123c => true,
+ 0x112a9 => true,
+ 0x1144b...0x1144c => true,
+ 0x115c2...0x115c3 => true,
+ 0x115c9...0x115d7 => true,
+ 0x11641...0x11642 => true,
+ 0x1173c...0x1173e => true,
+ 0x11944 => true,
+ 0x11946 => true,
+ 0x11a42...0x11a43 => true,
+ 0x11a9b...0x11a9c => true,
+ 0x11c41...0x11c42 => true,
+ 0x11ef7...0x11ef8 => true,
+ 0x11f43...0x11f44 => true,
+ 0x16a6e...0x16a6f => true,
+ 0x16af5 => true,
+ 0x16b37...0x16b38 => true,
+ 0x16b44 => true,
+ 0x16e98 => true,
+ 0x1bc9f => true,
+ 0x1da88 => true,
+ else => false,
+ };
+}
+
+pub fn isClose(cp: u21) bool {
+ if (cp < 0x22 or cp > 0x1f678) return false;
+
+ return switch (cp) {
+ 0x22 => true,
+ 0x27 => true,
+ 0x28 => true,
+ 0x29 => true,
+ 0x5b => true,
+ 0x5d => true,
+ 0x7b => true,
+ 0x7d => true,
+ 0xab => true,
+ 0xbb => true,
+ 0xf3a => true,
+ 0xf3b => true,
+ 0xf3c => true,
+ 0xf3d => true,
+ 0x169b => true,
+ 0x169c => true,
+ 0x2018 => true,
+ 0x2019 => true,
+ 0x201a => true,
+ 0x201b...0x201c => true,
+ 0x201d => true,
+ 0x201e => true,
+ 0x201f => true,
+ 0x2039 => true,
+ 0x203a => true,
+ 0x2045 => true,
+ 0x2046 => true,
+ 0x207d => true,
+ 0x207e => true,
+ 0x208d => true,
+ 0x208e => true,
+ 0x2308 => true,
+ 0x2309 => true,
+ 0x230a => true,
+ 0x230b => true,
+ 0x2329 => true,
+ 0x232a => true,
+ 0x275b...0x2760 => true,
+ 0x2768 => true,
+ 0x2769 => true,
+ 0x276a => true,
+ 0x276b => true,
+ 0x276c => true,
+ 0x276d => true,
+ 0x276e => true,
+ 0x276f => true,
+ 0x2770 => true,
+ 0x2771 => true,
+ 0x2772 => true,
+ 0x2773 => true,
+ 0x2774 => true,
+ 0x2775 => true,
+ 0x27c5 => true,
+ 0x27c6 => true,
+ 0x27e6 => true,
+ 0x27e7 => true,
+ 0x27e8 => true,
+ 0x27e9 => true,
+ 0x27ea => true,
+ 0x27eb => true,
+ 0x27ec => true,
+ 0x27ed => true,
+ 0x27ee => true,
+ 0x27ef => true,
+ 0x2983 => true,
+ 0x2984 => true,
+ 0x2985 => true,
+ 0x2986 => true,
+ 0x2987 => true,
+ 0x2988 => true,
+ 0x2989 => true,
+ 0x298a => true,
+ 0x298b => true,
+ 0x298c => true,
+ 0x298d => true,
+ 0x298e => true,
+ 0x298f => true,
+ 0x2990 => true,
+ 0x2991 => true,
+ 0x2992 => true,
+ 0x2993 => true,
+ 0x2994 => true,
+ 0x2995 => true,
+ 0x2996 => true,
+ 0x2997 => true,
+ 0x2998 => true,
+ 0x29d8 => true,
+ 0x29d9 => true,
+ 0x29da => true,
+ 0x29db => true,
+ 0x29fc => true,
+ 0x29fd => true,
+ 0x2e00...0x2e01 => true,
+ 0x2e02 => true,
+ 0x2e03 => true,
+ 0x2e04 => true,
+ 0x2e05 => true,
+ 0x2e06...0x2e08 => true,
+ 0x2e09 => true,
+ 0x2e0a => true,
+ 0x2e0b => true,
+ 0x2e0c => true,
+ 0x2e0d => true,
+ 0x2e1c => true,
+ 0x2e1d => true,
+ 0x2e20 => true,
+ 0x2e21 => true,
+ 0x2e22 => true,
+ 0x2e23 => true,
+ 0x2e24 => true,
+ 0x2e25 => true,
+ 0x2e26 => true,
+ 0x2e27 => true,
+ 0x2e28 => true,
+ 0x2e29 => true,
+ 0x2e42 => true,
+ 0x2e55 => true,
+ 0x2e56 => true,
+ 0x2e57 => true,
+ 0x2e58 => true,
+ 0x2e59 => true,
+ 0x2e5a => true,
+ 0x2e5b => true,
+ 0x2e5c => true,
+ 0x3008 => true,
+ 0x3009 => true,
+ 0x300a => true,
+ 0x300b => true,
+ 0x300c => true,
+ 0x300d => true,
+ 0x300e => true,
+ 0x300f => true,
+ 0x3010 => true,
+ 0x3011 => true,
+ 0x3014 => true,
+ 0x3015 => true,
+ 0x3016 => true,
+ 0x3017 => true,
+ 0x3018 => true,
+ 0x3019 => true,
+ 0x301a => true,
+ 0x301b => true,
+ 0x301d => true,
+ 0x301e...0x301f => true,
+ 0xfd3e => true,
+ 0xfd3f => true,
+ 0xfe17 => true,
+ 0xfe18 => true,
+ 0xfe35 => true,
+ 0xfe36 => true,
+ 0xfe37 => true,
+ 0xfe38 => true,
+ 0xfe39 => true,
+ 0xfe3a => true,
+ 0xfe3b => true,
+ 0xfe3c => true,
+ 0xfe3d => true,
+ 0xfe3e => true,
+ 0xfe3f => true,
+ 0xfe40 => true,
+ 0xfe41 => true,
+ 0xfe42 => true,
+ 0xfe43 => true,
+ 0xfe44 => true,
+ 0xfe47 => true,
+ 0xfe48 => true,
+ 0xfe59 => true,
+ 0xfe5a => true,
+ 0xfe5b => true,
+ 0xfe5c => true,
+ 0xfe5d => true,
+ 0xfe5e => true,
+ 0xff08 => true,
+ 0xff09 => true,
+ 0xff3b => true,
+ 0xff3d => true,
+ 0xff5b => true,
+ 0xff5d => true,
+ 0xff5f => true,
+ 0xff60 => true,
+ 0xff62 => true,
+ 0xff63 => true,
+ 0x1f676...0x1f678 => true,
+ else => false,
+ };
+}
+
+pub fn isScontinue(cp: u21) bool {
+ if (cp < 0x2c or cp > 0xff64) return false;
+
+ return switch (cp) {
+ 0x2c => true,
+ 0x2d => true,
+ 0x3a => true,
+ 0x55d => true,
+ 0x60c...0x60d => true,
+ 0x7f8 => true,
+ 0x1802 => true,
+ 0x1808 => true,
+ 0x2013...0x2014 => true,
+ 0x3001 => true,
+ 0xfe10...0xfe11 => true,
+ 0xfe13 => true,
+ 0xfe31...0xfe32 => true,
+ 0xfe50...0xfe51 => true,
+ 0xfe55 => true,
+ 0xfe58 => true,
+ 0xfe63 => true,
+ 0xff0c => true,
+ 0xff0d => true,
+ 0xff1a => true,
+ 0xff64 => true,
+ else => false,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/title_map.zig.html b/docs/src/ziglyph/autogen/title_map.zig.html
new file mode 100644
index 0000000..8d5ebd4
--- /dev/null
+++ b/docs/src/ziglyph/autogen/title_map.zig.html
@@ -0,0 +1,1579 @@
+
+
+
+
+
autogen/title_map.zig - source view
+
+
+
+
+
+
+
+
+pub fn toTitle(cp: u21) u21 {
+ return switch (cp) {
+ 0x61 => 0x41,
+ 0x62 => 0x42,
+ 0x63 => 0x43,
+ 0x64 => 0x44,
+ 0x65 => 0x45,
+ 0x66 => 0x46,
+ 0x67 => 0x47,
+ 0x68 => 0x48,
+ 0x69 => 0x49,
+ 0x6A => 0x4A,
+ 0x6B => 0x4B,
+ 0x6C => 0x4C,
+ 0x6D => 0x4D,
+ 0x6E => 0x4E,
+ 0x6F => 0x4F,
+ 0x70 => 0x50,
+ 0x71 => 0x51,
+ 0x72 => 0x52,
+ 0x73 => 0x53,
+ 0x74 => 0x54,
+ 0x75 => 0x55,
+ 0x76 => 0x56,
+ 0x77 => 0x57,
+ 0x78 => 0x58,
+ 0x79 => 0x59,
+ 0x7A => 0x5A,
+ 0xB5 => 0x39C,
+ 0xE0 => 0xC0,
+ 0xE1 => 0xC1,
+ 0xE2 => 0xC2,
+ 0xE3 => 0xC3,
+ 0xE4 => 0xC4,
+ 0xE5 => 0xC5,
+ 0xE6 => 0xC6,
+ 0xE7 => 0xC7,
+ 0xE8 => 0xC8,
+ 0xE9 => 0xC9,
+ 0xEA => 0xCA,
+ 0xEB => 0xCB,
+ 0xEC => 0xCC,
+ 0xED => 0xCD,
+ 0xEE => 0xCE,
+ 0xEF => 0xCF,
+ 0xF0 => 0xD0,
+ 0xF1 => 0xD1,
+ 0xF2 => 0xD2,
+ 0xF3 => 0xD3,
+ 0xF4 => 0xD4,
+ 0xF5 => 0xD5,
+ 0xF6 => 0xD6,
+ 0xF8 => 0xD8,
+ 0xF9 => 0xD9,
+ 0xFA => 0xDA,
+ 0xFB => 0xDB,
+ 0xFC => 0xDC,
+ 0xFD => 0xDD,
+ 0xFE => 0xDE,
+ 0xFF => 0x178,
+ 0x101 => 0x100,
+ 0x103 => 0x102,
+ 0x105 => 0x104,
+ 0x107 => 0x106,
+ 0x109 => 0x108,
+ 0x10B => 0x10A,
+ 0x10D => 0x10C,
+ 0x10F => 0x10E,
+ 0x111 => 0x110,
+ 0x113 => 0x112,
+ 0x115 => 0x114,
+ 0x117 => 0x116,
+ 0x119 => 0x118,
+ 0x11B => 0x11A,
+ 0x11D => 0x11C,
+ 0x11F => 0x11E,
+ 0x121 => 0x120,
+ 0x123 => 0x122,
+ 0x125 => 0x124,
+ 0x127 => 0x126,
+ 0x129 => 0x128,
+ 0x12B => 0x12A,
+ 0x12D => 0x12C,
+ 0x12F => 0x12E,
+ 0x131 => 0x49,
+ 0x133 => 0x132,
+ 0x135 => 0x134,
+ 0x137 => 0x136,
+ 0x13A => 0x139,
+ 0x13C => 0x13B,
+ 0x13E => 0x13D,
+ 0x140 => 0x13F,
+ 0x142 => 0x141,
+ 0x144 => 0x143,
+ 0x146 => 0x145,
+ 0x148 => 0x147,
+ 0x14B => 0x14A,
+ 0x14D => 0x14C,
+ 0x14F => 0x14E,
+ 0x151 => 0x150,
+ 0x153 => 0x152,
+ 0x155 => 0x154,
+ 0x157 => 0x156,
+ 0x159 => 0x158,
+ 0x15B => 0x15A,
+ 0x15D => 0x15C,
+ 0x15F => 0x15E,
+ 0x161 => 0x160,
+ 0x163 => 0x162,
+ 0x165 => 0x164,
+ 0x167 => 0x166,
+ 0x169 => 0x168,
+ 0x16B => 0x16A,
+ 0x16D => 0x16C,
+ 0x16F => 0x16E,
+ 0x171 => 0x170,
+ 0x173 => 0x172,
+ 0x175 => 0x174,
+ 0x177 => 0x176,
+ 0x17A => 0x179,
+ 0x17C => 0x17B,
+ 0x17E => 0x17D,
+ 0x17F => 0x53,
+ 0x180 => 0x243,
+ 0x183 => 0x182,
+ 0x185 => 0x184,
+ 0x188 => 0x187,
+ 0x18C => 0x18B,
+ 0x192 => 0x191,
+ 0x195 => 0x1F6,
+ 0x199 => 0x198,
+ 0x19A => 0x23D,
+ 0x19E => 0x220,
+ 0x1A1 => 0x1A0,
+ 0x1A3 => 0x1A2,
+ 0x1A5 => 0x1A4,
+ 0x1A8 => 0x1A7,
+ 0x1AD => 0x1AC,
+ 0x1B0 => 0x1AF,
+ 0x1B4 => 0x1B3,
+ 0x1B6 => 0x1B5,
+ 0x1B9 => 0x1B8,
+ 0x1BD => 0x1BC,
+ 0x1BF => 0x1F7,
+ 0x1C4 => 0x1C5,
+ 0x1C5 => 0x1C5,
+ 0x1C6 => 0x1C5,
+ 0x1C7 => 0x1C8,
+ 0x1C8 => 0x1C8,
+ 0x1C9 => 0x1C8,
+ 0x1CA => 0x1CB,
+ 0x1CB => 0x1CB,
+ 0x1CC => 0x1CB,
+ 0x1CE => 0x1CD,
+ 0x1D0 => 0x1CF,
+ 0x1D2 => 0x1D1,
+ 0x1D4 => 0x1D3,
+ 0x1D6 => 0x1D5,
+ 0x1D8 => 0x1D7,
+ 0x1DA => 0x1D9,
+ 0x1DC => 0x1DB,
+ 0x1DD => 0x18E,
+ 0x1DF => 0x1DE,
+ 0x1E1 => 0x1E0,
+ 0x1E3 => 0x1E2,
+ 0x1E5 => 0x1E4,
+ 0x1E7 => 0x1E6,
+ 0x1E9 => 0x1E8,
+ 0x1EB => 0x1EA,
+ 0x1ED => 0x1EC,
+ 0x1EF => 0x1EE,
+ 0x1F1 => 0x1F2,
+ 0x1F2 => 0x1F2,
+ 0x1F3 => 0x1F2,
+ 0x1F5 => 0x1F4,
+ 0x1F9 => 0x1F8,
+ 0x1FB => 0x1FA,
+ 0x1FD => 0x1FC,
+ 0x1FF => 0x1FE,
+ 0x201 => 0x200,
+ 0x203 => 0x202,
+ 0x205 => 0x204,
+ 0x207 => 0x206,
+ 0x209 => 0x208,
+ 0x20B => 0x20A,
+ 0x20D => 0x20C,
+ 0x20F => 0x20E,
+ 0x211 => 0x210,
+ 0x213 => 0x212,
+ 0x215 => 0x214,
+ 0x217 => 0x216,
+ 0x219 => 0x218,
+ 0x21B => 0x21A,
+ 0x21D => 0x21C,
+ 0x21F => 0x21E,
+ 0x223 => 0x222,
+ 0x225 => 0x224,
+ 0x227 => 0x226,
+ 0x229 => 0x228,
+ 0x22B => 0x22A,
+ 0x22D => 0x22C,
+ 0x22F => 0x22E,
+ 0x231 => 0x230,
+ 0x233 => 0x232,
+ 0x23C => 0x23B,
+ 0x23F => 0x2C7E,
+ 0x240 => 0x2C7F,
+ 0x242 => 0x241,
+ 0x247 => 0x246,
+ 0x249 => 0x248,
+ 0x24B => 0x24A,
+ 0x24D => 0x24C,
+ 0x24F => 0x24E,
+ 0x250 => 0x2C6F,
+ 0x251 => 0x2C6D,
+ 0x252 => 0x2C70,
+ 0x253 => 0x181,
+ 0x254 => 0x186,
+ 0x256 => 0x189,
+ 0x257 => 0x18A,
+ 0x259 => 0x18F,
+ 0x25B => 0x190,
+ 0x25C => 0xA7AB,
+ 0x260 => 0x193,
+ 0x261 => 0xA7AC,
+ 0x263 => 0x194,
+ 0x265 => 0xA78D,
+ 0x266 => 0xA7AA,
+ 0x268 => 0x197,
+ 0x269 => 0x196,
+ 0x26A => 0xA7AE,
+ 0x26B => 0x2C62,
+ 0x26C => 0xA7AD,
+ 0x26F => 0x19C,
+ 0x271 => 0x2C6E,
+ 0x272 => 0x19D,
+ 0x275 => 0x19F,
+ 0x27D => 0x2C64,
+ 0x280 => 0x1A6,
+ 0x282 => 0xA7C5,
+ 0x283 => 0x1A9,
+ 0x287 => 0xA7B1,
+ 0x288 => 0x1AE,
+ 0x289 => 0x244,
+ 0x28A => 0x1B1,
+ 0x28B => 0x1B2,
+ 0x28C => 0x245,
+ 0x292 => 0x1B7,
+ 0x29D => 0xA7B2,
+ 0x29E => 0xA7B0,
+ 0x345 => 0x399,
+ 0x371 => 0x370,
+ 0x373 => 0x372,
+ 0x377 => 0x376,
+ 0x37B => 0x3FD,
+ 0x37C => 0x3FE,
+ 0x37D => 0x3FF,
+ 0x3AC => 0x386,
+ 0x3AD => 0x388,
+ 0x3AE => 0x389,
+ 0x3AF => 0x38A,
+ 0x3B1 => 0x391,
+ 0x3B2 => 0x392,
+ 0x3B3 => 0x393,
+ 0x3B4 => 0x394,
+ 0x3B5 => 0x395,
+ 0x3B6 => 0x396,
+ 0x3B7 => 0x397,
+ 0x3B8 => 0x398,
+ 0x3B9 => 0x399,
+ 0x3BA => 0x39A,
+ 0x3BB => 0x39B,
+ 0x3BC => 0x39C,
+ 0x3BD => 0x39D,
+ 0x3BE => 0x39E,
+ 0x3BF => 0x39F,
+ 0x3C0 => 0x3A0,
+ 0x3C1 => 0x3A1,
+ 0x3C2 => 0x3A3,
+ 0x3C3 => 0x3A3,
+ 0x3C4 => 0x3A4,
+ 0x3C5 => 0x3A5,
+ 0x3C6 => 0x3A6,
+ 0x3C7 => 0x3A7,
+ 0x3C8 => 0x3A8,
+ 0x3C9 => 0x3A9,
+ 0x3CA => 0x3AA,
+ 0x3CB => 0x3AB,
+ 0x3CC => 0x38C,
+ 0x3CD => 0x38E,
+ 0x3CE => 0x38F,
+ 0x3D0 => 0x392,
+ 0x3D1 => 0x398,
+ 0x3D5 => 0x3A6,
+ 0x3D6 => 0x3A0,
+ 0x3D7 => 0x3CF,
+ 0x3D9 => 0x3D8,
+ 0x3DB => 0x3DA,
+ 0x3DD => 0x3DC,
+ 0x3DF => 0x3DE,
+ 0x3E1 => 0x3E0,
+ 0x3E3 => 0x3E2,
+ 0x3E5 => 0x3E4,
+ 0x3E7 => 0x3E6,
+ 0x3E9 => 0x3E8,
+ 0x3EB => 0x3EA,
+ 0x3ED => 0x3EC,
+ 0x3EF => 0x3EE,
+ 0x3F0 => 0x39A,
+ 0x3F1 => 0x3A1,
+ 0x3F2 => 0x3F9,
+ 0x3F3 => 0x37F,
+ 0x3F5 => 0x395,
+ 0x3F8 => 0x3F7,
+ 0x3FB => 0x3FA,
+ 0x430 => 0x410,
+ 0x431 => 0x411,
+ 0x432 => 0x412,
+ 0x433 => 0x413,
+ 0x434 => 0x414,
+ 0x435 => 0x415,
+ 0x436 => 0x416,
+ 0x437 => 0x417,
+ 0x438 => 0x418,
+ 0x439 => 0x419,
+ 0x43A => 0x41A,
+ 0x43B => 0x41B,
+ 0x43C => 0x41C,
+ 0x43D => 0x41D,
+ 0x43E => 0x41E,
+ 0x43F => 0x41F,
+ 0x440 => 0x420,
+ 0x441 => 0x421,
+ 0x442 => 0x422,
+ 0x443 => 0x423,
+ 0x444 => 0x424,
+ 0x445 => 0x425,
+ 0x446 => 0x426,
+ 0x447 => 0x427,
+ 0x448 => 0x428,
+ 0x449 => 0x429,
+ 0x44A => 0x42A,
+ 0x44B => 0x42B,
+ 0x44C => 0x42C,
+ 0x44D => 0x42D,
+ 0x44E => 0x42E,
+ 0x44F => 0x42F,
+ 0x450 => 0x400,
+ 0x451 => 0x401,
+ 0x452 => 0x402,
+ 0x453 => 0x403,
+ 0x454 => 0x404,
+ 0x455 => 0x405,
+ 0x456 => 0x406,
+ 0x457 => 0x407,
+ 0x458 => 0x408,
+ 0x459 => 0x409,
+ 0x45A => 0x40A,
+ 0x45B => 0x40B,
+ 0x45C => 0x40C,
+ 0x45D => 0x40D,
+ 0x45E => 0x40E,
+ 0x45F => 0x40F,
+ 0x461 => 0x460,
+ 0x463 => 0x462,
+ 0x465 => 0x464,
+ 0x467 => 0x466,
+ 0x469 => 0x468,
+ 0x46B => 0x46A,
+ 0x46D => 0x46C,
+ 0x46F => 0x46E,
+ 0x471 => 0x470,
+ 0x473 => 0x472,
+ 0x475 => 0x474,
+ 0x477 => 0x476,
+ 0x479 => 0x478,
+ 0x47B => 0x47A,
+ 0x47D => 0x47C,
+ 0x47F => 0x47E,
+ 0x481 => 0x480,
+ 0x48B => 0x48A,
+ 0x48D => 0x48C,
+ 0x48F => 0x48E,
+ 0x491 => 0x490,
+ 0x493 => 0x492,
+ 0x495 => 0x494,
+ 0x497 => 0x496,
+ 0x499 => 0x498,
+ 0x49B => 0x49A,
+ 0x49D => 0x49C,
+ 0x49F => 0x49E,
+ 0x4A1 => 0x4A0,
+ 0x4A3 => 0x4A2,
+ 0x4A5 => 0x4A4,
+ 0x4A7 => 0x4A6,
+ 0x4A9 => 0x4A8,
+ 0x4AB => 0x4AA,
+ 0x4AD => 0x4AC,
+ 0x4AF => 0x4AE,
+ 0x4B1 => 0x4B0,
+ 0x4B3 => 0x4B2,
+ 0x4B5 => 0x4B4,
+ 0x4B7 => 0x4B6,
+ 0x4B9 => 0x4B8,
+ 0x4BB => 0x4BA,
+ 0x4BD => 0x4BC,
+ 0x4BF => 0x4BE,
+ 0x4C2 => 0x4C1,
+ 0x4C4 => 0x4C3,
+ 0x4C6 => 0x4C5,
+ 0x4C8 => 0x4C7,
+ 0x4CA => 0x4C9,
+ 0x4CC => 0x4CB,
+ 0x4CE => 0x4CD,
+ 0x4CF => 0x4C0,
+ 0x4D1 => 0x4D0,
+ 0x4D3 => 0x4D2,
+ 0x4D5 => 0x4D4,
+ 0x4D7 => 0x4D6,
+ 0x4D9 => 0x4D8,
+ 0x4DB => 0x4DA,
+ 0x4DD => 0x4DC,
+ 0x4DF => 0x4DE,
+ 0x4E1 => 0x4E0,
+ 0x4E3 => 0x4E2,
+ 0x4E5 => 0x4E4,
+ 0x4E7 => 0x4E6,
+ 0x4E9 => 0x4E8,
+ 0x4EB => 0x4EA,
+ 0x4ED => 0x4EC,
+ 0x4EF => 0x4EE,
+ 0x4F1 => 0x4F0,
+ 0x4F3 => 0x4F2,
+ 0x4F5 => 0x4F4,
+ 0x4F7 => 0x4F6,
+ 0x4F9 => 0x4F8,
+ 0x4FB => 0x4FA,
+ 0x4FD => 0x4FC,
+ 0x4FF => 0x4FE,
+ 0x501 => 0x500,
+ 0x503 => 0x502,
+ 0x505 => 0x504,
+ 0x507 => 0x506,
+ 0x509 => 0x508,
+ 0x50B => 0x50A,
+ 0x50D => 0x50C,
+ 0x50F => 0x50E,
+ 0x511 => 0x510,
+ 0x513 => 0x512,
+ 0x515 => 0x514,
+ 0x517 => 0x516,
+ 0x519 => 0x518,
+ 0x51B => 0x51A,
+ 0x51D => 0x51C,
+ 0x51F => 0x51E,
+ 0x521 => 0x520,
+ 0x523 => 0x522,
+ 0x525 => 0x524,
+ 0x527 => 0x526,
+ 0x529 => 0x528,
+ 0x52B => 0x52A,
+ 0x52D => 0x52C,
+ 0x52F => 0x52E,
+ 0x561 => 0x531,
+ 0x562 => 0x532,
+ 0x563 => 0x533,
+ 0x564 => 0x534,
+ 0x565 => 0x535,
+ 0x566 => 0x536,
+ 0x567 => 0x537,
+ 0x568 => 0x538,
+ 0x569 => 0x539,
+ 0x56A => 0x53A,
+ 0x56B => 0x53B,
+ 0x56C => 0x53C,
+ 0x56D => 0x53D,
+ 0x56E => 0x53E,
+ 0x56F => 0x53F,
+ 0x570 => 0x540,
+ 0x571 => 0x541,
+ 0x572 => 0x542,
+ 0x573 => 0x543,
+ 0x574 => 0x544,
+ 0x575 => 0x545,
+ 0x576 => 0x546,
+ 0x577 => 0x547,
+ 0x578 => 0x548,
+ 0x579 => 0x549,
+ 0x57A => 0x54A,
+ 0x57B => 0x54B,
+ 0x57C => 0x54C,
+ 0x57D => 0x54D,
+ 0x57E => 0x54E,
+ 0x57F => 0x54F,
+ 0x580 => 0x550,
+ 0x581 => 0x551,
+ 0x582 => 0x552,
+ 0x583 => 0x553,
+ 0x584 => 0x554,
+ 0x585 => 0x555,
+ 0x586 => 0x556,
+ 0x10D0 => 0x10D0,
+ 0x10D1 => 0x10D1,
+ 0x10D2 => 0x10D2,
+ 0x10D3 => 0x10D3,
+ 0x10D4 => 0x10D4,
+ 0x10D5 => 0x10D5,
+ 0x10D6 => 0x10D6,
+ 0x10D7 => 0x10D7,
+ 0x10D8 => 0x10D8,
+ 0x10D9 => 0x10D9,
+ 0x10DA => 0x10DA,
+ 0x10DB => 0x10DB,
+ 0x10DC => 0x10DC,
+ 0x10DD => 0x10DD,
+ 0x10DE => 0x10DE,
+ 0x10DF => 0x10DF,
+ 0x10E0 => 0x10E0,
+ 0x10E1 => 0x10E1,
+ 0x10E2 => 0x10E2,
+ 0x10E3 => 0x10E3,
+ 0x10E4 => 0x10E4,
+ 0x10E5 => 0x10E5,
+ 0x10E6 => 0x10E6,
+ 0x10E7 => 0x10E7,
+ 0x10E8 => 0x10E8,
+ 0x10E9 => 0x10E9,
+ 0x10EA => 0x10EA,
+ 0x10EB => 0x10EB,
+ 0x10EC => 0x10EC,
+ 0x10ED => 0x10ED,
+ 0x10EE => 0x10EE,
+ 0x10EF => 0x10EF,
+ 0x10F0 => 0x10F0,
+ 0x10F1 => 0x10F1,
+ 0x10F2 => 0x10F2,
+ 0x10F3 => 0x10F3,
+ 0x10F4 => 0x10F4,
+ 0x10F5 => 0x10F5,
+ 0x10F6 => 0x10F6,
+ 0x10F7 => 0x10F7,
+ 0x10F8 => 0x10F8,
+ 0x10F9 => 0x10F9,
+ 0x10FA => 0x10FA,
+ 0x10FD => 0x10FD,
+ 0x10FE => 0x10FE,
+ 0x10FF => 0x10FF,
+ 0x13F8 => 0x13F0,
+ 0x13F9 => 0x13F1,
+ 0x13FA => 0x13F2,
+ 0x13FB => 0x13F3,
+ 0x13FC => 0x13F4,
+ 0x13FD => 0x13F5,
+ 0x1C80 => 0x412,
+ 0x1C81 => 0x414,
+ 0x1C82 => 0x41E,
+ 0x1C83 => 0x421,
+ 0x1C84 => 0x422,
+ 0x1C85 => 0x422,
+ 0x1C86 => 0x42A,
+ 0x1C87 => 0x462,
+ 0x1C88 => 0xA64A,
+ 0x1D79 => 0xA77D,
+ 0x1D7D => 0x2C63,
+ 0x1D8E => 0xA7C6,
+ 0x1E01 => 0x1E00,
+ 0x1E03 => 0x1E02,
+ 0x1E05 => 0x1E04,
+ 0x1E07 => 0x1E06,
+ 0x1E09 => 0x1E08,
+ 0x1E0B => 0x1E0A,
+ 0x1E0D => 0x1E0C,
+ 0x1E0F => 0x1E0E,
+ 0x1E11 => 0x1E10,
+ 0x1E13 => 0x1E12,
+ 0x1E15 => 0x1E14,
+ 0x1E17 => 0x1E16,
+ 0x1E19 => 0x1E18,
+ 0x1E1B => 0x1E1A,
+ 0x1E1D => 0x1E1C,
+ 0x1E1F => 0x1E1E,
+ 0x1E21 => 0x1E20,
+ 0x1E23 => 0x1E22,
+ 0x1E25 => 0x1E24,
+ 0x1E27 => 0x1E26,
+ 0x1E29 => 0x1E28,
+ 0x1E2B => 0x1E2A,
+ 0x1E2D => 0x1E2C,
+ 0x1E2F => 0x1E2E,
+ 0x1E31 => 0x1E30,
+ 0x1E33 => 0x1E32,
+ 0x1E35 => 0x1E34,
+ 0x1E37 => 0x1E36,
+ 0x1E39 => 0x1E38,
+ 0x1E3B => 0x1E3A,
+ 0x1E3D => 0x1E3C,
+ 0x1E3F => 0x1E3E,
+ 0x1E41 => 0x1E40,
+ 0x1E43 => 0x1E42,
+ 0x1E45 => 0x1E44,
+ 0x1E47 => 0x1E46,
+ 0x1E49 => 0x1E48,
+ 0x1E4B => 0x1E4A,
+ 0x1E4D => 0x1E4C,
+ 0x1E4F => 0x1E4E,
+ 0x1E51 => 0x1E50,
+ 0x1E53 => 0x1E52,
+ 0x1E55 => 0x1E54,
+ 0x1E57 => 0x1E56,
+ 0x1E59 => 0x1E58,
+ 0x1E5B => 0x1E5A,
+ 0x1E5D => 0x1E5C,
+ 0x1E5F => 0x1E5E,
+ 0x1E61 => 0x1E60,
+ 0x1E63 => 0x1E62,
+ 0x1E65 => 0x1E64,
+ 0x1E67 => 0x1E66,
+ 0x1E69 => 0x1E68,
+ 0x1E6B => 0x1E6A,
+ 0x1E6D => 0x1E6C,
+ 0x1E6F => 0x1E6E,
+ 0x1E71 => 0x1E70,
+ 0x1E73 => 0x1E72,
+ 0x1E75 => 0x1E74,
+ 0x1E77 => 0x1E76,
+ 0x1E79 => 0x1E78,
+ 0x1E7B => 0x1E7A,
+ 0x1E7D => 0x1E7C,
+ 0x1E7F => 0x1E7E,
+ 0x1E81 => 0x1E80,
+ 0x1E83 => 0x1E82,
+ 0x1E85 => 0x1E84,
+ 0x1E87 => 0x1E86,
+ 0x1E89 => 0x1E88,
+ 0x1E8B => 0x1E8A,
+ 0x1E8D => 0x1E8C,
+ 0x1E8F => 0x1E8E,
+ 0x1E91 => 0x1E90,
+ 0x1E93 => 0x1E92,
+ 0x1E95 => 0x1E94,
+ 0x1E9B => 0x1E60,
+ 0x1EA1 => 0x1EA0,
+ 0x1EA3 => 0x1EA2,
+ 0x1EA5 => 0x1EA4,
+ 0x1EA7 => 0x1EA6,
+ 0x1EA9 => 0x1EA8,
+ 0x1EAB => 0x1EAA,
+ 0x1EAD => 0x1EAC,
+ 0x1EAF => 0x1EAE,
+ 0x1EB1 => 0x1EB0,
+ 0x1EB3 => 0x1EB2,
+ 0x1EB5 => 0x1EB4,
+ 0x1EB7 => 0x1EB6,
+ 0x1EB9 => 0x1EB8,
+ 0x1EBB => 0x1EBA,
+ 0x1EBD => 0x1EBC,
+ 0x1EBF => 0x1EBE,
+ 0x1EC1 => 0x1EC0,
+ 0x1EC3 => 0x1EC2,
+ 0x1EC5 => 0x1EC4,
+ 0x1EC7 => 0x1EC6,
+ 0x1EC9 => 0x1EC8,
+ 0x1ECB => 0x1ECA,
+ 0x1ECD => 0x1ECC,
+ 0x1ECF => 0x1ECE,
+ 0x1ED1 => 0x1ED0,
+ 0x1ED3 => 0x1ED2,
+ 0x1ED5 => 0x1ED4,
+ 0x1ED7 => 0x1ED6,
+ 0x1ED9 => 0x1ED8,
+ 0x1EDB => 0x1EDA,
+ 0x1EDD => 0x1EDC,
+ 0x1EDF => 0x1EDE,
+ 0x1EE1 => 0x1EE0,
+ 0x1EE3 => 0x1EE2,
+ 0x1EE5 => 0x1EE4,
+ 0x1EE7 => 0x1EE6,
+ 0x1EE9 => 0x1EE8,
+ 0x1EEB => 0x1EEA,
+ 0x1EED => 0x1EEC,
+ 0x1EEF => 0x1EEE,
+ 0x1EF1 => 0x1EF0,
+ 0x1EF3 => 0x1EF2,
+ 0x1EF5 => 0x1EF4,
+ 0x1EF7 => 0x1EF6,
+ 0x1EF9 => 0x1EF8,
+ 0x1EFB => 0x1EFA,
+ 0x1EFD => 0x1EFC,
+ 0x1EFF => 0x1EFE,
+ 0x1F00 => 0x1F08,
+ 0x1F01 => 0x1F09,
+ 0x1F02 => 0x1F0A,
+ 0x1F03 => 0x1F0B,
+ 0x1F04 => 0x1F0C,
+ 0x1F05 => 0x1F0D,
+ 0x1F06 => 0x1F0E,
+ 0x1F07 => 0x1F0F,
+ 0x1F10 => 0x1F18,
+ 0x1F11 => 0x1F19,
+ 0x1F12 => 0x1F1A,
+ 0x1F13 => 0x1F1B,
+ 0x1F14 => 0x1F1C,
+ 0x1F15 => 0x1F1D,
+ 0x1F20 => 0x1F28,
+ 0x1F21 => 0x1F29,
+ 0x1F22 => 0x1F2A,
+ 0x1F23 => 0x1F2B,
+ 0x1F24 => 0x1F2C,
+ 0x1F25 => 0x1F2D,
+ 0x1F26 => 0x1F2E,
+ 0x1F27 => 0x1F2F,
+ 0x1F30 => 0x1F38,
+ 0x1F31 => 0x1F39,
+ 0x1F32 => 0x1F3A,
+ 0x1F33 => 0x1F3B,
+ 0x1F34 => 0x1F3C,
+ 0x1F35 => 0x1F3D,
+ 0x1F36 => 0x1F3E,
+ 0x1F37 => 0x1F3F,
+ 0x1F40 => 0x1F48,
+ 0x1F41 => 0x1F49,
+ 0x1F42 => 0x1F4A,
+ 0x1F43 => 0x1F4B,
+ 0x1F44 => 0x1F4C,
+ 0x1F45 => 0x1F4D,
+ 0x1F51 => 0x1F59,
+ 0x1F53 => 0x1F5B,
+ 0x1F55 => 0x1F5D,
+ 0x1F57 => 0x1F5F,
+ 0x1F60 => 0x1F68,
+ 0x1F61 => 0x1F69,
+ 0x1F62 => 0x1F6A,
+ 0x1F63 => 0x1F6B,
+ 0x1F64 => 0x1F6C,
+ 0x1F65 => 0x1F6D,
+ 0x1F66 => 0x1F6E,
+ 0x1F67 => 0x1F6F,
+ 0x1F70 => 0x1FBA,
+ 0x1F71 => 0x1FBB,
+ 0x1F72 => 0x1FC8,
+ 0x1F73 => 0x1FC9,
+ 0x1F74 => 0x1FCA,
+ 0x1F75 => 0x1FCB,
+ 0x1F76 => 0x1FDA,
+ 0x1F77 => 0x1FDB,
+ 0x1F78 => 0x1FF8,
+ 0x1F79 => 0x1FF9,
+ 0x1F7A => 0x1FEA,
+ 0x1F7B => 0x1FEB,
+ 0x1F7C => 0x1FFA,
+ 0x1F7D => 0x1FFB,
+ 0x1F80 => 0x1F88,
+ 0x1F81 => 0x1F89,
+ 0x1F82 => 0x1F8A,
+ 0x1F83 => 0x1F8B,
+ 0x1F84 => 0x1F8C,
+ 0x1F85 => 0x1F8D,
+ 0x1F86 => 0x1F8E,
+ 0x1F87 => 0x1F8F,
+ 0x1F90 => 0x1F98,
+ 0x1F91 => 0x1F99,
+ 0x1F92 => 0x1F9A,
+ 0x1F93 => 0x1F9B,
+ 0x1F94 => 0x1F9C,
+ 0x1F95 => 0x1F9D,
+ 0x1F96 => 0x1F9E,
+ 0x1F97 => 0x1F9F,
+ 0x1FA0 => 0x1FA8,
+ 0x1FA1 => 0x1FA9,
+ 0x1FA2 => 0x1FAA,
+ 0x1FA3 => 0x1FAB,
+ 0x1FA4 => 0x1FAC,
+ 0x1FA5 => 0x1FAD,
+ 0x1FA6 => 0x1FAE,
+ 0x1FA7 => 0x1FAF,
+ 0x1FB0 => 0x1FB8,
+ 0x1FB1 => 0x1FB9,
+ 0x1FB3 => 0x1FBC,
+ 0x1FBE => 0x399,
+ 0x1FC3 => 0x1FCC,
+ 0x1FD0 => 0x1FD8,
+ 0x1FD1 => 0x1FD9,
+ 0x1FE0 => 0x1FE8,
+ 0x1FE1 => 0x1FE9,
+ 0x1FE5 => 0x1FEC,
+ 0x1FF3 => 0x1FFC,
+ 0x214E => 0x2132,
+ 0x2170 => 0x2160,
+ 0x2171 => 0x2161,
+ 0x2172 => 0x2162,
+ 0x2173 => 0x2163,
+ 0x2174 => 0x2164,
+ 0x2175 => 0x2165,
+ 0x2176 => 0x2166,
+ 0x2177 => 0x2167,
+ 0x2178 => 0x2168,
+ 0x2179 => 0x2169,
+ 0x217A => 0x216A,
+ 0x217B => 0x216B,
+ 0x217C => 0x216C,
+ 0x217D => 0x216D,
+ 0x217E => 0x216E,
+ 0x217F => 0x216F,
+ 0x2184 => 0x2183,
+ 0x24D0 => 0x24B6,
+ 0x24D1 => 0x24B7,
+ 0x24D2 => 0x24B8,
+ 0x24D3 => 0x24B9,
+ 0x24D4 => 0x24BA,
+ 0x24D5 => 0x24BB,
+ 0x24D6 => 0x24BC,
+ 0x24D7 => 0x24BD,
+ 0x24D8 => 0x24BE,
+ 0x24D9 => 0x24BF,
+ 0x24DA => 0x24C0,
+ 0x24DB => 0x24C1,
+ 0x24DC => 0x24C2,
+ 0x24DD => 0x24C3,
+ 0x24DE => 0x24C4,
+ 0x24DF => 0x24C5,
+ 0x24E0 => 0x24C6,
+ 0x24E1 => 0x24C7,
+ 0x24E2 => 0x24C8,
+ 0x24E3 => 0x24C9,
+ 0x24E4 => 0x24CA,
+ 0x24E5 => 0x24CB,
+ 0x24E6 => 0x24CC,
+ 0x24E7 => 0x24CD,
+ 0x24E8 => 0x24CE,
+ 0x24E9 => 0x24CF,
+ 0x2C30 => 0x2C00,
+ 0x2C31 => 0x2C01,
+ 0x2C32 => 0x2C02,
+ 0x2C33 => 0x2C03,
+ 0x2C34 => 0x2C04,
+ 0x2C35 => 0x2C05,
+ 0x2C36 => 0x2C06,
+ 0x2C37 => 0x2C07,
+ 0x2C38 => 0x2C08,
+ 0x2C39 => 0x2C09,
+ 0x2C3A => 0x2C0A,
+ 0x2C3B => 0x2C0B,
+ 0x2C3C => 0x2C0C,
+ 0x2C3D => 0x2C0D,
+ 0x2C3E => 0x2C0E,
+ 0x2C3F => 0x2C0F,
+ 0x2C40 => 0x2C10,
+ 0x2C41 => 0x2C11,
+ 0x2C42 => 0x2C12,
+ 0x2C43 => 0x2C13,
+ 0x2C44 => 0x2C14,
+ 0x2C45 => 0x2C15,
+ 0x2C46 => 0x2C16,
+ 0x2C47 => 0x2C17,
+ 0x2C48 => 0x2C18,
+ 0x2C49 => 0x2C19,
+ 0x2C4A => 0x2C1A,
+ 0x2C4B => 0x2C1B,
+ 0x2C4C => 0x2C1C,
+ 0x2C4D => 0x2C1D,
+ 0x2C4E => 0x2C1E,
+ 0x2C4F => 0x2C1F,
+ 0x2C50 => 0x2C20,
+ 0x2C51 => 0x2C21,
+ 0x2C52 => 0x2C22,
+ 0x2C53 => 0x2C23,
+ 0x2C54 => 0x2C24,
+ 0x2C55 => 0x2C25,
+ 0x2C56 => 0x2C26,
+ 0x2C57 => 0x2C27,
+ 0x2C58 => 0x2C28,
+ 0x2C59 => 0x2C29,
+ 0x2C5A => 0x2C2A,
+ 0x2C5B => 0x2C2B,
+ 0x2C5C => 0x2C2C,
+ 0x2C5D => 0x2C2D,
+ 0x2C5E => 0x2C2E,
+ 0x2C5F => 0x2C2F,
+ 0x2C61 => 0x2C60,
+ 0x2C65 => 0x23A,
+ 0x2C66 => 0x23E,
+ 0x2C68 => 0x2C67,
+ 0x2C6A => 0x2C69,
+ 0x2C6C => 0x2C6B,
+ 0x2C73 => 0x2C72,
+ 0x2C76 => 0x2C75,
+ 0x2C81 => 0x2C80,
+ 0x2C83 => 0x2C82,
+ 0x2C85 => 0x2C84,
+ 0x2C87 => 0x2C86,
+ 0x2C89 => 0x2C88,
+ 0x2C8B => 0x2C8A,
+ 0x2C8D => 0x2C8C,
+ 0x2C8F => 0x2C8E,
+ 0x2C91 => 0x2C90,
+ 0x2C93 => 0x2C92,
+ 0x2C95 => 0x2C94,
+ 0x2C97 => 0x2C96,
+ 0x2C99 => 0x2C98,
+ 0x2C9B => 0x2C9A,
+ 0x2C9D => 0x2C9C,
+ 0x2C9F => 0x2C9E,
+ 0x2CA1 => 0x2CA0,
+ 0x2CA3 => 0x2CA2,
+ 0x2CA5 => 0x2CA4,
+ 0x2CA7 => 0x2CA6,
+ 0x2CA9 => 0x2CA8,
+ 0x2CAB => 0x2CAA,
+ 0x2CAD => 0x2CAC,
+ 0x2CAF => 0x2CAE,
+ 0x2CB1 => 0x2CB0,
+ 0x2CB3 => 0x2CB2,
+ 0x2CB5 => 0x2CB4,
+ 0x2CB7 => 0x2CB6,
+ 0x2CB9 => 0x2CB8,
+ 0x2CBB => 0x2CBA,
+ 0x2CBD => 0x2CBC,
+ 0x2CBF => 0x2CBE,
+ 0x2CC1 => 0x2CC0,
+ 0x2CC3 => 0x2CC2,
+ 0x2CC5 => 0x2CC4,
+ 0x2CC7 => 0x2CC6,
+ 0x2CC9 => 0x2CC8,
+ 0x2CCB => 0x2CCA,
+ 0x2CCD => 0x2CCC,
+ 0x2CCF => 0x2CCE,
+ 0x2CD1 => 0x2CD0,
+ 0x2CD3 => 0x2CD2,
+ 0x2CD5 => 0x2CD4,
+ 0x2CD7 => 0x2CD6,
+ 0x2CD9 => 0x2CD8,
+ 0x2CDB => 0x2CDA,
+ 0x2CDD => 0x2CDC,
+ 0x2CDF => 0x2CDE,
+ 0x2CE1 => 0x2CE0,
+ 0x2CE3 => 0x2CE2,
+ 0x2CEC => 0x2CEB,
+ 0x2CEE => 0x2CED,
+ 0x2CF3 => 0x2CF2,
+ 0x2D00 => 0x10A0,
+ 0x2D01 => 0x10A1,
+ 0x2D02 => 0x10A2,
+ 0x2D03 => 0x10A3,
+ 0x2D04 => 0x10A4,
+ 0x2D05 => 0x10A5,
+ 0x2D06 => 0x10A6,
+ 0x2D07 => 0x10A7,
+ 0x2D08 => 0x10A8,
+ 0x2D09 => 0x10A9,
+ 0x2D0A => 0x10AA,
+ 0x2D0B => 0x10AB,
+ 0x2D0C => 0x10AC,
+ 0x2D0D => 0x10AD,
+ 0x2D0E => 0x10AE,
+ 0x2D0F => 0x10AF,
+ 0x2D10 => 0x10B0,
+ 0x2D11 => 0x10B1,
+ 0x2D12 => 0x10B2,
+ 0x2D13 => 0x10B3,
+ 0x2D14 => 0x10B4,
+ 0x2D15 => 0x10B5,
+ 0x2D16 => 0x10B6,
+ 0x2D17 => 0x10B7,
+ 0x2D18 => 0x10B8,
+ 0x2D19 => 0x10B9,
+ 0x2D1A => 0x10BA,
+ 0x2D1B => 0x10BB,
+ 0x2D1C => 0x10BC,
+ 0x2D1D => 0x10BD,
+ 0x2D1E => 0x10BE,
+ 0x2D1F => 0x10BF,
+ 0x2D20 => 0x10C0,
+ 0x2D21 => 0x10C1,
+ 0x2D22 => 0x10C2,
+ 0x2D23 => 0x10C3,
+ 0x2D24 => 0x10C4,
+ 0x2D25 => 0x10C5,
+ 0x2D27 => 0x10C7,
+ 0x2D2D => 0x10CD,
+ 0xA641 => 0xA640,
+ 0xA643 => 0xA642,
+ 0xA645 => 0xA644,
+ 0xA647 => 0xA646,
+ 0xA649 => 0xA648,
+ 0xA64B => 0xA64A,
+ 0xA64D => 0xA64C,
+ 0xA64F => 0xA64E,
+ 0xA651 => 0xA650,
+ 0xA653 => 0xA652,
+ 0xA655 => 0xA654,
+ 0xA657 => 0xA656,
+ 0xA659 => 0xA658,
+ 0xA65B => 0xA65A,
+ 0xA65D => 0xA65C,
+ 0xA65F => 0xA65E,
+ 0xA661 => 0xA660,
+ 0xA663 => 0xA662,
+ 0xA665 => 0xA664,
+ 0xA667 => 0xA666,
+ 0xA669 => 0xA668,
+ 0xA66B => 0xA66A,
+ 0xA66D => 0xA66C,
+ 0xA681 => 0xA680,
+ 0xA683 => 0xA682,
+ 0xA685 => 0xA684,
+ 0xA687 => 0xA686,
+ 0xA689 => 0xA688,
+ 0xA68B => 0xA68A,
+ 0xA68D => 0xA68C,
+ 0xA68F => 0xA68E,
+ 0xA691 => 0xA690,
+ 0xA693 => 0xA692,
+ 0xA695 => 0xA694,
+ 0xA697 => 0xA696,
+ 0xA699 => 0xA698,
+ 0xA69B => 0xA69A,
+ 0xA723 => 0xA722,
+ 0xA725 => 0xA724,
+ 0xA727 => 0xA726,
+ 0xA729 => 0xA728,
+ 0xA72B => 0xA72A,
+ 0xA72D => 0xA72C,
+ 0xA72F => 0xA72E,
+ 0xA733 => 0xA732,
+ 0xA735 => 0xA734,
+ 0xA737 => 0xA736,
+ 0xA739 => 0xA738,
+ 0xA73B => 0xA73A,
+ 0xA73D => 0xA73C,
+ 0xA73F => 0xA73E,
+ 0xA741 => 0xA740,
+ 0xA743 => 0xA742,
+ 0xA745 => 0xA744,
+ 0xA747 => 0xA746,
+ 0xA749 => 0xA748,
+ 0xA74B => 0xA74A,
+ 0xA74D => 0xA74C,
+ 0xA74F => 0xA74E,
+ 0xA751 => 0xA750,
+ 0xA753 => 0xA752,
+ 0xA755 => 0xA754,
+ 0xA757 => 0xA756,
+ 0xA759 => 0xA758,
+ 0xA75B => 0xA75A,
+ 0xA75D => 0xA75C,
+ 0xA75F => 0xA75E,
+ 0xA761 => 0xA760,
+ 0xA763 => 0xA762,
+ 0xA765 => 0xA764,
+ 0xA767 => 0xA766,
+ 0xA769 => 0xA768,
+ 0xA76B => 0xA76A,
+ 0xA76D => 0xA76C,
+ 0xA76F => 0xA76E,
+ 0xA77A => 0xA779,
+ 0xA77C => 0xA77B,
+ 0xA77F => 0xA77E,
+ 0xA781 => 0xA780,
+ 0xA783 => 0xA782,
+ 0xA785 => 0xA784,
+ 0xA787 => 0xA786,
+ 0xA78C => 0xA78B,
+ 0xA791 => 0xA790,
+ 0xA793 => 0xA792,
+ 0xA794 => 0xA7C4,
+ 0xA797 => 0xA796,
+ 0xA799 => 0xA798,
+ 0xA79B => 0xA79A,
+ 0xA79D => 0xA79C,
+ 0xA79F => 0xA79E,
+ 0xA7A1 => 0xA7A0,
+ 0xA7A3 => 0xA7A2,
+ 0xA7A5 => 0xA7A4,
+ 0xA7A7 => 0xA7A6,
+ 0xA7A9 => 0xA7A8,
+ 0xA7B5 => 0xA7B4,
+ 0xA7B7 => 0xA7B6,
+ 0xA7B9 => 0xA7B8,
+ 0xA7BB => 0xA7BA,
+ 0xA7BD => 0xA7BC,
+ 0xA7BF => 0xA7BE,
+ 0xA7C1 => 0xA7C0,
+ 0xA7C3 => 0xA7C2,
+ 0xA7C8 => 0xA7C7,
+ 0xA7CA => 0xA7C9,
+ 0xA7D1 => 0xA7D0,
+ 0xA7D7 => 0xA7D6,
+ 0xA7D9 => 0xA7D8,
+ 0xA7F6 => 0xA7F5,
+ 0xAB53 => 0xA7B3,
+ 0xAB70 => 0x13A0,
+ 0xAB71 => 0x13A1,
+ 0xAB72 => 0x13A2,
+ 0xAB73 => 0x13A3,
+ 0xAB74 => 0x13A4,
+ 0xAB75 => 0x13A5,
+ 0xAB76 => 0x13A6,
+ 0xAB77 => 0x13A7,
+ 0xAB78 => 0x13A8,
+ 0xAB79 => 0x13A9,
+ 0xAB7A => 0x13AA,
+ 0xAB7B => 0x13AB,
+ 0xAB7C => 0x13AC,
+ 0xAB7D => 0x13AD,
+ 0xAB7E => 0x13AE,
+ 0xAB7F => 0x13AF,
+ 0xAB80 => 0x13B0,
+ 0xAB81 => 0x13B1,
+ 0xAB82 => 0x13B2,
+ 0xAB83 => 0x13B3,
+ 0xAB84 => 0x13B4,
+ 0xAB85 => 0x13B5,
+ 0xAB86 => 0x13B6,
+ 0xAB87 => 0x13B7,
+ 0xAB88 => 0x13B8,
+ 0xAB89 => 0x13B9,
+ 0xAB8A => 0x13BA,
+ 0xAB8B => 0x13BB,
+ 0xAB8C => 0x13BC,
+ 0xAB8D => 0x13BD,
+ 0xAB8E => 0x13BE,
+ 0xAB8F => 0x13BF,
+ 0xAB90 => 0x13C0,
+ 0xAB91 => 0x13C1,
+ 0xAB92 => 0x13C2,
+ 0xAB93 => 0x13C3,
+ 0xAB94 => 0x13C4,
+ 0xAB95 => 0x13C5,
+ 0xAB96 => 0x13C6,
+ 0xAB97 => 0x13C7,
+ 0xAB98 => 0x13C8,
+ 0xAB99 => 0x13C9,
+ 0xAB9A => 0x13CA,
+ 0xAB9B => 0x13CB,
+ 0xAB9C => 0x13CC,
+ 0xAB9D => 0x13CD,
+ 0xAB9E => 0x13CE,
+ 0xAB9F => 0x13CF,
+ 0xABA0 => 0x13D0,
+ 0xABA1 => 0x13D1,
+ 0xABA2 => 0x13D2,
+ 0xABA3 => 0x13D3,
+ 0xABA4 => 0x13D4,
+ 0xABA5 => 0x13D5,
+ 0xABA6 => 0x13D6,
+ 0xABA7 => 0x13D7,
+ 0xABA8 => 0x13D8,
+ 0xABA9 => 0x13D9,
+ 0xABAA => 0x13DA,
+ 0xABAB => 0x13DB,
+ 0xABAC => 0x13DC,
+ 0xABAD => 0x13DD,
+ 0xABAE => 0x13DE,
+ 0xABAF => 0x13DF,
+ 0xABB0 => 0x13E0,
+ 0xABB1 => 0x13E1,
+ 0xABB2 => 0x13E2,
+ 0xABB3 => 0x13E3,
+ 0xABB4 => 0x13E4,
+ 0xABB5 => 0x13E5,
+ 0xABB6 => 0x13E6,
+ 0xABB7 => 0x13E7,
+ 0xABB8 => 0x13E8,
+ 0xABB9 => 0x13E9,
+ 0xABBA => 0x13EA,
+ 0xABBB => 0x13EB,
+ 0xABBC => 0x13EC,
+ 0xABBD => 0x13ED,
+ 0xABBE => 0x13EE,
+ 0xABBF => 0x13EF,
+ 0xFF41 => 0xFF21,
+ 0xFF42 => 0xFF22,
+ 0xFF43 => 0xFF23,
+ 0xFF44 => 0xFF24,
+ 0xFF45 => 0xFF25,
+ 0xFF46 => 0xFF26,
+ 0xFF47 => 0xFF27,
+ 0xFF48 => 0xFF28,
+ 0xFF49 => 0xFF29,
+ 0xFF4A => 0xFF2A,
+ 0xFF4B => 0xFF2B,
+ 0xFF4C => 0xFF2C,
+ 0xFF4D => 0xFF2D,
+ 0xFF4E => 0xFF2E,
+ 0xFF4F => 0xFF2F,
+ 0xFF50 => 0xFF30,
+ 0xFF51 => 0xFF31,
+ 0xFF52 => 0xFF32,
+ 0xFF53 => 0xFF33,
+ 0xFF54 => 0xFF34,
+ 0xFF55 => 0xFF35,
+ 0xFF56 => 0xFF36,
+ 0xFF57 => 0xFF37,
+ 0xFF58 => 0xFF38,
+ 0xFF59 => 0xFF39,
+ 0xFF5A => 0xFF3A,
+ 0x10428 => 0x10400,
+ 0x10429 => 0x10401,
+ 0x1042A => 0x10402,
+ 0x1042B => 0x10403,
+ 0x1042C => 0x10404,
+ 0x1042D => 0x10405,
+ 0x1042E => 0x10406,
+ 0x1042F => 0x10407,
+ 0x10430 => 0x10408,
+ 0x10431 => 0x10409,
+ 0x10432 => 0x1040A,
+ 0x10433 => 0x1040B,
+ 0x10434 => 0x1040C,
+ 0x10435 => 0x1040D,
+ 0x10436 => 0x1040E,
+ 0x10437 => 0x1040F,
+ 0x10438 => 0x10410,
+ 0x10439 => 0x10411,
+ 0x1043A => 0x10412,
+ 0x1043B => 0x10413,
+ 0x1043C => 0x10414,
+ 0x1043D => 0x10415,
+ 0x1043E => 0x10416,
+ 0x1043F => 0x10417,
+ 0x10440 => 0x10418,
+ 0x10441 => 0x10419,
+ 0x10442 => 0x1041A,
+ 0x10443 => 0x1041B,
+ 0x10444 => 0x1041C,
+ 0x10445 => 0x1041D,
+ 0x10446 => 0x1041E,
+ 0x10447 => 0x1041F,
+ 0x10448 => 0x10420,
+ 0x10449 => 0x10421,
+ 0x1044A => 0x10422,
+ 0x1044B => 0x10423,
+ 0x1044C => 0x10424,
+ 0x1044D => 0x10425,
+ 0x1044E => 0x10426,
+ 0x1044F => 0x10427,
+ 0x104D8 => 0x104B0,
+ 0x104D9 => 0x104B1,
+ 0x104DA => 0x104B2,
+ 0x104DB => 0x104B3,
+ 0x104DC => 0x104B4,
+ 0x104DD => 0x104B5,
+ 0x104DE => 0x104B6,
+ 0x104DF => 0x104B7,
+ 0x104E0 => 0x104B8,
+ 0x104E1 => 0x104B9,
+ 0x104E2 => 0x104BA,
+ 0x104E3 => 0x104BB,
+ 0x104E4 => 0x104BC,
+ 0x104E5 => 0x104BD,
+ 0x104E6 => 0x104BE,
+ 0x104E7 => 0x104BF,
+ 0x104E8 => 0x104C0,
+ 0x104E9 => 0x104C1,
+ 0x104EA => 0x104C2,
+ 0x104EB => 0x104C3,
+ 0x104EC => 0x104C4,
+ 0x104ED => 0x104C5,
+ 0x104EE => 0x104C6,
+ 0x104EF => 0x104C7,
+ 0x104F0 => 0x104C8,
+ 0x104F1 => 0x104C9,
+ 0x104F2 => 0x104CA,
+ 0x104F3 => 0x104CB,
+ 0x104F4 => 0x104CC,
+ 0x104F5 => 0x104CD,
+ 0x104F6 => 0x104CE,
+ 0x104F7 => 0x104CF,
+ 0x104F8 => 0x104D0,
+ 0x104F9 => 0x104D1,
+ 0x104FA => 0x104D2,
+ 0x104FB => 0x104D3,
+ 0x10597 => 0x10570,
+ 0x10598 => 0x10571,
+ 0x10599 => 0x10572,
+ 0x1059A => 0x10573,
+ 0x1059B => 0x10574,
+ 0x1059C => 0x10575,
+ 0x1059D => 0x10576,
+ 0x1059E => 0x10577,
+ 0x1059F => 0x10578,
+ 0x105A0 => 0x10579,
+ 0x105A1 => 0x1057A,
+ 0x105A3 => 0x1057C,
+ 0x105A4 => 0x1057D,
+ 0x105A5 => 0x1057E,
+ 0x105A6 => 0x1057F,
+ 0x105A7 => 0x10580,
+ 0x105A8 => 0x10581,
+ 0x105A9 => 0x10582,
+ 0x105AA => 0x10583,
+ 0x105AB => 0x10584,
+ 0x105AC => 0x10585,
+ 0x105AD => 0x10586,
+ 0x105AE => 0x10587,
+ 0x105AF => 0x10588,
+ 0x105B0 => 0x10589,
+ 0x105B1 => 0x1058A,
+ 0x105B3 => 0x1058C,
+ 0x105B4 => 0x1058D,
+ 0x105B5 => 0x1058E,
+ 0x105B6 => 0x1058F,
+ 0x105B7 => 0x10590,
+ 0x105B8 => 0x10591,
+ 0x105B9 => 0x10592,
+ 0x105BB => 0x10594,
+ 0x105BC => 0x10595,
+ 0x10CC0 => 0x10C80,
+ 0x10CC1 => 0x10C81,
+ 0x10CC2 => 0x10C82,
+ 0x10CC3 => 0x10C83,
+ 0x10CC4 => 0x10C84,
+ 0x10CC5 => 0x10C85,
+ 0x10CC6 => 0x10C86,
+ 0x10CC7 => 0x10C87,
+ 0x10CC8 => 0x10C88,
+ 0x10CC9 => 0x10C89,
+ 0x10CCA => 0x10C8A,
+ 0x10CCB => 0x10C8B,
+ 0x10CCC => 0x10C8C,
+ 0x10CCD => 0x10C8D,
+ 0x10CCE => 0x10C8E,
+ 0x10CCF => 0x10C8F,
+ 0x10CD0 => 0x10C90,
+ 0x10CD1 => 0x10C91,
+ 0x10CD2 => 0x10C92,
+ 0x10CD3 => 0x10C93,
+ 0x10CD4 => 0x10C94,
+ 0x10CD5 => 0x10C95,
+ 0x10CD6 => 0x10C96,
+ 0x10CD7 => 0x10C97,
+ 0x10CD8 => 0x10C98,
+ 0x10CD9 => 0x10C99,
+ 0x10CDA => 0x10C9A,
+ 0x10CDB => 0x10C9B,
+ 0x10CDC => 0x10C9C,
+ 0x10CDD => 0x10C9D,
+ 0x10CDE => 0x10C9E,
+ 0x10CDF => 0x10C9F,
+ 0x10CE0 => 0x10CA0,
+ 0x10CE1 => 0x10CA1,
+ 0x10CE2 => 0x10CA2,
+ 0x10CE3 => 0x10CA3,
+ 0x10CE4 => 0x10CA4,
+ 0x10CE5 => 0x10CA5,
+ 0x10CE6 => 0x10CA6,
+ 0x10CE7 => 0x10CA7,
+ 0x10CE8 => 0x10CA8,
+ 0x10CE9 => 0x10CA9,
+ 0x10CEA => 0x10CAA,
+ 0x10CEB => 0x10CAB,
+ 0x10CEC => 0x10CAC,
+ 0x10CED => 0x10CAD,
+ 0x10CEE => 0x10CAE,
+ 0x10CEF => 0x10CAF,
+ 0x10CF0 => 0x10CB0,
+ 0x10CF1 => 0x10CB1,
+ 0x10CF2 => 0x10CB2,
+ 0x118C0 => 0x118A0,
+ 0x118C1 => 0x118A1,
+ 0x118C2 => 0x118A2,
+ 0x118C3 => 0x118A3,
+ 0x118C4 => 0x118A4,
+ 0x118C5 => 0x118A5,
+ 0x118C6 => 0x118A6,
+ 0x118C7 => 0x118A7,
+ 0x118C8 => 0x118A8,
+ 0x118C9 => 0x118A9,
+ 0x118CA => 0x118AA,
+ 0x118CB => 0x118AB,
+ 0x118CC => 0x118AC,
+ 0x118CD => 0x118AD,
+ 0x118CE => 0x118AE,
+ 0x118CF => 0x118AF,
+ 0x118D0 => 0x118B0,
+ 0x118D1 => 0x118B1,
+ 0x118D2 => 0x118B2,
+ 0x118D3 => 0x118B3,
+ 0x118D4 => 0x118B4,
+ 0x118D5 => 0x118B5,
+ 0x118D6 => 0x118B6,
+ 0x118D7 => 0x118B7,
+ 0x118D8 => 0x118B8,
+ 0x118D9 => 0x118B9,
+ 0x118DA => 0x118BA,
+ 0x118DB => 0x118BB,
+ 0x118DC => 0x118BC,
+ 0x118DD => 0x118BD,
+ 0x118DE => 0x118BE,
+ 0x118DF => 0x118BF,
+ 0x16E60 => 0x16E40,
+ 0x16E61 => 0x16E41,
+ 0x16E62 => 0x16E42,
+ 0x16E63 => 0x16E43,
+ 0x16E64 => 0x16E44,
+ 0x16E65 => 0x16E45,
+ 0x16E66 => 0x16E46,
+ 0x16E67 => 0x16E47,
+ 0x16E68 => 0x16E48,
+ 0x16E69 => 0x16E49,
+ 0x16E6A => 0x16E4A,
+ 0x16E6B => 0x16E4B,
+ 0x16E6C => 0x16E4C,
+ 0x16E6D => 0x16E4D,
+ 0x16E6E => 0x16E4E,
+ 0x16E6F => 0x16E4F,
+ 0x16E70 => 0x16E50,
+ 0x16E71 => 0x16E51,
+ 0x16E72 => 0x16E52,
+ 0x16E73 => 0x16E53,
+ 0x16E74 => 0x16E54,
+ 0x16E75 => 0x16E55,
+ 0x16E76 => 0x16E56,
+ 0x16E77 => 0x16E57,
+ 0x16E78 => 0x16E58,
+ 0x16E79 => 0x16E59,
+ 0x16E7A => 0x16E5A,
+ 0x16E7B => 0x16E5B,
+ 0x16E7C => 0x16E5C,
+ 0x16E7D => 0x16E5D,
+ 0x16E7E => 0x16E5E,
+ 0x16E7F => 0x16E5F,
+ 0x1E922 => 0x1E900,
+ 0x1E923 => 0x1E901,
+ 0x1E924 => 0x1E902,
+ 0x1E925 => 0x1E903,
+ 0x1E926 => 0x1E904,
+ 0x1E927 => 0x1E905,
+ 0x1E928 => 0x1E906,
+ 0x1E929 => 0x1E907,
+ 0x1E92A => 0x1E908,
+ 0x1E92B => 0x1E909,
+ 0x1E92C => 0x1E90A,
+ 0x1E92D => 0x1E90B,
+ 0x1E92E => 0x1E90C,
+ 0x1E92F => 0x1E90D,
+ 0x1E930 => 0x1E90E,
+ 0x1E931 => 0x1E90F,
+ 0x1E932 => 0x1E910,
+ 0x1E933 => 0x1E911,
+ 0x1E934 => 0x1E912,
+ 0x1E935 => 0x1E913,
+ 0x1E936 => 0x1E914,
+ 0x1E937 => 0x1E915,
+ 0x1E938 => 0x1E916,
+ 0x1E939 => 0x1E917,
+ 0x1E93A => 0x1E918,
+ 0x1E93B => 0x1E919,
+ 0x1E93C => 0x1E91A,
+ 0x1E93D => 0x1E91B,
+ 0x1E93E => 0x1E91C,
+ 0x1E93F => 0x1E91D,
+ 0x1E940 => 0x1E91E,
+ 0x1E941 => 0x1E91F,
+ 0x1E942 => 0x1E920,
+ 0x1E943 => 0x1E921,
+ else => cp,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/upper_map.zig.html b/docs/src/ziglyph/autogen/upper_map.zig.html
new file mode 100644
index 0000000..6fafb4b
--- /dev/null
+++ b/docs/src/ziglyph/autogen/upper_map.zig.html
@@ -0,0 +1,1575 @@
+
+
+
+
+
autogen/upper_map.zig - source view
+
+
+
+
+
+
+
+
+pub fn toUpper(cp: u21) u21 {
+ return switch (cp) {
+ 0x61 => 0x41,
+ 0x62 => 0x42,
+ 0x63 => 0x43,
+ 0x64 => 0x44,
+ 0x65 => 0x45,
+ 0x66 => 0x46,
+ 0x67 => 0x47,
+ 0x68 => 0x48,
+ 0x69 => 0x49,
+ 0x6A => 0x4A,
+ 0x6B => 0x4B,
+ 0x6C => 0x4C,
+ 0x6D => 0x4D,
+ 0x6E => 0x4E,
+ 0x6F => 0x4F,
+ 0x70 => 0x50,
+ 0x71 => 0x51,
+ 0x72 => 0x52,
+ 0x73 => 0x53,
+ 0x74 => 0x54,
+ 0x75 => 0x55,
+ 0x76 => 0x56,
+ 0x77 => 0x57,
+ 0x78 => 0x58,
+ 0x79 => 0x59,
+ 0x7A => 0x5A,
+ 0xB5 => 0x39C,
+ 0xE0 => 0xC0,
+ 0xE1 => 0xC1,
+ 0xE2 => 0xC2,
+ 0xE3 => 0xC3,
+ 0xE4 => 0xC4,
+ 0xE5 => 0xC5,
+ 0xE6 => 0xC6,
+ 0xE7 => 0xC7,
+ 0xE8 => 0xC8,
+ 0xE9 => 0xC9,
+ 0xEA => 0xCA,
+ 0xEB => 0xCB,
+ 0xEC => 0xCC,
+ 0xED => 0xCD,
+ 0xEE => 0xCE,
+ 0xEF => 0xCF,
+ 0xF0 => 0xD0,
+ 0xF1 => 0xD1,
+ 0xF2 => 0xD2,
+ 0xF3 => 0xD3,
+ 0xF4 => 0xD4,
+ 0xF5 => 0xD5,
+ 0xF6 => 0xD6,
+ 0xF8 => 0xD8,
+ 0xF9 => 0xD9,
+ 0xFA => 0xDA,
+ 0xFB => 0xDB,
+ 0xFC => 0xDC,
+ 0xFD => 0xDD,
+ 0xFE => 0xDE,
+ 0xFF => 0x178,
+ 0x101 => 0x100,
+ 0x103 => 0x102,
+ 0x105 => 0x104,
+ 0x107 => 0x106,
+ 0x109 => 0x108,
+ 0x10B => 0x10A,
+ 0x10D => 0x10C,
+ 0x10F => 0x10E,
+ 0x111 => 0x110,
+ 0x113 => 0x112,
+ 0x115 => 0x114,
+ 0x117 => 0x116,
+ 0x119 => 0x118,
+ 0x11B => 0x11A,
+ 0x11D => 0x11C,
+ 0x11F => 0x11E,
+ 0x121 => 0x120,
+ 0x123 => 0x122,
+ 0x125 => 0x124,
+ 0x127 => 0x126,
+ 0x129 => 0x128,
+ 0x12B => 0x12A,
+ 0x12D => 0x12C,
+ 0x12F => 0x12E,
+ 0x131 => 0x49,
+ 0x133 => 0x132,
+ 0x135 => 0x134,
+ 0x137 => 0x136,
+ 0x13A => 0x139,
+ 0x13C => 0x13B,
+ 0x13E => 0x13D,
+ 0x140 => 0x13F,
+ 0x142 => 0x141,
+ 0x144 => 0x143,
+ 0x146 => 0x145,
+ 0x148 => 0x147,
+ 0x14B => 0x14A,
+ 0x14D => 0x14C,
+ 0x14F => 0x14E,
+ 0x151 => 0x150,
+ 0x153 => 0x152,
+ 0x155 => 0x154,
+ 0x157 => 0x156,
+ 0x159 => 0x158,
+ 0x15B => 0x15A,
+ 0x15D => 0x15C,
+ 0x15F => 0x15E,
+ 0x161 => 0x160,
+ 0x163 => 0x162,
+ 0x165 => 0x164,
+ 0x167 => 0x166,
+ 0x169 => 0x168,
+ 0x16B => 0x16A,
+ 0x16D => 0x16C,
+ 0x16F => 0x16E,
+ 0x171 => 0x170,
+ 0x173 => 0x172,
+ 0x175 => 0x174,
+ 0x177 => 0x176,
+ 0x17A => 0x179,
+ 0x17C => 0x17B,
+ 0x17E => 0x17D,
+ 0x17F => 0x53,
+ 0x180 => 0x243,
+ 0x183 => 0x182,
+ 0x185 => 0x184,
+ 0x188 => 0x187,
+ 0x18C => 0x18B,
+ 0x192 => 0x191,
+ 0x195 => 0x1F6,
+ 0x199 => 0x198,
+ 0x19A => 0x23D,
+ 0x19E => 0x220,
+ 0x1A1 => 0x1A0,
+ 0x1A3 => 0x1A2,
+ 0x1A5 => 0x1A4,
+ 0x1A8 => 0x1A7,
+ 0x1AD => 0x1AC,
+ 0x1B0 => 0x1AF,
+ 0x1B4 => 0x1B3,
+ 0x1B6 => 0x1B5,
+ 0x1B9 => 0x1B8,
+ 0x1BD => 0x1BC,
+ 0x1BF => 0x1F7,
+ 0x1C5 => 0x1C4,
+ 0x1C6 => 0x1C4,
+ 0x1C8 => 0x1C7,
+ 0x1C9 => 0x1C7,
+ 0x1CB => 0x1CA,
+ 0x1CC => 0x1CA,
+ 0x1CE => 0x1CD,
+ 0x1D0 => 0x1CF,
+ 0x1D2 => 0x1D1,
+ 0x1D4 => 0x1D3,
+ 0x1D6 => 0x1D5,
+ 0x1D8 => 0x1D7,
+ 0x1DA => 0x1D9,
+ 0x1DC => 0x1DB,
+ 0x1DD => 0x18E,
+ 0x1DF => 0x1DE,
+ 0x1E1 => 0x1E0,
+ 0x1E3 => 0x1E2,
+ 0x1E5 => 0x1E4,
+ 0x1E7 => 0x1E6,
+ 0x1E9 => 0x1E8,
+ 0x1EB => 0x1EA,
+ 0x1ED => 0x1EC,
+ 0x1EF => 0x1EE,
+ 0x1F2 => 0x1F1,
+ 0x1F3 => 0x1F1,
+ 0x1F5 => 0x1F4,
+ 0x1F9 => 0x1F8,
+ 0x1FB => 0x1FA,
+ 0x1FD => 0x1FC,
+ 0x1FF => 0x1FE,
+ 0x201 => 0x200,
+ 0x203 => 0x202,
+ 0x205 => 0x204,
+ 0x207 => 0x206,
+ 0x209 => 0x208,
+ 0x20B => 0x20A,
+ 0x20D => 0x20C,
+ 0x20F => 0x20E,
+ 0x211 => 0x210,
+ 0x213 => 0x212,
+ 0x215 => 0x214,
+ 0x217 => 0x216,
+ 0x219 => 0x218,
+ 0x21B => 0x21A,
+ 0x21D => 0x21C,
+ 0x21F => 0x21E,
+ 0x223 => 0x222,
+ 0x225 => 0x224,
+ 0x227 => 0x226,
+ 0x229 => 0x228,
+ 0x22B => 0x22A,
+ 0x22D => 0x22C,
+ 0x22F => 0x22E,
+ 0x231 => 0x230,
+ 0x233 => 0x232,
+ 0x23C => 0x23B,
+ 0x23F => 0x2C7E,
+ 0x240 => 0x2C7F,
+ 0x242 => 0x241,
+ 0x247 => 0x246,
+ 0x249 => 0x248,
+ 0x24B => 0x24A,
+ 0x24D => 0x24C,
+ 0x24F => 0x24E,
+ 0x250 => 0x2C6F,
+ 0x251 => 0x2C6D,
+ 0x252 => 0x2C70,
+ 0x253 => 0x181,
+ 0x254 => 0x186,
+ 0x256 => 0x189,
+ 0x257 => 0x18A,
+ 0x259 => 0x18F,
+ 0x25B => 0x190,
+ 0x25C => 0xA7AB,
+ 0x260 => 0x193,
+ 0x261 => 0xA7AC,
+ 0x263 => 0x194,
+ 0x265 => 0xA78D,
+ 0x266 => 0xA7AA,
+ 0x268 => 0x197,
+ 0x269 => 0x196,
+ 0x26A => 0xA7AE,
+ 0x26B => 0x2C62,
+ 0x26C => 0xA7AD,
+ 0x26F => 0x19C,
+ 0x271 => 0x2C6E,
+ 0x272 => 0x19D,
+ 0x275 => 0x19F,
+ 0x27D => 0x2C64,
+ 0x280 => 0x1A6,
+ 0x282 => 0xA7C5,
+ 0x283 => 0x1A9,
+ 0x287 => 0xA7B1,
+ 0x288 => 0x1AE,
+ 0x289 => 0x244,
+ 0x28A => 0x1B1,
+ 0x28B => 0x1B2,
+ 0x28C => 0x245,
+ 0x292 => 0x1B7,
+ 0x29D => 0xA7B2,
+ 0x29E => 0xA7B0,
+ 0x345 => 0x399,
+ 0x371 => 0x370,
+ 0x373 => 0x372,
+ 0x377 => 0x376,
+ 0x37B => 0x3FD,
+ 0x37C => 0x3FE,
+ 0x37D => 0x3FF,
+ 0x3AC => 0x386,
+ 0x3AD => 0x388,
+ 0x3AE => 0x389,
+ 0x3AF => 0x38A,
+ 0x3B1 => 0x391,
+ 0x3B2 => 0x392,
+ 0x3B3 => 0x393,
+ 0x3B4 => 0x394,
+ 0x3B5 => 0x395,
+ 0x3B6 => 0x396,
+ 0x3B7 => 0x397,
+ 0x3B8 => 0x398,
+ 0x3B9 => 0x399,
+ 0x3BA => 0x39A,
+ 0x3BB => 0x39B,
+ 0x3BC => 0x39C,
+ 0x3BD => 0x39D,
+ 0x3BE => 0x39E,
+ 0x3BF => 0x39F,
+ 0x3C0 => 0x3A0,
+ 0x3C1 => 0x3A1,
+ 0x3C2 => 0x3A3,
+ 0x3C3 => 0x3A3,
+ 0x3C4 => 0x3A4,
+ 0x3C5 => 0x3A5,
+ 0x3C6 => 0x3A6,
+ 0x3C7 => 0x3A7,
+ 0x3C8 => 0x3A8,
+ 0x3C9 => 0x3A9,
+ 0x3CA => 0x3AA,
+ 0x3CB => 0x3AB,
+ 0x3CC => 0x38C,
+ 0x3CD => 0x38E,
+ 0x3CE => 0x38F,
+ 0x3D0 => 0x392,
+ 0x3D1 => 0x398,
+ 0x3D5 => 0x3A6,
+ 0x3D6 => 0x3A0,
+ 0x3D7 => 0x3CF,
+ 0x3D9 => 0x3D8,
+ 0x3DB => 0x3DA,
+ 0x3DD => 0x3DC,
+ 0x3DF => 0x3DE,
+ 0x3E1 => 0x3E0,
+ 0x3E3 => 0x3E2,
+ 0x3E5 => 0x3E4,
+ 0x3E7 => 0x3E6,
+ 0x3E9 => 0x3E8,
+ 0x3EB => 0x3EA,
+ 0x3ED => 0x3EC,
+ 0x3EF => 0x3EE,
+ 0x3F0 => 0x39A,
+ 0x3F1 => 0x3A1,
+ 0x3F2 => 0x3F9,
+ 0x3F3 => 0x37F,
+ 0x3F5 => 0x395,
+ 0x3F8 => 0x3F7,
+ 0x3FB => 0x3FA,
+ 0x430 => 0x410,
+ 0x431 => 0x411,
+ 0x432 => 0x412,
+ 0x433 => 0x413,
+ 0x434 => 0x414,
+ 0x435 => 0x415,
+ 0x436 => 0x416,
+ 0x437 => 0x417,
+ 0x438 => 0x418,
+ 0x439 => 0x419,
+ 0x43A => 0x41A,
+ 0x43B => 0x41B,
+ 0x43C => 0x41C,
+ 0x43D => 0x41D,
+ 0x43E => 0x41E,
+ 0x43F => 0x41F,
+ 0x440 => 0x420,
+ 0x441 => 0x421,
+ 0x442 => 0x422,
+ 0x443 => 0x423,
+ 0x444 => 0x424,
+ 0x445 => 0x425,
+ 0x446 => 0x426,
+ 0x447 => 0x427,
+ 0x448 => 0x428,
+ 0x449 => 0x429,
+ 0x44A => 0x42A,
+ 0x44B => 0x42B,
+ 0x44C => 0x42C,
+ 0x44D => 0x42D,
+ 0x44E => 0x42E,
+ 0x44F => 0x42F,
+ 0x450 => 0x400,
+ 0x451 => 0x401,
+ 0x452 => 0x402,
+ 0x453 => 0x403,
+ 0x454 => 0x404,
+ 0x455 => 0x405,
+ 0x456 => 0x406,
+ 0x457 => 0x407,
+ 0x458 => 0x408,
+ 0x459 => 0x409,
+ 0x45A => 0x40A,
+ 0x45B => 0x40B,
+ 0x45C => 0x40C,
+ 0x45D => 0x40D,
+ 0x45E => 0x40E,
+ 0x45F => 0x40F,
+ 0x461 => 0x460,
+ 0x463 => 0x462,
+ 0x465 => 0x464,
+ 0x467 => 0x466,
+ 0x469 => 0x468,
+ 0x46B => 0x46A,
+ 0x46D => 0x46C,
+ 0x46F => 0x46E,
+ 0x471 => 0x470,
+ 0x473 => 0x472,
+ 0x475 => 0x474,
+ 0x477 => 0x476,
+ 0x479 => 0x478,
+ 0x47B => 0x47A,
+ 0x47D => 0x47C,
+ 0x47F => 0x47E,
+ 0x481 => 0x480,
+ 0x48B => 0x48A,
+ 0x48D => 0x48C,
+ 0x48F => 0x48E,
+ 0x491 => 0x490,
+ 0x493 => 0x492,
+ 0x495 => 0x494,
+ 0x497 => 0x496,
+ 0x499 => 0x498,
+ 0x49B => 0x49A,
+ 0x49D => 0x49C,
+ 0x49F => 0x49E,
+ 0x4A1 => 0x4A0,
+ 0x4A3 => 0x4A2,
+ 0x4A5 => 0x4A4,
+ 0x4A7 => 0x4A6,
+ 0x4A9 => 0x4A8,
+ 0x4AB => 0x4AA,
+ 0x4AD => 0x4AC,
+ 0x4AF => 0x4AE,
+ 0x4B1 => 0x4B0,
+ 0x4B3 => 0x4B2,
+ 0x4B5 => 0x4B4,
+ 0x4B7 => 0x4B6,
+ 0x4B9 => 0x4B8,
+ 0x4BB => 0x4BA,
+ 0x4BD => 0x4BC,
+ 0x4BF => 0x4BE,
+ 0x4C2 => 0x4C1,
+ 0x4C4 => 0x4C3,
+ 0x4C6 => 0x4C5,
+ 0x4C8 => 0x4C7,
+ 0x4CA => 0x4C9,
+ 0x4CC => 0x4CB,
+ 0x4CE => 0x4CD,
+ 0x4CF => 0x4C0,
+ 0x4D1 => 0x4D0,
+ 0x4D3 => 0x4D2,
+ 0x4D5 => 0x4D4,
+ 0x4D7 => 0x4D6,
+ 0x4D9 => 0x4D8,
+ 0x4DB => 0x4DA,
+ 0x4DD => 0x4DC,
+ 0x4DF => 0x4DE,
+ 0x4E1 => 0x4E0,
+ 0x4E3 => 0x4E2,
+ 0x4E5 => 0x4E4,
+ 0x4E7 => 0x4E6,
+ 0x4E9 => 0x4E8,
+ 0x4EB => 0x4EA,
+ 0x4ED => 0x4EC,
+ 0x4EF => 0x4EE,
+ 0x4F1 => 0x4F0,
+ 0x4F3 => 0x4F2,
+ 0x4F5 => 0x4F4,
+ 0x4F7 => 0x4F6,
+ 0x4F9 => 0x4F8,
+ 0x4FB => 0x4FA,
+ 0x4FD => 0x4FC,
+ 0x4FF => 0x4FE,
+ 0x501 => 0x500,
+ 0x503 => 0x502,
+ 0x505 => 0x504,
+ 0x507 => 0x506,
+ 0x509 => 0x508,
+ 0x50B => 0x50A,
+ 0x50D => 0x50C,
+ 0x50F => 0x50E,
+ 0x511 => 0x510,
+ 0x513 => 0x512,
+ 0x515 => 0x514,
+ 0x517 => 0x516,
+ 0x519 => 0x518,
+ 0x51B => 0x51A,
+ 0x51D => 0x51C,
+ 0x51F => 0x51E,
+ 0x521 => 0x520,
+ 0x523 => 0x522,
+ 0x525 => 0x524,
+ 0x527 => 0x526,
+ 0x529 => 0x528,
+ 0x52B => 0x52A,
+ 0x52D => 0x52C,
+ 0x52F => 0x52E,
+ 0x561 => 0x531,
+ 0x562 => 0x532,
+ 0x563 => 0x533,
+ 0x564 => 0x534,
+ 0x565 => 0x535,
+ 0x566 => 0x536,
+ 0x567 => 0x537,
+ 0x568 => 0x538,
+ 0x569 => 0x539,
+ 0x56A => 0x53A,
+ 0x56B => 0x53B,
+ 0x56C => 0x53C,
+ 0x56D => 0x53D,
+ 0x56E => 0x53E,
+ 0x56F => 0x53F,
+ 0x570 => 0x540,
+ 0x571 => 0x541,
+ 0x572 => 0x542,
+ 0x573 => 0x543,
+ 0x574 => 0x544,
+ 0x575 => 0x545,
+ 0x576 => 0x546,
+ 0x577 => 0x547,
+ 0x578 => 0x548,
+ 0x579 => 0x549,
+ 0x57A => 0x54A,
+ 0x57B => 0x54B,
+ 0x57C => 0x54C,
+ 0x57D => 0x54D,
+ 0x57E => 0x54E,
+ 0x57F => 0x54F,
+ 0x580 => 0x550,
+ 0x581 => 0x551,
+ 0x582 => 0x552,
+ 0x583 => 0x553,
+ 0x584 => 0x554,
+ 0x585 => 0x555,
+ 0x586 => 0x556,
+ 0x10D0 => 0x1C90,
+ 0x10D1 => 0x1C91,
+ 0x10D2 => 0x1C92,
+ 0x10D3 => 0x1C93,
+ 0x10D4 => 0x1C94,
+ 0x10D5 => 0x1C95,
+ 0x10D6 => 0x1C96,
+ 0x10D7 => 0x1C97,
+ 0x10D8 => 0x1C98,
+ 0x10D9 => 0x1C99,
+ 0x10DA => 0x1C9A,
+ 0x10DB => 0x1C9B,
+ 0x10DC => 0x1C9C,
+ 0x10DD => 0x1C9D,
+ 0x10DE => 0x1C9E,
+ 0x10DF => 0x1C9F,
+ 0x10E0 => 0x1CA0,
+ 0x10E1 => 0x1CA1,
+ 0x10E2 => 0x1CA2,
+ 0x10E3 => 0x1CA3,
+ 0x10E4 => 0x1CA4,
+ 0x10E5 => 0x1CA5,
+ 0x10E6 => 0x1CA6,
+ 0x10E7 => 0x1CA7,
+ 0x10E8 => 0x1CA8,
+ 0x10E9 => 0x1CA9,
+ 0x10EA => 0x1CAA,
+ 0x10EB => 0x1CAB,
+ 0x10EC => 0x1CAC,
+ 0x10ED => 0x1CAD,
+ 0x10EE => 0x1CAE,
+ 0x10EF => 0x1CAF,
+ 0x10F0 => 0x1CB0,
+ 0x10F1 => 0x1CB1,
+ 0x10F2 => 0x1CB2,
+ 0x10F3 => 0x1CB3,
+ 0x10F4 => 0x1CB4,
+ 0x10F5 => 0x1CB5,
+ 0x10F6 => 0x1CB6,
+ 0x10F7 => 0x1CB7,
+ 0x10F8 => 0x1CB8,
+ 0x10F9 => 0x1CB9,
+ 0x10FA => 0x1CBA,
+ 0x10FD => 0x1CBD,
+ 0x10FE => 0x1CBE,
+ 0x10FF => 0x1CBF,
+ 0x13F8 => 0x13F0,
+ 0x13F9 => 0x13F1,
+ 0x13FA => 0x13F2,
+ 0x13FB => 0x13F3,
+ 0x13FC => 0x13F4,
+ 0x13FD => 0x13F5,
+ 0x1C80 => 0x412,
+ 0x1C81 => 0x414,
+ 0x1C82 => 0x41E,
+ 0x1C83 => 0x421,
+ 0x1C84 => 0x422,
+ 0x1C85 => 0x422,
+ 0x1C86 => 0x42A,
+ 0x1C87 => 0x462,
+ 0x1C88 => 0xA64A,
+ 0x1D79 => 0xA77D,
+ 0x1D7D => 0x2C63,
+ 0x1D8E => 0xA7C6,
+ 0x1E01 => 0x1E00,
+ 0x1E03 => 0x1E02,
+ 0x1E05 => 0x1E04,
+ 0x1E07 => 0x1E06,
+ 0x1E09 => 0x1E08,
+ 0x1E0B => 0x1E0A,
+ 0x1E0D => 0x1E0C,
+ 0x1E0F => 0x1E0E,
+ 0x1E11 => 0x1E10,
+ 0x1E13 => 0x1E12,
+ 0x1E15 => 0x1E14,
+ 0x1E17 => 0x1E16,
+ 0x1E19 => 0x1E18,
+ 0x1E1B => 0x1E1A,
+ 0x1E1D => 0x1E1C,
+ 0x1E1F => 0x1E1E,
+ 0x1E21 => 0x1E20,
+ 0x1E23 => 0x1E22,
+ 0x1E25 => 0x1E24,
+ 0x1E27 => 0x1E26,
+ 0x1E29 => 0x1E28,
+ 0x1E2B => 0x1E2A,
+ 0x1E2D => 0x1E2C,
+ 0x1E2F => 0x1E2E,
+ 0x1E31 => 0x1E30,
+ 0x1E33 => 0x1E32,
+ 0x1E35 => 0x1E34,
+ 0x1E37 => 0x1E36,
+ 0x1E39 => 0x1E38,
+ 0x1E3B => 0x1E3A,
+ 0x1E3D => 0x1E3C,
+ 0x1E3F => 0x1E3E,
+ 0x1E41 => 0x1E40,
+ 0x1E43 => 0x1E42,
+ 0x1E45 => 0x1E44,
+ 0x1E47 => 0x1E46,
+ 0x1E49 => 0x1E48,
+ 0x1E4B => 0x1E4A,
+ 0x1E4D => 0x1E4C,
+ 0x1E4F => 0x1E4E,
+ 0x1E51 => 0x1E50,
+ 0x1E53 => 0x1E52,
+ 0x1E55 => 0x1E54,
+ 0x1E57 => 0x1E56,
+ 0x1E59 => 0x1E58,
+ 0x1E5B => 0x1E5A,
+ 0x1E5D => 0x1E5C,
+ 0x1E5F => 0x1E5E,
+ 0x1E61 => 0x1E60,
+ 0x1E63 => 0x1E62,
+ 0x1E65 => 0x1E64,
+ 0x1E67 => 0x1E66,
+ 0x1E69 => 0x1E68,
+ 0x1E6B => 0x1E6A,
+ 0x1E6D => 0x1E6C,
+ 0x1E6F => 0x1E6E,
+ 0x1E71 => 0x1E70,
+ 0x1E73 => 0x1E72,
+ 0x1E75 => 0x1E74,
+ 0x1E77 => 0x1E76,
+ 0x1E79 => 0x1E78,
+ 0x1E7B => 0x1E7A,
+ 0x1E7D => 0x1E7C,
+ 0x1E7F => 0x1E7E,
+ 0x1E81 => 0x1E80,
+ 0x1E83 => 0x1E82,
+ 0x1E85 => 0x1E84,
+ 0x1E87 => 0x1E86,
+ 0x1E89 => 0x1E88,
+ 0x1E8B => 0x1E8A,
+ 0x1E8D => 0x1E8C,
+ 0x1E8F => 0x1E8E,
+ 0x1E91 => 0x1E90,
+ 0x1E93 => 0x1E92,
+ 0x1E95 => 0x1E94,
+ 0x1E9B => 0x1E60,
+ 0x1EA1 => 0x1EA0,
+ 0x1EA3 => 0x1EA2,
+ 0x1EA5 => 0x1EA4,
+ 0x1EA7 => 0x1EA6,
+ 0x1EA9 => 0x1EA8,
+ 0x1EAB => 0x1EAA,
+ 0x1EAD => 0x1EAC,
+ 0x1EAF => 0x1EAE,
+ 0x1EB1 => 0x1EB0,
+ 0x1EB3 => 0x1EB2,
+ 0x1EB5 => 0x1EB4,
+ 0x1EB7 => 0x1EB6,
+ 0x1EB9 => 0x1EB8,
+ 0x1EBB => 0x1EBA,
+ 0x1EBD => 0x1EBC,
+ 0x1EBF => 0x1EBE,
+ 0x1EC1 => 0x1EC0,
+ 0x1EC3 => 0x1EC2,
+ 0x1EC5 => 0x1EC4,
+ 0x1EC7 => 0x1EC6,
+ 0x1EC9 => 0x1EC8,
+ 0x1ECB => 0x1ECA,
+ 0x1ECD => 0x1ECC,
+ 0x1ECF => 0x1ECE,
+ 0x1ED1 => 0x1ED0,
+ 0x1ED3 => 0x1ED2,
+ 0x1ED5 => 0x1ED4,
+ 0x1ED7 => 0x1ED6,
+ 0x1ED9 => 0x1ED8,
+ 0x1EDB => 0x1EDA,
+ 0x1EDD => 0x1EDC,
+ 0x1EDF => 0x1EDE,
+ 0x1EE1 => 0x1EE0,
+ 0x1EE3 => 0x1EE2,
+ 0x1EE5 => 0x1EE4,
+ 0x1EE7 => 0x1EE6,
+ 0x1EE9 => 0x1EE8,
+ 0x1EEB => 0x1EEA,
+ 0x1EED => 0x1EEC,
+ 0x1EEF => 0x1EEE,
+ 0x1EF1 => 0x1EF0,
+ 0x1EF3 => 0x1EF2,
+ 0x1EF5 => 0x1EF4,
+ 0x1EF7 => 0x1EF6,
+ 0x1EF9 => 0x1EF8,
+ 0x1EFB => 0x1EFA,
+ 0x1EFD => 0x1EFC,
+ 0x1EFF => 0x1EFE,
+ 0x1F00 => 0x1F08,
+ 0x1F01 => 0x1F09,
+ 0x1F02 => 0x1F0A,
+ 0x1F03 => 0x1F0B,
+ 0x1F04 => 0x1F0C,
+ 0x1F05 => 0x1F0D,
+ 0x1F06 => 0x1F0E,
+ 0x1F07 => 0x1F0F,
+ 0x1F10 => 0x1F18,
+ 0x1F11 => 0x1F19,
+ 0x1F12 => 0x1F1A,
+ 0x1F13 => 0x1F1B,
+ 0x1F14 => 0x1F1C,
+ 0x1F15 => 0x1F1D,
+ 0x1F20 => 0x1F28,
+ 0x1F21 => 0x1F29,
+ 0x1F22 => 0x1F2A,
+ 0x1F23 => 0x1F2B,
+ 0x1F24 => 0x1F2C,
+ 0x1F25 => 0x1F2D,
+ 0x1F26 => 0x1F2E,
+ 0x1F27 => 0x1F2F,
+ 0x1F30 => 0x1F38,
+ 0x1F31 => 0x1F39,
+ 0x1F32 => 0x1F3A,
+ 0x1F33 => 0x1F3B,
+ 0x1F34 => 0x1F3C,
+ 0x1F35 => 0x1F3D,
+ 0x1F36 => 0x1F3E,
+ 0x1F37 => 0x1F3F,
+ 0x1F40 => 0x1F48,
+ 0x1F41 => 0x1F49,
+ 0x1F42 => 0x1F4A,
+ 0x1F43 => 0x1F4B,
+ 0x1F44 => 0x1F4C,
+ 0x1F45 => 0x1F4D,
+ 0x1F51 => 0x1F59,
+ 0x1F53 => 0x1F5B,
+ 0x1F55 => 0x1F5D,
+ 0x1F57 => 0x1F5F,
+ 0x1F60 => 0x1F68,
+ 0x1F61 => 0x1F69,
+ 0x1F62 => 0x1F6A,
+ 0x1F63 => 0x1F6B,
+ 0x1F64 => 0x1F6C,
+ 0x1F65 => 0x1F6D,
+ 0x1F66 => 0x1F6E,
+ 0x1F67 => 0x1F6F,
+ 0x1F70 => 0x1FBA,
+ 0x1F71 => 0x1FBB,
+ 0x1F72 => 0x1FC8,
+ 0x1F73 => 0x1FC9,
+ 0x1F74 => 0x1FCA,
+ 0x1F75 => 0x1FCB,
+ 0x1F76 => 0x1FDA,
+ 0x1F77 => 0x1FDB,
+ 0x1F78 => 0x1FF8,
+ 0x1F79 => 0x1FF9,
+ 0x1F7A => 0x1FEA,
+ 0x1F7B => 0x1FEB,
+ 0x1F7C => 0x1FFA,
+ 0x1F7D => 0x1FFB,
+ 0x1F80 => 0x1F88,
+ 0x1F81 => 0x1F89,
+ 0x1F82 => 0x1F8A,
+ 0x1F83 => 0x1F8B,
+ 0x1F84 => 0x1F8C,
+ 0x1F85 => 0x1F8D,
+ 0x1F86 => 0x1F8E,
+ 0x1F87 => 0x1F8F,
+ 0x1F90 => 0x1F98,
+ 0x1F91 => 0x1F99,
+ 0x1F92 => 0x1F9A,
+ 0x1F93 => 0x1F9B,
+ 0x1F94 => 0x1F9C,
+ 0x1F95 => 0x1F9D,
+ 0x1F96 => 0x1F9E,
+ 0x1F97 => 0x1F9F,
+ 0x1FA0 => 0x1FA8,
+ 0x1FA1 => 0x1FA9,
+ 0x1FA2 => 0x1FAA,
+ 0x1FA3 => 0x1FAB,
+ 0x1FA4 => 0x1FAC,
+ 0x1FA5 => 0x1FAD,
+ 0x1FA6 => 0x1FAE,
+ 0x1FA7 => 0x1FAF,
+ 0x1FB0 => 0x1FB8,
+ 0x1FB1 => 0x1FB9,
+ 0x1FB3 => 0x1FBC,
+ 0x1FBE => 0x399,
+ 0x1FC3 => 0x1FCC,
+ 0x1FD0 => 0x1FD8,
+ 0x1FD1 => 0x1FD9,
+ 0x1FE0 => 0x1FE8,
+ 0x1FE1 => 0x1FE9,
+ 0x1FE5 => 0x1FEC,
+ 0x1FF3 => 0x1FFC,
+ 0x214E => 0x2132,
+ 0x2170 => 0x2160,
+ 0x2171 => 0x2161,
+ 0x2172 => 0x2162,
+ 0x2173 => 0x2163,
+ 0x2174 => 0x2164,
+ 0x2175 => 0x2165,
+ 0x2176 => 0x2166,
+ 0x2177 => 0x2167,
+ 0x2178 => 0x2168,
+ 0x2179 => 0x2169,
+ 0x217A => 0x216A,
+ 0x217B => 0x216B,
+ 0x217C => 0x216C,
+ 0x217D => 0x216D,
+ 0x217E => 0x216E,
+ 0x217F => 0x216F,
+ 0x2184 => 0x2183,
+ 0x24D0 => 0x24B6,
+ 0x24D1 => 0x24B7,
+ 0x24D2 => 0x24B8,
+ 0x24D3 => 0x24B9,
+ 0x24D4 => 0x24BA,
+ 0x24D5 => 0x24BB,
+ 0x24D6 => 0x24BC,
+ 0x24D7 => 0x24BD,
+ 0x24D8 => 0x24BE,
+ 0x24D9 => 0x24BF,
+ 0x24DA => 0x24C0,
+ 0x24DB => 0x24C1,
+ 0x24DC => 0x24C2,
+ 0x24DD => 0x24C3,
+ 0x24DE => 0x24C4,
+ 0x24DF => 0x24C5,
+ 0x24E0 => 0x24C6,
+ 0x24E1 => 0x24C7,
+ 0x24E2 => 0x24C8,
+ 0x24E3 => 0x24C9,
+ 0x24E4 => 0x24CA,
+ 0x24E5 => 0x24CB,
+ 0x24E6 => 0x24CC,
+ 0x24E7 => 0x24CD,
+ 0x24E8 => 0x24CE,
+ 0x24E9 => 0x24CF,
+ 0x2C30 => 0x2C00,
+ 0x2C31 => 0x2C01,
+ 0x2C32 => 0x2C02,
+ 0x2C33 => 0x2C03,
+ 0x2C34 => 0x2C04,
+ 0x2C35 => 0x2C05,
+ 0x2C36 => 0x2C06,
+ 0x2C37 => 0x2C07,
+ 0x2C38 => 0x2C08,
+ 0x2C39 => 0x2C09,
+ 0x2C3A => 0x2C0A,
+ 0x2C3B => 0x2C0B,
+ 0x2C3C => 0x2C0C,
+ 0x2C3D => 0x2C0D,
+ 0x2C3E => 0x2C0E,
+ 0x2C3F => 0x2C0F,
+ 0x2C40 => 0x2C10,
+ 0x2C41 => 0x2C11,
+ 0x2C42 => 0x2C12,
+ 0x2C43 => 0x2C13,
+ 0x2C44 => 0x2C14,
+ 0x2C45 => 0x2C15,
+ 0x2C46 => 0x2C16,
+ 0x2C47 => 0x2C17,
+ 0x2C48 => 0x2C18,
+ 0x2C49 => 0x2C19,
+ 0x2C4A => 0x2C1A,
+ 0x2C4B => 0x2C1B,
+ 0x2C4C => 0x2C1C,
+ 0x2C4D => 0x2C1D,
+ 0x2C4E => 0x2C1E,
+ 0x2C4F => 0x2C1F,
+ 0x2C50 => 0x2C20,
+ 0x2C51 => 0x2C21,
+ 0x2C52 => 0x2C22,
+ 0x2C53 => 0x2C23,
+ 0x2C54 => 0x2C24,
+ 0x2C55 => 0x2C25,
+ 0x2C56 => 0x2C26,
+ 0x2C57 => 0x2C27,
+ 0x2C58 => 0x2C28,
+ 0x2C59 => 0x2C29,
+ 0x2C5A => 0x2C2A,
+ 0x2C5B => 0x2C2B,
+ 0x2C5C => 0x2C2C,
+ 0x2C5D => 0x2C2D,
+ 0x2C5E => 0x2C2E,
+ 0x2C5F => 0x2C2F,
+ 0x2C61 => 0x2C60,
+ 0x2C65 => 0x23A,
+ 0x2C66 => 0x23E,
+ 0x2C68 => 0x2C67,
+ 0x2C6A => 0x2C69,
+ 0x2C6C => 0x2C6B,
+ 0x2C73 => 0x2C72,
+ 0x2C76 => 0x2C75,
+ 0x2C81 => 0x2C80,
+ 0x2C83 => 0x2C82,
+ 0x2C85 => 0x2C84,
+ 0x2C87 => 0x2C86,
+ 0x2C89 => 0x2C88,
+ 0x2C8B => 0x2C8A,
+ 0x2C8D => 0x2C8C,
+ 0x2C8F => 0x2C8E,
+ 0x2C91 => 0x2C90,
+ 0x2C93 => 0x2C92,
+ 0x2C95 => 0x2C94,
+ 0x2C97 => 0x2C96,
+ 0x2C99 => 0x2C98,
+ 0x2C9B => 0x2C9A,
+ 0x2C9D => 0x2C9C,
+ 0x2C9F => 0x2C9E,
+ 0x2CA1 => 0x2CA0,
+ 0x2CA3 => 0x2CA2,
+ 0x2CA5 => 0x2CA4,
+ 0x2CA7 => 0x2CA6,
+ 0x2CA9 => 0x2CA8,
+ 0x2CAB => 0x2CAA,
+ 0x2CAD => 0x2CAC,
+ 0x2CAF => 0x2CAE,
+ 0x2CB1 => 0x2CB0,
+ 0x2CB3 => 0x2CB2,
+ 0x2CB5 => 0x2CB4,
+ 0x2CB7 => 0x2CB6,
+ 0x2CB9 => 0x2CB8,
+ 0x2CBB => 0x2CBA,
+ 0x2CBD => 0x2CBC,
+ 0x2CBF => 0x2CBE,
+ 0x2CC1 => 0x2CC0,
+ 0x2CC3 => 0x2CC2,
+ 0x2CC5 => 0x2CC4,
+ 0x2CC7 => 0x2CC6,
+ 0x2CC9 => 0x2CC8,
+ 0x2CCB => 0x2CCA,
+ 0x2CCD => 0x2CCC,
+ 0x2CCF => 0x2CCE,
+ 0x2CD1 => 0x2CD0,
+ 0x2CD3 => 0x2CD2,
+ 0x2CD5 => 0x2CD4,
+ 0x2CD7 => 0x2CD6,
+ 0x2CD9 => 0x2CD8,
+ 0x2CDB => 0x2CDA,
+ 0x2CDD => 0x2CDC,
+ 0x2CDF => 0x2CDE,
+ 0x2CE1 => 0x2CE0,
+ 0x2CE3 => 0x2CE2,
+ 0x2CEC => 0x2CEB,
+ 0x2CEE => 0x2CED,
+ 0x2CF3 => 0x2CF2,
+ 0x2D00 => 0x10A0,
+ 0x2D01 => 0x10A1,
+ 0x2D02 => 0x10A2,
+ 0x2D03 => 0x10A3,
+ 0x2D04 => 0x10A4,
+ 0x2D05 => 0x10A5,
+ 0x2D06 => 0x10A6,
+ 0x2D07 => 0x10A7,
+ 0x2D08 => 0x10A8,
+ 0x2D09 => 0x10A9,
+ 0x2D0A => 0x10AA,
+ 0x2D0B => 0x10AB,
+ 0x2D0C => 0x10AC,
+ 0x2D0D => 0x10AD,
+ 0x2D0E => 0x10AE,
+ 0x2D0F => 0x10AF,
+ 0x2D10 => 0x10B0,
+ 0x2D11 => 0x10B1,
+ 0x2D12 => 0x10B2,
+ 0x2D13 => 0x10B3,
+ 0x2D14 => 0x10B4,
+ 0x2D15 => 0x10B5,
+ 0x2D16 => 0x10B6,
+ 0x2D17 => 0x10B7,
+ 0x2D18 => 0x10B8,
+ 0x2D19 => 0x10B9,
+ 0x2D1A => 0x10BA,
+ 0x2D1B => 0x10BB,
+ 0x2D1C => 0x10BC,
+ 0x2D1D => 0x10BD,
+ 0x2D1E => 0x10BE,
+ 0x2D1F => 0x10BF,
+ 0x2D20 => 0x10C0,
+ 0x2D21 => 0x10C1,
+ 0x2D22 => 0x10C2,
+ 0x2D23 => 0x10C3,
+ 0x2D24 => 0x10C4,
+ 0x2D25 => 0x10C5,
+ 0x2D27 => 0x10C7,
+ 0x2D2D => 0x10CD,
+ 0xA641 => 0xA640,
+ 0xA643 => 0xA642,
+ 0xA645 => 0xA644,
+ 0xA647 => 0xA646,
+ 0xA649 => 0xA648,
+ 0xA64B => 0xA64A,
+ 0xA64D => 0xA64C,
+ 0xA64F => 0xA64E,
+ 0xA651 => 0xA650,
+ 0xA653 => 0xA652,
+ 0xA655 => 0xA654,
+ 0xA657 => 0xA656,
+ 0xA659 => 0xA658,
+ 0xA65B => 0xA65A,
+ 0xA65D => 0xA65C,
+ 0xA65F => 0xA65E,
+ 0xA661 => 0xA660,
+ 0xA663 => 0xA662,
+ 0xA665 => 0xA664,
+ 0xA667 => 0xA666,
+ 0xA669 => 0xA668,
+ 0xA66B => 0xA66A,
+ 0xA66D => 0xA66C,
+ 0xA681 => 0xA680,
+ 0xA683 => 0xA682,
+ 0xA685 => 0xA684,
+ 0xA687 => 0xA686,
+ 0xA689 => 0xA688,
+ 0xA68B => 0xA68A,
+ 0xA68D => 0xA68C,
+ 0xA68F => 0xA68E,
+ 0xA691 => 0xA690,
+ 0xA693 => 0xA692,
+ 0xA695 => 0xA694,
+ 0xA697 => 0xA696,
+ 0xA699 => 0xA698,
+ 0xA69B => 0xA69A,
+ 0xA723 => 0xA722,
+ 0xA725 => 0xA724,
+ 0xA727 => 0xA726,
+ 0xA729 => 0xA728,
+ 0xA72B => 0xA72A,
+ 0xA72D => 0xA72C,
+ 0xA72F => 0xA72E,
+ 0xA733 => 0xA732,
+ 0xA735 => 0xA734,
+ 0xA737 => 0xA736,
+ 0xA739 => 0xA738,
+ 0xA73B => 0xA73A,
+ 0xA73D => 0xA73C,
+ 0xA73F => 0xA73E,
+ 0xA741 => 0xA740,
+ 0xA743 => 0xA742,
+ 0xA745 => 0xA744,
+ 0xA747 => 0xA746,
+ 0xA749 => 0xA748,
+ 0xA74B => 0xA74A,
+ 0xA74D => 0xA74C,
+ 0xA74F => 0xA74E,
+ 0xA751 => 0xA750,
+ 0xA753 => 0xA752,
+ 0xA755 => 0xA754,
+ 0xA757 => 0xA756,
+ 0xA759 => 0xA758,
+ 0xA75B => 0xA75A,
+ 0xA75D => 0xA75C,
+ 0xA75F => 0xA75E,
+ 0xA761 => 0xA760,
+ 0xA763 => 0xA762,
+ 0xA765 => 0xA764,
+ 0xA767 => 0xA766,
+ 0xA769 => 0xA768,
+ 0xA76B => 0xA76A,
+ 0xA76D => 0xA76C,
+ 0xA76F => 0xA76E,
+ 0xA77A => 0xA779,
+ 0xA77C => 0xA77B,
+ 0xA77F => 0xA77E,
+ 0xA781 => 0xA780,
+ 0xA783 => 0xA782,
+ 0xA785 => 0xA784,
+ 0xA787 => 0xA786,
+ 0xA78C => 0xA78B,
+ 0xA791 => 0xA790,
+ 0xA793 => 0xA792,
+ 0xA794 => 0xA7C4,
+ 0xA797 => 0xA796,
+ 0xA799 => 0xA798,
+ 0xA79B => 0xA79A,
+ 0xA79D => 0xA79C,
+ 0xA79F => 0xA79E,
+ 0xA7A1 => 0xA7A0,
+ 0xA7A3 => 0xA7A2,
+ 0xA7A5 => 0xA7A4,
+ 0xA7A7 => 0xA7A6,
+ 0xA7A9 => 0xA7A8,
+ 0xA7B5 => 0xA7B4,
+ 0xA7B7 => 0xA7B6,
+ 0xA7B9 => 0xA7B8,
+ 0xA7BB => 0xA7BA,
+ 0xA7BD => 0xA7BC,
+ 0xA7BF => 0xA7BE,
+ 0xA7C1 => 0xA7C0,
+ 0xA7C3 => 0xA7C2,
+ 0xA7C8 => 0xA7C7,
+ 0xA7CA => 0xA7C9,
+ 0xA7D1 => 0xA7D0,
+ 0xA7D7 => 0xA7D6,
+ 0xA7D9 => 0xA7D8,
+ 0xA7F6 => 0xA7F5,
+ 0xAB53 => 0xA7B3,
+ 0xAB70 => 0x13A0,
+ 0xAB71 => 0x13A1,
+ 0xAB72 => 0x13A2,
+ 0xAB73 => 0x13A3,
+ 0xAB74 => 0x13A4,
+ 0xAB75 => 0x13A5,
+ 0xAB76 => 0x13A6,
+ 0xAB77 => 0x13A7,
+ 0xAB78 => 0x13A8,
+ 0xAB79 => 0x13A9,
+ 0xAB7A => 0x13AA,
+ 0xAB7B => 0x13AB,
+ 0xAB7C => 0x13AC,
+ 0xAB7D => 0x13AD,
+ 0xAB7E => 0x13AE,
+ 0xAB7F => 0x13AF,
+ 0xAB80 => 0x13B0,
+ 0xAB81 => 0x13B1,
+ 0xAB82 => 0x13B2,
+ 0xAB83 => 0x13B3,
+ 0xAB84 => 0x13B4,
+ 0xAB85 => 0x13B5,
+ 0xAB86 => 0x13B6,
+ 0xAB87 => 0x13B7,
+ 0xAB88 => 0x13B8,
+ 0xAB89 => 0x13B9,
+ 0xAB8A => 0x13BA,
+ 0xAB8B => 0x13BB,
+ 0xAB8C => 0x13BC,
+ 0xAB8D => 0x13BD,
+ 0xAB8E => 0x13BE,
+ 0xAB8F => 0x13BF,
+ 0xAB90 => 0x13C0,
+ 0xAB91 => 0x13C1,
+ 0xAB92 => 0x13C2,
+ 0xAB93 => 0x13C3,
+ 0xAB94 => 0x13C4,
+ 0xAB95 => 0x13C5,
+ 0xAB96 => 0x13C6,
+ 0xAB97 => 0x13C7,
+ 0xAB98 => 0x13C8,
+ 0xAB99 => 0x13C9,
+ 0xAB9A => 0x13CA,
+ 0xAB9B => 0x13CB,
+ 0xAB9C => 0x13CC,
+ 0xAB9D => 0x13CD,
+ 0xAB9E => 0x13CE,
+ 0xAB9F => 0x13CF,
+ 0xABA0 => 0x13D0,
+ 0xABA1 => 0x13D1,
+ 0xABA2 => 0x13D2,
+ 0xABA3 => 0x13D3,
+ 0xABA4 => 0x13D4,
+ 0xABA5 => 0x13D5,
+ 0xABA6 => 0x13D6,
+ 0xABA7 => 0x13D7,
+ 0xABA8 => 0x13D8,
+ 0xABA9 => 0x13D9,
+ 0xABAA => 0x13DA,
+ 0xABAB => 0x13DB,
+ 0xABAC => 0x13DC,
+ 0xABAD => 0x13DD,
+ 0xABAE => 0x13DE,
+ 0xABAF => 0x13DF,
+ 0xABB0 => 0x13E0,
+ 0xABB1 => 0x13E1,
+ 0xABB2 => 0x13E2,
+ 0xABB3 => 0x13E3,
+ 0xABB4 => 0x13E4,
+ 0xABB5 => 0x13E5,
+ 0xABB6 => 0x13E6,
+ 0xABB7 => 0x13E7,
+ 0xABB8 => 0x13E8,
+ 0xABB9 => 0x13E9,
+ 0xABBA => 0x13EA,
+ 0xABBB => 0x13EB,
+ 0xABBC => 0x13EC,
+ 0xABBD => 0x13ED,
+ 0xABBE => 0x13EE,
+ 0xABBF => 0x13EF,
+ 0xFF41 => 0xFF21,
+ 0xFF42 => 0xFF22,
+ 0xFF43 => 0xFF23,
+ 0xFF44 => 0xFF24,
+ 0xFF45 => 0xFF25,
+ 0xFF46 => 0xFF26,
+ 0xFF47 => 0xFF27,
+ 0xFF48 => 0xFF28,
+ 0xFF49 => 0xFF29,
+ 0xFF4A => 0xFF2A,
+ 0xFF4B => 0xFF2B,
+ 0xFF4C => 0xFF2C,
+ 0xFF4D => 0xFF2D,
+ 0xFF4E => 0xFF2E,
+ 0xFF4F => 0xFF2F,
+ 0xFF50 => 0xFF30,
+ 0xFF51 => 0xFF31,
+ 0xFF52 => 0xFF32,
+ 0xFF53 => 0xFF33,
+ 0xFF54 => 0xFF34,
+ 0xFF55 => 0xFF35,
+ 0xFF56 => 0xFF36,
+ 0xFF57 => 0xFF37,
+ 0xFF58 => 0xFF38,
+ 0xFF59 => 0xFF39,
+ 0xFF5A => 0xFF3A,
+ 0x10428 => 0x10400,
+ 0x10429 => 0x10401,
+ 0x1042A => 0x10402,
+ 0x1042B => 0x10403,
+ 0x1042C => 0x10404,
+ 0x1042D => 0x10405,
+ 0x1042E => 0x10406,
+ 0x1042F => 0x10407,
+ 0x10430 => 0x10408,
+ 0x10431 => 0x10409,
+ 0x10432 => 0x1040A,
+ 0x10433 => 0x1040B,
+ 0x10434 => 0x1040C,
+ 0x10435 => 0x1040D,
+ 0x10436 => 0x1040E,
+ 0x10437 => 0x1040F,
+ 0x10438 => 0x10410,
+ 0x10439 => 0x10411,
+ 0x1043A => 0x10412,
+ 0x1043B => 0x10413,
+ 0x1043C => 0x10414,
+ 0x1043D => 0x10415,
+ 0x1043E => 0x10416,
+ 0x1043F => 0x10417,
+ 0x10440 => 0x10418,
+ 0x10441 => 0x10419,
+ 0x10442 => 0x1041A,
+ 0x10443 => 0x1041B,
+ 0x10444 => 0x1041C,
+ 0x10445 => 0x1041D,
+ 0x10446 => 0x1041E,
+ 0x10447 => 0x1041F,
+ 0x10448 => 0x10420,
+ 0x10449 => 0x10421,
+ 0x1044A => 0x10422,
+ 0x1044B => 0x10423,
+ 0x1044C => 0x10424,
+ 0x1044D => 0x10425,
+ 0x1044E => 0x10426,
+ 0x1044F => 0x10427,
+ 0x104D8 => 0x104B0,
+ 0x104D9 => 0x104B1,
+ 0x104DA => 0x104B2,
+ 0x104DB => 0x104B3,
+ 0x104DC => 0x104B4,
+ 0x104DD => 0x104B5,
+ 0x104DE => 0x104B6,
+ 0x104DF => 0x104B7,
+ 0x104E0 => 0x104B8,
+ 0x104E1 => 0x104B9,
+ 0x104E2 => 0x104BA,
+ 0x104E3 => 0x104BB,
+ 0x104E4 => 0x104BC,
+ 0x104E5 => 0x104BD,
+ 0x104E6 => 0x104BE,
+ 0x104E7 => 0x104BF,
+ 0x104E8 => 0x104C0,
+ 0x104E9 => 0x104C1,
+ 0x104EA => 0x104C2,
+ 0x104EB => 0x104C3,
+ 0x104EC => 0x104C4,
+ 0x104ED => 0x104C5,
+ 0x104EE => 0x104C6,
+ 0x104EF => 0x104C7,
+ 0x104F0 => 0x104C8,
+ 0x104F1 => 0x104C9,
+ 0x104F2 => 0x104CA,
+ 0x104F3 => 0x104CB,
+ 0x104F4 => 0x104CC,
+ 0x104F5 => 0x104CD,
+ 0x104F6 => 0x104CE,
+ 0x104F7 => 0x104CF,
+ 0x104F8 => 0x104D0,
+ 0x104F9 => 0x104D1,
+ 0x104FA => 0x104D2,
+ 0x104FB => 0x104D3,
+ 0x10597 => 0x10570,
+ 0x10598 => 0x10571,
+ 0x10599 => 0x10572,
+ 0x1059A => 0x10573,
+ 0x1059B => 0x10574,
+ 0x1059C => 0x10575,
+ 0x1059D => 0x10576,
+ 0x1059E => 0x10577,
+ 0x1059F => 0x10578,
+ 0x105A0 => 0x10579,
+ 0x105A1 => 0x1057A,
+ 0x105A3 => 0x1057C,
+ 0x105A4 => 0x1057D,
+ 0x105A5 => 0x1057E,
+ 0x105A6 => 0x1057F,
+ 0x105A7 => 0x10580,
+ 0x105A8 => 0x10581,
+ 0x105A9 => 0x10582,
+ 0x105AA => 0x10583,
+ 0x105AB => 0x10584,
+ 0x105AC => 0x10585,
+ 0x105AD => 0x10586,
+ 0x105AE => 0x10587,
+ 0x105AF => 0x10588,
+ 0x105B0 => 0x10589,
+ 0x105B1 => 0x1058A,
+ 0x105B3 => 0x1058C,
+ 0x105B4 => 0x1058D,
+ 0x105B5 => 0x1058E,
+ 0x105B6 => 0x1058F,
+ 0x105B7 => 0x10590,
+ 0x105B8 => 0x10591,
+ 0x105B9 => 0x10592,
+ 0x105BB => 0x10594,
+ 0x105BC => 0x10595,
+ 0x10CC0 => 0x10C80,
+ 0x10CC1 => 0x10C81,
+ 0x10CC2 => 0x10C82,
+ 0x10CC3 => 0x10C83,
+ 0x10CC4 => 0x10C84,
+ 0x10CC5 => 0x10C85,
+ 0x10CC6 => 0x10C86,
+ 0x10CC7 => 0x10C87,
+ 0x10CC8 => 0x10C88,
+ 0x10CC9 => 0x10C89,
+ 0x10CCA => 0x10C8A,
+ 0x10CCB => 0x10C8B,
+ 0x10CCC => 0x10C8C,
+ 0x10CCD => 0x10C8D,
+ 0x10CCE => 0x10C8E,
+ 0x10CCF => 0x10C8F,
+ 0x10CD0 => 0x10C90,
+ 0x10CD1 => 0x10C91,
+ 0x10CD2 => 0x10C92,
+ 0x10CD3 => 0x10C93,
+ 0x10CD4 => 0x10C94,
+ 0x10CD5 => 0x10C95,
+ 0x10CD6 => 0x10C96,
+ 0x10CD7 => 0x10C97,
+ 0x10CD8 => 0x10C98,
+ 0x10CD9 => 0x10C99,
+ 0x10CDA => 0x10C9A,
+ 0x10CDB => 0x10C9B,
+ 0x10CDC => 0x10C9C,
+ 0x10CDD => 0x10C9D,
+ 0x10CDE => 0x10C9E,
+ 0x10CDF => 0x10C9F,
+ 0x10CE0 => 0x10CA0,
+ 0x10CE1 => 0x10CA1,
+ 0x10CE2 => 0x10CA2,
+ 0x10CE3 => 0x10CA3,
+ 0x10CE4 => 0x10CA4,
+ 0x10CE5 => 0x10CA5,
+ 0x10CE6 => 0x10CA6,
+ 0x10CE7 => 0x10CA7,
+ 0x10CE8 => 0x10CA8,
+ 0x10CE9 => 0x10CA9,
+ 0x10CEA => 0x10CAA,
+ 0x10CEB => 0x10CAB,
+ 0x10CEC => 0x10CAC,
+ 0x10CED => 0x10CAD,
+ 0x10CEE => 0x10CAE,
+ 0x10CEF => 0x10CAF,
+ 0x10CF0 => 0x10CB0,
+ 0x10CF1 => 0x10CB1,
+ 0x10CF2 => 0x10CB2,
+ 0x118C0 => 0x118A0,
+ 0x118C1 => 0x118A1,
+ 0x118C2 => 0x118A2,
+ 0x118C3 => 0x118A3,
+ 0x118C4 => 0x118A4,
+ 0x118C5 => 0x118A5,
+ 0x118C6 => 0x118A6,
+ 0x118C7 => 0x118A7,
+ 0x118C8 => 0x118A8,
+ 0x118C9 => 0x118A9,
+ 0x118CA => 0x118AA,
+ 0x118CB => 0x118AB,
+ 0x118CC => 0x118AC,
+ 0x118CD => 0x118AD,
+ 0x118CE => 0x118AE,
+ 0x118CF => 0x118AF,
+ 0x118D0 => 0x118B0,
+ 0x118D1 => 0x118B1,
+ 0x118D2 => 0x118B2,
+ 0x118D3 => 0x118B3,
+ 0x118D4 => 0x118B4,
+ 0x118D5 => 0x118B5,
+ 0x118D6 => 0x118B6,
+ 0x118D7 => 0x118B7,
+ 0x118D8 => 0x118B8,
+ 0x118D9 => 0x118B9,
+ 0x118DA => 0x118BA,
+ 0x118DB => 0x118BB,
+ 0x118DC => 0x118BC,
+ 0x118DD => 0x118BD,
+ 0x118DE => 0x118BE,
+ 0x118DF => 0x118BF,
+ 0x16E60 => 0x16E40,
+ 0x16E61 => 0x16E41,
+ 0x16E62 => 0x16E42,
+ 0x16E63 => 0x16E43,
+ 0x16E64 => 0x16E44,
+ 0x16E65 => 0x16E45,
+ 0x16E66 => 0x16E46,
+ 0x16E67 => 0x16E47,
+ 0x16E68 => 0x16E48,
+ 0x16E69 => 0x16E49,
+ 0x16E6A => 0x16E4A,
+ 0x16E6B => 0x16E4B,
+ 0x16E6C => 0x16E4C,
+ 0x16E6D => 0x16E4D,
+ 0x16E6E => 0x16E4E,
+ 0x16E6F => 0x16E4F,
+ 0x16E70 => 0x16E50,
+ 0x16E71 => 0x16E51,
+ 0x16E72 => 0x16E52,
+ 0x16E73 => 0x16E53,
+ 0x16E74 => 0x16E54,
+ 0x16E75 => 0x16E55,
+ 0x16E76 => 0x16E56,
+ 0x16E77 => 0x16E57,
+ 0x16E78 => 0x16E58,
+ 0x16E79 => 0x16E59,
+ 0x16E7A => 0x16E5A,
+ 0x16E7B => 0x16E5B,
+ 0x16E7C => 0x16E5C,
+ 0x16E7D => 0x16E5D,
+ 0x16E7E => 0x16E5E,
+ 0x16E7F => 0x16E5F,
+ 0x1E922 => 0x1E900,
+ 0x1E923 => 0x1E901,
+ 0x1E924 => 0x1E902,
+ 0x1E925 => 0x1E903,
+ 0x1E926 => 0x1E904,
+ 0x1E927 => 0x1E905,
+ 0x1E928 => 0x1E906,
+ 0x1E929 => 0x1E907,
+ 0x1E92A => 0x1E908,
+ 0x1E92B => 0x1E909,
+ 0x1E92C => 0x1E90A,
+ 0x1E92D => 0x1E90B,
+ 0x1E92E => 0x1E90C,
+ 0x1E92F => 0x1E90D,
+ 0x1E930 => 0x1E90E,
+ 0x1E931 => 0x1E90F,
+ 0x1E932 => 0x1E910,
+ 0x1E933 => 0x1E911,
+ 0x1E934 => 0x1E912,
+ 0x1E935 => 0x1E913,
+ 0x1E936 => 0x1E914,
+ 0x1E937 => 0x1E915,
+ 0x1E938 => 0x1E916,
+ 0x1E939 => 0x1E917,
+ 0x1E93A => 0x1E918,
+ 0x1E93B => 0x1E919,
+ 0x1E93C => 0x1E91A,
+ 0x1E93D => 0x1E91B,
+ 0x1E93E => 0x1E91C,
+ 0x1E93F => 0x1E91D,
+ 0x1E940 => 0x1E91E,
+ 0x1E941 => 0x1E91F,
+ 0x1E942 => 0x1E920,
+ 0x1E943 => 0x1E921,
+ else => cp,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/autogen/word_break_property.zig.html b/docs/src/ziglyph/autogen/word_break_property.zig.html
new file mode 100644
index 0000000..9949db0
--- /dev/null
+++ b/docs/src/ziglyph/autogen/word_break_property.zig.html
@@ -0,0 +1,1597 @@
+
+
+
+
+
autogen/word_break_property.zig - source view
+
+
+
+
+
+
+
+
+pub fn isDoubleQuote(cp: u21) bool {
+ return cp == 0x22;
+}
+
+pub fn isSingleQuote(cp: u21) bool {
+ return cp == 0x27;
+}
+
+pub fn isHebrewLetter(cp: u21) bool {
+ if (cp < 0x5d0 or cp > 0xfb4f) return false;
+
+ return switch (cp) {
+ 0x5d0...0x5ea => true,
+ 0x5ef...0x5f2 => true,
+ 0xfb1d => true,
+ 0xfb1f...0xfb28 => true,
+ 0xfb2a...0xfb36 => true,
+ 0xfb38...0xfb3c => true,
+ 0xfb3e => true,
+ 0xfb40...0xfb41 => true,
+ 0xfb43...0xfb44 => true,
+ 0xfb46...0xfb4f => true,
+ else => false,
+ };
+}
+
+pub fn isCr(cp: u21) bool {
+ return cp == 0xd;
+}
+
+pub fn isLf(cp: u21) bool {
+ return cp == 0xa;
+}
+
+pub fn isNewline(cp: u21) bool {
+ if (cp < 0xb or cp > 0x2029) return false;
+
+ return switch (cp) {
+ 0xb...0xc => true,
+ 0x85 => true,
+ 0x2028 => true,
+ 0x2029 => true,
+ else => false,
+ };
+}
+
+pub fn isExtend(cp: u21) bool {
+ if (cp < 0x300 or cp > 0xe01ef) return false;
+
+ return switch (cp) {
+ 0x300...0x36f => true,
+ 0x483...0x487 => true,
+ 0x488...0x489 => true,
+ 0x591...0x5bd => true,
+ 0x5bf => true,
+ 0x5c1...0x5c2 => true,
+ 0x5c4...0x5c5 => true,
+ 0x5c7 => true,
+ 0x610...0x61a => true,
+ 0x64b...0x65f => true,
+ 0x670 => true,
+ 0x6d6...0x6dc => true,
+ 0x6df...0x6e4 => true,
+ 0x6e7...0x6e8 => true,
+ 0x6ea...0x6ed => true,
+ 0x711 => true,
+ 0x730...0x74a => true,
+ 0x7a6...0x7b0 => true,
+ 0x7eb...0x7f3 => true,
+ 0x7fd => true,
+ 0x816...0x819 => true,
+ 0x81b...0x823 => true,
+ 0x825...0x827 => true,
+ 0x829...0x82d => true,
+ 0x859...0x85b => true,
+ 0x898...0x89f => true,
+ 0x8ca...0x8e1 => true,
+ 0x8e3...0x902 => true,
+ 0x903 => true,
+ 0x93a => true,
+ 0x93b => true,
+ 0x93c => true,
+ 0x93e...0x940 => true,
+ 0x941...0x948 => true,
+ 0x949...0x94c => true,
+ 0x94d => true,
+ 0x94e...0x94f => true,
+ 0x951...0x957 => true,
+ 0x962...0x963 => true,
+ 0x981 => true,
+ 0x982...0x983 => true,
+ 0x9bc => true,
+ 0x9be...0x9c0 => true,
+ 0x9c1...0x9c4 => true,
+ 0x9c7...0x9c8 => true,
+ 0x9cb...0x9cc => true,
+ 0x9cd => true,
+ 0x9d7 => true,
+ 0x9e2...0x9e3 => true,
+ 0x9fe => true,
+ 0xa01...0xa02 => true,
+ 0xa03 => true,
+ 0xa3c => true,
+ 0xa3e...0xa40 => true,
+ 0xa41...0xa42 => true,
+ 0xa47...0xa48 => true,
+ 0xa4b...0xa4d => true,
+ 0xa51 => true,
+ 0xa70...0xa71 => true,
+ 0xa75 => true,
+ 0xa81...0xa82 => true,
+ 0xa83 => true,
+ 0xabc => true,
+ 0xabe...0xac0 => true,
+ 0xac1...0xac5 => true,
+ 0xac7...0xac8 => true,
+ 0xac9 => true,
+ 0xacb...0xacc => true,
+ 0xacd => true,
+ 0xae2...0xae3 => true,
+ 0xafa...0xaff => true,
+ 0xb01 => true,
+ 0xb02...0xb03 => true,
+ 0xb3c => true,
+ 0xb3e => true,
+ 0xb3f => true,
+ 0xb40 => true,
+ 0xb41...0xb44 => true,
+ 0xb47...0xb48 => true,
+ 0xb4b...0xb4c => true,
+ 0xb4d => true,
+ 0xb55...0xb56 => true,
+ 0xb57 => true,
+ 0xb62...0xb63 => true,
+ 0xb82 => true,
+ 0xbbe...0xbbf => true,
+ 0xbc0 => true,
+ 0xbc1...0xbc2 => true,
+ 0xbc6...0xbc8 => true,
+ 0xbca...0xbcc => true,
+ 0xbcd => true,
+ 0xbd7 => true,
+ 0xc00 => true,
+ 0xc01...0xc03 => true,
+ 0xc04 => true,
+ 0xc3c => true,
+ 0xc3e...0xc40 => true,
+ 0xc41...0xc44 => true,
+ 0xc46...0xc48 => true,
+ 0xc4a...0xc4d => true,
+ 0xc55...0xc56 => true,
+ 0xc62...0xc63 => true,
+ 0xc81 => true,
+ 0xc82...0xc83 => true,
+ 0xcbc => true,
+ 0xcbe => true,
+ 0xcbf => true,
+ 0xcc0...0xcc4 => true,
+ 0xcc6 => true,
+ 0xcc7...0xcc8 => true,
+ 0xcca...0xccb => true,
+ 0xccc...0xccd => true,
+ 0xcd5...0xcd6 => true,
+ 0xce2...0xce3 => true,
+ 0xcf3 => true,
+ 0xd00...0xd01 => true,
+ 0xd02...0xd03 => true,
+ 0xd3b...0xd3c => true,
+ 0xd3e...0xd40 => true,
+ 0xd41...0xd44 => true,
+ 0xd46...0xd48 => true,
+ 0xd4a...0xd4c => true,
+ 0xd4d => true,
+ 0xd57 => true,
+ 0xd62...0xd63 => true,
+ 0xd81 => true,
+ 0xd82...0xd83 => true,
+ 0xdca => true,
+ 0xdcf...0xdd1 => true,
+ 0xdd2...0xdd4 => true,
+ 0xdd6 => true,
+ 0xdd8...0xddf => true,
+ 0xdf2...0xdf3 => true,
+ 0xe31 => true,
+ 0xe34...0xe3a => true,
+ 0xe47...0xe4e => true,
+ 0xeb1 => true,
+ 0xeb4...0xebc => true,
+ 0xec8...0xece => true,
+ 0xf18...0xf19 => true,
+ 0xf35 => true,
+ 0xf37 => true,
+ 0xf39 => true,
+ 0xf3e...0xf3f => true,
+ 0xf71...0xf7e => true,
+ 0xf7f => true,
+ 0xf80...0xf84 => true,
+ 0xf86...0xf87 => true,
+ 0xf8d...0xf97 => true,
+ 0xf99...0xfbc => true,
+ 0xfc6 => true,
+ 0x102b...0x102c => true,
+ 0x102d...0x1030 => true,
+ 0x1031 => true,
+ 0x1032...0x1037 => true,
+ 0x1038 => true,
+ 0x1039...0x103a => true,
+ 0x103b...0x103c => true,
+ 0x103d...0x103e => true,
+ 0x1056...0x1057 => true,
+ 0x1058...0x1059 => true,
+ 0x105e...0x1060 => true,
+ 0x1062...0x1064 => true,
+ 0x1067...0x106d => true,
+ 0x1071...0x1074 => true,
+ 0x1082 => true,
+ 0x1083...0x1084 => true,
+ 0x1085...0x1086 => true,
+ 0x1087...0x108c => true,
+ 0x108d => true,
+ 0x108f => true,
+ 0x109a...0x109c => true,
+ 0x109d => true,
+ 0x135d...0x135f => true,
+ 0x1712...0x1714 => true,
+ 0x1715 => true,
+ 0x1732...0x1733 => true,
+ 0x1734 => true,
+ 0x1752...0x1753 => true,
+ 0x1772...0x1773 => true,
+ 0x17b4...0x17b5 => true,
+ 0x17b6 => true,
+ 0x17b7...0x17bd => true,
+ 0x17be...0x17c5 => true,
+ 0x17c6 => true,
+ 0x17c7...0x17c8 => true,
+ 0x17c9...0x17d3 => true,
+ 0x17dd => true,
+ 0x180b...0x180d => true,
+ 0x180f => true,
+ 0x1885...0x1886 => true,
+ 0x18a9 => true,
+ 0x1920...0x1922 => true,
+ 0x1923...0x1926 => true,
+ 0x1927...0x1928 => true,
+ 0x1929...0x192b => true,
+ 0x1930...0x1931 => true,
+ 0x1932 => true,
+ 0x1933...0x1938 => true,
+ 0x1939...0x193b => true,
+ 0x1a17...0x1a18 => true,
+ 0x1a19...0x1a1a => true,
+ 0x1a1b => true,
+ 0x1a55 => true,
+ 0x1a56 => true,
+ 0x1a57 => true,
+ 0x1a58...0x1a5e => true,
+ 0x1a60 => true,
+ 0x1a61 => true,
+ 0x1a62 => true,
+ 0x1a63...0x1a64 => true,
+ 0x1a65...0x1a6c => true,
+ 0x1a6d...0x1a72 => true,
+ 0x1a73...0x1a7c => true,
+ 0x1a7f => true,
+ 0x1ab0...0x1abd => true,
+ 0x1abe => true,
+ 0x1abf...0x1ace => true,
+ 0x1b00...0x1b03 => true,
+ 0x1b04 => true,
+ 0x1b34 => true,
+ 0x1b35 => true,
+ 0x1b36...0x1b3a => true,
+ 0x1b3b => true,
+ 0x1b3c => true,
+ 0x1b3d...0x1b41 => true,
+ 0x1b42 => true,
+ 0x1b43...0x1b44 => true,
+ 0x1b6b...0x1b73 => true,
+ 0x1b80...0x1b81 => true,
+ 0x1b82 => true,
+ 0x1ba1 => true,
+ 0x1ba2...0x1ba5 => true,
+ 0x1ba6...0x1ba7 => true,
+ 0x1ba8...0x1ba9 => true,
+ 0x1baa => true,
+ 0x1bab...0x1bad => true,
+ 0x1be6 => true,
+ 0x1be7 => true,
+ 0x1be8...0x1be9 => true,
+ 0x1bea...0x1bec => true,
+ 0x1bed => true,
+ 0x1bee => true,
+ 0x1bef...0x1bf1 => true,
+ 0x1bf2...0x1bf3 => true,
+ 0x1c24...0x1c2b => true,
+ 0x1c2c...0x1c33 => true,
+ 0x1c34...0x1c35 => true,
+ 0x1c36...0x1c37 => true,
+ 0x1cd0...0x1cd2 => true,
+ 0x1cd4...0x1ce0 => true,
+ 0x1ce1 => true,
+ 0x1ce2...0x1ce8 => true,
+ 0x1ced => true,
+ 0x1cf4 => true,
+ 0x1cf7 => true,
+ 0x1cf8...0x1cf9 => true,
+ 0x1dc0...0x1dff => true,
+ 0x200c => true,
+ 0x20d0...0x20dc => true,
+ 0x20dd...0x20e0 => true,
+ 0x20e1 => true,
+ 0x20e2...0x20e4 => true,
+ 0x20e5...0x20f0 => true,
+ 0x2cef...0x2cf1 => true,
+ 0x2d7f => true,
+ 0x2de0...0x2dff => true,
+ 0x302a...0x302d => true,
+ 0x302e...0x302f => true,
+ 0x3099...0x309a => true,
+ 0xa66f => true,
+ 0xa670...0xa672 => true,
+ 0xa674...0xa67d => true,
+ 0xa69e...0xa69f => true,
+ 0xa6f0...0xa6f1 => true,
+ 0xa802 => true,
+ 0xa806 => true,
+ 0xa80b => true,
+ 0xa823...0xa824 => true,
+ 0xa825...0xa826 => true,
+ 0xa827 => true,
+ 0xa82c => true,
+ 0xa880...0xa881 => true,
+ 0xa8b4...0xa8c3 => true,
+ 0xa8c4...0xa8c5 => true,
+ 0xa8e0...0xa8f1 => true,
+ 0xa8ff => true,
+ 0xa926...0xa92d => true,
+ 0xa947...0xa951 => true,
+ 0xa952...0xa953 => true,
+ 0xa980...0xa982 => true,
+ 0xa983 => true,
+ 0xa9b3 => true,
+ 0xa9b4...0xa9b5 => true,
+ 0xa9b6...0xa9b9 => true,
+ 0xa9ba...0xa9bb => true,
+ 0xa9bc...0xa9bd => true,
+ 0xa9be...0xa9c0 => true,
+ 0xa9e5 => true,
+ 0xaa29...0xaa2e => true,
+ 0xaa2f...0xaa30 => true,
+ 0xaa31...0xaa32 => true,
+ 0xaa33...0xaa34 => true,
+ 0xaa35...0xaa36 => true,
+ 0xaa43 => true,
+ 0xaa4c => true,
+ 0xaa4d => true,
+ 0xaa7b => true,
+ 0xaa7c => true,
+ 0xaa7d => true,
+ 0xaab0 => true,
+ 0xaab2...0xaab4 => true,
+ 0xaab7...0xaab8 => true,
+ 0xaabe...0xaabf => true,
+ 0xaac1 => true,
+ 0xaaeb => true,
+ 0xaaec...0xaaed => true,
+ 0xaaee...0xaaef => true,
+ 0xaaf5 => true,
+ 0xaaf6 => true,
+ 0xabe3...0xabe4 => true,
+ 0xabe5 => true,
+ 0xabe6...0xabe7 => true,
+ 0xabe8 => true,
+ 0xabe9...0xabea => true,
+ 0xabec => true,
+ 0xabed => true,
+ 0xfb1e => true,
+ 0xfe00...0xfe0f => true,
+ 0xfe20...0xfe2f => true,
+ 0xff9e...0xff9f => true,
+ 0x101fd => true,
+ 0x102e0 => true,
+ 0x10376...0x1037a => true,
+ 0x10a01...0x10a03 => true,
+ 0x10a05...0x10a06 => true,
+ 0x10a0c...0x10a0f => true,
+ 0x10a38...0x10a3a => true,
+ 0x10a3f => true,
+ 0x10ae5...0x10ae6 => true,
+ 0x10d24...0x10d27 => true,
+ 0x10eab...0x10eac => true,
+ 0x10efd...0x10eff => true,
+ 0x10f46...0x10f50 => true,
+ 0x10f82...0x10f85 => true,
+ 0x11000 => true,
+ 0x11001 => true,
+ 0x11002 => true,
+ 0x11038...0x11046 => true,
+ 0x11070 => true,
+ 0x11073...0x11074 => true,
+ 0x1107f...0x11081 => true,
+ 0x11082 => true,
+ 0x110b0...0x110b2 => true,
+ 0x110b3...0x110b6 => true,
+ 0x110b7...0x110b8 => true,
+ 0x110b9...0x110ba => true,
+ 0x110c2 => true,
+ 0x11100...0x11102 => true,
+ 0x11127...0x1112b => true,
+ 0x1112c => true,
+ 0x1112d...0x11134 => true,
+ 0x11145...0x11146 => true,
+ 0x11173 => true,
+ 0x11180...0x11181 => true,
+ 0x11182 => true,
+ 0x111b3...0x111b5 => true,
+ 0x111b6...0x111be => true,
+ 0x111bf...0x111c0 => true,
+ 0x111c9...0x111cc => true,
+ 0x111ce => true,
+ 0x111cf => true,
+ 0x1122c...0x1122e => true,
+ 0x1122f...0x11231 => true,
+ 0x11232...0x11233 => true,
+ 0x11234 => true,
+ 0x11235 => true,
+ 0x11236...0x11237 => true,
+ 0x1123e => true,
+ 0x11241 => true,
+ 0x112df => true,
+ 0x112e0...0x112e2 => true,
+ 0x112e3...0x112ea => true,
+ 0x11300...0x11301 => true,
+ 0x11302...0x11303 => true,
+ 0x1133b...0x1133c => true,
+ 0x1133e...0x1133f => true,
+ 0x11340 => true,
+ 0x11341...0x11344 => true,
+ 0x11347...0x11348 => true,
+ 0x1134b...0x1134d => true,
+ 0x11357 => true,
+ 0x11362...0x11363 => true,
+ 0x11366...0x1136c => true,
+ 0x11370...0x11374 => true,
+ 0x11435...0x11437 => true,
+ 0x11438...0x1143f => true,
+ 0x11440...0x11441 => true,
+ 0x11442...0x11444 => true,
+ 0x11445 => true,
+ 0x11446 => true,
+ 0x1145e => true,
+ 0x114b0...0x114b2 => true,
+ 0x114b3...0x114b8 => true,
+ 0x114b9 => true,
+ 0x114ba => true,
+ 0x114bb...0x114be => true,
+ 0x114bf...0x114c0 => true,
+ 0x114c1 => true,
+ 0x114c2...0x114c3 => true,
+ 0x115af...0x115b1 => true,
+ 0x115b2...0x115b5 => true,
+ 0x115b8...0x115bb => true,
+ 0x115bc...0x115bd => true,
+ 0x115be => true,
+ 0x115bf...0x115c0 => true,
+ 0x115dc...0x115dd => true,
+ 0x11630...0x11632 => true,
+ 0x11633...0x1163a => true,
+ 0x1163b...0x1163c => true,
+ 0x1163d => true,
+ 0x1163e => true,
+ 0x1163f...0x11640 => true,
+ 0x116ab => true,
+ 0x116ac => true,
+ 0x116ad => true,
+ 0x116ae...0x116af => true,
+ 0x116b0...0x116b5 => true,
+ 0x116b6 => true,
+ 0x116b7 => true,
+ 0x1171d...0x1171f => true,
+ 0x11720...0x11721 => true,
+ 0x11722...0x11725 => true,
+ 0x11726 => true,
+ 0x11727...0x1172b => true,
+ 0x1182c...0x1182e => true,
+ 0x1182f...0x11837 => true,
+ 0x11838 => true,
+ 0x11839...0x1183a => true,
+ 0x11930...0x11935 => true,
+ 0x11937...0x11938 => true,
+ 0x1193b...0x1193c => true,
+ 0x1193d => true,
+ 0x1193e => true,
+ 0x11940 => true,
+ 0x11942 => true,
+ 0x11943 => true,
+ 0x119d1...0x119d3 => true,
+ 0x119d4...0x119d7 => true,
+ 0x119da...0x119db => true,
+ 0x119dc...0x119df => true,
+ 0x119e0 => true,
+ 0x119e4 => true,
+ 0x11a01...0x11a0a => true,
+ 0x11a33...0x11a38 => true,
+ 0x11a39 => true,
+ 0x11a3b...0x11a3e => true,
+ 0x11a47 => true,
+ 0x11a51...0x11a56 => true,
+ 0x11a57...0x11a58 => true,
+ 0x11a59...0x11a5b => true,
+ 0x11a8a...0x11a96 => true,
+ 0x11a97 => true,
+ 0x11a98...0x11a99 => true,
+ 0x11c2f => true,
+ 0x11c30...0x11c36 => true,
+ 0x11c38...0x11c3d => true,
+ 0x11c3e => true,
+ 0x11c3f => true,
+ 0x11c92...0x11ca7 => true,
+ 0x11ca9 => true,
+ 0x11caa...0x11cb0 => true,
+ 0x11cb1 => true,
+ 0x11cb2...0x11cb3 => true,
+ 0x11cb4 => true,
+ 0x11cb5...0x11cb6 => true,
+ 0x11d31...0x11d36 => true,
+ 0x11d3a => true,
+ 0x11d3c...0x11d3d => true,
+ 0x11d3f...0x11d45 => true,
+ 0x11d47 => true,
+ 0x11d8a...0x11d8e => true,
+ 0x11d90...0x11d91 => true,
+ 0x11d93...0x11d94 => true,
+ 0x11d95 => true,
+ 0x11d96 => true,
+ 0x11d97 => true,
+ 0x11ef3...0x11ef4 => true,
+ 0x11ef5...0x11ef6 => true,
+ 0x11f00...0x11f01 => true,
+ 0x11f03 => true,
+ 0x11f34...0x11f35 => true,
+ 0x11f36...0x11f3a => true,
+ 0x11f3e...0x11f3f => true,
+ 0x11f40 => true,
+ 0x11f41 => true,
+ 0x11f42 => true,
+ 0x13440 => true,
+ 0x13447...0x13455 => true,
+ 0x16af0...0x16af4 => true,
+ 0x16b30...0x16b36 => true,
+ 0x16f4f => true,
+ 0x16f51...0x16f87 => true,
+ 0x16f8f...0x16f92 => true,
+ 0x16fe4 => true,
+ 0x16ff0...0x16ff1 => true,
+ 0x1bc9d...0x1bc9e => true,
+ 0x1cf00...0x1cf2d => true,
+ 0x1cf30...0x1cf46 => true,
+ 0x1d165...0x1d166 => true,
+ 0x1d167...0x1d169 => true,
+ 0x1d16d...0x1d172 => true,
+ 0x1d17b...0x1d182 => true,
+ 0x1d185...0x1d18b => true,
+ 0x1d1aa...0x1d1ad => true,
+ 0x1d242...0x1d244 => true,
+ 0x1da00...0x1da36 => true,
+ 0x1da3b...0x1da6c => true,
+ 0x1da75 => true,
+ 0x1da84 => true,
+ 0x1da9b...0x1da9f => true,
+ 0x1daa1...0x1daaf => true,
+ 0x1e000...0x1e006 => true,
+ 0x1e008...0x1e018 => true,
+ 0x1e01b...0x1e021 => true,
+ 0x1e023...0x1e024 => true,
+ 0x1e026...0x1e02a => true,
+ 0x1e08f => true,
+ 0x1e130...0x1e136 => true,
+ 0x1e2ae => true,
+ 0x1e2ec...0x1e2ef => true,
+ 0x1e4ec...0x1e4ef => true,
+ 0x1e8d0...0x1e8d6 => true,
+ 0x1e944...0x1e94a => true,
+ 0x1f3fb...0x1f3ff => true,
+ 0xe0020...0xe007f => true,
+ 0xe0100...0xe01ef => true,
+ else => false,
+ };
+}
+
+pub fn isRegionalIndicator(cp: u21) bool {
+ if (cp < 0x1f1e6 or cp > 0x1f1ff) return false;
+
+ return switch (cp) {
+ 0x1f1e6...0x1f1ff => true,
+ else => false,
+ };
+}
+
+pub fn isFormat(cp: u21) bool {
+ if (cp < 0xad or cp > 0xe0001) return false;
+
+ return switch (cp) {
+ 0xad => true,
+ 0x600...0x605 => true,
+ 0x61c => true,
+ 0x6dd => true,
+ 0x70f => true,
+ 0x890...0x891 => true,
+ 0x8e2 => true,
+ 0x180e => true,
+ 0x200e...0x200f => true,
+ 0x202a...0x202e => true,
+ 0x2060...0x2064 => true,
+ 0x2066...0x206f => true,
+ 0xfeff => true,
+ 0xfff9...0xfffb => true,
+ 0x110bd => true,
+ 0x110cd => true,
+ 0x13430...0x1343f => true,
+ 0x1bca0...0x1bca3 => true,
+ 0x1d173...0x1d17a => true,
+ 0xe0001 => true,
+ else => false,
+ };
+}
+
+pub fn isKatakana(cp: u21) bool {
+ if (cp < 0x3031 or cp > 0x1b167) return false;
+
+ return switch (cp) {
+ 0x3031...0x3035 => true,
+ 0x309b...0x309c => true,
+ 0x30a0 => true,
+ 0x30a1...0x30fa => true,
+ 0x30fc...0x30fe => true,
+ 0x30ff => true,
+ 0x31f0...0x31ff => true,
+ 0x32d0...0x32fe => true,
+ 0x3300...0x3357 => true,
+ 0xff66...0xff6f => true,
+ 0xff70 => true,
+ 0xff71...0xff9d => true,
+ 0x1aff0...0x1aff3 => true,
+ 0x1aff5...0x1affb => true,
+ 0x1affd...0x1affe => true,
+ 0x1b000 => true,
+ 0x1b120...0x1b122 => true,
+ 0x1b155 => true,
+ 0x1b164...0x1b167 => true,
+ else => false,
+ };
+}
+
+pub fn isAletter(cp: u21) bool {
+ if (cp < 0x41 or cp > 0x1f189) return false;
+
+ return switch (cp) {
+ 0x41...0x5a => true,
+ 0x61...0x7a => true,
+ 0xaa => true,
+ 0xb5 => true,
+ 0xba => true,
+ 0xc0...0xd6 => true,
+ 0xd8...0xf6 => true,
+ 0xf8...0x1ba => true,
+ 0x1bb => true,
+ 0x1bc...0x1bf => true,
+ 0x1c0...0x1c3 => true,
+ 0x1c4...0x293 => true,
+ 0x294 => true,
+ 0x295...0x2af => true,
+ 0x2b0...0x2c1 => true,
+ 0x2c2...0x2c5 => true,
+ 0x2c6...0x2d1 => true,
+ 0x2d2...0x2d7 => true,
+ 0x2de...0x2df => true,
+ 0x2e0...0x2e4 => true,
+ 0x2e5...0x2eb => true,
+ 0x2ec => true,
+ 0x2ed => true,
+ 0x2ee => true,
+ 0x2ef...0x2ff => true,
+ 0x370...0x373 => true,
+ 0x374 => true,
+ 0x376...0x377 => true,
+ 0x37a => true,
+ 0x37b...0x37d => true,
+ 0x37f => true,
+ 0x386 => true,
+ 0x388...0x38a => true,
+ 0x38c => true,
+ 0x38e...0x3a1 => true,
+ 0x3a3...0x3f5 => true,
+ 0x3f7...0x481 => true,
+ 0x48a...0x52f => true,
+ 0x531...0x556 => true,
+ 0x559 => true,
+ 0x55a...0x55c => true,
+ 0x55e => true,
+ 0x560...0x588 => true,
+ 0x58a => true,
+ 0x5f3 => true,
+ 0x620...0x63f => true,
+ 0x640 => true,
+ 0x641...0x64a => true,
+ 0x66e...0x66f => true,
+ 0x671...0x6d3 => true,
+ 0x6d5 => true,
+ 0x6e5...0x6e6 => true,
+ 0x6ee...0x6ef => true,
+ 0x6fa...0x6fc => true,
+ 0x6ff => true,
+ 0x710 => true,
+ 0x712...0x72f => true,
+ 0x74d...0x7a5 => true,
+ 0x7b1 => true,
+ 0x7ca...0x7ea => true,
+ 0x7f4...0x7f5 => true,
+ 0x7fa => true,
+ 0x800...0x815 => true,
+ 0x81a => true,
+ 0x824 => true,
+ 0x828 => true,
+ 0x840...0x858 => true,
+ 0x860...0x86a => true,
+ 0x870...0x887 => true,
+ 0x889...0x88e => true,
+ 0x8a0...0x8c8 => true,
+ 0x8c9 => true,
+ 0x904...0x939 => true,
+ 0x93d => true,
+ 0x950 => true,
+ 0x958...0x961 => true,
+ 0x971 => true,
+ 0x972...0x980 => true,
+ 0x985...0x98c => true,
+ 0x98f...0x990 => true,
+ 0x993...0x9a8 => true,
+ 0x9aa...0x9b0 => true,
+ 0x9b2 => true,
+ 0x9b6...0x9b9 => true,
+ 0x9bd => true,
+ 0x9ce => true,
+ 0x9dc...0x9dd => true,
+ 0x9df...0x9e1 => true,
+ 0x9f0...0x9f1 => true,
+ 0x9fc => true,
+ 0xa05...0xa0a => true,
+ 0xa0f...0xa10 => true,
+ 0xa13...0xa28 => true,
+ 0xa2a...0xa30 => true,
+ 0xa32...0xa33 => true,
+ 0xa35...0xa36 => true,
+ 0xa38...0xa39 => true,
+ 0xa59...0xa5c => true,
+ 0xa5e => true,
+ 0xa72...0xa74 => true,
+ 0xa85...0xa8d => true,
+ 0xa8f...0xa91 => true,
+ 0xa93...0xaa8 => true,
+ 0xaaa...0xab0 => true,
+ 0xab2...0xab3 => true,
+ 0xab5...0xab9 => true,
+ 0xabd => true,
+ 0xad0 => true,
+ 0xae0...0xae1 => true,
+ 0xaf9 => true,
+ 0xb05...0xb0c => true,
+ 0xb0f...0xb10 => true,
+ 0xb13...0xb28 => true,
+ 0xb2a...0xb30 => true,
+ 0xb32...0xb33 => true,
+ 0xb35...0xb39 => true,
+ 0xb3d => true,
+ 0xb5c...0xb5d => true,
+ 0xb5f...0xb61 => true,
+ 0xb71 => true,
+ 0xb83 => true,
+ 0xb85...0xb8a => true,
+ 0xb8e...0xb90 => true,
+ 0xb92...0xb95 => true,
+ 0xb99...0xb9a => true,
+ 0xb9c => true,
+ 0xb9e...0xb9f => true,
+ 0xba3...0xba4 => true,
+ 0xba8...0xbaa => true,
+ 0xbae...0xbb9 => true,
+ 0xbd0 => true,
+ 0xc05...0xc0c => true,
+ 0xc0e...0xc10 => true,
+ 0xc12...0xc28 => true,
+ 0xc2a...0xc39 => true,
+ 0xc3d => true,
+ 0xc58...0xc5a => true,
+ 0xc5d => true,
+ 0xc60...0xc61 => true,
+ 0xc80 => true,
+ 0xc85...0xc8c => true,
+ 0xc8e...0xc90 => true,
+ 0xc92...0xca8 => true,
+ 0xcaa...0xcb3 => true,
+ 0xcb5...0xcb9 => true,
+ 0xcbd => true,
+ 0xcdd...0xcde => true,
+ 0xce0...0xce1 => true,
+ 0xcf1...0xcf2 => true,
+ 0xd04...0xd0c => true,
+ 0xd0e...0xd10 => true,
+ 0xd12...0xd3a => true,
+ 0xd3d => true,
+ 0xd4e => true,
+ 0xd54...0xd56 => true,
+ 0xd5f...0xd61 => true,
+ 0xd7a...0xd7f => true,
+ 0xd85...0xd96 => true,
+ 0xd9a...0xdb1 => true,
+ 0xdb3...0xdbb => true,
+ 0xdbd => true,
+ 0xdc0...0xdc6 => true,
+ 0xf00 => true,
+ 0xf40...0xf47 => true,
+ 0xf49...0xf6c => true,
+ 0xf88...0xf8c => true,
+ 0x10a0...0x10c5 => true,
+ 0x10c7 => true,
+ 0x10cd => true,
+ 0x10d0...0x10fa => true,
+ 0x10fc => true,
+ 0x10fd...0x10ff => true,
+ 0x1100...0x1248 => true,
+ 0x124a...0x124d => true,
+ 0x1250...0x1256 => true,
+ 0x1258 => true,
+ 0x125a...0x125d => true,
+ 0x1260...0x1288 => true,
+ 0x128a...0x128d => true,
+ 0x1290...0x12b0 => true,
+ 0x12b2...0x12b5 => true,
+ 0x12b8...0x12be => true,
+ 0x12c0 => true,
+ 0x12c2...0x12c5 => true,
+ 0x12c8...0x12d6 => true,
+ 0x12d8...0x1310 => true,
+ 0x1312...0x1315 => true,
+ 0x1318...0x135a => true,
+ 0x1380...0x138f => true,
+ 0x13a0...0x13f5 => true,
+ 0x13f8...0x13fd => true,
+ 0x1401...0x166c => true,
+ 0x166f...0x167f => true,
+ 0x1681...0x169a => true,
+ 0x16a0...0x16ea => true,
+ 0x16ee...0x16f0 => true,
+ 0x16f1...0x16f8 => true,
+ 0x1700...0x1711 => true,
+ 0x171f...0x1731 => true,
+ 0x1740...0x1751 => true,
+ 0x1760...0x176c => true,
+ 0x176e...0x1770 => true,
+ 0x1820...0x1842 => true,
+ 0x1843 => true,
+ 0x1844...0x1878 => true,
+ 0x1880...0x1884 => true,
+ 0x1887...0x18a8 => true,
+ 0x18aa => true,
+ 0x18b0...0x18f5 => true,
+ 0x1900...0x191e => true,
+ 0x1a00...0x1a16 => true,
+ 0x1b05...0x1b33 => true,
+ 0x1b45...0x1b4c => true,
+ 0x1b83...0x1ba0 => true,
+ 0x1bae...0x1baf => true,
+ 0x1bba...0x1be5 => true,
+ 0x1c00...0x1c23 => true,
+ 0x1c4d...0x1c4f => true,
+ 0x1c5a...0x1c77 => true,
+ 0x1c78...0x1c7d => true,
+ 0x1c80...0x1c88 => true,
+ 0x1c90...0x1cba => true,
+ 0x1cbd...0x1cbf => true,
+ 0x1ce9...0x1cec => true,
+ 0x1cee...0x1cf3 => true,
+ 0x1cf5...0x1cf6 => true,
+ 0x1cfa => true,
+ 0x1d00...0x1d2b => true,
+ 0x1d2c...0x1d6a => true,
+ 0x1d6b...0x1d77 => true,
+ 0x1d78 => true,
+ 0x1d79...0x1d9a => true,
+ 0x1d9b...0x1dbf => true,
+ 0x1e00...0x1f15 => true,
+ 0x1f18...0x1f1d => true,
+ 0x1f20...0x1f45 => true,
+ 0x1f48...0x1f4d => true,
+ 0x1f50...0x1f57 => true,
+ 0x1f59 => true,
+ 0x1f5b => true,
+ 0x1f5d => true,
+ 0x1f5f...0x1f7d => true,
+ 0x1f80...0x1fb4 => true,
+ 0x1fb6...0x1fbc => true,
+ 0x1fbe => true,
+ 0x1fc2...0x1fc4 => true,
+ 0x1fc6...0x1fcc => true,
+ 0x1fd0...0x1fd3 => true,
+ 0x1fd6...0x1fdb => true,
+ 0x1fe0...0x1fec => true,
+ 0x1ff2...0x1ff4 => true,
+ 0x1ff6...0x1ffc => true,
+ 0x2071 => true,
+ 0x207f => true,
+ 0x2090...0x209c => true,
+ 0x2102 => true,
+ 0x2107 => true,
+ 0x210a...0x2113 => true,
+ 0x2115 => true,
+ 0x2119...0x211d => true,
+ 0x2124 => true,
+ 0x2126 => true,
+ 0x2128 => true,
+ 0x212a...0x212d => true,
+ 0x212f...0x2134 => true,
+ 0x2135...0x2138 => true,
+ 0x2139 => true,
+ 0x213c...0x213f => true,
+ 0x2145...0x2149 => true,
+ 0x214e => true,
+ 0x2160...0x2182 => true,
+ 0x2183...0x2184 => true,
+ 0x2185...0x2188 => true,
+ 0x24b6...0x24e9 => true,
+ 0x2c00...0x2c7b => true,
+ 0x2c7c...0x2c7d => true,
+ 0x2c7e...0x2ce4 => true,
+ 0x2ceb...0x2cee => true,
+ 0x2cf2...0x2cf3 => true,
+ 0x2d00...0x2d25 => true,
+ 0x2d27 => true,
+ 0x2d2d => true,
+ 0x2d30...0x2d67 => true,
+ 0x2d6f => true,
+ 0x2d80...0x2d96 => true,
+ 0x2da0...0x2da6 => true,
+ 0x2da8...0x2dae => true,
+ 0x2db0...0x2db6 => true,
+ 0x2db8...0x2dbe => true,
+ 0x2dc0...0x2dc6 => true,
+ 0x2dc8...0x2dce => true,
+ 0x2dd0...0x2dd6 => true,
+ 0x2dd8...0x2dde => true,
+ 0x2e2f => true,
+ 0x3005 => true,
+ 0x303b => true,
+ 0x303c => true,
+ 0x3105...0x312f => true,
+ 0x3131...0x318e => true,
+ 0x31a0...0x31bf => true,
+ 0xa000...0xa014 => true,
+ 0xa015 => true,
+ 0xa016...0xa48c => true,
+ 0xa4d0...0xa4f7 => true,
+ 0xa4f8...0xa4fd => true,
+ 0xa500...0xa60b => true,
+ 0xa60c => true,
+ 0xa610...0xa61f => true,
+ 0xa62a...0xa62b => true,
+ 0xa640...0xa66d => true,
+ 0xa66e => true,
+ 0xa67f => true,
+ 0xa680...0xa69b => true,
+ 0xa69c...0xa69d => true,
+ 0xa6a0...0xa6e5 => true,
+ 0xa6e6...0xa6ef => true,
+ 0xa708...0xa716 => true,
+ 0xa717...0xa71f => true,
+ 0xa720...0xa721 => true,
+ 0xa722...0xa76f => true,
+ 0xa770 => true,
+ 0xa771...0xa787 => true,
+ 0xa788 => true,
+ 0xa789...0xa78a => true,
+ 0xa78b...0xa78e => true,
+ 0xa78f => true,
+ 0xa790...0xa7ca => true,
+ 0xa7d0...0xa7d1 => true,
+ 0xa7d3 => true,
+ 0xa7d5...0xa7d9 => true,
+ 0xa7f2...0xa7f4 => true,
+ 0xa7f5...0xa7f6 => true,
+ 0xa7f7 => true,
+ 0xa7f8...0xa7f9 => true,
+ 0xa7fa => true,
+ 0xa7fb...0xa801 => true,
+ 0xa803...0xa805 => true,
+ 0xa807...0xa80a => true,
+ 0xa80c...0xa822 => true,
+ 0xa840...0xa873 => true,
+ 0xa882...0xa8b3 => true,
+ 0xa8f2...0xa8f7 => true,
+ 0xa8fb => true,
+ 0xa8fd...0xa8fe => true,
+ 0xa90a...0xa925 => true,
+ 0xa930...0xa946 => true,
+ 0xa960...0xa97c => true,
+ 0xa984...0xa9b2 => true,
+ 0xa9cf => true,
+ 0xaa00...0xaa28 => true,
+ 0xaa40...0xaa42 => true,
+ 0xaa44...0xaa4b => true,
+ 0xaae0...0xaaea => true,
+ 0xaaf2 => true,
+ 0xaaf3...0xaaf4 => true,
+ 0xab01...0xab06 => true,
+ 0xab09...0xab0e => true,
+ 0xab11...0xab16 => true,
+ 0xab20...0xab26 => true,
+ 0xab28...0xab2e => true,
+ 0xab30...0xab5a => true,
+ 0xab5b => true,
+ 0xab5c...0xab5f => true,
+ 0xab60...0xab68 => true,
+ 0xab69 => true,
+ 0xab70...0xabbf => true,
+ 0xabc0...0xabe2 => true,
+ 0xac00...0xd7a3 => true,
+ 0xd7b0...0xd7c6 => true,
+ 0xd7cb...0xd7fb => true,
+ 0xfb00...0xfb06 => true,
+ 0xfb13...0xfb17 => true,
+ 0xfb50...0xfbb1 => true,
+ 0xfbd3...0xfd3d => true,
+ 0xfd50...0xfd8f => true,
+ 0xfd92...0xfdc7 => true,
+ 0xfdf0...0xfdfb => true,
+ 0xfe70...0xfe74 => true,
+ 0xfe76...0xfefc => true,
+ 0xff21...0xff3a => true,
+ 0xff41...0xff5a => true,
+ 0xffa0...0xffbe => true,
+ 0xffc2...0xffc7 => true,
+ 0xffca...0xffcf => true,
+ 0xffd2...0xffd7 => true,
+ 0xffda...0xffdc => true,
+ 0x10000...0x1000b => true,
+ 0x1000d...0x10026 => true,
+ 0x10028...0x1003a => true,
+ 0x1003c...0x1003d => true,
+ 0x1003f...0x1004d => true,
+ 0x10050...0x1005d => true,
+ 0x10080...0x100fa => true,
+ 0x10140...0x10174 => true,
+ 0x10280...0x1029c => true,
+ 0x102a0...0x102d0 => true,
+ 0x10300...0x1031f => true,
+ 0x1032d...0x10340 => true,
+ 0x10341 => true,
+ 0x10342...0x10349 => true,
+ 0x1034a => true,
+ 0x10350...0x10375 => true,
+ 0x10380...0x1039d => true,
+ 0x103a0...0x103c3 => true,
+ 0x103c8...0x103cf => true,
+ 0x103d1...0x103d5 => true,
+ 0x10400...0x1044f => true,
+ 0x10450...0x1049d => true,
+ 0x104b0...0x104d3 => true,
+ 0x104d8...0x104fb => true,
+ 0x10500...0x10527 => true,
+ 0x10530...0x10563 => true,
+ 0x10570...0x1057a => true,
+ 0x1057c...0x1058a => true,
+ 0x1058c...0x10592 => true,
+ 0x10594...0x10595 => true,
+ 0x10597...0x105a1 => true,
+ 0x105a3...0x105b1 => true,
+ 0x105b3...0x105b9 => true,
+ 0x105bb...0x105bc => true,
+ 0x10600...0x10736 => true,
+ 0x10740...0x10755 => true,
+ 0x10760...0x10767 => true,
+ 0x10780...0x10785 => true,
+ 0x10787...0x107b0 => true,
+ 0x107b2...0x107ba => true,
+ 0x10800...0x10805 => true,
+ 0x10808 => true,
+ 0x1080a...0x10835 => true,
+ 0x10837...0x10838 => true,
+ 0x1083c => true,
+ 0x1083f...0x10855 => true,
+ 0x10860...0x10876 => true,
+ 0x10880...0x1089e => true,
+ 0x108e0...0x108f2 => true,
+ 0x108f4...0x108f5 => true,
+ 0x10900...0x10915 => true,
+ 0x10920...0x10939 => true,
+ 0x10980...0x109b7 => true,
+ 0x109be...0x109bf => true,
+ 0x10a00 => true,
+ 0x10a10...0x10a13 => true,
+ 0x10a15...0x10a17 => true,
+ 0x10a19...0x10a35 => true,
+ 0x10a60...0x10a7c => true,
+ 0x10a80...0x10a9c => true,
+ 0x10ac0...0x10ac7 => true,
+ 0x10ac9...0x10ae4 => true,
+ 0x10b00...0x10b35 => true,
+ 0x10b40...0x10b55 => true,
+ 0x10b60...0x10b72 => true,
+ 0x10b80...0x10b91 => true,
+ 0x10c00...0x10c48 => true,
+ 0x10c80...0x10cb2 => true,
+ 0x10cc0...0x10cf2 => true,
+ 0x10d00...0x10d23 => true,
+ 0x10e80...0x10ea9 => true,
+ 0x10eb0...0x10eb1 => true,
+ 0x10f00...0x10f1c => true,
+ 0x10f27 => true,
+ 0x10f30...0x10f45 => true,
+ 0x10f70...0x10f81 => true,
+ 0x10fb0...0x10fc4 => true,
+ 0x10fe0...0x10ff6 => true,
+ 0x11003...0x11037 => true,
+ 0x11071...0x11072 => true,
+ 0x11075 => true,
+ 0x11083...0x110af => true,
+ 0x110d0...0x110e8 => true,
+ 0x11103...0x11126 => true,
+ 0x11144 => true,
+ 0x11147 => true,
+ 0x11150...0x11172 => true,
+ 0x11176 => true,
+ 0x11183...0x111b2 => true,
+ 0x111c1...0x111c4 => true,
+ 0x111da => true,
+ 0x111dc => true,
+ 0x11200...0x11211 => true,
+ 0x11213...0x1122b => true,
+ 0x1123f...0x11240 => true,
+ 0x11280...0x11286 => true,
+ 0x11288 => true,
+ 0x1128a...0x1128d => true,
+ 0x1128f...0x1129d => true,
+ 0x1129f...0x112a8 => true,
+ 0x112b0...0x112de => true,
+ 0x11305...0x1130c => true,
+ 0x1130f...0x11310 => true,
+ 0x11313...0x11328 => true,
+ 0x1132a...0x11330 => true,
+ 0x11332...0x11333 => true,
+ 0x11335...0x11339 => true,
+ 0x1133d => true,
+ 0x11350 => true,
+ 0x1135d...0x11361 => true,
+ 0x11400...0x11434 => true,
+ 0x11447...0x1144a => true,
+ 0x1145f...0x11461 => true,
+ 0x11480...0x114af => true,
+ 0x114c4...0x114c5 => true,
+ 0x114c7 => true,
+ 0x11580...0x115ae => true,
+ 0x115d8...0x115db => true,
+ 0x11600...0x1162f => true,
+ 0x11644 => true,
+ 0x11680...0x116aa => true,
+ 0x116b8 => true,
+ 0x11800...0x1182b => true,
+ 0x118a0...0x118df => true,
+ 0x118ff...0x11906 => true,
+ 0x11909 => true,
+ 0x1190c...0x11913 => true,
+ 0x11915...0x11916 => true,
+ 0x11918...0x1192f => true,
+ 0x1193f => true,
+ 0x11941 => true,
+ 0x119a0...0x119a7 => true,
+ 0x119aa...0x119d0 => true,
+ 0x119e1 => true,
+ 0x119e3 => true,
+ 0x11a00 => true,
+ 0x11a0b...0x11a32 => true,
+ 0x11a3a => true,
+ 0x11a50 => true,
+ 0x11a5c...0x11a89 => true,
+ 0x11a9d => true,
+ 0x11ab0...0x11af8 => true,
+ 0x11c00...0x11c08 => true,
+ 0x11c0a...0x11c2e => true,
+ 0x11c40 => true,
+ 0x11c72...0x11c8f => true,
+ 0x11d00...0x11d06 => true,
+ 0x11d08...0x11d09 => true,
+ 0x11d0b...0x11d30 => true,
+ 0x11d46 => true,
+ 0x11d60...0x11d65 => true,
+ 0x11d67...0x11d68 => true,
+ 0x11d6a...0x11d89 => true,
+ 0x11d98 => true,
+ 0x11ee0...0x11ef2 => true,
+ 0x11f02 => true,
+ 0x11f04...0x11f10 => true,
+ 0x11f12...0x11f33 => true,
+ 0x11fb0 => true,
+ 0x12000...0x12399 => true,
+ 0x12400...0x1246e => true,
+ 0x12480...0x12543 => true,
+ 0x12f90...0x12ff0 => true,
+ 0x13000...0x1342f => true,
+ 0x13441...0x13446 => true,
+ 0x14400...0x14646 => true,
+ 0x16800...0x16a38 => true,
+ 0x16a40...0x16a5e => true,
+ 0x16a70...0x16abe => true,
+ 0x16ad0...0x16aed => true,
+ 0x16b00...0x16b2f => true,
+ 0x16b40...0x16b43 => true,
+ 0x16b63...0x16b77 => true,
+ 0x16b7d...0x16b8f => true,
+ 0x16e40...0x16e7f => true,
+ 0x16f00...0x16f4a => true,
+ 0x16f50 => true,
+ 0x16f93...0x16f9f => true,
+ 0x16fe0...0x16fe1 => true,
+ 0x16fe3 => true,
+ 0x1bc00...0x1bc6a => true,
+ 0x1bc70...0x1bc7c => true,
+ 0x1bc80...0x1bc88 => true,
+ 0x1bc90...0x1bc99 => true,
+ 0x1d400...0x1d454 => true,
+ 0x1d456...0x1d49c => true,
+ 0x1d49e...0x1d49f => true,
+ 0x1d4a2 => true,
+ 0x1d4a5...0x1d4a6 => true,
+ 0x1d4a9...0x1d4ac => true,
+ 0x1d4ae...0x1d4b9 => true,
+ 0x1d4bb => true,
+ 0x1d4bd...0x1d4c3 => true,
+ 0x1d4c5...0x1d505 => true,
+ 0x1d507...0x1d50a => true,
+ 0x1d50d...0x1d514 => true,
+ 0x1d516...0x1d51c => true,
+ 0x1d51e...0x1d539 => true,
+ 0x1d53b...0x1d53e => true,
+ 0x1d540...0x1d544 => true,
+ 0x1d546 => true,
+ 0x1d54a...0x1d550 => true,
+ 0x1d552...0x1d6a5 => true,
+ 0x1d6a8...0x1d6c0 => true,
+ 0x1d6c2...0x1d6da => true,
+ 0x1d6dc...0x1d6fa => true,
+ 0x1d6fc...0x1d714 => true,
+ 0x1d716...0x1d734 => true,
+ 0x1d736...0x1d74e => true,
+ 0x1d750...0x1d76e => true,
+ 0x1d770...0x1d788 => true,
+ 0x1d78a...0x1d7a8 => true,
+ 0x1d7aa...0x1d7c2 => true,
+ 0x1d7c4...0x1d7cb => true,
+ 0x1df00...0x1df09 => true,
+ 0x1df0a => true,
+ 0x1df0b...0x1df1e => true,
+ 0x1df25...0x1df2a => true,
+ 0x1e030...0x1e06d => true,
+ 0x1e100...0x1e12c => true,
+ 0x1e137...0x1e13d => true,
+ 0x1e14e => true,
+ 0x1e290...0x1e2ad => true,
+ 0x1e2c0...0x1e2eb => true,
+ 0x1e4d0...0x1e4ea => true,
+ 0x1e4eb => true,
+ 0x1e7e0...0x1e7e6 => true,
+ 0x1e7e8...0x1e7eb => true,
+ 0x1e7ed...0x1e7ee => true,
+ 0x1e7f0...0x1e7fe => true,
+ 0x1e800...0x1e8c4 => true,
+ 0x1e900...0x1e943 => true,
+ 0x1e94b => true,
+ 0x1ee00...0x1ee03 => true,
+ 0x1ee05...0x1ee1f => true,
+ 0x1ee21...0x1ee22 => true,
+ 0x1ee24 => true,
+ 0x1ee27 => true,
+ 0x1ee29...0x1ee32 => true,
+ 0x1ee34...0x1ee37 => true,
+ 0x1ee39 => true,
+ 0x1ee3b => true,
+ 0x1ee42 => true,
+ 0x1ee47 => true,
+ 0x1ee49 => true,
+ 0x1ee4b => true,
+ 0x1ee4d...0x1ee4f => true,
+ 0x1ee51...0x1ee52 => true,
+ 0x1ee54 => true,
+ 0x1ee57 => true,
+ 0x1ee59 => true,
+ 0x1ee5b => true,
+ 0x1ee5d => true,
+ 0x1ee5f => true,
+ 0x1ee61...0x1ee62 => true,
+ 0x1ee64 => true,
+ 0x1ee67...0x1ee6a => true,
+ 0x1ee6c...0x1ee72 => true,
+ 0x1ee74...0x1ee77 => true,
+ 0x1ee79...0x1ee7c => true,
+ 0x1ee7e => true,
+ 0x1ee80...0x1ee89 => true,
+ 0x1ee8b...0x1ee9b => true,
+ 0x1eea1...0x1eea3 => true,
+ 0x1eea5...0x1eea9 => true,
+ 0x1eeab...0x1eebb => true,
+ 0x1f130...0x1f149 => true,
+ 0x1f150...0x1f169 => true,
+ 0x1f170...0x1f189 => true,
+ else => false,
+ };
+}
+
+pub fn isMidletter(cp: u21) bool {
+ if (cp < 0x3a or cp > 0xff1a) return false;
+
+ return switch (cp) {
+ 0x3a => true,
+ 0xb7 => true,
+ 0x387 => true,
+ 0x55f => true,
+ 0x5f4 => true,
+ 0x2027 => true,
+ 0xfe13 => true,
+ 0xfe55 => true,
+ 0xff1a => true,
+ else => false,
+ };
+}
+
+pub fn isMidnum(cp: u21) bool {
+ if (cp < 0x2c or cp > 0xff1b) return false;
+
+ return switch (cp) {
+ 0x2c => true,
+ 0x3b => true,
+ 0x37e => true,
+ 0x589 => true,
+ 0x60c...0x60d => true,
+ 0x66c => true,
+ 0x7f8 => true,
+ 0x2044 => true,
+ 0xfe10 => true,
+ 0xfe14 => true,
+ 0xfe50 => true,
+ 0xfe54 => true,
+ 0xff0c => true,
+ 0xff1b => true,
+ else => false,
+ };
+}
+
+pub fn isMidnumlet(cp: u21) bool {
+ if (cp < 0x2e or cp > 0xff0e) return false;
+
+ return switch (cp) {
+ 0x2e => true,
+ 0x2018 => true,
+ 0x2019 => true,
+ 0x2024 => true,
+ 0xfe52 => true,
+ 0xff07 => true,
+ 0xff0e => true,
+ else => false,
+ };
+}
+
+pub fn isNumeric(cp: u21) bool {
+ if (cp < 0x30 or cp > 0x1fbf9) return false;
+
+ return switch (cp) {
+ 0x30...0x39 => true,
+ 0x660...0x669 => true,
+ 0x66b => true,
+ 0x6f0...0x6f9 => true,
+ 0x7c0...0x7c9 => true,
+ 0x966...0x96f => true,
+ 0x9e6...0x9ef => true,
+ 0xa66...0xa6f => true,
+ 0xae6...0xaef => true,
+ 0xb66...0xb6f => true,
+ 0xbe6...0xbef => true,
+ 0xc66...0xc6f => true,
+ 0xce6...0xcef => true,
+ 0xd66...0xd6f => true,
+ 0xde6...0xdef => true,
+ 0xe50...0xe59 => true,
+ 0xed0...0xed9 => true,
+ 0xf20...0xf29 => true,
+ 0x1040...0x1049 => true,
+ 0x1090...0x1099 => true,
+ 0x17e0...0x17e9 => true,
+ 0x1810...0x1819 => true,
+ 0x1946...0x194f => true,
+ 0x19d0...0x19d9 => true,
+ 0x1a80...0x1a89 => true,
+ 0x1a90...0x1a99 => true,
+ 0x1b50...0x1b59 => true,
+ 0x1bb0...0x1bb9 => true,
+ 0x1c40...0x1c49 => true,
+ 0x1c50...0x1c59 => true,
+ 0xa620...0xa629 => true,
+ 0xa8d0...0xa8d9 => true,
+ 0xa900...0xa909 => true,
+ 0xa9d0...0xa9d9 => true,
+ 0xa9f0...0xa9f9 => true,
+ 0xaa50...0xaa59 => true,
+ 0xabf0...0xabf9 => true,
+ 0xff10...0xff19 => true,
+ 0x104a0...0x104a9 => true,
+ 0x10d30...0x10d39 => true,
+ 0x11066...0x1106f => true,
+ 0x110f0...0x110f9 => true,
+ 0x11136...0x1113f => true,
+ 0x111d0...0x111d9 => true,
+ 0x112f0...0x112f9 => true,
+ 0x11450...0x11459 => true,
+ 0x114d0...0x114d9 => true,
+ 0x11650...0x11659 => true,
+ 0x116c0...0x116c9 => true,
+ 0x11730...0x11739 => true,
+ 0x118e0...0x118e9 => true,
+ 0x11950...0x11959 => true,
+ 0x11c50...0x11c59 => true,
+ 0x11d50...0x11d59 => true,
+ 0x11da0...0x11da9 => true,
+ 0x11f50...0x11f59 => true,
+ 0x16a60...0x16a69 => true,
+ 0x16ac0...0x16ac9 => true,
+ 0x16b50...0x16b59 => true,
+ 0x1d7ce...0x1d7ff => true,
+ 0x1e140...0x1e149 => true,
+ 0x1e2f0...0x1e2f9 => true,
+ 0x1e4f0...0x1e4f9 => true,
+ 0x1e950...0x1e959 => true,
+ 0x1fbf0...0x1fbf9 => true,
+ else => false,
+ };
+}
+
+pub fn isExtendnumlet(cp: u21) bool {
+ if (cp < 0x5f or cp > 0xff3f) return false;
+
+ return switch (cp) {
+ 0x5f => true,
+ 0x202f => true,
+ 0x203f...0x2040 => true,
+ 0x2054 => true,
+ 0xfe33...0xfe34 => true,
+ 0xfe4d...0xfe4f => true,
+ 0xff3f => true,
+ else => false,
+ };
+}
+
+pub fn isZwj(cp: u21) bool {
+ return cp == 0x200d;
+}
+
+pub fn isWsegspace(cp: u21) bool {
+ if (cp < 0x20 or cp > 0x3000) return false;
+
+ return switch (cp) {
+ 0x20 => true,
+ 0x1680 => true,
+ 0x2000...0x2006 => true,
+ 0x2008...0x200a => true,
+ 0x205f => true,
+ 0x3000 => true,
+ else => false,
+ };
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/category/letter.zig.html b/docs/src/ziglyph/category/letter.zig.html
new file mode 100644
index 0000000..d6d7f83
--- /dev/null
+++ b/docs/src/ziglyph/category/letter.zig.html
@@ -0,0 +1,331 @@
+
+
+
+
+
category/letter.zig - source view
+
+
+
+
+
+
+
+const std = @import("std");
+
+const case_fold_map = @import("../autogen/case_folding.zig");
+const props = @import("../autogen/derived_core_properties.zig");
+const cats = @import("../autogen/derived_general_category.zig");
+const lower_map = @import("../autogen/lower_map.zig");
+const title_map = @import("../autogen/title_map.zig");
+const upper_map = @import("../autogen/upper_map.zig");
+
+
+pub fn isCased(cp: u21) bool {
+
+
+ if (('A' <= cp and cp <= 'Z') or ('a' <= cp and cp <= 'z')) return true;
+ return props.isCased(cp);
+}
+
+
+pub fn isLetter(cp: u21) bool {
+
+
+ if (('A' <= cp and cp <= 'Z') or ('a' <= cp and cp <= 'z')) return true;
+
+ return cats.isLowercaseLetter(cp) or
+ cats.isUppercaseLetter(cp) or
+ cats.isTitlecaseLetter(cp) or
+ cats.isModifierLetter(cp) or
+ cats.isOtherLetter(cp);
+}
+
+
+pub fn isAsciiLetter(cp: u21) bool {
+ return ('A' <= cp and cp <= 'Z') or ('a' <= cp and cp <= 'z');
+}
+
+
+pub fn isLower(cp: u21) bool {
+
+
+ if ('a' <= cp and cp <= 'z') return true;
+ return props.isLowercase(cp);
+}
+
+
+pub fn isAsciiLower(cp: u21) bool {
+ return 'a' <= cp and cp <= 'z';
+}
+
+
+pub fn isTitle(cp: u21) bool {
+ return cats.isTitlecaseLetter(cp);
+}
+
+
+pub fn isUpper(cp: u21) bool {
+
+
+ if (('A' <= cp and cp <= 'Z')) return true;
+ return props.isUppercase(cp);
+}
+
+
+pub fn isAsciiUpper(cp: u21) bool {
+ return 'A' <= cp and cp <= 'Z';
+}
+
+
+pub fn toLower(cp: u21) u21 {
+
+
+ if ('A' <= cp and cp <= 'Z') return cp ^ 32;
+ return lower_map.toLower(cp);
+}
+
+
+pub fn toAsciiLower(cp: u21) u21 {
+ return if ('A' <= cp and cp <= 'Z') cp ^ 32 else cp;
+}
+
+
+pub fn toTitle(cp: u21) u21 {
+ return title_map.toTitle(cp);
+}
+
+
+pub fn toUpper(cp: u21) u21 {
+
+
+ if ('a' <= cp and cp <= 'z') return cp ^ 32;
+ return upper_map.toUpper(cp);
+}
+
+
+pub fn toAsciiUpper(cp: u21) u21 {
+ return if ('a' <= cp and cp <= 'z') cp ^ 32 else cp;
+}
+
+
+
+
+pub fn toCaseFold(cp: u21) [3]u21 {
+ return case_fold_map.toCaseFold(cp);
+}
+
+test "letter" {
+ const z = 'z';
+ try std.testing.expect(isLetter(z));
+ try std.testing.expect(!isUpper(z));
+ const uz = toUpper(z);
+ try std.testing.expect(isUpper(uz));
+ try std.testing.expectEqual(uz, 'Z');
+}
+
+test "letter isCased" {
+ try std.testing.expect(isCased('a'));
+ try std.testing.expect(isCased('A'));
+ try std.testing.expect(!isCased('1'));
+}
+
+test "letter isLower" {
+ try std.testing.expect(isLower('a'));
+ try std.testing.expect(isAsciiLower('a'));
+ try std.testing.expect(isLower('é'));
+ try std.testing.expect(isLower('i'));
+ try std.testing.expect(!isLower('A'));
+ try std.testing.expect(!isLower('É'));
+ try std.testing.expect(!isLower('İ'));
+}
+
+test "letter toCaseFold" {
+ var result = toCaseFold('A');
+ try std.testing.expectEqualSlices(u21, &[_]u21{ 'a', 0, 0 }, &result);
+
+ result = toCaseFold('a');
+ try std.testing.expectEqualSlices(u21, &[_]u21{ 'a', 0, 0 }, &result);
+
+ result = toCaseFold('1');
+ try std.testing.expectEqualSlices(u21, &[_]u21{ '1', 0, 0 }, &result);
+
+ result = toCaseFold('\u{00DF}');
+ try std.testing.expectEqualSlices(u21, &[_]u21{ 0x0073, 0x0073, 0 }, &result);
+
+ result = toCaseFold('\u{0390}');
+ try std.testing.expectEqualSlices(u21, &[_]u21{ 0x03B9, 0x0308, 0x0301 }, &result);
+}
+
+test "letter toLower" {
+ try std.testing.expectEqual(toLower('a'), 'a');
+ try std.testing.expectEqual(toLower('A'), 'a');
+ try std.testing.expectEqual(toLower('İ'), 'i');
+ try std.testing.expectEqual(toLower('É'), 'é');
+ try std.testing.expectEqual(toLower(0x80), 0x80);
+ try std.testing.expectEqual(toLower(0x80), 0x80);
+ try std.testing.expectEqual(toLower('Å'), 'å');
+ try std.testing.expectEqual(toLower('å'), 'å');
+ try std.testing.expectEqual(toLower('\u{212A}'), 'k');
+ try std.testing.expectEqual(toLower('1'), '1');
+}
+
+test "letter isUpper" {
+ try std.testing.expect(!isUpper('a'));
+ try std.testing.expect(!isAsciiUpper('a'));
+ try std.testing.expect(!isUpper('é'));
+ try std.testing.expect(!isUpper('i'));
+ try std.testing.expect(isUpper('A'));
+ try std.testing.expect(isUpper('É'));
+ try std.testing.expect(isUpper('İ'));
+}
+
+test "letter toUpper" {
+ try std.testing.expectEqual(toUpper('a'), 'A');
+ try std.testing.expectEqual(toUpper('A'), 'A');
+ try std.testing.expectEqual(toUpper('i'), 'I');
+ try std.testing.expectEqual(toUpper('é'), 'É');
+ try std.testing.expectEqual(toUpper(0x80), 0x80);
+ try std.testing.expectEqual(toUpper('Å'), 'Å');
+ try std.testing.expectEqual(toUpper('å'), 'Å');
+ try std.testing.expectEqual(toUpper('1'), '1');
+}
+
+test "letter isTitle" {
+ try std.testing.expect(!isTitle('a'));
+ try std.testing.expect(!isTitle('é'));
+ try std.testing.expect(!isTitle('i'));
+ try std.testing.expect(isTitle('\u{1FBC}'));
+ try std.testing.expect(isTitle('\u{1FCC}'));
+ try std.testing.expect(isTitle('Lj'));
+}
+
+test "letter toTitle" {
+ try std.testing.expectEqual(toTitle('a'), 'A');
+ try std.testing.expectEqual(toTitle('A'), 'A');
+ try std.testing.expectEqual(toTitle('i'), 'I');
+ try std.testing.expectEqual(toTitle('é'), 'É');
+ try std.testing.expectEqual(toTitle('1'), '1');
+}
+
+test "letter isLetter" {
+ var cp: u21 = 'a';
+ while (cp <= 'z') : (cp += 1) {
+ try std.testing.expect(isLetter(cp));
+ }
+
+ cp = 'A';
+ while (cp <= 'Z') : (cp += 1) {
+ try std.testing.expect(isLetter(cp));
+ }
+
+ try std.testing.expect(isLetter('É'));
+ try std.testing.expect(isLetter('\u{2CEB3}'));
+ try std.testing.expect(!isLetter('\u{0003}'));
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/category/mark.zig.html b/docs/src/ziglyph/category/mark.zig.html
new file mode 100644
index 0000000..740531d
--- /dev/null
+++ b/docs/src/ziglyph/category/mark.zig.html
@@ -0,0 +1,135 @@
+
+
+
+
+
category/mark.zig - source view
+
+
+
+
+
+
+
+const std = @import("std");
+
+const cats = @import("../autogen/derived_general_category.zig");
+
+
+pub fn isMark(cp: u21) bool {
+ return cats.isSpacingMark(cp) or
+ cats.isNonspacingMark(cp) or
+ cats.isEnclosingMark(cp);
+}
+
+test "mark isMark" {
+ try std.testing.expect(isMark('\u{20E4}'));
+ try std.testing.expect(isMark(0x0301));
+ try std.testing.expect(!isMark('='));
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/category/number.zig.html b/docs/src/ziglyph/category/number.zig.html
new file mode 100644
index 0000000..d07c3dc
--- /dev/null
+++ b/docs/src/ziglyph/category/number.zig.html
@@ -0,0 +1,202 @@
+
+
+
+
+
category/number.zig - source view
+
+
+
+
+
+
+
+const std = @import("std");
+
+const cats = @import("../autogen/derived_general_category.zig");
+const numeric = @import("../autogen/derived_numeric_type.zig");
+const props = @import("../autogen/prop_list.zig");
+
+
+pub fn isDecimal(cp: u21) bool {
+
+
+ if ('0' <= cp and cp <= '9') return true;
+ return numeric.isDecimal(cp);
+}
+
+
+pub fn isDigit(cp: u21) bool {
+ return numeric.isDigit(cp);
+}
+
+
+pub fn isAsciiDigit(cp: u21) bool {
+ return '0' <= cp and cp <= '9';
+}
+
+
+pub fn isHexDigit(cp: u21) bool {
+
+
+ if (('a' <= cp and cp <= 'f') or ('A' <= cp and cp <= 'F') or (cp >= '0' and cp <= '9')) return true;
+ return props.isHexDigit(cp);
+}
+
+
+pub fn isAsciiHexDigit(cp: u21) bool {
+ return ('a' <= cp and cp <= 'f') or ('A' <= cp and cp <= 'F') or (cp >= '0' and cp <= '9');
+}
+
+
+pub fn isNumber(cp: u21) bool {
+
+
+ if ('0' <= cp and cp <= '9') return true;
+ return isDecimal(cp) or
+ isDigit(cp) or
+ numeric.isNumeric(cp);
+}
+
+
+pub fn isAsciiNumber(cp: u21) bool {
+ return '0' <= cp and cp <= '9';
+}
+
+test "number isDecimal" {
+ var cp: u21 = '0';
+ while (cp <= '9') : (cp += 1) {
+ try std.testing.expect(isDecimal(cp));
+ try std.testing.expect(isAsciiDigit(cp));
+ try std.testing.expect(isAsciiNumber(cp));
+ }
+
+ try std.testing.expect(!isDecimal('\u{0003}'));
+ try std.testing.expect(!isDecimal('A'));
+}
+
+test "number isHexDigit" {
+ var cp: u21 = '0';
+ while (cp <= '9') : (cp += 1) {
+ try std.testing.expect(isHexDigit(cp));
+ }
+
+ try std.testing.expect(!isHexDigit('\u{0003}'));
+ try std.testing.expect(!isHexDigit('Z'));
+}
+
+test "number isNumber" {
+ var cp: u21 = '0';
+ while (cp <= '9') : (cp += 1) {
+ try std.testing.expect(isNumber(cp));
+ }
+
+ try std.testing.expect(!isNumber('\u{0003}'));
+ try std.testing.expect(!isNumber('A'));
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/category/punct.zig.html b/docs/src/ziglyph/category/punct.zig.html
new file mode 100644
index 0000000..ee05752
--- /dev/null
+++ b/docs/src/ziglyph/category/punct.zig.html
@@ -0,0 +1,163 @@
+
+
+
+
+
category/punct.zig - source view
+
+
+
+
+
+
+
+const std = @import("std");
+
+const cats = @import("../autogen/derived_general_category.zig");
+
+
+pub fn isPunct(cp: u21) bool {
+ return cats.isInitialPunctuation(cp) or
+ cats.isFinalPunctuation(cp) or
+ cats.isOpenPunctuation(cp) or
+ cats.isClosePunctuation(cp) or
+ cats.isConnectorPunctuation(cp) or
+ cats.isDashPunctuation(cp) or
+ cats.isOtherPunctuation(cp);
+}
+
+test "punct isPunct" {
+ try std.testing.expect(isPunct('!'));
+ try std.testing.expect(isPunct('?'));
+ try std.testing.expect(isPunct(','));
+ try std.testing.expect(isPunct('.'));
+ try std.testing.expect(isPunct(':'));
+ try std.testing.expect(isPunct(';'));
+ try std.testing.expect(isPunct('\''));
+ try std.testing.expect(isPunct('"'));
+ try std.testing.expect(isPunct('¿'));
+ try std.testing.expect(isPunct('¡'));
+ try std.testing.expect(isPunct('-'));
+ try std.testing.expect(isPunct('('));
+ try std.testing.expect(isPunct(')'));
+ try std.testing.expect(isPunct('{'));
+ try std.testing.expect(isPunct('}'));
+ try std.testing.expect(isPunct('–'));
+
+
+ try std.testing.expect(isPunct('@'));
+ try std.testing.expect(isPunct('#'));
+ try std.testing.expect(isPunct('%'));
+ try std.testing.expect(isPunct('&'));
+ try std.testing.expect(isPunct('*'));
+ try std.testing.expect(isPunct('_'));
+ try std.testing.expect(isPunct('/'));
+ try std.testing.expect(isPunct('\\'));
+ try std.testing.expect(!isPunct('\u{0003}'));
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/collator/Collator.zig.html b/docs/src/ziglyph/collator/Collator.zig.html
new file mode 100644
index 0000000..58e0e0e
--- /dev/null
+++ b/docs/src/ziglyph/collator/Collator.zig.html
@@ -0,0 +1,639 @@
+
+
+
+
+
collator/Collator.zig - source view
+
+
+
+
+
+
const std = @import("std");
+
+const ccc_map = @import("../autogen/derived_combining_class.zig");
+const CodePointIterator = @import("../segmenter/CodePoint.zig").CodePointIterator;
+const Normalizer = @import("../normalizer/Normalizer.zig");
+const props = @import("../autogen/prop_list.zig");
+
+const Element = struct {
+ l1: u16 = 0,
+ l2: u16 = 0,
+ l3: u8 = 0,
+};
+
+const Implicit = struct {
+ start: u21,
+ end: u21,
+ base: u16,
+};
+
+const Self = @This();
+
+ducet: std.AutoHashMap([3]u21, [18]?Element),
+implicits: [4]Implicit,
+normalizer: Normalizer,
+
+pub fn init(allocator: std.mem.Allocator) !Self {
+ var self = Self{
+ .ducet = std.AutoHashMap([3]u21, [18]?Element).init(allocator),
+ .implicits = undefined,
+ .normalizer = try Normalizer.init(allocator),
+ };
+ errdefer self.deinit();
+
+
+
+ const ak_file = @embedFile("../data/allkeys-diffs.txt.deflate");
+ var ak_fb = std.io.fixedBufferStream(ak_file);
+ var ak_comp = try std.compress.deflate.decompressor(allocator, ak_fb.reader(), null);
+ defer ak_comp.deinit();
+ var ak_br = std.io.bufferedReader(ak_comp.reader());
+ const ak_reader = ak_br.reader();
+
+ var buf: [4096]u8 = undefined;
+ var line_num: usize = 0;
+
+
+
+ var prev_cp: u21 = 0;
+ var cp_diff: isize = 0;
+ var prev_l1: u16 = 0;
+ var l1_diff: isize = 0;
+
+ while (try ak_reader.readUntilDelimiterOrEof(&buf, '\n')) |line| : (line_num += 1) {
+ var fields = std.mem.split(u8, line, ";");
+
+
+
+ if (line_num < 4) {
+ self.implicits[line_num] = Implicit{
+ .start = try std.fmt.parseInt(u21, fields.next().?, 16),
+ .end = try std.fmt.parseInt(u21, fields.next().?, 16),
+ .base = try std.fmt.parseInt(u16, fields.next().?, 16),
+ };
+
+ continue;
+ }
+
+ var i: usize = 0;
+ var cps = [_]u21{0} ** 3;
+ var cp_diff_strs = std.mem.split(u8, fields.next().?, " ");
+
+ while (cp_diff_strs.next()) |cp_diff_str| : (i += 1) {
+ cp_diff = try std.fmt.parseInt(isize, cp_diff_str, 16);
+ prev_cp = @intCast(@as(isize, prev_cp) + cp_diff);
+ cps[i] = prev_cp;
+ }
+
+ i = 0;
+ var elements = [_]?Element{null} ** 18;
+
+ while (fields.next()) |element_diff_str| : (i += 1) {
+
+
+ if (std.mem.indexOf(u8, element_diff_str, ".") == null) {
+ l1_diff = try std.fmt.parseInt(isize, element_diff_str, 16);
+ prev_l1 = @intCast(@as(isize, prev_l1) + l1_diff);
+
+ elements[i] = Element{
+ .l1 = prev_l1,
+ .l2 = 0x20,
+ .l3 = 0x2,
+ };
+
+ continue;
+ }
+
+ var weight_strs = std.mem.split(u8, element_diff_str, ".");
+ l1_diff = try std.fmt.parseInt(isize, weight_strs.next().?, 16);
+ prev_l1 = @intCast(@as(isize, prev_l1) + l1_diff);
+ elements[i] = Element{ .l1 = prev_l1 };
+
+ var j: usize = 0;
+ while (weight_strs.next()) |weight_str| : (j += 1) {
+ if (weight_str.len == 1 and weight_str[0] == ')') {
+ elements[i].?.l2 = 0;
+ elements[i].?.l3 = 0;
+ break;
+ }
+
+ if (weight_str[0] == '@') {
+ elements[i].?.l2 = 0x20;
+ elements[i].?.l3 = try std.fmt.parseInt(u8, weight_str[1..], 16);
+ break;
+ }
+
+ switch (j) {
+ 0 => elements[i].?.l2 = try std.fmt.parseInt(u16, weight_str, 16),
+ 1 => elements[i].?.l3 = try std.fmt.parseInt(u8, weight_str, 16),
+ else => unreachable,
+ }
+ }
+ }
+
+ try self.ducet.put(cps, elements);
+ }
+
+ return self;
+}
+
+pub fn deinit(self: *Self) void {
+ self.ducet.deinit();
+ self.normalizer.deinit();
+}
+
+test "init / deinit" {
+ var c = try init(std.testing.allocator);
+ defer c.deinit();
+
+ try std.testing.expectEqual(@as(u16, 0xfb00), c.implicits[0].base);
+
+
+ try std.testing.expectEqual(@as(usize, 32130), c.ducet.count());
+
+}
+
+fn implicitWeight(self: Self, cp: u21) [18]?Element {
+ var base: u16 = 0;
+ var aaaa: u16 = 0;
+ var bbbb: u16 = 0;
+
+ if (props.isUnifiedIdeograph(cp) and ((0x4E00 <= cp and cp <= 0x9FFF) or (0xF900 <= cp and cp <= 0xFAFF))) {
+ base = 0xFB40;
+ aaaa = base + @as(u16, @intCast((cp >> 15)));
+ bbbb = @as(u16, @intCast((cp & 0x7FFF))) | 0x8000;
+ } else if (props.isUnifiedIdeograph(cp) and !((0x4E00 <= cp and cp <= 0x9FFF) or (0xF900 <= cp and cp <= 0xFAFF))) {
+ base = 0xFB80;
+ aaaa = base + @as(u16, @intCast((cp >> 15)));
+ bbbb = @as(u16, @intCast((cp & 0x7FFF))) | 0x8000;
+ } else {
+ for (self.implicits) |implicit| {
+ if (implicit.start <= cp and cp <= implicit.end) {
+ aaaa = implicit.base;
+
+ if (0x18D00 <= cp and cp <= 0x18D8F) {
+ bbbb = @as(u16, @truncate((cp - 17000))) | 0x8000;
+ } else {
+ bbbb = @as(u16, @intCast((cp - implicit.start))) | 0x8000;
+ }
+
+ break;
+ }
+ }
+
+ if (aaaa == 0) {
+ base = 0xFBC0;
+ aaaa = base + @as(u16, @intCast((cp >> 15)));
+ bbbb = @as(u16, @intCast((cp & 0x7FFF))) | 0x8000;
+ }
+ }
+
+ var elements = [_]?Element{null} ** 18;
+ elements[0] = Element{ .l1 = aaaa, .l2 = 0x0020, .l3 = 0x0002 };
+ elements[1] = Element{ .l1 = bbbb, .l2 = 0x0000, .l3 = 0x0000 };
+
+ return elements;
+}
+
+fn getElements(self: Self, allocator: std.mem.Allocator, str: []const u8) ![]const Element {
+ std.debug.assert(str.len > 0);
+
+ var normalized = try self.normalizer.nfd(allocator, str);
+ defer normalized.deinit();
+
+ var cp_list = try std.ArrayList(u21).initCapacity(allocator, normalized.slice.len);
+ defer cp_list.deinit();
+ var cp_iter = CodePointIterator{ .bytes = normalized.slice };
+ while (cp_iter.next()) |cp| cp_list.appendAssumeCapacity(cp.code);
+
+ var all_elements = std.ArrayList(Element).init(allocator);
+ defer all_elements.deinit();
+
+ var cp_index: usize = 0;
+
+ while (cp_index < cp_list.items.len) {
+ var S: [3]u21 = undefined;
+ var s_len: usize = 3;
+ var elements: ?[18]?Element = null;
+
+ if (cp_list.items.len > cp_index + 2) {
+ S[0] = cp_list.items[cp_index];
+ S[1] = cp_list.items[cp_index + 1];
+ S[2] = cp_list.items[cp_index + 2];
+ elements = self.ducet.get(S);
+ }
+
+ if (elements == null and cp_list.items.len > cp_index + 1) {
+ S[0] = cp_list.items[cp_index];
+ S[1] = cp_list.items[cp_index + 1];
+ S[2] = 0;
+ s_len = 2;
+ elements = self.ducet.get(S);
+ }
+
+ if (elements == null) {
+ S[0] = cp_list.items[cp_index];
+ S[1] = 0;
+ S[2] = 0;
+ s_len = 1;
+ elements = self.ducet.get(S);
+ }
+
+ if (elements != null and s_len < 3) {
+
+
+ var prev_ccc: ?u8 = null;
+ const tail_start = cp_index + s_len;
+
+ var tail_index = tail_start;
+
+
+
+ while (tail_index < cp_list.items.len) : (tail_index += 1) {
+ const ccc = ccc_map.combiningClass(cp_list.items[tail_index]);
+ if (ccc == 0 or (prev_ccc != null and prev_ccc.? >= ccc)) break;
+ prev_ccc = ccc;
+ }
+
+ if (tail_start != tail_index) {
+
+ S[s_len] = cp_list.items[tail_index - 1];
+
+ s_len += 1;
+
+ if (self.ducet.get(S)) |sc_elements| {
+
+
+ const segment = cp_list.items[tail_start..tail_index];
+ std.mem.rotate(u21, segment, segment.len - 1);
+
+
+
+ for (sc_elements) |element_opt| {
+ if (element_opt) |element| {
+ try all_elements.append(element);
+ } else {
+ break;
+ }
+ }
+
+ cp_index += s_len;
+
+
+ continue;
+ }
+
+ if (s_len < 3) S[s_len] = 0;
+
+ s_len -= 1;
+ }
+ }
+
+ if (elements == null) {
+
+
+ elements = self.implicitWeight(cp_list.items[cp_index]);
+ }
+
+
+
+ for (elements.?) |element_opt| {
+ if (element_opt) |element| {
+ try all_elements.append(element);
+ } else {
+ break;
+ }
+ }
+
+ cp_index += s_len;
+
+ }
+
+ return all_elements.toOwnedSlice();
+}
+
+test "getElements" {
+ var c = try init(std.testing.allocator);
+ defer c.deinit();
+
+ const elements_1 = try c.getElements(std.testing.allocator, "ca\u{301}b");
+ defer std.testing.allocator.free(elements_1);
+
+ try std.testing.expectEqual(@as(usize, 4), elements_1.len);
+ try std.testing.expectEqual(@as(u16, 0x20e7), elements_1[0].l1);
+ try std.testing.expectEqual(@as(u16, 0x20b3), elements_1[1].l1);
+ try std.testing.expectEqual(@as(u16, 0x0024), elements_1[2].l2);
+ try std.testing.expectEqual(@as(u16, 0x20cd), elements_1[3].l1);
+
+ const elements_2 = try c.getElements(std.testing.allocator, "\u{0CC6}\u{0CC2}\u{0CD5}");
+ defer std.testing.allocator.free(elements_2);
+
+ try std.testing.expectEqual(@as(usize, 1), elements_2.len);
+ try std.testing.expectEqual(@as(u16, 0x2D59), elements_2[0].l1);
+ try std.testing.expectEqual(@as(u16, 0x0020), elements_2[0].l2);
+ try std.testing.expectEqual(@as(u16, 0x0002), elements_2[0].l3);
+}
+
+
+pub fn sortKey(self: Self, allocator: std.mem.Allocator, str: []const u8) ![]const u16 {
+ const elements = try self.getElements(allocator, str);
+ defer allocator.free(elements);
+
+ var sort_key = std.ArrayList(u16).init(allocator);
+ defer sort_key.deinit();
+
+ var level: usize = 0;
+ while (level < 3) : (level += 1) {
+ if (level != 0) try sort_key.append(0);
+
+
+ for (elements) |element| {
+ switch (level) {
+ 0 => if (element.l1 != 0) try sort_key.append(element.l1),
+ 1 => if (element.l2 != 0) try sort_key.append(element.l2),
+ 2 => if (element.l3 != 0) try sort_key.append(element.l3),
+ else => unreachable,
+ }
+ }
+ }
+
+ return sort_key.toOwnedSlice();
+}
+
+
+pub fn primaryOrder(a: []const u16, b: []const u16) std.math.Order {
+ return for (a, 0..) |weight, i| {
+ if (weight == 0) break .eq;
+
+ const order = std.math.order(weight, b[i]);
+ if (order != .eq) break order;
+ } else .eq;
+}
+
+
+pub fn secondaryOrder(a: []const u16, b: []const u16) std.math.Order {
+ var last_level = false;
+
+ return for (a, 0..) |weight, i| {
+ if (weight == 0) {
+ if (last_level) break .eq else last_level = true;
+ continue;
+ }
+
+ const order = std.math.order(weight, b[i]);
+ if (order != .eq) break order;
+ } else .eq;
+}
+
+
+pub fn tertiaryOrder(a: []const u16, b: []const u16) std.math.Order {
+ return for (a, 0..) |weight, i| {
+ const order = std.math.order(weight, b[i]);
+ if (order != .eq) break order;
+ } else .eq;
+}
+
+test "key order" {
+ var c = try init(std.testing.allocator);
+ defer c.deinit();
+
+ const key_a = try c.sortKey(std.testing.allocator, "cab");
+ defer std.testing.allocator.free(key_a);
+ const key_b = try c.sortKey(std.testing.allocator, "Cab");
+ defer std.testing.allocator.free(key_b);
+
+ try std.testing.expectEqual(std.math.Order.eq, primaryOrder(key_a, key_b));
+ try std.testing.expectEqual(std.math.Order.eq, secondaryOrder(key_a, key_b));
+ try std.testing.expectEqual(std.math.Order.lt, tertiaryOrder(key_a, key_b));
+}
+
+test "key order with combining" {
+ var c = try init(std.testing.allocator);
+ defer c.deinit();
+
+ const key_a = try c.sortKey(std.testing.allocator, "ca\u{301}b");
+ defer std.testing.allocator.free(key_a);
+ const key_b = try c.sortKey(std.testing.allocator, "Cab");
+ defer std.testing.allocator.free(key_b);
+
+ try std.testing.expectEqual(std.math.Order.eq, primaryOrder(key_a, key_b));
+ try std.testing.expectEqual(std.math.Order.gt, secondaryOrder(key_a, key_b));
+ try std.testing.expectEqual(std.math.Order.gt, tertiaryOrder(key_a, key_b));
+}
+
+
+
+pub fn ascending(self: Self, a: []const u8, b: []const u8) bool {
+ const key_a = self.sortKey(self.ducet.allocator, a) catch return false;
+ defer self.ducet.allocator.free(key_a);
+ const key_b = self.sortKey(self.ducet.allocator, b) catch return false;
+ defer self.ducet.allocator.free(key_b);
+
+ return tertiaryOrder(key_a, key_b) == .lt;
+}
+
+
+
+pub fn descending(self: Self, a: []const u8, b: []const u8) bool {
+ const key_a = self.sortKey(self.ducet.allocator, a) catch return false;
+ defer self.ducet.allocator.free(key_a);
+ const key_b = self.sortKey(self.ducet.allocator, b) catch return false;
+ defer self.ducet.allocator.free(key_b);
+
+ return tertiaryOrder(key_a, key_b) == .gt;
+}
+
+test "sort functions" {
+ var c = try init(std.testing.allocator);
+ defer c.deinit();
+
+ var strings = [_][]const u8{ "def", "xyz", "abc" };
+ var want = [_][]const u8{ "abc", "def", "xyz" };
+
+ std.mem.sort([]const u8, &strings, c, ascending);
+ try std.testing.expectEqualSlices([]const u8, &want, &strings);
+
+ want = [_][]const u8{ "xyz", "def", "abc" };
+ std.mem.sort([]const u8, &strings, c, descending);
+ try std.testing.expectEqualSlices([]const u8, &want, &strings);
+}
+
+
+
+pub fn ascendingCaseless(self: Self, a: []const u8, b: []const u8) bool {
+ const key_a = self.sortKey(self.ducet.allocator, a) catch return false;
+ defer self.ducet.allocator.free(key_a);
+ const key_b = self.sortKey(self.ducet.allocator, b) catch return false;
+ defer self.ducet.allocator.free(key_b);
+
+ return secondaryOrder(key_a, key_b) == .lt;
+}
+
+
+
+pub fn descendingCaseless(self: Self, a: []const u8, b: []const u8) bool {
+ const key_a = self.sortKey(self.ducet.allocator, a) catch return false;
+ defer self.ducet.allocator.free(key_a);
+ const key_b = self.sortKey(self.ducet.allocator, b) catch return false;
+ defer self.ducet.allocator.free(key_b);
+
+ return secondaryOrder(key_a, key_b) == .gt;
+}
+
+test "caseless sort functions" {
+ var c = try init(std.testing.allocator);
+ defer c.deinit();
+
+ var strings = [_][]const u8{ "def", "Abc", "abc" };
+ var want = [_][]const u8{ "Abc", "abc", "def" };
+
+ std.mem.sort([]const u8, &strings, c, ascendingCaseless);
+ try std.testing.expectEqualSlices([]const u8, &want, &strings);
+
+ want = [_][]const u8{ "def", "Abc", "abc" };
+ std.mem.sort([]const u8, &strings, c, descendingCaseless);
+ try std.testing.expectEqualSlices([]const u8, &want, &strings);
+}
+
+test "caseless / markless sort functions" {
+ var c = try init(std.testing.allocator);
+ defer c.deinit();
+
+ var strings = [_][]const u8{ "ábc", "Abc", "abc" };
+ const want = [_][]const u8{ "ábc", "Abc", "abc" };
+
+ std.mem.sort([]const u8, &strings, c, ascendingBase);
+ try std.testing.expectEqualSlices([]const u8, &want, &strings);
+
+ std.mem.sort([]const u8, &strings, c, descendingBase);
+ try std.testing.expectEqualSlices([]const u8, &want, &strings);
+}
+
+
+
+pub fn ascendingBase(self: Self, a: []const u8, b: []const u8) bool {
+ const key_a = self.sortKey(self.ducet.allocator, a) catch return false;
+ defer self.ducet.allocator.free(key_a);
+ const key_b = self.sortKey(self.ducet.allocator, b) catch return false;
+ defer self.ducet.allocator.free(key_b);
+
+ return primaryOrder(key_a, key_b) == .lt;
+}
+
+
+
+pub fn descendingBase(self: Self, a: []const u8, b: []const u8) bool {
+ const key_a = self.sortKey(self.ducet.allocator, a) catch return false;
+ defer self.ducet.allocator.free(key_a);
+ const key_b = self.sortKey(self.ducet.allocator, b) catch return false;
+ defer self.ducet.allocator.free(key_b);
+
+ return primaryOrder(key_a, key_b) == .gt;
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/display_width.zig.html b/docs/src/ziglyph/display_width.zig.html
new file mode 100644
index 0000000..ffe37c8
--- /dev/null
+++ b/docs/src/ziglyph/display_width.zig.html
@@ -0,0 +1,540 @@
+
+
+
+
+
display_width.zig - source view
+
+
+
+
+
+
+
+
+const std = @import("std");
+const unicode = std.unicode;
+
+const cats = @import("ziglyph.zig").general_category;
+const eaw = @import("ziglyph.zig").east_asian_width;
+const emoji = @import("ziglyph.zig").emoji;
+const gbp = @import("ziglyph.zig").grapheme_break;
+const GraphemeIterator = @import("ziglyph.zig").GraphemeIterator;
+const Word = @import("ziglyph.zig").Word;
+const WordIterator = Word.WordIterator;
+
+fn isAsciiStr(str: []const u8) bool {
+ return for (str) |b| {
+ if (b > 127) break false;
+ } else true;
+}
+
+
+
+
+pub const AmbiguousWidth = enum(u2) {
+ half = 1,
+ full = 2,
+};
+
+
+
+pub fn codePointWidth(cp: u21, am_width: AmbiguousWidth) i3 {
+ if (cp == 0x000 or cp == 0x0005 or cp == 0x0007 or (cp >= 0x000A and cp <= 0x000F)) {
+
+
+ return 0;
+ } else if (cp == 0x0008 or cp == 0x007F) {
+
+
+ return -1;
+ } else if (cp == 0x00AD) {
+
+
+ return 1;
+ } else if (cp == 0x2E3A) {
+
+
+ return 2;
+ } else if (cp == 0x2E3B) {
+
+
+ return 3;
+ } else if (cats.isEnclosingMark(cp) or cats.isNonspacingMark(cp)) {
+
+
+ return 0;
+ } else if (cats.isFormat(cp) and (!(cp >= 0x0600 and cp <= 0x0605) and cp != 0x061C and
+ cp != 0x06DD and cp != 0x08E2))
+ {
+
+
+ return 0;
+ } else if ((cp >= 0x1160 and cp <= 0x11FF) or (cp >= 0x2060 and cp <= 0x206F) or
+ (cp >= 0xFFF0 and cp <= 0xFFF8) or (cp >= 0xE0000 and cp <= 0xE0FFF))
+ {
+
+
+ return 0;
+ } else if ((cp >= 0x3400 and cp <= 0x4DBF) or (cp >= 0x4E00 and cp <= 0x9FFF) or
+ (cp >= 0xF900 and cp <= 0xFAFF) or (cp >= 0x20000 and cp <= 0x2FFFD) or
+ (cp >= 0x30000 and cp <= 0x3FFFD))
+ {
+ return 2;
+ } else if (eaw.isWide(cp) or eaw.isFullwidth(cp)) {
+ return 2;
+ } else if (gbp.isRegionalIndicator(cp)) {
+ return 2;
+ } else if (eaw.isAmbiguous(cp)) {
+ return @intFromEnum(am_width);
+ } else {
+ return 1;
+ }
+}
+
+
+
+pub fn strWidth(str: []const u8, am_width: AmbiguousWidth) !usize {
+ var total: isize = 0;
+
+
+
+ if (isAsciiStr(str)) {
+ for (str) |b| {
+
+
+ if (b == 8 or b == 127) {
+ total -= 1;
+ continue;
+ }
+
+
+
+ if (b < 32) continue;
+
+
+
+ total += 1;
+ }
+
+ return if (total > 0) @intCast(total) else 0;
+ }
+
+ var giter = GraphemeIterator.init(str);
+
+ while (giter.next()) |gc| {
+ var cp_iter = (try unicode.Utf8View.init(str[gc.offset .. gc.offset + gc.len])).iterator();
+
+ while (cp_iter.nextCodepoint()) |cp| {
+ var w = codePointWidth(cp, am_width);
+
+ if (w != 0) {
+
+
+ if (emoji.isExtendedPictographic(cp)) {
+ if (cp_iter.nextCodepoint()) |ncp| {
+
+
+ if (ncp == 0xFE0E) w = 1;
+ if (ncp == 0xFE0F) w = 2;
+ }
+ }
+ total += w;
+ break;
+ }
+ }
+ }
+
+ return if (total > 0) @intCast(total) else 0;
+}
+
+
+
+
+
+pub fn center(allocator: std.mem.Allocator, str: []const u8, total_width: usize, pad: []const u8) ![]u8 {
+ const str_width = try strWidth(str, .half);
+ if (str_width > total_width) return error.StrTooLong;
+ if (str_width == total_width) return try allocator.dupe(u8, str);
+
+ const pad_width = try strWidth(pad, .half);
+ if (pad_width > total_width or str_width + pad_width > total_width) return error.PadTooLong;
+
+ const margin_width = @divFloor((total_width - str_width), 2);
+ if (pad_width > margin_width) return error.PadTooLong;
+ const extra_pad: usize = if (total_width % 2 != str_width % 2) 1 else 0;
+ const pads = @divFloor(margin_width, pad_width) * 2 + extra_pad;
+
+ var result = try allocator.alloc(u8, pads * pad.len + str.len);
+ var bytes_index: usize = 0;
+ var pads_index: usize = 0;
+
+ while (pads_index < pads / 2) : (pads_index += 1) {
+ @memcpy(result[bytes_index..][0..pad.len], pad);
+ bytes_index += pad.len;
+ }
+
+ @memcpy(result[bytes_index..][0..str.len], str);
+ bytes_index += str.len;
+
+ pads_index = 0;
+ while (pads_index < pads / 2 + extra_pad) : (pads_index += 1) {
+ @memcpy(result[bytes_index..][0..pad.len], pad);
+ bytes_index += pad.len;
+ }
+
+ return result;
+}
+
+
+
+pub fn padLeft(allocator: std.mem.Allocator, str: []const u8, total_width: usize, pad: []const u8) ![]u8 {
+ const str_width = try strWidth(str, .half);
+ if (str_width > total_width) return error.StrTooLong;
+
+ const pad_width = try strWidth(pad, .half);
+ if (pad_width > total_width or str_width + pad_width > total_width) return error.PadTooLong;
+
+ const margin_width = total_width - str_width;
+ if (pad_width > margin_width) return error.PadTooLong;
+
+ const pads = @divFloor(margin_width, pad_width);
+
+ var result = try allocator.alloc(u8, pads * pad.len + str.len);
+ var bytes_index: usize = 0;
+ var pads_index: usize = 0;
+
+ while (pads_index < pads) : (pads_index += 1) {
+ @memcpy(result[bytes_index..][0..pad.len], pad);
+ bytes_index += pad.len;
+ }
+
+ @memcpy(result[bytes_index..][0..str.len], str);
+
+ return result;
+}
+
+
+
+pub fn padRight(allocator: std.mem.Allocator, str: []const u8, total_width: usize, pad: []const u8) ![]u8 {
+ const str_width = try strWidth(str, .half);
+ if (str_width > total_width) return error.StrTooLong;
+
+ const pad_width = try strWidth(pad, .half);
+ if (pad_width > total_width or str_width + pad_width > total_width) return error.PadTooLong;
+
+ const margin_width = total_width - str_width;
+ if (pad_width > margin_width) return error.PadTooLong;
+
+ const pads = @divFloor(margin_width, pad_width);
+
+ var result = try allocator.alloc(u8, pads * pad.len + str.len);
+ var bytes_index: usize = 0;
+ var pads_index: usize = 0;
+
+ @memcpy(result[bytes_index..][0..str.len], str);
+ bytes_index += str.len;
+
+ while (pads_index < pads) : (pads_index += 1) {
+ @memcpy(result[bytes_index..][0..pad.len], pad);
+ bytes_index += pad.len;
+ }
+
+ return result;
+}
+
+
+
+pub fn wrap(allocator: std.mem.Allocator, str: []const u8, columns: usize, threshold: usize) ![]u8 {
+ var iter = try WordIterator.init(str);
+ var result = std.ArrayList(u8).init(allocator);
+ defer result.deinit();
+ var line_width: usize = 0;
+
+ while (iter.next()) |word| {
+ if (isLineBreak(word.bytes)) {
+ try result.append(' ');
+ continue;
+ }
+ try result.appendSlice(word.bytes);
+ line_width += try strWidth(word.bytes, .half);
+
+ if (line_width > columns or columns - line_width <= threshold) {
+ try result.append('\n');
+ line_width = 0;
+ }
+ }
+
+ return result.toOwnedSlice();
+}
+
+fn isLineBreak(str: []const u8) bool {
+ if (std.mem.eql(u8, str, "\r\n")) {
+ return true;
+ } else if (std.mem.eql(u8, str, "\r")) {
+ return true;
+ } else if (std.mem.eql(u8, str, "\n")) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+test "display_width Width" {
+ try std.testing.expectEqual(@as(i8, -1), codePointWidth(0x0008, .half));
+
+ try std.testing.expectEqual(@as(i8, 0), codePointWidth(0x0000, .half));
+
+ try std.testing.expectEqual(@as(i8, 0), codePointWidth(0x0005, .half));
+
+ try std.testing.expectEqual(@as(i8, 0), codePointWidth(0x0007, .half));
+
+ try std.testing.expectEqual(@as(i8, 0), codePointWidth(0x000A, .half));
+
+ try std.testing.expectEqual(@as(i8, 0), codePointWidth(0x000B, .half));
+
+ try std.testing.expectEqual(@as(i8, 0), codePointWidth(0x000C, .half));
+
+ try std.testing.expectEqual(@as(i8, 0), codePointWidth(0x000D, .half));
+
+ try std.testing.expectEqual(@as(i8, 0), codePointWidth(0x000E, .half));
+
+ try std.testing.expectEqual(@as(i8, 0), codePointWidth(0x000F, .half));
+
+
+ try std.testing.expectEqual(@as(i8, 0), codePointWidth(0x070F, .half));
+
+ try std.testing.expectEqual(@as(i8, 1), codePointWidth(0x0603, .half));
+
+
+ try std.testing.expectEqual(@as(i8, 1), codePointWidth(0x00AD, .half));
+
+ try std.testing.expectEqual(@as(i8, 2), codePointWidth(0x2E3A, .half));
+
+ try std.testing.expectEqual(@as(i8, 3), codePointWidth(0x2E3B, .half));
+
+
+ try std.testing.expectEqual(@as(i8, 1), codePointWidth(0x00BD, .half));
+
+ try std.testing.expectEqual(@as(i8, 2), codePointWidth(0x00BD, .full));
+
+
+ try std.testing.expectEqual(@as(i8, 1), codePointWidth('é', .half));
+ try std.testing.expectEqual(@as(i8, 2), codePointWidth('😊', .half));
+ try std.testing.expectEqual(@as(i8, 2), codePointWidth('统', .half));
+
+ try std.testing.expectEqual(@as(usize, 5), try strWidth("Hello\r\n", .half));
+ try std.testing.expectEqual(@as(usize, 1), try strWidth("\u{0065}\u{0301}", .half));
+ try std.testing.expectEqual(@as(usize, 2), try strWidth("\u{1F476}\u{1F3FF}\u{0308}\u{200D}\u{1F476}\u{1F3FF}", .half));
+ try std.testing.expectEqual(@as(usize, 8), try strWidth("Hello 😊", .half));
+ try std.testing.expectEqual(@as(usize, 8), try strWidth("Héllo 😊", .half));
+ try std.testing.expectEqual(@as(usize, 8), try strWidth("Héllo :)", .half));
+ try std.testing.expectEqual(@as(usize, 8), try strWidth("Héllo 🇪🇸", .half));
+ try std.testing.expectEqual(@as(usize, 2), try strWidth("\u{26A1}", .half));
+
+ try std.testing.expectEqual(@as(usize, 1), try strWidth("\u{26A1}\u{FE0E}", .half));
+
+ try std.testing.expectEqual(@as(usize, 2), try strWidth("\u{26A1}\u{FE0F}", .half));
+
+ try std.testing.expectEqual(@as(usize, 1), try strWidth("\u{2764}", .half));
+
+ try std.testing.expectEqual(@as(usize, 1), try strWidth("\u{2764}\u{FE0E}", .half));
+
+ try std.testing.expectEqual(@as(usize, 2), try strWidth("\u{2764}\u{FE0F}", .half));
+
+ try std.testing.expectEqual(@as(usize, 0), try strWidth("A\x08", .half));
+
+ try std.testing.expectEqual(@as(usize, 0), try strWidth("\x7FA", .half));
+
+ try std.testing.expectEqual(@as(usize, 0), try strWidth("\x7FA\x08\x08", .half));
+
+}
+
+test "display_width center" {
+ var allocator = std.testing.allocator;
+
+
+
+ var centered = try center(allocator, "abc", 9, "*");
+ try std.testing.expectEqualSlices(u8, "***abc***", centered);
+
+
+
+ allocator.free(centered);
+ centered = try center(allocator, "w😊w", 10, "-");
+ try std.testing.expectEqualSlices(u8, "---w😊w---", centered);
+
+
+
+ allocator.free(centered);
+ centered = try center(allocator, "1234", 9, "-");
+ try std.testing.expectEqualSlices(u8, "--1234---", centered);
+
+
+
+ allocator.free(centered);
+ centered = try center(allocator, "123", 8, "-");
+ try std.testing.expectEqualSlices(u8, "--123---", centered);
+
+
+
+ allocator.free(centered);
+ centered = try center(allocator, "123", 3, "-");
+ try std.testing.expectEqualSlices(u8, "123", centered);
+
+
+
+ allocator.free(centered);
+ centered = try center(allocator, "", 3, "-");
+ try std.testing.expectEqualSlices(u8, "---", centered);
+
+
+
+ allocator.free(centered);
+ centered = try center(allocator, "", 0, "-");
+ try std.testing.expectEqualSlices(u8, "", centered);
+
+
+
+ allocator.free(centered);
+ try std.testing.expectError(error.StrTooLong, center(allocator, "123", 2, "-"));
+}
+
+test "display_width padLeft" {
+ var allocator = std.testing.allocator;
+
+ var right_aligned = try padLeft(allocator, "abc", 9, "*");
+ defer allocator.free(right_aligned);
+ try std.testing.expectEqualSlices(u8, "******abc", right_aligned);
+
+ allocator.free(right_aligned);
+ right_aligned = try padLeft(allocator, "w😊w", 10, "-");
+ try std.testing.expectEqualSlices(u8, "------w😊w", right_aligned);
+}
+
+test "display_width padRight" {
+ var allocator = std.testing.allocator;
+
+ var left_aligned = try padRight(allocator, "abc", 9, "*");
+ defer allocator.free(left_aligned);
+ try std.testing.expectEqualSlices(u8, "abc******", left_aligned);
+
+ allocator.free(left_aligned);
+ left_aligned = try padRight(allocator, "w😊w", 10, "-");
+ try std.testing.expectEqualSlices(u8, "w😊w------", left_aligned);
+}
+
+test "display_width wrap" {
+ var allocator = std.testing.allocator;
+ const input = "The quick brown fox\r\njumped over the lazy dog!";
+ const got = try wrap(allocator, input, 10, 3);
+ defer allocator.free(got);
+ const want = "The quick\n brown \nfox jumped\n over the\n lazy dog\n!";
+ try std.testing.expectEqualStrings(want, got);
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/normalizer/Normalizer.zig.html b/docs/src/ziglyph/normalizer/Normalizer.zig.html
new file mode 100644
index 0000000..da50e1b
--- /dev/null
+++ b/docs/src/ziglyph/normalizer/Normalizer.zig.html
@@ -0,0 +1,902 @@
+
+
+
+
+
normalizer/Normalizer.zig - source view
+
+
+
+
+
+
+
+
+
+const std = @import("std");
+
+const CodePointIterator = @import("../segmenter/CodePoint.zig").CodePointIterator;
+const case_fold_map = @import("../autogen/case_folding.zig");
+const ccc_map = @import("../autogen/derived_combining_class.zig");
+const hangul_map = @import("../autogen/hangul_syllable_type.zig");
+const norm_props = @import("../autogen/derived_normalization_props.zig");
+
+const Self = @This();
+
+nfc_map: std.AutoHashMap([2]u21, u21),
+nfd_map: std.AutoHashMap(u21, [2]u21),
+nfkd_map: std.AutoHashMap(u21, [18]u21),
+
+pub fn init(allocator: std.mem.Allocator) !Self {
+ var self = Self{
+ .nfc_map = std.AutoHashMap([2]u21, u21).init(allocator),
+ .nfd_map = std.AutoHashMap(u21, [2]u21).init(allocator),
+ .nfkd_map = std.AutoHashMap(u21, [18]u21).init(allocator),
+ };
+ errdefer self.deinit();
+
+
+
+ const decompressor = std.compress.deflate.decompressor;
+ const comp_file = @embedFile("../autogen/canonical_compositions.txt.deflate");
+ var comp_stream = std.io.fixedBufferStream(comp_file);
+ var comp_decomp = try decompressor(allocator, comp_stream.reader(), null);
+ defer comp_decomp.deinit();
+
+ var comp_buf = std.io.bufferedReader(comp_decomp.reader());
+ const comp_reader = comp_buf.reader();
+ var buf: [4096]u8 = undefined;
+
+ while (try comp_reader.readUntilDelimiterOrEof(&buf, '\n')) |line| {
+ if (line.len == 0) continue;
+ var fields = std.mem.split(u8, line, ";");
+ const cp_a = try std.fmt.parseInt(u21, fields.next().?, 16);
+ const cp_b = try std.fmt.parseInt(u21, fields.next().?, 16);
+ const cp_c = try std.fmt.parseInt(u21, fields.next().?, 16);
+ try self.nfc_map.put(.{ cp_a, cp_b }, cp_c);
+ }
+
+
+
+ const decomp_file = @embedFile("../autogen/canonical_decompositions.txt.deflate");
+ var decomp_stream = std.io.fixedBufferStream(decomp_file);
+ var decomp_decomp = try decompressor(allocator, decomp_stream.reader(), null);
+ defer decomp_decomp.deinit();
+
+ var decomp_buf = std.io.bufferedReader(decomp_decomp.reader());
+ const decomp_reader = decomp_buf.reader();
+
+ while (try decomp_reader.readUntilDelimiterOrEof(&buf, '\n')) |line| {
+ if (line.len == 0) continue;
+ var fields = std.mem.split(u8, line, ";");
+ const cp_a = try std.fmt.parseInt(u21, fields.next().?, 16);
+ const cp_b = try std.fmt.parseInt(u21, fields.next().?, 16);
+ const cp_c = try std.fmt.parseInt(u21, fields.next().?, 16);
+ try self.nfd_map.put(cp_a, .{ cp_b, cp_c });
+ }
+
+
+
+ const dekomp_file = @embedFile("../autogen/compatibility_decompositions.txt.deflate");
+ var dekomp_stream = std.io.fixedBufferStream(dekomp_file);
+ var dekomp_decomp = try decompressor(allocator, dekomp_stream.reader(), null);
+ defer dekomp_decomp.deinit();
+
+ var dekomp_buf = std.io.bufferedReader(dekomp_decomp.reader());
+ const dekomp_reader = dekomp_buf.reader();
+
+ while (try dekomp_reader.readUntilDelimiterOrEof(&buf, '\n')) |line| {
+ if (line.len == 0) continue;
+ var fields = std.mem.split(u8, line, ";");
+ const cp_a = try std.fmt.parseInt(u21, fields.next().?, 16);
+ var cps = [_]u21{0} ** 18;
+ var i: usize = 0;
+
+ while (fields.next()) |cp| : (i += 1) {
+ cps[i] = try std.fmt.parseInt(u21, cp, 16);
+ }
+
+ try self.nfkd_map.put(cp_a, cps);
+ }
+
+ return self;
+}
+
+pub fn deinit(self: *Self) void {
+ self.nfc_map.deinit();
+ self.nfd_map.deinit();
+ self.nfkd_map.deinit();
+}
+
+test "init / deinit" {
+ var n = try init(std.testing.allocator);
+ defer n.deinit();
+}
+
+
+fn isHangulPrecomposed(cp: u21) bool {
+ if (hangul_map.syllableType(cp)) |kind| return kind == .LV or kind == .LVT;
+ return false;
+}
+
+const SBase: u21 = 0xAC00;
+const LBase: u21 = 0x1100;
+const VBase: u21 = 0x1161;
+const TBase: u21 = 0x11A7;
+const LCount: u21 = 19;
+const VCount: u21 = 21;
+const TCount: u21 = 28;
+const NCount: u21 = 588;
+
+const SCount: u21 = 11172;
+
+
+fn decomposeHangul(cp: u21) [3]u21 {
+ const SIndex: u21 = cp - SBase;
+ const LIndex: u21 = SIndex / NCount;
+ const VIndex: u21 = (SIndex % NCount) / TCount;
+ const TIndex: u21 = SIndex % TCount;
+ const LPart: u21 = LBase + LIndex;
+ const VPart: u21 = VBase + VIndex;
+ var TPart: u21 = 0;
+ if (TIndex != 0) TPart = TBase + TIndex;
+
+ return [3]u21{ LPart, VPart, TPart };
+}
+
+fn composeHangulCanon(lv: u21, t: u21) u21 {
+ std.debug.assert(0x11A8 <= t and t <= 0x11C2);
+ return lv + (t - TBase);
+}
+
+fn composeHangulFull(l: u21, v: u21, t: u21) u21 {
+ std.debug.assert(0x1100 <= l and l <= 0x1112);
+ std.debug.assert(0x1161 <= v and v <= 0x1175);
+ const LIndex = l - LBase;
+ const VIndex = v - VBase;
+ const LVIndex = LIndex * NCount + VIndex * TCount;
+
+ if (t == 0) return SBase + LVIndex;
+
+ std.debug.assert(0x11A8 <= t and t <= 0x11C2);
+ const TIndex = t - TBase;
+
+ return SBase + LVIndex + TIndex;
+}
+
+const Form = enum {
+ nfc,
+ nfd,
+ nfkc,
+ nfkd,
+ same,
+};
+
+const Decomp = struct {
+ form: Form = .nfd,
+ cps: [18]u21 = [_]u21{0} ** 18,
+};
+
+
+pub fn mapping(self: Self, cp: u21, form: Form) Decomp {
+ std.debug.assert(form == .nfd or form == .nfkd);
+
+ var dc = Decomp{ .form = .same };
+ dc.cps[0] = cp;
+
+ if (self.nfkd_map.get(cp)) |array| {
+ if (form != .nfd) {
+ dc.form = .nfkd;
+ @memcpy(dc.cps[0..array.len], &array);
+ }
+ } else if (self.nfd_map.get(cp)) |array| {
+ dc.form = .nfd;
+ @memcpy(dc.cps[0..array.len], &array);
+ }
+
+ return dc;
+}
+
+
+pub fn decompose(self: Self, cp: u21, form: Form) Decomp {
+ std.debug.assert(form == .nfd or form == .nfkd);
+
+ var dc = Decomp{ .form = form };
+
+
+
+ if (cp <= 127 or (form == .nfd and norm_props.isNfd(cp)) or (form == .nfkd and norm_props.isNfkd(cp))) {
+ dc.cps[0] = cp;
+ return dc;
+ }
+
+
+
+ if (isHangulPrecomposed(cp)) {
+ const cps = decomposeHangul(cp);
+ @memcpy(dc.cps[0..cps.len], &cps);
+ return dc;
+ }
+
+
+
+ var result_index: usize = 0;
+ var work_index: usize = 1;
+
+
+
+ var work = [_]u21{cp} ++ [_]u21{0} ** 17;
+
+ while (work_index > 0) {
+
+
+ work_index -= 1;
+ const next = work[work_index];
+ const m = self.mapping(next, form);
+
+
+
+ if (m.form == .same) {
+ dc.cps[result_index] = m.cps[0];
+ result_index += 1;
+ continue;
+ }
+
+
+
+ const m_last = for (m.cps, 0..) |mcp, i| {
+ if (mcp == 0) break i;
+ } else m.cps.len;
+
+
+
+
+
+ var i: usize = 1;
+ while (i <= m_last) : ({
+ i += 1;
+ work_index += 1;
+ }) {
+ work[work_index] = m.cps[m_last - i];
+ }
+ }
+
+ return dc;
+}
+
+test "decompose" {
+ const allocator = std.testing.allocator;
+ var n = try init(allocator);
+ defer n.deinit();
+
+ var dc = n.decompose('é', .nfd);
+ try std.testing.expect(dc.form == .nfd);
+ try std.testing.expectEqualSlices(u21, &[_]u21{ 'e', '\u{301}' }, dc.cps[0..2]);
+
+ dc = n.decompose('\u{1e0a}', .nfd);
+ try std.testing.expect(dc.form == .nfd);
+ try std.testing.expectEqualSlices(u21, &[_]u21{ 'D', '\u{307}' }, dc.cps[0..2]);
+
+ dc = n.decompose('\u{1e0a}', .nfkd);
+ try std.testing.expect(dc.form == .nfkd);
+ try std.testing.expectEqualSlices(u21, &[_]u21{ 'D', '\u{307}' }, dc.cps[0..2]);
+
+ dc = n.decompose('\u{3189}', .nfd);
+ try std.testing.expect(dc.form == .nfd);
+ try std.testing.expectEqualSlices(u21, &[_]u21{'\u{3189}'}, dc.cps[0..1]);
+
+ dc = n.decompose('\u{3189}', .nfkd);
+ try std.testing.expect(dc.form == .nfkd);
+ try std.testing.expectEqualSlices(u21, &[_]u21{'\u{1188}'}, dc.cps[0..1]);
+
+ dc = n.decompose('\u{ace1}', .nfd);
+ try std.testing.expect(dc.form == .nfd);
+ try std.testing.expectEqualSlices(u21, &[_]u21{ '\u{1100}', '\u{1169}', '\u{11a8}' }, dc.cps[0..3]);
+
+ dc = n.decompose('\u{ace1}', .nfkd);
+ try std.testing.expect(dc.form == .nfkd);
+ try std.testing.expectEqualSlices(u21, &[_]u21{ '\u{1100}', '\u{1169}', '\u{11a8}' }, dc.cps[0..3]);
+
+ dc = n.decompose('\u{3d3}', .nfd);
+ try std.testing.expect(dc.form == .nfd);
+ try std.testing.expectEqualSlices(u21, &[_]u21{ '\u{3d2}', '\u{301}' }, dc.cps[0..2]);
+
+ dc = n.decompose('\u{3d3}', .nfkd);
+ try std.testing.expect(dc.form == .nfkd);
+ try std.testing.expectEqualSlices(u21, &[_]u21{ '\u{3a5}', '\u{301}' }, dc.cps[0..2]);
+}
+
+
+
+
+fn onlyAscii(str: []const u8) bool {
+ return for (str) |b| {
+ if (b > 127) break false;
+ } else true;
+}
+
+fn onlyLatin1(str: []const u8) bool {
+ var cp_iter = CodePointIterator{ .bytes = str };
+ return while (cp_iter.next()) |cp| {
+ if (cp.code > 256) break false;
+ } else true;
+}
+
+
+pub const Result = struct {
+ allocator: ?std.mem.Allocator = null,
+ slice: []const u8,
+
+ pub fn deinit(self: *Result) void {
+ if (self.allocator) |allocator| allocator.free(self.slice);
+ }
+};
+
+
+
+fn cccLess(_: void, lhs: u21, rhs: u21) bool {
+ return ccc_map.combiningClass(lhs) < ccc_map.combiningClass(rhs);
+}
+
+
+
+fn canonicalSort(cps: []u21) void {
+ var i: usize = 0;
+ while (i < cps.len) : (i += 1) {
+ const start: usize = i;
+ while (i < cps.len and ccc_map.combiningClass(cps[i]) != 0) : (i += 1) {}
+ std.mem.sort(u21, cps[start..i], {}, cccLess);
+ }
+}
+
+
+pub fn nfd(self: Self, allocator: std.mem.Allocator, str: []const u8) !Result {
+ return self.nfxd(allocator, str, .nfd);
+}
+
+
+pub fn nfkd(self: Self, allocator: std.mem.Allocator, str: []const u8) !Result {
+ return self.nfxd(allocator, str, .nfkd);
+}
+
+fn nfxd(self: Self, allocator: std.mem.Allocator, str: []const u8, form: Form) !Result {
+
+
+ if (onlyAscii(str)) return Result{ .slice = str };
+
+ var dcp_list = try std.ArrayList(u21).initCapacity(allocator, str.len + str.len / 2);
+ defer dcp_list.deinit();
+
+ var cp_iter = CodePointIterator{ .bytes = str };
+ while (cp_iter.next()) |cp| {
+ const dc = self.decompose(cp.code, form);
+ const slice = for (dc.cps, 0..) |dcp, i| {
+ if (dcp == 0) break dc.cps[0..i];
+ } else dc.cps[0..];
+ try dcp_list.appendSlice(slice);
+ }
+
+ canonicalSort(dcp_list.items);
+
+ var dstr_list = try std.ArrayList(u8).initCapacity(allocator, dcp_list.items.len * 4);
+ defer dstr_list.deinit();
+
+ var buf: [4]u8 = undefined;
+ for (dcp_list.items) |dcp| {
+ const len = try std.unicode.utf8Encode(dcp, &buf);
+ dstr_list.appendSliceAssumeCapacity(buf[0..len]);
+ }
+
+ return Result{ .allocator = allocator, .slice = try dstr_list.toOwnedSlice() };
+}
+
+test "nfd ASCII / no-alloc" {
+ const allocator = std.testing.allocator;
+ var n = try init(allocator);
+ defer n.deinit();
+
+ var result = try n.nfd(allocator, "Hello World!");
+ defer result.deinit();
+
+ try std.testing.expectEqualStrings("Hello World!", result.slice);
+}
+
+test "nfd !ASCII / alloc" {
+ const allocator = std.testing.allocator;
+ var n = try init(allocator);
+ defer n.deinit();
+
+ var result = try n.nfd(allocator, "Héllo World! \u{3d3}");
+ defer result.deinit();
+
+ try std.testing.expectEqualStrings("He\u{301}llo World! \u{3d2}\u{301}", result.slice);
+}
+
+test "nfkd ASCII / no-alloc" {
+ const allocator = std.testing.allocator;
+ var n = try init(allocator);
+ defer n.deinit();
+
+ var result = try n.nfkd(allocator, "Hello World!");
+ defer result.deinit();
+
+ try std.testing.expectEqualStrings("Hello World!", result.slice);
+}
+
+test "nfkd !ASCII / alloc" {
+ const allocator = std.testing.allocator;
+ var n = try init(allocator);
+ defer n.deinit();
+
+ var result = try n.nfkd(allocator, "Héllo World! \u{3d3}");
+ defer result.deinit();
+
+ try std.testing.expectEqualStrings("He\u{301}llo World! \u{3a5}\u{301}", result.slice);
+}
+
+
+
+
+fn isHangul(cp: u21) bool {
+ return cp >= 0x1100 and hangul_map.syllableType(cp) != null;
+}
+
+fn isStarter(cp: u21) bool {
+ return ccc_map.combiningClass(cp) == 0;
+}
+
+fn isCombining(cp: u21) bool {
+ return ccc_map.combiningClass(cp) != 0;
+}
+
+fn isNonHangulStarter(cp: u21) bool {
+ return !isHangul(cp) and isStarter(cp);
+}
+
+
+pub fn nfc(self: Self, allocator: std.mem.Allocator, str: []const u8) !Result {
+ return self.nfxc(allocator, str, .nfc);
+}
+
+
+pub fn nfkc(self: Self, allocator: std.mem.Allocator, str: []const u8) !Result {
+ return self.nfxc(allocator, str, .nfkc);
+}
+
+fn nfxc(self: Self, allocator: std.mem.Allocator, str: []const u8, form: Form) !Result {
+
+
+ if (onlyAscii(str)) return Result{ .slice = str };
+ if (form == .nfc and onlyLatin1(str)) return Result{ .slice = str };
+
+
+
+ var d_result = if (form == .nfc)
+ try self.nfd(allocator, str)
+ else
+ try self.nfkd(allocator, str);
+ defer d_result.deinit();
+
+
+
+ var cp_iter = CodePointIterator{ .bytes = d_result.slice };
+
+ var d_list = try std.ArrayList(u21).initCapacity(allocator, d_result.slice.len);
+ defer d_list.deinit();
+
+ while (cp_iter.next()) |cp| d_list.appendAssumeCapacity(cp.code);
+
+
+
+ const tombstone = 0xe000;
+
+
+ while (true) {
+ var i: usize = 1;
+
+ var deleted: usize = 0;
+
+ block_check: while (i < d_list.items.len) : (i += 1) {
+ const C = d_list.items[i];
+ var starter_index: ?usize = null;
+ var j: usize = i;
+
+ while (true) {
+ j -= 1;
+
+
+
+ if (ccc_map.combiningClass(d_list.items[j]) == 0) {
+ if (i - j > 1) {
+
+ for (d_list.items[(j + 1)..i]) |B| {
+
+
+ if (isHangul(C)) {
+ if (isCombining(B) or isNonHangulStarter(B)) continue :block_check;
+ }
+ if (ccc_map.combiningClass(B) >= ccc_map.combiningClass(C)) continue :block_check;
+ }
+ }
+
+
+
+ starter_index = j;
+ break;
+ }
+
+ if (j == 0) break;
+ }
+
+ if (starter_index) |sidx| {
+ const L = d_list.items[sidx];
+ var processed_hangul = false;
+
+ if (isHangul(L) and isHangul(C)) {
+ const l_stype = hangul_map.syllableType(L).?;
+ const c_stype = hangul_map.syllableType(C).?;
+
+ if (l_stype == .LV and c_stype == .T) {
+
+
+ d_list.items[sidx] = composeHangulCanon(L, C);
+ d_list.items[i] = tombstone;
+
+ processed_hangul = true;
+ }
+
+ if (l_stype == .L and c_stype == .V) {
+
+
+ d_list.items[sidx] = composeHangulFull(L, C, 0);
+ d_list.items[i] = tombstone;
+
+ processed_hangul = true;
+ }
+
+ if (processed_hangul) deleted += 1;
+ }
+
+ if (!processed_hangul) {
+
+
+ if (self.nfc_map.get(.{ L, C })) |P| {
+ if (!norm_props.isFcx(P)) {
+ d_list.items[sidx] = P;
+ d_list.items[i] = tombstone;
+
+ deleted += 1;
+ }
+ }
+ }
+ }
+ }
+
+
+
+ if (deleted == 0) {
+ var cstr_list = try std.ArrayList(u8).initCapacity(allocator, d_list.items.len * 4);
+ defer cstr_list.deinit();
+ var buf: [4]u8 = undefined;
+
+ for (d_list.items) |cp| {
+ if (cp == tombstone) continue;
+
+ const len = try std.unicode.utf8Encode(cp, &buf);
+ cstr_list.appendSliceAssumeCapacity(buf[0..len]);
+ }
+
+ return Result{ .allocator = allocator, .slice = try cstr_list.toOwnedSlice() };
+ }
+
+
+
+ var tmp_d_list = try std.ArrayList(u21).initCapacity(allocator, d_list.items.len - deleted);
+ defer tmp_d_list.deinit();
+
+ for (d_list.items) |cp| {
+ if (cp != tombstone) tmp_d_list.appendAssumeCapacity(cp);
+ }
+
+ d_list.clearRetainingCapacity();
+ d_list.appendSliceAssumeCapacity(tmp_d_list.items);
+ }
+}
+
+test "nfc" {
+ const allocator = std.testing.allocator;
+ var n = try init(allocator);
+ defer n.deinit();
+
+ var result = try n.nfc(allocator, "Complex char: \u{3D2}\u{301}");
+ defer result.deinit();
+
+ try std.testing.expectEqualStrings("Complex char: \u{3D3}", result.slice);
+}
+
+test "nfkc" {
+ const allocator = std.testing.allocator;
+ var n = try init(allocator);
+ defer n.deinit();
+
+ var result = try n.nfkc(allocator, "Complex char: \u{03A5}\u{0301}");
+ defer result.deinit();
+
+ try std.testing.expectEqualStrings("Complex char: \u{038E}", result.slice);
+}
+
+
+pub fn eqlIdentifiers(allocator: std.mem.Allocator, a: []const u8, b: []const u8) !bool {
+ var list_a = try std.ArrayList(u21).initCapacity(allocator, a.len);
+ defer list_a.deinit();
+ var list_b = try std.ArrayList(u21).initCapacity(allocator, b.len);
+ defer list_b.deinit();
+
+ const Item = struct {
+ str: []const u8,
+ list: *std.ArrayList(u21),
+ };
+
+ const items = [_]Item{
+ .{ .str = a, .list = &list_a },
+ .{ .str = b, .list = &list_b },
+ };
+
+ for (items) |item| {
+ var cp_iter = CodePointIterator{ .bytes = item.str };
+ while (cp_iter.next()) |cp| {
+ if (norm_props.toNfkcCaseFold(cp.code)) |nfkcf| {
+ for (nfkcf) |c| {
+ if (c == 0) break;
+ item.list.appendAssumeCapacity(c);
+ }
+ } else {
+ item.list.appendAssumeCapacity(cp.code);
+
+ }
+ }
+ }
+
+ return std.mem.eql(u21, list_a.items, list_b.items);
+}
+
+test "eqlIdentifiers" {
+ try std.testing.expect(try eqlIdentifiers(std.testing.allocator, "Foé", "foé"));
+}
+
+
+pub fn eql(self: Self, allocator: std.mem.Allocator, a: []const u8, b: []const u8) !bool {
+ var norm_result_a = try self.nfd(allocator, a);
+ defer norm_result_a.deinit();
+ var norm_result_b = try self.nfd(allocator, b);
+ defer norm_result_b.deinit();
+
+ return std.mem.eql(u8, norm_result_a.slice, norm_result_b.slice);
+}
+
+test "eql" {
+ const allocator = std.testing.allocator;
+ var n = try init(allocator);
+ defer n.deinit();
+
+ try std.testing.expect(try n.eql(allocator, "foé", "foe\u{0301}"));
+ try std.testing.expect(try n.eql(allocator, "foϓ", "fo\u{03D2}\u{0301}"));
+}
+
+fn requiresNfdBeforeCaseFold(cp: u21) bool {
+ return switch (cp) {
+ 0x0345 => true,
+ 0x1F80...0x1FAF => true,
+ 0x1FB2...0x1FB4 => true,
+ 0x1FB7 => true,
+ 0x1FBC => true,
+ 0x1FC2...0x1FC4 => true,
+ 0x1FC7 => true,
+ 0x1FCC => true,
+ 0x1FF2...0x1FF4 => true,
+ 0x1FF7 => true,
+ 0x1FFC => true,
+ else => false,
+ };
+}
+
+fn requiresPreNfd(str: []const u8) bool {
+ var cp_iter = CodePointIterator{ .bytes = str };
+
+ return while (cp_iter.next()) |cp| {
+ if (requiresNfdBeforeCaseFold(cp.code)) break true;
+ } else false;
+}
+
+
+pub fn eqlCaseless(self: Self, allocator: std.mem.Allocator, a: []const u8, b: []const u8) !bool {
+
+
+
+
+ var norm_result_a: Result = Result{ .slice = a };
+ if (requiresPreNfd(a)) {
+ if (!self.isFcd(a)) {
+ norm_result_a = try self.nfd(allocator, a);
+ }
+ }
+ defer norm_result_a.deinit();
+
+ const cf_a = try case_fold_map.caseFoldStr(allocator, norm_result_a.slice);
+ defer allocator.free(cf_a);
+ norm_result_a.deinit();
+ norm_result_a = try self.nfd(allocator, cf_a);
+
+ var norm_result_b: Result = Result{ .slice = b };
+ if (requiresPreNfd(b)) {
+ if (!self.isFcd(b)) {
+ norm_result_b = try self.nfd(allocator, b);
+ }
+ }
+ defer norm_result_b.deinit();
+
+ const cf_b = try case_fold_map.caseFoldStr(allocator, norm_result_b.slice);
+ defer allocator.free(cf_b);
+ norm_result_b.deinit();
+ norm_result_b = try self.nfd(allocator, cf_b);
+
+ return std.mem.eql(u8, norm_result_a.slice, norm_result_b.slice);
+}
+
+test "eqlCaseless" {
+ const allocator = std.testing.allocator;
+ var n = try init(allocator);
+ defer n.deinit();
+
+ try std.testing.expect(try n.eqlCaseless(allocator, "Foϓ", "fo\u{03D2}\u{0301}"));
+ try std.testing.expect(try n.eqlCaseless(allocator, "FOÉ", "foe\u{0301}"));
+
+}
+
+
+
+fn getLeadCcc(self: Self, cp: u21) u8 {
+ const dc = self.mapping(cp, .nfd);
+ return ccc_map.combiningClass(dc.cps[0]);
+}
+
+fn getTrailCcc(self: Self, cp: u21) u8 {
+ const dc = self.mapping(cp, .nfd);
+ const len = for (dc.cps, 0..) |dcp, i| {
+ if (dcp == 0) break i;
+ } else dc.cps.len;
+ return ccc_map.combiningClass(dc.cps[len -| 1]);
+}
+
+
+pub fn isFcd(self: Self, str: []const u8) bool {
+ var prev_ccc: u8 = 0;
+ var cp_iter = CodePointIterator{ .bytes = str };
+
+ return while (cp_iter.next()) |cp| {
+ const ccc = self.getLeadCcc(cp.code);
+ if (ccc != 0 and ccc < prev_ccc) break false;
+ prev_ccc = self.getTrailCcc(cp.code);
+ } else true;
+}
+
+test "isFcd" {
+ const allocator = std.testing.allocator;
+ var n = try init(allocator);
+ defer n.deinit();
+
+ const is_nfc = "José \u{3D3}";
+ try std.testing.expect(n.isFcd(is_nfc));
+
+ const is_nfd = "Jose\u{301} \u{3d2}\u{301}";
+ try std.testing.expect(n.isFcd(is_nfd));
+
+ const not_fcd = "Jose\u{301} \u{3d2}\u{315}\u{301}";
+ try std.testing.expect(!n.isFcd(not_fcd));
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/segmenter/CodePoint.zig.html b/docs/src/ziglyph/segmenter/CodePoint.zig.html
new file mode 100644
index 0000000..591c4b8
--- /dev/null
+++ b/docs/src/ziglyph/segmenter/CodePoint.zig.html
@@ -0,0 +1,250 @@
+
+
+
+
+
segmenter/CodePoint.zig - source view
+
+
+
+
+
+
+
+const std = @import("std");
+
+code: u21,
+len: u3,
+offset: usize,
+
+const CodePoint = @This();
+
+
+pub const CodePointIterator = struct {
+ bytes: []const u8,
+ i: usize = 0,
+
+ pub fn next(self: *CodePointIterator) ?CodePoint {
+ if (self.i >= self.bytes.len) return null;
+
+ if (self.bytes[self.i] < 128) {
+
+
+ const cp = CodePoint{
+ .code = self.bytes[self.i],
+ .len = 1,
+ .offset = self.i,
+ };
+
+ self.i += 1;
+
+ return cp;
+ }
+
+ var cp = CodePoint{
+ .code = undefined,
+ .len = blk: {
+ break :blk switch (self.bytes[self.i]) {
+ 0b0000_0000...0b0111_1111 => 1,
+ 0b1100_0000...0b1101_1111 => 2,
+ 0b1110_0000...0b1110_1111 => 3,
+ 0b1111_0000...0b1111_0111 => 4,
+ else => unreachable,
+ };
+ },
+ .offset = self.i,
+ };
+
+ self.i += cp.len;
+ const cp_bytes = self.bytes[self.i - cp.len .. self.i];
+
+ cp.code = switch (cp.len) {
+ 2 => (@as(u21, (cp_bytes[0] & 0b00011111)) << 6) | (cp_bytes[1] & 0b00111111),
+
+ 3 => (((@as(u21, (cp_bytes[0] & 0b00001111)) << 6) |
+ (cp_bytes[1] & 0b00111111)) << 6) |
+ (cp_bytes[2] & 0b00111111),
+
+ 4 => (((((@as(u21, (cp_bytes[0] & 0b00000111)) << 6) |
+ (cp_bytes[1] & 0b00111111)) << 6) |
+ (cp_bytes[2] & 0b00111111)) << 6) |
+ (cp_bytes[3] & 0b00111111),
+
+ else => unreachable,
+ };
+
+ return cp;
+ }
+
+ pub fn peek(self: *CodePointIterator) ?CodePoint {
+ const saved_i = self.i;
+ defer self.i = saved_i;
+ return self.next();
+ }
+};
+
+test "CodePointIterator peek" {
+ var iter = CodePointIterator{ .bytes = "Hi" };
+
+ try std.testing.expectEqual(@as(u21, 'H'), iter.next().?.code);
+ try std.testing.expectEqual(@as(u21, 'i'), iter.peek().?.code);
+ try std.testing.expectEqual(@as(u21, 'i'), iter.next().?.code);
+ try std.testing.expectEqual(@as(?CodePoint, null), iter.peek());
+ try std.testing.expectEqual(@as(?CodePoint, null), iter.next());
+}
+
+
+pub fn readCodePoint(reader: anytype) !?u21 {
+ var buf: [4]u8 = undefined;
+
+ buf[0] = reader.readByte() catch |err| switch (err) {
+ error.EndOfStream => return null,
+ else => return err,
+ };
+
+ if (buf[0] < 128) return @as(u21, buf[0]);
+
+ const len: u3 = switch (buf[0]) {
+ 0b1100_0000...0b1101_1111 => 2,
+ 0b1110_0000...0b1110_1111 => 3,
+ 0b1111_0000...0b1111_0111 => 4,
+ else => return error.InvalidUtf8,
+ };
+
+ const read = try reader.read(buf[1..len]);
+
+ if (read < len - 1) return error.InvalidUtf8;
+
+ return switch (len) {
+ 2 => (@as(u21, (buf[0] & 0b00011111)) << 6) | (buf[1] & 0b00111111),
+
+ 3 => (((@as(u21, (buf[0] & 0b00001111)) << 6) |
+ (buf[1] & 0b00111111)) << 6) |
+ (buf[2] & 0b00111111),
+
+ 4 => (((((@as(u21, (buf[0] & 0b00000111)) << 6) |
+ (buf[1] & 0b00111111)) << 6) |
+ (buf[2] & 0b00111111)) << 6) |
+ (buf[3] & 0b00111111),
+
+ else => unreachable,
+ };
+}
+
+test "readCodePoint" {
+ var buf = "abé😹".*;
+ var fis = std.io.fixedBufferStream(&buf);
+ const reader = fis.reader();
+
+ try std.testing.expectEqual(@as(u21, 'a'), (try readCodePoint(reader)).?);
+ try std.testing.expectEqual(@as(u21, 'b'), (try readCodePoint(reader)).?);
+ try std.testing.expectEqual(@as(u21, 'é'), (try readCodePoint(reader)).?);
+ try std.testing.expectEqual(@as(u21, '😹'), (try readCodePoint(reader)).?);
+ try std.testing.expectEqual(@as(?u21, null), try readCodePoint(reader));
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/segmenter/Grapheme.zig.html b/docs/src/ziglyph/segmenter/Grapheme.zig.html
new file mode 100644
index 0000000..23ec06d
--- /dev/null
+++ b/docs/src/ziglyph/segmenter/Grapheme.zig.html
@@ -0,0 +1,542 @@
+
+
+
+
+
segmenter/Grapheme.zig - source view
+
+
+
+
+
+
+
+const std = @import("std");
+const unicode = std.unicode;
+
+const CodePoint = @import("CodePoint.zig");
+const CodePointIterator = CodePoint.CodePointIterator;
+const readCodePoint = CodePoint.readCodePoint;
+const emoji = @import("../autogen/emoji_data.zig");
+const gbp = @import("../autogen/grapheme_break_property.zig");
+
+pub const Grapheme = @This();
+
+len: usize,
+offset: usize,
+
+
+pub fn eql(self: Grapheme, src: []const u8, other: []const u8) bool {
+ return std.mem.eql(u8, src[self.offset .. self.offset + self.len], other);
+}
+
+
+pub fn slice(self: Grapheme, src: []const u8) []const u8 {
+ return src[self.offset .. self.offset + self.len];
+}
+
+
+pub const GraphemeIterator = struct {
+ buf: [2]?CodePoint = [_]?CodePoint{ null, null },
+ cp_iter: CodePointIterator,
+
+ const Self = @This();
+
+
+ pub fn init(str: []const u8) Self {
+ var self = Self{ .cp_iter = CodePointIterator{ .bytes = str } };
+ self.buf[1] = self.cp_iter.next();
+
+ return self;
+ }
+
+ fn advance(self: *Self) void {
+ self.buf[0] = self.buf[1];
+ self.buf[1] = self.cp_iter.next();
+ }
+
+ pub fn next(self: *Self) ?Grapheme {
+ self.advance();
+
+
+
+ if (self.buf[0] == null) return null;
+ if (self.buf[1] == null) return Grapheme{ .len = self.buf[0].?.len, .offset = self.buf[0].?.offset };
+
+ const gc_start = self.buf[0].?.offset;
+ var gc_len: usize = self.buf[0].?.len;
+ var state: u3 = 0;
+
+ if (graphemeBreak(
+ self.buf[0].?.code,
+ self.buf[1].?.code,
+ &state,
+ )) return Grapheme{ .len = gc_len, .offset = gc_start };
+
+ while (true) {
+ self.advance();
+ if (self.buf[0] == null) break;
+
+ gc_len += self.buf[0].?.len;
+
+ if (graphemeBreak(
+ self.buf[0].?.code,
+ if (self.buf[1]) |ncp| ncp.code else 0,
+ &state,
+ )) break;
+ }
+
+ return Grapheme{ .len = gc_len, .offset = gc_start };
+ }
+};
+
+
+
+pub fn StreamingGraphemeIterator(comptime T: type) type {
+ return struct {
+ allocator: std.mem.Allocator,
+ buf: [2]?u21 = [_]?u21{ null, null },
+ reader: T,
+
+ const Self = @This();
+
+ pub fn init(allocator: std.mem.Allocator, reader: anytype) !Self {
+ var self = Self{ .allocator = allocator, .reader = reader };
+ self.buf[1] = try readCodePoint(self.reader);
+
+ return self;
+ }
+
+
+ pub fn next(self: *Self) !?[]u8 {
+ const code = (try self.advance()) orelse return null;
+
+ var all_bytes = std.ArrayList(u8).init(self.allocator);
+ errdefer all_bytes.deinit();
+
+ try encode_and_append(code, &all_bytes);
+
+
+
+ if (self.buf[1] == null) return try all_bytes.toOwnedSlice();
+
+
+
+
+
+ if (code == '\x0d') {
+ if (self.buf[1].? == '\x0a') {
+
+
+ try encode_and_append(self.buf[1].?, &all_bytes);
+ _ = self.advance() catch unreachable;
+ }
+
+ return try all_bytes.toOwnedSlice();
+ }
+
+
+ if (code == '\x0a') return try all_bytes.toOwnedSlice();
+
+
+ if (gbp.isControl(code)) return try all_bytes.toOwnedSlice();
+
+
+
+ if (code < 0xa9) {
+
+
+ while (self.buf[1]) |next_cp| {
+ if (next_cp >= 0x300 and isIgnorable(next_cp)) {
+ try encode_and_append(next_cp, &all_bytes);
+ _ = self.advance() catch unreachable;
+ } else {
+ break;
+ }
+ }
+
+ return try all_bytes.toOwnedSlice();
+ }
+
+ if (emoji.isExtendedPictographic(code)) {
+ var after_zwj = false;
+
+
+
+ while (self.buf[1]) |next_cp| {
+ if (next_cp >= 0x300 and
+ after_zwj and
+ emoji.isExtendedPictographic(next_cp))
+ {
+ try encode_and_append(next_cp, &all_bytes);
+ _ = self.advance() catch unreachable;
+ after_zwj = false;
+ } else if (next_cp >= 0x300 and isIgnorable(next_cp)) {
+ try encode_and_append(next_cp, &all_bytes);
+ _ = self.advance() catch unreachable;
+ if (next_cp == '\u{200d}') after_zwj = true;
+ } else {
+ break;
+ }
+ }
+
+ return try all_bytes.toOwnedSlice();
+ }
+
+ if (0x1100 <= code and code <= 0xd7c6) {
+ const next_cp = self.buf[1].?;
+
+ if (gbp.isL(code)) {
+ if (next_cp >= 0x1100 and
+ (gbp.isL(next_cp) or
+ gbp.isV(next_cp) or
+ gbp.isLv(next_cp) or
+ gbp.isLvt(next_cp)))
+ {
+ try encode_and_append(next_cp, &all_bytes);
+ _ = self.advance() catch unreachable;
+ }
+ } else if (gbp.isLv(code) or gbp.isV(code)) {
+ if (next_cp >= 0x1100 and
+ (gbp.isV(next_cp) or
+ gbp.isT(next_cp)))
+ {
+ try encode_and_append(next_cp, &all_bytes);
+ _ = self.advance() catch unreachable;
+ }
+ } else if (gbp.isLvt(code) or gbp.isT(code)) {
+ if (next_cp >= 0x1100 and gbp.isT(next_cp)) {
+ try encode_and_append(next_cp, &all_bytes);
+ _ = self.advance() catch unreachable;
+ }
+ }
+ } else if (0x600 <= code and code <= 0x11f02) {
+ if (gbp.isPrepend(code)) {
+ const next_cp = self.buf[1].?;
+
+ if (isBreaker(next_cp)) {
+ return try all_bytes.toOwnedSlice();
+ } else {
+ try encode_and_append(next_cp, &all_bytes);
+ _ = self.advance() catch unreachable;
+ }
+ }
+ } else if (0x1f1e6 <= code and code <= 0x1f1ff) {
+ if (gbp.isRegionalIndicator(code)) {
+ const next_cp = self.buf[1].?;
+
+ if (next_cp >= 0x1f1e6 and gbp.isRegionalIndicator(next_cp)) {
+ try encode_and_append(next_cp, &all_bytes);
+ _ = self.advance() catch unreachable;
+ }
+ }
+ }
+
+
+
+ while (self.buf[1]) |next_cp| {
+ if (next_cp >= 0x300 and isIgnorable(next_cp)) {
+ try encode_and_append(next_cp, &all_bytes);
+ _ = self.advance() catch unreachable;
+ } else {
+ break;
+ }
+ }
+
+ return try all_bytes.toOwnedSlice();
+ }
+
+ fn advance(self: *Self) !?u21 {
+ self.buf[0] = self.buf[1];
+ self.buf[1] = try readCodePoint(self.reader);
+
+ return self.buf[0];
+ }
+
+ fn peek(self: Self) ?u21 {
+ return self.buf[1];
+ }
+
+ fn encode_and_append(cp: u21, list: *std.ArrayList(u8)) !void {
+ var tmp: [4]u8 = undefined;
+ const len = try unicode.utf8Encode(cp, &tmp);
+ try list.appendSlice(tmp[0..len]);
+ }
+ };
+}
+
+
+
+fn isBreaker(cp: u21) bool {
+ return cp == '\x0d' or cp == '\x0a' or gbp.isControl(cp);
+}
+
+fn isIgnorable(cp: u21) bool {
+ return gbp.isExtend(cp) or gbp.isSpacingmark(cp) or cp == '\u{200d}';
+}
+
+test "Segmentation comptime GraphemeIterator" {
+ const want = [_][]const u8{ "H", "é", "l", "l", "o" };
+
+ comptime {
+ const src = "Héllo";
+ var ct_iter = GraphemeIterator.init(src);
+ var i = 0;
+ while (ct_iter.next()) |grapheme| : (i += 1) {
+ try std.testing.expect(grapheme.eql(src, want[i]));
+ }
+ }
+}
+
+test "Simple StreamingGraphemeIterator" {
+ var buf = "abe\u{301}😹".*;
+ var fis = std.io.fixedBufferStream(&buf);
+ const reader = fis.reader();
+ var iter = try StreamingGraphemeIterator(@TypeOf(reader)).init(std.testing.allocator, reader);
+ const want = [_][]const u8{ "a", "b", "e\u{301}", "😹" };
+
+ for (want) |str| {
+ const gc = (try iter.next()).?;
+ defer std.testing.allocator.free(gc);
+ try std.testing.expectEqualStrings(gc, str);
+ }
+
+ try std.testing.expectEqual(@as(?[]u8, null), try iter.next());
+}
+
+test "Segmentation ZWJ and ZWSP emoji sequences" {
+ const seq_1 = "\u{1F43B}\u{200D}\u{2744}\u{FE0F}";
+ const seq_2 = "\u{1F43B}\u{200D}\u{2744}\u{FE0F}";
+ const with_zwj = seq_1 ++ "\u{200D}" ++ seq_2;
+ const with_zwsp = seq_1 ++ "\u{200B}" ++ seq_2;
+ const no_joiner = seq_1 ++ seq_2;
+
+ var ct_iter = GraphemeIterator.init(with_zwj);
+ var i: usize = 0;
+ while (ct_iter.next()) |_| : (i += 1) {}
+ try std.testing.expectEqual(@as(usize, 1), i);
+
+ ct_iter = GraphemeIterator.init(with_zwsp);
+ i = 0;
+ while (ct_iter.next()) |_| : (i += 1) {}
+ try std.testing.expectEqual(@as(usize, 3), i);
+
+ ct_iter = GraphemeIterator.init(no_joiner);
+ i = 0;
+ while (ct_iter.next()) |_| : (i += 1) {}
+ try std.testing.expectEqual(@as(usize, 2), i);
+}
+
+
+
+fn hasXpic(state: *const u3) bool {
+ return state.* & 1 == 1;
+}
+
+fn setXpic(state: *u3) void {
+ state.* |= 1;
+}
+
+fn unsetXpic(state: *u3) void {
+ state.* ^= 1;
+}
+
+fn hasRegional(state: *const u3) bool {
+ return state.* & 2 == 2;
+}
+
+fn setRegional(state: *u3) void {
+ state.* |= 2;
+}
+
+fn unsetRegional(state: *u3) void {
+ state.* ^= 2;
+}
+
+
+
+
+
+
+
+pub fn graphemeBreak(
+ cp1: u21,
+ cp2: u21,
+ state: *u3,
+) bool {
+
+
+ if (!hasXpic(state) and emoji.isExtendedPictographic(cp1)) setXpic(state);
+
+
+
+ if (cp1 == '\r' and cp2 == '\n') return false;
+
+
+
+ if (isBreaker(cp1)) return true;
+
+
+
+ if (gbp.isL(cp1)) {
+ if (gbp.isL(cp2) or
+ gbp.isV(cp2) or
+ gbp.isLv(cp2) or
+ gbp.isLvt(cp2)) return false;
+ }
+
+
+
+ if (gbp.isLv(cp1) or gbp.isV(cp1)) {
+ if (gbp.isV(cp2) or
+ gbp.isT(cp2)) return false;
+ }
+
+
+
+ if (gbp.isLvt(cp1) or gbp.isT(cp1)) {
+ if (gbp.isT(cp2)) return false;
+ }
+
+
+
+ if (gbp.isExtend(cp2) or gbp.isZwj(cp2)) return false;
+
+
+
+ if (gbp.isSpacingmark(cp2)) return false;
+
+
+
+ if (gbp.isPrepend(cp1) and !isBreaker(cp2)) return false;
+
+
+
+ if (gbp.isRegionalIndicator(cp1) and gbp.isRegionalIndicator(cp2)) {
+ if (hasRegional(state)) {
+ unsetRegional(state);
+ return true;
+ } else {
+ setRegional(state);
+ return false;
+ }
+ }
+
+
+
+ if (hasXpic(state) and
+ gbp.isZwj(cp1) and
+ emoji.isExtendedPictographic(cp2))
+ {
+ unsetXpic(state);
+ return false;
+ }
+
+ return true;
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/segmenter/Sentence.zig.html b/docs/src/ziglyph/segmenter/Sentence.zig.html
new file mode 100644
index 0000000..74cf604
--- /dev/null
+++ b/docs/src/ziglyph/segmenter/Sentence.zig.html
@@ -0,0 +1,847 @@
+
+
+
+
+
segmenter/Sentence.zig - source view
+
+
+
+
+
+
+
+const std = @import("std");
+const unicode = std.unicode;
+
+const sbp = @import("../autogen/sentence_break_property.zig");
+const CodePoint = @import("CodePoint.zig");
+const CodePointIterator = CodePoint.CodePointIterator;
+
+pub const Sentence = @This();
+
+bytes: []const u8,
+offset: usize,
+
+
+pub fn eql(self: Sentence, str: []const u8) bool {
+ return std.mem.eql(u8, self.bytes, str);
+}
+
+const Type = enum {
+ aterm,
+ close,
+ cr,
+ extend,
+ format,
+ lf,
+ lower,
+ numeric,
+ oletter,
+ scontinue,
+ sep,
+ sp,
+ sterm,
+ upper,
+ any,
+
+ fn get(cp: CodePoint) Type {
+ var ty: Type = .any;
+ if (0x000D == cp.code) ty = .cr;
+ if (0x000A == cp.code) ty = .lf;
+ if (sbp.isLower(cp.code)) ty = .lower;
+ if (sbp.isUpper(cp.code)) ty = .upper;
+ if (sbp.isOletter(cp.code)) ty = .oletter;
+ if (sbp.isNumeric(cp.code)) ty = .numeric;
+ if (sbp.isSep(cp.code)) ty = .sep;
+ if (sbp.isSp(cp.code)) ty = .sp;
+ if (sbp.isClose(cp.code)) ty = .close;
+ if (sbp.isAterm(cp.code)) ty = .aterm;
+ if (sbp.isSterm(cp.code)) ty = .sterm;
+ if (sbp.isScontinue(cp.code)) ty = .scontinue;
+ if (sbp.isExtend(cp.code)) ty = .extend;
+ if (sbp.isFormat(cp.code)) ty = .format;
+
+ return ty;
+ }
+};
+
+const Token = struct {
+ ty: Type,
+ code_point: CodePoint,
+ offset: usize = 0,
+
+ fn is(self: Token, ty: Type) bool {
+ return self.ty == ty;
+ }
+};
+
+const TokenList = std.ArrayList(Token);
+
+
+pub const SentenceIterator = struct {
+ bytes: []const u8,
+ i: ?usize = null,
+ start: ?Token = null,
+ tokens: TokenList,
+
+ const Self = @This();
+
+ pub fn init(allocator: std.mem.Allocator, str: []const u8) !Self {
+ if (!unicode.utf8ValidateSlice(str)) return error.InvalidUtf8;
+
+ var self = Self{
+ .bytes = str,
+ .tokens = TokenList.init(allocator),
+ };
+
+ try self.lex();
+
+ if (self.tokens.items.len == 0) return error.NoTokens;
+ self.start = self.tokens.items[0];
+
+
+
+ for (self.tokens.items, 0..) |*token, i| {
+ token.offset = i;
+ }
+
+ return self;
+ }
+
+ pub fn deinit(self: *Self) void {
+ self.tokens.deinit();
+ }
+
+ fn lex(self: *Self) !void {
+ var iter = CodePointIterator{
+ .bytes = self.bytes,
+ .i = 0,
+ };
+
+ while (iter.next()) |cp| {
+ try self.tokens.append(.{
+ .ty = Type.get(cp),
+ .code_point = cp,
+ });
+ }
+ }
+
+
+
+ pub fn next(self: *Self) ?Sentence {
+ no_break: while (self.advance()) |current_token| {
+ if (isParaSep(current_token)) {
+ var end = current_token;
+
+ if (current_token.is(.cr)) {
+ if (self.peek()) |p| {
+ if (p.is(.lf)) {
+ _ = self.advance();
+ end = self.current();
+ }
+ }
+ }
+
+ const start = self.start.?;
+ self.start = self.peek();
+
+ return self.emit(start, end);
+ }
+
+ if (current_token.is(.aterm)) {
+ var end = self.current();
+
+ if (self.peek()) |p| {
+ if (isUpper(p)) {
+
+
+ const original_i = self.i;
+ self.i = current_token.offset;
+ defer self.i = original_i;
+
+ if (self.prevAfterSkip(isIgnorable)) |v| {
+ if (isUpperLower(v)) continue :no_break;
+ }
+ } else if (isParaSep(p) or isLower(p) or isNumeric(p) or isSContinue(p)) {
+ continue :no_break;
+ } else if (isSpace(p)) {
+
+
+ self.run(isSpace);
+ end = self.current();
+
+
+ if (self.peek()) |pp| {
+ if (isLower(pp)) continue :no_break;
+ }
+ } else if (isClose(p)) {
+
+
+ self.run(isClose);
+ if (self.peek()) |pp| {
+
+
+ if (isParaSep(pp)) {
+ _ = self.advance();
+ end = self.current();
+ const start = self.start.?;
+ self.start = self.peek();
+
+ return self.emit(start, end);
+ }
+
+
+ if (isSpace(pp)) {
+
+
+ self.run(isSpace);
+
+ if (self.peek()) |ppp| {
+
+
+ if (isLower(ppp)) continue :no_break;
+
+
+ if (isAllowedBeforeLower(ppp)) {
+ if (self.peekAfterSkip(isAllowedBeforeLower)) |pppp| {
+
+
+ if (isLower(pppp)) continue :no_break;
+ }
+ }
+ }
+ }
+ }
+
+ end = self.current();
+ } else if (isSATerm(p)) {
+ self.run(isSATerm);
+ end = self.current();
+ }
+ }
+
+ const start = self.start.?;
+ self.start = self.peek();
+
+ return self.emit(start, end);
+ }
+
+ if (current_token.is(.sterm)) {
+ var end = self.current();
+
+ if (self.peek()) |p| {
+ if (isParaSep(p) or isSATerm(p) or isSContinue(p)) {
+ _ = self.advance();
+ end = self.current();
+ } else if (isSpace(p)) {
+ self.run(isSpace);
+ end = self.current();
+ } else if (isClose(p)) {
+
+
+ self.run(isClose);
+ if (self.peek()) |pp| {
+ if (isSpace(pp)) {
+
+
+ self.run(isSpace);
+ }
+ }
+
+ end = self.current();
+ }
+ }
+
+ const start = self.start.?;
+ self.start = self.peek();
+
+ return self.emit(start, end);
+ }
+ }
+
+ return if (self.start) |start| self.emit(start, self.last()) else null;
+ }
+
+
+
+ fn forward(self: *Self) bool {
+ if (self.i) |*index| {
+ index.* += 1;
+ if (index.* >= self.tokens.items.len) return false;
+ } else {
+ self.i = 0;
+ }
+
+ return true;
+ }
+
+
+
+ fn getRelative(self: Self, n: isize) ?Token {
+ var index: usize = self.i orelse 0;
+
+ if (n < 0) {
+ if (index == 0 or -%n > index) return null;
+ index -= @intCast(-%n);
+ } else {
+ const un: usize = @intCast(n);
+ if (index + un >= self.tokens.items.len) return null;
+ index += un;
+ }
+
+ return self.tokens.items[index];
+ }
+
+ fn prevAfterSkip(self: *Self, predicate: TokenPredicate) ?Token {
+ if (self.i == null or self.i.? == 0) return null;
+
+ var i: isize = 1;
+ while (self.getRelative(-i)) |token| : (i += 1) {
+ if (!predicate(token)) return token;
+ }
+
+ return null;
+ }
+
+ fn current(self: Self) Token {
+
+
+ return self.tokens.items[self.i.?];
+ }
+
+ fn last(self: Self) Token {
+ return self.tokens.items[self.tokens.items.len - 1];
+ }
+
+ fn peek(self: Self) ?Token {
+ return self.getRelative(1);
+ }
+
+ fn peekAfterSkip(self: *Self, predicate: TokenPredicate) ?Token {
+ var i: isize = 1;
+ while (self.getRelative(i)) |token| : (i += 1) {
+ if (!predicate(token)) return token;
+ }
+
+ return null;
+ }
+
+ fn advance(self: *Self) ?Token {
+ const token = if (self.forward()) self.current() else return null;
+ if (!isParaSep(token)) _ = self.skipIgnorables(token);
+
+ return token;
+ }
+
+ fn run(self: *Self, predicate: TokenPredicate) void {
+ while (self.peek()) |token| {
+ if (!predicate(token)) break;
+ _ = self.advance();
+ }
+ }
+
+ fn skipIgnorables(self: *Self, end: Token) Token {
+ if (self.peek()) |p| {
+ if (isIgnorable(p)) {
+ self.run(isIgnorable);
+ return self.current();
+ }
+ }
+
+ return end;
+ }
+
+
+
+ fn emit(self: Self, start_token: Token, end_token: Token) Sentence {
+ const start = start_token.code_point.offset;
+ const end = end_token.code_point.offset + end_token.code_point.len;
+
+ return .{
+ .bytes = self.bytes[start..end],
+ .offset = start,
+ };
+ }
+};
+
+
+
+const TokenPredicate = *const fn (Token) bool;
+
+fn isNumeric(token: Token) bool {
+ return token.ty == .numeric;
+}
+
+fn isLower(token: Token) bool {
+ return token.ty == .lower;
+}
+
+fn isUpper(token: Token) bool {
+ return token.ty == .upper;
+}
+
+fn isUpperLower(token: Token) bool {
+ return isUpper(token) or isLower(token);
+}
+
+fn isIgnorable(token: Token) bool {
+ return token.ty == .extend or token.ty == .format;
+}
+
+fn isClose(token: Token) bool {
+ return token.ty == .close;
+}
+
+fn isSpace(token: Token) bool {
+ return token.ty == .sp;
+}
+
+fn isParaSep(token: Token) bool {
+ return token.ty == .cr or token.ty == .lf or token.ty == .sep;
+}
+
+fn isSATerm(token: Token) bool {
+ return token.ty == .aterm or token.ty == .sterm;
+}
+
+fn isSContinue(token: Token) bool {
+ return token.ty == .scontinue;
+}
+
+fn isUnallowedBeforeLower(token: Token) bool {
+ return token.ty == .oletter or isUpperLower(token) or isSATerm(token) or isParaSep(token);
+}
+
+fn isAllowedBeforeLower(token: Token) bool {
+ return !isUnallowedBeforeLower(token);
+}
+
+
+
+fn getTokens(comptime str: []const u8, comptime n: usize) [n]Token {
+ var i: usize = 0;
+ var cp_iter = CodePointIterator{ .bytes = str };
+ var tokens: [n]Token = undefined;
+
+ while (cp_iter.next()) |cp| : (i += 1) {
+ tokens[i] = .{
+ .ty = Type.get(cp),
+ .code_point = cp,
+ .offset = i,
+ };
+ }
+
+ return tokens;
+}
+
+
+pub fn ComptimeSentenceIterator(comptime str: []const u8) type {
+ const cp_count: usize = unicode.utf8CountCodepoints(str) catch @compileError("Invalid UTF-8.");
+ if (cp_count == 0) @compileError("No code points?");
+ const tokens = getTokens(str, cp_count);
+
+ return struct {
+ bytes: []const u8 = str,
+ i: ?usize = null,
+ start: ?Token = tokens[0],
+ tokens: [cp_count]Token = tokens,
+
+ const Self = @This();
+
+
+
+ pub fn next(self: *Self) ?Sentence {
+ no_break: while (self.advance()) |current_token| {
+ if (isParaSep(current_token)) {
+ var end = current_token;
+
+ if (current_token.is(.cr)) {
+ if (self.peek()) |p| {
+ if (p.is(.lf)) {
+ _ = self.advance();
+ end = self.current();
+ }
+ }
+ }
+
+ const start = self.start.?;
+ self.start = self.peek();
+
+ return self.emit(start, end);
+ }
+
+ if (current_token.is(.aterm)) {
+ var end = self.current();
+
+ if (self.peek()) |p| {
+ if (isUpper(p)) {
+
+
+ const original_i = self.i;
+ self.i = current_token.offset;
+ defer self.i = original_i;
+
+ if (self.prevAfterSkip(isIgnorable)) |v| {
+ if (isUpperLower(v)) continue :no_break;
+ }
+ } else if (isParaSep(p) or isLower(p) or isNumeric(p) or isSContinue(p)) {
+ continue :no_break;
+ } else if (isSpace(p)) {
+
+
+ self.run(isSpace);
+ end = self.current();
+
+
+ if (self.peek()) |pp| {
+ if (isLower(pp)) continue :no_break;
+ }
+ } else if (isClose(p)) {
+
+
+ self.run(isClose);
+ if (self.peek()) |pp| {
+
+
+ if (isParaSep(pp)) {
+ _ = self.advance();
+ end = self.current();
+ const start = self.start.?;
+ self.start = self.peek();
+
+ return self.emit(start, end);
+ }
+
+
+ if (isSpace(pp)) {
+
+
+ self.run(isSpace);
+
+ if (self.peek()) |ppp| {
+
+
+ if (isLower(ppp)) continue :no_break;
+
+
+ if (isAllowedBeforeLower(ppp)) {
+ if (self.peekAfterSkip(isAllowedBeforeLower)) |pppp| {
+
+
+ if (isLower(pppp)) continue :no_break;
+ }
+ }
+ }
+ }
+ }
+
+ end = self.current();
+ } else if (isSATerm(p)) {
+ self.run(isSATerm);
+ end = self.current();
+ }
+ }
+
+ const start = self.start.?;
+ self.start = self.peek();
+
+ return self.emit(start, end);
+ }
+
+ if (current_token.is(.sterm)) {
+ var end = self.current();
+
+ if (self.peek()) |p| {
+ if (isParaSep(p) or isSATerm(p) or isSContinue(p)) {
+ _ = self.advance();
+ end = self.current();
+ } else if (isSpace(p)) {
+ self.run(isSpace);
+ end = self.current();
+ } else if (isClose(p)) {
+
+
+ self.run(isClose);
+ if (self.peek()) |pp| {
+ if (isSpace(pp)) {
+
+
+ self.run(isSpace);
+ }
+ }
+
+ end = self.current();
+ }
+ }
+
+ const start = self.start.?;
+ self.start = self.peek();
+
+ return self.emit(start, end);
+ }
+ }
+
+ return if (self.start) |start| self.emit(start, self.last()) else null;
+ }
+
+
+
+ fn forward(self: *Self) bool {
+ if (self.i) |*index| {
+ index.* += 1;
+ if (index.* >= self.tokens.len) return false;
+ } else {
+ self.i = 0;
+ }
+
+ return true;
+ }
+
+ pub fn count(self: *Self) usize {
+ const original_i = self.i;
+ const original_start = self.start;
+ defer {
+ self.i = original_i;
+ self.start = original_start;
+ }
+
+ self.rewind();
+ var i: usize = 0;
+ while (self.next()) |_| : (i += 1) {}
+
+ return i;
+ }
+
+
+
+ pub fn rewind(self: *Self) void {
+ self.i = null;
+ self.start = self.tokens[0];
+ }
+
+ fn getRelative(self: Self, n: isize) ?Token {
+ var index: usize = self.i orelse 0;
+
+ if (n < 0) {
+ if (index == 0 or -%n > index) return null;
+ index -= @intCast(-%n);
+ } else {
+ const un: usize = @intCast(n);
+ if (index + un >= self.tokens.len) return null;
+ index += un;
+ }
+
+ return self.tokens[index];
+ }
+
+ fn prevAfterSkip(self: *Self, predicate: TokenPredicate) ?Token {
+ if (self.i == null or self.i.? == 0) return null;
+
+ var i: isize = 1;
+ while (self.getRelative(-i)) |token| : (i += 1) {
+ if (!predicate(token)) return token;
+ }
+
+ return null;
+ }
+
+ fn current(self: Self) Token {
+
+
+ return self.tokens[self.i.?];
+ }
+
+ fn last(self: Self) Token {
+ return self.tokens[self.tokens.len - 1];
+ }
+
+ fn peek(self: Self) ?Token {
+ return self.getRelative(1);
+ }
+
+ fn peekAfterSkip(self: *Self, predicate: TokenPredicate) ?Token {
+ var i: isize = 1;
+ while (self.getRelative(i)) |token| : (i += 1) {
+ if (!predicate(token)) return token;
+ }
+
+ return null;
+ }
+
+ fn advance(self: *Self) ?Token {
+ const token = if (self.forward()) self.current() else return null;
+ if (!isParaSep(token)) _ = self.skipIgnorables(token);
+
+ return token;
+ }
+
+ fn run(self: *Self, predicate: TokenPredicate) void {
+ while (self.peek()) |token| {
+ if (!predicate(token)) break;
+ _ = self.advance();
+ }
+ }
+
+ fn skipIgnorables(self: *Self, end: Token) Token {
+ if (self.peek()) |p| {
+ if (isIgnorable(p)) {
+ self.run(isIgnorable);
+ return self.current();
+ }
+ }
+
+ return end;
+ }
+
+
+
+ fn emit(self: Self, start_token: Token, end_token: Token) Sentence {
+ const start = start_token.code_point.offset;
+ const end = end_token.code_point.offset + end_token.code_point.len;
+
+ return .{
+ .bytes = self.bytes[start..end],
+ .offset = start,
+ };
+ }
+ };
+}
+
+test "Segmentation ComptimeSentenceIterator" {
+ @setEvalBranchQuota(2_000);
+
+ const input =
+ \\("Go.") ("He said.")
+
+ ;
+ comptime var ct_iter = ComptimeSentenceIterator(input){};
+ const n = comptime ct_iter.count();
+ comptime var sentences: [n]Sentence = undefined;
+ comptime {
+ var i: usize = 0;
+ while (ct_iter.next()) |sentence| : (i += 1) {
+ sentences[i] = sentence;
+ }
+ }
+
+ const s1 =
+ \\("Go.")
+
+ ;
+ const s2 =
+ \\("He said.")
+
+ ;
+ const want = &[_][]const u8{ s1, s2 };
+
+ for (sentences, 0..) |sentence, i| {
+ try std.testing.expect(sentence.eql(want[i]));
+ }
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/segmenter/Word.zig.html b/docs/src/ziglyph/segmenter/Word.zig.html
new file mode 100644
index 0000000..1cb7bda
--- /dev/null
+++ b/docs/src/ziglyph/segmenter/Word.zig.html
@@ -0,0 +1,572 @@
+
+
+
+
+
segmenter/Word.zig - source view
+
+
+
+
+
+
+
+const std = @import("std");
+const unicode = std.unicode;
+
+const wbp = @import("../autogen/word_break_property.zig");
+const CodePoint = @import("CodePoint.zig");
+const CodePointIterator = CodePoint.CodePointIterator;
+const emoji = @import("../autogen/emoji_data.zig");
+
+pub const Word = @This();
+
+bytes: []const u8,
+offset: usize,
+
+
+pub fn eql(self: Word, str: []const u8) bool {
+ return std.mem.eql(u8, self.bytes, str);
+}
+
+const Type = enum {
+ aletter,
+ cr,
+ dquote,
+ extend,
+ extendnumlet,
+ format,
+ hletter,
+ katakana,
+ lf,
+ midletter,
+ midnum,
+ midnumlet,
+ newline,
+ numeric,
+ regional,
+ squote,
+ wsegspace,
+ xpic,
+ zwj,
+ any,
+
+ fn get(cp: CodePoint) Type {
+ var ty: Type = .any;
+ if (0x000D == cp.code) ty = .cr;
+ if (0x000A == cp.code) ty = .lf;
+ if (0x200D == cp.code) ty = .zwj;
+ if (0x0022 == cp.code) ty = .dquote;
+ if (0x0027 == cp.code) ty = .squote;
+ if (wbp.isAletter(cp.code)) ty = .aletter;
+ if (wbp.isExtend(cp.code)) ty = .extend;
+ if (wbp.isExtendnumlet(cp.code)) ty = .extendnumlet;
+ if (wbp.isFormat(cp.code)) ty = .format;
+ if (wbp.isHebrewLetter(cp.code)) ty = .hletter;
+ if (wbp.isKatakana(cp.code)) ty = .katakana;
+ if (wbp.isMidletter(cp.code)) ty = .midletter;
+ if (wbp.isMidnum(cp.code)) ty = .midnum;
+ if (wbp.isMidnumlet(cp.code)) ty = .midnumlet;
+ if (wbp.isNewline(cp.code)) ty = .newline;
+ if (wbp.isNumeric(cp.code)) ty = .numeric;
+ if (wbp.isRegionalIndicator(cp.code)) ty = .regional;
+ if (wbp.isWsegspace(cp.code)) ty = .wsegspace;
+ if (emoji.isExtendedPictographic(cp.code)) ty = .xpic;
+
+ return ty;
+ }
+};
+
+const Token = struct {
+ ty: Type,
+ code_point: CodePoint,
+
+ fn is(self: Token, ty: Type) bool {
+ return self.ty == ty;
+ }
+};
+
+
+
+pub const WordIterator = struct {
+ cp_iter: CodePointIterator,
+ current: ?Token = null,
+ start: ?Token = null,
+
+ const Self = @This();
+
+ pub fn init(str: []const u8) !Self {
+ if (!unicode.utf8ValidateSlice(str)) return error.InvalidUtf8;
+ return Self{ .cp_iter = CodePointIterator{ .bytes = str } };
+ }
+
+
+
+ pub fn next(self: *Self) ?Word {
+ if (self.advance()) |latest_non_ignorable| {
+ var end = self.current.?;
+ var done = false;
+
+ if (!done and isBreaker(latest_non_ignorable)) {
+ if (latest_non_ignorable.is(.cr)) {
+ if (self.peek()) |p| {
+
+
+ if (p.is(.lf)) {
+ _ = self.advance();
+ end = self.current.?;
+ done = true;
+ }
+ }
+ }
+ }
+
+ if (!done and end.is(.zwj)) {
+ if (self.peek()) |p| {
+
+
+ if (p.is(.xpic)) {
+ _ = self.advance();
+ end = self.current.?;
+ done = true;
+ }
+ }
+ }
+
+ if (!done and latest_non_ignorable.is(.wsegspace)) {
+ while (self.peek()) |p| {
+
+
+ if (p.is(.wsegspace) and !isIgnorable(end)) {
+ _ = self.advance();
+ end = self.current.?;
+ done = true;
+ } else break;
+ }
+ }
+
+ if (!done and (isAHLetter(latest_non_ignorable) or latest_non_ignorable.is(.numeric))) {
+ if (self.peek()) |p| {
+
+
+ if (isAHLetter(p) or p.is(.numeric)) {
+ self.run(isAlphaNum);
+ end = self.current.?;
+ done = true;
+ }
+ }
+ }
+
+ if (!done and isAHLetter(latest_non_ignorable)) {
+ if (self.peek()) |p| {
+
+
+ if (p.is(.midletter) or isMidNumLetQ(p)) {
+
+
+ const saved_i = self.cp_iter.i;
+ const saved_current = self.current;
+ const saved_start = self.start;
+
+ _ = self.advance();
+
+ if (self.peek()) |pp| {
+ if (isAHLetter(pp)) {
+ _ = self.advance();
+
+ end = self.current.?;
+ done = true;
+ }
+ }
+
+ if (!done) {
+
+
+ self.cp_iter.i = saved_i;
+ self.current = saved_current;
+ self.start = saved_start;
+ }
+ }
+ }
+ }
+
+ if (!done and latest_non_ignorable.is(.hletter)) {
+ if (self.peek()) |p| {
+
+
+ if (p.is(.squote)) {
+ _ = self.advance();
+ end = self.current.?;
+ done = true;
+ } else if (p.is(.dquote)) {
+
+
+
+
+ const saved_i = self.cp_iter.i;
+ const saved_current = self.current;
+ const saved_start = self.start;
+
+ _ = self.advance();
+
+ if (self.peek()) |pp| {
+ if (pp.is(.hletter)) {
+ _ = self.advance();
+
+ end = self.current.?;
+ done = true;
+ }
+ }
+
+ if (!done) {
+
+
+ self.cp_iter.i = saved_i;
+ self.current = saved_current;
+ self.start = saved_start;
+ }
+ }
+ }
+ }
+
+ if (!done and latest_non_ignorable.is(.numeric)) {
+ if (self.peek()) |p| {
+ if (p.is(.midnum) or isMidNumLetQ(p)) {
+
+
+
+
+ const saved_i = self.cp_iter.i;
+ const saved_current = self.current;
+ const saved_start = self.start;
+
+ _ = self.advance();
+
+ if (self.peek()) |pp| {
+ if (pp.is(.numeric)) {
+ _ = self.advance();
+
+ end = self.current.?;
+ done = true;
+ }
+ }
+
+ if (!done) {
+
+
+ self.cp_iter.i = saved_i;
+ self.current = saved_current;
+ self.start = saved_start;
+ }
+ }
+ }
+ }
+
+ if (!done and (isAHLetter(latest_non_ignorable) or latest_non_ignorable.is(.numeric) or latest_non_ignorable.is(.katakana) or
+ latest_non_ignorable.is(.extendnumlet)))
+ {
+ while (true) {
+ if (self.peek()) |p| {
+
+
+ if (p.is(.extendnumlet)) {
+ _ = self.advance();
+
+ if (self.peek()) |pp| {
+ if (isAHLetter(pp) or isNumeric(pp) or pp.is(.katakana)) {
+
+
+ _ = self.advance();
+
+ }
+ }
+ end = self.current.?;
+ done = true;
+ } else break;
+ } else break;
+ }
+ }
+
+ if (!done and latest_non_ignorable.is(.extendnumlet)) {
+ while (true) {
+ if (self.peek()) |p| {
+
+
+ if (isAHLetter(p) or p.is(.numeric) or p.is(.katakana)) {
+ _ = self.advance();
+
+ end = self.current.?;
+ done = true;
+
+ if (self.peek()) |pp| {
+
+
+ if (pp.is(.extendnumlet)) {
+ _ = self.advance();
+
+ continue;
+ }
+ }
+ } else break;
+ } else break;
+ }
+ }
+
+ if (!done and latest_non_ignorable.is(.katakana)) {
+ if (self.peek()) |p| {
+
+
+ if (p.is(.katakana)) {
+ _ = self.advance();
+ end = self.current.?;
+ done = true;
+ }
+ }
+ }
+
+ if (!done and latest_non_ignorable.is(.regional)) {
+ if (self.peek()) |p| {
+
+
+ if (p.is(.regional)) {
+ _ = self.advance();
+ end = self.current.?;
+ done = true;
+ }
+ }
+ }
+
+ if (!done and latest_non_ignorable.is(.xpic)) {
+ if (self.peek()) |p| {
+
+
+ if (p.is(.xpic) and end.is(.zwj)) {
+ _ = self.advance();
+ end = self.current.?;
+ done = true;
+ }
+ }
+ }
+
+ const start = self.start.?;
+ self.start = self.peek();
+
+
+
+ return self.emit(start, end);
+ }
+
+ return null;
+ }
+
+ fn peek(self: *Self) ?Token {
+ const saved_i = self.cp_iter.i;
+ defer self.cp_iter.i = saved_i;
+
+ return if (self.cp_iter.next()) |cp| Token{
+ .ty = Type.get(cp),
+ .code_point = cp,
+ } else null;
+ }
+
+ fn advance(self: *Self) ?Token {
+ const latest_non_ignorable = if (self.cp_iter.next()) |cp| Token{
+ .ty = Type.get(cp),
+ .code_point = cp,
+ } else return null;
+
+ self.current = latest_non_ignorable;
+ if (self.start == null) self.start = latest_non_ignorable;
+
+
+
+
+ if (!isBreaker(latest_non_ignorable)) self.skipIgnorables();
+
+ return latest_non_ignorable;
+ }
+
+ fn run(self: *Self, predicate: TokenPredicate) void {
+ while (self.peek()) |token| {
+ if (!predicate(token)) break;
+ _ = self.advance();
+ }
+ }
+
+ fn skipIgnorables(self: *Self) void {
+ while (self.peek()) |peek_token| {
+ if (!isIgnorable(peek_token)) break;
+ _ = self.advance();
+ }
+ }
+
+
+
+ fn emit(self: Self, start_token: Token, end_token: Token) Word {
+ const start = start_token.code_point.offset;
+ const end = end_token.code_point.offset + end_token.code_point.len;
+
+ return .{
+ .bytes = self.cp_iter.bytes[start..end],
+ .offset = start,
+ };
+ }
+};
+
+
+
+const TokenPredicate = *const fn (Token) bool;
+
+fn isAHLetter(token: Token) bool {
+ return token.ty == .aletter or token.ty == .hletter;
+}
+
+fn isAlphaNum(token: Token) bool {
+ return isAHLetter(token) or isNumeric(token);
+}
+
+fn isBreaker(token: Token) bool {
+ return token.ty == .newline or token.ty == .cr or token.ty == .lf;
+}
+
+fn isIgnorable(token: Token) bool {
+ return token.ty == .extend or token.ty == .format or token.ty == .zwj;
+}
+
+fn isMidNumLetQ(token: Token) bool {
+ return token.ty == .midnumlet or token.ty == .squote;
+}
+
+fn isNumeric(token: Token) bool {
+ return token.ty == .numeric;
+}
+
+test "Segmentation comptime WordIterator" {
+ const want = [_][]const u8{ "Hello", " ", "World" };
+
+ comptime {
+ var ct_iter = try WordIterator.init("Hello World");
+ var i = 0;
+ while (ct_iter.next()) |word| : (i += 1) {
+ try std.testing.expect(word.eql(want[i]));
+ }
+ }
+}
+
+test "WB3d - Keep horizontal whitespace together." {
+ const want = [_][]const u8{ " ", "Hello", " ", "World", " " };
+
+ comptime {
+ var ct_iter = try WordIterator.init(" Hello World ");
+ var i = 0;
+ while (ct_iter.next()) |word| : (i += 1) {
+ try std.testing.expect(word.eql(want[i]));
+ }
+ }
+}
+
+
+
\ No newline at end of file
diff --git a/docs/src/ziglyph/ziglyph.zig.html b/docs/src/ziglyph/ziglyph.zig.html
new file mode 100644
index 0000000..93b36a9
--- /dev/null
+++ b/docs/src/ziglyph/ziglyph.zig.html
@@ -0,0 +1,612 @@
+
+
+
+
+
ziglyph.zig - source view
+
+
+
+
+
+
+
+const std = @import("std");
+const unicode = std.unicode;
+
+
+
+pub const letter = @import("category/letter.zig");
+pub const mark = @import("category/mark.zig");
+pub const number = @import("category/number.zig");
+pub const punct = @import("category/punct.zig");
+
+
+
+pub const display_width = @import("display_width.zig");
+
+
+
+pub const CodePoint = @import("segmenter/CodePoint.zig");
+pub const CodePointIterator = CodePoint.CodePointIterator;
+pub const readCodePoint = CodePoint.readCodePoint;
+pub const Grapheme = @import("segmenter/Grapheme.zig");
+pub const GraphemeIterator = Grapheme.GraphemeIterator;
+pub const StreamingGraphemeIterator = Grapheme.StreamingGraphemeIterator;
+pub const graphemeBreak = Grapheme.graphemeBreak;
+pub const Word = @import("segmenter/Word.zig");
+pub const WordIterator = Word.WordIterator;
+pub const Sentence = @import("segmenter/Sentence.zig");
+pub const SentenceIterator = Sentence.SentenceIterator;
+pub const ComptimeSentenceIterator = Sentence.ComptimeSentenceIterator;
+
+
+
+pub const Collator = @import("collator/Collator.zig");
+
+
+
+pub const Normalizer = @import("normalizer/Normalizer.zig");
+
+
+
+pub const blocks = @import("autogen/blocks.zig");
+pub const case_folding = @import("autogen/case_folding.zig");
+pub const combining_class = @import("autogen/derived_combining_class.zig");
+pub const core_properties = @import("autogen/derived_core_properties.zig");
+pub const east_asian_width = @import("autogen/derived_east_asian_width.zig");
+pub const general_category = @import("autogen/derived_general_category.zig");
+pub const normalization_props = @import("autogen/derived_normalization_props.zig");
+pub const numeric_type = @import("autogen/derived_numeric_type.zig");
+pub const emoji = @import("autogen/emoji_data.zig");
+pub const grapheme_break = @import("autogen/grapheme_break_property.zig");
+pub const hangul = @import("autogen/hangul_syllable_type.zig");
+pub const lowercase = @import("autogen/lower_map.zig");
+pub const properties = @import("autogen/prop_list.zig");
+pub const sentence_break = @import("autogen/sentence_break_property.zig");
+pub const titlecase = @import("autogen/title_map.zig");
+pub const uppercase = @import("autogen/upper_map.zig");
+pub const word_break = @import("autogen/word_break_property.zig");
+
+pub fn isAlphabetic(cp: u21) bool {
+ return core_properties.isAlphabetic(cp);
+}
+
+pub fn isAsciiAlphabetic(cp: u21) bool {
+ return (cp >= 'A' and cp <= 'Z') or (cp >= 'a' and cp <= 'z');
+}
+
+pub fn isAlphaNum(cp: u21) bool {
+ return isAlphabetic(cp) or isNumber(cp);
+}
+
+pub fn isAsciiAlphaNum(cp: u21) bool {
+ return (cp >= 'A' and cp <= 'Z') or (cp >= 'a' and cp <= 'z') or (cp >= '0' and cp <= '9');
+}
+
+
+pub fn isCased(cp: u21) bool {
+ return letter.isCased(cp);
+}
+
+
+pub fn isCasedStr(str: []const u8) bool {
+ var iter = CodePointIterator{ .bytes = str };
+
+ return while (iter.next()) |cp| {
+ if (!isCased(cp.code)) break false;
+ } else true;
+}
+
+test "ziglyph isCasedStr" {
+ try std.testing.expect(isCasedStr("abc"));
+ try std.testing.expect(!isCasedStr("abc123"));
+ try std.testing.expect(!isCasedStr("123"));
+}
+
+
+pub fn isDecimal(cp: u21) bool {
+ return number.isDecimal(cp);
+}
+
+pub fn isDigit(cp: u21) bool {
+ return number.isDigit(cp);
+}
+
+pub fn isAsciiDigit(cp: u21) bool {
+ return cp >= '0' and cp <= '9';
+}
+
+
+pub fn isGraphic(cp: u21) bool {
+ return isPrint(cp) or isWhiteSpace(cp);
+}
+
+
+
+pub fn isHexDigit(cp: u21) bool {
+ return number.isHexDigit(cp);
+}
+
+pub fn isAsciiHexDigit(cp: u21) bool {
+ return (cp >= 'a' and cp <= 'f') or (cp >= 'A' and cp <= 'F') or (cp >= '0' and cp <= '9');
+}
+
+
+pub fn isPrint(cp: u21) bool {
+ return isAlphaNum(cp) or isMark(cp) or isPunct(cp) or
+ isSymbol(cp) or isWhiteSpace(cp);
+}
+
+pub fn isAsciiPrint(cp: u21) bool {
+ return std.ascii.isPrint(@intCast(cp));
+}
+
+
+pub fn isControl(cp: u21) bool {
+ return general_category.isControl(cp);
+}
+
+pub fn isAsciiControl(cp: u21) bool {
+ return std.ascii.isControl(@intCast(cp));
+}
+
+pub fn isLetter(cp: u21) bool {
+ return letter.isLetter(cp);
+}
+
+pub fn isAsciiLetter(cp: u21) bool {
+ return (cp >= 'A' and cp <= 'Z') or (cp >= 'a' and cp <= 'z');
+}
+
+
+pub fn isLower(cp: u21) bool {
+ return letter.isLower(cp);
+}
+
+pub fn isAsciiLower(cp: u21) bool {
+ return cp >= 'a' and cp <= 'z';
+}
+
+
+pub fn isLowerStr(str: []const u8) bool {
+ var iter = CodePointIterator{ .bytes = str };
+
+ return while (iter.next()) |cp| {
+ if (isCased(cp.code) and !isLower(cp.code)) break false;
+ } else true;
+}
+
+test "ziglyph isLowerStr" {
+ try std.testing.expect(isLowerStr("abc"));
+ try std.testing.expect(isLowerStr("abc123"));
+ try std.testing.expect(!isLowerStr("Abc123"));
+}
+
+
+pub fn isMark(cp: u21) bool {
+ return mark.isMark(cp);
+}
+
+pub fn isNumber(cp: u21) bool {
+ return number.isNumber(cp);
+}
+
+pub fn isAsciiNumber(cp: u21) bool {
+ return cp >= '0' and cp <= '9';
+}
+
+
+pub fn isPunct(cp: u21) bool {
+ return punct.isPunct(cp);
+}
+
+pub fn isAsciiPunct(cp: u21) bool {
+ return std.ascii.isPunct(@intCast(cp));
+}
+
+
+pub fn isWhiteSpace(cp: u21) bool {
+ return properties.isWhiteSpace(cp);
+}
+
+pub fn isAsciiWhiteSpace(cp: u21) bool {
+ return std.ascii.isSpace(@intCast(cp));
+}
+
+
+
+pub fn isSymbol(cp: u21) bool {
+ return general_category.isMathSymbol(cp) or
+ general_category.isCurrencySymbol(cp) or
+ general_category.isModifierSymbol(cp) or
+ general_category.isOtherSymbol(cp);
+}
+
+
+pub fn isTitle(cp: u21) bool {
+ return letter.isTitle(cp);
+}
+
+
+pub fn isUpper(cp: u21) bool {
+ return letter.isUpper(cp);
+}
+
+pub fn isAsciiUpper(cp: u21) bool {
+ return cp >= 'A' and cp <= 'Z';
+}
+
+
+pub fn isUpperStr(str: []const u8) bool {
+ var iter = CodePointIterator{ .bytes = str };
+
+ return while (iter.next()) |cp| {
+ if (isCased(cp.code) and !isUpper(cp.code)) break false;
+ } else true;
+}
+
+test "ziglyph isUpperStr" {
+ try std.testing.expect(isUpperStr("ABC"));
+ try std.testing.expect(isUpperStr("ABC123"));
+ try std.testing.expect(!isUpperStr("abc123"));
+}
+
+
+
+pub fn toLower(cp: u21) u21 {
+ return letter.toLower(cp);
+}
+
+pub fn toAsciiLower(cp: u21) u21 {
+ return if (cp >= 'A' and cp <= 'Z') cp ^ 32 else cp;
+}
+
+
+pub fn toCaseFoldStr(allocator: std.mem.Allocator, str: []const u8) ![]u8 {
+ var result = std.ArrayList(u8).init(allocator);
+ defer result.deinit();
+ var buf: [4]u8 = undefined;
+ var iter = CodePointIterator{ .bytes = str };
+
+ while (iter.next()) |cp| {
+ const cf = letter.toCaseFold(cp.code);
+ for (cf) |cfcp| {
+ if (cfcp == 0) break;
+ const len = try unicode.utf8Encode(cfcp, &buf);
+ try result.appendSlice(buf[0..len]);
+ }
+ }
+
+ return result.toOwnedSlice();
+}
+
+test "ziglyph toCaseFoldStr" {
+ var allocator = std.testing.allocator;
+ const got = try toCaseFoldStr(allocator, "AbC123\u{0390}");
+ defer allocator.free(got);
+ try std.testing.expect(std.mem.eql(u8, "abc123\u{03B9}\u{0308}\u{0301}", got));
+}
+
+
+pub fn toLowerStr(allocator: std.mem.Allocator, str: []const u8) ![]u8 {
+ var result = std.ArrayList(u8).init(allocator);
+ defer result.deinit();
+ var buf: [4]u8 = undefined;
+ var iter = CodePointIterator{ .bytes = str };
+
+ while (iter.next()) |cp| {
+ const len = try unicode.utf8Encode(toLower(cp.code), &buf);
+ try result.appendSlice(buf[0..len]);
+ }
+
+ return result.toOwnedSlice();
+}
+
+test "ziglyph toLowerStr" {
+ var allocator = std.testing.allocator;
+ const got = try toLowerStr(allocator, "AbC123");
+ defer allocator.free(got);
+ try std.testing.expect(std.mem.eql(u8, "abc123", got));
+}
+
+
+
+pub fn toTitle(cp: u21) u21 {
+ return letter.toTitle(cp);
+}
+
+
+pub fn toTitleStr(allocator: std.mem.Allocator, str: []const u8) ![]u8 {
+ var words = try WordIterator.init(str);
+ var result = std.ArrayList(u8).init(allocator);
+ defer result.deinit();
+ var buf: [4]u8 = undefined;
+
+ while (words.next()) |word| {
+ var code_points = CodePointIterator{ .bytes = word.bytes };
+ var got_f = false;
+
+ while (code_points.next()) |cp| {
+ var len: usize = 0;
+
+ if (!got_f and isCased(cp.code)) {
+
+
+ len = try unicode.utf8Encode(toTitle(cp.code), &buf);
+ got_f = true;
+ } else if (isCased(cp.code)) {
+
+
+ len = try unicode.utf8Encode(toLower(cp.code), &buf);
+ } else {
+
+
+ len = try unicode.utf8Encode(cp.code, &buf);
+ }
+
+ try result.appendSlice(buf[0..len]);
+ }
+ }
+
+ return result.toOwnedSlice();
+}
+
+test "ziglyph toTitleStr" {
+ var allocator = std.testing.allocator;
+ const got = try toTitleStr(allocator, "the aBc123 broWn. fox");
+ defer allocator.free(got);
+ try std.testing.expectEqualStrings("The Abc123 Brown. Fox", got);
+}
+
+
+
+pub fn toUpper(cp: u21) u21 {
+ return letter.toUpper(cp);
+}
+
+pub fn toAsciiUpper(cp: u21) u21 {
+ return if (cp >= 'a' and cp <= 'z') cp ^ 32 else cp;
+}
+
+
+pub fn toUpperStr(allocator: std.mem.Allocator, str: []const u8) ![]u8 {
+ var result = std.ArrayList(u8).init(allocator);
+ defer result.deinit();
+ var buf: [4]u8 = undefined;
+ var iter = CodePointIterator{ .bytes = str };
+
+ while (iter.next()) |cp| {
+ const len = try unicode.utf8Encode(toUpper(cp.code), &buf);
+ try result.appendSlice(buf[0..len]);
+ }
+
+ return result.toOwnedSlice();
+}
+
+test "ziglyph toUpperStr" {
+ var allocator = std.testing.allocator;
+ const got = try toUpperStr(allocator, "aBc123");
+ defer allocator.free(got);
+ try std.testing.expect(std.mem.eql(u8, "ABC123", got));
+}
+
+test "ziglyph ASCII methods" {
+ const z = 'F';
+ try std.testing.expect(isAsciiAlphabetic(z));
+ try std.testing.expect(isAsciiAlphaNum(z));
+ try std.testing.expect(isAsciiHexDigit(z));
+ try std.testing.expect(isAsciiPrint(z));
+ try std.testing.expect(isAsciiUpper(z));
+ try std.testing.expect(!isAsciiControl(z));
+ try std.testing.expect(!isAsciiDigit(z));
+ try std.testing.expect(!isAsciiNumber(z));
+ try std.testing.expect(!isAsciiLower(z));
+ try std.testing.expectEqual(toAsciiLower(z), 'f');
+ try std.testing.expectEqual(toAsciiUpper('a'), 'A');
+ try std.testing.expect(isAsciiLower(toAsciiLower(z)));
+}
+
+test "ziglyph struct" {
+ const z = 'z';
+ try std.testing.expect(isAlphaNum(z));
+ try std.testing.expect(!isControl(z));
+ try std.testing.expect(!isDecimal(z));
+ try std.testing.expect(!isDigit(z));
+ try std.testing.expect(!isHexDigit(z));
+ try std.testing.expect(isGraphic(z));
+ try std.testing.expect(isLetter(z));
+ try std.testing.expect(isLower(z));
+ try std.testing.expect(!isMark(z));
+ try std.testing.expect(!isNumber(z));
+ try std.testing.expect(isPrint(z));
+ try std.testing.expect(!isPunct(z));
+ try std.testing.expect(!isWhiteSpace(z));
+ try std.testing.expect(!isSymbol(z));
+ try std.testing.expect(!isTitle(z));
+ try std.testing.expect(!isUpper(z));
+ const uz = toUpper(z);
+ try std.testing.expect(isUpper(uz));
+ try std.testing.expectEqual(uz, 'Z');
+ const lz = toLower(uz);
+ try std.testing.expect(isLower(lz));
+ try std.testing.expectEqual(lz, 'z');
+ const tz = toTitle(lz);
+ try std.testing.expect(isUpper(tz));
+ try std.testing.expectEqual(tz, 'Z');
+}
+
+test "ziglyph isGraphic" {
+ try std.testing.expect(isGraphic('A'));
+ try std.testing.expect(isGraphic('\u{20E4}'));
+ try std.testing.expect(isGraphic('1'));
+ try std.testing.expect(isGraphic('?'));
+ try std.testing.expect(isGraphic(' '));
+ try std.testing.expect(isGraphic('='));
+ try std.testing.expect(!isGraphic('\u{0003}'));
+}
+
+test "ziglyph isHexDigit" {
+ var cp: u21 = '0';
+ while (cp <= '9') : (cp += 1) {
+ try std.testing.expect(isHexDigit(cp));
+ }
+
+ cp = 'A';
+ while (cp <= 'F') : (cp += 1) {
+ try std.testing.expect(isHexDigit(cp));
+ }
+
+ cp = 'a';
+ while (cp <= 'f') : (cp += 1) {
+ try std.testing.expect(isHexDigit(cp));
+ }
+
+ try std.testing.expect(!isHexDigit('\u{0003}'));
+ try std.testing.expect(!isHexDigit('Z'));
+}
+
+test "ziglyph isPrint" {
+ try std.testing.expect(isPrint('A'));
+ try std.testing.expect(isPrint('\u{20E4}'));
+ try std.testing.expect(isPrint('1'));
+ try std.testing.expect(isPrint('?'));
+ try std.testing.expect(isPrint('='));
+ try std.testing.expect(isPrint(' '));
+ try std.testing.expect(isPrint('\t'));
+ try std.testing.expect(!isPrint('\u{0003}'));
+}
+
+test "ziglyph isAlphaNum" {
+ var cp: u21 = '0';
+ while (cp <= '9') : (cp += 1) {
+ try std.testing.expect(isAlphaNum(cp));
+ }
+
+ cp = 'a';
+ while (cp <= 'z') : (cp += 1) {
+ try std.testing.expect(isAlphaNum(cp));
+ }
+
+ cp = 'A';
+ while (cp <= 'Z') : (cp += 1) {
+ try std.testing.expect(isAlphaNum(cp));
+ }
+
+ try std.testing.expect(!isAlphaNum('='));
+}
+
+test "ziglyph isControl" {
+ try std.testing.expect(isControl('\t'));
+ try std.testing.expect(isControl('\u{0008}'));
+ try std.testing.expect(isControl('\u{0012}'));
+ try std.testing.expect(isControl('\n'));
+ try std.testing.expect(isControl('\r'));
+ try std.testing.expect(!isControl('A'));
+}
+
+
+
\ No newline at end of file
diff --git a/docs/ziglexer.js b/docs/ziglexer.js
new file mode 100644
index 0000000..fdd94be
--- /dev/null
+++ b/docs/ziglexer.js
@@ -0,0 +1,2147 @@
+'use strict';
+
+const Tag = {
+ whitespace: "whitespace",
+ invalid: "invalid",
+ identifier: "identifier",
+ string_literal: "string_literal",
+ multiline_string_literal_line: "multiline_string_literal_line",
+ char_literal: "char_literal",
+ eof: "eof",
+ builtin: "builtin",
+ number_literal: "number_literal",
+ doc_comment: "doc_comment",
+ container_doc_comment: "container_doc_comment",
+ line_comment: "line_comment",
+ invalid_periodasterisks: "invalid_periodasterisks",
+ bang: "bang",
+ pipe: "pipe",
+ pipe_pipe: "pipe_pipe",
+ pipe_equal: "pipe_equal",
+ equal: "equal",
+ equal_equal: "equal_equal",
+ equal_angle_bracket_right: "equal_angle_bracket_right",
+ bang_equal: "bang_equal",
+ l_paren: "l_paren",
+ r_paren: "r_paren",
+ semicolon: "semicolon",
+ percent: "percent",
+ percent_equal: "percent_equal",
+ l_brace: "l_brace",
+ r_brace: "r_brace",
+ l_bracket: "l_bracket",
+ r_bracket: "r_bracket",
+ period: "period",
+ period_asterisk: "period_asterisk",
+ ellipsis2: "ellipsis2",
+ ellipsis3: "ellipsis3",
+ caret: "caret",
+ caret_equal: "caret_equal",
+ plus: "plus",
+ plus_plus: "plus_plus",
+ plus_equal: "plus_equal",
+ plus_percent: "plus_percent",
+ plus_percent_equal: "plus_percent_equal",
+ plus_pipe: "plus_pipe",
+ plus_pipe_equal: "plus_pipe_equal",
+ minus: "minus",
+ minus_equal: "minus_equal",
+ minus_percent: "minus_percent",
+ minus_percent_equal: "minus_percent_equal",
+ minus_pipe: "minus_pipe",
+ minus_pipe_equal: "minus_pipe_equal",
+ asterisk: "asterisk",
+ asterisk_equal: "asterisk_equal",
+ asterisk_asterisk: "asterisk_asterisk",
+ asterisk_percent: "asterisk_percent",
+ asterisk_percent_equal: "asterisk_percent_equal",
+ asterisk_pipe: "asterisk_pipe",
+ asterisk_pipe_equal: "asterisk_pipe_equal",
+ arrow: "arrow",
+ colon: "colon",
+ slash: "slash",
+ slash_equal: "slash_equal",
+ comma: "comma",
+ ampersand: "ampersand",
+ ampersand_equal: "ampersand_equal",
+ question_mark: "question_mark",
+ angle_bracket_left: "angle_bracket_left",
+ angle_bracket_left_equal: "angle_bracket_left_equal",
+ angle_bracket_angle_bracket_left: "angle_bracket_angle_bracket_left",
+ angle_bracket_angle_bracket_left_equal: "angle_bracket_angle_bracket_left_equal",
+ angle_bracket_angle_bracket_left_pipe: "angle_bracket_angle_bracket_left_pipe",
+ angle_bracket_angle_bracket_left_pipe_equal: "angle_bracket_angle_bracket_left_pipe_equal",
+ angle_bracket_right: "angle_bracket_right",
+ angle_bracket_right_equal: "angle_bracket_right_equal",
+ angle_bracket_angle_bracket_right: "angle_bracket_angle_bracket_right",
+ angle_bracket_angle_bracket_right_equal: "angle_bracket_angle_bracket_right_equal",
+ tilde: "tilde",
+ keyword_addrspace: "keyword_addrspace",
+ keyword_align: "keyword_align",
+ keyword_allowzero: "keyword_allowzero",
+ keyword_and: "keyword_and",
+ keyword_anyframe: "keyword_anyframe",
+ keyword_anytype: "keyword_anytype",
+ keyword_asm: "keyword_asm",
+ keyword_async: "keyword_async",
+ keyword_await: "keyword_await",
+ keyword_break: "keyword_break",
+ keyword_callconv: "keyword_callconv",
+ keyword_catch: "keyword_catch",
+ keyword_comptime: "keyword_comptime",
+ keyword_const: "keyword_const",
+ keyword_continue: "keyword_continue",
+ keyword_defer: "keyword_defer",
+ keyword_else: "keyword_else",
+ keyword_enum: "keyword_enum",
+ keyword_errdefer: "keyword_errdefer",
+ keyword_error: "keyword_error",
+ keyword_export: "keyword_export",
+ keyword_extern: "keyword_extern",
+ keyword_fn: "keyword_fn",
+ keyword_for: "keyword_for",
+ keyword_if: "keyword_if",
+ keyword_inline: "keyword_inline",
+ keyword_noalias: "keyword_noalias",
+ keyword_noinline: "keyword_noinline",
+ keyword_nosuspend: "keyword_nosuspend",
+ keyword_opaque: "keyword_opaque",
+ keyword_or: "keyword_or",
+ keyword_orelse: "keyword_orelse",
+ keyword_packed: "keyword_packed",
+ keyword_pub: "keyword_pub",
+ keyword_resume: "keyword_resume",
+ keyword_return: "keyword_return",
+ keyword_linksection: "keyword_linksection",
+ keyword_struct: "keyword_struct",
+ keyword_suspend: "keyword_suspend",
+ keyword_switch: "keyword_switch",
+ keyword_test: "keyword_test",
+ keyword_threadlocal: "keyword_threadlocal",
+ keyword_try: "keyword_try",
+ keyword_union: "keyword_union",
+ keyword_unreachable: "keyword_unreachable",
+ keyword_usingnamespace: "keyword_usingnamespace",
+ keyword_var: "keyword_var",
+ keyword_volatile: "keyword_volatile",
+ keyword_while: "keyword_while"
+}
+
+const Tok = {
+ const: { src: "const", tag: Tag.keyword_const },
+ var: { src: "var", tag: Tag.keyword_var },
+ colon: { src: ":", tag: Tag.colon },
+ eql: { src: "=", tag: Tag.equals },
+ space: { src: " ", tag: Tag.whitespace },
+ tab: { src: " ", tag: Tag.whitespace },
+ enter: { src: "\n", tag: Tag.whitespace },
+ semi: { src: ";", tag: Tag.semicolon },
+ l_bracket: { src: "[", tag: Tag.l_bracket },
+ r_bracket: { src: "]", tag: Tag.r_bracket },
+ l_brace: { src: "{", tag: Tag.l_brace },
+ r_brace: { src: "}", tag: Tag.r_brace },
+ l_paren: { src: "(", tag: Tag.l_paren },
+ r_paren: { src: ")", tag: Tag.r_paren },
+ period: { src: ".", tag: Tag.period },
+ comma: { src: ",", tag: Tag.comma },
+ question_mark: { src: "?", tag: Tag.question_mark },
+ asterisk: { src: "*", tag: Tag.asterisk },
+ identifier: (name) => { return { src: name, tag: Tag.identifier } },
+};
+
+
+const State = {
+ start: 0,
+ identifier: 1,
+ builtin: 2,
+ string_literal: 3,
+ string_literal_backslash: 4,
+ multiline_string_literal_line: 5,
+ char_literal: 6,
+ char_literal_backslash: 7,
+ char_literal_hex_escape: 8,
+ char_literal_unicode_escape_saw_u: 9,
+ char_literal_unicode_escape: 10,
+ char_literal_unicode_invalid: 11,
+ char_literal_unicode: 12,
+ char_literal_end: 13,
+ backslash: 14,
+ equal: 15,
+ bang: 16,
+ pipe: 17,
+ minus: 18,
+ minus_percent: 19,
+ minus_pipe: 20,
+ asterisk: 21,
+ asterisk_percent: 22,
+ asterisk_pipe: 23,
+ slash: 24,
+ line_comment_start: 25,
+ line_comment: 26,
+ doc_comment_start: 27,
+ doc_comment: 28,
+ int: 29,
+ int_exponent: 30,
+ int_period: 31,
+ float: 32,
+ float_exponent: 33,
+ ampersand: 34,
+ caret: 35,
+ percent: 36,
+ plus: 37,
+ plus_percent: 38,
+ plus_pipe: 39,
+ angle_bracket_left: 40,
+ angle_bracket_angle_bracket_left: 41,
+ angle_bracket_angle_bracket_left_pipe: 42,
+ angle_bracket_right: 43,
+ angle_bracket_angle_bracket_right: 44,
+ period: 45,
+ period_2: 46,
+ period_asterisk: 47,
+ saw_at_sign: 48,
+ whitespace: 49,
+}
+
+const keywords = {
+ "addrspace": Tag.keyword_addrspace,
+ "align": Tag.keyword_align,
+ "allowzero": Tag.keyword_allowzero,
+ "and": Tag.keyword_and,
+ "anyframe": Tag.keyword_anyframe,
+ "anytype": Tag.keyword_anytype,
+ "asm": Tag.keyword_asm,
+ "async": Tag.keyword_async,
+ "await": Tag.keyword_await,
+ "break": Tag.keyword_break,
+ "callconv": Tag.keyword_callconv,
+ "catch": Tag.keyword_catch,
+ "comptime": Tag.keyword_comptime,
+ "const": Tag.keyword_const,
+ "continue": Tag.keyword_continue,
+ "defer": Tag.keyword_defer,
+ "else": Tag.keyword_else,
+ "enum": Tag.keyword_enum,
+ "errdefer": Tag.keyword_errdefer,
+ "error": Tag.keyword_error,
+ "export": Tag.keyword_export,
+ "extern": Tag.keyword_extern,
+ "fn": Tag.keyword_fn,
+ "for": Tag.keyword_for,
+ "if": Tag.keyword_if,
+ "inline": Tag.keyword_inline,
+ "noalias": Tag.keyword_noalias,
+ "noinline": Tag.keyword_noinline,
+ "nosuspend": Tag.keyword_nosuspend,
+ "opaque": Tag.keyword_opaque,
+ "or": Tag.keyword_or,
+ "orelse": Tag.keyword_orelse,
+ "packed": Tag.keyword_packed,
+ "pub": Tag.keyword_pub,
+ "resume": Tag.keyword_resume,
+ "return": Tag.keyword_return,
+ "linksection": Tag.keyword_linksection,
+ "struct": Tag.keyword_struct,
+ "suspend": Tag.keyword_suspend,
+ "switch": Tag.keyword_switch,
+ "test": Tag.keyword_test,
+ "threadlocal": Tag.keyword_threadlocal,
+ "try": Tag.keyword_try,
+ "union": Tag.keyword_union,
+ "unreachable": Tag.keyword_unreachable,
+ "usingnamespace": Tag.keyword_usingnamespace,
+ "var": Tag.keyword_var,
+ "volatile": Tag.keyword_volatile,
+ "while": Tag.keyword_while,
+};
+
+function make_token(tag, start, end) {
+ return {
+ tag: tag,
+ loc: {
+ start: start,
+ end: end
+ }
+ }
+
+}
+
+function dump_tokens(tokens, raw_source) {
+
+ //TODO: this is not very fast
+ function find_tag_key(tag) {
+ for (const [key, value] of Object.entries(Tag)) {
+ if (value == tag) return key;
+ }
+ }
+
+ for (let i = 0; i < tokens.length; i++) {
+ const tok = tokens[i];
+ const z = raw_source.substring(tok.loc.start, tok.loc.end).toLowerCase();
+ console.log(`${find_tag_key(tok.tag)} "${tok.tag}" '${z}'`)
+ }
+}
+
+function* Tokenizer(raw_source) {
+ let tokenizer = new InnerTokenizer(raw_source);
+ while (true) {
+ let t = tokenizer.next();
+ if (t.tag == Tag.eof)
+ return;
+
+ t.src = raw_source.slice(t.loc.start, t.loc.end);
+
+ yield t;
+ }
+
+}
+function InnerTokenizer(raw_source) {
+ this.index = 0;
+ this.flag = false;
+
+ this.seen_escape_digits = undefined;
+ this.remaining_code_units = undefined;
+
+ this.next = () => {
+ let state = State.start;
+
+ var result = {
+ tag: -1,
+ loc: {
+ start: this.index,
+ end: undefined,
+ },
+ src: undefined,
+ };
+
+ //having a while (true) loop seems like a bad idea the loop should never
+ //take more iterations than twice the length of the source code
+ const MAX_ITERATIONS = raw_source.length * 2;
+ let iterations = 0;
+
+ while (iterations <= MAX_ITERATIONS) {
+
+ if (this.flag) {
+ return make_token(Tag.eof, this.index - 2, this.index - 2);
+ }
+ iterations += 1; // avoid death loops
+
+ var c = raw_source[this.index];
+
+ if (c === undefined) {
+ c = ' '; // push the last token
+ this.flag = true;
+ }
+
+ switch (state) {
+ case State.start:
+ switch (c) {
+ case 0: {
+ if (this.index != raw_source.length) {
+ result.tag = Tag.invalid;
+ result.loc.start = this.index;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ result.loc.end = this.index;
+ return result;
+ }
+ case ' ':
+ case '\n':
+ case '\t':
+ case '\r': {
+ state = State.whitespace;
+ result.tag = Tag.whitespace;
+ result.loc.start = this.index;
+ break;
+ }
+ case '"': {
+ state = State.string_literal;
+ result.tag = Tag.string_literal;
+ break;
+ }
+ case '\'': {
+ state = State.char_literal;
+ break;
+ }
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_': {
+ state = State.identifier;
+ result.tag = Tag.identifier;
+ break;
+ }
+ case '@': {
+ state = State.saw_at_sign;
+ break;
+ }
+ case '=': {
+ state = State.equal;
+ break;
+ }
+ case '!': {
+ state = State.bang;
+ break;
+ }
+ case '|': {
+ state = State.pipe;
+ break;
+ }
+ case '(': {
+ result.tag = Tag.l_paren;
+ this.index += 1;
+ result.loc.end = this.index;
+
+ return result;
+
+ }
+ case ')': {
+ result.tag = Tag.r_paren;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+
+ }
+ case '[': {
+ result.tag = Tag.l_bracket;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+
+ }
+ case ']': {
+ result.tag = Tag.r_bracket;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+
+ }
+ case ';': {
+ result.tag = Tag.semicolon;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+
+ }
+ case ',': {
+ result.tag = Tag.comma;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+
+ }
+ case '?': {
+ result.tag = Tag.question_mark;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+
+ }
+ case ':': {
+ result.tag = Tag.colon;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+
+ }
+ case '%': {
+ state = State.percent; break;
+ }
+ case '*': {
+ state = State.asterisk; break;
+ }
+ case '+': {
+ state = State.plus; break;
+ }
+ case '<': {
+ state = State.angle_bracket_left; break;
+ }
+ case '>': {
+ state = State.angle_bracket_right; break;
+ }
+ case '^': {
+ state = State.caret; break;
+ }
+ case '\\': {
+ state = State.backslash;
+ result.tag = Tag.multiline_string_literal_line; break;
+ }
+ case '{': {
+ result.tag = Tag.l_brace;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+
+ }
+ case '}': {
+ result.tag = Tag.r_brace;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+
+ }
+ case '~': {
+ result.tag = Tag.tilde;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+
+ }
+ case '.': {
+ state = State.period; break;
+ }
+ case '-': {
+ state = State.minus; break;
+ }
+ case '/': {
+ state = State.slash; break;
+ }
+ case '&': {
+ state = State.ampersand; break;
+ }
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ state = State.int;
+ result.tag = Tag.number_literal; break;
+ }
+ default: {
+ result.tag = Tag.invalid;
+ result.loc.end = this.index;
+ this.index += 1;
+ return result;
+ }
+ }
+ break;
+ case State.saw_at_sign:
+ switch (c) {
+ case '"': {
+ result.tag = Tag.identifier;
+ state = State.string_literal; break;
+ }
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_': {
+ state = State.builtin;
+ result.tag = Tag.builtin;
+ break;
+ }
+ default: {
+ result.tag = Tag.invalid;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.ampersand:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.ampersand_equal;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.ampersand; result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.asterisk: switch (c) {
+ case '=': {
+ result.tag = Tag.asterisk_equal;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+ }
+ case '*': {
+ result.tag = Tag.asterisk_asterisk;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+ }
+ case '%': {
+ state = State.asterisk_percent; break;
+ }
+ case '|': {
+ state = State.asterisk_pipe; break;
+ }
+ default: {
+ result.tag = Tag.asterisk;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.asterisk_percent:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.asterisk_percent_equal;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.asterisk_percent;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.asterisk_pipe:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.asterisk_pipe_equal;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.asterisk_pipe; result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.percent:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.percent_equal;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.percent; result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.plus:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.plus_equal;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+ }
+ case '+': {
+ result.tag = Tag.plus_plus;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+ }
+ case '%': {
+ state = State.plus_percent; break;
+ }
+ case '|': {
+ state = State.plus_pipe; break;
+ }
+ default: {
+ result.tag = Tag.plus; result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.plus_percent:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.plus_percent_equal;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.plus_percent; result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.plus_pipe:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.plus_pipe_equal;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.plus_pipe; result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.caret:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.caret_equal;
+ this.index += 1; result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.caret; result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.identifier:
+ switch (c) {
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': break;
+ default: {
+ // if (Token.getKeyword(buffer[result.loc.start..this.index])) | tag | {
+ const z = raw_source.substring(result.loc.start, this.index);
+ if (z in keywords) {
+ result.tag = keywords[z];
+ }
+ result.loc.end = this.index;
+ return result;
+ }
+
+
+ }
+ break;
+ case State.builtin: switch (c) {
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': break;
+ default: result.loc.end = this.index;
+ return result;
+ }
+ break;
+ case State.backslash:
+ switch (c) {
+ case '\\': {
+ state = State.multiline_string_literal_line;
+ break;
+ }
+ default: {
+ result.tag = Tag.invalid;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.string_literal:
+ switch (c) {
+ case '\\': {
+ state = State.string_literal_backslash; break;
+ }
+ case '"': {
+ this.index += 1;
+ result.loc.end = this.index;
+
+ return result;
+ }
+ case 0: {
+ //TODO: PORT
+ // if (this.index == buffer.len) {
+ // result.tag = .invalid;
+ // break;
+ // } else {
+ // checkLiteralCharacter();
+ // }
+ result.loc.end = this.index;
+ return result;
+ }
+ case '\n': {
+ result.tag = Tag.invalid;
+ result.loc.end = this.index;
+ return result;
+ }
+ //TODO: PORT
+ //default: checkLiteralCharacter(),
+ }
+ break;
+ case State.string_literal_backslash:
+ switch (c) {
+ case 0:
+ case '\n': {
+ result.tag = Tag.invalid;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ state = State.string_literal; break;
+ }
+ }
+ break;
+ case State.char_literal: switch (c) {
+ case 0: {
+ result.tag = Tag.invalid;
+ result.loc.end = this.index;
+ return result;
+ }
+ case '\\': {
+ state = State.char_literal_backslash;
+ break;
+ }
+ //TODO: PORT
+ // '\'', 0x80...0xbf, 0xf8...0xff => {
+ // result.tag = .invalid;
+ // break;
+ // },
+ // 0xc0...0xdf => { // 110xxxxx
+ // this.remaining_code_units = 1;
+ // state = .char_literal_unicode;
+ // },
+ // 0xe0...0xef => { // 1110xxxx
+ // this.remaining_code_units = 2;
+ // state = .char_literal_unicode;
+ // },
+ // 0xf0...0xf7 => { // 11110xxx
+ // this.remaining_code_units = 3;
+ // state = .char_literal_unicode;
+ // },
+
+ // case 0x80:
+ // case 0x81:
+ // case 0x82:
+ // case 0x83:
+ // case 0x84:
+ // case 0x85:
+ // case 0x86:
+ // case 0x87:
+ // case 0x88:
+ // case 0x89:
+ // case 0x8a:
+ // case 0x8b:
+ // case 0x8c:
+ // case 0x8d:
+ // case 0x8e:
+ // case 0x8f:
+ // case 0x90:
+ // case 0x91:
+ // case 0x92:
+ // case 0x93:
+ // case 0x94:
+ // case 0x95:
+ // case 0x96:
+ // case 0x97:
+ // case 0x98:
+ // case 0x99:
+ // case 0x9a:
+ // case 0x9b:
+ // case 0x9c:
+ // case 0x9d:
+ // case 0x9e:
+ // case 0x9f:
+ // case 0xa0:
+ // case 0xa1:
+ // case 0xa2:
+ // case 0xa3:
+ // case 0xa4:
+ // case 0xa5:
+ // case 0xa6:
+ // case 0xa7:
+ // case 0xa8:
+ // case 0xa9:
+ // case 0xaa:
+ // case 0xab:
+ // case 0xac:
+ // case 0xad:
+ // case 0xae:
+ // case 0xaf:
+ // case 0xb0:
+ // case 0xb1:
+ // case 0xb2:
+ // case 0xb3:
+ // case 0xb4:
+ // case 0xb5:
+ // case 0xb6:
+ // case 0xb7:
+ // case 0xb8:
+ // case 0xb9:
+ // case 0xba:
+ // case 0xbb:
+ // case 0xbc:
+ // case 0xbd:
+ // case 0xbe:
+ // case 0xbf:
+ // case 0xf8:
+ // case 0xf9:
+ // case 0xfa:
+ // case 0xfb:
+ // case 0xfc:
+ // case 0xfd:
+ // case 0xfe:
+ // case 0xff:
+ // result.tag = .invalid;
+ // break;
+ // case 0xc0:
+ // case 0xc1:
+ // case 0xc2:
+ // case 0xc3:
+ // case 0xc4:
+ // case 0xc5:
+ // case 0xc6:
+ // case 0xc7:
+ // case 0xc8:
+ // case 0xc9:
+ // case 0xca:
+ // case 0xcb:
+ // case 0xcc:
+ // case 0xcd:
+ // case 0xce:
+ // case 0xcf:
+ // case 0xd0:
+ // case 0xd1:
+ // case 0xd2:
+ // case 0xd3:
+ // case 0xd4:
+ // case 0xd5:
+ // case 0xd6:
+ // case 0xd7:
+ // case 0xd8:
+ // case 0xd9:
+ // case 0xda:
+ // case 0xdb:
+ // case 0xdc:
+ // case 0xdd:
+ // case 0xde:
+ // case 0xdf:
+ // this.remaining_code_units = 1;
+ // state = .char_literal_unicode;
+ // case 0xe0:
+ // case 0xe1:
+ // case 0xe2:
+ // case 0xe3:
+ // case 0xe4:
+ // case 0xe5:
+ // case 0xe6:
+ // case 0xe7:
+ // case 0xe8:
+ // case 0xe9:
+ // case 0xea:
+ // case 0xeb:
+ // case 0xec:
+ // case 0xed:
+ // case 0xee:
+ // case 0xef:
+ // this.remaining_code_units = 2;
+ // state = .char_literal_unicode;
+ // case 0xf0:
+ // case 0xf1:
+ // case 0xf2:
+ // case 0xf3:
+ // case 0xf4:
+ // case 0xf5:
+ // case 0xf6:
+ // case 0xf7:
+ // this.remaining_code_units = 3;
+ // state = .char_literal_unicode;
+
+ case '\n': {
+ result.tag = Tag.invalid;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ state = State.char_literal_end; break;
+ }
+ }
+ break;
+ case State.char_literal_backslash:
+ switch (c) {
+ case 0:
+ case '\n': {
+ result.tag = Tag.invalid;
+ result.loc.end = this.index;
+ return result;
+ }
+ case 'x': {
+ state = State.char_literal_hex_escape;
+ this.seen_escape_digits = 0; break;
+ }
+ case 'u': {
+ state = State.char_literal_unicode_escape_saw_u; break;
+ }
+ default: {
+ state = State.char_literal_end; break;
+ }
+ }
+ break;
+ case State.char_literal_hex_escape:
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F': {
+ this.seen_escape_digits += 1;
+ if (this.seen_escape_digits == 2) {
+ state = State.char_literal_end;
+ } break;
+ }
+ default: {
+ result.tag = Tag.invalid;
+ esult.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.char_literal_unicode_escape_saw_u:
+ switch (c) {
+ case 0: {
+ result.tag = Tag.invalid;
+ result.loc.end = this.index;
+ return result;
+ }
+ case '{': {
+ state = State.char_literal_unicode_escape; break;
+ }
+ default: {
+ result.tag = Tag.invalid;
+ state = State.char_literal_unicode_invalid; break;
+ }
+ }
+ break;
+ case State.char_literal_unicode_escape:
+ switch (c) {
+ case 0: {
+ result.tag = Tag.invalid;
+ result.loc.end = this.index;
+ return result;
+ }
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F': break;
+ case '}': {
+ state = State.char_literal_end; // too many/few digits handled later
+ break;
+ }
+ default: {
+ result.tag = Tag.invalid;
+ state = State.char_literal_unicode_invalid; break;
+ }
+ }
+ break;
+ case State.char_literal_unicode_invalid:
+ switch (c) {
+ // Keep consuming characters until an obvious stopping point.
+ // This consolidates e.g. `u{0ab1Q}` into a single invalid token
+ // instead of creating the tokens `u{0ab1`, `Q`, `}`
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '}':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': break;
+ default: break;
+ }
+ break;
+ case State.char_literal_end:
+ switch (c) {
+ case '\'': {
+ result.tag = Tag.char_literal;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.invalid;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.char_literal_unicode:
+ switch (c) {
+ // 0x80...0xbf => {
+ // this.remaining_code_units -= 1;
+ // if (this.remaining_code_units == 0) {
+ // state = .char_literal_end;
+ // }
+ // },
+ default: {
+ result.tag = Tag.invalid;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.multiline_string_literal_line:
+ switch (c) {
+ case 0:
+ result.loc.end = this.index;
+ return result;
+ case '\n': {
+
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ case '\t': break;
+ //TODO: PORT
+ //default: checkLiteralCharacter(),
+
+ }
+ break;
+ case State.bang:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.bang_equal;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.bang;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.pipe:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.pipe_equal;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ case '|': {
+ result.tag = Tag.pipe_pipe;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.pipe;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.equal: switch (c) {
+ case '=': {
+ result.tag = Tag.equal_equal;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ case '>': {
+ result.tag = Tag.equal_angle_bracket_right;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.equal;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.minus: switch (c) {
+ case '>': {
+ result.tag = Tag.arrow;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ case '=': {
+ result.tag = Tag.minus_equal;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ case '%': {
+ state = State.minus_percent; break;
+ }
+ case '|': {
+ state = State.minus_pipe; break;
+ }
+ default: {
+ result.tag = Tag.minus;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.minus_percent:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.minus_percent_equal;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.minus_percent;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.minus_pipe:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.minus_pipe_equal;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.minus_pipe;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.angle_bracket_left:
+ switch (c) {
+ case '<': {
+ state = State.angle_bracket_angle_bracket_left; break;
+ }
+ case '=': {
+ result.tag = Tag.angle_bracket_left_equal;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.angle_bracket_left;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.angle_bracket_angle_bracket_left:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.angle_bracket_angle_bracket_left_equal;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ case '|': {
+ state = State.angle_bracket_angle_bracket_left_pipe;
+ }
+ default: {
+ result.tag = Tag.angle_bracket_angle_bracket_left;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.angle_bracket_angle_bracket_left_pipe:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.angle_bracket_angle_bracket_left_pipe_equal;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.angle_bracket_angle_bracket_left_pipe;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.angle_bracket_right:
+ switch (c) {
+ case '>': {
+ state = State.angle_bracket_angle_bracket_right; break;
+ }
+ case '=': {
+ result.tag = Tag.angle_bracket_right_equal;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.angle_bracket_right;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.angle_bracket_angle_bracket_right:
+ switch (c) {
+ case '=': {
+ result.tag = Tag.angle_bracket_angle_bracket_right_equal;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.angle_bracket_angle_bracket_right;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.period:
+ switch (c) {
+ case '.': {
+ state = State.period_2; break;
+ }
+ case '*': {
+ state = State.period_asterisk; break;
+ }
+ default: {
+ result.tag = Tag.period;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.period_2:
+ switch (c) {
+ case '.': {
+ result.tag = Tag.ellipsis3;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.ellipsis2;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.period_asterisk:
+ switch (c) {
+ case '*': {
+ result.tag = Tag.invalid_periodasterisks;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.period_asterisk;
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ break;
+ case State.slash:
+ switch (c) {
+ case '/': {
+ state = State.line_comment_start;
+ break;
+ }
+ case '=': {
+ result.tag = Tag.slash_equal;
+ this.index += 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ default: {
+ result.tag = Tag.slash;
+ result.loc.end = this.index;
+ return result;
+ }
+ } break;
+ case State.line_comment_start:
+ switch (c) {
+ case 0: {
+ if (this.index != raw_source.length) {
+ result.tag = Tag.invalid;
+ this.index += 1;
+ }
+ result.loc.end = this.index;
+ return result;
+ }
+ case '/': {
+ state = State.doc_comment_start; break;
+ }
+ case '!': {
+ result.tag = Tag.container_doc_comment;
+ state = State.doc_comment; break;
+ }
+ case '\n': {
+ state = State.start;
+ result.loc.start = this.index + 1; break;
+ }
+ case '\t':
+ state = State.line_comment; break;
+ default: {
+ state = State.line_comment;
+ //TODO: PORT
+ //checkLiteralCharacter();
+ break;
+ }
+ } break;
+ case State.doc_comment_start:
+ switch (c) {
+ case '/': {
+ state = State.line_comment; break;
+ }
+ case 0:
+ case '\n':
+ {
+ result.tag = Tag.doc_comment;
+ result.loc.end = this.index;
+ return result;
+ }
+ case '\t': {
+ state = State.doc_comment;
+ result.tag = Tag.doc_comment; break;
+ }
+ default: {
+ state = State.doc_comment;
+ result.tag = Tag.doc_comment;
+ //TODO: PORT
+ //checkLiteralCharacter();
+ break;
+ }
+ } break;
+ case State.line_comment:
+ switch (c) {
+ case 0: {
+ if (this.index != raw_source.length) {
+ result.tag = Tag.invalid;
+ this.index += 1;
+ }
+ result.loc.end = this.index;
+ return result;
+ }
+ case '\n': {
+ result.tag = Tag.line_comment;
+ result.loc.end = this.index;
+ return result;
+ }
+ case '\t': break;
+ //TODO: PORT
+ //default: checkLiteralCharacter(),
+ } break;
+ case State.doc_comment:
+ switch (c) {
+ case 0://
+ case '\n':
+ result.loc.end = this.index;
+ return result;
+ case '\t': break;
+ //TODOL PORT
+ // default: checkLiteralCharacter(),
+ default:
+ break;
+ } break;
+ case State.int:
+ switch (c) {
+ case '.':
+ state = State.int_period;
+ break;
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ break;
+ case 'e':
+ case 'E':
+ case 'p':
+ case 'P':
+ state = State.int_exponent;
+ break;
+ default: result.loc.end = this.index;
+ return result;
+ } break;
+ case State.int_exponent:
+ switch (c) {
+ case '-':
+ case '+':
+ {
+ ``
+ state = State.float; break;
+ }
+ default: {
+ this.index -= 1;
+ state = State.int; break;
+ }
+ } break;
+ case State.int_period: switch (c) {
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': {
+ state = State.float; break;
+ }
+ case 'e':
+ case 'E':
+ case 'p':
+ case 'P':
+ state = State.float_exponent; break;
+ default: {
+ this.index -= 1;
+ result.loc.end = this.index;
+ return result;
+ }
+ } break;
+ case State.float:
+ switch (c) {
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ break;
+
+ case 'e':
+ case 'E':
+ case 'p':
+ case 'P':
+ state = State.float_exponent; break;
+ default: result.loc.end = this.index;
+ return result;
+ } break;
+ case State.float_exponent:
+ switch (c) {
+ case '-':
+ case '+':
+ state = State.float; break;
+ default: {
+ this.index -= 1;
+ state = State.float; break;
+ }
+ }
+ break;
+
+ case State.whitespace:
+ switch(c) {
+ case ' ':
+ case '\n':
+ case '\t':
+ case '\r': {
+ break;
+ }
+ default: {
+ result.loc.end = this.index;
+ return result;
+ }
+ }
+ }
+ this.index += 1;
+ }
+
+ //TODO: PORT
+ // if (result.tag == Tag.eof) {
+ // if (pending_invalid_token) | token | {
+ // pending_invalid_token = null;
+ // return token;
+ // }
+ // result.loc.start = sindex;
+ // }
+
+ result.loc.end = this.index;
+ return result;
+
+ }
+}
+
+
+const builtin_types = [
+ "f16", "f32", "f64", "f80", "f128",
+ "c_longdouble", "c_short", "c_ushort", "c_int", "c_uint",
+ "c_long", "c_ulong", "c_longlong", "c_ulonglong", "c_char",
+ "anyopaque", "void", "bool", "isize", "usize",
+ "noreturn", "type", "anyerror", "comptime_int", "comptime_float",
+];
+
+function isSimpleType(typeName) {
+ return builtin_types.includes(typeName) || isIntType(typeName);
+}
+
+function isIntType(typeName) {
+ if (typeName[0] != 'u' && typeName[0] != 'i') return false;
+ let i = 1;
+ if (i == typeName.length) return false;
+ for (; i < typeName.length; i += 1) {
+ if (typeName[i] < '0' || typeName[i] > '9') return false;
+ }
+ return true;
+}
+
+function isSpecialIndentifier(identifier) {
+ return ["null", "true", "false", ,"undefined"].includes(identifier);
+}
+
+//const fs = require('fs');
+//const src = fs.readFileSync("../std/c.zig", 'utf8');
+//console.log(generate_html_for_src(src));
+
+
+// gist for zig_lexer_test code: https://gist.github.com/Myvar/2684ba4fb86b975274629d6f21eddc7b
+// // Just for testing not to commit in pr
+// var isNode = new Function("try {return this===global;}catch(e){return false;}");
+// if (isNode()) {
+
+
+// //const s = "const std = @import(\"std\");";
+// //const toksa = tokenize_zig_source(s);
+// //dump_tokens(toksa, s);
+// //console.log(JSON.stringify(toksa));
+
+// const fs = require('fs');
+
+// function testFile(fileName) {
+// //console.log(fileName);
+// var exec = require('child_process').execFileSync;
+// var passed = true;
+// const zig_data = exec('./zig_lexer_test', [fileName]);
+// const data = fs.readFileSync(fileName, 'utf8');
+
+// const toks = tokenize_zig_source(data);
+// const a_json = toks;
+
+// // dump_tokens(a_json, data);
+// // return;
+
+// const b_json = JSON.parse(zig_data.toString());
+
+// if (a_json.length !== b_json.length) {
+// console.log("FAILED a and be is not the same length");
+// passed = false;
+// //return;
+// }
+
+// let len = a_json.length;
+// if (len >= b_json.length) len = b_json.length;
+
+// for (let i = 0; i < len; i++) {
+// const a = a_json[i];
+// const b = b_json[i];
+
+// // console.log(a.tag + " == " + b.tag);
+
+// if (a.tag !== b.tag) {
+
+// // console.log("Around here:");
+// // console.log(
+// // data.substring(b_json[i - 2].loc.start, b_json[i - 2].loc.end),
+// // data.substring(b_json[i - 1].loc.start, b_json[i - 1].loc.end),
+// // data.substring(b_json[i].loc.start, b_json[i].loc.end),
+// // data.substring(b_json[i + 1].loc.start, b_json[i + 1].loc.end),
+// // data.substring(b_json[i + 2].loc.start, b_json[i + 2].loc.end),
+// // );
+
+// console.log("TAG: a != b");
+// console.log("js", a.tag);
+// console.log("zig", b.tag);
+// passed = false;
+// return;
+// }
+
+// if (a.tag !== Tag.eof && a.loc.start !== b.loc.start) {
+// console.log("START: a != b");
+
+// console.log("js", "\"" + data.substring(a_json[i ].loc.start, a_json[i].loc.end) + "\"");
+// console.log("zig", "\"" + data.substring(b_json[i ].loc.start, b_json[i].loc.end) + "\"");
+
+
+// passed = false;
+// return;
+// }
+
+// // if (a.tag !== Tag.eof && a.loc.end !== b.loc.end) {
+// // console.log("END: a != b");
+// // // console.log("Around here:");
+// // // console.log(
+// // // // data.substring(b_json[i - 2].loc.start, b_json[i - 2].loc.end),
+// // // // data.substring(b_json[i - 1].loc.start, b_json[i - 1].loc.end),
+// // // data.substring(b_json[i ].loc.start, b_json[i].loc.end),
+// // // // data.substring(b_json[i + 1].loc.start, b_json[i + 1].loc.end),
+// // // // data.substring(b_json[i + 2].loc.start, b_json[i + 2].loc.end),
+// // // );
+// // console.log("js", "\"" + data.substring(a_json[i ].loc.start, a_json[i].loc.end) + "\"");
+// // console.log("zig", "\"" + data.substring(b_json[i ].loc.start, b_json[i].loc.end) + "\"");
+// // passed = false;
+// // return;
+// // }
+// }
+// return passed;
+// }
+// var path = require('path');
+// function fromDir(startPath, filter) {
+// if (!fs.existsSync(startPath)) {
+// console.log("no dir ", startPath);
+// return;
+// }
+// var files = fs.readdirSync(startPath);
+// for (var i = 0; i < files.length; i++) {
+// var filename = path.join(startPath, files[i]);
+// var stat = fs.lstatSync(filename);
+// if (stat.isDirectory()) {
+// fromDir(filename, filter); //recurse
+// } else if (filename.endsWith(filter)) {
+// try {
+// console.log('-- TESTING: ', filename);
+// console.log("\t\t", testFile(filename));
+// }
+// catch {
+// }
+// };
+// };
+// };
+// fromDir('../std', '.zig');
+// //console.log(testFile("/home/myvar/code/zig/lib/std/fmt/errol.zig"));
+// //console.log(testFile("test.zig"));
+// }
\ No newline at end of file