From 266c5912c0b35e86cab22e9e7dedc5e4d8d2b7ad Mon Sep 17 00:00:00 2001 From: hneemann Date: Tue, 18 Dec 2018 11:12:24 +0100 Subject: [PATCH] refactoring of DataField.java --- .../digital/core/memory/DataField.java | 79 ++++++++----------- .../core/memory/DataFieldConverter.java | 16 ++-- .../core/memory/DataFieldImporter.java | 5 +- .../neemann/digital/core/memory/EEPROM.java | 7 +- .../digital/core/memory/EEPROMDualPort.java | 7 +- .../digital/core/memory/rom/ROMManger.java | 4 +- .../neemann/digital/draw/shapes/RAMShape.java | 4 +- .../digital/gui/components/DataEditor.java | 14 ++-- .../digital/gui/components/EditorFactory.java | 6 +- .../digital/gui/components/ProbeDialog.java | 1 - .../gui/components/ROMEditorDialog.java | 2 +- .../core/memory/DataFieldConverterTest.java | 24 +++--- .../digital/core/memory/DataFieldTest.java | 25 +++--- 13 files changed, 86 insertions(+), 108 deletions(-) diff --git a/src/main/java/de/neemann/digital/core/memory/DataField.java b/src/main/java/de/neemann/digital/core/memory/DataField.java index ae8528073..a928803b7 100644 --- a/src/main/java/de/neemann/digital/core/memory/DataField.java +++ b/src/main/java/de/neemann/digital/core/memory/DataField.java @@ -23,7 +23,6 @@ public class DataField implements HGSArray { */ public static final DataField DEFAULT = new DataField(0); - private final int size; private long[] data; private final transient ArrayList listeners = new ArrayList<>(); @@ -34,31 +33,27 @@ public class DataField implements HGSArray { * @param size size */ public DataField(int size) { - this(new long[size], size); + this(new long[size]); + } + + /** + * Creates a new data field + * + * @param data the data to copy + */ + public DataField(DataField data) { + this.data = Arrays.copyOf(data.data, data.data.length); } /** * Creates a new data field * * @param data the data - * @param size the size */ - public DataField(long[] data, int size) { - this.size = size; + public DataField(long[] data) { this.data = data; } - /** - * Create a new instance based on a given instance. - * The data given is copied. - * - * @param dataField the data to use - * @param newSize new size - */ - public DataField(DataField dataField, int newSize) { - this(Arrays.copyOf(dataField.data, newSize), newSize); - } - /** * Creates a new instance and fills it with the data in the given reader * @@ -86,16 +81,14 @@ public class DataField implements HGSArray { if (line.length() > 0) { long v = Bits.decode(line, 0, 16); - if (pos == data.length) - data = Arrays.copyOf(data, data.length * 2); - data[pos] = v; + setData(pos, v); pos++; } } catch (Bits.NumberFormatException e) { throw new IOException(e); } } - size = pos; + data = Arrays.copyOf(data, pos); } } @@ -106,11 +99,11 @@ public class DataField implements HGSArray { * @throws IOException IOException */ public void saveTo(File file) throws IOException { - DataField df = getMinimized(); + trim(); try (BufferedWriter w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) { w.write("v2.0 raw"); w.newLine(); - for (long l : df.getData()) { + for (long l : data) { w.write(Long.toHexString(l)); w.newLine(); } @@ -130,21 +123,23 @@ public class DataField implements HGSArray { } /** - * Sets a data value the DataField + * Sets a data value the DataField. + * If the actual data field capacity is to small the size in increased. * * @param addr the address * @param value the value * @return this for chained calls */ public DataField setData(int addr, long value) { - if (addr < size) { - if (addr >= data.length) - data = Arrays.copyOf(data, size); + if (addr >= data.length) { + int newLen = addr * 2; + if (newLen < 32) newLen = 32; + data = Arrays.copyOf(data, newLen); + } - if (data[addr] != value) { - data[addr] = value; - fireChanged(addr); - } + if (data[addr] != value) { + data[addr] = value; + fireChanged(addr); } return this; } @@ -163,27 +158,17 @@ public class DataField implements HGSArray { } /** - * Returns the size of this field - * - * @return the size - */ - public int size() { - return size; - } - - /** - * Returns a new minimal {@link DataField}. + * Trims the data field to it's minimal size * All trailing zeros are removed. * - * @return the new {@link DataField} + * @return the new length of the data array */ - public DataField getMinimized() { + public int trim() { int pos = data.length; while (pos > 0 && data[pos - 1] == 0) pos--; - if (pos == data.length) - return this; - else - return new DataField(Arrays.copyOf(data, pos), size); + if (pos < data.length) + data = Arrays.copyOf(data, pos); + return data.length; } /** @@ -226,7 +211,7 @@ public class DataField implements HGSArray { * @param dataField the data to set to this data field */ public void setDataFrom(DataField dataField) { - data = Arrays.copyOf(dataField.data, size); + data = Arrays.copyOf(dataField.data, dataField.data.length); fireChanged(-1); } diff --git a/src/main/java/de/neemann/digital/core/memory/DataFieldConverter.java b/src/main/java/de/neemann/digital/core/memory/DataFieldConverter.java index 8e6b99860..356afc2c9 100644 --- a/src/main/java/de/neemann/digital/core/memory/DataFieldConverter.java +++ b/src/main/java/de/neemann/digital/core/memory/DataFieldConverter.java @@ -12,7 +12,6 @@ import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import de.neemann.digital.core.Bits; -import java.util.Arrays; import java.util.StringTokenizer; /** @@ -28,9 +27,7 @@ public class DataFieldConverter implements Converter { @Override public void marshal(Object o, HierarchicalStreamWriter writer, MarshallingContext marshallingContext) { DataField df = (DataField) o; - df = df.getMinimized(); - //writer.startNode("data"); - writer.addAttribute("size", Integer.toString(df.size())); + df.trim(); StringBuilder data = new StringBuilder(); int pos = 0; for (long d : df.getData()) { @@ -49,12 +46,11 @@ public class DataFieldConverter implements Converter { pos += s.length(); } writer.setValue(data.toString()); - //writer.endNode(); } @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext unmarshallingContext) { - if (reader.getAttribute("size") == null) { + if (reader.hasMoreChildren()) { // old type reader.moveDown(); DataField df = new DataField(Integer.parseInt(reader.getValue())); @@ -70,15 +66,15 @@ public class DataFieldConverter implements Converter { } else { try { // new type - int size = Integer.parseInt(reader.getAttribute("size")); - long[] data = new long[size]; + DataField df = new DataField(1024); StringTokenizer st = new StringTokenizer(reader.getValue(), ","); int i = 0; while (st.hasMoreTokens()) { - data[i] = Bits.decode(st.nextToken().trim(), 0, 16); + df.setData(i, Bits.decode(st.nextToken().trim(), 0, 16)); i++; } - return new DataField(Arrays.copyOf(data, i), size); + df.trim(); + return df; } catch (Bits.NumberFormatException e) { throw new RuntimeException(e); } diff --git a/src/main/java/de/neemann/digital/core/memory/DataFieldImporter.java b/src/main/java/de/neemann/digital/core/memory/DataFieldImporter.java index dedcf0b89..24b7dfc5b 100644 --- a/src/main/java/de/neemann/digital/core/memory/DataFieldImporter.java +++ b/src/main/java/de/neemann/digital/core/memory/DataFieldImporter.java @@ -44,9 +44,10 @@ public final class DataFieldImporter { } private static DataField readByteArray(File file, int dataBits, Reader reader) throws IOException { - DataField dataField = new DataField(0x10000); + DataField dataField = new DataField(1024); reader.read(file, create(dataField, dataBits)); - return dataField.getMinimized(); + dataField.trim(); + return dataField; } interface DataArray { diff --git a/src/main/java/de/neemann/digital/core/memory/EEPROM.java b/src/main/java/de/neemann/digital/core/memory/EEPROM.java index da9cf5b48..4e14d2a57 100644 --- a/src/main/java/de/neemann/digital/core/memory/EEPROM.java +++ b/src/main/java/de/neemann/digital/core/memory/EEPROM.java @@ -44,11 +44,6 @@ public class EEPROM extends RAMSinglePortSel implements ROMInterface { @Override protected DataField createDataField(ElementAttributes attr, int size) { - DataField memory = attr.get(Keys.DATA); - if (memory.size() != size) { - memory = new DataField(memory, size); - attr.set(Keys.DATA, memory); - } - return memory; + return attr.get(Keys.DATA); } } diff --git a/src/main/java/de/neemann/digital/core/memory/EEPROMDualPort.java b/src/main/java/de/neemann/digital/core/memory/EEPROMDualPort.java index 02ac56d76..d1f11e4dc 100644 --- a/src/main/java/de/neemann/digital/core/memory/EEPROMDualPort.java +++ b/src/main/java/de/neemann/digital/core/memory/EEPROMDualPort.java @@ -44,12 +44,7 @@ public class EEPROMDualPort extends RAMDualPort implements ROMInterface { @Override protected DataField createDataField(ElementAttributes attr, int size) { - DataField memory = attr.get(Keys.DATA); - if (memory.size() != size) { - memory = new DataField(memory, size); - attr.set(Keys.DATA, memory); - } - return memory; + return attr.get(Keys.DATA); } } diff --git a/src/main/java/de/neemann/digital/core/memory/rom/ROMManger.java b/src/main/java/de/neemann/digital/core/memory/rom/ROMManger.java index 16a6372fd..875826f2b 100644 --- a/src/main/java/de/neemann/digital/core/memory/rom/ROMManger.java +++ b/src/main/java/de/neemann/digital/core/memory/rom/ROMManger.java @@ -54,13 +54,13 @@ public class ROMManger { } /** - * Adds a rom's contet to this ROMManager + * Adds a rom's content to this ROMManager * * @param label the label * @param data the data */ public void addRom(String label, DataField data) { - data = data.getMinimized(); + data.trim(); if (data.getData().length > 0) roms.put(label, data); } diff --git a/src/main/java/de/neemann/digital/draw/shapes/RAMShape.java b/src/main/java/de/neemann/digital/draw/shapes/RAMShape.java index 3562a2fdb..fbb35c972 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/RAMShape.java +++ b/src/main/java/de/neemann/digital/draw/shapes/RAMShape.java @@ -26,7 +26,6 @@ import java.awt.*; */ public class RAMShape extends GenericShape { private final int dataBits; - private final int size; private final int addrBits; private final String dialogTitle; private Model model; @@ -63,7 +62,6 @@ public class RAMShape extends GenericShape { dialogTitle = description.getShortName(); dataBits = attr.get(Keys.BITS); addrBits = attr.get(Keys.ADDR_BITS); - size = 1 << addrBits; setInverterConfig(attr.get(Keys.INVERTER_CONFIG)); } @@ -74,7 +72,7 @@ public class RAMShape extends GenericShape { public boolean clicked(CircuitComponent cc, Point pos, IOState ioState, Element element, SyncAccess modelSync) { if (element instanceof RAMInterface) { DataField dataField = ((RAMInterface) element).getMemory(); - DataEditor dataEditor = new DataEditor(cc, dataField, size, dataBits, addrBits, true, modelSync); + DataEditor dataEditor = new DataEditor(cc, dataField, dataBits, addrBits, true, modelSync); dataEditor.showDialog(dialogTitle, model); } return false; diff --git a/src/main/java/de/neemann/digital/gui/components/DataEditor.java b/src/main/java/de/neemann/digital/gui/components/DataEditor.java index 4cf64e951..69c7faef2 100644 --- a/src/main/java/de/neemann/digital/gui/components/DataEditor.java +++ b/src/main/java/de/neemann/digital/gui/components/DataEditor.java @@ -48,25 +48,26 @@ public class DataEditor extends JDialog { * * @param parent the parent * @param dataField the data to edit - * @param size the size of the data field to edit * @param dataBits the bit count of the values to edit * @param addrBits the bit count of the adresses * @param modelIsRunning true if model is running * @param modelSync used to access the running model */ - public DataEditor(Component parent, DataField dataField, int size, int dataBits, int addrBits, boolean modelIsRunning, SyncAccess modelSync) { + public DataEditor(Component parent, DataField dataField, int dataBits, int addrBits, boolean modelIsRunning, SyncAccess modelSync) { super(SwingUtilities.windowForComponent(parent), Lang.get("key_Data"), modelIsRunning ? ModalityType.MODELESS : ModalityType.APPLICATION_MODAL); setDefaultCloseOperation(DISPOSE_ON_CLOSE); if (modelIsRunning) localDataField = dataField; else - localDataField = new DataField(dataField, size); + localDataField = new DataField(dataField); + final int size = 1 << addrBits; final int cols = calcCols(size, dataBits); + final int rows = (size - 1) / cols + 1; int tableWidth = 0; - MyTableModel dm = new MyTableModel(this.localDataField, cols, modelSync); + MyTableModel dm = new MyTableModel(this.localDataField, cols, rows, modelSync); table = new JTable(dm); int widthOfZero = table.getFontMetrics(table.getFont()).stringWidth("00000000") / 8; table.setDefaultRenderer(MyLong.class, new MyLongRenderer(dataBits)); @@ -184,6 +185,7 @@ public class DataEditor extends JDialog { * @return the data field */ public DataField getModifiedDataField() { + localDataField.trim(); return localDataField; } @@ -247,11 +249,11 @@ public class DataEditor extends JDialog { private final int rows; private ArrayList listener = new ArrayList<>(); - private MyTableModel(DataField dataField, int cols, SyncAccess modelSync) { + private MyTableModel(DataField dataField, int cols, int rows, SyncAccess modelSync) { this.dataField = dataField; this.cols = cols; + this.rows = rows; this.modelSync = modelSync; - rows = (dataField.size() - 1) / cols + 1; } @Override diff --git a/src/main/java/de/neemann/digital/gui/components/EditorFactory.java b/src/main/java/de/neemann/digital/gui/components/EditorFactory.java index fd279d6b9..6d71baccb 100644 --- a/src/main/java/de/neemann/digital/gui/components/EditorFactory.java +++ b/src/main/java/de/neemann/digital/gui/components/EditorFactory.java @@ -612,8 +612,7 @@ public final class EditorFactory { // memory, RAM/ROM addrBits = attr.get(Keys.ADDR_BITS); } - int size = 1 << addrBits; - DataEditor de = new DataEditor(panel, data, size, dataBits, addrBits, false, SyncAccess.NOSYNC); + DataEditor de = new DataEditor(panel, data, dataBits, addrBits, false, SyncAccess.NOSYNC); de.setFileName(attr.getFile(ROM.LAST_DATA_FILE_KEY)); if (de.showDialog()) { data = de.getModifiedDataField(); @@ -647,7 +646,8 @@ public final class EditorFactory { @Override public DataField getValue() { - return data.getMinimized(); + data.trim(); + return data; } @Override diff --git a/src/main/java/de/neemann/digital/gui/components/ProbeDialog.java b/src/main/java/de/neemann/digital/gui/components/ProbeDialog.java index da3edc315..1dbec84ba 100644 --- a/src/main/java/de/neemann/digital/gui/components/ProbeDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/ProbeDialog.java @@ -85,7 +85,6 @@ public class ProbeDialog extends JDialog implements ModelStateObserverTyped { public void actionPerformed(ActionEvent actionEvent) { new DataEditor(ProbeDialog.this, ram.getMemory(), - ram.getSize(), ram.getDataBits(), ram.getAddrBits(), true, diff --git a/src/main/java/de/neemann/digital/gui/components/ROMEditorDialog.java b/src/main/java/de/neemann/digital/gui/components/ROMEditorDialog.java index 49a09f686..34fb862c5 100644 --- a/src/main/java/de/neemann/digital/gui/components/ROMEditorDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/ROMEditorDialog.java @@ -138,7 +138,7 @@ public class ROMEditorDialog extends JDialog { } public boolean edit(ROMEditorDialog romEditorDialog) { - DataEditor de = new DataEditor(romEditorDialog, data, 1 << ri.getAddrBits(), ri.getDataBits(), ri.getAddrBits(), false, SyncAccess.NOSYNC); + DataEditor de = new DataEditor(romEditorDialog, data, ri.getDataBits(), ri.getAddrBits(), false, SyncAccess.NOSYNC); if (de.showDialog()) { data = de.getModifiedDataField(); return true; diff --git a/src/test/java/de/neemann/digital/core/memory/DataFieldConverterTest.java b/src/test/java/de/neemann/digital/core/memory/DataFieldConverterTest.java index f4fb73e00..218459b2d 100644 --- a/src/test/java/de/neemann/digital/core/memory/DataFieldConverterTest.java +++ b/src/test/java/de/neemann/digital/core/memory/DataFieldConverterTest.java @@ -28,7 +28,7 @@ public class DataFieldConverterTest extends TestCase { XStream xStream = getxStream(); String xml = xStream.toXML(d); - assertEquals("0,1,2,3,4,5,6,7,8,9", xml); + assertEquals("0,1,2,3,4,5,6,7,8,9", xml); } public void testUnmarshal() throws Exception { @@ -36,7 +36,7 @@ public class DataFieldConverterTest extends TestCase { DataField df = (DataField) xStream.fromXML("0,1,2,3,4,5,6,7,8,9"); - assertEquals(1000, df.size()); + assertEquals(10, df.getData().length); for (int i = 0; i < 10; i++) assertEquals(i, df.getDataWord(i)); } @@ -64,8 +64,8 @@ public class DataFieldConverterTest extends TestCase { XStream xs = getxStream(); String xml = xs.toXML(t); assertEquals("\n" + - " 1,0,0,0,0,2\n" + - " 3,0,0,0,0,0,0,0,4\n" + + " 1,0,0,0,0,2\n" + + " 3,0,0,0,0,0,0,0,4\n" + "", xml); } @@ -73,14 +73,14 @@ public class DataFieldConverterTest extends TestCase { public void testUnarshalObj() throws Exception { XStream xs = getxStream(); Test t = (Test) xs.fromXML("\n" + - " 1,0,0,0,0,2\n" + - " 3,0,0,0,0,0,0,0,4\n" + + " 1,0,0,0,0,2\n" + + " 3,0,0,0,0,0,0,0,4\n" + ""); - assertEquals(20, t.d1.size()); + assertEquals(6, t.d1.getData().length); assertEquals(1, t.d1.getDataWord(0)); assertEquals(2, t.d1.getDataWord(5)); - assertEquals(20, t.d2.size()); + assertEquals(9, t.d2.getData().length); assertEquals(3, t.d2.getDataWord(0)); assertEquals(4, t.d2.getDataWord(8)); } @@ -94,7 +94,7 @@ public class DataFieldConverterTest extends TestCase { XStream xStream = getxStream(); String xml = xStream.toXML(d); - assertEquals("0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,10,11,12,13,14,15,16,17,18,19,1a,1b,1c,1d,1e,1f,20,\n" + + assertEquals("0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,10,11,12,13,14,15,16,17,18,19,1a,1b,1c,1d,1e,1f,20,\n" + "21,22,23,24,25,26,27,28,29,2a,2b,2c,2d,2e,2f,30,31,32,33,34,35,36,37,38,39,3a,3b,\n" + "3c,3d,3e,3f,40,41,42,43,44,45,46,47,48,49,4a,4b,4c,4d,4e,4f,50,51,52,53,54,55,56,\n" + "57,58,59,5a,5b,5c,5d,5e,5f,60,61,62,63", xml); @@ -103,12 +103,12 @@ public class DataFieldConverterTest extends TestCase { public void testUnmarshalMuch() throws Exception { XStream xStream = getxStream(); - DataField df = (DataField) xStream.fromXML("0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,10,11,12,13,14,15,16,17,18,19,1a,1b,1c,1d,1e,1f,20,\n" + + DataField df = (DataField) xStream.fromXML("0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,10,11,12,13,14,15,16,17,18,19,1a,1b,1c,1d,1e,1f,20,\n" + "21,22,23,24,25,26,27,28,29,2a,2b,2c,2d,2e,2f,30,31,32,33,34,35,36,37,38,39,3a,3b,\n" + "3c,3d,3e,3f,40,41,42,43,44,45,46,47,48,49,4a,4b,4c,4d,4e,4f,50,51,52,53,54,55,56,\n" + "57,58,59,5a,5b,5c,5d,5e,5f,60,61,62,63"); - assertEquals(1000, df.size()); + assertEquals(100, df.getData().length); for (int i = 0; i < 100; i++) assertEquals(i, df.getDataWord(i)); } @@ -130,7 +130,7 @@ public class DataFieldConverterTest extends TestCase { " 8\n" + " 9\n" + ""); - assertEquals(1000, df.size()); + assertEquals(1000, df.getData().length); for (int i = 0; i < 10; i++) assertEquals(i, df.getDataWord(i)); } diff --git a/src/test/java/de/neemann/digital/core/memory/DataFieldTest.java b/src/test/java/de/neemann/digital/core/memory/DataFieldTest.java index 0a0f93639..985ad7938 100644 --- a/src/test/java/de/neemann/digital/core/memory/DataFieldTest.java +++ b/src/test/java/de/neemann/digital/core/memory/DataFieldTest.java @@ -13,28 +13,35 @@ import java.io.StringReader; */ public class DataFieldTest extends TestCase { - public void testGetMinimized() throws Exception { + public void testGetMinimized() { DataField data = new DataField(100); data.setData(9, 1); - data = data.getMinimized(); + assertEquals(10, data.trim()); assertEquals(1, data.getDataWord(9)); - data = data.getMinimized(); + assertEquals(10, data.trim()); assertEquals(1, data.getDataWord(9)); } - public void testGrow() throws Exception { + public void testGrow() { DataField data = new DataField(100); data.setData(9, 1); - data = data.getMinimized(); + data.trim(); assertEquals(1, data.getDataWord(9)); data.setData(30, 1); assertEquals(1, data.getDataWord(30)); } + public void testGrow2() { + DataField data = new DataField(0); + data.setData(0, 1); + assertEquals(1, data.getDataWord(0)); + assertEquals(0, data.getDataWord(1)); + } + public void testLoad() throws Exception { String data = "v2.0 raw\n0\n10\nAA\nFF"; DataField df = new DataField(new StringReader(data)); - assertEquals(4, df.size()); + assertEquals(4, df.trim()); assertEquals(0x00, df.getDataWord(0)); assertEquals(0x10, df.getDataWord(1)); assertEquals(0xAA, df.getDataWord(2)); @@ -44,7 +51,7 @@ public class DataFieldTest extends TestCase { public void testLoad64Bit() throws Exception { String data = "v2.0 raw\n8000000000000000\n10\nAA\nFF"; DataField df = new DataField(new StringReader(data)); - assertEquals(4, df.size()); + assertEquals(4, df.trim()); assertEquals(0x8000000000000000L, df.getDataWord(0)); assertEquals(0x10, df.getDataWord(1)); assertEquals(0xAA, df.getDataWord(2)); @@ -54,7 +61,7 @@ public class DataFieldTest extends TestCase { public void testLoadComments() throws Exception { String data = "v2.0 raw\n#test1 \n 0 \n#test1\n # test2\n10 # test3\n\n\nAA\nFF #test"; DataField df = new DataField(new StringReader(data)); - assertEquals(4, df.size()); + assertEquals(4, df.trim()); assertEquals(0x00, df.getDataWord(0)); assertEquals(0x10, df.getDataWord(1)); assertEquals(0xAA, df.getDataWord(2)); @@ -64,7 +71,7 @@ public class DataFieldTest extends TestCase { public void testLoadCommentsRealHex() throws Exception { String data = "v2.0 raw\n#test1 \n 0x0 \n#test1\n # test2\n0x10 # test3\n\n\n0xAA\n0XFF #test"; DataField df = new DataField(new StringReader(data)); - assertEquals(4, df.size()); + assertEquals(4, df.trim()); assertEquals(0x00, df.getDataWord(0)); assertEquals(0x10, df.getDataWord(1)); assertEquals(0xAA, df.getDataWord(2));