Adam seriously mangles XML.java in the process of adding a pull-based API
authoradam <adam@megacz.com>
Mon, 27 Sep 2004 07:52:27 +0000 (07:52 +0000)
committeradam <adam@megacz.com>
Mon, 27 Sep 2004 07:52:27 +0000 (07:52 +0000)
darcs-hash:20040927075227-5007d-6322087fa922c2a0eb51b1034e406cafed282276.gz

src/org/ibex/util/XML.java

index d0775c7..5837b04 100644 (file)
@@ -8,6 +8,7 @@
 package org.ibex.util;
 
 import java.io.Reader;
+import java.io.Writer;
 import java.io.IOException;
 import java.io.EOFException;
 
@@ -47,8 +48,8 @@ import java.io.EOFException;
  * @see <a href="http://w3.org/TR/REC-xml">XML Specification</a> 
  * @see <a href="http://w3.org/TR/REC-xml-names">XML Namespaces</a>
  */
-public abstract class XML
-{
+public abstract class XML {
+
     /////////////////////////////////////////////////////////////////////////////////////////////
     // XML Parser
     /////////////////////////////////////////////////////////////////////////////////////////////
@@ -64,16 +65,16 @@ public abstract class XML
     private static final char[] single_lt   = new char[] { '<'  };
     private static final char[] single_quot = new char[] { '"'  };
 
-    private int line;
-    private int col;
+    int line;
+    int col;
 
-    private Reader in;
-    private char[] buf;
-    private int    off;
-    private int    base;  // base+off == distance into the stream
-    private int    len;
+    Reader in;
+    char[] buf;
+    int    off;
+    int    base;  // base+off == distance into the stream
+    int    len;
 
-    private Element current;
+    Element current = null;
 
     // used in readEntity() to process a single character without creating a new array
     private char[] singlechar = new char[1];
@@ -83,9 +84,8 @@ public abstract class XML
 
     public XML(int bSize) {
         buf = new char[bSize];
-
-        current = (Element)elements.remove(false);
-        if (current == null) current = new Element();
+        //current = (Element)elements.remove(false);
+        if (current == null) current = newElement();
     }
 
     /** Returns the line number at the beginning of the last process call. */
@@ -97,6 +97,8 @@ public abstract class XML
     /** Returns the global file offset at the beginning of the last process call. */
     public int getGlobalOffset() { return base + off; }
 
+    Element newElement() { return new Element(); }
+
     /**
      * Parse given input and call the abstract event functions.
      *
@@ -123,8 +125,39 @@ public abstract class XML
         } finally { clear(); } // clean up elements
     }
 
+    // Stuff below here is Adam's hack //////////////////////////////////////////////////////////////////////////////
+
+    boolean done = false;
+    public static class Pull extends XML {
+        public Pull(Reader in) { this.in = in; off = len = 0; line = col = 1; clear(); }
+        StringBuffer sb = new StringBuffer();
+        Element pending = null;
+        boolean emptytag = true;
+        public int level = 0;
+        public final void startElement(Element e) throws Exn { emptytag = false; level++; pending = e; }
+        public final void endElement(Element e) throws Exn, IOException { emptytag=pending!=null; level--; }
+        public final void whitespace(char[] ch, int start, int length) throws Exn, IOException { }
+        public final void characters(char[] ch, int start, int length) throws Exn, IOException {
+            emptytag=false; sb.append(ch,start,length);}
+        public Object read() throws Exn, IOException {
+            while(!done) {
+                if (pending != null) { Element ret = pending; pending = null; ret.level = level-(emptytag?0:1); return ret; }
+                if (sb.length() > 0) { String ret = sb.toString(); sb.setLength(0); return ret; }
+                if (!buffer(1)) {
+                    if (done) return null;
+                    throw new Exn("reached eof without closing <"+current.qName+"> element", Exn.WFC, getLine(), getCol());
+                }
+                if (buf[off] == '<') readTag(); else readChars(!done);
+            }
+            return null;
+        }
+    }
+   
+   
+    // Stuff above here is Adam's hack //////////////////////////////////////////////////////////////////////////////
+    
     /** remove any leftover elements from the linked list and queue them */
-    private final void clear() {
+    final void clear() {
         for (Element last = current; current.parent != null; ) {
             current = current.parent;
             last.clear();
@@ -134,7 +167,7 @@ public abstract class XML
     }
 
     /** reads in a tag. expects <tt>buf[off] == '&#60;'</tt> */
-    private final void readTag() throws IOException, Exn {
+    final void readTag() throws IOException, Exn {
         // Start Tag    '<' Name (S Attribute)* S? '>'
         boolean starttag  = true;
 
@@ -296,8 +329,7 @@ public abstract class XML
                 // create the in-memory element representation of this beast
                 // if current.qName == null then this is the root element we're dealing with
                 if (current.qName != null) {
-                    Element next = (Element)elements.remove(false);
-                    if (next == null) next = new Element();
+                    Element next = newElement();
                     //next.clear(); // TODO: remove as elements now checked as they're added to the queue
                     next.parent = current;
                     current = next;
@@ -358,17 +390,18 @@ public abstract class XML
                 // we just closed an element, so remove it from the element 'stack'
                 if (current.getParent() == null) {
                     // we just finished the root element
-                    current.clear(); 
+                    done = true;
                 } else {
                     Element last = current;
                     current = current.parent;
-                    last.clear();
+                    //last.clear();  FIXME
                     elements.append(last);
                 }
             }
         }
     }
 
+
     /** reads in an attribute of an element. expects Name(buf[off]) */
     private final void readAttribute() throws IOException, Exn {
         int ref = 0;
@@ -538,7 +571,7 @@ public abstract class XML
     }
 
     /** reads until the passed string is encountered. */
-    private final void readChars(boolean p, String match, boolean entities) throws IOException, Exn {
+    final void readChars(boolean p, String match, boolean entities) throws IOException, Exn {
         int ref;
         char[] end = match.toCharArray();
 
@@ -593,7 +626,7 @@ public abstract class XML
      * reads until a <tt>&#60;</tt> symbol is encountered
      * @param p If true call the characters(char[],int,int) funciton for the processed characters 
      */
-    private final void readChars(boolean p) throws IOException, Exn {
+    final void readChars(boolean p) throws IOException, Exn {
         int ref;
 
         for (boolean more = true; more;) {
@@ -686,7 +719,7 @@ public abstract class XML
      * @param min Minimum number of characters to read (even if we have to block to do it).
      * @return return false if min can't be reached.
      */
-    private final boolean buffer(int min) throws IOException {
+    final boolean buffer(int min) throws IOException {
         if (len > min) return true;
 
         if (buf.length - (off+len) >= min) {
@@ -746,7 +779,6 @@ public abstract class XML
     /** Represents the end of an Element. */
     public abstract void endElement(Element e) throws Exn, IOException;
 
-
     /////////////////////////////////////////////////////////////////////////////////////////////
     // Inner Classes for Parser Support
     /////////////////////////////////////////////////////////////////////////////////////////////
@@ -769,6 +801,7 @@ public abstract class XML
         protected String localName = null;
         protected String qName = null;
         protected String prefix = null;
+        public int level = 0;
 
         protected Hash urimap = new Hash(3,3);