/* * Copyright (c) 2004-2014, Willem Cazander * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.x4o.o2o; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.PrimitiveIterator; /** * CDC1604DashP6 has 27 pie slice number systems and BASIC letters in a six bit encoding. * * This is used as the first 64 word numbers of the china four corner method, and acts like ascii glue for adult 18 bit computers. * * @author Willem Cazander * @version 1.0 Dec 22, 2024 */ public enum CDC1604DashP6 { // [NUL][WN][WG][WE] [WL][WS]?! {[(< }])> // ~+-* ,.:; '"`^ =#$% // |_\/ @ABC DEFG HIJK // LMNO PQRS TUVW XYZ& /// NUL for termination. _NUL('\u0000'), /// Select packed number encoding. /// A = 1, first P6 is terminator select, than next P6 _A++ select pie part 1-27, until other P6 stops it. /// Example ascii "012" is /// 0 = _WORD_NUMBER _A _A (WN T001 PART_1 = 0) /// 12 = _WORD_NUMBER _I _A _B (WN T009 PART_1+2 = 1+2) _WORD_NUMBER('\u0001'), /// Word glue to flag for automatic casing or separator in renderer. _WORD_GLUE('\u0002'), /// Escape to terminal control code. (note only needed for 6 bit and 8 bit systems) _WORD_ESC('\u0003'), _WORD_LINE('\n'), _WORD_SPACE(' '), _QUESTION_MARK('?'), _EXCLAMATION_MARK('!'), _CURLY_BRACKET_LEFT('{'), _SQUARE_BRACKET_LEFT('['), _ROUND_BRACKET_LEFT('('), _LESSER_THAN_SIGN('<'), _CURLY_BRACKET_RIGHT('}'), _SQUARE_BRACKET_RIGHT(']'), _ROUND_BRACKET_RIGHT(')'), _GREATER_THAN_SIGN('>'), _TILDE_SIGN('~'), _PLUS_SIGN('+'), _MINUS_SIGN('-'), _ASTERISK('*'), _COMMA(','), _FULL_POINT('.'), _COLON(':'), _SEMICOLON(';'), _APOSTROPHE('\''), _QUOTATION_MARK('\"'), _BACKTICK_MARK('`'), _CARET('^'), _EQUALS_SIGN('='), _NUMBER_SIGN('#'), _DOLLAR_SIGN('$'), _PERCENT_SIGN('%'), _VERTICAL_BAR('|'), _UNDERSCORE('_'), _BACKSLASH('\\'), _SLASH('/'), _AT_SIGN('@'), _A('A', "Æ æ Å å Ǻ ǻ Ḁ ḁ ẚ Ă ă Ặ ặ Ắ ắ Ằ ằ Ẳ ẳ Ẵ ẵ Ȃ ȃ Â â Ậ ậ Ấ ấ Ầ ầ Ẫ ẫ Ẩ ẩ Ả ả Ǎ ǎ Ⱥ ⱥ Ȧ ȧ Ǡ ǡ Ạ ạ Ä ä Ǟ ǟ À à Ȁ ȁ Á á Ā ā Ā̀ ā̀ Ã ã Ą ą Ą́ ą́ Ą̃ ą̃ A̲ a̲ ᶏ"), _B('B', "Ƀ ƀ Ḃ ḃ Ḅ ḅ Ḇ ḇ Ɓ ɓ ᵬ ᶀ"), _C('C', "Ć ć Ĉ ĉ Č č Ċ ċ Ḉ ḉ Ƈ ƈ C̈ c̈ Ȼ ȼ Ç ç Ꞔ ꞔ Ꞓ ꞓ"), _D('D', "Đ đ Ꟈ ꟈ Ɗ ɗ Ḋ ḋ Ḍ ḍ Ḑ ḑ Ḓ ḓ Ď ď Ḏ ḏ"), _E('E', "Ĕ ĕ Ḝ ḝ Ȇ ȇ Ê ê Ê̄ ê̄ Ê̌ ê̌ Ề ề Ế ế Ể ể Ễ ễ Ệ ệ Ẻ ẻ Ḙ ḙ Ě ě Ɇ ɇ Ė ė Ė́ ė́ Ė̃ ė̃ Ẹ ẹ Ë ë È è È̩ è̩ Ȅ ȅ É é É̩ Ē ē Ḕ ḕ Ḗ ḗ Ẽ ẽ Ḛ ḛ Ę ę Ę́ ę́ Ę̃ ę̃ Ȩ ȩ E̩ e̩ ᶒ"), _F('F', "Ƒ ƒ Ḟ ḟ ᵮ ᶂ Ꞙ ꞙ"), _G('G', "Ǵ ǵ Ǥ ǥ Ĝ ĝ Ǧ ǧ Ğ ğ Ģ ģ Ɠ ɠ Ġ ġ Ḡ ḡ Ꞡ ꞡ ᶃ"), _H('H', "Ĥ ĥ Ȟ ȟ Ħ ħ Ḩ ḩ Ⱨ ⱨ ẖ ẖ Ḥ ḥ Ḣ ḣ Ḧ ḧ Ḫ ḫ ꞕ Ꜧ ꜧ"), _I('I', "Ị ị Ĭ ĭ Î î Ǐ ǐ Ɨ ɨ Ï ï Ḯ ḯ Í í Ì ì Ȉ ȉ Į į Į́ Į̃ Ī ī Ī̀ ī̀ ᶖ Ỉ ỉ Ȋ ȋ Ĩ ĩ Ḭ ḭ ᶤ"), _J('J', "J́ j́ Ĵ ĵ J̌ ǰ Ɉ ɉ J̃ j̇̃"), _K('K', "Ƙ ƙ Ꝁ ꝁ Ḱ ḱ Ǩ ǩ Ḳ ḳ Ķ ķ ᶄ Ⱪ ⱪ Ḵ ḵ"), _L('L', "Ĺ ĺ Ł ł Ľ ľ Ḹ ḹ L̃ l̃ Ļ ļ Ŀ ŀ Ḷ ḷ Ḻ ḻ Ḽ ḽ Ƚ ƚ Ⱡ ⱡ"), _M('M', "Ḿ ḿ Ṁ ṁ Ṃ ṃ M̃ m̃ ᵯ"), _N('N', "Ń ń Ñ ñ Ň ň Ǹ ǹ Ṅ ṅ Ṇ ṇ Ņ ņ Ṉ ṉ Ṋ ṋ Ꞥ ꞥ ᵰ ᶇ"), _O('O', "Ø ø Ǿ ǿ Ö ö Ȫ ȫ Ó ó Ò ò Ô ô Ố ố Ồ ồ Ổ ổ Ỗ ỗ Ộ ộ Ǒ ǒ Ő ő Ŏ ŏ Ȏ ȏ Ȯ ȯ Ȱ ȱ Ọ ọ Ɵ ɵ ᶱ Ơ ơ Ớ ớ Ờ ờ Ỡ ỡ Ợ ợ Ở ở Ỏ ỏ Ō ō Ṓ ṓ Ṑ ṑ Õ õ Ȭ ȭ Ṍ ṍ Ṏ ṏ Ǫ ǫ Ȍ ȍ O̩ o̩ Ó̩ ó̩ Ò̩ ò̩ Ǭ ǭ O͍ o͍"), _P('P', "Ṕ ṕ Ṗ ṗ Ᵽ ᵽ Ƥ ƥ ᵱ ᶈ"), _Q('Q', "ʠ Ɋ ɋ q̃"), _R('R', "Ŕ ŕ Ɍ ɍ Ř ř Ŗ ŗ Ṙ ṙ Ȑ ȑ Ȓ ȓ Ṛ ṛ Ṝ ṝ Ṟ ṟ Ꞧ ꞧ Ɽ ɽ R̃ r̃ ᵲ ꭨ ᵳ ᶉ"), _S('S', "Ś ś Ṡ ṡ ẛ Ṩ ṩ Ṥ ṥ Ṣ ṣ S̩ s̩ Ꞩ ꞩ Ꟊ ꟊ Ꟍ ꟍ Ŝ ŝ Ṧ ṧ Š š Ş ş Ș ș S̈ s̈ ᶊ Ȿ ȿ ᵴ ᶳ"), _T('T', "Ť ť Ṫ ṫ ẗ Ţ ţ Ṭ ṭ Ʈ ʈ Ț ț ƫ Ṱ ṱ Ṯ ṯ Ŧ ŧ Ⱦ ⱦ Ƭ ƭ ᵵ ᶵ"), _U('U', "Ŭ ŭ Ʉ ʉ ᵾ ᶶ Ꞹ ꞹ Ụ ụ Ü ü Ǜ ǜ Ǘ ǘ Ǚ ǚ Ǖ ǖ Ṳ ṳ Ú ú Ù ù Û û Ṷ ṷ Ǔ ǔ Ȗ ȗ Ű ű Ŭ ŭ Ư ư Ứ ứ Ừ ừ Ử ử Ự ự Ữ Ữ Ủ ủ Ū ū Ū̀ ū̀ Ū́ ū́ Ṻ ṻ Ū̃ ū̃ Ũ ũ Ṹ ṹ Ṵ ṵ ᶙ Ų ų Ų́ ų́ Ų̃ ų̃ Ȕ ȕ Ů ů"), _V('V', "Ṽ ṽ Ṿ ṿ Ʋ ʋ ᶌ"), _W('W', "Ẃ ẃ Ẁ ẁ Ŵ ŵ Ẅ ẅ Ẇ ẇ Ẉ ẉ ẘ"), _X('X', "Ẍ ẍ Ẋ ẋ X̂ x̂ ᶍ"), _Y('Y', "Ý ý Ỳ ỳ Ŷ ŷ Ÿ ÿ Ỹ ỹ Ẏ ẏ Ỵ ỵ ẙ Ỷ ỷ Ȳ ȳ Ɏ ɏ Ƴ ƴ"), _Z('Z', "Ź ź Ẑ ẑ Ž ž Ż ż Ẓ ẓ Ẕ ẕ Ƶ ƶ ᵶ Ᶎ ᶎ Ⱬ ⱬ"), /// The 27th letter is at the end of the old english alphabet. _AMPERSAND('&'), ; private final char codePoint; private final char codePointLower; private final String aliases; private CDC1604DashP6(char codePoint) { this(codePoint, null); } private CDC1604DashP6(char codePoint, String aliases) { this.codePoint = codePoint; this.codePointLower = Character.toLowerCase(codePoint); this.aliases = aliases; } public byte cdcByte() { return (byte) ordinal(); } public byte asciiByte() { return (byte) codePoint; } public char asciiChar() { return codePoint; } static public List convertFromUnicode(String text) { return convertFromUnicode(text, false); } static public List convertFromUnicode(String text, boolean strict) { String textSingleNewLines = text.replaceAll("\r\n", "\n"); PrimitiveIterator.OfInt i = textSingleNewLines.codePoints().iterator(); List result = new ArrayList<>(text.length()); CDC1604DashP6[] cdcChars = values(); CDC1604DashP6 cdcNumberTerminator = null; while (i.hasNext()) { int codePoint = i.next(); boolean found = false; if ('\r' == codePoint) { result.add(CDC1604DashP6._WORD_LINE); continue; } for (CDC1604DashP6 v : cdcChars) { if (v.codePoint == codePoint) { result.add(v); found = true; cdcNumberTerminator = null; break; } if ('0' == codePoint) { if (!CDC1604DashP6._A.equals(cdcNumberTerminator)) { result.add(CDC1604DashP6._WORD_NUMBER); result.add(CDC1604DashP6._A); cdcNumberTerminator = CDC1604DashP6._A; } result.add(CDC1604DashP6._A); found = true; break; } if (codePoint >= '1' && codePoint <= '9') { if (!CDC1604DashP6._I.equals(cdcNumberTerminator)) { result.add(CDC1604DashP6._WORD_NUMBER); result.add(CDC1604DashP6._I); cdcNumberTerminator = CDC1604DashP6._I; } int cdcNumberOff = codePoint - '1'; // 0 = 1 int cdcNumber = CDC1604DashP6._A.ordinal() + cdcNumberOff; result.add(CDC1604DashP6.values()[cdcNumber]); found = true; break; } } if (!found && !strict) { String codePointStr = Character.toString(codePoint); for (CDC1604DashP6 v : cdcChars) { if (v.codePointLower == codePoint) { result.add(v); found = true; cdcNumberTerminator = null; break; } if (v.aliases == null) { continue; } if (v.aliases.contains(codePointStr)) { result.add(v); found = true; cdcNumberTerminator = null; break; } } } if (!found) { throw new IllegalArgumentException("Unsupported char: '" + ((char)codePoint) + "' 0x" + Integer.toHexString(codePoint)); } } return result; } static public String convertToUnicode(List cdcChars) { StringBuilder buf = new StringBuilder(); Iterator cdc = cdcChars.iterator(); CDC1604DashP6 numberMode = null; while (cdc.hasNext()) { CDC1604DashP6 cdcPoint = cdc.next(); if (numberMode != null && (cdcPoint.ordinal() > numberMode.ordinal())) { numberMode = null; // out of range } if (numberMode != null && (cdcPoint.ordinal() < CDC1604DashP6._A.ordinal())) { numberMode = null; // below index 1 is end number mode } if (_WORD_GLUE.equals(cdcPoint)) { continue; } if (_WORD_NUMBER.equals(cdcPoint)) { if (!cdc.hasNext()) { break; } numberMode = cdc.next(); continue; } if (numberMode == null) { buf.appendCodePoint(cdcPoint.asciiByte()); } else { int terminatorNum = numberMode.ordinal() - CDC1604DashP6._A.ordinal() + 1; int valueNumber = cdcPoint.ordinal() - CDC1604DashP6._A.ordinal(); appendTerminatorNumber(buf, terminatorNum, valueNumber); } } return buf.toString(); } static private void appendTerminatorNumber(StringBuilder buf, int terminator, int value) { switch (terminator) { case 1: buf.appendCodePoint('0'); // T001 is zero for all 27 gematria number systems. return; case 2: if (value == 0) { buf.append("true"); // FIXME: T002ᖟGunPunchedHoles would be better, as it supports two-way conversion } else { buf.append("false"); } return; //case 3: // return; // TODO: after nether DB, generate add all terminator up to 27 from "number system" gun bullets. case 9: buf.appendCodePoint(('1' + value)); // 0 = 1 return; // NOTE: Latin decimals are not decimals as zero is not a part of the pie. default: throw new IllegalArgumentException("Unsupported terminator index: " + terminator); } } }