diff --git a/nx01-x4o-fc18/src/main/java/org/x4o/fc18/FourCornerUnicodeDisplay.java b/nx01-x4o-fc18/src/main/java/org/x4o/fc18/FourCornerUnicodeDisplay.java index d6c23bd..121e3fd 100644 --- a/nx01-x4o-fc18/src/main/java/org/x4o/fc18/FourCornerUnicodeDisplay.java +++ b/nx01-x4o-fc18/src/main/java/org/x4o/fc18/FourCornerUnicodeDisplay.java @@ -268,7 +268,9 @@ public class FourCornerUnicodeDisplay { if (failPipeSmoke) { throw new IllegalStateException(errBuf.toString()); } else { + output.append("["); output.append(errBuf); + output.append("]"); } } } diff --git a/nx01-x4o-fc18/src/main/java/org/x4o/fc18/FourCornerUnicodeMapper.java b/nx01-x4o-fc18/src/main/java/org/x4o/fc18/FourCornerUnicodeMapper.java index b5a73ee..bfae3e2 100644 --- a/nx01-x4o-fc18/src/main/java/org/x4o/fc18/FourCornerUnicodeMapper.java +++ b/nx01-x4o-fc18/src/main/java/org/x4o/fc18/FourCornerUnicodeMapper.java @@ -168,6 +168,45 @@ public enum FourCornerUnicodeMapper { return result; } + // todo move... + public List embedNCR1632Denominator(BigInteger value) { + return embedNCR1632Value(value, FourCornerDotCake.FC_NCR1632_XD.getStart()); + } + + // todo move... + public List embedNCR1632Numerator(BigInteger value) { + return embedNCR1632Value(value, FourCornerDotCake.FC_NCR1632_XN.getStart()); + } + + // todo move... + private List embedNCR1632Value(BigInteger value, int bankStart) { + if (value.equals(BigInteger.ZERO)) { + throw new IllegalArgumentException("The value ZERO is not allowed."); + } + List result = new ArrayList<>(); + BigInteger valueZero = value.subtract(BigInteger.ONE); + if (valueZero.equals(BigInteger.ZERO)) { + result.add(bankStart); + return result; + } + BigInteger pageSize = BigInteger.valueOf(0x1FF); + BigInteger reminder = valueZero; + + for (int i = 63; i >= 0; i--) { + int bankValue = valueZero.shiftRight(i * 9).and(pageSize).intValue(); + if (bankValue == 0) { + continue; + } + int cakePoint = bankStart + bankValue + (i * 512); + result.add(cakePoint); + reminder = reminder.subtract(BigInteger.valueOf(bankValue).shiftLeft(i * 9)); + } + if (!reminder.equals(BigInteger.ZERO)) { + throw new IllegalArgumentException("value is larger than 576 bit allowed: " + reminder + " of " + value); + } + return result; + } + public List toScriptSuper(int value) { return toScript(Integer.toString(value), 0); } diff --git a/nx01-x4o-fc18/src/main/java/org/x4o/fc18/zion7/FourCornerZionStenoGrapher.java b/nx01-x4o-fc18/src/main/java/org/x4o/fc18/zion7/FourCornerZionStenoGrapher.java index 2159f46..908b145 100644 --- a/nx01-x4o-fc18/src/main/java/org/x4o/fc18/zion7/FourCornerZionStenoGrapher.java +++ b/nx01-x4o-fc18/src/main/java/org/x4o/fc18/zion7/FourCornerZionStenoGrapher.java @@ -26,6 +26,7 @@ import java.math.BigInteger; import java.util.List; import java.util.Objects; +import org.x4o.fc18.FourCornerUnicodeMapper; import org.x4o.fc18.cake2.zero33.dec1.FCDotDEC2701DashPX0; import org.x4o.fc18.octal8.PrimordialOctal; @@ -63,6 +64,8 @@ public class FourCornerZionStenoGrapher { @Override public void strobeNCR1632(BigInteger denominator, BigInteger numerator) { + out.addAll(FourCornerUnicodeMapper.DICTIONARY.embedNCR1632Denominator(denominator)); + out.addAll(FourCornerUnicodeMapper.DICTIONARY.embedNCR1632Numerator(numerator)); } @Override diff --git a/nx01-x4o-fc18/src/main/java/org/x4o/fc18/zion7/FourCornerZionStenoLexer.java b/nx01-x4o-fc18/src/main/java/org/x4o/fc18/zion7/FourCornerZionStenoLexer.java index 79ba898..e0708a5 100644 --- a/nx01-x4o-fc18/src/main/java/org/x4o/fc18/zion7/FourCornerZionStenoLexer.java +++ b/nx01-x4o-fc18/src/main/java/org/x4o/fc18/zion7/FourCornerZionStenoLexer.java @@ -59,7 +59,7 @@ public class FourCornerZionStenoLexer { private final FourCornerZion7WaterCodex handlerCodex; private final FourCornerZion7SalahSequence handlerSalahSequence; private final FourCornerZion7TempleScrolls handlerTempleScrolls; - private final int denominatorBank[] = new int[64]; // <== is the terminator select per 9 bit group + private final int denominatorBank[] = new int[64]; // <== is the terminator select per 9 bit group of 9 bit values private final int numeratorBank[] = new int[denominatorBank.length]; private List input; private int inputIndex = 0; @@ -175,22 +175,15 @@ public class FourCornerZionStenoLexer { decModeReset(); ncrBankResetSilent(); handlerDocument.strobeDocumentAlpha(); - while (true) { - ScanResult run = ScanResult.DONE; - while (run.isDone()) { - run = readTokens(); // FIXME: remove triple looper to ones here - if (run.isEOF()) { - break; - } - break; - } + do { + ScanResult run = readTokens(); if (run.isEOF()) { break; } if (!run.isDone()) { smokeSignals.burnLexerReservedCakePoint(currLine, currCol, input.get(inputIndex)); } - } + } while (safeNext()); handlerDocument.strobeDocumentOmega(); } @@ -207,9 +200,6 @@ public class FourCornerZionStenoLexer { return result; } } - if (!safeNext()) { - return ScanResult.EOF; - } return result; } @@ -288,6 +278,7 @@ public class FourCornerZionStenoLexer { while (true) { int cakePoint = lexer.input.get(lexer.inputIndex); if (cakePoint < blockStart || cakePoint > blockStop) { + lexer.inputIndex--; // go back one, this is other steno segment break; } idxLast = lexer.inputIndex; @@ -426,6 +417,8 @@ public class FourCornerZionStenoLexer { static class StenoScannerNCR18 extends StenoScanner { + static private final int CAKEPOINT_BANK0_END = FourCornerDotCake.FC_NCR1632_XN.getStart() + 512; + public StenoScannerNCR18() { super(FourCornerDotCake.FC_NCR1632_XD.getStart(), FourCornerDotCake.FC_NCR1632_XN.getStop()); } @@ -457,7 +450,7 @@ public class FourCornerZionStenoLexer { } else { requestBankReset = false; } - if (cakePoint > FourCornerDotCake.FC_NCR1632_XN.getStart() + 512) { + if (cakePoint > CAKEPOINT_BANK0_END) { magicSparkler = true; continue; // Only fire fraction on lowest value select } diff --git a/nx01-x4o-fc18/src/test/java/org/x4o/fc18/zion7/LexerInvalidTest.java b/nx01-x4o-fc18/src/test/java/org/x4o/fc18/zion7/LexerInvalidTest.java new file mode 100644 index 0000000..ff6b7a7 --- /dev/null +++ b/nx01-x4o-fc18/src/test/java/org/x4o/fc18/zion7/LexerInvalidTest.java @@ -0,0 +1,84 @@ +/* + * 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.fc18.zion7; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.x4o.fc18.FourCornerUnicodeDisplay; +import org.x4o.fc18.cake2.zero33.FCDotCDC1604DashP6; + +/** + * Tests four corner lexer invalid chars. + * + * @author Willem Cazander + * @version 1.0 Aug 4, 2025 + */ +public class LexerInvalidTest { + + @Test + public void testInvalid18Plus() throws Exception { + String res = "[0:0:burnLexerReservedCakePoint:0x40000]"; + Assertions.assertEquals(res, FourCornerUnicodeDisplay.text().renderFromInt18(List.of(0x040000))); + } + + @Test + public void testInvalid18PlusError() throws Exception { + Assertions.assertThrows(IllegalStateException.class, () -> { + new FourCornerUnicodeDisplay(true, true, null).renderFromInt18(List.of(0x040000)); + }); + } + + @Test + public void testInvalidFirstLast() throws Exception { + List cdc = new ArrayList<>(); + cdc.add(0x0400FF); + cdc.add(FCDotCDC1604DashP6.NX23_W.ordinal()); + cdc.add(0x0400FE); + cdc.add(FCDotCDC1604DashP6.NX23_W.ordinal()); + cdc.add(0x0400FD); + cdc.add(FCDotCDC1604DashP6.NX23_W.ordinal()); + cdc.add(0x0400FC); + String res = FourCornerUnicodeDisplay.text().renderFromInt18(cdc); + Assertions.assertTrue(res.contains("400ff"), "No 400ff in: " + res); + Assertions.assertTrue(res.contains("400fe"), "No 400fe in: " + res); + Assertions.assertTrue(res.contains("400fd"), "No 400fd in: " + res); + Assertions.assertTrue(res.contains("400fc"), "No 400fc in: " + res); + } + + @Test + public void testInvalidGap8() throws Exception { + List cdc = new ArrayList<>(); + cdc.add(0xFF); + cdc.add(FCDotCDC1604DashP6.NX01_A.ordinal()); + cdc.add(0xFE); + cdc.add(FCDotCDC1604DashP6.NY01_AT.ordinal()); + cdc.add(0xFD); + String res = FourCornerUnicodeDisplay.text().renderFromInt18(cdc); + Assertions.assertTrue(res.contains("0xff"), "No 0xff in: " + res); + Assertions.assertTrue(res.contains("0xfe"), "No 0xfe in: " + res); + Assertions.assertTrue(res.contains("0xfd"), "No 0xfd in: " + res); + } +} diff --git a/nx01-x4o-fc18/src/test/java/org/x4o/fc18/zion7/LexerNCRTest.java b/nx01-x4o-fc18/src/test/java/org/x4o/fc18/zion7/LexerNCRTest.java index 6795b34..61b7e2e 100644 --- a/nx01-x4o-fc18/src/test/java/org/x4o/fc18/zion7/LexerNCRTest.java +++ b/nx01-x4o-fc18/src/test/java/org/x4o/fc18/zion7/LexerNCRTest.java @@ -22,12 +22,14 @@ */ package org.x4o.fc18.zion7; +import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.x4o.fc18.FourCornerUnicodeDisplay; +import org.x4o.fc18.FourCornerUnicodeMapper; import org.x4o.fc18.cake2.FourCornerDotCake; import org.x4o.fc18.cake2.FourCornerX06BaklavaPointSequence; import org.x4o.fc18.cake2.zero33.FCDotCDC1604DashP6; @@ -121,10 +123,31 @@ public class LexerNCRTest { @Test public void testNCRLargestF576() throws Exception { List cdc = new ArrayList<>(); - cdc.add(FourCornerDotCake.FC_NCR1632_XD.getStart() + (512*63) + 1); - cdc.add(FourCornerDotCake.FC_NCR1632_XN.getStart() - 1 + 123); // NXX_123 - - String res = "¹²³/₄₈₃₀₆₇₁₉₀₃₇₇₁₅₇₂₉₃₀₈₆₉₁₈₉₈₆₃₆₆₄₉₈₄₁₈₀₃₇₃₆₅₉₁₆₂₁₃₃₀₄₃₇₄₈₃₂₁₅₄₄₀₆₄₃₁₄₃₉₈₉₂₇₈₆₁₉₅₀₅₃₀₆₇₀₂₄₂₂₀₈₂₂₇₄₀₃₂₂₂₄₅₃₀₇₉₅₂₀₀₃₉₃₇₇₇₂₁₄₇₁₇₀₆₃₄₈₃₂₆₃₀₃₇₃₄₅₆₉₆₇₈₆₃₅₈₄₁₈₃₃₈₅₀₉₃₅₈₇₁₂₂₆₀₁₈₅₂₉₂₉"; - Assertions.assertEquals(res, FourCornerUnicodeDisplay.text().renderFromInt18(cdc)); + for (int i = FourCornerDotCake.FC_NCR1632_XD.getStop(); i >= FourCornerDotCake.FC_NCR1632_XD.getStart(); i = i - 512) { + cdc.add(i); + } + for (int i = FourCornerDotCake.FC_NCR1632_XN.getStop(); i >= FourCornerDotCake.FC_NCR1632_XN.getStart(); i = i - 512) { + cdc.add(i); + } + String resSuper = "²⁴⁷³³⁰⁴⁰¹⁴⁷³¹⁰⁴⁵³⁴⁰⁶⁰⁵⁰²⁵²¹⁰¹⁹⁶⁴⁷¹⁹⁰⁰³⁵¹³¹³⁴⁹¹⁰¹²¹¹⁸³⁹⁹¹⁴⁰⁶³⁰⁵⁶⁰⁹²⁸⁹⁷²²⁵¹⁰⁶⁵³¹⁸⁶⁷¹⁷⁰³¹⁶⁴⁰¹⁰⁶¹²⁴³⁰⁴⁴⁹⁸⁹⁵⁹⁷⁶⁷¹⁴²⁶⁰¹⁶¹³⁹³³⁹³⁵¹³⁶⁵⁰³⁴³⁰⁶⁷⁵¹²⁰⁹⁹⁶⁷⁵⁴⁶¹⁵⁵¹⁰¹⁸⁹³¹⁶⁷⁹¹⁶⁶⁰⁶⁷⁷²¹⁴⁸⁶⁹⁹¹³⁶"; + String resSuber = "₂₄₇₃₃₀₄₀₁₄₇₃₁₀₄₅₃₄₀₆₀₅₀₂₅₂₁₀₁₉₆₄₇₁₉₀₀₃₅₁₃₁₃₄₉₁₀₁₂₁₁₈₃₉₉₁₄₀₆₃₀₅₆₀₉₂₈₉₇₂₂₅₁₀₆₅₃₁₈₆₇₁₇₀₃₁₆₄₀₁₀₆₁₂₄₃₀₄₄₉₈₉₅₉₇₆₇₁₄₂₆₀₁₆₁₃₉₃₃₉₃₅₁₃₆₅₀₃₄₃₀₆₇₅₁₂₀₉₉₆₇₅₄₆₁₅₅₁₀₁₈₉₃₁₆₇₉₁₆₆₀₆₇₇₂₁₄₈₆₉₉₁₃₆"; + Assertions.assertEquals(resSuper + "/" + resSuber, FourCornerUnicodeDisplay.text().renderFromInt18(cdc)); + } + + @Test + public void testNCRCount1024() throws Exception { + List cdc = new ArrayList<>(); + for (int x = 1; x <= 1024; x++) { + BigInteger v = BigInteger.valueOf(x); + cdc.addAll(FourCornerUnicodeMapper.DICTIONARY.embedNCR1632Denominator(v)); + + //cdc.add(FourCornerDotCake.FC_NCR1632_XN.getStart()); // NXX_1 + List nomList = FourCornerUnicodeMapper.DICTIONARY.embedNCR1632Numerator(BigInteger.ONE); + Assertions.assertEquals(1, nomList.size()); + cdc.addAll(nomList); // NXX_1 + } + String res = FourCornerUnicodeDisplay.text().renderFromInt18(cdc); + Assertions.assertTrue(res.startsWith("¹/₁¹/₂"), "missing " + res); + Assertions.assertTrue(res.endsWith("¹/₁₀₂₃¹/₁₀₂₄"), "missing " + res); } }