From 481417e5eea3fbde3b7fec3e46a7697da60438d9 Mon Sep 17 00:00:00 2001 From: Jason Long Date: Sat, 27 Jul 2013 17:48:38 -0400 Subject: [PATCH] file-format: ability to read in history arrays from xml --- src/micropolisj/engine/Micropolis.java | 84 ++++++++++++++-- src/micropolisj/engine/XML_Helper.java | 133 +++++++++++++++++++++++++ 2 files changed, 209 insertions(+), 8 deletions(-) create mode 100644 src/micropolisj/engine/XML_Helper.java diff --git a/src/micropolisj/engine/Micropolis.java b/src/micropolisj/engine/Micropolis.java index 4014f8d..d2078f2 100644 --- a/src/micropolisj/engine/Micropolis.java +++ b/src/micropolisj/engine/Micropolis.java @@ -12,6 +12,7 @@ import java.io.*; import java.util.*; // for XML load/save +import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import javax.xml.stream.*; @@ -1906,7 +1907,7 @@ public class Micropolis static final int [] MltdwnTab = { 30000, 20000, 10000 }; - void loadHistoryArray(int [] array, DataInputStream dis) + void loadHistoryArray_v1(int [] array, DataInputStream dis) throws IOException { for (int i = 0; i < 240; i++) @@ -1915,13 +1916,25 @@ public class Micropolis } } + void loadHistoryArray_v2(int [] array, XMLStreamReader in) + throws XMLStreamException + { + Reader r = XML_Helper.readElementText(in); + Scanner s = new Scanner(r); + for (int i = 0; i < 240; i++) + { + array[i] = s.nextShort(); + } + s.close(); + } + void writeHistoryArray(String tagName, int [] array, XMLStreamWriter out) throws XMLStreamException { out.writeStartElement(tagName); for (int i = 0; i < 240; i++) { - if (i != 0) { out.writeCharacters(","); } + if (i != 0) { out.writeCharacters(" "); } out.writeCharacters(Integer.toString(array[i])); } out.writeEndElement(); @@ -2126,14 +2139,69 @@ public class Micropolis public void load(InputStream inStream) throws IOException + { + try { + GZIPInputStream z_in = new GZIPInputStream(inStream); + XMLStreamReader in = XMLInputFactory.newInstance().createXMLStreamReader(z_in, "UTF-8"); + + in.nextTag(); + if (!(in.getEventType() == XMLStreamConstants.START_ELEMENT && + in.getLocalName().equals("micropolis"))) { + throw new IOException("Unrecognized file format"); + } + + while (in.next() != XMLStreamConstants.END_ELEMENT) { + if (!in.isStartElement()) { + // skip over comments, text, etc. + continue; + } + + String tagName = in.getLocalName(); + if (tagName.equals("res-history")) { + loadHistoryArray_v2(history.res, in); + } + else if (tagName.equals("com-history")) { + loadHistoryArray_v2(history.com, in); + } + else if (tagName.equals("ind-history")) { + loadHistoryArray_v2(history.ind, in); + } + else if (tagName.equals("crime-history")) { + loadHistoryArray_v2(history.crime, in); + } + else if (tagName.equals("pollution-history")) { + loadHistoryArray_v2(history.pollution, in); + } + else if (tagName.equals("money-history")) { + loadHistoryArray_v2(history.money, in); + } + else { + // unrecognized tag + XML_Helper.skipToEndElement(in); + } + } + in.close(); + } catch (XMLStreamException e) { + throw new IOException(e); + } + + checkPowerMap(); + + fireWholeMapChanged(); + fireDemandChanged(); + fireFundsChanged(); + } + + public void load_v1(InputStream inStream) + throws IOException { DataInputStream dis = new DataInputStream(inStream); - loadHistoryArray(history.res, dis); - loadHistoryArray(history.com, dis); - loadHistoryArray(history.ind, dis); - loadHistoryArray(history.crime, dis); - loadHistoryArray(history.pollution, dis); - loadHistoryArray(history.money, dis); + loadHistoryArray_v1(history.res, dis); + loadHistoryArray_v1(history.com, dis); + loadHistoryArray_v1(history.ind, dis); + loadHistoryArray_v1(history.crime, dis); + loadHistoryArray_v1(history.pollution, dis); + loadHistoryArray_v1(history.money, dis); loadMisc(dis); loadMap(dis); dis.close(); diff --git a/src/micropolisj/engine/XML_Helper.java b/src/micropolisj/engine/XML_Helper.java new file mode 100644 index 0000000..8f647d4 --- /dev/null +++ b/src/micropolisj/engine/XML_Helper.java @@ -0,0 +1,133 @@ +package micropolisj.engine; + +import java.io.*; +import javax.xml.stream.*; + +public class XML_Helper +{ + private XML_Helper() {} + + public static void skipToEndElement(XMLStreamReader in) + throws XMLStreamException + { + int tagDepth = 1; + while (tagDepth > 0 && in.hasNext()) { + in.next(); + if (in.isStartElement()) { + tagDepth++; + } + else if (in.isEndElement()) { + tagDepth--; + } + } + } + + public static Reader readElementText(XMLStreamReader in) + { + return new ElementTextReader(in); + } + + static class ElementTextReader extends Reader + { + XMLStreamReader xsr; + int tagDepth; + char [] buf; + int buf_start; + int buf_end; + + ElementTextReader(XMLStreamReader xsr) + { + this.xsr = xsr; + this.tagDepth = 1; + } + + private void readMore() + throws XMLStreamException + { + while (tagDepth > 0 && buf_start == buf_end) { + + int nodeType = xsr.next(); + if (nodeType == XMLStreamConstants.START_ELEMENT) { + tagDepth++; + } + else if (nodeType == XMLStreamConstants.END_ELEMENT) { + tagDepth--; + } + else if (nodeType == XMLStreamConstants.CDATA || + nodeType == XMLStreamConstants.CHARACTERS || + nodeType == XMLStreamConstants.ENTITY_REFERENCE || + nodeType == XMLStreamConstants.SPACE) + { + buf = xsr.getTextCharacters(); + buf_start = xsr.getTextStart(); + buf_end = buf_start + xsr.getTextLength(); + } + } + + } + + @Override + public int read(char[] cbuf, int off, int len) + throws IOException + { + if (buf_start == buf_end) { + + try { + readMore(); + } + catch (XMLStreamException e) { + throw new IOException("XML stream error: "+ e, e); + } + + if (tagDepth == 0) { + // reached closing tag + return 0; + } + } + + if (buf_start + len <= buf_end) { + // already have the text loaded + System.arraycopy(buf, buf_start, cbuf, off, len); + buf_start += len; + return len; + } + else { + // not enough text available for entire request, + // so just return what we have until the next + // request + + len = buf_end - buf_start; + assert len > 0; + + System.arraycopy(buf, buf_start, cbuf, off, len); + buf_start += len; + assert buf_start == buf_end; + return len; + } + } + + @Override + public void close() + throws IOException + { + buf_start = 0; + buf_end = 0; + + try { + + while (tagDepth > 0 && xsr.hasNext()) { + xsr.next(); + if (xsr.isStartElement()) { + tagDepth++; + } + else if (xsr.isEndElement()) { + tagDepth--; + } + } + } + catch (XMLStreamException e) { + throw new IOException("XML stream error: "+e, e); + } + } + } +}