You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dj...@apache.org on 2009/10/05 20:54:56 UTC
svn commit: r821961 [27/30] - in /geronimo/sandbox/djencks/osgi/framework:
./ buildsupport/ buildsupport/car-maven-plugin/
buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/
buildsupport/geronimo-maven-plugin/src/main/jav...
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXParser.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXParser.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXParser.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXParser.java Mon Oct 5 18:54:50 2009
@@ -0,0 +1,3375 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
+/*
+ * Copyright (c) 2003 Extreme! Lab, Indiana University. All rights reserved.
+ *
+ * This software is open source. See the bottom of this file for the licence.
+ *
+ * $Id: MXParser.java 8238 2009-05-28 23:51:31Z vsiveton $
+ */
+
+package org.apache.geronimo.system.plugin.plexus.util.xml.pull;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.geronimo.system.plugin.plexus.util.ReaderFactory;
+
+//import java.util.Hashtable;
+
+//TODO best handling of interning issues
+// have isAllNewStringInterned ???
+
+//TODO handling surrogate pairs: http://www.unicode.org/unicode/faq/utf_bom.html#6
+
+//TODO review code for use of bufAbsoluteStart when keeping pos between next()/fillBuf()
+
+/**
+ * Absolutely minimal implementation of XMLPULL V1 API. Encoding handling done with XmlReader
+ *
+ * @see org.apache.geronimo.system.plugin.plexus.util.xml.XmlReader
+ * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
+ */
+
+public class MXParser
+ implements XmlPullParser
+{
+ //NOTE: no interning of those strings --> by Java leng spec they MUST be already interned
+ protected final static String XML_URI = "http://www.w3.org/XML/1998/namespace";
+ protected final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
+ protected final static String FEATURE_XML_ROUNDTRIP=
+ //"http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
+ "http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
+ protected final static String FEATURE_NAMES_INTERNED =
+ "http://xmlpull.org/v1/doc/features.html#names-interned";
+ protected final static String PROPERTY_XMLDECL_VERSION =
+ "http://xmlpull.org/v1/doc/properties.html#xmldecl-version";
+ protected final static String PROPERTY_XMLDECL_STANDALONE =
+ "http://xmlpull.org/v1/doc/properties.html#xmldecl-standalone";
+ protected final static String PROPERTY_XMLDECL_CONTENT =
+ "http://xmlpull.org/v1/doc/properties.html#xmldecl-content";
+ protected final static String PROPERTY_LOCATION =
+ "http://xmlpull.org/v1/doc/properties.html#location";
+
+ /**
+ * Implementation notice:
+ * the is instance variable that controls if newString() is interning.
+ * <p><b>NOTE:</b> newStringIntern <b>always</b> returns interned strings
+ * and newString MAY return interned String depending on this variable.
+ * <p><b>NOTE:</b> by default in this minimal implementation it is false!
+ */
+ protected boolean allStringsInterned;
+
+ protected void resetStringCache() {
+ //System.out.println("resetStringCache() minimum called");
+ }
+
+ protected String newString(char[] cbuf, int off, int len) {
+ return new String(cbuf, off, len);
+ }
+
+ protected String newStringIntern(char[] cbuf, int off, int len) {
+ return (new String(cbuf, off, len)).intern();
+ }
+
+ private static final boolean TRACE_SIZING = false;
+
+ // NOTE: features are not resetable and typically defaults to false ...
+ protected boolean processNamespaces;
+ protected boolean roundtripSupported;
+
+ // global parser state
+ protected String location;
+ protected int lineNumber;
+ protected int columnNumber;
+ protected boolean seenRoot;
+ protected boolean reachedEnd;
+ protected int eventType;
+ protected boolean emptyElementTag;
+ // element stack
+ protected int depth;
+ protected char[] elRawName[];
+ protected int elRawNameEnd[];
+ protected int elRawNameLine[];
+
+ protected String elName[];
+ protected String elPrefix[];
+ protected String elUri[];
+ //protected String elValue[];
+ protected int elNamespaceCount[];
+
+
+
+ /**
+ * Make sure that we have enough space to keep element stack if passed size.
+ * It will always create one additional slot then current depth
+ */
+ protected void ensureElementsCapacity() {
+ final int elStackSize = elName != null ? elName.length : 0;
+ if( (depth + 1) >= elStackSize) {
+ // we add at least one extra slot ...
+ final int newSize = (depth >= 7 ? 2 * depth : 8) + 2; // = lucky 7 + 1 //25
+ if(TRACE_SIZING) {
+ System.err.println("TRACE_SIZING elStackSize "+elStackSize+" ==> "+newSize);
+ }
+ final boolean needsCopying = elStackSize > 0;
+ String[] arr = null;
+ // resue arr local variable slot
+ arr = new String[newSize];
+ if(needsCopying) System.arraycopy(elName, 0, arr, 0, elStackSize);
+ elName = arr;
+ arr = new String[newSize];
+ if(needsCopying) System.arraycopy(elPrefix, 0, arr, 0, elStackSize);
+ elPrefix = arr;
+ arr = new String[newSize];
+ if(needsCopying) System.arraycopy(elUri, 0, arr, 0, elStackSize);
+ elUri = arr;
+
+ int[] iarr = new int[newSize];
+ if(needsCopying) {
+ System.arraycopy(elNamespaceCount, 0, iarr, 0, elStackSize);
+ } else {
+ // special initialization
+ iarr[0] = 0;
+ }
+ elNamespaceCount = iarr;
+
+ //TODO: avoid using element raw name ...
+ iarr = new int[newSize];
+ if(needsCopying) {
+ System.arraycopy(elRawNameEnd, 0, iarr, 0, elStackSize);
+ }
+ elRawNameEnd = iarr;
+
+ iarr = new int[newSize];
+ if(needsCopying) {
+ System.arraycopy(elRawNameLine, 0, iarr, 0, elStackSize);
+ }
+ elRawNameLine = iarr;
+
+ final char[][] carr = new char[newSize][];
+ if(needsCopying) {
+ System.arraycopy(elRawName, 0, carr, 0, elStackSize);
+ }
+ elRawName = carr;
+ // arr = new String[newSize];
+ // if(needsCopying) System.arraycopy(elLocalName, 0, arr, 0, elStackSize);
+ // elLocalName = arr;
+ // arr = new String[newSize];
+ // if(needsCopying) System.arraycopy(elDefaultNs, 0, arr, 0, elStackSize);
+ // elDefaultNs = arr;
+ // int[] iarr = new int[newSize];
+ // if(needsCopying) System.arraycopy(elNsStackPos, 0, iarr, 0, elStackSize);
+ // for (int i = elStackSize; i < iarr.length; i++)
+ // {
+ // iarr[i] = (i > 0) ? -1 : 0;
+ // }
+ // elNsStackPos = iarr;
+ //assert depth < elName.length;
+ }
+ }
+
+
+
+ // attribute stack
+ protected int attributeCount;
+ protected String attributeName[];
+ protected int attributeNameHash[];
+ //protected int attributeNameStart[];
+ //protected int attributeNameEnd[];
+ protected String attributePrefix[];
+ protected String attributeUri[];
+ protected String attributeValue[];
+ //protected int attributeValueStart[];
+ //protected int attributeValueEnd[];
+
+
+ /**
+ * Make sure that in attributes temporary array is enough space.
+ */
+ protected void ensureAttributesCapacity(int size) {
+ final int attrPosSize = attributeName != null ? attributeName.length : 0;
+ if(size >= attrPosSize) {
+ final int newSize = size > 7 ? 2 * size : 8; // = lucky 7 + 1 //25
+ if(TRACE_SIZING) {
+ System.err.println("TRACE_SIZING attrPosSize "+attrPosSize+" ==> "+newSize);
+ }
+ final boolean needsCopying = attrPosSize > 0;
+ String[] arr = null;
+
+ arr = new String[newSize];
+ if(needsCopying) System.arraycopy(attributeName, 0, arr, 0, attrPosSize);
+ attributeName = arr;
+
+ arr = new String[newSize];
+ if(needsCopying) System.arraycopy(attributePrefix, 0, arr, 0, attrPosSize);
+ attributePrefix = arr;
+
+ arr = new String[newSize];
+ if(needsCopying) System.arraycopy(attributeUri, 0, arr, 0, attrPosSize);
+ attributeUri = arr;
+
+ arr = new String[newSize];
+ if(needsCopying) System.arraycopy(attributeValue, 0, arr, 0, attrPosSize);
+ attributeValue = arr;
+
+ if( ! allStringsInterned ) {
+ final int[] iarr = new int[newSize];
+ if(needsCopying) System.arraycopy(attributeNameHash, 0, iarr, 0, attrPosSize);
+ attributeNameHash = iarr;
+ }
+
+ arr = null;
+ // //assert attrUri.length > size
+ }
+ }
+
+ // namespace stack
+ protected int namespaceEnd;
+ protected String namespacePrefix[];
+ protected int namespacePrefixHash[];
+ protected String namespaceUri[];
+
+ protected void ensureNamespacesCapacity(int size) {
+ final int namespaceSize = namespacePrefix != null ? namespacePrefix.length : 0;
+ if(size >= namespaceSize) {
+ final int newSize = size > 7 ? 2 * size : 8; // = lucky 7 + 1 //25
+ if(TRACE_SIZING) {
+ System.err.println("TRACE_SIZING namespaceSize "+namespaceSize+" ==> "+newSize);
+ }
+ final String[] newNamespacePrefix = new String[newSize];
+ final String[] newNamespaceUri = new String[newSize];
+ if(namespacePrefix != null) {
+ System.arraycopy(
+ namespacePrefix, 0, newNamespacePrefix, 0, namespaceEnd);
+ System.arraycopy(
+ namespaceUri, 0, newNamespaceUri, 0, namespaceEnd);
+ }
+ namespacePrefix = newNamespacePrefix;
+ namespaceUri = newNamespaceUri;
+
+
+ if( ! allStringsInterned ) {
+ final int[] newNamespacePrefixHash = new int[newSize];
+ if(namespacePrefixHash != null) {
+ System.arraycopy(
+ namespacePrefixHash, 0, newNamespacePrefixHash, 0, namespaceEnd);
+ }
+ namespacePrefixHash = newNamespacePrefixHash;
+ }
+ //prefixesSize = newSize;
+ // //assert nsPrefixes.length > size && nsPrefixes.length == newSize
+ }
+ }
+
+ /**
+ * simplistic implementation of hash function that has <b>constant</b>
+ * time to compute - so it also means diminishing hash quality for long strings
+ * but for XML parsing it should be good enough ...
+ */
+ protected static final int fastHash( char ch[], int off, int len ) {
+ if(len == 0) return 0;
+ //assert len >0
+ int hash = ch[off]; // hash at beginning
+ //try {
+ hash = (hash << 7) + ch[ off + len - 1 ]; // hash at the end
+ //} catch(ArrayIndexOutOfBoundsException aie) {
+ // aie.printStackTrace(); //should never happen ...
+ // throw new RuntimeException("this is violation of pre-condition");
+ //}
+ if(len > 16) hash = (hash << 7) + ch[ off + (len / 4)]; // 1/4 from beginning
+ if(len > 8) hash = (hash << 7) + ch[ off + (len / 2)]; // 1/2 of string size ...
+ // notice that hash is at most done 3 times <<7 so shifted by 21 bits 8 bit value
+ // so max result == 29 bits so it is quite just below 31 bits for long (2^32) ...
+ //assert hash >= 0;
+ return hash;
+ }
+
+ // entity replacement stack
+ protected int entityEnd;
+
+ protected String entityName[];
+ protected char[] entityNameBuf[];
+ protected String entityReplacement[];
+ protected char[] entityReplacementBuf[];
+
+ protected int entityNameHash[];
+
+ protected void ensureEntityCapacity() {
+ final int entitySize = entityReplacementBuf != null ? entityReplacementBuf.length : 0;
+ if(entityEnd >= entitySize) {
+ final int newSize = entityEnd > 7 ? 2 * entityEnd : 8; // = lucky 7 + 1 //25
+ if(TRACE_SIZING) {
+ System.err.println("TRACE_SIZING entitySize "+entitySize+" ==> "+newSize);
+ }
+ final String[] newEntityName = new String[newSize];
+ final char[] newEntityNameBuf[] = new char[newSize][];
+ final String[] newEntityReplacement = new String[newSize];
+ final char[] newEntityReplacementBuf[] = new char[newSize][];
+ if(entityName != null) {
+ System.arraycopy(entityName, 0, newEntityName, 0, entityEnd);
+ System.arraycopy(entityNameBuf, 0, newEntityNameBuf, 0, entityEnd);
+ System.arraycopy(entityReplacement, 0, newEntityReplacement, 0, entityEnd);
+ System.arraycopy(entityReplacementBuf, 0, newEntityReplacementBuf, 0, entityEnd);
+ }
+ entityName = newEntityName;
+ entityNameBuf = newEntityNameBuf;
+ entityReplacement = newEntityReplacement;
+ entityReplacementBuf = newEntityReplacementBuf;
+
+ if( ! allStringsInterned ) {
+ final int[] newEntityNameHash = new int[newSize];
+ if(entityNameHash != null) {
+ System.arraycopy(entityNameHash, 0, newEntityNameHash, 0, entityEnd);
+ }
+ entityNameHash = newEntityNameHash;
+ }
+ }
+ }
+
+ // input buffer management
+ protected static final int READ_CHUNK_SIZE = 8*1024; //max data chars in one read() call
+ protected Reader reader;
+ protected String inputEncoding;
+
+
+ protected int bufLoadFactor = 95; // 99%
+ //protected int bufHardLimit; // only matters when expanding
+
+ protected char buf[] = new char[
+ Runtime.getRuntime().freeMemory() > 1000000L ? READ_CHUNK_SIZE : 256 ];
+ protected int bufSoftLimit = ( bufLoadFactor * buf.length ) /100; // desirable size of buffer
+ protected boolean preventBufferCompaction;
+
+ protected int bufAbsoluteStart; // this is buf
+ protected int bufStart;
+ protected int bufEnd;
+ protected int pos;
+ protected int posStart;
+ protected int posEnd;
+
+ protected char pc[] = new char[
+ Runtime.getRuntime().freeMemory() > 1000000L ? READ_CHUNK_SIZE : 64 ];
+ protected int pcStart;
+ protected int pcEnd;
+
+
+ // parsing state
+ //protected boolean needsMore;
+ //protected boolean seenMarkup;
+ protected boolean usePC;
+
+
+ protected boolean seenStartTag;
+ protected boolean seenEndTag;
+ protected boolean pastEndTag;
+ protected boolean seenAmpersand;
+ protected boolean seenMarkup;
+ protected boolean seenDocdecl;
+
+ // transient variable set during each call to next/Token()
+ protected boolean tokenize;
+ protected String text;
+ protected String entityRefName;
+
+ protected String xmlDeclVersion;
+ protected Boolean xmlDeclStandalone;
+ protected String xmlDeclContent;
+
+ protected void reset() {
+ //System.out.println("reset() called");
+ location = null;
+ lineNumber = 1;
+ columnNumber = 0;
+ seenRoot = false;
+ reachedEnd = false;
+ eventType = START_DOCUMENT;
+ emptyElementTag = false;
+
+ depth = 0;
+
+ attributeCount = 0;
+
+ namespaceEnd = 0;
+
+ entityEnd = 0;
+
+ reader = null;
+ inputEncoding = null;
+
+ preventBufferCompaction = false;
+ bufAbsoluteStart = 0;
+ bufEnd = bufStart = 0;
+ pos = posStart = posEnd = 0;
+
+ pcEnd = pcStart = 0;
+
+ usePC = false;
+
+ seenStartTag = false;
+ seenEndTag = false;
+ pastEndTag = false;
+ seenAmpersand = false;
+ seenMarkup = false;
+ seenDocdecl = false;
+
+ xmlDeclVersion = null;
+ xmlDeclStandalone = null;
+ xmlDeclContent = null;
+
+ resetStringCache();
+ }
+
+ public MXParser() {
+ }
+
+
+ /**
+ * Method setFeature
+ *
+ * @param name a String
+ * @param state a boolean
+ *
+ * @throws XmlPullParserException
+ *
+ */
+ public void setFeature(String name,
+ boolean state) throws XmlPullParserException
+ {
+ if(name == null) throw new IllegalArgumentException("feature name should not be null");
+ if(FEATURE_PROCESS_NAMESPACES.equals(name)) {
+ if(eventType != START_DOCUMENT) throw new XmlPullParserException(
+ "namespace processing feature can only be changed before parsing", this, null);
+ processNamespaces = state;
+ // } else if(FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
+ // if(type != START_DOCUMENT) throw new XmlPullParserException(
+ // "namespace reporting feature can only be changed before parsing", this, null);
+ // reportNsAttribs = state;
+ } else if(FEATURE_NAMES_INTERNED.equals(name)) {
+ if(state != false) {
+ throw new XmlPullParserException(
+ "interning names in this implementation is not supported");
+ }
+ } else if(FEATURE_PROCESS_DOCDECL.equals(name)) {
+ if(state != false) {
+ throw new XmlPullParserException(
+ "processing DOCDECL is not supported");
+ }
+ //} else if(REPORT_DOCDECL.equals(name)) {
+ // paramNotifyDoctype = state;
+ } else if(FEATURE_XML_ROUNDTRIP.equals(name)) {
+ //if(state == false) {
+ // throw new XmlPullParserException(
+ // "roundtrip feature can not be switched off");
+ //}
+ roundtripSupported = state;
+ } else {
+ throw new XmlPullParserException("unsupporte feature "+name);
+ }
+ }
+
+ /** Unknown properties are <string>always</strong> returned as false */
+ public boolean getFeature(String name)
+ {
+ if(name == null) throw new IllegalArgumentException("feature name should not be nulll");
+ if(FEATURE_PROCESS_NAMESPACES.equals(name)) {
+ return processNamespaces;
+ // } else if(FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
+ // return reportNsAttribs;
+ } else if(FEATURE_NAMES_INTERNED.equals(name)) {
+ return false;
+ } else if(FEATURE_PROCESS_DOCDECL.equals(name)) {
+ return false;
+ //} else if(REPORT_DOCDECL.equals(name)) {
+ // return paramNotifyDoctype;
+ } else if(FEATURE_XML_ROUNDTRIP.equals(name)) {
+ //return true;
+ return roundtripSupported;
+ }
+ return false;
+ }
+
+ public void setProperty(String name,
+ Object value)
+ throws XmlPullParserException
+ {
+ if(PROPERTY_LOCATION.equals(name)) {
+ location = (String) value;
+ } else {
+ throw new XmlPullParserException("unsupported property: '"+name+"'");
+ }
+ }
+
+
+ public Object getProperty(String name)
+ {
+ if(name == null) throw new IllegalArgumentException("property name should not be nulll");
+ if(PROPERTY_XMLDECL_VERSION.equals(name)) {
+ return xmlDeclVersion;
+ } else if(PROPERTY_XMLDECL_STANDALONE.equals(name)) {
+ return xmlDeclStandalone;
+ } else if(PROPERTY_XMLDECL_CONTENT.equals(name)) {
+ return xmlDeclContent;
+ } else if(PROPERTY_LOCATION.equals(name)) {
+ return location;
+ }
+ return null;
+ }
+
+
+ public void setInput(Reader in) throws XmlPullParserException
+ {
+ reset();
+ reader = in;
+ }
+
+
+ public void setInput(java.io.InputStream inputStream, String inputEncoding)
+ throws XmlPullParserException
+ {
+ if(inputStream == null) {
+ throw new IllegalArgumentException("input stream can not be null");
+ }
+ Reader reader;
+ try {
+ if(inputEncoding != null) {
+ reader = ReaderFactory.newReader(inputStream, inputEncoding);
+ } else {
+ reader = ReaderFactory.newXmlReader(inputStream);
+ }
+ } catch (UnsupportedEncodingException une) {
+ throw new XmlPullParserException(
+ "could not create reader for encoding "+inputEncoding+" : "+une, this, une);
+ }
+ catch ( IOException e )
+ {
+ throw new XmlPullParserException(
+ "could not create reader : "+e, this, e);
+ }
+ setInput(reader);
+ //must be here as reset() was called in setInput() and has set this.inputEncoding to null ...
+ this.inputEncoding = inputEncoding;
+ }
+
+ public String getInputEncoding() {
+ return inputEncoding;
+ }
+
+ public void defineEntityReplacementText(String entityName,
+ String replacementText)
+ throws XmlPullParserException
+ {
+ // throw new XmlPullParserException("not allowed");
+
+ if ( !replacementText.startsWith( "&#" ) && this.entityName != null && replacementText.length() > 1 )
+ {
+ String tmp = replacementText.substring( 1, replacementText.length() - 1 );
+ for ( int i = 0; i < this.entityName.length; i++ )
+ {
+ if ( this.entityName[i] != null && this.entityName[i].equals( tmp ) )
+ {
+ replacementText = this.entityReplacement[i];
+ }
+ }
+ }
+
+ //protected char[] entityReplacement[];
+ ensureEntityCapacity();
+
+ // this is to make sure that if interning works we will take advantage of it ...
+ this.entityName[entityEnd] = newString(entityName.toCharArray(), 0, entityName.length());
+ entityNameBuf[entityEnd] = entityName.toCharArray();
+
+ entityReplacement[entityEnd] = replacementText;
+ entityReplacementBuf[entityEnd] = replacementText.toCharArray();
+ if(!allStringsInterned) {
+ entityNameHash[ entityEnd ] =
+ fastHash(entityNameBuf[entityEnd], 0, entityNameBuf[entityEnd].length);
+ }
+ ++entityEnd;
+ //TODO disallow < or & in entity replacement text (or ]]>???)
+ // TOOD keepEntityNormalizedForAttributeValue cached as well ...
+ }
+
+ public int getNamespaceCount(int depth)
+ throws XmlPullParserException
+ {
+ if(processNamespaces == false || depth == 0) {
+ return 0;
+ }
+ //int maxDepth = eventType == END_TAG ? this.depth + 1 : this.depth;
+ //if(depth < 0 || depth > maxDepth) throw new IllegalArgumentException(
+ if(depth < 0 || depth > this.depth) throw new IllegalArgumentException(
+ "napespace count mayt be for depth 0.."+this.depth+" not "+depth);
+ return elNamespaceCount[ depth ];
+ }
+
+ public String getNamespacePrefix(int pos)
+ throws XmlPullParserException
+ {
+
+ //int end = eventType == END_TAG ? elNamespaceCount[ depth + 1 ] : namespaceEnd;
+ //if(pos < end) {
+ if(pos < namespaceEnd) {
+ return namespacePrefix[ pos ];
+ } else {
+ throw new XmlPullParserException(
+ "position "+pos+" exceeded number of available namespaces "+namespaceEnd);
+ }
+ }
+
+ public String getNamespaceUri(int pos) throws XmlPullParserException
+ {
+ //int end = eventType == END_TAG ? elNamespaceCount[ depth + 1 ] : namespaceEnd;
+ //if(pos < end) {
+ if(pos < namespaceEnd) {
+ return namespaceUri[ pos ];
+ } else {
+ throw new XmlPullParserException(
+ "position "+pos+" exceedded number of available namespaces "+namespaceEnd);
+ }
+ }
+
+ public String getNamespace( String prefix )
+ //throws XmlPullParserException
+ {
+ //int count = namespaceCount[ depth ];
+ if(prefix != null) {
+ for( int i = namespaceEnd -1; i >= 0; i--) {
+ if( prefix.equals( namespacePrefix[ i ] ) ) {
+ return namespaceUri[ i ];
+ }
+ }
+ if("xml".equals( prefix )) {
+ return XML_URI;
+ } else if("xmlns".equals( prefix )) {
+ return XMLNS_URI;
+ }
+ } else {
+ for( int i = namespaceEnd -1; i >= 0; i--) {
+ if( namespacePrefix[ i ] == null) { //"") { //null ) { //TODO check FIXME Alek
+ return namespaceUri[ i ];
+ }
+ }
+
+ }
+ return null;
+ }
+
+
+ public int getDepth()
+ {
+ return depth;
+ }
+
+
+ private static int findFragment(int bufMinPos, char[] b, int start, int end) {
+ //System.err.println("bufStart="+bufStart+" b="+printable(new String(b, start, end - start))+" start="+start+" end="+end);
+ if(start < bufMinPos) {
+ start = bufMinPos;
+ if(start > end) start = end;
+ return start;
+ }
+ if(end - start > 65) {
+ start = end - 10; // try to find good location
+ }
+ int i = start + 1;
+ while(--i > bufMinPos) {
+ if((end - i) > 65) break;
+ final char c = b[i];
+ if(c == '<' && (start - i) > 10) break;
+ }
+ return i;
+ }
+
+
+ /**
+ * Return string describing current position of parsers as
+ * text 'STATE [seen %s...] @line:column'.
+ */
+ public String getPositionDescription ()
+ {
+ String fragment = null;
+ if(posStart <= pos) {
+ final int start = findFragment(0, buf, posStart, pos);
+ //System.err.println("start="+start);
+ if(start < pos) {
+ fragment = new String(buf, start, pos - start);
+ }
+ if(bufAbsoluteStart > 0 || start > 0) fragment = "..." + fragment;
+ }
+ // return " at line "+tokenizerPosRow
+ // +" and column "+(tokenizerPosCol-1)
+ // +(fragment != null ? " seen "+printable(fragment)+"..." : "");
+ return " "+TYPES[ eventType ] +
+ (fragment != null ? " seen "+printable(fragment)+"..." : "")
+ +" "+(location != null ? location : "")
+ +"@"+getLineNumber()+":"+getColumnNumber();
+ }
+
+ public int getLineNumber()
+ {
+ return lineNumber;
+ }
+
+ public int getColumnNumber()
+ {
+ return columnNumber;
+ }
+
+
+ public boolean isWhitespace() throws XmlPullParserException
+ {
+ if(eventType == TEXT || eventType == CDSECT) {
+ if(usePC) {
+ for (int i = pcStart; i <pcEnd; i++)
+ {
+ if(!isS(pc[ i ])) return false;
+ }
+ return true;
+ } else {
+ for (int i = posStart; i <posEnd; i++)
+ {
+ if(!isS(buf[ i ])) return false;
+ }
+ return true;
+ }
+ } else if(eventType == IGNORABLE_WHITESPACE) {
+ return true;
+ }
+ throw new XmlPullParserException("no content available to check for whitespaces");
+ }
+
+ public String getText()
+ {
+ if(eventType == START_DOCUMENT || eventType == END_DOCUMENT) {
+ //throw new XmlPullParserException("no content available to read");
+ // if(roundtripSupported) {
+ // text = new String(buf, posStart, posEnd - posStart);
+ // } else {
+ return null;
+ // }
+ } else if(eventType == ENTITY_REF) {
+ return text;
+ }
+ if(text == null) {
+ if(!usePC || eventType == START_TAG || eventType == END_TAG) {
+ text = new String(buf, posStart, posEnd - posStart);
+ } else {
+ text = new String(pc, pcStart, pcEnd - pcStart);
+ }
+ }
+ return text;
+ }
+
+ public char[] getTextCharacters(int [] holderForStartAndLength)
+ {
+ if( eventType == TEXT ) {
+ if(usePC) {
+ holderForStartAndLength[0] = pcStart;
+ holderForStartAndLength[1] = pcEnd - pcStart;
+ return pc;
+ } else {
+ holderForStartAndLength[0] = posStart;
+ holderForStartAndLength[1] = posEnd - posStart;
+ return buf;
+
+ }
+ } else if( eventType == START_TAG
+ || eventType == END_TAG
+ || eventType == CDSECT
+ || eventType == COMMENT
+ || eventType == ENTITY_REF
+ || eventType == PROCESSING_INSTRUCTION
+ || eventType == IGNORABLE_WHITESPACE
+ || eventType == DOCDECL)
+ {
+ holderForStartAndLength[0] = posStart;
+ holderForStartAndLength[1] = posEnd - posStart;
+ return buf;
+ } else if(eventType == START_DOCUMENT
+ || eventType == END_DOCUMENT) {
+ //throw new XmlPullParserException("no content available to read");
+ holderForStartAndLength[0] = holderForStartAndLength[1] = -1;
+ return null;
+ } else {
+ throw new IllegalArgumentException("unknown text eventType: "+eventType);
+ }
+ // String s = getText();
+ // char[] cb = null;
+ // if(s!= null) {
+ // cb = s.toCharArray();
+ // holderForStartAndLength[0] = 0;
+ // holderForStartAndLength[1] = s.length();
+ // } else {
+ // }
+ // return cb;
+ }
+
+ public String getNamespace()
+ {
+ if(eventType == START_TAG) {
+ //return processNamespaces ? elUri[ depth - 1 ] : NO_NAMESPACE;
+ return processNamespaces ? elUri[ depth ] : NO_NAMESPACE;
+ } else if(eventType == END_TAG) {
+ return processNamespaces ? elUri[ depth ] : NO_NAMESPACE;
+ }
+ return null;
+ // String prefix = elPrefix[ maxDepth ];
+ // if(prefix != null) {
+ // for( int i = namespaceEnd -1; i >= 0; i--) {
+ // if( prefix.equals( namespacePrefix[ i ] ) ) {
+ // return namespaceUri[ i ];
+ // }
+ // }
+ // } else {
+ // for( int i = namespaceEnd -1; i >= 0; i--) {
+ // if( namespacePrefix[ i ] == null ) {
+ // return namespaceUri[ i ];
+ // }
+ // }
+ //
+ // }
+ // return "";
+ }
+
+ public String getName()
+ {
+ if(eventType == START_TAG) {
+ //return elName[ depth - 1 ] ;
+ return elName[ depth ] ;
+ } else if(eventType == END_TAG) {
+ return elName[ depth ] ;
+ } else if(eventType == ENTITY_REF) {
+ if(entityRefName == null) {
+ entityRefName = newString(buf, posStart, posEnd - posStart);
+ }
+ return entityRefName;
+ } else {
+ return null;
+ }
+ }
+
+ public String getPrefix()
+ {
+ if(eventType == START_TAG) {
+ //return elPrefix[ depth - 1 ] ;
+ return elPrefix[ depth ] ;
+ } else if(eventType == END_TAG) {
+ return elPrefix[ depth ] ;
+ }
+ return null;
+ // if(eventType != START_TAG && eventType != END_TAG) return null;
+ // int maxDepth = eventType == END_TAG ? depth : depth - 1;
+ // return elPrefix[ maxDepth ];
+ }
+
+
+ public boolean isEmptyElementTag() throws XmlPullParserException
+ {
+ if(eventType != START_TAG) throw new XmlPullParserException(
+ "parser must be on START_TAG to check for empty element", this, null);
+ return emptyElementTag;
+ }
+
+ public int getAttributeCount()
+ {
+ if(eventType != START_TAG) return -1;
+ return attributeCount;
+ }
+
+ public String getAttributeNamespace(int index)
+ {
+ if(eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes");
+ if(processNamespaces == false) return NO_NAMESPACE;
+ if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+ "attribute position must be 0.."+(attributeCount-1)+" and not "+index);
+ return attributeUri[ index ];
+ }
+
+ public String getAttributeName(int index)
+ {
+ if(eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes");
+ if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+ "attribute position must be 0.."+(attributeCount-1)+" and not "+index);
+ return attributeName[ index ];
+ }
+
+ public String getAttributePrefix(int index)
+ {
+ if(eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes");
+ if(processNamespaces == false) return null;
+ if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+ "attribute position must be 0.."+(attributeCount-1)+" and not "+index);
+ return attributePrefix[ index ];
+ }
+
+ public String getAttributeType(int index) {
+ if(eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes");
+ if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+ "attribute position must be 0.."+(attributeCount-1)+" and not "+index);
+ return "CDATA";
+ }
+
+ public boolean isAttributeDefault(int index) {
+ if(eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes");
+ if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+ "attribute position must be 0.."+(attributeCount-1)+" and not "+index);
+ return false;
+ }
+
+ public String getAttributeValue(int index)
+ {
+ if(eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes");
+ if(index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+ "attribute position must be 0.."+(attributeCount-1)+" and not "+index);
+ return attributeValue[ index ];
+ }
+
+ public String getAttributeValue(String namespace,
+ String name)
+ {
+ if(eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes"+getPositionDescription());
+ if(name == null) {
+ throw new IllegalArgumentException("attribute name can not be null");
+ }
+ // TODO make check if namespace is interned!!! etc. for names!!!
+ if(processNamespaces) {
+ if(namespace == null) {
+ namespace = "";
+ }
+
+ for(int i = 0; i < attributeCount; ++i) {
+ if((namespace == attributeUri[ i ] ||
+ namespace.equals(attributeUri[ i ]) )
+ //(namespace != null && namespace.equals(attributeUri[ i ]))
+ // taking advantage of String.intern()
+ && name.equals(attributeName[ i ]) )
+ {
+ return attributeValue[i];
+ }
+ }
+ } else {
+ if(namespace != null && namespace.length() == 0) {
+ namespace = null;
+ }
+ if(namespace != null) throw new IllegalArgumentException(
+ "when namespaces processing is disabled attribute namespace must be null");
+ for(int i = 0; i < attributeCount; ++i) {
+ if(name.equals(attributeName[i]))
+ {
+ return attributeValue[i];
+ }
+ }
+ }
+ return null;
+ }
+
+
+ public int getEventType()
+ throws XmlPullParserException
+ {
+ return eventType;
+ }
+
+ public void require(int type, String namespace, String name)
+ throws XmlPullParserException, IOException
+ {
+ if(processNamespaces == false && namespace != null) {
+ throw new XmlPullParserException(
+ "processing namespaces must be enabled on parser (or factory)"+
+ " to have possible namespaces delcared on elements"
+ +(" (postion:"+ getPositionDescription())+")");
+ }
+ if (type != getEventType()
+ || (namespace != null && !namespace.equals (getNamespace()))
+ || (name != null && !name.equals (getName ())) )
+ {
+ throw new XmlPullParserException (
+ "expected event "+TYPES[ type ]
+ +(name != null ? " with name '"+name+"'" : "")
+ +(namespace != null && name != null ? " and" : "")
+ +(namespace != null ? " with namespace '"+namespace+"'" : "")
+ +" but got"
+ +(type != getEventType() ? " "+TYPES[ getEventType() ] : "")
+ +(name != null && getName() != null && !name.equals (getName ())
+ ? " name '"+getName()+"'" : "")
+ +(namespace != null && name != null
+ && getName() != null && !name.equals (getName ())
+ && getNamespace() != null && !namespace.equals (getNamespace())
+ ? " and" : "")
+ +(namespace != null && getNamespace() != null && !namespace.equals (getNamespace())
+ ? " namespace '"+getNamespace()+"'" : "")
+ +(" (postion:"+ getPositionDescription())+")");
+ }
+ }
+
+
+ /**
+ * Skip sub tree that is currently porser positioned on.
+ * <br>NOTE: parser must be on START_TAG and when funtion returns
+ * parser will be positioned on corresponding END_TAG
+ */
+ public void skipSubTree()
+ throws XmlPullParserException, IOException
+ {
+ require(START_TAG, null, null);
+ int level = 1;
+ while(level > 0) {
+ int eventType = next();
+ if(eventType == END_TAG) {
+ --level;
+ } else if(eventType == START_TAG) {
+ ++level;
+ }
+ }
+ }
+
+ // public String readText() throws XmlPullParserException, IOException
+ // {
+ // if (getEventType() != TEXT) return "";
+ // String result = getText();
+ // next();
+ // return result;
+ // }
+
+ public String nextText() throws XmlPullParserException, IOException
+ {
+ // String result = null;
+ // boolean onStartTag = false;
+ // if(eventType == START_TAG) {
+ // onStartTag = true;
+ // next();
+ // }
+ // if(eventType == TEXT) {
+ // result = getText();
+ // next();
+ // } else if(onStartTag && eventType == END_TAG) {
+ // result = "";
+ // } else {
+ // throw new XmlPullParserException(
+ // "parser must be on START_TAG or TEXT to read text", this, null);
+ // }
+ // if(eventType != END_TAG) {
+ // throw new XmlPullParserException(
+ // "event TEXT it must be immediately followed by END_TAG", this, null);
+ // }
+ // return result;
+ if(getEventType() != START_TAG) {
+ throw new XmlPullParserException(
+ "parser must be on START_TAG to read next text", this, null);
+ }
+ int eventType = next();
+ if(eventType == TEXT) {
+ final String result = getText();
+ eventType = next();
+ if(eventType != END_TAG) {
+ throw new XmlPullParserException(
+ "TEXT must be immediately followed by END_TAG and not "
+ +TYPES[ getEventType() ], this, null);
+ }
+ return result;
+ } else if(eventType == END_TAG) {
+ return "";
+ } else {
+ throw new XmlPullParserException(
+ "parser must be on START_TAG or TEXT to read text", this, null);
+ }
+ }
+
+ public int nextTag() throws XmlPullParserException, IOException
+ {
+ next();
+ if(eventType == TEXT && isWhitespace()) { // skip whitespace
+ next();
+ }
+ if (eventType != START_TAG && eventType != END_TAG) {
+ throw new XmlPullParserException("expected START_TAG or END_TAG not "
+ +TYPES[ getEventType() ], this, null);
+ }
+ return eventType;
+ }
+
+ public int next()
+ throws XmlPullParserException, IOException
+ {
+ tokenize = false;
+ return nextImpl();
+ }
+
+ public int nextToken()
+ throws XmlPullParserException, IOException
+ {
+ tokenize = true;
+ return nextImpl();
+ }
+
+
+ protected int nextImpl()
+ throws XmlPullParserException, IOException
+ {
+ text = null;
+ pcEnd = pcStart = 0;
+ usePC = false;
+ bufStart = posEnd;
+ if(pastEndTag) {
+ pastEndTag = false;
+ --depth;
+ namespaceEnd = elNamespaceCount[ depth ]; // less namespaces available
+ }
+ if(emptyElementTag) {
+ emptyElementTag = false;
+ pastEndTag = true;
+ return eventType = END_TAG;
+ }
+
+ // [1] document ::= prolog element Misc*
+ if(depth > 0) {
+
+ if(seenStartTag) {
+ seenStartTag = false;
+ return eventType = parseStartTag();
+ }
+ if(seenEndTag) {
+ seenEndTag = false;
+ return eventType = parseEndTag();
+ }
+
+ // ASSUMPTION: we are _on_ first character of content or markup!!!!
+ // [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)*
+ char ch;
+ if(seenMarkup) { // we have read ahead ...
+ seenMarkup = false;
+ ch = '<';
+ } else if(seenAmpersand) {
+ seenAmpersand = false;
+ ch = '&';
+ } else {
+ ch = more();
+ }
+ posStart = pos - 1; // VERY IMPORTANT: this is correct start of event!!!
+
+ // when true there is some potential event TEXT to return - keep gathering
+ boolean hadCharData = false;
+
+ // when true TEXT data is not continuous (like <![CDATA[text]]>) and requires PC merging
+ boolean needsMerging = false;
+
+ MAIN_LOOP:
+ while(true) {
+ // work on MARKUP
+ if(ch == '<') {
+ if(hadCharData) {
+ //posEnd = pos - 1;
+ if(tokenize) {
+ seenMarkup = true;
+ return eventType = TEXT;
+ }
+ }
+ ch = more();
+ if(ch == '/') {
+ if(!tokenize && hadCharData) {
+ seenEndTag = true;
+ //posEnd = pos - 2;
+ return eventType = TEXT;
+ }
+ return eventType = parseEndTag();
+ } else if(ch == '!') {
+ ch = more();
+ if(ch == '-') {
+ // note: if(tokenize == false) posStart/End is NOT changed!!!!
+ parseComment();
+ if(tokenize) return eventType = COMMENT;
+ if( !usePC && hadCharData ) {
+ needsMerging = true;
+ } else {
+ posStart = pos; //completely ignore comment
+ }
+ } else if(ch == '[') {
+ //posEnd = pos - 3;
+ // must remember previous posStart/End as it merges with content of CDATA
+ //int oldStart = posStart + bufAbsoluteStart;
+ //int oldEnd = posEnd + bufAbsoluteStart;
+ parseCDSect(hadCharData);
+ if(tokenize) return eventType = CDSECT;
+ final int cdStart = posStart;
+ final int cdEnd = posEnd;
+ final int cdLen = cdEnd - cdStart;
+
+
+ if(cdLen > 0) { // was there anything inside CDATA section?
+ hadCharData = true;
+ if(!usePC) {
+ needsMerging = true;
+ }
+ }
+
+ // posStart = oldStart;
+ // posEnd = oldEnd;
+ // if(cdLen > 0) { // was there anything inside CDATA section?
+ // if(hadCharData) {
+ // // do merging if there was anything in CDSect!!!!
+ // // if(!usePC) {
+ // // // posEnd is correct already!!!
+ // // if(posEnd > posStart) {
+ // // joinPC();
+ // // } else {
+ // // usePC = true;
+ // // pcStart = pcEnd = 0;
+ // // }
+ // // }
+ // // if(pcEnd + cdLen >= pc.length) ensurePC(pcEnd + cdLen);
+ // // // copy [cdStart..cdEnd) into PC
+ // // System.arraycopy(buf, cdStart, pc, pcEnd, cdLen);
+ // // pcEnd += cdLen;
+ // if(!usePC) {
+ // needsMerging = true;
+ // posStart = cdStart;
+ // posEnd = cdEnd;
+ // }
+ // } else {
+ // if(!usePC) {
+ // needsMerging = true;
+ // posStart = cdStart;
+ // posEnd = cdEnd;
+ // hadCharData = true;
+ // }
+ // }
+ // //hadCharData = true;
+ // } else {
+ // if( !usePC && hadCharData ) {
+ // needsMerging = true;
+ // }
+ // }
+ } else {
+ throw new XmlPullParserException(
+ "unexpected character in markup "+printable(ch), this, null);
+ }
+ } else if(ch == '?') {
+ parsePI();
+ if(tokenize) return eventType = PROCESSING_INSTRUCTION;
+ if( !usePC && hadCharData ) {
+ needsMerging = true;
+ } else {
+ posStart = pos; //completely ignore PI
+ }
+
+ } else if( isNameStartChar(ch) ) {
+ if(!tokenize && hadCharData) {
+ seenStartTag = true;
+ //posEnd = pos - 2;
+ return eventType = TEXT;
+ }
+ return eventType = parseStartTag();
+ } else {
+ throw new XmlPullParserException(
+ "unexpected character in markup "+printable(ch), this, null);
+ }
+ // do content comapctation if it makes sense!!!!
+
+ } else if(ch == '&') {
+ // work on ENTITTY
+ //posEnd = pos - 1;
+ if(tokenize && hadCharData) {
+ seenAmpersand = true;
+ return eventType = TEXT;
+ }
+ final int oldStart = posStart + bufAbsoluteStart;
+ final int oldEnd = posEnd + bufAbsoluteStart;
+ final char[] resolvedEntity = parseEntityRef();
+ if(tokenize) return eventType = ENTITY_REF;
+ // check if replacement text can be resolved !!!
+ if(resolvedEntity == null) {
+ if(entityRefName == null) {
+ entityRefName = newString(buf, posStart, posEnd - posStart);
+ }
+ throw new XmlPullParserException(
+ "could not resolve entity named '"+printable(entityRefName)+"'",
+ this, null);
+ }
+ //int entStart = posStart;
+ //int entEnd = posEnd;
+ posStart = oldStart - bufAbsoluteStart;
+ posEnd = oldEnd - bufAbsoluteStart;
+ if(!usePC) {
+ if(hadCharData) {
+ joinPC(); // posEnd is already set correctly!!!
+ needsMerging = false;
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+ // write into PC replacement text - do merge for replacement text!!!!
+ for (int i = 0; i < resolvedEntity.length; i++)
+ {
+ if(pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = resolvedEntity[ i ];
+
+ }
+ hadCharData = true;
+ //assert needsMerging == false;
+ } else {
+
+ if(needsMerging) {
+ //assert usePC == false;
+ joinPC(); // posEnd is already set correctly!!!
+ //posStart = pos - 1;
+ needsMerging = false;
+ }
+
+
+ //no MARKUP not ENTITIES so work on character data ...
+
+
+
+ // [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
+
+
+ hadCharData = true;
+
+ boolean normalizedCR = false;
+ final boolean normalizeInput = tokenize == false || roundtripSupported == false;
+ // use loop locality here!!!!
+ boolean seenBracket = false;
+ boolean seenBracketBracket = false;
+ do {
+
+ // check that ]]> does not show in
+ if(ch == ']') {
+ if(seenBracket) {
+ seenBracketBracket = true;
+ } else {
+ seenBracket = true;
+ }
+ } else if(seenBracketBracket && ch == '>') {
+ throw new XmlPullParserException(
+ "characters ]]> are not allowed in content", this, null);
+ } else {
+ if(seenBracket) {
+ seenBracketBracket = seenBracket = false;
+ }
+ // assert seenTwoBrackets == seenBracket == false;
+ }
+ if(normalizeInput) {
+ // deal with normalization issues ...
+ if(ch == '\r') {
+ normalizedCR = true;
+ posEnd = pos -1;
+ // posEnd is already set
+ if(!usePC) {
+ if(posEnd > posStart) {
+ joinPC();
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+ if(pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ } else if(ch == '\n') {
+ // if(!usePC) { joinPC(); } else { if(pcEnd >= pc.length) ensurePC(); }
+ if(!normalizedCR && usePC) {
+ if(pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ }
+ normalizedCR = false;
+ } else {
+ if(usePC) {
+ if(pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = ch;
+ }
+ normalizedCR = false;
+ }
+ }
+
+ ch = more();
+ } while(ch != '<' && ch != '&');
+ posEnd = pos - 1;
+ continue MAIN_LOOP; // skip ch = more() from below - we are already ahead ...
+ }
+ ch = more();
+ } // endless while(true)
+ } else {
+ if(seenRoot) {
+ return parseEpilog();
+ } else {
+ return parseProlog();
+ }
+ }
+ }
+
+
+ protected int parseProlog()
+ throws XmlPullParserException, IOException
+ {
+ // [2] prolog: ::= XMLDecl? Misc* (doctypedecl Misc*)? and look for [39] element
+
+ char ch;
+ if(seenMarkup) {
+ ch = buf[ pos - 1 ];
+ } else {
+ ch = more();
+ }
+
+ if(eventType == START_DOCUMENT) {
+ // bootstrap parsing with getting first character input!
+ // deal with BOM
+ // detect BOM and crop it (Unicode int Order Mark)
+ if(ch == '\uFFFE') {
+ throw new XmlPullParserException(
+ "first character in input was UNICODE noncharacter (0xFFFE)"+
+ "- input requires int swapping", this, null);
+ }
+ if(ch == '\uFEFF') {
+ // skipping UNICODE int Order Mark (so called BOM)
+ ch = more();
+ }
+ }
+ seenMarkup = false;
+ boolean gotS = false;
+ posStart = pos - 1;
+ final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
+ boolean normalizedCR = false;
+ while(true) {
+ // deal with Misc
+ // [27] Misc ::= Comment | PI | S
+ // deal with docdecl --> mark it!
+ // else parseStartTag seen <[^/]
+ if(ch == '<') {
+ if(gotS && tokenize) {
+ posEnd = pos - 1;
+ seenMarkup = true;
+ return eventType = IGNORABLE_WHITESPACE;
+ }
+ ch = more();
+ if(ch == '?') {
+ // check if it is 'xml'
+ // deal with XMLDecl
+ boolean isXMLDecl = parsePI();
+ if(tokenize) {
+ if (isXMLDecl) {
+ return eventType = START_DOCUMENT;
+ }
+ return eventType = PROCESSING_INSTRUCTION;
+ }
+ } else if(ch == '!') {
+ ch = more();
+ if(ch == 'D') {
+ if(seenDocdecl) {
+ throw new XmlPullParserException(
+ "only one docdecl allowed in XML document", this, null);
+ }
+ seenDocdecl = true;
+ parseDocdecl();
+ if(tokenize) return eventType = DOCDECL;
+ } else if(ch == '-') {
+ parseComment();
+ if(tokenize) return eventType = COMMENT;
+ } else {
+ throw new XmlPullParserException(
+ "unexpected markup <!"+printable(ch), this, null);
+ }
+ } else if(ch == '/') {
+ throw new XmlPullParserException(
+ "expected start tag name and not "+printable(ch), this, null);
+ } else if(isNameStartChar(ch)) {
+ seenRoot = true;
+ return parseStartTag();
+ } else {
+ throw new XmlPullParserException(
+ "expected start tag name and not "+printable(ch), this, null);
+ }
+ } else if(isS(ch)) {
+ gotS = true;
+ if(normalizeIgnorableWS) {
+ if(ch == '\r') {
+ normalizedCR = true;
+ //posEnd = pos -1;
+ //joinPC();
+ // posEnd is already set
+ if(!usePC) {
+ posEnd = pos -1;
+ if(posEnd > posStart) {
+ joinPC();
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+ if(pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ } else if(ch == '\n') {
+ if(!normalizedCR && usePC) {
+ if(pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ }
+ normalizedCR = false;
+ } else {
+ if(usePC) {
+ if(pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = ch;
+ }
+ normalizedCR = false;
+ }
+ }
+ } else {
+ throw new XmlPullParserException(
+ "only whitespace content allowed before start tag and not "+printable(ch),
+ this, null);
+ }
+ ch = more();
+ }
+ }
+
+ protected int parseEpilog()
+ throws XmlPullParserException, IOException
+ {
+ if(eventType == END_DOCUMENT) {
+ throw new XmlPullParserException("already reached end of XML input", this, null);
+ }
+ if(reachedEnd) {
+ return eventType = END_DOCUMENT;
+ }
+ boolean gotS = false;
+ final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
+ boolean normalizedCR = false;
+ try {
+ // epilog: Misc*
+ char ch;
+ if(seenMarkup) {
+ ch = buf[ pos - 1 ];
+ } else {
+ ch = more();
+ }
+ seenMarkup = false;
+ posStart = pos - 1;
+ if(!reachedEnd) {
+ while(true) {
+ // deal with Misc
+ // [27] Misc ::= Comment | PI | S
+ if(ch == '<') {
+ if(gotS && tokenize) {
+ posEnd = pos - 1;
+ seenMarkup = true;
+ return eventType = IGNORABLE_WHITESPACE;
+ }
+ ch = more();
+ if(reachedEnd) {
+ break;
+ }
+ if(ch == '?') {
+ // check if it is 'xml'
+ // deal with XMLDecl
+ parsePI();
+ if(tokenize) return eventType = PROCESSING_INSTRUCTION;
+
+ } else if(ch == '!') {
+ ch = more();
+ if(reachedEnd) {
+ break;
+ }
+ if(ch == 'D') {
+ parseDocdecl(); //FIXME
+ if(tokenize) return eventType = DOCDECL;
+ } else if(ch == '-') {
+ parseComment();
+ if(tokenize) return eventType = COMMENT;
+ } else {
+ throw new XmlPullParserException(
+ "unexpected markup <!"+printable(ch), this, null);
+ }
+ } else if(ch == '/') {
+ throw new XmlPullParserException(
+ "end tag not allowed in epilog but got "+printable(ch), this, null);
+ } else if(isNameStartChar(ch)) {
+ throw new XmlPullParserException(
+ "start tag not allowed in epilog but got "+printable(ch), this, null);
+ } else {
+ throw new XmlPullParserException(
+ "in epilog expected ignorable content and not "+printable(ch),
+ this, null);
+ }
+ } else if(isS(ch)) {
+ gotS = true;
+ if(normalizeIgnorableWS) {
+ if(ch == '\r') {
+ normalizedCR = true;
+ //posEnd = pos -1;
+ //joinPC();
+ // posEnd is already set
+ if(!usePC) {
+ posEnd = pos -1;
+ if(posEnd > posStart) {
+ joinPC();
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+ if(pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ } else if(ch == '\n') {
+ if(!normalizedCR && usePC) {
+ if(pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ }
+ normalizedCR = false;
+ } else {
+ if(usePC) {
+ if(pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = ch;
+ }
+ normalizedCR = false;
+ }
+ }
+ } else {
+ throw new XmlPullParserException(
+ "in epilog non whitespace content is not allowed but got "+printable(ch),
+ this, null);
+ }
+ ch = more();
+ if(reachedEnd) {
+ break;
+ }
+
+ }
+ }
+
+ // throw Exception("unexpected content in epilog
+ // catch EOFException return END_DOCUMENT
+ //try {
+ } catch(EOFException ex) {
+ reachedEnd = true;
+ }
+ if(reachedEnd) {
+ if(tokenize && gotS) {
+ posEnd = pos; // well - this is LAST available character pos
+ return eventType = IGNORABLE_WHITESPACE;
+ }
+ return eventType = END_DOCUMENT;
+ } else {
+ throw new XmlPullParserException("internal error in parseEpilog");
+ }
+ }
+
+
+ public int parseEndTag() throws XmlPullParserException, IOException {
+ //ASSUMPTION ch is past "</"
+ // [42] ETag ::= '</' Name S? '>'
+ char ch = more();
+ if(!isNameStartChar(ch)) {
+ throw new XmlPullParserException(
+ "expected name start and not "+printable(ch), this, null);
+ }
+ posStart = pos - 3;
+ final int nameStart = pos - 1 + bufAbsoluteStart;
+ do {
+ ch = more();
+ } while(isNameChar(ch));
+
+ // now we go one level down -- do checks
+ //--depth; //FIXME
+
+ // check that end tag name is the same as start tag
+ //String name = new String(buf, nameStart - bufAbsoluteStart,
+ // (pos - 1) - (nameStart - bufAbsoluteStart));
+ //int last = pos - 1;
+ int off = nameStart - bufAbsoluteStart;
+ //final int len = last - off;
+ final int len = (pos - 1) - off;
+ final char[] cbuf = elRawName[depth];
+ if(elRawNameEnd[depth] != len) {
+ // construct strings for exception
+ final String startname = new String(cbuf, 0, elRawNameEnd[depth]);
+ final String endname = new String(buf, off, len);
+ throw new XmlPullParserException(
+ "end tag name </"+endname+"> must match start tag name <"+startname+">"
+ +" from line "+elRawNameLine[depth], this, null);
+ }
+ for (int i = 0; i < len; i++)
+ {
+ if(buf[off++] != cbuf[i]) {
+ // construct strings for exception
+ final String startname = new String(cbuf, 0, len);
+ final String endname = new String(buf, off - i - 1, len);
+ throw new XmlPullParserException(
+ "end tag name </"+endname+"> must be the same as start tag <"+startname+">"
+ +" from line "+elRawNameLine[depth], this, null);
+ }
+ }
+
+ while(isS(ch)) { ch = more(); } // skip additional white spaces
+ if(ch != '>') {
+ throw new XmlPullParserException(
+ "expected > to finsh end tag not "+printable(ch)
+ +" from line "+elRawNameLine[depth], this, null);
+ }
+
+
+ //namespaceEnd = elNamespaceCount[ depth ]; //FIXME
+
+ posEnd = pos;
+ pastEndTag = true;
+ return eventType = END_TAG;
+ }
+
+ public int parseStartTag() throws XmlPullParserException, IOException {
+ //ASSUMPTION ch is past <T
+ // [40] STag ::= '<' Name (S Attribute)* S? '>'
+ // [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
+ ++depth; //FIXME
+
+ posStart = pos - 2;
+
+ emptyElementTag = false;
+ attributeCount = 0;
+ // retrieve name
+ final int nameStart = pos - 1 + bufAbsoluteStart;
+ int colonPos = -1;
+ char ch = buf[ pos - 1];
+ if(ch == ':' && processNamespaces) throw new XmlPullParserException(
+ "when namespaces processing enabled colon can not be at element name start",
+ this, null);
+ while(true) {
+ ch = more();
+ if(!isNameChar(ch)) break;
+ if(ch == ':' && processNamespaces) {
+ if(colonPos != -1) throw new XmlPullParserException(
+ "only one colon is allowed in name of element when namespaces are enabled",
+ this, null);
+ colonPos = pos - 1 + bufAbsoluteStart;
+ }
+ }
+
+ // retrieve name
+ ensureElementsCapacity();
+
+
+ //TODO check for efficient interning and then use elRawNameInterned!!!!
+
+ int elLen = (pos - 1) - (nameStart - bufAbsoluteStart);
+ if(elRawName[ depth ] == null || elRawName[ depth ].length < elLen) {
+ elRawName[ depth ] = new char[ 2 * elLen ];
+ }
+ System.arraycopy(buf, nameStart - bufAbsoluteStart, elRawName[ depth ], 0, elLen);
+ elRawNameEnd[ depth ] = elLen;
+ elRawNameLine[ depth ] = lineNumber;
+
+ String name = null;
+
+ // work on prefixes and namespace URI
+ String prefix = null;
+ if(processNamespaces) {
+ if(colonPos != -1) {
+ prefix = elPrefix[ depth ] = newString(buf, nameStart - bufAbsoluteStart,
+ colonPos - nameStart);
+ name = elName[ depth ] = newString(buf, colonPos + 1 - bufAbsoluteStart,
+ //(pos -1) - (colonPos + 1));
+ pos - 2 - (colonPos - bufAbsoluteStart));
+ } else {
+ prefix = elPrefix[ depth ] = null;
+ name = elName[ depth ] = newString(buf, nameStart - bufAbsoluteStart, elLen);
+ }
+ } else {
+
+ name = elName[ depth ] = newString(buf, nameStart - bufAbsoluteStart, elLen);
+
+ }
+
+
+ while(true) {
+
+ while(isS(ch)) { ch = more(); } // skip additional white spaces
+
+ if(ch == '>') {
+ break;
+ } else if(ch == '/') {
+ if(emptyElementTag) throw new XmlPullParserException(
+ "repeated / in tag declaration", this, null);
+ emptyElementTag = true;
+ ch = more();
+ if(ch != '>') throw new XmlPullParserException(
+ "expected > to end empty tag not "+printable(ch), this, null);
+ break;
+ } else if(isNameStartChar(ch)) {
+ ch = parseAttribute();
+ ch = more();
+ continue;
+ } else {
+ throw new XmlPullParserException(
+ "start tag unexpected character "+printable(ch), this, null);
+ }
+ //ch = more(); // skip space
+ }
+
+ // now when namespaces were declared we can resolve them
+ if(processNamespaces) {
+ String uri = getNamespace(prefix);
+ if(uri == null) {
+ if(prefix == null) { // no prefix and no uri => use default namespace
+ uri = NO_NAMESPACE;
+ } else {
+ throw new XmlPullParserException(
+ "could not determine namespace bound to element prefix "+prefix,
+ this, null);
+ }
+
+ }
+ elUri[ depth ] = uri;
+
+
+ //String uri = getNamespace(prefix);
+ //if(uri == null && prefix == null) { // no prefix and no uri => use default namespace
+ // uri = "";
+ //}
+ // resolve attribute namespaces
+ for (int i = 0; i < attributeCount; i++)
+ {
+ final String attrPrefix = attributePrefix[ i ];
+ if(attrPrefix != null) {
+ final String attrUri = getNamespace(attrPrefix);
+ if(attrUri == null) {
+ throw new XmlPullParserException(
+ "could not determine namespace bound to attribute prefix "+attrPrefix,
+ this, null);
+
+ }
+ attributeUri[ i ] = attrUri;
+ } else {
+ attributeUri[ i ] = NO_NAMESPACE;
+ }
+ }
+
+ //TODO
+ //[ WFC: Unique Att Spec ]
+ // check namespaced attribute uniqueness contraint!!!
+
+ for (int i = 1; i < attributeCount; i++)
+ {
+ for (int j = 0; j < i; j++)
+ {
+ if( attributeUri[j] == attributeUri[i]
+ && (allStringsInterned && attributeName[j].equals(attributeName[i])
+ || (!allStringsInterned
+ && attributeNameHash[ j ] == attributeNameHash[ i ]
+ && attributeName[j].equals(attributeName[i])) )
+
+ ) {
+ // prepare data for nice error messgae?
+ String attr1 = attributeName[j];
+ if(attributeUri[j] != null) attr1 = attributeUri[j]+":"+attr1;
+ String attr2 = attributeName[i];
+ if(attributeUri[i] != null) attr2 = attributeUri[i]+":"+attr2;
+ throw new XmlPullParserException(
+ "duplicated attributes "+attr1+" and "+attr2, this, null);
+ }
+ }
+ }
+
+
+ } else { // ! processNamespaces
+
+ //[ WFC: Unique Att Spec ]
+ // check raw attribute uniqueness contraint!!!
+ for (int i = 1; i < attributeCount; i++)
+ {
+ for (int j = 0; j < i; j++)
+ {
+ if((allStringsInterned && attributeName[j].equals(attributeName[i])
+ || (!allStringsInterned
+ && attributeNameHash[ j ] == attributeNameHash[ i ]
+ && attributeName[j].equals(attributeName[i])) )
+
+ ) {
+ // prepare data for nice error messgae?
+ final String attr1 = attributeName[j];
+ final String attr2 = attributeName[i];
+ throw new XmlPullParserException(
+ "duplicated attributes "+attr1+" and "+attr2, this, null);
+ }
+ }
+ }
+ }
+
+ elNamespaceCount[ depth ] = namespaceEnd;
+ posEnd = pos;
+ return eventType = START_TAG;
+ }
+
+ protected char parseAttribute() throws XmlPullParserException, IOException
+ {
+ // parse attribute
+ // [41] Attribute ::= Name Eq AttValue
+ // [WFC: No External Entity References]
+ // [WFC: No < in Attribute Values]
+ final int prevPosStart = posStart + bufAbsoluteStart;
+ final int nameStart = pos - 1 + bufAbsoluteStart;
+ int colonPos = -1;
+ char ch = buf[ pos - 1 ];
+ if(ch == ':' && processNamespaces) throw new XmlPullParserException(
+ "when namespaces processing enabled colon can not be at attribute name start",
+ this, null);
+
+
+ boolean startsWithXmlns = processNamespaces && ch == 'x';
+ int xmlnsPos = 0;
+
+ ch = more();
+ while(isNameChar(ch)) {
+ if(processNamespaces) {
+ if(startsWithXmlns && xmlnsPos < 5) {
+ ++xmlnsPos;
+ if(xmlnsPos == 1) { if(ch != 'm') startsWithXmlns = false; }
+ else if(xmlnsPos == 2) { if(ch != 'l') startsWithXmlns = false; }
+ else if(xmlnsPos == 3) { if(ch != 'n') startsWithXmlns = false; }
+ else if(xmlnsPos == 4) { if(ch != 's') startsWithXmlns = false; }
+ else if(xmlnsPos == 5) {
+ if(ch != ':') throw new XmlPullParserException(
+ "after xmlns in attribute name must be colon"
+ +"when namespaces are enabled", this, null);
+ //colonPos = pos - 1 + bufAbsoluteStart;
+ }
+ }
+ if(ch == ':') {
+ if(colonPos != -1) throw new XmlPullParserException(
+ "only one colon is allowed in attribute name"
+ +" when namespaces are enabled", this, null);
+ colonPos = pos - 1 + bufAbsoluteStart;
+ }
+ }
+ ch = more();
+ }
+
+ ensureAttributesCapacity(attributeCount);
+
+ // --- start processing attributes
+ String name = null;
+ String prefix = null;
+ // work on prefixes and namespace URI
+ if(processNamespaces) {
+ if(xmlnsPos < 4) startsWithXmlns = false;
+ if(startsWithXmlns) {
+ if(colonPos != -1) {
+ //prefix = attributePrefix[ attributeCount ] = null;
+ final int nameLen = pos - 2 - (colonPos - bufAbsoluteStart);
+ if(nameLen == 0) {
+ throw new XmlPullParserException(
+ "namespace prefix is required after xmlns: "
+ +" when namespaces are enabled", this, null);
+ }
+ name = //attributeName[ attributeCount ] =
+ newString(buf, colonPos - bufAbsoluteStart + 1, nameLen);
+ //pos - 1 - (colonPos + 1 - bufAbsoluteStart)
+ }
+ } else {
+ if(colonPos != -1) {
+ int prefixLen = colonPos - nameStart;
+ prefix = attributePrefix[ attributeCount ] =
+ newString(buf, nameStart - bufAbsoluteStart,prefixLen);
+ //colonPos - (nameStart - bufAbsoluteStart));
+ int nameLen = pos - 2 - (colonPos - bufAbsoluteStart);
+ name = attributeName[ attributeCount ] =
+ newString(buf, colonPos - bufAbsoluteStart + 1, nameLen);
+ //pos - 1 - (colonPos + 1 - bufAbsoluteStart));
+
+ //name.substring(0, colonPos-nameStart);
+ } else {
+ prefix = attributePrefix[ attributeCount ] = null;
+ name = attributeName[ attributeCount ] =
+ newString(buf, nameStart - bufAbsoluteStart,
+ pos - 1 - (nameStart - bufAbsoluteStart));
+ }
+ if(!allStringsInterned) {
+ attributeNameHash[ attributeCount ] = name.hashCode();
+ }
+ }
+
+ } else {
+ // retrieve name
+ name = attributeName[ attributeCount ] =
+ newString(buf, nameStart - bufAbsoluteStart,
+ pos - 1 - (nameStart - bufAbsoluteStart));
+ ////assert name != null;
+ if(!allStringsInterned) {
+ attributeNameHash[ attributeCount ] = name.hashCode();
+ }
+ }
+
+ // [25] Eq ::= S? '=' S?
+ while(isS(ch)) { ch = more(); } // skip additional spaces
+ if(ch != '=') throw new XmlPullParserException(
+ "expected = after attribute name", this, null);
+ ch = more();
+ while(isS(ch)) { ch = more(); } // skip additional spaces
+
+ // [10] AttValue ::= '"' ([^<&"] | Reference)* '"'
+ // | "'" ([^<&'] | Reference)* "'"
+ final char delimit = ch;
+ if(delimit != '"' && delimit != '\'') throw new XmlPullParserException(
+ "attribute value must start with quotation or apostrophe not "
+ +printable(delimit), this, null);
+ // parse until delimit or < and resolve Reference
+ //[67] Reference ::= EntityRef | CharRef
+ //int valueStart = pos + bufAbsoluteStart;
+
+
+ boolean normalizedCR = false;
+ usePC = false;
+ pcStart = pcEnd;
+ posStart = pos;
+
+ while(true) {
+ ch = more();
+ if(ch == delimit) {
+ break;
+ } if(ch == '<') {
+ throw new XmlPullParserException(
+ "markup not allowed inside attribute value - illegal < ", this, null);
+ } if(ch == '&') {
+ // extractEntityRef
+ posEnd = pos - 1;
+ if(!usePC) {
+ final boolean hadCharData = posEnd > posStart;
+ if(hadCharData) {
+ // posEnd is already set correctly!!!
+ joinPC();
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+
+ final char[] resolvedEntity = parseEntityRef();
+ // check if replacement text can be resolved !!!
+ if(resolvedEntity == null) {
+ if(entityRefName == null) {
+ entityRefName = newString(buf, posStart, posEnd - posStart);
+ }
+ throw new XmlPullParserException(
+ "could not resolve entity named '"+printable(entityRefName)+"'",
+ this, null);
+ }
+ // write into PC replacement text - do merge for replacement text!!!!
+ for (int i = 0; i < resolvedEntity.length; i++)
+ {
+ if(pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = resolvedEntity[ i ];
+ }
+ } else if(ch == '\t' || ch == '\n' || ch == '\r') {
+ // do attribute value normalization
+ // as described in http://www.w3.org/TR/REC-xml#AVNormalize
+ // TODO add test for it form spec ...
+ // handle EOL normalization ...
+ if(!usePC) {
+ posEnd = pos - 1;
+ if(posEnd > posStart) {
+ joinPC();
+ } else {
+ usePC = true;
+ pcEnd = pcStart = 0;
+ }
+ }
+ //assert usePC == true;
+ if(pcEnd >= pc.length) ensurePC(pcEnd);
+ if(ch != '\n' || !normalizedCR) {
+ pc[pcEnd++] = ' '; //'\n';
+ }
+
+ } else {
+ if(usePC) {
+ if(pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = ch;
+ }
+ }
+ normalizedCR = ch == '\r';
+ }
+
+
+ if(processNamespaces && startsWithXmlns) {
+ String ns = null;
+ if(!usePC) {
+ ns = newStringIntern(buf, posStart, pos - 1 - posStart);
+ } else {
+ ns = newStringIntern(pc, pcStart, pcEnd - pcStart);
+ }
+ ensureNamespacesCapacity(namespaceEnd);
+ int prefixHash = -1;
+ if(colonPos != -1) {
+ if(ns.length() == 0) {
+ throw new XmlPullParserException(
+ "non-default namespace can not be declared to be empty string", this, null);
+ }
+ // declare new namespace
+ namespacePrefix[ namespaceEnd ] = name;
+ if(!allStringsInterned) {
+ prefixHash = namespacePrefixHash[ namespaceEnd ] = name.hashCode();
+ }
+ } else {
+ // declare new default namespace...
+ namespacePrefix[ namespaceEnd ] = null; //""; //null; //TODO check FIXME Alek
+ if(!allStringsInterned) {
+ prefixHash = namespacePrefixHash[ namespaceEnd ] = -1;
+ }
+ }
+ namespaceUri[ namespaceEnd ] = ns;
+
+ // detect duplicate namespace declarations!!!
+ final int startNs = elNamespaceCount[ depth - 1 ];
+ for (int i = namespaceEnd - 1; i >= startNs; --i)
+ {
+ if(((allStringsInterned || name == null) && namespacePrefix[ i ] == name)
+ || (!allStringsInterned && name != null &&
+ namespacePrefixHash[ i ] == prefixHash
+ && name.equals(namespacePrefix[ i ])
+ ))
+ {
+ final String s = name == null ? "default" : "'"+name+"'";
+ throw new XmlPullParserException(
+ "duplicated namespace declaration for "+s+" prefix", this, null);
+ }
+ }
+
+ ++namespaceEnd;
+
+ } else {
+ if(!usePC) {
+ attributeValue[ attributeCount ] =
+ new String(buf, posStart, pos - 1 - posStart);
+ } else {
+ attributeValue[ attributeCount ] =
+ new String(pc, pcStart, pcEnd - pcStart);
+ }
+ ++attributeCount;
+ }
+ posStart = prevPosStart - bufAbsoluteStart;
+ return ch;
+ }
+
+ protected char[] charRefOneCharBuf = new char[1];
+
+ protected char[] parseEntityRef()
[... 1212 lines stripped ...]