fixes an issue in the logisim hex reader; closes #642

This commit is contained in:
hneemann 2021-02-09 18:32:57 +01:00
parent 8a8f1260fc
commit 7032942ad3
2 changed files with 41 additions and 32 deletions

View File

@ -9,7 +9,8 @@ import de.neemann.digital.core.Bits;
import de.neemann.digital.lang.Lang; import de.neemann.digital.lang.Lang;
import java.io.*; import java.io.*;
import java.util.StringTokenizer;
import static java.io.StreamTokenizer.*;
/** /**
* Reader to read the original Logisim hex file format * Reader to read the original Logisim hex file format
@ -38,42 +39,42 @@ public class LogisimReader implements ValueArrayReader {
@Override @Override
public void read(ValueArray valueArray) throws IOException { public void read(ValueArray valueArray) throws IOException {
try (BufferedReader br = new BufferedReader(reader)) { try (BufferedReader bufferedReader = new BufferedReader(reader)) {
String header = br.readLine(); String header = bufferedReader.readLine();
if (header == null || !header.equals("v2.0 raw")) if (header == null || !header.equals("v2.0 raw"))
throw new IOException(Lang.get("err_invalidFileFormat")); throw new IOException(Lang.get("err_invalidFileFormat"));
String line;
StreamTokenizer t = new StreamTokenizer(bufferedReader);
t.resetSyntax();
t.commentChar('#');
t.wordChars('a', 'f');
t.wordChars('A', 'F');
t.wordChars('x', 'x');
t.wordChars('X', 'X');
t.wordChars('0', '9');
t.whitespaceChars(0, ' ');
int pos = 0; int pos = 0;
while ((line = br.readLine()) != null) { while (t.nextToken() != TT_EOF) {
try { try {
int p = line.indexOf('#'); String vStr = t.sval;
if (p >= 0) if (vStr == null)
line = line.substring(0, p).trim(); throw new IOException("invalid token in line " + t.lineno());
else if (t.nextToken() == '*') {
line = line.trim(); t.nextToken();
if (t.sval == null)
StringTokenizer tc = new StringTokenizer(line, " \t"); throw new IOException("invalid token in line " + t.lineno());
while (tc.hasMoreTokens()) { long v = getHexLong(t.sval);
String num = tc.nextToken(); int reps = (int) Bits.decode(vStr, 0, 10);
int rle = 1; for (int i = 0; i < reps; i++) {
p = num.indexOf('*');
if (p > 0) {
rle = Integer.parseInt(num.substring(0, p));
num = num.substring(p + 1).trim();
}
if (num.length() > 2 && num.charAt(0) == '0' && (num.charAt(1) == 'x' || num.charAt(1) == 'X'))
num = num.substring(2);
if (num.length() > 0) {
long v = Bits.decode(num, 0, 16);
for (int i = 0; i < rle; i++) {
valueArray.set(pos, v); valueArray.set(pos, v);
pos++; pos++;
} }
} else {
t.pushBack();
valueArray.set(pos, getHexLong(vStr));
pos++;
} }
}
} catch (Bits.NumberFormatException e) { } catch (Bits.NumberFormatException e) {
throw new IOException(e); throw new IOException(e);
} }
@ -81,4 +82,12 @@ public class LogisimReader implements ValueArrayReader {
} }
} }
private long getHexLong(String vStr) throws Bits.NumberFormatException {
int p = 0;
if (vStr.length() > 2 && vStr.charAt(0) == '0' && (vStr.charAt(1) == 'x' || vStr.charAt(1) == 'X'))
p = 2;
return Bits.decode(vStr, p, 16);
}
} }

View File

@ -99,7 +99,7 @@ public class LogisimReaderTest extends TestCase {
} }
public void testLoadRLEMultiline() throws Exception { public void testLoadRLEMultiline() throws Exception {
String data = "v2.0 raw\n#test1 \n 5*0x0 10*0x10 0xAA 0XFF #test"; String data = "v2.0 raw\n#test1 \n 5*0x0 10 * 0x10 0xAA 0XFF #test";
DataField df = new DataField(1024); DataField df = new DataField(1024);
new LogisimReader(new StringReader(data)).read(new DataFieldValueArray(df, 0)); new LogisimReader(new StringReader(data)).read(new DataFieldValueArray(df, 0));