Coverage Report - org.codehaus.plexus.metadata.merge.MXParser
 
Classes in this File Line Coverage Branch Coverage Complexity
MXParser
0 %
0/1410
0 %
0/1412
13,117
 
 1  
 /* -*-             c-basic-offset: 4; indent-tabs-mode: nil; -*-  //------100-columns-wide------>|*/
 2  
 /*
 3  
  * Copyright (c) 2003 Extreme! Lab, Indiana University. All rights reserved.
 4  
  *
 5  
  * This software is open source. See the bottom of this file for the licence.
 6  
  *
 7  
  * $Id$
 8  
  */
 9  
 
 10  
 package org.codehaus.plexus.metadata.merge;
 11  
 
 12  
 import java.io.EOFException;
 13  
 import java.io.IOException;
 14  
 import java.io.Reader;
 15  
 import java.io.UnsupportedEncodingException;
 16  
 
 17  
 import org.codehaus.plexus.util.ReaderFactory;
 18  
 import org.codehaus.plexus.util.xml.pull.XmlPullParser;
 19  
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 20  
 
 21  
 //import java.util.Hashtable;
 22  
 
 23  
 //TODO best handling of interning issues
 24  
 //   have isAllNewStringInterned ???
 25  
 
 26  
 //TODO handling surrogate pairs: http://www.unicode.org/unicode/faq/utf_bom.html#6
 27  
 
 28  
 //TODO review code for use of bufAbsoluteStart when keeping pos between next()/fillBuf()
 29  
 
 30  
 /**
 31  
  * Absolutely minimal implementation of XMLPULL V1 API. Encoding handling done with XmlReader
 32  
  *
 33  
  * @see org.codehaus.plexus.util.xml.XmlReader
 34  
  * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
 35  
  */
 36  
 
 37  
 public class MXParser
 38  
     implements XmlPullParser
 39  
 {
 40  
     //NOTE: no interning of those strings --> by Java leng spec they MUST be already interned
 41  
     protected final static String XML_URI = "http://www.w3.org/XML/1998/namespace";
 42  
     protected final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
 43  
     protected final static String FEATURE_XML_ROUNDTRIP=
 44  
         //"http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
 45  
         "http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
 46  
     protected final static String FEATURE_NAMES_INTERNED =
 47  
         "http://xmlpull.org/v1/doc/features.html#names-interned";
 48  
     protected final static String PROPERTY_XMLDECL_VERSION =
 49  
         "http://xmlpull.org/v1/doc/properties.html#xmldecl-version";
 50  
     protected final static String PROPERTY_XMLDECL_STANDALONE =
 51  
         "http://xmlpull.org/v1/doc/properties.html#xmldecl-standalone";
 52  
     protected final static String PROPERTY_XMLDECL_CONTENT =
 53  
         "http://xmlpull.org/v1/doc/properties.html#xmldecl-content";
 54  
     protected final static String PROPERTY_LOCATION =
 55  
         "http://xmlpull.org/v1/doc/properties.html#location";
 56  
 
 57  
     
 58  
     protected final static String REPORT_NAMESPACE_PREFIXES =
 59  
         "http://xmlpull.org/v1/doc/features.html#report-namespace-prefixes";
 60  
     /**
 61  
      * Implementation notice:
 62  
      * the is instance variable that controls if newString() is interning.
 63  
      * <p><b>NOTE:</b> newStringIntern <b>always</b> returns interned strings
 64  
      * and newString MAY return interned String depending on this variable.
 65  
      * <p><b>NOTE:</b> by default in this minimal implementation it is false!
 66  
      */
 67  
     protected boolean allStringsInterned;
 68  
 
 69  
     protected boolean usePC;
 70  
     protected boolean seenStartTag;
 71  
     protected boolean seenEndTag;
 72  
     protected boolean pastEndTag;
 73  
     protected boolean seenAmpersand;
 74  
     protected boolean seenMarkup;
 75  
     protected boolean seenDocdecl;
 76  
 
 77  
     // transient variable set during each call to next/Token()
 78  
     protected boolean tokenize;
 79  
     protected String text;
 80  
     protected String entityRefName;
 81  
 
 82  
     protected String xmlDeclVersion;
 83  
     protected Boolean xmlDeclStandalone;
 84  
     protected String xmlDeclContent;
 85  
 
 86  
     // NOTE: features are not resetable and typically defaults to false ...
 87  
     protected boolean processNamespaces;
 88  
     protected boolean roundtripSupported;
 89  
 
 90  
     // global parser state
 91  
     protected String location;
 92  
     protected int lineNumber;
 93  
     protected int columnNumber;
 94  
     protected boolean seenRoot;
 95  
     protected boolean reachedEnd;
 96  
     protected int eventType;
 97  
     protected boolean emptyElementTag;
 98  
     // element stack
 99  
     protected int depth;
 100  
     protected char[] elRawName[];
 101  
     protected int elRawNameEnd[];
 102  
     protected int elRawNameLine[];
 103  
 
 104  
     protected String elName[];
 105  
     protected String elPrefix[];
 106  
     protected String elUri[];
 107  
     //protected String elValue[];
 108  
     protected int elNamespaceCount[];
 109  
 
 110  
     // input buffer management
 111  
     protected static final int READ_CHUNK_SIZE = 8*1024; //max data chars in one read() call
 112  
     protected Reader reader;
 113  
     protected String inputEncoding;
 114  
 
 115  
 
 116  0
     protected int bufLoadFactor = 95;  // 99%
 117  
     //protected int bufHardLimit;  // only matters when expanding
 118  
 
 119  0
     protected char buf[] = new char[READ_CHUNK_SIZE];
 120  0
     protected int bufSoftLimit = ( bufLoadFactor * buf.length ) /100; 
 121  
     protected boolean preventBufferCompaction;
 122  
 
 123  
     protected int bufAbsoluteStart; // this is buf
 124  
     protected int bufStart;
 125  
     protected int bufEnd;
 126  
     protected int pos;
 127  
     protected int posStart;
 128  
     protected int posEnd;
 129  
 
 130  0
     protected char pc[] = new char[READ_CHUNK_SIZE];
 131  
     protected int pcStart;
 132  
     protected int pcEnd;
 133  
 
 134  
     protected void resetStringCache() {
 135  
         //System.out.println("resetStringCache() minimum called");
 136  0
     }
 137  
 
 138  
     protected String newString(char[] cbuf, int off, int len) {
 139  0
         return new String(cbuf, off, len);
 140  
     }
 141  
 
 142  
     protected String newStringIntern(char[] cbuf, int off, int len) {
 143  0
         return (new String(cbuf, off, len)).intern();
 144  
     }
 145  
 
 146  
     private static final boolean TRACE_SIZING = false;
 147  
 
 148  
  
 149  
     /**
 150  
      * Make sure that we have enough space to keep element stack if passed size.
 151  
      * It will always create one additional slot then current depth
 152  
      */
 153  
     protected void ensureElementsCapacity() {
 154  0
         final int elStackSize = elName != null ? elName.length : 0;
 155  0
         if( (depth + 1) >= elStackSize) {
 156  
             // we add at least one extra slot ...
 157  0
             final int newSize = (depth >= 7 ? 2 * depth : 8) + 2; // = lucky 7 + 1 //25
 158  
             if(TRACE_SIZING) {
 159  
                 System.err.println("TRACE_SIZING elStackSize "+elStackSize+" ==> "+newSize);
 160  
             }
 161  0
             final boolean needsCopying = elStackSize > 0;
 162  0
             String[] arr = null;
 163  
             // resue arr local variable slot
 164  0
             arr = new String[newSize];
 165  0
             if(needsCopying) System.arraycopy(elName, 0, arr, 0, elStackSize);
 166  0
             elName = arr;
 167  0
             arr = new String[newSize];
 168  0
             if(needsCopying) System.arraycopy(elPrefix, 0, arr, 0, elStackSize);
 169  0
             elPrefix = arr;
 170  0
             arr = new String[newSize];
 171  0
             if(needsCopying) System.arraycopy(elUri, 0, arr, 0, elStackSize);
 172  0
             elUri = arr;
 173  
 
 174  0
             int[] iarr = new int[newSize];
 175  0
             if(needsCopying) {
 176  0
                 System.arraycopy(elNamespaceCount, 0, iarr, 0, elStackSize);
 177  
             } else {
 178  
                 // special initialization
 179  0
                 iarr[0] = 0;
 180  
             }
 181  0
             elNamespaceCount = iarr;
 182  
 
 183  
             //TODO: avoid using element raw name ...
 184  0
             iarr = new int[newSize];
 185  0
             if(needsCopying) {
 186  0
                 System.arraycopy(elRawNameEnd, 0, iarr, 0, elStackSize);
 187  
             }
 188  0
             elRawNameEnd = iarr;
 189  
 
 190  0
             iarr = new int[newSize];
 191  0
             if(needsCopying) {
 192  0
                 System.arraycopy(elRawNameLine, 0, iarr, 0, elStackSize);
 193  
             }
 194  0
             elRawNameLine = iarr;
 195  
 
 196  0
             final char[][] carr = new char[newSize][];
 197  0
             if(needsCopying) {
 198  0
                 System.arraycopy(elRawName, 0, carr, 0, elStackSize);
 199  
             }
 200  0
             elRawName = carr;
 201  
             //            arr = new String[newSize];
 202  
             //            if(needsCopying) System.arraycopy(elLocalName, 0, arr, 0, elStackSize);
 203  
             //            elLocalName = arr;
 204  
             //            arr = new String[newSize];
 205  
             //            if(needsCopying) System.arraycopy(elDefaultNs, 0, arr, 0, elStackSize);
 206  
             //            elDefaultNs = arr;
 207  
             //            int[] iarr = new int[newSize];
 208  
             //            if(needsCopying) System.arraycopy(elNsStackPos, 0, iarr, 0, elStackSize);
 209  
             //            for (int i = elStackSize; i < iarr.length; i++)
 210  
             //            {
 211  
             //                iarr[i] = (i > 0) ? -1 : 0;
 212  
             //            }
 213  
             //            elNsStackPos = iarr;
 214  
             //assert depth < elName.length;
 215  
         }
 216  0
     }
 217  
 
 218  
 
 219  
 
 220  
     // attribute stack
 221  
     protected int attributeCount;
 222  
     protected String attributeName[];
 223  
     protected int attributeNameHash[];
 224  
     //protected int attributeNameStart[];
 225  
     //protected int attributeNameEnd[];
 226  
     protected String attributePrefix[];
 227  
     protected String attributeUri[];
 228  
     protected String attributeValue[];
 229  
     //protected int attributeValueStart[];
 230  
     //protected int attributeValueEnd[];
 231  
 
 232  
 
 233  
     /**
 234  
      * Make sure that in attributes temporary array is enough space.
 235  
      */
 236  
     protected  void ensureAttributesCapacity(int size) {
 237  0
         final int attrPosSize = attributeName != null ? attributeName.length : 0;
 238  0
         if(size >= attrPosSize) {
 239  0
             final int newSize = size > 7 ? 2 * size : 8; // = lucky 7 + 1 //25
 240  
             if(TRACE_SIZING) {
 241  
                 System.err.println("TRACE_SIZING attrPosSize "+attrPosSize+" ==> "+newSize);
 242  
             }
 243  0
             final boolean needsCopying = attrPosSize > 0;
 244  0
             String[] arr = null;
 245  
 
 246  0
             arr = new String[newSize];
 247  0
             if(needsCopying) System.arraycopy(attributeName, 0, arr, 0, attrPosSize);
 248  0
             attributeName = arr;
 249  
 
 250  0
             arr = new String[newSize];
 251  0
             if(needsCopying) System.arraycopy(attributePrefix, 0, arr, 0, attrPosSize);
 252  0
             attributePrefix = arr;
 253  
 
 254  0
             arr = new String[newSize];
 255  0
             if(needsCopying) System.arraycopy(attributeUri, 0, arr, 0, attrPosSize);
 256  0
             attributeUri = arr;
 257  
 
 258  0
             arr = new String[newSize];
 259  0
             if(needsCopying) System.arraycopy(attributeValue, 0, arr, 0, attrPosSize);
 260  0
             attributeValue = arr;
 261  
 
 262  0
             if( ! allStringsInterned ) {
 263  0
                 final int[] iarr = new int[newSize];
 264  0
                 if(needsCopying) System.arraycopy(attributeNameHash, 0, iarr, 0, attrPosSize);
 265  0
                 attributeNameHash = iarr;
 266  
             }
 267  
 
 268  0
             arr = null;
 269  
             // //assert attrUri.length > size
 270  
         }
 271  0
     }
 272  
 
 273  
     // namespace stack
 274  
     protected int namespaceEnd;
 275  
     protected String namespacePrefix[];
 276  
     protected int namespacePrefixHash[];
 277  
     protected String namespaceUri[];
 278  
 
 279  
     protected void ensureNamespacesCapacity(int size) {
 280  0
         final int namespaceSize = namespacePrefix != null ? namespacePrefix.length : 0;
 281  0
         if(size >= namespaceSize) {
 282  0
             final int newSize = size > 7 ? 2 * size : 8; // = lucky 7 + 1 //25
 283  
             if(TRACE_SIZING) {
 284  
                 System.err.println("TRACE_SIZING namespaceSize "+namespaceSize+" ==> "+newSize);
 285  
             }
 286  0
             final String[] newNamespacePrefix = new String[newSize];
 287  0
             final String[] newNamespaceUri = new String[newSize];
 288  0
             if(namespacePrefix != null) {
 289  0
                 System.arraycopy(
 290  
                     namespacePrefix, 0, newNamespacePrefix, 0, namespaceEnd);
 291  0
                 System.arraycopy(
 292  
                     namespaceUri, 0, newNamespaceUri, 0, namespaceEnd);
 293  
             }
 294  0
             namespacePrefix = newNamespacePrefix;
 295  0
             namespaceUri = newNamespaceUri;
 296  
 
 297  
 
 298  0
             if( ! allStringsInterned ) {
 299  0
                 final int[] newNamespacePrefixHash = new int[newSize];
 300  0
                 if(namespacePrefixHash != null) {
 301  0
                     System.arraycopy(
 302  
                         namespacePrefixHash, 0, newNamespacePrefixHash, 0, namespaceEnd);
 303  
                 }
 304  0
                 namespacePrefixHash = newNamespacePrefixHash;
 305  
             }
 306  
             //prefixesSize = newSize;
 307  
             // //assert nsPrefixes.length > size && nsPrefixes.length == newSize
 308  
         }
 309  0
     }
 310  
 
 311  
     /**
 312  
      * simplistic implementation of hash function that has <b>constant</b>
 313  
      * time to compute - so it also means diminishing hash quality for long strings
 314  
      * but for XML parsing it should be good enough ...
 315  
      */
 316  
     protected static final int fastHash( char ch[], int off, int len ) {
 317  0
         if(len == 0) return 0;
 318  
         //assert len >0
 319  0
         int hash = ch[off]; // hash at beginning
 320  
         //try {
 321  0
         hash = (hash << 7) + ch[ off +  len - 1 ]; // hash at the end
 322  
         //} catch(ArrayIndexOutOfBoundsException aie) {
 323  
         //    aie.printStackTrace(); //should never happen ...
 324  
         //    throw new RuntimeException("this is violation of pre-condition");
 325  
         //}
 326  0
         if(len > 16) hash = (hash << 7) + ch[ off + (len / 4)];  // 1/4 from beginning
 327  0
         if(len > 8)  hash = (hash << 7) + ch[ off + (len / 2)];  // 1/2 of string size ...
 328  
         // notice that hash is at most done 3 times <<7 so shifted by 21 bits 8 bit value
 329  
         // so max result == 29 bits so it is quite just below 31 bits for long (2^32) ...
 330  
         //assert hash >= 0;
 331  0
         return  hash;
 332  
     }
 333  
 
 334  
     // entity replacement stack
 335  
     protected int entityEnd;
 336  
 
 337  
     protected String entityName[];
 338  
     protected char[] entityNameBuf[];
 339  
     protected String entityReplacement[];
 340  
     protected char[] entityReplacementBuf[];
 341  
 
 342  
     protected int entityNameHash[];
 343  
 
 344  
     protected void ensureEntityCapacity() {
 345  0
         final int entitySize = entityReplacementBuf != null ? entityReplacementBuf.length : 0;
 346  0
         if(entityEnd >= entitySize) {
 347  0
             final int newSize = entityEnd > 7 ? 2 * entityEnd : 8; // = lucky 7 + 1 //25
 348  
             if(TRACE_SIZING) {
 349  
                 System.err.println("TRACE_SIZING entitySize "+entitySize+" ==> "+newSize);
 350  
             }
 351  0
             final String[] newEntityName = new String[newSize];
 352  0
             final char[] newEntityNameBuf[] = new char[newSize][];
 353  0
             final String[] newEntityReplacement = new String[newSize];
 354  0
             final char[] newEntityReplacementBuf[] = new char[newSize][];
 355  0
             if(entityName != null) {
 356  0
                 System.arraycopy(entityName, 0, newEntityName, 0, entityEnd);
 357  0
                 System.arraycopy(entityNameBuf, 0, newEntityNameBuf, 0, entityEnd);
 358  0
                 System.arraycopy(entityReplacement, 0, newEntityReplacement, 0, entityEnd);
 359  0
                 System.arraycopy(entityReplacementBuf, 0, newEntityReplacementBuf, 0, entityEnd);
 360  
             }
 361  0
             entityName = newEntityName;
 362  0
             entityNameBuf = newEntityNameBuf;
 363  0
             entityReplacement = newEntityReplacement;
 364  0
             entityReplacementBuf = newEntityReplacementBuf;
 365  
 
 366  0
             if( ! allStringsInterned ) {
 367  0
                 final int[] newEntityNameHash = new int[newSize];
 368  0
                 if(entityNameHash != null) {
 369  0
                     System.arraycopy(entityNameHash, 0, newEntityNameHash, 0, entityEnd);
 370  
                 }
 371  0
                 entityNameHash = newEntityNameHash;
 372  
             }
 373  
         }
 374  0
     }
 375  
         
 376  
     protected void reset() 
 377  
     {
 378  0
         location = null;
 379  0
         lineNumber = 1;
 380  0
         columnNumber = 0;
 381  0
         seenRoot = false;
 382  0
         reachedEnd = false;
 383  0
         eventType = START_DOCUMENT;
 384  0
         emptyElementTag = false;
 385  
 
 386  0
         depth = 0;
 387  
 
 388  0
         attributeCount = 0;
 389  
 
 390  0
         namespaceEnd = 0;
 391  
 
 392  0
         entityEnd = 0;
 393  
 
 394  0
         reader = null;
 395  0
         inputEncoding = null;
 396  
 
 397  0
         preventBufferCompaction = false;
 398  0
         bufAbsoluteStart = 0;
 399  0
         bufEnd = bufStart = 0;
 400  0
         pos = posStart = posEnd = 0;
 401  
 
 402  0
         pcEnd = pcStart = 0;
 403  
 
 404  0
         usePC = false;
 405  
 
 406  0
         seenStartTag = false;
 407  0
         seenEndTag = false;
 408  0
         pastEndTag = false;
 409  0
         seenAmpersand = false;
 410  0
         seenMarkup = false;
 411  0
         seenDocdecl = false;
 412  
 
 413  0
         xmlDeclVersion = null;
 414  0
         xmlDeclStandalone = null;
 415  0
         xmlDeclContent = null;
 416  
 
 417  0
         resetStringCache();
 418  0
     }
 419  
 
 420  0
     public MXParser() {
 421  0
     }
 422  
 
 423  
 
 424  
     /**
 425  
      * Method setFeature
 426  
      *
 427  
      * @param    name                a  String
 428  
      * @param    state               a  boolean
 429  
      *
 430  
      * @throws   XmlPullParserException
 431  
      *
 432  
      */
 433  
     public void setFeature(String name,
 434  
                            boolean state) throws XmlPullParserException
 435  
     {
 436  0
         if(name == null) throw new IllegalArgumentException("feature name should not be null");
 437  0
         if(FEATURE_PROCESS_NAMESPACES.equals(name)) {
 438  0
             if(eventType != START_DOCUMENT) throw new XmlPullParserException(
 439  
                     "namespace processing feature can only be changed before parsing", this, null);
 440  0
             processNamespaces = state;
 441  
             //        } else if(FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
 442  
             //      if(type != START_DOCUMENT) throw new XmlPullParserException(
 443  
             //              "namespace reporting feature can only be changed before parsing", this, null);
 444  
             //            reportNsAttribs = state;
 445  0
         } else if(FEATURE_NAMES_INTERNED.equals(name)) {
 446  0
             if(state != false) {
 447  0
                 throw new XmlPullParserException(
 448  
                     "interning names in this implementation is not supported");
 449  
             }
 450  0
         } else if(FEATURE_PROCESS_DOCDECL.equals(name)) {
 451  0
             if(state != false) {
 452  0
                 throw new XmlPullParserException(
 453  
                     "processing DOCDECL is not supported");
 454  
             }
 455  
             //} else if(REPORT_DOCDECL.equals(name)) {
 456  
             //    paramNotifyDoctype = state;
 457  0
         } else if(FEATURE_XML_ROUNDTRIP.equals(name)) {
 458  
             //if(state == false) {
 459  
             //    throw new XmlPullParserException(
 460  
             //        "roundtrip feature can not be switched off");
 461  
             //}
 462  0
             roundtripSupported = state;
 463  
         } else {
 464  0
             throw new XmlPullParserException("unsupporte feature "+name);
 465  
         }
 466  0
     }
 467  
 
 468  
     /** Unknown properties are <string>always</strong> returned as false */
 469  
     public boolean getFeature(String name)
 470  
     {
 471  0
         if(name == null) throw new IllegalArgumentException("feature name should not be nulll");
 472  0
         if(FEATURE_PROCESS_NAMESPACES.equals(name)) {
 473  0
             return processNamespaces;
 474  
             //        } else if(FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
 475  
             //            return reportNsAttribs;
 476  0
         } else if(FEATURE_NAMES_INTERNED.equals(name)) {
 477  0
             return false;
 478  0
         } else if(FEATURE_PROCESS_DOCDECL.equals(name)) {
 479  0
             return false;
 480  
             //} else if(REPORT_DOCDECL.equals(name)) {
 481  
             //    return paramNotifyDoctype;
 482  0
         } else if(FEATURE_XML_ROUNDTRIP.equals(name)) {
 483  
             //return true;
 484  0
             return roundtripSupported;
 485  
         }
 486  0
         else if( REPORT_NAMESPACE_PREFIXES.equals(  name ) ) {
 487  0
             return processNamespaces;
 488  
         }
 489  
                 
 490  0
         return false;
 491  
     }
 492  
 
 493  
     public void setProperty(String name,
 494  
                             Object value)
 495  
         throws XmlPullParserException
 496  
     {
 497  0
         if(PROPERTY_LOCATION.equals(name)) {
 498  0
             location = (String) value;
 499  
         } else {
 500  0
             throw new XmlPullParserException("unsupported property: '"+name+"'");
 501  
         }
 502  0
     }
 503  
 
 504  
 
 505  
     public Object getProperty(String name)
 506  
     {
 507  0
         if(name == null) throw new IllegalArgumentException("property name should not be nulll");
 508  0
         if(PROPERTY_XMLDECL_VERSION.equals(name)) {
 509  0
             return xmlDeclVersion;
 510  0
         } else if(PROPERTY_XMLDECL_STANDALONE.equals(name)) {
 511  0
             return xmlDeclStandalone;
 512  0
         } else if(PROPERTY_XMLDECL_CONTENT.equals(name)) {
 513  0
             return xmlDeclContent;
 514  0
         } else if(PROPERTY_LOCATION.equals(name)) {
 515  0
             return location;
 516  
         }
 517  0
         return null;
 518  
     }
 519  
 
 520  
 
 521  
     public void setInput(Reader in) throws XmlPullParserException
 522  
     {
 523  0
         reset();
 524  0
         reader = in;
 525  0
     }
 526  
 
 527  
 
 528  
     public void setInput(java.io.InputStream inputStream, String inputEncoding)
 529  
         throws XmlPullParserException
 530  
     {
 531  0
         if(inputStream == null) {
 532  0
             throw new IllegalArgumentException("input stream can not be null");
 533  
         }
 534  
         Reader reader;
 535  
         try {
 536  0
             if(inputEncoding != null) {
 537  0
                 reader = ReaderFactory.newReader(inputStream, inputEncoding);
 538  
             } else {
 539  0
                 reader = ReaderFactory.newXmlReader(inputStream);
 540  
             }
 541  0
         } catch (UnsupportedEncodingException une) {
 542  0
             throw new XmlPullParserException(
 543  
                 "could not create reader for encoding "+inputEncoding+" : "+une, this, une);
 544  
         }
 545  0
         catch ( IOException e )
 546  
         {
 547  0
             throw new XmlPullParserException(
 548  
                 "could not create reader : "+e, this, e);
 549  0
         }
 550  0
         setInput(reader);
 551  
         //must be  here as reset() was called in setInput() and has set this.inputEncoding to null ...
 552  0
         this.inputEncoding = inputEncoding;
 553  0
     }
 554  
 
 555  
     public String getInputEncoding() {
 556  0
         return inputEncoding;
 557  
     }
 558  
 
 559  
     public void defineEntityReplacementText(String entityName,
 560  
                                             String replacementText)
 561  
         throws XmlPullParserException
 562  
     {
 563  
         //      throw new XmlPullParserException("not allowed");
 564  
 
 565  
         //protected char[] entityReplacement[];
 566  0
         ensureEntityCapacity();
 567  
 
 568  
         // this is to make sure that if interning works we will take advantage of it ...
 569  0
         this.entityName[entityEnd] = newString(entityName.toCharArray(), 0, entityName.length());
 570  0
         entityNameBuf[entityEnd] = entityName.toCharArray();
 571  
 
 572  0
         entityReplacement[entityEnd] = replacementText;
 573  0
         entityReplacementBuf[entityEnd] = replacementText.toCharArray();
 574  0
         if(!allStringsInterned) {
 575  0
             entityNameHash[ entityEnd ] =
 576  
                 fastHash(entityNameBuf[entityEnd], 0, entityNameBuf[entityEnd].length);
 577  
         }
 578  0
         ++entityEnd;
 579  
         //TODO disallow < or & in entity replacement text (or ]]>???)
 580  
         // TOOD keepEntityNormalizedForAttributeValue cached as well ...
 581  0
     }
 582  
 
 583  
     public int getNamespaceCount(int depth)
 584  
         throws XmlPullParserException
 585  
     {
 586  0
         if(processNamespaces == false || depth == 0) {
 587  0
             return 0;
 588  
         }
 589  
         //int maxDepth = eventType == END_TAG ? this.depth + 1 : this.depth;
 590  
         //if(depth < 0 || depth > maxDepth) throw new IllegalArgumentException(
 591  0
         if(depth < 0 || depth > this.depth) throw new IllegalArgumentException(
 592  
                 "napespace count mayt be for depth 0.."+this.depth+" not "+depth);
 593  0
         return elNamespaceCount[ depth ];
 594  
     }
 595  
 
 596  
     public String getNamespacePrefix(int pos)
 597  
         throws XmlPullParserException
 598  
     {
 599  
 
 600  
         //int end = eventType == END_TAG ? elNamespaceCount[ depth + 1 ] : namespaceEnd;
 601  
         //if(pos < end) {
 602  0
         if(pos < namespaceEnd) {
 603  0
             return namespacePrefix[ pos ];
 604  
         } else {
 605  0
             throw new XmlPullParserException(
 606  
                 "position "+pos+" exceeded number of available namespaces "+namespaceEnd);
 607  
         }
 608  
     }
 609  
 
 610  
     public String getNamespaceUri(int pos) throws XmlPullParserException
 611  
     {
 612  
         //int end = eventType == END_TAG ? elNamespaceCount[ depth + 1 ] : namespaceEnd;
 613  
         //if(pos < end) {
 614  0
         if(pos < namespaceEnd) {
 615  0
             return namespaceUri[ pos ];
 616  
         } else {
 617  0
             throw new XmlPullParserException(
 618  
                 "position "+pos+" exceedded number of available namespaces "+namespaceEnd);
 619  
         }
 620  
     }
 621  
 
 622  
     public String getNamespace( String prefix )
 623  
         //throws XmlPullParserException
 624  
     {
 625  
         //int count = namespaceCount[ depth ];
 626  0
         if(prefix != null) {
 627  0
             for( int i = namespaceEnd -1; i >= 0; i--) {
 628  0
                 if( prefix.equals( namespacePrefix[ i ] ) ) {
 629  0
                     return namespaceUri[ i ];
 630  
                 }
 631  
             }
 632  0
             if("xml".equals( prefix )) {
 633  0
                 return XML_URI;
 634  0
             } else if("xmlns".equals( prefix )) {
 635  0
                 return XMLNS_URI;
 636  
             }
 637  
         } else {
 638  0
             for( int i = namespaceEnd -1; i >= 0; i--) {
 639  0
                 if( namespacePrefix[ i ]  == null) { //"") { //null ) { //TODO check FIXME Alek
 640  0
                     return namespaceUri[ i ];
 641  
                 }
 642  
             }
 643  
 
 644  
         }
 645  0
         return null;
 646  
     }
 647  
 
 648  
 
 649  
     public int getDepth()
 650  
     {
 651  0
         return depth;
 652  
     }
 653  
 
 654  
 
 655  
     private static int findFragment(int bufMinPos, char[] b, int start, int end) {
 656  
         //System.err.println("bufStart="+bufStart+" b="+printable(new String(b, start, end - start))+" start="+start+" end="+end);
 657  0
         if(start < bufMinPos) {
 658  0
             start = bufMinPos;
 659  0
             if(start > end) start = end;
 660  0
             return start;
 661  
         }
 662  0
         if(end - start > 65) {
 663  0
             start = end - 10; // try to find good location
 664  
         }
 665  0
         int i = start + 1;
 666  0
         while(--i > bufMinPos) {
 667  0
             if((end - i) > 65) break;
 668  0
             final char c = b[i];
 669  0
             if(c == '<' && (start - i) > 10) break;
 670  0
         }
 671  0
         return i;
 672  
     }
 673  
 
 674  
 
 675  
     /**
 676  
      * Return string describing current position of parsers as
 677  
      * text 'STATE [seen %s...] @line:column'.
 678  
      */
 679  
     public String getPositionDescription ()
 680  
     {
 681  0
         String fragment = null;
 682  0
         if(posStart <= pos) {
 683  0
             final int start = findFragment(0, buf, posStart, pos);
 684  
             //System.err.println("start="+start);
 685  0
             if(start < pos) {
 686  0
                 fragment = new String(buf, start, pos - start);
 687  
             }
 688  0
             if(bufAbsoluteStart > 0 || start > 0) fragment = "..." + fragment;
 689  
         }
 690  
         //        return " at line "+tokenizerPosRow
 691  
         //            +" and column "+(tokenizerPosCol-1)
 692  
         //            +(fragment != null ? " seen "+printable(fragment)+"..." : "");
 693  0
         return " "+TYPES[ eventType ] +
 694  
             (fragment != null ? " seen "+printable(fragment)+"..." : "")
 695  
             +" "+(location != null ? location : "")
 696  
             +"@"+getLineNumber()+":"+getColumnNumber();
 697  
     }
 698  
 
 699  
     public int getLineNumber()
 700  
     {
 701  0
         return lineNumber;
 702  
     }
 703  
 
 704  
     public int getColumnNumber()
 705  
     {
 706  0
         return columnNumber;
 707  
     }
 708  
 
 709  
 
 710  
     public boolean isWhitespace() throws XmlPullParserException
 711  
     {
 712  0
         if(eventType == TEXT || eventType == CDSECT) {
 713  0
             if(usePC) {
 714  0
                 for (int i = pcStart; i <pcEnd; i++)
 715  
                 {
 716  0
                     if(!isS(pc[ i ])) return false;
 717  
                 }
 718  0
                 return true;
 719  
             } else {
 720  0
                 for (int i = posStart; i <posEnd; i++)
 721  
                 {
 722  0
                     if(!isS(buf[ i ])) return false;
 723  
                 }
 724  0
                 return true;
 725  
             }
 726  0
         } else if(eventType == IGNORABLE_WHITESPACE) {
 727  0
             return true;
 728  
         }
 729  0
         throw new XmlPullParserException("no content available to check for whitespaces");
 730  
     }
 731  
 
 732  
     public String getText()
 733  
     {
 734  0
         if(eventType == START_DOCUMENT || eventType == END_DOCUMENT) {
 735  
             //throw new XmlPullParserException("no content available to read");
 736  
             //      if(roundtripSupported) {
 737  
             //          text = new String(buf, posStart, posEnd - posStart);
 738  
             //      } else {
 739  0
             return null;
 740  
             //      }
 741  0
         } else if(eventType == ENTITY_REF) {
 742  0
             return text;
 743  
         }
 744  0
         if(text == null) {
 745  0
             if(!usePC || eventType == START_TAG || eventType == END_TAG) {
 746  0
                 text = new String(buf, posStart, posEnd - posStart);
 747  
             } else {
 748  0
                 text = new String(pc, pcStart, pcEnd - pcStart);
 749  
             }
 750  
         }
 751  0
         return text;
 752  
     }
 753  
 
 754  
     public char[] getTextCharacters(int [] holderForStartAndLength)
 755  
     {
 756  0
         if( eventType == TEXT ) {
 757  0
             if(usePC) {
 758  0
                 holderForStartAndLength[0] = pcStart;
 759  0
                 holderForStartAndLength[1] = pcEnd - pcStart;
 760  0
                 return pc;
 761  
             } else {
 762  0
                 holderForStartAndLength[0] = posStart;
 763  0
                 holderForStartAndLength[1] = posEnd - posStart;
 764  0
                 return buf;
 765  
 
 766  
             }
 767  0
         } else if( eventType == START_TAG
 768  
                       || eventType == END_TAG
 769  
                       || eventType == CDSECT
 770  
                       || eventType == COMMENT
 771  
                       || eventType == ENTITY_REF
 772  
                       || eventType == PROCESSING_INSTRUCTION
 773  
                       || eventType == IGNORABLE_WHITESPACE
 774  
                       || eventType == DOCDECL)
 775  
         {
 776  0
             holderForStartAndLength[0] = posStart;
 777  0
             holderForStartAndLength[1] = posEnd - posStart;
 778  0
             return buf;
 779  0
         } else if(eventType == START_DOCUMENT
 780  
                       || eventType == END_DOCUMENT) {
 781  
             //throw new XmlPullParserException("no content available to read");
 782  0
             holderForStartAndLength[0] = holderForStartAndLength[1] = -1;
 783  0
             return null;
 784  
         } else {
 785  0
             throw new IllegalArgumentException("unknown text eventType: "+eventType);
 786  
         }
 787  
         //      String s = getText();
 788  
         //      char[] cb = null;
 789  
         //      if(s!= null) {
 790  
         //          cb = s.toCharArray();
 791  
         //          holderForStartAndLength[0] = 0;
 792  
         //          holderForStartAndLength[1] = s.length();
 793  
         //      } else {
 794  
         //      }
 795  
         //      return cb;
 796  
     }
 797  
 
 798  
     public String getNamespace()
 799  
     {
 800  0
         if(eventType == START_TAG) {
 801  
             //return processNamespaces ? elUri[ depth - 1 ] : NO_NAMESPACE;
 802  0
             return processNamespaces ? elUri[ depth  ] : NO_NAMESPACE;
 803  0
         } else if(eventType == END_TAG) {
 804  0
             return processNamespaces ? elUri[ depth ] : NO_NAMESPACE;
 805  
         }
 806  0
         return null;
 807  
         //        String prefix = elPrefix[ maxDepth ];
 808  
         //        if(prefix != null) {
 809  
         //            for( int i = namespaceEnd -1; i >= 0; i--) {
 810  
         //                if( prefix.equals( namespacePrefix[ i ] ) ) {
 811  
         //                    return namespaceUri[ i ];
 812  
         //                }
 813  
         //            }
 814  
         //        } else {
 815  
         //            for( int i = namespaceEnd -1; i >= 0; i--) {
 816  
         //                if( namespacePrefix[ i ]  == null ) {
 817  
         //                    return namespaceUri[ i ];
 818  
         //                }
 819  
         //            }
 820  
         //
 821  
         //        }
 822  
         //        return "";
 823  
     }
 824  
 
 825  
     public String getName()
 826  
     {
 827  0
         if(eventType == START_TAG) {
 828  
             //return elName[ depth - 1 ] ;
 829  0
             return elName[ depth ] ;
 830  0
         } else if(eventType == END_TAG) {
 831  0
             return elName[ depth ] ;
 832  0
         } else if(eventType == ENTITY_REF) {
 833  0
             if(entityRefName == null) {
 834  0
                 entityRefName = newString(buf, posStart, posEnd - posStart);
 835  
             }
 836  0
             return entityRefName;
 837  
         } else {
 838  0
             return null;
 839  
         }
 840  
     }
 841  
 
 842  
     public String getPrefix()
 843  
     {
 844  0
         if(eventType == START_TAG) {
 845  
             //return elPrefix[ depth - 1 ] ;
 846  0
             return elPrefix[ depth ] ;
 847  0
         } else if(eventType == END_TAG) {
 848  0
             return elPrefix[ depth ] ;
 849  
         }
 850  0
         return null;
 851  
         //        if(eventType != START_TAG && eventType != END_TAG) return null;
 852  
         //        int maxDepth = eventType == END_TAG ? depth : depth - 1;
 853  
         //        return elPrefix[ maxDepth ];
 854  
     }
 855  
 
 856  
 
 857  
     public boolean isEmptyElementTag() throws XmlPullParserException
 858  
     {
 859  0
         if(eventType != START_TAG) throw new XmlPullParserException(
 860  
                 "parser must be on START_TAG to check for empty element", this, null);
 861  0
         return emptyElementTag;
 862  
     }
 863  
 
 864  
     public int getAttributeCount()
 865  
     {
 866  0
         if(eventType != START_TAG) return -1;
 867  0
         return attributeCount;
 868  
     }
 869  
 
 870  
     public String getAttributeNamespace(int index)
 871  
     {
 872  0
         if(eventType != START_TAG) throw new IndexOutOfBoundsException(
 873  
                 "only START_TAG can have attributes");
 874  0
         if(processNamespaces == false) return NO_NAMESPACE;
 875  0
         if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
 876  
                 "attribute position must be 0.."+(attributeCount-1)+" and not "+index);
 877  0
         return attributeUri[ index ];
 878  
     }
 879  
 
 880  
     public String getAttributeName(int index)
 881  
     {
 882  0
         if(eventType != START_TAG) throw new IndexOutOfBoundsException(
 883  
                 "only START_TAG can have attributes");
 884  0
         if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
 885  
                 "attribute position must be 0.."+(attributeCount-1)+" and not "+index);
 886  0
         return attributeName[ index ];
 887  
     }
 888  
 
 889  
     public String getAttributePrefix(int index)
 890  
     {
 891  0
         if(eventType != START_TAG) throw new IndexOutOfBoundsException(
 892  
                 "only START_TAG can have attributes");
 893  0
         if(processNamespaces == false) return null;
 894  0
         if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
 895  
                 "attribute position must be 0.."+(attributeCount-1)+" and not "+index);
 896  0
         return attributePrefix[ index ];
 897  
     }
 898  
 
 899  
     public String getAttributeType(int index) {
 900  0
         if(eventType != START_TAG) throw new IndexOutOfBoundsException(
 901  
                 "only START_TAG can have attributes");
 902  0
         if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
 903  
                 "attribute position must be 0.."+(attributeCount-1)+" and not "+index);
 904  0
         return "CDATA";
 905  
     }
 906  
 
 907  
     public boolean isAttributeDefault(int index) {
 908  0
         if(eventType != START_TAG) throw new IndexOutOfBoundsException(
 909  
                 "only START_TAG can have attributes");
 910  0
         if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
 911  
                 "attribute position must be 0.."+(attributeCount-1)+" and not "+index);
 912  0
         return false;
 913  
     }
 914  
 
 915  
     public String getAttributeValue(int index)
 916  
     {
 917  0
         if(eventType != START_TAG) throw new IndexOutOfBoundsException(
 918  
                 "only START_TAG can have attributes");
 919  0
         if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
 920  
                 "attribute position must be 0.."+(attributeCount-1)+" and not "+index);
 921  0
         return attributeValue[ index ];
 922  
     }
 923  
 
 924  
     public String getAttributeValue(String namespace,
 925  
                                     String name)
 926  
     {
 927  0
         if(eventType != START_TAG) throw new IndexOutOfBoundsException(
 928  
                 "only START_TAG can have attributes"+getPositionDescription());
 929  0
         if(name == null) {
 930  0
             throw new IllegalArgumentException("attribute name can not be null");
 931  
         }
 932  
         // TODO make check if namespace is interned!!! etc. for names!!!
 933  0
         if(processNamespaces) {
 934  0
             if(namespace == null) {
 935  0
                 namespace = "";
 936  
             }
 937  
 
 938  0
             for(int i = 0; i < attributeCount; ++i) {
 939  0
                 if((namespace == attributeUri[ i ] ||
 940  
                         namespace.equals(attributeUri[ i ]) )
 941  
                        //(namespace != null && namespace.equals(attributeUri[ i ]))
 942  
                        // taking advantage of String.intern()
 943  
                        && name.equals(attributeName[ i ]) )
 944  
                 {
 945  0
                     return attributeValue[i];
 946  
                 }
 947  
             }
 948  
         } else {
 949  0
             if(namespace != null && namespace.length() == 0) {
 950  0
                 namespace = null;
 951  
             }
 952  0
             if(namespace != null) throw new IllegalArgumentException(
 953  
                     "when namespaces processing is disabled attribute namespace must be null");
 954  0
             for(int i = 0; i < attributeCount; ++i) {
 955  0
                 if(name.equals(attributeName[i]))
 956  
                 {
 957  0
                     return attributeValue[i];
 958  
                 }
 959  
             }
 960  
         }
 961  0
         return null;
 962  
     }
 963  
 
 964  
 
 965  
     public int getEventType()
 966  
         throws XmlPullParserException
 967  
     {
 968  0
         return eventType;
 969  
     }
 970  
 
 971  
     public void require(int type, String namespace, String name)
 972  
         throws XmlPullParserException, IOException
 973  
     {
 974  0
         if(processNamespaces == false && namespace != null) {
 975  0
             throw new XmlPullParserException(
 976  
                 "processing namespaces must be enabled on parser (or factory)"+
 977  
                     " to have possible namespaces delcared on elements"
 978  
                     +(" (postion:"+ getPositionDescription())+")");
 979  
         }
 980  0
         if (type != getEventType()
 981  
                 || (namespace != null && !namespace.equals (getNamespace()))
 982  
                 || (name != null && !name.equals (getName ())) )
 983  
         {
 984  0
             throw new XmlPullParserException (
 985  
                 "expected event "+TYPES[ type ]
 986  
                     +(name != null ? " with name '"+name+"'" : "")
 987  
                     +(namespace != null && name != null ? " and" : "")
 988  
                     +(namespace != null ? " with namespace '"+namespace+"'" : "")
 989  
                     +" but got"
 990  
                     +(type != getEventType() ? " "+TYPES[ getEventType() ] : "")
 991  
                     +(name != null && getName() != null && !name.equals (getName ())
 992  
                           ? " name '"+getName()+"'" : "")
 993  
                     +(namespace != null && name != null
 994  
                           && getName() != null && !name.equals (getName ())
 995  
                           && getNamespace() != null && !namespace.equals (getNamespace())
 996  
                           ? " and" : "")
 997  
                     +(namespace != null && getNamespace() != null && !namespace.equals (getNamespace())
 998  
                           ? " namespace '"+getNamespace()+"'" : "")
 999  
                     +(" (postion:"+ getPositionDescription())+")");
 1000  
         }
 1001  0
     }
 1002  
 
 1003  
 
 1004  
     /**
 1005  
      * Skip sub tree that is currently porser positioned on.
 1006  
      * <br>NOTE: parser must be on START_TAG and when funtion returns
 1007  
      * parser will be positioned on corresponding END_TAG
 1008  
      */
 1009  
     public void skipSubTree()
 1010  
         throws XmlPullParserException, IOException
 1011  
     {
 1012  0
         require(START_TAG, null, null);
 1013  0
         int level = 1;
 1014  0
         while(level > 0) {
 1015  0
             int eventType = next();
 1016  0
             if(eventType == END_TAG) {
 1017  0
                 --level;
 1018  0
             } else if(eventType == START_TAG) {
 1019  0
                 ++level;
 1020  
             }
 1021  0
         }
 1022  0
     }
 1023  
 
 1024  
     //    public String readText() throws XmlPullParserException, IOException
 1025  
     //    {
 1026  
     //        if (getEventType() != TEXT) return "";
 1027  
     //        String result = getText();
 1028  
     //        next();
 1029  
     //        return result;
 1030  
     //    }
 1031  
 
 1032  
     public String nextText() throws XmlPullParserException, IOException
 1033  
     {
 1034  
         //        String result = null;
 1035  
         //        boolean onStartTag = false;
 1036  
         //        if(eventType == START_TAG) {
 1037  
         //            onStartTag = true;
 1038  
         //            next();
 1039  
         //        }
 1040  
         //        if(eventType == TEXT) {
 1041  
         //            result = getText();
 1042  
         //            next();
 1043  
         //        } else if(onStartTag && eventType == END_TAG) {
 1044  
         //            result = "";
 1045  
         //        } else {
 1046  
         //            throw new XmlPullParserException(
 1047  
         //                "parser must be on START_TAG or TEXT to read text", this, null);
 1048  
         //        }
 1049  
         //        if(eventType != END_TAG) {
 1050  
         //            throw new XmlPullParserException(
 1051  
         //                "event TEXT it must be immediately followed by END_TAG", this, null);
 1052  
         //        }
 1053  
         //        return result;
 1054  0
         if(getEventType() != START_TAG) {
 1055  0
             throw new XmlPullParserException(
 1056  
                 "parser must be on START_TAG to read next text", this, null);
 1057  
         }
 1058  0
         int eventType = next();
 1059  0
         if(eventType == TEXT) {
 1060  0
             final String result = getText();
 1061  0
             eventType = next();
 1062  0
             if(eventType != END_TAG) {
 1063  0
                 throw new XmlPullParserException(
 1064  
                     "TEXT must be immediately followed by END_TAG and not "
 1065  
                         +TYPES[ getEventType() ], this, null);
 1066  
             }
 1067  0
             return result;
 1068  0
         } else if(eventType == END_TAG) {
 1069  0
             return "";
 1070  
         } else {
 1071  0
             throw new XmlPullParserException(
 1072  
                 "parser must be on START_TAG or TEXT to read text", this, null);
 1073  
         }
 1074  
     }
 1075  
 
 1076  
     public int nextTag() throws XmlPullParserException, IOException
 1077  
     {
 1078  0
         next();
 1079  0
         if(eventType == TEXT && isWhitespace()) {  // skip whitespace
 1080  0
             next();
 1081  
         }
 1082  0
         if (eventType != START_TAG && eventType != END_TAG) {
 1083  0
             throw new XmlPullParserException("expected START_TAG or END_TAG not "
 1084  
                                                  +TYPES[ getEventType() ], this, null);
 1085  
         }
 1086  0
         return eventType;
 1087  
     }
 1088  
 
 1089  
     public int next()
 1090  
         throws XmlPullParserException, IOException
 1091  
     {
 1092  0
         tokenize = false;
 1093  0
         return nextImpl();
 1094  
     }
 1095  
 
 1096  
     public int nextToken()
 1097  
         throws XmlPullParserException, IOException
 1098  
     {
 1099  0
         tokenize = true;
 1100  0
         return nextImpl();
 1101  
     }
 1102  
 
 1103  
 
 1104  
     protected int nextImpl()
 1105  
         throws XmlPullParserException, IOException
 1106  
     {
 1107  0
         text = null;
 1108  0
         pcEnd = pcStart = 0;
 1109  0
         usePC = false;
 1110  0
         bufStart = posEnd;
 1111  0
         if(pastEndTag) {
 1112  0
             pastEndTag = false;
 1113  0
             --depth;
 1114  0
             namespaceEnd = elNamespaceCount[ depth ]; // less namespaces available
 1115  
         }
 1116  0
         if(emptyElementTag) {
 1117  0
             emptyElementTag = false;
 1118  0
             pastEndTag = true;
 1119  0
             return eventType = END_TAG;
 1120  
         }
 1121  
 
 1122  
         // [1] document ::= prolog element Misc*
 1123  0
         if(depth > 0) {
 1124  
 
 1125  0
             if(seenStartTag) {
 1126  0
                 seenStartTag = false;
 1127  0
                 return eventType = parseStartTag();
 1128  
             }
 1129  0
             if(seenEndTag) {
 1130  0
                 seenEndTag = false;
 1131  0
                 return eventType = parseEndTag();
 1132  
             }
 1133  
 
 1134  
             // ASSUMPTION: we are _on_ first character of content or markup!!!!
 1135  
             // [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)*
 1136  
             char ch;
 1137  0
             if(seenMarkup) {  // we have read ahead ...
 1138  0
                 seenMarkup = false;
 1139  0
                 ch = '<';
 1140  0
             } else if(seenAmpersand) {
 1141  0
                 seenAmpersand = false;
 1142  0
                 ch = '&';
 1143  
             } else {
 1144  0
                 ch = more();
 1145  
             }
 1146  0
             posStart = pos - 1; // VERY IMPORTANT: this is correct start of event!!!
 1147  
 
 1148  
             // when true there is some potential event TEXT to return - keep gathering
 1149  0
             boolean hadCharData = false;
 1150  
 
 1151  
             // when true TEXT data is not continuous (like <![CDATA[text]]>) and requires PC merging
 1152  0
             boolean needsMerging = false;
 1153  
 
 1154  
             MAIN_LOOP:
 1155  
             while(true) {
 1156  
                 // work on MARKUP
 1157  0
                 if(ch == '<') {
 1158  0
                     if(hadCharData) {
 1159  
                         //posEnd = pos - 1;
 1160  0
                         if(tokenize) {
 1161  0
                             seenMarkup = true;
 1162  0
                             return eventType = TEXT;
 1163  
                         }
 1164  
                     }
 1165  0
                     ch = more();
 1166  0
                     if(ch == '/') {
 1167  0
                         if(!tokenize && hadCharData) {
 1168  0
                             seenEndTag = true;
 1169  
                             //posEnd = pos - 2;
 1170  0
                             return eventType = TEXT;
 1171  
                         }
 1172  0
                         return eventType = parseEndTag();
 1173  0
                     } else if(ch == '!') {
 1174  0
                         ch = more();
 1175  0
                         if(ch == '-') {
 1176  
                             // note: if(tokenize == false) posStart/End is NOT changed!!!!
 1177  0
                             parseComment();
 1178  0
                             if(tokenize) return eventType = COMMENT;
 1179  0
                             if( !usePC && hadCharData ) {
 1180  0
                                 needsMerging = true;
 1181  
                             } else {
 1182  0
                                 posStart = pos;  //completely ignore comment
 1183  
                             }
 1184  0
                         } else if(ch == '[') {
 1185  
                             //posEnd = pos - 3;
 1186  
                             // must remember previous posStart/End as it merges with content of CDATA
 1187  
                             //int oldStart = posStart + bufAbsoluteStart;
 1188  
                             //int oldEnd = posEnd + bufAbsoluteStart;
 1189  0
                             parseCDSect(hadCharData);
 1190  0
                             if(tokenize) return eventType = CDSECT;
 1191  0
                             final int cdStart = posStart;
 1192  0
                             final int cdEnd = posEnd;
 1193  0
                             final int cdLen = cdEnd - cdStart;
 1194  
 
 1195  
 
 1196  0
                             if(cdLen > 0) { // was there anything inside CDATA section?
 1197  0
                                 hadCharData = true;
 1198  0
                                 if(!usePC) {
 1199  0
                                     needsMerging = true;
 1200  
                                 }
 1201  
                             }
 1202  
 
 1203  
                             //                          posStart = oldStart;
 1204  
                             //                          posEnd = oldEnd;
 1205  
                             //                          if(cdLen > 0) { // was there anything inside CDATA section?
 1206  
                             //                              if(hadCharData) {
 1207  
                             //                                  // do merging if there was anything in CDSect!!!!
 1208  
                             //                                  //                                    if(!usePC) {
 1209  
                             //                                  //                                        // posEnd is correct already!!!
 1210  
                             //                                  //                                        if(posEnd > posStart) {
 1211  
                             //                                  //                                            joinPC();
 1212  
                             //                                  //                                        } else {
 1213  
                             //                                  //                                            usePC = true;
 1214  
                             //                                  //                                            pcStart = pcEnd = 0;
 1215  
                             //                                  //                                        }
 1216  
                             //                                  //                                    }
 1217  
                             //                                  //                                    if(pcEnd + cdLen >= pc.length) ensurePC(pcEnd + cdLen);
 1218  
                             //                                  //                                    // copy [cdStart..cdEnd) into PC
 1219  
                             //                                  //                                    System.arraycopy(buf, cdStart, pc, pcEnd, cdLen);
 1220  
                             //                                  //                                    pcEnd += cdLen;
 1221  
                             //                                  if(!usePC) {
 1222  
                             //                                      needsMerging = true;
 1223  
                             //                                      posStart = cdStart;
 1224  
                             //                                      posEnd = cdEnd;
 1225  
                             //                                  }
 1226  
                             //                              } else {
 1227  
                             //                                  if(!usePC) {
 1228  
                             //                                      needsMerging = true;
 1229  
                             //                                      posStart = cdStart;
 1230  
                             //                                      posEnd = cdEnd;
 1231  
                             //                                      hadCharData = true;
 1232  
                             //                                  }
 1233  
                             //                              }
 1234  
                             //                              //hadCharData = true;
 1235  
                             //                          } else {
 1236  
                             //                              if( !usePC && hadCharData ) {
 1237  
                             //                                  needsMerging = true;
 1238  
                             //                              }
 1239  
                             //                          }
 1240  0
                         } else {
 1241  0
                             throw new XmlPullParserException(
 1242  
                                 "unexpected character in markup "+printable(ch), this, null);
 1243  
                         }
 1244  0
                     } else if(ch == '?') {
 1245  0
                         parsePI();
 1246  0
                         if(tokenize) return eventType = PROCESSING_INSTRUCTION;
 1247  0
                         if( !usePC && hadCharData ) {
 1248  0
                             needsMerging = true;
 1249  
                         } else {
 1250  0
                             posStart = pos;  //completely ignore PI
 1251  
                         }
 1252  
 
 1253  0
                     } else if( isNameStartChar(ch) ) {
 1254  0
                         if(!tokenize && hadCharData) {
 1255  0
                             seenStartTag = true;
 1256  
                             //posEnd = pos - 2;
 1257  0
                             return eventType = TEXT;
 1258  
                         }
 1259  0
                         return eventType = parseStartTag();
 1260  
                     } else {
 1261  0
                         throw new XmlPullParserException(
 1262  
                             "unexpected character in markup "+printable(ch), this, null);
 1263  
                     }
 1264  
                     // do content comapctation if it makes sense!!!!
 1265  
 
 1266  0
                 } else if(ch == '&') {
 1267  
                     // work on ENTITTY
 1268  
                     //posEnd = pos - 1;
 1269  0
                     if(tokenize && hadCharData) {
 1270  0
                         seenAmpersand = true;
 1271  0
                         return eventType = TEXT;
 1272  
                     }
 1273  0
                     final int oldStart = posStart + bufAbsoluteStart;
 1274  0
                     final int oldEnd = posEnd + bufAbsoluteStart;
 1275  0
                     final char[] resolvedEntity = parseEntityRef();
 1276  0
                     if(tokenize) return eventType = ENTITY_REF;
 1277  
                     // check if replacement text can be resolved !!!
 1278  0
                     if(resolvedEntity == null) {
 1279  0
                         if(entityRefName == null) {
 1280  0
                             entityRefName = newString(buf, posStart, posEnd - posStart);
 1281  
                         }
 1282  0
                         throw new XmlPullParserException(
 1283  
                             "could not resolve entity named '"+printable(entityRefName)+"'",
 1284  
                             this, null);
 1285  
                     }
 1286  
                     //int entStart = posStart;
 1287  
                     //int entEnd = posEnd;
 1288  0
                     posStart = oldStart - bufAbsoluteStart;
 1289  0
                     posEnd = oldEnd - bufAbsoluteStart;
 1290  0
                     if(!usePC) {
 1291  0
                         if(hadCharData) {
 1292  0
                             joinPC(); // posEnd is already set correctly!!!
 1293  0
                             needsMerging = false;
 1294  
                         } else {
 1295  0
                             usePC = true;
 1296  0
                             pcStart = pcEnd = 0;
 1297  
                         }
 1298  
                     }
 1299  
                     //assert usePC == true;
 1300  
                     // write into PC replacement text - do merge for replacement text!!!!
 1301  0
                     for (char aResolvedEntity : resolvedEntity) {
 1302  0
                         if (pcEnd >= pc.length) ensurePC(pcEnd);
 1303  0
                         pc[pcEnd++] = aResolvedEntity;
 1304  
 
 1305  
                     }
 1306  0
                     hadCharData = true;
 1307  
                     //assert needsMerging == false;
 1308  0
                 } else {
 1309  
 
 1310  0
                     if(needsMerging) {
 1311  
                         //assert usePC == false;
 1312  0
                         joinPC();  // posEnd is already set correctly!!!
 1313  
                         //posStart = pos  -  1;
 1314  0
                         needsMerging = false;
 1315  
                     }
 1316  
 
 1317  
 
 1318  
                     //no MARKUP not ENTITIES so work on character data ...
 1319  
 
 1320  
 
 1321  
 
 1322  
                     // [14] CharData ::=   [^<&]* - ([^<&]* ']]>' [^<&]*)
 1323  
 
 1324  
 
 1325  0
                     hadCharData = true;
 1326  
 
 1327  0
                     boolean normalizedCR = false;
 1328  0
                     final boolean normalizeInput = tokenize == false || roundtripSupported == false;
 1329  
                     // use loop locality here!!!!
 1330  0
                     boolean seenBracket = false;
 1331  0
                     boolean seenBracketBracket = false;
 1332  
                     do {
 1333  
 
 1334  
                         // check that ]]> does not show in
 1335  0
                         if(ch == ']') {
 1336  0
                             if(seenBracket) {
 1337  0
                                 seenBracketBracket = true;
 1338  
                             } else {
 1339  0
                                 seenBracket = true;
 1340  
                             }
 1341  0
                         } else if(seenBracketBracket && ch == '>') {
 1342  0
                             throw new XmlPullParserException(
 1343  
                                 "characters ]]> are not allowed in content", this, null);
 1344  
                         } else {
 1345  0
                             if(seenBracket) {
 1346  0
                                 seenBracketBracket = seenBracket = false;
 1347  
                             }
 1348  
                             // assert seenTwoBrackets == seenBracket == false;
 1349  
                         }
 1350  0
                         if(normalizeInput) {
 1351  
                             // deal with normalization issues ...
 1352  0
                             if(ch == '\r') {
 1353  0
                                 normalizedCR = true;
 1354  0
                                 posEnd = pos -1;
 1355  
                                 // posEnd is already set
 1356  0
                                 if(!usePC) {
 1357  0
                                     if(posEnd > posStart) {
 1358  0
                                         joinPC();
 1359  
                                     } else {
 1360  0
                                         usePC = true;
 1361  0
                                         pcStart = pcEnd = 0;
 1362  
                                     }
 1363  
                                 }
 1364  
                                 //assert usePC == true;
 1365  0
                                 if(pcEnd >= pc.length) ensurePC(pcEnd);
 1366  0
                                 pc[pcEnd++] = '\n';
 1367  0
                             } else if(ch == '\n') {
 1368  
                                 //   if(!usePC) {  joinPC(); } else { if(pcEnd >= pc.length) ensurePC(); }
 1369  0
                                 if(!normalizedCR && usePC) {
 1370  0
                                     if(pcEnd >= pc.length) ensurePC(pcEnd);
 1371  0
                                     pc[pcEnd++] = '\n';
 1372  
                                 }
 1373  0
                                 normalizedCR = false;
 1374  
                             } else {
 1375  0
                                 if(usePC) {
 1376  0
                                     if(pcEnd >= pc.length) ensurePC(pcEnd);
 1377  0
                                     pc[pcEnd++] = ch;
 1378  
                                 }
 1379  0
                                 normalizedCR = false;
 1380  
                             }
 1381  
                         }
 1382  
 
 1383  0
                         ch = more();
 1384  0
                     } while(ch != '<' && ch != '&');
 1385  0
                     posEnd = pos - 1;
 1386  0
                     continue MAIN_LOOP;  // skip ch = more() from below - we are already ahead ...
 1387  
                 }
 1388  0
                 ch = more();
 1389  
             } // endless while(true)
 1390  
         } else {
 1391  0
             if(seenRoot) {
 1392  0
                 return parseEpilog();
 1393  
             } else {
 1394  0
                 return parseProlog();
 1395  
             }
 1396  
         }
 1397  
     }
 1398  
 
 1399  
 
 1400  
     protected int parseProlog()
 1401  
         throws XmlPullParserException, IOException
 1402  
     {
 1403  
         // [2] prolog: ::= XMLDecl? Misc* (doctypedecl Misc*)? and look for [39] element
 1404  
 
 1405  
         char ch;
 1406  0
         if(seenMarkup) {
 1407  0
             ch = buf[ pos - 1 ];
 1408  
         } else {
 1409  0
             ch = more();
 1410  
         }
 1411  
 
 1412  0
         if(eventType == START_DOCUMENT) {
 1413  
             // bootstrap parsing with getting first character input!
 1414  
             // deal with BOM
 1415  
             // detect BOM and crop it (Unicode int Order Mark)
 1416  0
             if(ch == '\uFFFE') {
 1417  0
                 throw new XmlPullParserException(
 1418  
                     "first character in input was UNICODE noncharacter (0xFFFE)"+
 1419  
                         "- input requires int swapping", this, null);
 1420  
             }
 1421  0
             if(ch == '\uFEFF') {
 1422  
                 // skipping UNICODE int Order Mark (so called BOM)
 1423  0
                 ch = more();
 1424  
             }
 1425  
         }
 1426  0
         seenMarkup = false;
 1427  0
         boolean gotS = false;
 1428  0
         posStart = pos - 1;
 1429  0
         final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
 1430  0
         boolean normalizedCR = false;
 1431  
         while(true) {
 1432  
             // deal with Misc
 1433  
             // [27] Misc ::= Comment | PI | S
 1434  
             // deal with docdecl --> mark it!
 1435  
             // else parseStartTag seen <[^/]
 1436  0
             if(ch == '<') {
 1437  0
                 if(gotS && tokenize) {
 1438  0
                     posEnd = pos - 1;
 1439  0
                     seenMarkup = true;
 1440  0
                     return eventType = IGNORABLE_WHITESPACE;
 1441  
                 }
 1442  0
                 ch = more();
 1443  0
                 if(ch == '?') {
 1444  
                     // check if it is 'xml'
 1445  
                     // deal with XMLDecl
 1446  0
                     boolean isXMLDecl = parsePI();
 1447  0
                     if(tokenize) {
 1448  0
                         if (isXMLDecl) {
 1449  0
                             return eventType = START_DOCUMENT;
 1450  
                         }
 1451  0
                         return eventType = PROCESSING_INSTRUCTION;
 1452  
                     }
 1453  0
                 } else if(ch == '!') {
 1454  0
                     ch = more();
 1455  0
                     if(ch == 'D') {
 1456  0
                         if(seenDocdecl) {
 1457  0
                             throw new XmlPullParserException(
 1458  
                                 "only one docdecl allowed in XML document", this, null);
 1459  
                         }
 1460  0
                         seenDocdecl = true;
 1461  0
                         parseDocdecl();
 1462  0
                         if(tokenize) return eventType = DOCDECL;
 1463  0
                     } else if(ch == '-') {
 1464  0
                         parseComment();
 1465  0
                         if(tokenize) return eventType = COMMENT;
 1466  
                     } else {
 1467  0
                         throw new XmlPullParserException(
 1468  
                             "unexpected markup <!"+printable(ch), this, null);
 1469  
                     }
 1470  0
                 } else if(ch == '/') {
 1471  0
                     throw new XmlPullParserException(
 1472  
                         "expected start tag name and not "+printable(ch), this, null);
 1473  0
                 } else if(isNameStartChar(ch)) {
 1474  0
                     seenRoot = true;
 1475  0
                     return parseStartTag();
 1476  
                 } else {
 1477  0
                     throw new XmlPullParserException(
 1478  
                         "expected start tag name and not "+printable(ch), this, null);
 1479  
                 }
 1480  0
             } else if(isS(ch)) {
 1481  0
                 gotS = true;
 1482  0
                 if(normalizeIgnorableWS) {
 1483  0
                     if(ch == '\r') {
 1484  0
                         normalizedCR = true;
 1485  
                         //posEnd = pos -1;
 1486  
                         //joinPC();
 1487  
                         // posEnd is already set
 1488  0
                         if(!usePC) {
 1489  0
                             posEnd = pos -1;
 1490  0
                             if(posEnd > posStart) {
 1491  0
                                 joinPC();
 1492  
                             } else {
 1493  0
                                 usePC = true;
 1494  0
                                 pcStart = pcEnd = 0;
 1495  
                             }
 1496  
                         }
 1497  
                         //assert usePC == true;
 1498  0
                         if(pcEnd >= pc.length) ensurePC(pcEnd);
 1499  0
                         pc[pcEnd++] = '\n';
 1500  0
                     } else if(ch == '\n') {
 1501  0
                         if(!normalizedCR && usePC) {
 1502  0
                             if(pcEnd >= pc.length) ensurePC(pcEnd);
 1503  0
                             pc[pcEnd++] = '\n';
 1504  
                         }
 1505  0
                         normalizedCR = false;
 1506  
                     } else {
 1507  0
                         if(usePC) {
 1508  0
                             if(pcEnd >= pc.length) ensurePC(pcEnd);
 1509  0
                             pc[pcEnd++] = ch;
 1510  
                         }
 1511  0
                         normalizedCR = false;
 1512  
                     }
 1513  
                 }
 1514  
             } else {
 1515  0
                 throw new XmlPullParserException(
 1516  
                     "only whitespace content allowed before start tag and not "+printable(ch),
 1517  
                     this, null);
 1518  
             }
 1519  0
             ch = more();
 1520  
         }
 1521  
     }
 1522  
 
 1523  
     protected int parseEpilog()
 1524  
         throws XmlPullParserException, IOException
 1525  
     {
 1526  0
         if(eventType == END_DOCUMENT) {
 1527  0
             throw new XmlPullParserException("already reached end of XML input", this, null);
 1528  
         }
 1529  0
         if(reachedEnd) {
 1530  0
             return eventType = END_DOCUMENT;
 1531  
         }
 1532  0
         boolean gotS = false;
 1533  0
         final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
 1534  0
         boolean normalizedCR = false;
 1535  
         try {
 1536  
             // epilog: Misc*
 1537  
             char ch;
 1538  0
             if(seenMarkup) {
 1539  0
                 ch = buf[ pos - 1 ];
 1540  
             } else {
 1541  0
                 ch = more();
 1542  
             }
 1543  0
             seenMarkup = false;
 1544  0
             posStart = pos - 1;
 1545  0
             if(!reachedEnd) {
 1546  
                 while(true) {
 1547  
                     // deal with Misc
 1548  
                     // [27] Misc ::= Comment | PI | S
 1549  0
                     if(ch == '<') {
 1550  0
                         if(gotS && tokenize) {
 1551  0
                             posEnd = pos - 1;
 1552  0
                             seenMarkup = true;
 1553  0
                             return eventType = IGNORABLE_WHITESPACE;
 1554  
                         }
 1555  0
                         ch = more();
 1556  0
                         if(reachedEnd) {
 1557  0
                             break;
 1558  
                         }
 1559  0
                         if(ch == '?') {
 1560  
                             // check if it is 'xml'
 1561  
                             // deal with XMLDecl
 1562  0
                             parsePI();
 1563  0
                             if(tokenize) return eventType = PROCESSING_INSTRUCTION;
 1564  
 
 1565  0
                         } else if(ch == '!') {
 1566  0
                             ch = more();
 1567  0
                             if(reachedEnd) {
 1568  0
                                 break;
 1569  
                             }
 1570  0
                             if(ch == 'D') {
 1571  0
                                 parseDocdecl(); //FIXME
 1572  0
                                 if(tokenize) return eventType = DOCDECL;
 1573  0
                             } else if(ch == '-') {
 1574  0
                                 parseComment();
 1575  0
                                 if(tokenize) return eventType = COMMENT;
 1576  
                             } else {
 1577  0
                                 throw new XmlPullParserException(
 1578  
                                     "unexpected markup <!"+printable(ch), this, null);
 1579  
                             }
 1580  0
                         } else if(ch == '/') {
 1581  0
                             throw new XmlPullParserException(
 1582  
                                 "end tag not allowed in epilog but got "+printable(ch), this, null);
 1583  0
                         } else if(isNameStartChar(ch)) {
 1584  0
                             throw new XmlPullParserException(
 1585  
                                 "start tag not allowed in epilog but got "+printable(ch), this, null);
 1586  
                         } else {
 1587  0
                             throw new XmlPullParserException(
 1588  
                                 "in epilog expected ignorable content and not "+printable(ch),
 1589  
                                 this, null);
 1590  
                         }
 1591  0
                     } else if(isS(ch)) {
 1592  0
                         gotS = true;
 1593  0
                         if(normalizeIgnorableWS) {
 1594  0
                             if(ch == '\r') {
 1595  0
                                 normalizedCR = true;
 1596  
                                 //posEnd = pos -1;
 1597  
                                 //joinPC();
 1598  
                                 // posEnd is already set
 1599  0
                                 if(!usePC) {
 1600  0
                                     posEnd = pos -1;
 1601  0
                                     if(posEnd > posStart) {
 1602  0
                                         joinPC();
 1603  
                                     } else {
 1604  0
                                         usePC = true;
 1605  0
                                         pcStart = pcEnd = 0;
 1606  
                                     }
 1607  
                                 }
 1608  
                                 //assert usePC == true;
 1609  0
                                 if(pcEnd >= pc.length) ensurePC(pcEnd);
 1610  0
                                 pc[pcEnd++] = '\n';
 1611  0
                             } else if(ch == '\n') {
 1612  0
                                 if(!normalizedCR && usePC) {
 1613  0
                                     if(pcEnd >= pc.length) ensurePC(pcEnd);
 1614  0
                                     pc[pcEnd++] = '\n';
 1615  
                                 }
 1616  0
                                 normalizedCR = false;
 1617  
                             } else {
 1618  0
                                 if(usePC) {
 1619  0
                                     if(pcEnd >= pc.length) ensurePC(pcEnd);
 1620  0
                                     pc[pcEnd++] = ch;
 1621  
                                 }
 1622  0
                                 normalizedCR = false;
 1623  
                             }
 1624  
                         }
 1625  
                     } else {
 1626  0
                         throw new XmlPullParserException(
 1627  
                             "in epilog non whitespace content is not allowed but got "+printable(ch),
 1628  
                             this, null);
 1629  
                     }
 1630  0
                     ch = more();
 1631  0
                     if(reachedEnd) {
 1632  0
                         break;
 1633  
                     }
 1634  
 
 1635  
                 }
 1636  
             }
 1637  
 
 1638  
             // throw Exception("unexpected content in epilog
 1639  
             // catch EOFException return END_DOCUMENT
 1640  
             //try {
 1641  0
         } catch(EOFException ex) {
 1642  0
             reachedEnd = true;
 1643  0
         }
 1644  0
         if(reachedEnd) {
 1645  0
             if(tokenize && gotS) {
 1646  0
                 posEnd = pos; // well - this is LAST available character pos
 1647  0
                 return eventType = IGNORABLE_WHITESPACE;
 1648  
             }
 1649  0
             return eventType = END_DOCUMENT;
 1650  
         } else {
 1651  0
             throw new XmlPullParserException("internal error in parseEpilog");
 1652  
         }
 1653  
     }
 1654  
 
 1655  
 
 1656  
     public int parseEndTag() throws XmlPullParserException, IOException {
 1657  
         //ASSUMPTION ch is past "</"
 1658  
         // [42] ETag ::=  '</' Name S? '>'
 1659  0
         char ch = more();
 1660  0
         if(!isNameStartChar(ch)) {
 1661  0
             throw new XmlPullParserException(
 1662  
                 "expected name start and not "+printable(ch), this, null);
 1663  
         }
 1664  0
         posStart = pos - 3;
 1665  0
         final int nameStart = pos - 1 + bufAbsoluteStart;
 1666  
         do {
 1667  0
             ch = more();
 1668  0
         } while(isNameChar(ch));
 1669  
 
 1670  
         // now we go one level down -- do checks
 1671  
         //--depth;  //FIXME
 1672  
 
 1673  
         // check that end tag name is the same as start tag
 1674  
         //String name = new String(buf, nameStart - bufAbsoluteStart,
 1675  
         //                           (pos - 1) - (nameStart - bufAbsoluteStart));
 1676  
         //int last = pos - 1;
 1677  0
         int off = nameStart - bufAbsoluteStart;
 1678  
         //final int len = last - off;
 1679  0
         final int len = (pos - 1) - off;
 1680  0
         final char[] cbuf = elRawName[depth];
 1681  0
         if(elRawNameEnd[depth] != len) {
 1682  
             // construct strings for exception
 1683  0
             final String startname = new String(cbuf, 0, elRawNameEnd[depth]);
 1684  0
             final String endname = new String(buf, off, len);
 1685  0
             throw new XmlPullParserException(
 1686  
                 "end tag name </"+endname+"> must match start tag name <"+startname+">"
 1687  
                     +" from line "+elRawNameLine[depth], this, null);
 1688  
         }
 1689  0
         for (int i = 0; i < len; i++)
 1690  
         {
 1691  0
             if(buf[off++] != cbuf[i]) {
 1692  
                 // construct strings for exception
 1693  0
                 final String startname = new String(cbuf, 0, len);
 1694  0
                 final String endname = new String(buf, off - i - 1, len);
 1695  0
                 throw new XmlPullParserException(
 1696  
                     "end tag name </"+endname+"> must be the same as start tag <"+startname+">"
 1697  
                         +" from line "+elRawNameLine[depth], this, null);
 1698  
             }
 1699  
         }
 1700  
 
 1701  0
         while(isS(ch)) { ch = more(); } // skip additional white spaces
 1702  0
         if(ch != '>') {
 1703  0
             throw new XmlPullParserException(
 1704  
                 "expected > to finsh end tag not "+printable(ch)
 1705  
                     +" from line "+elRawNameLine[depth], this, null);
 1706  
         }
 1707  
 
 1708  
 
 1709  
         //namespaceEnd = elNamespaceCount[ depth ]; //FIXME
 1710  
 
 1711  0
         posEnd = pos;
 1712  0
         pastEndTag = true;
 1713  0
         return eventType = END_TAG;
 1714  
     }
 1715  
 
 1716  
     public int parseStartTag() throws XmlPullParserException, IOException {
 1717  
         //ASSUMPTION ch is past <T
 1718  
         // [40] STag ::=  '<' Name (S Attribute)* S? '>'
 1719  
         // [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
 1720  0
         ++depth; //FIXME
 1721  
 
 1722  0
         posStart = pos - 2;
 1723  
 
 1724  0
         emptyElementTag = false;
 1725  0
         attributeCount = 0;
 1726  
         // retrieve name
 1727  0
         final int nameStart = pos - 1 + bufAbsoluteStart;
 1728  0
         int colonPos = -1;
 1729  0
         char ch = buf[ pos - 1];
 1730  0
         if(ch == ':' && processNamespaces) throw new XmlPullParserException(
 1731  
                 "when namespaces processing enabled colon can not be at element name start",
 1732  
                 this, null);
 1733  
         while(true) {
 1734  0
             ch = more();
 1735  0
             if(!isNameChar(ch)) break;
 1736  0
             if(ch == ':' && processNamespaces) {
 1737  0
                 if(colonPos != -1) throw new XmlPullParserException(
 1738  
                         "only one colon is allowed in name of element when namespaces are enabled",
 1739  
                         this, null);
 1740  0
                 colonPos = pos - 1 + bufAbsoluteStart;
 1741  
             }
 1742  
         }
 1743  
 
 1744  
         // retrieve name
 1745  0
         ensureElementsCapacity();
 1746  
 
 1747  
 
 1748  
         //TODO check for efficient interning and then use elRawNameInterned!!!!
 1749  
 
 1750  0
         int elLen = (pos - 1) - (nameStart - bufAbsoluteStart);
 1751  0
         if(elRawName[ depth ] == null || elRawName[ depth ].length < elLen) {
 1752  0
             elRawName[ depth ] = new char[ 2 * elLen ];
 1753  
         }
 1754  0
         System.arraycopy(buf, nameStart - bufAbsoluteStart, elRawName[ depth ], 0, elLen);
 1755  0
         elRawNameEnd[ depth ] = elLen;
 1756  0
         elRawNameLine[ depth ] = lineNumber;
 1757  
 
 1758  0
         String name = null;
 1759  
 
 1760  
         // work on prefixes and namespace URI
 1761  0
         String prefix = null;
 1762  0
         if(processNamespaces) {
 1763  0
             if(colonPos != -1) {
 1764  0
                 prefix = elPrefix[ depth ] = newString(buf, nameStart - bufAbsoluteStart,
 1765  
                                                        colonPos - nameStart);
 1766  0
                 name = elName[ depth ] = newString(buf, colonPos + 1 - bufAbsoluteStart,
 1767  
                                                    //(pos -1) - (colonPos + 1));
 1768  
                                                    pos - 2 - (colonPos - bufAbsoluteStart));
 1769  
             } else {
 1770  0
                 prefix = elPrefix[ depth ] = null;
 1771  0
                 name = elName[ depth ] = newString(buf, nameStart - bufAbsoluteStart, elLen);
 1772  
             }
 1773  
         } else {
 1774  
 
 1775  0
             name = elName[ depth ] = newString(buf, nameStart - bufAbsoluteStart, elLen);
 1776  
 
 1777  
         }
 1778  
 
 1779  
 
 1780  
         while(true) {
 1781  
 
 1782  0
             while(isS(ch)) { ch = more(); } // skip additional white spaces
 1783  
 
 1784  0
             if(ch == '>') {
 1785  0
                 break;
 1786  0
             } else if(ch == '/') {
 1787  0
                 if(emptyElementTag) throw new XmlPullParserException(
 1788  
                         "repeated / in tag declaration", this, null);
 1789  0
                 emptyElementTag = true;
 1790  0
                 ch = more();
 1791  0
                 if(ch != '>') throw new XmlPullParserException(
 1792  
                         "expected > to end empty tag not "+printable(ch), this, null);
 1793  
                 break;
 1794  0
             } else if(isNameStartChar(ch)) {
 1795  0
                 ch = parseAttribute();
 1796  0
                 ch = more();
 1797  0
                 continue;
 1798  
             } else {
 1799  0
                 throw new XmlPullParserException(
 1800  
                     "start tag unexpected character "+printable(ch), this, null);
 1801  
             }
 1802  
             //ch = more(); // skip space
 1803  
         }
 1804  
 
 1805  
         // now when namespaces were declared we can resolve them
 1806  0
         if(processNamespaces) {
 1807  0
             String uri = getNamespace(prefix);
 1808  0
             if(uri == null) {
 1809  0
                 if(prefix == null) { // no prefix and no uri => use default namespace
 1810  0
                     uri = NO_NAMESPACE;
 1811  
                 } else {
 1812  0
                     throw new XmlPullParserException(
 1813  
                         "could not determine namespace bound to element prefix "+prefix,
 1814  
                         this, null);
 1815  
                 }
 1816  
 
 1817  
             }
 1818  0
             elUri[ depth ] = uri;
 1819  
 
 1820  
 
 1821  
             //String uri = getNamespace(prefix);
 1822  
             //if(uri == null && prefix == null) { // no prefix and no uri => use default namespace
 1823  
             //  uri = "";
 1824  
             //}
 1825  
             // resolve attribute namespaces
 1826  0
             for (int i = 0; i < attributeCount; i++)
 1827  
             {
 1828  0
                 final String attrPrefix = attributePrefix[ i ];
 1829  0
                 if(attrPrefix != null) {
 1830  0
                     final String attrUri = getNamespace(attrPrefix);
 1831  0
                     if(attrUri == null) {
 1832  0
                         throw new XmlPullParserException(
 1833  
                             "could not determine namespace bound to attribute prefix "+attrPrefix,
 1834  
                             this, null);
 1835  
 
 1836  
                     }
 1837  0
                     attributeUri[ i ] = attrUri;
 1838  0
                 } else {
 1839  0
                     attributeUri[ i ] = NO_NAMESPACE;
 1840  
                 }
 1841  
             }
 1842  
 
 1843  
             //TODO
 1844  
             //[ WFC: Unique Att Spec ]
 1845  
             // check namespaced attribute uniqueness contraint!!!
 1846  
 
 1847  0
             for (int i = 1; i < attributeCount; i++)
 1848  
             {
 1849  0
                 for (int j = 0; j < i; j++)
 1850  
                 {
 1851  0
                     if( attributeUri[j] == attributeUri[i]
 1852  
                            && (allStringsInterned && attributeName[j].equals(attributeName[i])
 1853  
                                    || (!allStringsInterned
 1854  
                                            && attributeNameHash[ j ] == attributeNameHash[ i ]
 1855  
                                            && attributeName[j].equals(attributeName[i])) )
 1856  
 
 1857  
                       ) {
 1858  
                         // prepare data for nice error messgae?
 1859  0
                         String attr1 = attributeName[j];
 1860  0
                         if(attributeUri[j] != null) attr1 = attributeUri[j]+":"+attr1;
 1861  0
                         String attr2 = attributeName[i];
 1862  0
                         if(attributeUri[i] != null) attr2 = attributeUri[i]+":"+attr2;
 1863  0
                         throw new XmlPullParserException(
 1864  
                             "duplicated attributes "+attr1+" and "+attr2, this, null);
 1865  
                     }
 1866  
                 }
 1867  
             }
 1868  
 
 1869  
 
 1870  0
         } else { // ! processNamespaces
 1871  
 
 1872  
             //[ WFC: Unique Att Spec ]
 1873  
             // check raw attribute uniqueness contraint!!!
 1874  0
             for (int i = 1; i < attributeCount; i++)
 1875  
             {
 1876  0
                 for (int j = 0; j < i; j++)
 1877  
                 {
 1878  0
                     if((allStringsInterned && attributeName[j].equals(attributeName[i])
 1879  
                             || (!allStringsInterned
 1880  
                                     && attributeNameHash[ j ] == attributeNameHash[ i ]
 1881  
                                     && attributeName[j].equals(attributeName[i])) )
 1882  
 
 1883  
                       ) {
 1884  
                         // prepare data for nice error messgae?
 1885  0
                         final String attr1 = attributeName[j];
 1886  0
                         final String attr2 = attributeName[i];
 1887  0
                         throw new XmlPullParserException(
 1888  
                             "duplicated attributes "+attr1+" and "+attr2, this, null);
 1889  
                     }
 1890  
                 }
 1891  
             }
 1892  
         }
 1893  
 
 1894  0
         elNamespaceCount[ depth ] = namespaceEnd;
 1895  0
         posEnd = pos;
 1896  0
         return eventType = START_TAG;
 1897  
     }
 1898  
 
 1899  
     protected char parseAttribute() throws XmlPullParserException, IOException
 1900  
     {
 1901  
         // parse attribute
 1902  
         // [41] Attribute ::= Name Eq AttValue
 1903  
         // [WFC: No External Entity References]
 1904  
         // [WFC: No < in Attribute Values]
 1905  0
         final int prevPosStart = posStart + bufAbsoluteStart;
 1906  0
         final int nameStart = pos - 1 + bufAbsoluteStart;
 1907  0
         int colonPos = -1;
 1908  0
         char ch = buf[ pos - 1 ];
 1909  0
         if(ch == ':' && processNamespaces) throw new XmlPullParserException(
 1910  
                 "when namespaces processing enabled colon can not be at attribute name start",
 1911  
                 this, null);
 1912  
 
 1913  
 
 1914  0
         boolean startsWithXmlns = processNamespaces && ch == 'x';
 1915  0
         int xmlnsPos = 0;
 1916  
 
 1917  0
         ch = more();
 1918  0
         while(isNameChar(ch)) {
 1919  0
             if(processNamespaces) {
 1920  0
                 if(startsWithXmlns && xmlnsPos < 5) {
 1921  0
                     ++xmlnsPos;
 1922  0
                     if(xmlnsPos == 1) { if(ch != 'm') startsWithXmlns = false; }
 1923  0
                     else if(xmlnsPos == 2) { if(ch != 'l') startsWithXmlns = false; }
 1924  0
                     else if(xmlnsPos == 3) { if(ch != 'n') startsWithXmlns = false; }
 1925  0
                     else if(xmlnsPos == 4) { if(ch != 's') startsWithXmlns = false; }
 1926  0
                     else if(xmlnsPos == 5) {
 1927  0
                         if(ch != ':') throw new XmlPullParserException(
 1928  
                                 "after xmlns in attribute name must be colon"
 1929  
                                     +"when namespaces are enabled", this, null);
 1930  
                         //colonPos = pos - 1 + bufAbsoluteStart;
 1931  
                     }
 1932  
                 }
 1933  0
                 if(ch == ':') {
 1934  0
                     if(colonPos != -1) throw new XmlPullParserException(
 1935  
                             "only one colon is allowed in attribute name"
 1936  
                                 +" when namespaces are enabled", this, null);
 1937  0
                     colonPos = pos - 1 + bufAbsoluteStart;
 1938  
                 }
 1939  
             }
 1940  0
             ch = more();
 1941  
         }
 1942  
 
 1943  0
         ensureAttributesCapacity(attributeCount);
 1944  
 
 1945  
         // --- start processing attributes
 1946  0
         String name = null;
 1947  0
         String prefix = null;
 1948  
         // work on prefixes and namespace URI
 1949  0
         if(processNamespaces) {
 1950  0
             if(xmlnsPos < 4) startsWithXmlns = false;
 1951  0
             if(startsWithXmlns) {
 1952  0
                 if(colonPos != -1) {
 1953  
                     //prefix = attributePrefix[ attributeCount ] = null;
 1954  0
                     final int nameLen = pos - 2 - (colonPos - bufAbsoluteStart);
 1955  0
                     if(nameLen == 0) {
 1956  0
                         throw new XmlPullParserException(
 1957  
                             "namespace prefix is required after xmlns: "
 1958  
                                 +" when namespaces are enabled", this, null);
 1959  
                     }
 1960  0
                     name = //attributeName[ attributeCount ] =
 1961  
                         newString(buf, colonPos - bufAbsoluteStart + 1, nameLen);
 1962  
                     //pos - 1 - (colonPos + 1 - bufAbsoluteStart)
 1963  0
                 }
 1964  
             } else {
 1965  0
                 if(colonPos != -1) {
 1966  0
                     int prefixLen = colonPos - nameStart;
 1967  0
                     prefix = attributePrefix[ attributeCount ] =
 1968  
                         newString(buf, nameStart - bufAbsoluteStart,prefixLen);
 1969  
                     //colonPos - (nameStart - bufAbsoluteStart));
 1970  0
                     int nameLen = pos - 2 - (colonPos - bufAbsoluteStart);
 1971  0
                     name = attributeName[ attributeCount ] =
 1972  
                         newString(buf, colonPos - bufAbsoluteStart + 1, nameLen);
 1973  
                     //pos - 1 - (colonPos + 1 - bufAbsoluteStart));
 1974  
 
 1975  
                     //name.substring(0, colonPos-nameStart);
 1976  0
                 } else {
 1977  0
                     prefix = attributePrefix[ attributeCount ]  = null;
 1978  0
                     name = attributeName[ attributeCount ] =
 1979  
                         newString(buf, nameStart - bufAbsoluteStart,
 1980  
                                   pos - 1 - (nameStart - bufAbsoluteStart));
 1981  
                 }
 1982  0
                 if(!allStringsInterned) {
 1983  0
                     attributeNameHash[ attributeCount ] = name.hashCode();
 1984  
                 }
 1985  
             }
 1986  
 
 1987  
         } else {
 1988  
             // retrieve name
 1989  0
             name = attributeName[ attributeCount ] =
 1990  
                 newString(buf, nameStart - bufAbsoluteStart,
 1991  
                           pos - 1 - (nameStart - bufAbsoluteStart));
 1992  
             ////assert name != null;
 1993  0
             if(!allStringsInterned) {
 1994  0
                 attributeNameHash[ attributeCount ] = name.hashCode();
 1995  
             }
 1996  
         }
 1997  
 
 1998  
         // [25] Eq ::=  S? '=' S?
 1999  0
         while(isS(ch)) { ch = more(); } // skip additional spaces
 2000  0
         if(ch != '=') throw new XmlPullParserException(
 2001  
                 "expected = after attribute name", this, null);
 2002  0
         ch = more();
 2003  0
         while(isS(ch)) { ch = more(); } // skip additional spaces
 2004  
 
 2005  
         // [10] AttValue ::=   '"' ([^<&"] | Reference)* '"'
 2006  
         //                  |  "'" ([^<&'] | Reference)* "'"
 2007  0
         final char delimit = ch;
 2008  0
         if(delimit != '"' && delimit != '\'') throw new XmlPullParserException(
 2009  
                 "attribute value must start with quotation or apostrophe not "
 2010  
                     +printable(delimit), this, null);
 2011  
         // parse until delimit or < and resolve Reference
 2012  
         //[67] Reference ::= EntityRef | CharRef
 2013  
         //int valueStart = pos + bufAbsoluteStart;
 2014  
 
 2015  
 
 2016  0
         boolean normalizedCR = false;
 2017  0
         usePC = false;
 2018  0
         pcStart = pcEnd;
 2019  0
         posStart = pos;
 2020  
 
 2021  
         while(true) {
 2022  0
             ch = more();
 2023  0
             if(ch == delimit) {
 2024  0
                 break;
 2025  0
             } if(ch == '<') {
 2026  0
                 throw new XmlPullParserException(
 2027  
                     "markup not allowed inside attribute value - illegal < ", this, null);
 2028  0
             } if(ch == '&') {
 2029  
                 // extractEntityRef
 2030  0
                 posEnd = pos - 1;
 2031  0
                 if(!usePC) {
 2032  0
                     final boolean hadCharData = posEnd > posStart;
 2033  0
                     if(hadCharData) {
 2034  
                         // posEnd is already set correctly!!!
 2035  0
                         joinPC();
 2036  
                     } else {
 2037  0
                         usePC = true;
 2038  0
                         pcStart = pcEnd = 0;
 2039  
                     }
 2040  
                 }
 2041  
                 //assert usePC == true;
 2042  
 
 2043  0
                 final char[] resolvedEntity = parseEntityRef();
 2044  
                 // check if replacement text can be resolved !!!
 2045  0
                 if(resolvedEntity == null) {
 2046  0
                     if(entityRefName == null) {
 2047  0
                         entityRefName = newString(buf, posStart, posEnd - posStart);
 2048  
                     }
 2049  0
                     throw new XmlPullParserException(
 2050  
                         "could not resolve entity named '"+printable(entityRefName)+"'",
 2051  
                         this, null);
 2052  
                 }
 2053  
                 // write into PC replacement text - do merge for replacement text!!!!
 2054  0
                 for (char aResolvedEntity : resolvedEntity) {
 2055  0
                     if (pcEnd >= pc.length) ensurePC(pcEnd);
 2056  0
                     pc[pcEnd++] = aResolvedEntity;
 2057  
                 }
 2058  0
             } else if(ch == '\t' || ch == '\n' || ch == '\r') {
 2059  
                 // do attribute value normalization
 2060  
                 // as described in http://www.w3.org/TR/REC-xml#AVNormalize
 2061  
                 // TODO add test for it form spec ...
 2062  
                 // handle EOL normalization ...
 2063  0
                 if(!usePC) {
 2064  0
                     posEnd = pos - 1;
 2065  0
                     if(posEnd > posStart) {
 2066  0
                         joinPC();
 2067  
                     } else {
 2068  0
                         usePC = true;
 2069  0
                         pcEnd = pcStart = 0;
 2070  
                     }
 2071  
                 }
 2072  
                 //assert usePC == true;
 2073  0
                 if(pcEnd >= pc.length) ensurePC(pcEnd);
 2074  0
                 if(ch != '\n' || !normalizedCR) {
 2075  0
                     pc[pcEnd++] = ' '; //'\n';
 2076  
                 }
 2077  
 
 2078  
             } else {
 2079  0
                 if(usePC) {
 2080  0
                     if(pcEnd >= pc.length) ensurePC(pcEnd);
 2081  0
                     pc[pcEnd++] = ch;
 2082  
                 }
 2083  
             }
 2084  0
             normalizedCR = ch == '\r';
 2085  
         }
 2086  
 
 2087  
 
 2088  0
         if(processNamespaces && startsWithXmlns) {
 2089  0
             String ns = null;
 2090  0
             if(!usePC) {
 2091  0
                 ns = newStringIntern(buf, posStart, pos - 1 - posStart);
 2092  
             } else {
 2093  0
                 ns = newStringIntern(pc, pcStart, pcEnd - pcStart);
 2094  
             }
 2095  0
             ensureNamespacesCapacity(namespaceEnd);
 2096  0
             int prefixHash = -1;
 2097  0
             if(colonPos != -1) {
 2098  0
                 if(ns.length() == 0) {
 2099  0
                     throw new XmlPullParserException(
 2100  
                         "non-default namespace can not be declared to be empty string", this, null);
 2101  
                 }
 2102  
                 // declare new namespace
 2103  0
                 namespacePrefix[ namespaceEnd ] = name;
 2104  0
                 if(!allStringsInterned) {
 2105  0
                     prefixHash = namespacePrefixHash[ namespaceEnd ] = name.hashCode();
 2106  
                 }
 2107  
             } else {
 2108  
                 // declare new default namespace...
 2109  0
                 namespacePrefix[ namespaceEnd ] = null; //""; //null; //TODO check FIXME Alek
 2110  0
                 if(!allStringsInterned) {
 2111  0
                     prefixHash = namespacePrefixHash[ namespaceEnd ] = -1;
 2112  
                 }
 2113  
             }
 2114  0
             namespaceUri[ namespaceEnd ] = ns;
 2115  
 
 2116  
             // detect duplicate namespace declarations!!!
 2117  0
             final int startNs = elNamespaceCount[ depth - 1 ];
 2118  0
             for (int i = namespaceEnd - 1; i >= startNs; --i)
 2119  
             {
 2120  0
                 if(((allStringsInterned || name == null) && namespacePrefix[ i ] == name)
 2121  
                        || (!allStringsInterned && name != null &&
 2122  
                                namespacePrefixHash[ i ] == prefixHash
 2123  
                                && name.equals(namespacePrefix[ i ])
 2124  
                           ))
 2125  
                 {
 2126  0
                     final String s = name == null ? "default" : "'"+name+"'";
 2127  0
                     throw new XmlPullParserException(
 2128  
                         "duplicated namespace declaration for "+s+" prefix", this, null);
 2129  
                 }
 2130  
             }
 2131  
 
 2132  0
             ++namespaceEnd;
 2133  
 
 2134  0
         } else {
 2135  0
             if(!usePC) {
 2136  0
                 attributeValue[ attributeCount ] =
 2137  
                     new String(buf, posStart, pos - 1 - posStart);
 2138  
             } else {
 2139  0
                 attributeValue[ attributeCount ] =
 2140  
                     new String(pc, pcStart, pcEnd - pcStart);
 2141  
             }
 2142  0
             ++attributeCount;
 2143  
         }
 2144  0
         posStart = prevPosStart - bufAbsoluteStart;
 2145  0
         return ch;
 2146  
     }
 2147  
 
 2148  0
     protected char[] charRefOneCharBuf = new char[1];
 2149  
 
 2150  
     protected char[] parseEntityRef()
 2151  
         throws XmlPullParserException, IOException
 2152  
     {
 2153  
         // entity reference http://www.w3.org/TR/2000/REC-xml-20001006#NT-Reference
 2154  
         // [67] Reference          ::=          EntityRef | CharRef
 2155  
 
 2156  
         // ASSUMPTION just after &
 2157  0
         entityRefName = null;
 2158  0
         posStart = pos;
 2159  0
         char ch = more();
 2160  0
         if(ch == '#') {
 2161  
             // parse character reference
 2162  0
             char charRef = 0;
 2163  0
             ch = more();
 2164  0
             if(ch == 'x') {
 2165  
                 //encoded in hex
 2166  
                 while(true) {
 2167  0
                     ch = more();
 2168  0
                     if(ch >= '0' && ch <= '9') {
 2169  0
                         charRef = (char)(charRef * 16 + (ch - '0'));
 2170  0
                     } else if(ch >= 'a' && ch <= 'f') {
 2171  0
                         charRef = (char)(charRef * 16 + (ch - ('a' - 10)));
 2172  0
                     } else if(ch >= 'A' && ch <= 'F') {
 2173  0
                         charRef = (char)(charRef * 16 + (ch - ('A' - 10)));
 2174  0
                     } else if(ch == ';') {
 2175  0
                         break;
 2176  
                     } else {
 2177  0
                         throw new XmlPullParserException(
 2178  
                             "character reference (with hex value) may not contain "
 2179  
                                 +printable(ch), this, null);
 2180  
                     }
 2181  
                 }
 2182  
             } else {
 2183  
                 // encoded in decimal
 2184  
                 while(true) {
 2185  0
                     if(ch >= '0' && ch <= '9') {
 2186  0
                         charRef = (char)(charRef * 10 + (ch - '0'));
 2187  0
                     } else if(ch == ';') {
 2188  0
                         break;
 2189  
                     } else {
 2190  0
                         throw new XmlPullParserException(
 2191  
                             "character reference (with decimal value) may not contain "
 2192  
                                 +printable(ch), this, null);
 2193  
                     }
 2194  0
                     ch = more();
 2195  
                 }
 2196  
             }
 2197  0
             posEnd = pos - 1;
 2198  0
             charRefOneCharBuf[0] = charRef;
 2199  0
             if(tokenize) {
 2200  0
                 text = newString(charRefOneCharBuf, 0, 1);
 2201  
             }
 2202  0
             return charRefOneCharBuf;
 2203  
         } else {
 2204  
             // [68]     EntityRef          ::=          '&' Name ';'
 2205  
             // scan anem until ;
 2206  0
             if(!isNameStartChar(ch)) {
 2207  0
                 throw new XmlPullParserException(
 2208  
                     "entity reference names can not start with character '"
 2209  
                         +printable(ch)+"'", this, null);
 2210  
             }
 2211  
             while(true) {
 2212  0
                 ch = more();
 2213  0
                 if(ch == ';') {
 2214  0
                     break;
 2215  
                 }
 2216  0
                 if(!isNameChar(ch)) {
 2217  0
                     throw new XmlPullParserException(
 2218  
                         "entity reference name can not contain character "
 2219  
                             +printable(ch)+"'", this, null);
 2220  
                 }
 2221  
             }
 2222  0
             posEnd = pos - 1;
 2223  
             // determine what name maps to
 2224  0
             final int len = posEnd - posStart;
 2225  0
             if(len == 2 && buf[posStart] == 'l' && buf[posStart+1] == 't') {
 2226  0
                 if(tokenize) {
 2227  0
                     text = "<";
 2228  
                 }
 2229  0
                 charRefOneCharBuf[0] = '<';
 2230  0
                 return charRefOneCharBuf;
 2231  
                 //if(paramPC || isParserTokenizing) {
 2232  
                 //    if(pcEnd >= pc.length) ensurePC();
 2233  
                 //   pc[pcEnd++] = '<';
 2234  
                 //}
 2235  0
             } else if(len == 3 && buf[posStart] == 'a'
 2236  
                           && buf[posStart+1] == 'm' && buf[posStart+2] == 'p') {
 2237  0
                 if(tokenize) {
 2238  0
                     text = "&";
 2239  
                 }
 2240  0
                 charRefOneCharBuf[0] = '&';
 2241  0
                 return charRefOneCharBuf;
 2242  0
             } else if(len == 2 && buf[posStart] == 'g' && buf[posStart+1] == 't') {
 2243  0
                 if(tokenize) {
 2244  0
                     text = ">";
 2245  
                 }
 2246  0
                 charRefOneCharBuf[0] = '>';
 2247  0
                 return charRefOneCharBuf;
 2248  0
             } else if(len == 4 && buf[posStart] == 'a' && buf[posStart+1] == 'p'
 2249  
                           && buf[posStart+2] == 'o' && buf[posStart+3] == 's')
 2250  
             {
 2251  0
                 if(tokenize) {
 2252  0
                     text = "'";
 2253  
                 }
 2254  0
                 charRefOneCharBuf[0] = '\'';
 2255  0
                 return charRefOneCharBuf;
 2256  0
             } else if(len == 4 && buf[posStart] == 'q' && buf[posStart+1] == 'u'
 2257  
                           && buf[posStart+2] == 'o' && buf[posStart+3] == 't')
 2258  
             {
 2259  0
                 if(tokenize) {
 2260  0
                     text = "\"";
 2261  
                 }
 2262  0
                 charRefOneCharBuf[0] = '"';
 2263  0
                 return charRefOneCharBuf;
 2264  
             } else {
 2265  0
                 final char[] result = lookuEntityReplacement(len);
 2266  0
                 if(result != null) {
 2267  0
                     return result;
 2268  
                 }
 2269  
             }
 2270  0
             if(tokenize) text = null;
 2271  0
             return null;
 2272  
         }
 2273  
     }
 2274  
 
 2275  
     protected char[] lookuEntityReplacement(int entitNameLen)
 2276  
         throws XmlPullParserException, IOException
 2277  
 
 2278  
     {
 2279  0
         if(!allStringsInterned) {
 2280  0
             final int hash = fastHash(buf, posStart, posEnd - posStart);
 2281  
             LOOP:
 2282  0
             for (int i = entityEnd - 1; i >= 0; --i)
 2283  
             {
 2284  0
                 if(hash == entityNameHash[ i ] && entitNameLen == entityNameBuf[ i ].length) {
 2285  0
                     final char[] entityBuf = entityNameBuf[ i ];
 2286  0
                     for (int j = 0; j < entitNameLen; j++)
 2287  
                     {
 2288  0
                         if(buf[posStart + j] != entityBuf[j]) continue LOOP;
 2289  
                     }
 2290  0
                     if(tokenize) text = entityReplacement[ i ];
 2291  0
                     return entityReplacementBuf[ i ];
 2292  
                 }
 2293  
             }
 2294  0
         } else {
 2295  0
             entityRefName = newString(buf, posStart, posEnd - posStart);
 2296  0
             for (int i = entityEnd - 1; i >= 0; --i)
 2297  
             {
 2298  
                 // take advantage that interning for newStirng is enforced
 2299  0
                 if(entityRefName == entityName[ i ]) {
 2300  0
                     if(tokenize) text = entityReplacement[ i ];
 2301  0
                     return entityReplacementBuf[ i ];
 2302  
                 }
 2303  
             }
 2304  
         }
 2305  0
         return null;
 2306  
     }
 2307  
 
 2308  
 
 2309  
     protected void parseComment()
 2310  
         throws XmlPullParserException, IOException
 2311  
     {
 2312  
         // implements XML 1.0 Section 2.5 Comments
 2313  
 
 2314  
         //ASSUMPTION: seen <!-
 2315  0
         char ch = more();
 2316  0
         if(ch != '-') throw new XmlPullParserException(
 2317  
                 "expected <!-- for comment start", this, null);
 2318  0
         if(tokenize) posStart = pos;
 2319  
 
 2320  0
         final int curLine = lineNumber;
 2321  0
         final int curColumn = columnNumber;
 2322  
         try {
 2323  0
             final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
 2324  0
             boolean normalizedCR = false;
 2325  
 
 2326  0
             boolean seenDash = false;
 2327  0
             boolean seenDashDash = false;
 2328  
             while(true) {
 2329  
                 // scan until it hits -->
 2330  0
                 ch = more();
 2331  0
                 if(seenDashDash && ch != '>') {
 2332  0
                     throw new XmlPullParserException(
 2333  
                         "in comment after two dashes (--) next character must be >"
 2334  
                             +" not "+printable(ch), this, null);
 2335  
                 }
 2336  0
                 if(ch == '-') {
 2337  0
                     if(!seenDash) {
 2338  0
                         seenDash = true;
 2339  
                     } else {
 2340  0
                         seenDashDash = true;
 2341  0
                         seenDash = false;
 2342  
                     }
 2343  0
                 } else if(ch == '>') {
 2344  0
                     if(seenDashDash) {
 2345  0
                         break;  // found end sequence!!!!
 2346  
                     } else {
 2347  0
                         seenDashDash = false;
 2348  
                     }
 2349  0
                     seenDash = false;
 2350  
                 } else {
 2351  0
                     seenDash = false;
 2352  
                 }
 2353  0
                 if(normalizeIgnorableWS) {
 2354  0
                     if(ch == '\r') {
 2355  0
                         normalizedCR = true;
 2356  
                         //posEnd = pos -1;
 2357  
                         //joinPC();
 2358  
                         // posEnd is alreadys set
 2359  0
                         if(!usePC) {
 2360  0
                             posEnd = pos -1;
 2361  0
                             if(posEnd > posStart) {
 2362  0
                                 joinPC();
 2363  
                             } else {
 2364  0
                                 usePC = true;
 2365  0
                                 pcStart = pcEnd = 0;
 2366  
                             }
 2367  
                         }
 2368  
                         //assert usePC == true;
 2369  0
                         if(pcEnd >= pc.length) ensurePC(pcEnd);
 2370  0
                         pc[pcEnd++] = '\n';
 2371  0
                     } else if(ch == '\n') {
 2372  0
                         if(!normalizedCR && usePC) {
 2373  0
                             if(pcEnd >= pc.length) ensurePC(pcEnd);
 2374  0
                             pc[pcEnd++] = '\n';
 2375  
                         }
 2376  0
                         normalizedCR = false;
 2377  
                     } else {
 2378  0
                         if(usePC) {
 2379  0
                             if(pcEnd >= pc.length) ensurePC(pcEnd);
 2380  0
                             pc[pcEnd++] = ch;
 2381  
                         }
 2382  0
                         normalizedCR = false;
 2383  
                     }
 2384  
                 }
 2385  
             }
 2386  
 
 2387  0
         } catch(EOFException ex) {
 2388  
             // detect EOF and create meaningful error ...
 2389  0
             throw new XmlPullParserException(
 2390  
                 "comment started on line "+curLine+" and column "+curColumn+" was not closed",
 2391  
                 this, ex);
 2392  0
         }
 2393  0
         if(tokenize) {
 2394  0
             posEnd = pos - 3;
 2395  0
             if(usePC) {
 2396  0
                 pcEnd -= 2;
 2397  
             }
 2398  
         }
 2399  0
     }
 2400  
 
 2401  
     protected boolean parsePI()
 2402  
         throws XmlPullParserException, IOException
 2403  
     {
 2404  
         // implements XML 1.0 Section 2.6 Processing Instructions
 2405  
 
 2406  
         // [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
 2407  
         // [17] PITarget         ::=    Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
 2408  
         //ASSUMPTION: seen <?
 2409  0
         if(tokenize) posStart = pos;
 2410  0
         final int curLine = lineNumber;
 2411  0
         final int curColumn = columnNumber;
 2412  0
         int piTargetStart = pos + bufAbsoluteStart;
 2413  0
         int piTargetEnd = -1;
 2414  0
         final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
 2415  0
         boolean normalizedCR = false;
 2416  
 
 2417  
         try {
 2418  0
             boolean seenQ = false;
 2419  0
             char ch = more();
 2420  0
             if(isS(ch)) {
 2421  0
                 throw new XmlPullParserException(
 2422  
                     "processing instruction PITarget must be exactly after <? and not white space character",
 2423  
                     this, null);
 2424  
             }
 2425  
             while(true) {
 2426  
                 // scan until it hits ?>
 2427  
                 //ch = more();
 2428  
 
 2429  0
                 if(ch == '?') {
 2430  0
                     seenQ = true;
 2431  0
                 } else if(ch == '>') {
 2432  0
                     if(seenQ) {
 2433  0
                         break;  // found end sequence!!!!
 2434  
                     }
 2435  0
                     seenQ = false;
 2436  
                 } else {
 2437  0
                     if(piTargetEnd == -1 && isS(ch)) {
 2438  0
                         piTargetEnd = pos - 1 + bufAbsoluteStart;
 2439  
 
 2440  
                         // [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
 2441  0
                         if((piTargetEnd - piTargetStart) == 3) {
 2442  0
                             if((buf[piTargetStart] == 'x' || buf[piTargetStart] == 'X')
 2443  
                                    && (buf[piTargetStart+1] == 'm' || buf[piTargetStart+1] == 'M')
 2444  
                                    && (buf[piTargetStart+2] == 'l' || buf[piTargetStart+2] == 'L')
 2445  
                               )
 2446  
                             {
 2447  0
                                 if(piTargetStart > 3) {  //<?xml is allowed as first characters in input ...
 2448  0
                                     throw new XmlPullParserException(
 2449  
                                         "processing instruction can not have PITarget with reserveld xml name",
 2450  
                                         this, null);
 2451  
                                 } else {
 2452  0
                                     if(buf[piTargetStart] != 'x'
 2453  
                                            && buf[piTargetStart+1] != 'm'
 2454  
                                            && buf[piTargetStart+2] != 'l')
 2455  
                                     {
 2456  0
                                         throw new XmlPullParserException(
 2457  
                                             "XMLDecl must have xml name in lowercase",
 2458  
                                             this, null);
 2459  
                                     }
 2460  
                                 }
 2461  0
                                 parseXmlDecl(ch);
 2462  0
                                 if(tokenize) posEnd = pos - 2;
 2463  0
                                 final int off = piTargetStart - bufAbsoluteStart + 3;
 2464  0
                                 final int len = pos - 2 - off;
 2465  0
                                 xmlDeclContent = newString(buf, off, len);
 2466  0
                                 return false;
 2467  
                             }
 2468  
                         }
 2469  
                     }
 2470  0
                     seenQ = false;
 2471  
                 }
 2472  0
                 if(normalizeIgnorableWS) {
 2473  0
                     if(ch == '\r') {
 2474  0
                         normalizedCR = true;
 2475  
                         //posEnd = pos -1;
 2476  
                         //joinPC();
 2477  
                         // posEnd is alreadys set
 2478  0
                         if(!usePC) {
 2479  0
                             posEnd = pos -1;
 2480  0
                             if(posEnd > posStart) {
 2481  0
                                 joinPC();
 2482  
                             } else {
 2483  0
                                 usePC = true;
 2484  0
                                 pcStart = pcEnd = 0;
 2485  
                             }
 2486  
                         }
 2487  
                         //assert usePC == true;
 2488  0
                         if(pcEnd >= pc.length) ensurePC(pcEnd);
 2489  0
                         pc[pcEnd++] = '\n';
 2490  0
                     } else if(ch == '\n') {
 2491  0
                         if(!normalizedCR && usePC) {
 2492  0
                             if(pcEnd >= pc.length) ensurePC(pcEnd);
 2493  0
                             pc[pcEnd++] = '\n';
 2494  
                         }
 2495  0
                         normalizedCR = false;
 2496  
                     } else {
 2497  0
                         if(usePC) {
 2498  0
                             if(pcEnd >= pc.length) ensurePC(pcEnd);
 2499  0
                             pc[pcEnd++] = ch;
 2500  
                         }
 2501  0
                         normalizedCR = false;
 2502  
                     }
 2503  
                 }
 2504  0
                 ch = more();
 2505  
             }
 2506  0
         } catch(EOFException ex) {
 2507  
             // detect EOF and create meaningful error ...
 2508  0
             throw new XmlPullParserException(
 2509  
                 "processing instruction started on line "+curLine+" and column "+curColumn
 2510  
                     +" was not closed",
 2511  
                 this, ex);
 2512  0
         }
 2513  0
         if(piTargetEnd == -1) {
 2514  0
             piTargetEnd = pos - 2 + bufAbsoluteStart;
 2515  
             //throw new XmlPullParserException(
 2516  
             //    "processing instruction must have PITarget name", this, null);
 2517  
         }
 2518  0
         piTargetStart -= bufAbsoluteStart;
 2519  0
         piTargetEnd -= bufAbsoluteStart;
 2520  0
         if(tokenize) {
 2521  0
             posEnd = pos - 2;
 2522  0
             if(normalizeIgnorableWS) {
 2523  0
                 --pcEnd;
 2524  
             }
 2525  
         }
 2526  0
         return true;
 2527  
     }
 2528  
 
 2529  
     //    protected final static char[] VERSION = {'v','e','r','s','i','o','n'};
 2530  
     //    protected final static char[] NCODING = {'n','c','o','d','i','n','g'};
 2531  
     //    protected final static char[] TANDALONE = {'t','a','n','d','a','l','o','n','e'};
 2532  
     //    protected final static char[] YES = {'y','e','s'};
 2533  
     //    protected final static char[] NO = {'n','o'};
 2534  
 
 2535  0
     protected final static char[] VERSION = "version".toCharArray();
 2536  0
     protected final static char[] NCODING = "ncoding".toCharArray();
 2537  0
     protected final static char[] TANDALONE = "tandalone".toCharArray();
 2538  0
     protected final static char[] YES = "yes".toCharArray();
 2539  0
     protected final static char[] NO = "no".toCharArray();
 2540  
 
 2541  
 
 2542  
 
 2543  
     protected void parseXmlDecl(char ch)
 2544  
         throws XmlPullParserException, IOException
 2545  
     {
 2546  
         // [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
 2547  
 
 2548  
         // first make sure that relative positions will stay OK
 2549  0
         preventBufferCompaction = true;
 2550  0
         bufStart = 0; // necessary to keep pos unchanged during expansion!
 2551  
 
 2552  
         // --- parse VersionInfo
 2553  
 
 2554  
         // [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
 2555  
         // parse is positioned just on first S past <?xml
 2556  0
         ch = skipS(ch);
 2557  0
         ch = requireInput(ch, VERSION);
 2558  
         // [25] Eq ::= S? '=' S?
 2559  0
         ch = skipS(ch);
 2560  0
         if(ch != '=') {
 2561  0
             throw new XmlPullParserException(
 2562  
                 "expected equals sign (=) after version and not "+printable(ch), this, null);
 2563  
         }
 2564  0
         ch = more();
 2565  0
         ch = skipS(ch);
 2566  0
         if(ch != '\'' && ch != '"') {
 2567  0
             throw new XmlPullParserException(
 2568  
                 "expected apostrophe (') or quotation mark (\") after version and not "
 2569  
                     +printable(ch), this, null);
 2570  
         }
 2571  0
         final char quotChar = ch;
 2572  
         //int versionStart = pos + bufAbsoluteStart;  // required if preventBufferCompaction==false
 2573  0
         final int versionStart = pos;
 2574  0
         ch = more();
 2575  
         // [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
 2576  0
         while(ch != quotChar) {
 2577  0
             if((ch  < 'a' || ch > 'z') && (ch  < 'A' || ch > 'Z') && (ch  < '0' || ch > '9')
 2578  
                    && ch != '_' && ch != '.' && ch != ':' && ch != '-')
 2579  
             {
 2580  0
                 throw new XmlPullParserException(
 2581  
                     "<?xml version value expected to be in ([a-zA-Z0-9_.:] | '-')"
 2582  
                         +" not "+printable(ch), this, null);
 2583  
             }
 2584  0
             ch = more();
 2585  
         }
 2586  0
         final int versionEnd = pos - 1;
 2587  0
         parseXmlDeclWithVersion(versionStart, versionEnd);
 2588  0
         preventBufferCompaction = false; // allow again buffer commpaction - pos MAY chnage
 2589  0
     }
 2590  
     //protected String xmlDeclVersion;
 2591  
 
 2592  
     protected void parseXmlDeclWithVersion(int versionStart, int versionEnd)
 2593  
         throws XmlPullParserException, IOException
 2594  
     {
 2595  
         // check version is "1.0"
 2596  0
         if((versionEnd - versionStart != 3)
 2597  
                || buf[versionStart] != '1'
 2598  
                || buf[versionStart+1] != '.'
 2599  
                || buf[versionStart+2] != '0')
 2600  
         {
 2601  0
             throw new XmlPullParserException(
 2602  
                 "only 1.0 is supported as <?xml version not '"
 2603  
                     +printable(new String(buf, versionStart, versionEnd - versionStart))+"'", this, null);
 2604  
         }
 2605  0
         xmlDeclVersion = newString(buf, versionStart, versionEnd - versionStart);
 2606  
 
 2607  
         // [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
 2608  0
         char ch = more();
 2609  0
         ch = skipS(ch);
 2610  0
         if(ch == 'e') {
 2611  0
             ch = more();
 2612  0
             ch = requireInput(ch, NCODING);
 2613  0
             ch = skipS(ch);
 2614  0
             if(ch != '=') {
 2615  0
                 throw new XmlPullParserException(
 2616  
                     "expected equals sign (=) after encoding and not "+printable(ch), this, null);
 2617  
             }
 2618  0
             ch = more();
 2619  0
             ch = skipS(ch);
 2620  0
             if(ch != '\'' && ch != '"') {
 2621  0
                 throw new XmlPullParserException(
 2622  
                     "expected apostrophe (') or quotation mark (\") after encoding and not "
 2623  
                         +printable(ch), this, null);
 2624  
             }
 2625  0
             final char quotChar = ch;
 2626  0
             final int encodingStart = pos;
 2627  0
             ch = more();
 2628  
             // [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
 2629  0
             if((ch  < 'a' || ch > 'z') && (ch  < 'A' || ch > 'Z'))
 2630  
             {
 2631  0
                 throw new XmlPullParserException(
 2632  
                     "<?xml encoding name expected to start with [A-Za-z]"
 2633  
                         +" not "+printable(ch), this, null);
 2634  
             }
 2635  0
             ch = more();
 2636  0
             while(ch != quotChar) {
 2637  0
                 if((ch  < 'a' || ch > 'z') && (ch  < 'A' || ch > 'Z') && (ch  < '0' || ch > '9')
 2638  
                        && ch != '.' && ch != '_' && ch != '-')
 2639  
                 {
 2640  0
                     throw new XmlPullParserException(
 2641  
                         "<?xml encoding value expected to be in ([A-Za-z0-9._] | '-')"
 2642  
                             +" not "+printable(ch), this, null);
 2643  
                 }
 2644  0
                 ch = more();
 2645  
             }
 2646  0
             final int encodingEnd = pos - 1;
 2647  
 
 2648  
 
 2649  
             // TODO reconcile with setInput encodingName
 2650  0
             inputEncoding = newString(buf, encodingStart, encodingEnd - encodingStart);
 2651  0
             ch = more();
 2652  
         }
 2653  
 
 2654  0
         ch = skipS(ch);
 2655  
         // [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"'))
 2656  0
         if(ch == 's') {
 2657  0
             ch = more();
 2658  0
             ch = requireInput(ch, TANDALONE);
 2659  0
             ch = skipS(ch);
 2660  0
             if(ch != '=') {
 2661  0
                 throw new XmlPullParserException(
 2662  
                     "expected equals sign (=) after standalone and not "+printable(ch),
 2663  
                     this, null);
 2664  
             }
 2665  0
             ch = more();
 2666  0
             ch = skipS(ch);
 2667  0
             if(ch != '\'' && ch != '"') {
 2668  0
                 throw new XmlPullParserException(
 2669  
                     "expected apostrophe (') or quotation mark (\") after encoding and not "
 2670  
                         +printable(ch), this, null);
 2671  
             }
 2672  0
             char quotChar = ch;
 2673  0
             int standaloneStart = pos;
 2674  0
             ch = more();
 2675  0
             if(ch == 'y') {
 2676  0
                 ch = requireInput(ch, YES);
 2677  
                 //Boolean standalone = new Boolean(true);
 2678  0
                 xmlDeclStandalone = true;
 2679  0
             } else if(ch == 'n') {
 2680  0
                 ch = requireInput(ch, NO);
 2681  
                 //Boolean standalone = new Boolean(false);
 2682  0
                 xmlDeclStandalone = false;
 2683  
             } else {
 2684  0
                 throw new XmlPullParserException(
 2685  
                     "expected 'yes' or 'no' after standalone and not "
 2686  
                         +printable(ch), this, null);
 2687  
             }
 2688  0
             if(ch != quotChar) {
 2689  0
                 throw new XmlPullParserException(
 2690  
                     "expected "+quotChar+" after standalone value not "
 2691  
                         +printable(ch), this, null);
 2692  
             }
 2693  0
             ch = more();
 2694  
         }
 2695  
 
 2696  
 
 2697  0
         ch = skipS(ch);
 2698  0
         if(ch != '?') {
 2699  0
             throw new XmlPullParserException(
 2700  
                 "expected ?> as last part of <?xml not "
 2701  
                     +printable(ch), this, null);
 2702  
         }
 2703  0
         ch = more();
 2704  0
         if(ch != '>') {
 2705  0
             throw new XmlPullParserException(
 2706  
                 "expected ?> as last part of <?xml not "
 2707  
                     +printable(ch), this, null);
 2708  
         }
 2709  
 
 2710  0
     }
 2711  
     protected void parseDocdecl()
 2712  
         throws XmlPullParserException, IOException
 2713  
     {
 2714  
         //ASSUMPTION: seen <!D
 2715  0
         char ch = more();
 2716  0
         if(ch != 'O') throw new XmlPullParserException(
 2717  
                 "expected <!DOCTYPE", this, null);
 2718  0
         ch = more();
 2719  0
         if(ch != 'C') throw new XmlPullParserException(
 2720  
                 "expected <!DOCTYPE", this, null);
 2721  0
         ch = more();
 2722  0
         if(ch != 'T') throw new XmlPullParserException(
 2723  
                 "expected <!DOCTYPE", this, null);
 2724  0
         ch = more();
 2725  0
         if(ch != 'Y') throw new XmlPullParserException(
 2726  
                 "expected <!DOCTYPE", this, null);
 2727  0
         ch = more();
 2728  0
         if(ch != 'P') throw new XmlPullParserException(
 2729  
                 "expected <!DOCTYPE", this, null);
 2730  0
         ch = more();
 2731  0
         if(ch != 'E') throw new XmlPullParserException(
 2732  
                 "expected <!DOCTYPE", this, null);
 2733  0
         posStart = pos;
 2734  
         // do simple and crude scanning for end of doctype
 2735  
 
 2736  
         // [28]  doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('['
 2737  
         //                      (markupdecl | DeclSep)* ']' S?)? '>'
 2738  0
         int bracketLevel = 0;
 2739  0
         final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
 2740  0
         boolean normalizedCR = false;
 2741  
         while(true) {
 2742  0
             ch = more();
 2743  0
             if(ch == '[') ++bracketLevel;
 2744  0
             if(ch == ']') --bracketLevel;
 2745  0
             if(ch == '>' && bracketLevel == 0) break;
 2746  0
             if(normalizeIgnorableWS) {
 2747  0
                 if(ch == '\r') {
 2748  0
                     normalizedCR = true;
 2749  
                     //posEnd = pos -1;
 2750  
                     //joinPC();
 2751  
                     // posEnd is alreadys set
 2752  0
                     if(!usePC) {
 2753  0
                         posEnd = pos -1;
 2754  0
                         if(posEnd > posStart) {
 2755  0
                             joinPC();
 2756  
                         } else {
 2757  0
                             usePC = true;
 2758  0
                             pcStart = pcEnd = 0;
 2759  
                         }
 2760  
                     }
 2761  
                     //assert usePC == true;
 2762  0
                     if(pcEnd >= pc.length) ensurePC(pcEnd);
 2763  0
                     pc[pcEnd++] = '\n';
 2764  0
                 } else if(ch == '\n') {
 2765  0
                     if(!normalizedCR && usePC) {
 2766  0
                         if(pcEnd >= pc.length) ensurePC(pcEnd);
 2767  0
                         pc[pcEnd++] = '\n';
 2768  
                     }
 2769  0
                     normalizedCR = false;
 2770  
                 } else {
 2771  0
                     if(usePC) {
 2772  0
                         if(pcEnd >= pc.length) ensurePC(pcEnd);
 2773  0
                         pc[pcEnd++] = ch;
 2774  
                     }
 2775  0
                     normalizedCR = false;
 2776  
                 }
 2777  
             }
 2778  
 
 2779  
         }
 2780  0
         posEnd = pos - 1;
 2781  0
     }
 2782  
 
 2783  
     protected void parseCDSect(boolean hadCharData)
 2784  
         throws XmlPullParserException, IOException
 2785  
     {
 2786  
         // implements XML 1.0 Section 2.7 CDATA Sections
 2787  
 
 2788  
         // [18] CDSect ::= CDStart CData CDEnd
 2789  
         // [19] CDStart ::=  '<![CDATA['
 2790  
         // [20] CData ::= (Char* - (Char* ']]>' Char*))
 2791  
         // [21] CDEnd ::= ']]>'
 2792  
 
 2793  
         //ASSUMPTION: seen <![
 2794  0
         char ch = more();
 2795  0
         if(ch != 'C') throw new XmlPullParserException(
 2796  
                 "expected <[CDATA[ for comment start", this, null);
 2797  0
         ch = more();
 2798  0
         if(ch != 'D') throw new XmlPullParserException(
 2799  
                 "expected <[CDATA[ for comment start", this, null);
 2800  0
         ch = more();
 2801  0
         if(ch != 'A') throw new XmlPullParserException(
 2802  
                 "expected <[CDATA[ for comment start", this, null);
 2803  0
         ch = more();
 2804  0
         if(ch != 'T') throw new XmlPullParserException(
 2805  
                 "expected <[CDATA[ for comment start", this, null);
 2806  0
         ch = more();
 2807  0
         if(ch != 'A') throw new XmlPullParserException(
 2808  
                 "expected <[CDATA[ for comment start", this, null);
 2809  0
         ch = more();
 2810  0
         if(ch != '[') throw new XmlPullParserException(
 2811  
                 "expected <![CDATA[ for comment start", this, null);
 2812  
 
 2813  
         //if(tokenize) {
 2814  0
         final int cdStart = pos + bufAbsoluteStart;
 2815  0
         final int curLine = lineNumber;
 2816  0
         final int curColumn = columnNumber;
 2817  0
         final boolean normalizeInput = tokenize == false || roundtripSupported == false;
 2818  
         try {
 2819  0
             if(normalizeInput) {
 2820  0
                 if(hadCharData) {
 2821  0
                     if(!usePC) {
 2822  
                         // posEnd is correct already!!!
 2823  0
                         if(posEnd > posStart) {
 2824  0
                             joinPC();
 2825  
                         } else {
 2826  0
                             usePC = true;
 2827  0
                             pcStart = pcEnd = 0;
 2828  
                         }
 2829  
                     }
 2830  
                 }
 2831  
             }
 2832  0
             boolean seenBracket = false;
 2833  0
             boolean seenBracketBracket = false;
 2834  0
             boolean normalizedCR = false;
 2835  
             while(true) {
 2836  
                 // scan until it hits "]]>"
 2837  0
                 ch = more();
 2838  0
                 if(ch == ']') {
 2839  0
                     if(!seenBracket) {
 2840  0
                         seenBracket = true;
 2841  
                     } else {
 2842  0
                         seenBracketBracket = true;
 2843  
                         //seenBracket = false;
 2844  
                     }
 2845  0
                 } else if(ch == '>') {
 2846  0
                     if(seenBracket && seenBracketBracket) {
 2847  0
                         break;  // found end sequence!!!!
 2848  
                     } else {
 2849  0
                         seenBracketBracket = false;
 2850  
                     }
 2851  0
                     seenBracket = false;
 2852  
                 } else {
 2853  0
                     if(seenBracket) {
 2854  0
                         seenBracket = false;
 2855  
                     }
 2856  
                 }
 2857  0
                 if(normalizeInput) {
 2858  
                     // deal with normalization issues ...
 2859  0
                     if(ch == '\r') {
 2860  0
                         normalizedCR = true;
 2861  0
                         posStart = cdStart - bufAbsoluteStart;
 2862  0
                         posEnd = pos - 1; // posEnd is alreadys set
 2863  0
                         if(!usePC) {
 2864  0
                             if(posEnd > posStart) {
 2865  0
                                 joinPC();
 2866  
                             } else {
 2867  0
                                 usePC = true;
 2868  0
                                 pcStart = pcEnd = 0;
 2869  
                             }
 2870  
                         }
 2871  
                         //assert usePC == true;
 2872  0
                         if(pcEnd >= pc.length) ensurePC(pcEnd);
 2873  0
                         pc[pcEnd++] = '\n';
 2874  0
                     } else if(ch == '\n') {
 2875  0
                         if(!normalizedCR && usePC) {
 2876  0
                             if(pcEnd >= pc.length) ensurePC(pcEnd);
 2877  0
                             pc[pcEnd++] = '\n';
 2878  
                         }
 2879  0
                         normalizedCR = false;
 2880  
                     } else {
 2881  0
                         if(usePC) {
 2882  0
                             if(pcEnd >= pc.length) ensurePC(pcEnd);
 2883  0
                             pc[pcEnd++] = ch;
 2884  
                         }
 2885  0
                         normalizedCR = false;
 2886  
                     }
 2887  
                 }
 2888  
             }
 2889  0
         } catch(EOFException ex) {
 2890  
             // detect EOF and create meaningful error ...
 2891  0
             throw new XmlPullParserException(
 2892  
                 "CDATA section started on line "+curLine+" and column "+curColumn+" was not closed",
 2893  
                 this, ex);
 2894  0
         }
 2895  0
         if(normalizeInput) {
 2896  0
             if(usePC) {
 2897  0
                 pcEnd = pcEnd - 2;
 2898  
             }
 2899  
         }
 2900  0
         posStart = cdStart - bufAbsoluteStart;
 2901  0
         posEnd = pos - 3;
 2902  0
     }
 2903  
 
 2904  
     protected void fillBuf() throws IOException, XmlPullParserException {
 2905  0
         if(reader == null) throw new XmlPullParserException(
 2906  
                 "reader must be set before parsing is started");
 2907  
 
 2908  
         // see if we are in compaction area
 2909  0
         if(bufEnd > bufSoftLimit) {
 2910  
 
 2911  
             // expand buffer it makes sense!!!!
 2912  0
             boolean compact = bufStart > bufSoftLimit;
 2913  0
             boolean expand = false;
 2914  0
             if(preventBufferCompaction) {
 2915  0
                 compact = false;
 2916  0
                 expand = true;
 2917  0
             } else if(!compact) {
 2918  
                 //freeSpace
 2919  0
                 if(bufStart < buf.length / 2) {
 2920  
                     // less then half buffer available forcompactin --> expand instead!!!
 2921  0
                     expand = true;
 2922  
                 } else {
 2923  
                     // at least half of buffer can be reclaimed --> worthwhile effort!!!
 2924  0
                     compact = true;
 2925  
                 }
 2926  
             }
 2927  
 
 2928  
             // if buffer almost full then compact it
 2929  0
             if(compact) {
 2930  
                 //TODO: look on trashing
 2931  
                 // //assert bufStart > 0
 2932  0
                 System.arraycopy(buf, bufStart, buf, 0, bufEnd - bufStart);
 2933  
                 if(TRACE_SIZING) System.out.println(
 2934  
                         "TRACE_SIZING fillBuf() compacting "+bufStart
 2935  
                             +" bufEnd="+bufEnd
 2936  
                             +" pos="+pos+" posStart="+posStart+" posEnd="+posEnd
 2937  
                             +" buf first 100 chars:"+new String(buf, bufStart,
 2938  
                                                                 bufEnd - bufStart < 100 ? bufEnd - bufStart : 100 ));
 2939  
 
 2940  0
             } else if(expand) {
 2941  0
                 final int newSize = 2 * buf.length;
 2942  0
                 final char newBuf[] = new char[ newSize ];
 2943  
                 if(TRACE_SIZING) System.out.println("TRACE_SIZING fillBuf() "+buf.length+" => "+newSize);
 2944  0
                 System.arraycopy(buf, bufStart, newBuf, 0, bufEnd - bufStart);
 2945  0
                 buf = newBuf;
 2946  0
                 if(bufLoadFactor > 0) {
 2947  0
                     bufSoftLimit = ( bufLoadFactor * buf.length ) /100;
 2948  
                 }
 2949  
 
 2950  0
             } else {
 2951  0
                 throw new XmlPullParserException("internal error in fillBuffer()");
 2952  
             }
 2953  0
             bufEnd -= bufStart;
 2954  0
             pos -= bufStart;
 2955  0
             posStart -= bufStart;
 2956  0
             posEnd -= bufStart;
 2957  0
             bufAbsoluteStart += bufStart;
 2958  0
             bufStart = 0;
 2959  
             if(TRACE_SIZING) System.out.println(
 2960  
                     "TRACE_SIZING fillBuf() after bufEnd="+bufEnd
 2961  
                         +" pos="+pos+" posStart="+posStart+" posEnd="+posEnd
 2962  
                         +" buf first 100 chars:"+new String(buf, 0, bufEnd < 100 ? bufEnd : 100));
 2963  
         }
 2964  
         // at least one charcter must be read or error
 2965  0
         final int len = buf.length - bufEnd > READ_CHUNK_SIZE ? READ_CHUNK_SIZE : buf.length - bufEnd;
 2966  0
         final int ret = reader.read(buf, bufEnd, len);
 2967  0
         if(ret > 0) {
 2968  0
             bufEnd += ret;
 2969  
             if(TRACE_SIZING) System.out.println(
 2970  
                     "TRACE_SIZING fillBuf() after filling in buffer"
 2971  
                         +" buf first 100 chars:"+new String(buf, 0, bufEnd < 100 ? bufEnd : 100));
 2972  
 
 2973  0
             return;
 2974  
         }
 2975  0
         if(ret == -1) {
 2976  0
             if(bufAbsoluteStart == 0 && pos == 0) {
 2977  0
                 throw new EOFException("input contained no data");
 2978  
             } else {
 2979  0
                 if(seenRoot && depth == 0) { // inside parsing epilog!!!
 2980  0
                     reachedEnd = true;
 2981  0
                     return;
 2982  
                 } else {
 2983  0
                     StringBuilder expectedTagStack = new StringBuilder();
 2984  0
                     if(depth > 0) {
 2985  
                         //final char[] cbuf = elRawName[depth];
 2986  
                         //final String startname = new String(cbuf, 0, elRawNameEnd[depth]);
 2987  0
                         expectedTagStack.append(" - expected end tag");
 2988  0
                         if(depth > 1) {
 2989  0
                             expectedTagStack.append("s"); //more than one end tag
 2990  
                         }
 2991  0
                         expectedTagStack.append(" ");
 2992  0
                         for (int i = depth; i > 0; i--)
 2993  
                         {
 2994  0
                             String tagName = new String(elRawName[i], 0, elRawNameEnd[i]);
 2995  0
                             expectedTagStack.append("</").append(tagName).append('>');
 2996  
                         }
 2997  0
                         expectedTagStack.append(" to close");
 2998  0
                         for (int i = depth; i > 0; i--)
 2999  
                         {
 3000  0
                             if(i != depth) {
 3001  0
                                 expectedTagStack.append(" and"); //more than one end tag
 3002  
                             }
 3003  0
                             String tagName = new String(elRawName[i], 0, elRawNameEnd[i]);
 3004  0
                             expectedTagStack.append(" start tag <"+tagName+">");
 3005  0
                             expectedTagStack.append(" from line "+elRawNameLine[i]);
 3006  
                         }
 3007  0
                         expectedTagStack.append(", parser stopped on");
 3008  
                     }
 3009  0
                     throw new EOFException("no more data available"
 3010  
                                                +expectedTagStack.toString()+getPositionDescription());
 3011  
                 }
 3012  
             }
 3013  
         } else {
 3014  0
             throw new IOException("error reading input, returned "+ret);
 3015  
         }
 3016  
     }
 3017  
 
 3018  
     protected char more() throws IOException, XmlPullParserException {
 3019  0
         if(pos >= bufEnd) {
 3020  0
             fillBuf();
 3021  
             // this return value should be ignonored as it is used in epilog parsing ...
 3022  0
             if(reachedEnd) return (char)-1;
 3023  
         }
 3024  0
         final char ch = buf[pos++];
 3025  
         //line/columnNumber
 3026  0
         if(ch == '\n') { ++lineNumber; columnNumber = 1; }
 3027  0
         else { ++columnNumber; }
 3028  
         //System.out.print(ch);
 3029  0
         return ch;
 3030  
     }
 3031  
 
 3032  
     //    /**
 3033  
     //     * This function returns position of parser in XML input stream
 3034  
     //     * (how many <b>characters</b> were processed.
 3035  
     //     * <p><b>NOTE:</b> this logical position and not byte offset as encodings
 3036  
     //     * such as UTF8 may use more than one byte to encode one character.
 3037  
     //     */
 3038  
     //    public int getCurrentInputPosition() {
 3039  
     //        return pos + bufAbsoluteStart;
 3040  
     //    }
 3041  
 
 3042  
     protected void ensurePC(int end) {
 3043  
         //assert end >= pc.length;
 3044  0
         final int newSize = end > READ_CHUNK_SIZE ? 2 * end : 2 * READ_CHUNK_SIZE;
 3045  0
         final char[] newPC = new char[ newSize ];
 3046  
         if(TRACE_SIZING) System.out.println("TRACE_SIZING ensurePC() "+pc.length+" ==> "+newSize+" end="+end);
 3047  0
         System.arraycopy(pc, 0, newPC, 0, pcEnd);
 3048  0
         pc = newPC;
 3049  
         //assert end < pc.length;
 3050  0
     }
 3051  
 
 3052  
     protected void joinPC() {
 3053  
         //assert usePC == false;
 3054  
         //assert posEnd > posStart;
 3055  0
         final int len = posEnd - posStart;
 3056  0
         final int newEnd = pcEnd + len + 1;
 3057  0
         if(newEnd >= pc.length) ensurePC(newEnd); // add 1 for extra space for one char
 3058  
         //assert newEnd < pc.length;
 3059  0
         System.arraycopy(buf, posStart, pc, pcEnd, len);
 3060  0
         pcEnd += len;
 3061  0
         usePC = true;
 3062  
 
 3063  0
     }
 3064  
 
 3065  
     protected char requireInput(char ch, char[] input)
 3066  
         throws XmlPullParserException, IOException
 3067  
     {
 3068  0
         for (char anInput : input) {
 3069  0
             if (ch != anInput) {
 3070  0
                 throw new XmlPullParserException(
 3071  
                         "expected " + printable(anInput) + " in " + new String(input)
 3072  
                                 + " and not " + printable(ch), this, null);
 3073  
             }
 3074  0
             ch = more();
 3075  
         }
 3076  0
         return ch;
 3077  
     }
 3078  
 
 3079  
     protected char requireNextS()
 3080  
         throws XmlPullParserException, IOException
 3081  
     {
 3082  0
         final char ch = more();
 3083  0
         if(!isS(ch)) {
 3084  0
             throw new XmlPullParserException(
 3085  
                 "white space is required and not "+printable(ch), this, null);
 3086  
         }
 3087  0
         return skipS(ch);
 3088  
     }
 3089  
 
 3090  
     protected char skipS(char ch)
 3091  
         throws XmlPullParserException, IOException
 3092  
     {
 3093  0
         while(isS(ch)) { ch = more(); } // skip additional spaces
 3094  0
         return ch;
 3095  
     }
 3096  
 
 3097  
     // nameStart / name lookup tables based on XML 1.1 http://www.w3.org/TR/2001/WD-xml11-20011213/
 3098  
     protected static final int LOOKUP_MAX = 0x400;
 3099  
     protected static final char LOOKUP_MAX_CHAR = (char)LOOKUP_MAX;
 3100  
     //    protected static int lookupNameStartChar[] = new int[ LOOKUP_MAX_CHAR / 32 ];
 3101  
     //    protected static int lookupNameChar[] = new int[ LOOKUP_MAX_CHAR / 32 ];
 3102  0
     protected static boolean lookupNameStartChar[] = new boolean[ LOOKUP_MAX ];
 3103  0
     protected static boolean lookupNameChar[] = new boolean[ LOOKUP_MAX ];
 3104  
 
 3105  
     private static final void setName(char ch)
 3106  
         //{ lookupNameChar[ (int)ch / 32 ] |= (1 << (ch % 32)); }
 3107  0
     { lookupNameChar[ ch ] = true; }
 3108  
     private static final void setNameStart(char ch)
 3109  
         //{ lookupNameStartChar[ (int)ch / 32 ] |= (1 << (ch % 32)); setName(ch); }
 3110  0
     { lookupNameStartChar[ ch ] = true; setName(ch); }
 3111  
 
 3112  
     static {
 3113  0
         setNameStart(':');
 3114  0
         for (char ch = 'A'; ch <= 'Z'; ++ch) setNameStart(ch);
 3115  0
         setNameStart('_');
 3116  0
         for (char ch = 'a'; ch <= 'z'; ++ch) setNameStart(ch);
 3117  0
         for (char ch = '\u00c0'; ch <= '\u02FF'; ++ch) setNameStart(ch);
 3118  0
         for (char ch = '\u0370'; ch <= '\u037d'; ++ch) setNameStart(ch);
 3119  0
         for (char ch = '\u037f'; ch < '\u0400'; ++ch) setNameStart(ch);
 3120  
 
 3121  0
         setName('-');
 3122  0
         setName('.');
 3123  0
         for (char ch = '0'; ch <= '9'; ++ch) setName(ch);
 3124  0
         setName('\u00b7');
 3125  0
         for (char ch = '\u0300'; ch <= '\u036f'; ++ch) setName(ch);
 3126  0
     }
 3127  
 
 3128  
     //private final static boolean isNameStartChar(char ch) {
 3129  
     protected boolean isNameStartChar(char ch) {
 3130  0
         return (ch < LOOKUP_MAX_CHAR && lookupNameStartChar[ ch ])
 3131  
             || (ch >= LOOKUP_MAX_CHAR && ch <= '\u2027')
 3132  
             || (ch >= '\u202A' &&  ch <= '\u218F')
 3133  
             || (ch >= '\u2800' &&  ch <= '\uFFEF')
 3134  
             ;
 3135  
 
 3136  
         //      if(ch < LOOKUP_MAX_CHAR) return lookupNameStartChar[ ch ];
 3137  
         //      else return ch <= '\u2027'
 3138  
         //              || (ch >= '\u202A' &&  ch <= '\u218F')
 3139  
         //              || (ch >= '\u2800' &&  ch <= '\uFFEF')
 3140  
         //              ;
 3141  
         //return false;
 3142  
         //        return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == ':'
 3143  
         //          || (ch >= '0' && ch <= '9');
 3144  
         //        if(ch < LOOKUP_MAX_CHAR) return (lookupNameStartChar[ (int)ch / 32 ] & (1 << (ch % 32))) != 0;
 3145  
         //        if(ch <= '\u2027') return true;
 3146  
         //        //[#x202A-#x218F]
 3147  
         //        if(ch < '\u202A') return false;
 3148  
         //        if(ch <= '\u218F') return true;
 3149  
         //        // added pairts [#x2800-#xD7FF] | [#xE000-#xFDCF] | [#xFDE0-#xFFEF] | [#x10000-#x10FFFF]
 3150  
         //        if(ch < '\u2800') return false;
 3151  
         //        if(ch <= '\uFFEF') return true;
 3152  
         //        return false;
 3153  
 
 3154  
 
 3155  
         // else return (supportXml11 && ( (ch < '\u2027') || (ch > '\u2029' && ch < '\u2200') ...
 3156  
     }
 3157  
 
 3158  
     //private final static boolean isNameChar(char ch) {
 3159  
     protected boolean isNameChar(char ch) {
 3160  
         //return isNameStartChar(ch);
 3161  
 
 3162  
         //        if(ch < LOOKUP_MAX_CHAR) return (lookupNameChar[ (int)ch / 32 ] & (1 << (ch % 32))) != 0;
 3163  
 
 3164  0
         return (ch < LOOKUP_MAX_CHAR && lookupNameChar[ ch ])
 3165  
             || (ch >= LOOKUP_MAX_CHAR && ch <= '\u2027')
 3166  
             || (ch >= '\u202A' &&  ch <= '\u218F')
 3167  
             || (ch >= '\u2800' &&  ch <= '\uFFEF')
 3168  
             ;
 3169  
         //return false;
 3170  
         //        return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == ':'
 3171  
         //          || (ch >= '0' && ch <= '9');
 3172  
         //        if(ch < LOOKUP_MAX_CHAR) return (lookupNameStartChar[ (int)ch / 32 ] & (1 << (ch % 32))) != 0;
 3173  
 
 3174  
         //else return
 3175  
         //  else if(ch <= '\u2027') return true;
 3176  
         //        //[#x202A-#x218F]
 3177  
         //        else if(ch < '\u202A') return false;
 3178  
         //        else if(ch <= '\u218F') return true;
 3179  
         //        // added pairts [#x2800-#xD7FF] | [#xE000-#xFDCF] | [#xFDE0-#xFFEF] | [#x10000-#x10FFFF]
 3180  
         //        else if(ch < '\u2800') return false;
 3181  
         //        else if(ch <= '\uFFEF') return true;
 3182  
         //else return false;
 3183  
     }
 3184  
 
 3185  
     protected boolean isS(char ch) {
 3186  0
         return (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t');
 3187  
         // || (supportXml11 && (ch == '\u0085' || ch == '\u2028');
 3188  
     }
 3189  
 
 3190  
     //protected boolean isChar(char ch) { return (ch < '\uD800' || ch > '\uDFFF')
 3191  
     //  ch != '\u0000' ch < '\uFFFE'
 3192  
 
 3193  
 
 3194  
     //protected char printable(char ch) { return ch; }
 3195  
     protected String printable(char ch) {
 3196  0
         if(ch == '\n') {
 3197  0
             return "\\n";
 3198  0
         } else if(ch == '\r') {
 3199  0
             return "\\r";
 3200  0
         } else if(ch == '\t') {
 3201  0
             return "\\t";
 3202  0
         } else if(ch == '\'') {
 3203  0
             return "\\'";
 3204  0
         } if(ch > 127 || ch < 32) {
 3205  0
             return "\\u"+Integer.toHexString((int)ch);
 3206  
         }
 3207  0
         return ""+ch;
 3208  
     }
 3209  
 
 3210  
     protected String printable(String s) {
 3211  0
         if(s == null) return null;
 3212  0
         final int sLen = s.length();
 3213  0
         StringBuilder buf = new StringBuilder(sLen + 10);
 3214  0
         for(int i = 0; i < sLen; ++i) {
 3215  0
             buf.append(printable(s.charAt(i)));
 3216  
         }
 3217  0
         s = buf.toString();
 3218  0
         return s;
 3219  
     }
 3220  
 }
 3221  
 
 3222  
 
 3223  
 /*
 3224  
  * Indiana University Extreme! Lab Software License, Version 1.2
 3225  
  *
 3226  
  * Copyright (C) 2003 The Trustees of Indiana University.
 3227  
  * All rights reserved.
 3228  
  *
 3229  
  * Redistribution and use in source and binary forms, with or without
 3230  
  * modification, are permitted provided that the following conditions are
 3231  
  * met:
 3232  
  *
 3233  
  * 1) All redistributions of source code must retain the above
 3234  
  *    copyright notice, the list of authors in the original source
 3235  
  *    code, this list of conditions and the disclaimer listed in this
 3236  
  *    license;
 3237  
  *
 3238  
  * 2) All redistributions in binary form must reproduce the above
 3239  
  *    copyright notice, this list of conditions and the disclaimer
 3240  
  *    listed in this license in the documentation and/or other
 3241  
  *    materials provided with the distribution;
 3242  
  *
 3243  
  * 3) Any documentation included with all redistributions must include
 3244  
  *    the following acknowledgement:
 3245  
  *
 3246  
  *      "This product includes software developed by the Indiana
 3247  
  *      University Extreme! Lab.  For further information please visit
 3248  
  *      http://www.extreme.indiana.edu/"
 3249  
  *
 3250  
  *    Alternatively, this acknowledgment may appear in the software
 3251  
  *    itself, and wherever such third-party acknowledgments normally
 3252  
  *    appear.
 3253  
  *
 3254  
  * 4) The name "Indiana University" or "Indiana University
 3255  
  *    Extreme! Lab" shall not be used to endorse or promote
 3256  
  *    products derived from this software without prior written
 3257  
  *    permission from Indiana University.  For written permission,
 3258  
  *    please contact http://www.extreme.indiana.edu/.
 3259  
  *
 3260  
  * 5) Products derived from this software may not use "Indiana
 3261  
  *    University" name nor may "Indiana University" appear in their name,
 3262  
  *    without prior written permission of the Indiana University.
 3263  
  *
 3264  
  * Indiana University provides no reassurances that the source code
 3265  
  * provided does not infringe the patent or any other intellectual
 3266  
  * property rights of any other entity.  Indiana University disclaims any
 3267  
  * liability to any recipient for claims brought by any other entity
 3268  
  * based on infringement of intellectual property rights or otherwise.
 3269  
  *
 3270  
  * LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH
 3271  
  * NO WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA
 3272  
  * UNIVERSITY GIVES NO WARRANTIES AND MAKES NO REPRESENTATION THAT
 3273  
  * SOFTWARE IS FREE OF INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR
 3274  
  * OTHER PROPRIETARY RIGHTS.  INDIANA UNIVERSITY MAKES NO WARRANTIES THAT
 3275  
  * SOFTWARE IS FREE FROM "BUGS", "VIRUSES", "TROJAN HORSES", "TRAP
 3276  
  * DOORS", "WORMS", OR OTHER HARMFUL CODE.  LICENSEE ASSUMES THE ENTIRE
 3277  
  * RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR ASSOCIATED MATERIALS,
 3278  
  * AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION GENERATED USING
 3279  
  * SOFTWARE.
 3280  
  */
 3281  
 
 3282  
 
 3283  
 
 3284  
 
 3285  
 
 3286