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