1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of this software and associated documentation files (the "Software"), to deal 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * in the Software without restriction, including without limitation the rights 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * sell copies of the Software, and to permit persons to whom the Software is 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * furnished to do so, subject to the following conditions: 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The above copyright notice and this permission notice shall be included in 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * all copies or substantial portions of the Software. 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * IN THE SOFTWARE. */ 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// Contributors: Paul Hackenberger (unterminated entity handling in relaxed mode) 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.kxml2.io; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 25086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilsonimport java.io.Closeable; 26ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilsonimport java.io.IOException; 27ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilsonimport java.io.InputStream; 28ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilsonimport java.io.InputStreamReader; 29ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilsonimport java.io.Reader; 30ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilsonimport java.util.HashMap; 31ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilsonimport java.util.Map; 32a78c2aac2a73f001aa00971adfae90af4d6726fbJesse Wilsonimport libcore.internal.StringPool; 33ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilsonimport org.xmlpull.v1.XmlPullParser; 34ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilsonimport org.xmlpull.v1.XmlPullParserException; 35ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson 36ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson/** 3776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * An XML pull parser with limited support for parsing internal DTDs. 38ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson */ 39086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilsonpublic class KXmlParser implements XmlPullParser, Closeable { 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 416aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes private static final String PROPERTY_XMLDECL_VERSION 4276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson = "http://xmlpull.org/v1/doc/properties.html#xmldecl-version"; 436aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes private static final String PROPERTY_XMLDECL_STANDALONE 4476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson = "http://xmlpull.org/v1/doc/properties.html#xmldecl-standalone"; 456aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes private static final String PROPERTY_LOCATION = "http://xmlpull.org/v1/doc/properties.html#location"; 4676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private static final String FEATURE_RELAXED = "http://xmlpull.org/v1/doc/features.html#relaxed"; 4776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 4876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private static final Map<String, String> DEFAULT_ENTITIES = new HashMap<String, String>(); 4976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson static { 5076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson DEFAULT_ENTITIES.put("lt", "<"); 5176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson DEFAULT_ENTITIES.put("gt", ">"); 5276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson DEFAULT_ENTITIES.put("amp", "&"); 5376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson DEFAULT_ENTITIES.put("apos", "'"); 5476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson DEFAULT_ENTITIES.put("quot", "\""); 5576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 5676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 577fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final int ELEMENTDECL = 11; 587fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final int ENTITYDECL = 12; 597fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final int ATTLISTDECL = 13; 607fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final int NOTATIONDECL = 14; 617fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final int PARAMETER_ENTITY_REF = 15; 62fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private static final char[] START_COMMENT = { '<', '!', '-', '-' }; 63fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private static final char[] END_COMMENT = { '-', '-', '>' }; 64bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson private static final char[] COMMENT_DOUBLE_DASH = { '-', '-' }; 65fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private static final char[] START_CDATA = { '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[' }; 66fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private static final char[] END_CDATA = { ']', ']', '>' }; 67fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private static final char[] START_PROCESSING_INSTRUCTION = { '<', '?' }; 68fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private static final char[] END_PROCESSING_INSTRUCTION = { '?', '>' }; 69fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private static final char[] START_DOCTYPE = { '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E' }; 707fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final char[] SYSTEM = { 'S', 'Y', 'S', 'T', 'E', 'M' }; 717fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final char[] PUBLIC = { 'P', 'U', 'B', 'L', 'I', 'C' }; 727fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final char[] START_ELEMENT = { '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T' }; 737fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final char[] START_ATTLIST = { '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T' }; 747fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final char[] START_ENTITY = { '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y' }; 757fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final char[] START_NOTATION = { '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N' }; 767fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final char[] EMPTY = new char[] { 'E', 'M', 'P', 'T', 'Y' }; 777fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final char[] ANY = new char[]{ 'A', 'N', 'Y' }; 787fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final char[] NDATA = new char[]{ 'N', 'D', 'A', 'T', 'A' }; 797fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final char[] NOTATION = new char[]{ 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N' }; 807fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final char[] REQUIRED = new char[] { 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D' }; 817fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final char[] IMPLIED = new char[] { 'I', 'M', 'P', 'L', 'I', 'E', 'D' }; 827fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private static final char[] FIXED = new char[] { 'F', 'I', 'X', 'E', 'D' }; 83fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 84d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes static final private String UNEXPECTED_EOF = "Unexpected EOF"; 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project static final private String ILLEGAL_TYPE = "Wrong event type"; 86fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson static final private int XML_DECLARATION = 998; 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // general 89fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private String location; 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String version; 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Boolean standalone; 93086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson private String rootElementName; 94086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson private String systemId; 95086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson private String publicId; 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson /** 9876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * True if the {@code <!DOCTYPE>} contents are handled. The DTD defines 9976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * entity values and default attribute values. These values are parsed at 10076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * inclusion time and may contain both tags and entity references. 10176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * 10276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <p>If this is false, the user must {@link #defineEntityReplacementText 10376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * define entity values manually}. Such entity values are literal strings 10476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * and will not be parsed. There is no API to define default attributes 10576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * manually. 10676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson */ 10776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private boolean processDocDecl; 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean processNsp; 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean relaxed; 110ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson private boolean keepNamespaceAttributes; 11176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 11276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson /** 11338e84b835c2101206d846f7ab6fc444914661753Jesse Wilson * If non-null, the contents of the read buffer must be copied into this 11438e84b835c2101206d846f7ab6fc444914661753Jesse Wilson * string builder before the read buffer is overwritten. This is used to 11538e84b835c2101206d846f7ab6fc444914661753Jesse Wilson * capture the raw DTD text while parsing the DTD. 11638e84b835c2101206d846f7ab6fc444914661753Jesse Wilson */ 11738e84b835c2101206d846f7ab6fc444914661753Jesse Wilson private StringBuilder bufferCapture; 11838e84b835c2101206d846f7ab6fc444914661753Jesse Wilson 11938e84b835c2101206d846f7ab6fc444914661753Jesse Wilson /** 12076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * Entities defined in or for this document. This map is created lazily. 12176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson */ 12276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private Map<String, char[]> documentEntities; 12376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 12476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson /** 12576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * Default attributes in this document. The outer map's key is the element 12676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * name; the inner map's key is the attribute name. Both keys should be 12776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * without namespace adjustments. This map is created lazily. 12876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson */ 12976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private Map<String, Map<String, String>> defaultAttributes; 13076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 13176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int depth; 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String[] elementStack = new String[16]; 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String[] nspStack = new String[8]; 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int[] nspCounts = new int[4]; 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // source 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Reader reader; 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String encoding; 14176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private ContentSource nextContentSource; 14276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private char[] buffer = new char[8192]; 143fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private int position = 0; 144fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private int limit = 0; 145fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 146fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson /* 147fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * Track the number of newlines and columns preceding the current buffer. To 148fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * compute the line and column of a position in the buffer, compute the line 149fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * and column in the buffer and add the preceding values. 150fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson */ 151fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private int bufferStartLine; 152fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private int bufferStartColumn; 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 154fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // the current token 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int type; 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean isWhitespace; 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String namespace; 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String prefix; 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String name; 161fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private String text; 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean degenerated; 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int attributeCount; 1651ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson 1660424d12f9b8a19c4a451282bc8ae974f6109424dNarayan Kamath // true iff. we've encountered the START_TAG of an XML element at depth == 0; 1670424d12f9b8a19c4a451282bc8ae974f6109424dNarayan Kamath private boolean parsedTopLevelStartTag; 1680424d12f9b8a19c4a451282bc8ae974f6109424dNarayan Kamath 169fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson /* 1701ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * The current element's attributes arranged in groups of 4: 1711ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * i + 0 = attribute namespace URI 1721ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * i + 1 = attribute namespace prefix 1731ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * i + 2 = attribute qualified name (may contain ":", as in "html:h1") 1741ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * i + 3 = attribute value 1751ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson */ 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String[] attributes = new String[16]; 177ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String error; 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean unresolved; 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 182a78c2aac2a73f001aa00971adfae90af4d6726fbJesse Wilson public final StringPool stringPool = new StringPool(); 183a78c2aac2a73f001aa00971adfae90af4d6726fbJesse Wilson 1841ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson /** 185ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson * Retains namespace attributes like {@code xmlns="http://foo"} or {@code xmlns:foo="http:foo"} 186ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson * in pulled elements. Most applications will only be interested in the effective namespaces of 187ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson * their elements, so these attributes aren't useful. But for structure preserving wrappers like 188ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson * DOM, it is necessary to keep the namespace data around. 1891ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson */ 1901ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson public void keepNamespaceAttributes() { 1911ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson this.keepNamespaceAttributes = true; 1921ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson } 1931ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson 194ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson private boolean adjustNsp() throws XmlPullParserException { 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean any = false; 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < attributeCount << 2; i += 4) { 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String attrName = attributes[i + 2]; 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int cut = attrName.indexOf(':'); 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String prefix; 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (cut != -1) { 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project prefix = attrName.substring(0, cut); 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project attrName = attrName.substring(cut + 1); 205ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else if (attrName.equals("xmlns")) { 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project prefix = attrName; 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project attrName = null; 208ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else { 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 210ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!prefix.equals("xmlns")) { 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project any = true; 214ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else { 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int j = (nspCounts[depth]++) << 1; 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project nspStack = ensureCapacity(nspStack, j + 2); 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project nspStack[j] = attrName; 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project nspStack[j + 1] = attributes[i + 3]; 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 221ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (attrName != null && attributes[i + 3].isEmpty()) { 222fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("illegal empty namespace"); 223ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2251ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson if (keepNamespaceAttributes) { 226f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // explicitly set the namespace for unprefixed attributes 2271ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson // such as xmlns="http://foo" 2281ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson attributes[i] = "http://www.w3.org/2000/xmlns/"; 2291ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson any = true; 2301ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson } else { 2311ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson System.arraycopy( 2321ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson attributes, 2331ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson i + 4, 2341ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson attributes, 2351ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson i, 2361ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson ((--attributeCount) << 2) - i); 2371ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson 2381ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson i -= 4; 2391ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson } 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (any) { 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4) { 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String attrName = attributes[i + 2]; 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int cut = attrName.indexOf(':'); 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 249ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (cut == 0 && !relaxed) { 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new RuntimeException( 251ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson "illegal attribute name: " + attrName + " at " + this); 252ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else if (cut != -1) { 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String attrPrefix = attrName.substring(0, cut); 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project attrName = attrName.substring(cut + 1); 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String attrNs = getNamespace(attrPrefix); 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 259ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (attrNs == null && !relaxed) { 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new RuntimeException( 261ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson "Undefined Prefix: " + attrPrefix + " in " + this); 262ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project attributes[i] = attrNs; 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project attributes[i + 1] = attrPrefix; 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project attributes[i + 2] = attrName; 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int cut = name.indexOf(':'); 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 273ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (cut == 0) { 274fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("illegal tag name: " + name); 275ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (cut != -1) { 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project prefix = name.substring(0, cut); 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project name = name.substring(cut + 1); 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.namespace = getNamespace(prefix); 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (this.namespace == null) { 285ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (prefix != null) { 286fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("undefined prefix: " + prefix); 287ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.namespace = NO_NAMESPACE; 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return any; 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 294ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson private String[] ensureCapacity(String[] arr, int required) { 295ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (arr.length >= required) { 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return arr; 297ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String[] bigger = new String[required + 16]; 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(arr, 0, bigger, 0, arr.length); 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return bigger; 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 303fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private void checkRelaxed(String errorMessage) throws XmlPullParserException { 304fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (!relaxed) { 305fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new XmlPullParserException(errorMessage, this, null); 306fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 307fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (error == null) { 308fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson error = "Error: " + errorMessage; 309ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 312bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson public int next() throws XmlPullParserException, IOException { 313bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson return next(false); 314bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } 315bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson 316bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson public int nextToken() throws XmlPullParserException, IOException { 317bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson return next(true); 318bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } 319bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson 320bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson private int next(boolean justOneToken) throws IOException, XmlPullParserException { 321ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (reader == null) { 322fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new XmlPullParserException("setInput() must be called first.", this, null); 323ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 325ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (type == END_TAG) { 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project depth--; 327ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 329bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson // degenerated needs to be handled before error because of possible 330bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson // processor expectations(!) 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 332bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (degenerated) { 333bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson degenerated = false; 334bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson type = END_TAG; 335bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson return type; 336bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 338bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (error != null) { 339bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (justOneToken) { 340fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson text = error; 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project type = COMMENT; 342bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson error = null; 343bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson return type; 344bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } else { 345bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson error = null; 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 347bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3497fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson type = peekType(false); 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 351bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (type == XML_DECLARATION) { 352bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson readXmlDeclaration(); 3537fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson type = peekType(false); 354bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } 355bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson 356bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson text = null; 357bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson isWhitespace = true; 358bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson prefix = null; 359bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson name = null; 360bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson namespace = null; 361bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson attributeCount = -1; 362086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson boolean throwOnResolveFailure = !justOneToken; 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 364bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson while (true) { 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project switch (type) { 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 367bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson /* 368bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson * Return immediately after encountering a start tag, end tag, or 369bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson * the end of the document. 370bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson */ 371bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson case START_TAG: 372086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson parseStartTag(false, throwOnResolveFailure); 373bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson return type; 374bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson case END_TAG: 375bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson readEndTag(); 376bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson return type; 377bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson case END_DOCUMENT: 378bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson return type; 379bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson 380bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson /* 381bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson * Return after any text token when we're looking for a single 382bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson * token. Otherwise concatenate all text between tags. 383bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson */ 384fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson case ENTITY_REF: 385bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (justOneToken) { 386fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson StringBuilder entityTextBuilder = new StringBuilder(); 387086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson readEntity(entityTextBuilder, true, throwOnResolveFailure, ValueContext.TEXT); 388fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson text = entityTextBuilder.toString(); 389bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson break; 390fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 391fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // fall-through 392fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson case TEXT: 393086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson text = readValue('<', !justOneToken, throwOnResolveFailure, ValueContext.TEXT); 394fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (depth == 0 && isWhitespace) { 395fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson type = IGNORABLE_WHITESPACE; 396fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 397bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson break; 398bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson case CDSECT: 399bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson read(START_CDATA); 400bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson text = readUntil(END_CDATA, true); 401bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson break; 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 403bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson /* 404bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson * Comments, processing instructions and declarations are returned 405bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson * when we're looking for a single token. Otherwise they're skipped. 406bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson */ 407bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson case COMMENT: 408bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson String commentText = readComment(justOneToken); 409bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (justOneToken) { 410bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson text = commentText; 411bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } 412bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson break; 413fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson case PROCESSING_INSTRUCTION: 414fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson read(START_PROCESSING_INSTRUCTION); 415bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson String processingInstruction = readUntil(END_PROCESSING_INSTRUCTION, justOneToken); 416bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (justOneToken) { 417bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson text = processingInstruction; 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 419bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson break; 420fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson case DOCDECL: 42138e84b835c2101206d846f7ab6fc444914661753Jesse Wilson readDoctype(justOneToken); 4220424d12f9b8a19c4a451282bc8ae974f6109424dNarayan Kamath if (parsedTopLevelStartTag) { 4230424d12f9b8a19c4a451282bc8ae974f6109424dNarayan Kamath throw new XmlPullParserException("Unexpected token", this, null); 4240424d12f9b8a19c4a451282bc8ae974f6109424dNarayan Kamath } 425bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson break; 4267fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 4277fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson default: 4287fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson throw new XmlPullParserException("Unexpected token", this, null); 429bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 431995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson if (depth == 0 && (type == ENTITY_REF || type == TEXT || type == CDSECT)) { 432995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson throw new XmlPullParserException("Unexpected token", this, null); 433995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson } 434995a384234fd0ba9233ebcce380628bbe346b911Jesse Wilson 435bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (justOneToken) { 436bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson return type; 437bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } 438bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson 439bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (type == IGNORABLE_WHITESPACE) { 440bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson text = null; 441fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 442bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson 443bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson /* 444bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson * We've read all that we can of a non-empty text block. Always 445bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson * report this as text, even if it was a CDATA block or entity 446bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson * reference. 447bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson */ 4487fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson int peek = peekType(false); 449bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (text != null && !text.isEmpty() && peek < TEXT) { 450bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson type = TEXT; 451bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson return type; 452bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } 453bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson 454bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson type = peek; 455fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 456fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 458fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson /** 459fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * Reads text until the specified delimiter is encountered. Consumes the 460fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * text and the delimiter. 461fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * 462fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * @param returnText true to return the read text excluding the delimiter; 463fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * false to return null. 464fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson */ 465fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private String readUntil(char[] delimiter, boolean returnText) 466fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throws IOException, XmlPullParserException { 467fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int start = position; 468fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson StringBuilder result = null; 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 470bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (returnText && text != null) { 471bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson result = new StringBuilder(); 472bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson result.append(text); 473bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } 474bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson 475fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson search: 476fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson while (true) { 4779349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko if (position + delimiter.length > limit) { 478fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (start < position && returnText) { 479fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (result == null) { 480fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result = new StringBuilder(); 481ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 482fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result.append(buffer, start, position - start); 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 484fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (!fillBuffer(delimiter.length)) { 485fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed(UNEXPECTED_EOF); 486fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson type = COMMENT; 487fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return null; 488fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 489fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson start = position; 490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 492fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // TODO: replace with Arrays.equals(buffer, position, delimiter, 0, delimiter.length) 493fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // when the VM has better method inlining 494fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson for (int i = 0; i < delimiter.length; i++) { 495fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (buffer[position + i] != delimiter[i]) { 496fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 497fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson continue search; 498fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 500fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 501fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson break; 502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 504fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int end = position; 505fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position += delimiter.length; 506fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 507fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (!returnText) { 508fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return null; 509fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else if (result == null) { 510a78c2aac2a73f001aa00971adfae90af4d6726fbJesse Wilson return stringPool.get(buffer, start, end - start); 511ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else { 512fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result.append(buffer, start, end - start); 513fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return result.toString(); 514fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 515fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 517fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson /** 518fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * Returns true if an XML declaration was read. 519fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson */ 520bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson private void readXmlDeclaration() throws IOException, XmlPullParserException { 521fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (bufferStartLine != 0 || bufferStartColumn != 0 || position != 0) { 522fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("processing instructions must not start with xml"); 523fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 525fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson read(START_PROCESSING_INSTRUCTION); 526086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson parseStartTag(true, true); 527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 528fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (attributeCount < 1 || !"version".equals(attributes[2])) { 529fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("version expected"); 530fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 532fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson version = attributes[3]; 533fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 534fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int pos = 1; 535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 536fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (pos < attributeCount && "encoding".equals(attributes[2 + 4])) { 537fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson encoding = attributes[3 + 4]; 538fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson pos++; 539fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 541fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (pos < attributeCount && "standalone".equals(attributes[4 * pos + 2])) { 542fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson String st = attributes[3 + 4 * pos]; 543fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if ("yes".equals(st)) { 544fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson standalone = Boolean.TRUE; 545fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else if ("no".equals(st)) { 546fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson standalone = Boolean.FALSE; 547fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else { 548fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("illegal standalone value: " + st); 549ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 550fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson pos++; 551fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 553fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (pos != attributeCount) { 554fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("unexpected attributes in XML declaration"); 555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 556fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 557fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson isWhitespace = true; 558fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson text = null; 559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 561bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson private String readComment(boolean returnText) throws IOException, XmlPullParserException { 562bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson read(START_COMMENT); 563bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson 564bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (relaxed) { 565bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson return readUntil(END_COMMENT, returnText); 566bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } 567bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson 568bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson String commentText = readUntil(COMMENT_DOUBLE_DASH, returnText); 569bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (peekCharacter() != '>') { 570bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson throw new XmlPullParserException("Comments may not contain --", this, null); 571bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } 572bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson position++; 573bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson return commentText; 574bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } 575bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson 5767fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson /** 5777fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * Read the document's DTD. Although this parser is non-validating, the DTD 5787fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * must be parsed to capture entity values and default attribute values. 5797fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson */ 58038e84b835c2101206d846f7ab6fc444914661753Jesse Wilson private void readDoctype(boolean saveDtdText) throws IOException, XmlPullParserException { 581fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson read(START_DOCTYPE); 58238e84b835c2101206d846f7ab6fc444914661753Jesse Wilson 58338e84b835c2101206d846f7ab6fc444914661753Jesse Wilson int startPosition = -1; 58438e84b835c2101206d846f7ab6fc444914661753Jesse Wilson if (saveDtdText) { 58538e84b835c2101206d846f7ab6fc444914661753Jesse Wilson bufferCapture = new StringBuilder(); 58638e84b835c2101206d846f7ab6fc444914661753Jesse Wilson startPosition = position; 5877fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 58838e84b835c2101206d846f7ab6fc444914661753Jesse Wilson try { 58938e84b835c2101206d846f7ab6fc444914661753Jesse Wilson skip(); 59038e84b835c2101206d846f7ab6fc444914661753Jesse Wilson rootElementName = readName(); 59138e84b835c2101206d846f7ab6fc444914661753Jesse Wilson readExternalId(true, true); 59238e84b835c2101206d846f7ab6fc444914661753Jesse Wilson skip(); 59338e84b835c2101206d846f7ab6fc444914661753Jesse Wilson if (peekCharacter() == '[') { 59438e84b835c2101206d846f7ab6fc444914661753Jesse Wilson readInternalSubset(); 59538e84b835c2101206d846f7ab6fc444914661753Jesse Wilson } 59638e84b835c2101206d846f7ab6fc444914661753Jesse Wilson skip(); 59738e84b835c2101206d846f7ab6fc444914661753Jesse Wilson } finally { 59838e84b835c2101206d846f7ab6fc444914661753Jesse Wilson if (saveDtdText) { 59938e84b835c2101206d846f7ab6fc444914661753Jesse Wilson bufferCapture.append(buffer, 0, position); 60038e84b835c2101206d846f7ab6fc444914661753Jesse Wilson bufferCapture.delete(0, startPosition); 60138e84b835c2101206d846f7ab6fc444914661753Jesse Wilson text = bufferCapture.toString(); 60238e84b835c2101206d846f7ab6fc444914661753Jesse Wilson bufferCapture = null; 60338e84b835c2101206d846f7ab6fc444914661753Jesse Wilson } 60438e84b835c2101206d846f7ab6fc444914661753Jesse Wilson } 60538e84b835c2101206d846f7ab6fc444914661753Jesse Wilson 6067fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read('>'); 607d343b157ab7b919467f1bdb06b6c5c7b49437049Wojciech Staszkiewicz skip(); 6087fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 609fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 6107fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson /** 6117fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * Reads an external ID of one of these two forms: 6127fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * SYSTEM "quoted system name" 6137fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * PUBLIC "quoted public id" "quoted system name" 6147fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * 6157fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * If the system name is not required, this also supports lone public IDs of 6167fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * this form: 6177fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * PUBLIC "quoted public id" 6187fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * 6197fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * Returns true if any ID was read. 6207fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson */ 621086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson private boolean readExternalId(boolean requireSystemName, boolean assignFields) 6227fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson throws IOException, XmlPullParserException { 6237fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 6247fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson int c = peekCharacter(); 6257fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 6267fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (c == 'S') { 6277fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(SYSTEM); 6287fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } else if (c == 'P') { 6297fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(PUBLIC); 6307fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 631086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson if (assignFields) { 632086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson publicId = readQuotedId(true); 633086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson } else { 634086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson readQuotedId(false); 635086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson } 6367fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } else { 6377fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return false; 6387fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 6397fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 6407fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 6417fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 6427fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (!requireSystemName) { 6437fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson int delimiter = peekCharacter(); 6447fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (delimiter != '"' && delimiter != '\'') { 6457fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return true; // no system name! 6467fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 6477fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 6487fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 649086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson if (assignFields) { 650086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson systemId = readQuotedId(true); 651086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson } else { 652086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson readQuotedId(false); 653086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson } 6547fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return true; 6557fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 6567fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 657086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson private static final char[] SINGLE_QUOTE = new char[] { '\'' }; 658086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson private static final char[] DOUBLE_QUOTE = new char[] { '"' }; 659086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson 6607fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson /** 6617fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * Reads a quoted string, performing no entity escaping of the contents. 6627fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson */ 663086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson private String readQuotedId(boolean returnText) throws IOException, XmlPullParserException { 6647fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson int quote = peekCharacter(); 665086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson char[] delimiter; 666086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson if (quote == '"') { 667086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson delimiter = DOUBLE_QUOTE; 668086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson } else if (quote == '\'') { 669086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson delimiter = SINGLE_QUOTE; 670086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson } else { 6717fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson throw new XmlPullParserException("Expected a quoted string", this, null); 6727fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 6737fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson position++; 674086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson return readUntil(delimiter, returnText); 6757fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 6767fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 6777fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private void readInternalSubset() throws IOException, XmlPullParserException { 6787fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read('['); 679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 6817fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 6827fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (peekCharacter() == ']') { 6837fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson position++; 6847fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return; 6857fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 6867fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 6877fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson int declarationType = peekType(true); 6887fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson switch (declarationType) { 6897fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case ELEMENTDECL: 6907fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson readElementDeclaration(); 6917fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson break; 6927fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 6937fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case ATTLISTDECL: 6947fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson readAttributeListDeclaration(); 6957fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson break; 6967fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 6977fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case ENTITYDECL: 6987fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson readEntityDeclaration(); 6997fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson break; 7007fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 7017fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case NOTATIONDECL: 7027fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson readNotationDeclaration(); 7037fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson break; 7047fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 7057fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case PROCESSING_INSTRUCTION: 7067fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(START_PROCESSING_INSTRUCTION); 7077fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson readUntil(END_PROCESSING_INSTRUCTION, false); 7087fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson break; 7097fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 7107fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case COMMENT: 7117fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson readComment(false); 7127fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson break; 7137fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 7147fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case PARAMETER_ENTITY_REF: 7157fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson throw new XmlPullParserException( 7167fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson "Parameter entity references are not supported", this, null); 7177fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 7187fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson default: 7197fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson throw new XmlPullParserException("Unexpected token", this, null); 7207fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 7217fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 7227fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 7237fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 7247fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson /** 7257fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * Read an element declaration. This contains a name and a content spec. 7267fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * <!ELEMENT foo EMPTY > 7277fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * <!ELEMENT foo (bar?,(baz|quux)) > 7287fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * <!ELEMENT foo (#PCDATA|bar)* > 7297fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson */ 7307fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private void readElementDeclaration() throws IOException, XmlPullParserException { 7317fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(START_ELEMENT); 7327fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 7337fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson readName(); 7347fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson readContentSpec(); 7357fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 7367fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read('>'); 7377fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 7387fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 7397fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson /** 7407fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * Read an element content spec. This is a regular expression-like pattern 7417fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * of names or other content specs. The following operators are supported: 7427fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * sequence: (a,b,c) 7437fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * choice: (a|b|c) 7447fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * optional: a? 7457fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * one or more: a+ 7467fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * any number: a* 7477fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * 7487fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * The special name '#PCDATA' is permitted but only if it is the first 7497fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * element of the first group: 7507fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * (#PCDATA|a|b) 7517fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * 7527fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * The top-level element must be either a choice, a sequence, or one of the 7537fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * special names EMPTY and ANY. 7547fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson */ 7557fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private void readContentSpec() throws IOException, XmlPullParserException { 7567fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson // this implementation is very lenient; it scans for balanced parens only 7577fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 7587fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson int c = peekCharacter(); 7597fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (c == '(') { 7607fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson int depth = 0; 7617fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson do { 7627fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (c == '(') { 7637fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson depth++; 7647fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } else if (c == ')') { 7657fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson depth--; 7669349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko } else if (c == -1) { 7679349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko throw new XmlPullParserException( 7689349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko "Unterminated element content spec", this, null); 769fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 7707fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson position++; 7717fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson c = peekCharacter(); 7727fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } while (depth > 0); 7737fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 7747fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (c == '*' || c == '?' || c == '+') { 7757fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson position++; 7767fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 7777fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } else if (c == EMPTY[0]) { 7787fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(EMPTY); 7797fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } else if (c == ANY[0]) { 7807fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(ANY); 7817fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } else { 7827fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson throw new XmlPullParserException("Expected element content spec", this, null); 7837fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 7847fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 7857fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 7867fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson /** 7877fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * Reads an attribute list declaration such as the following: 7887fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * <!ATTLIST foo 7897fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * bar CDATA #IMPLIED 7907fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * quux (a|b|c) "c" 7917fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * baz NOTATION (a|b|c) #FIXED "c"> 7927fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * 7937fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * Each attribute has a name, type and default. 7947fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * 7957fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * Types are one of the built-in types (CDATA, ID, IDREF, IDREFS, ENTITY, 7967fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * ENTITIES, NMTOKEN, or NMTOKENS), an enumerated type "(list|of|options)" 7977fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * or NOTATION followed by an enumerated type. 7987fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * 7997fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * The default is either #REQUIRED, #IMPLIED, #FIXED, a quoted value, or 8007fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * #FIXED with a quoted value. 8017fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson */ 8027fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private void readAttributeListDeclaration() throws IOException, XmlPullParserException { 8037fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(START_ATTLIST); 8047fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 8057fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson String elementName = readName(); 8067fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 8077fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson while (true) { 8087fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 8097fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson int c = peekCharacter(); 8107fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (c == '>') { 8117fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson position++; 8127fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return; 813fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8157fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson // attribute name 8167fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson String attributeName = readName(); 817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8187fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson // attribute type 8197fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 8207fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (position + 1 >= limit && !fillBuffer(2)) { 8217fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson throw new XmlPullParserException("Malformed attribute list", this, null); 8227fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 8237fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (buffer[position] == NOTATION[0] && buffer[position + 1] == NOTATION[1]) { 8247fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(NOTATION); 8257fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 8267fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 8277fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson c = peekCharacter(); 8287fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (c == '(') { 8297fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson position++; 8307fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson while (true) { 8317fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 8327fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson readName(); 8337fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 8347fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson c = peekCharacter(); 8357fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (c == ')') { 8367fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson position++; 8377fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson break; 8387fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } else if (c == '|') { 8397fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson position++; 8407fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } else { 8417fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson throw new XmlPullParserException("Malformed attribute type", this, null); 8427fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 843fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 8447fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } else { 8457fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson readName(); 8467fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 8477fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 8487fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson // default value 8497fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 8507fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson c = peekCharacter(); 8517fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (c == '#') { 8527fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson position++; 8537fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson c = peekCharacter(); 8547fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (c == 'R') { 8557fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(REQUIRED); 8567fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } else if (c == 'I') { 8577fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(IMPLIED); 8587fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } else if (c == 'F') { 8597fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(FIXED); 8607fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } else { 8617fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson throw new XmlPullParserException("Malformed attribute type", this, null); 862fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 8637fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 8647fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson c = peekCharacter(); 8657fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 8667fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (c == '"' || c == '\'') { 8677fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson position++; 8687fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson // TODO: does this do escaping correctly? 869086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson String value = readValue((char) c, true, true, ValueContext.ATTRIBUTE); 8709349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko if (peekCharacter() == c) { 8719349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko position++; 8729349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko } 8737fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson defineAttributeDefault(elementName, attributeName, value); 874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 875fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 8767fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 877fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 8787fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private void defineAttributeDefault(String elementName, String attributeName, String value) { 87976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (defaultAttributes == null) { 88076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson defaultAttributes = new HashMap<String, Map<String, String>>(); 88176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 88276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson Map<String, String> elementAttributes = defaultAttributes.get(elementName); 88376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (elementAttributes == null) { 88476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson elementAttributes = new HashMap<String, String>(); 88576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson defaultAttributes.put(elementName, elementAttributes); 88676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 88776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson elementAttributes.put(attributeName, value); 8887fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 8897fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 8907fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson /** 8917fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * Read an entity declaration. The value of internal entities are inline: 8927fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * <!ENTITY foo "bar"> 8937fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * 8947fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * The values of external entities must be retrieved by URL or path: 8957fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * <!ENTITY foo SYSTEM "http://host/file"> 8967fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * <!ENTITY foo PUBLIC "-//Android//Foo//EN" "http://host/file"> 8977fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * <!ENTITY foo SYSTEM "../file.png" NDATA png> 8987fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * 8997fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * Entities may be general or parameterized. Parameterized entities are 9007fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * marked by a percent sign. Such entities may only be used in the DTD: 9017fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * <!ENTITY % foo "bar"> 9027fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson */ 9037fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private void readEntityDeclaration() throws IOException, XmlPullParserException { 9047fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(START_ENTITY); 9057fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson boolean generalEntity = true; 9067fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 9077fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 9087fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (peekCharacter() == '%') { 9097fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson generalEntity = false; 9107fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson position++; 9117fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 9127fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 9137fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 9147fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson String name = readName(); 9157fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 9167fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 9177fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson int quote = peekCharacter(); 918773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson String entityValue; 9197fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (quote == '"' || quote == '\'') { 9207fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson position++; 921773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson entityValue = readValue((char) quote, true, false, ValueContext.ENTITY_DECLARATION); 9229349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko if (peekCharacter() == quote) { 9239349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko position++; 9249349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko } 925086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson } else if (readExternalId(true, false)) { 926773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson /* 927773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson * Map external entities to the empty string. This is dishonest, 928773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson * but it's consistent with Android's Expat pull parser. 929773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson */ 930773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson entityValue = ""; 9317fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 9327fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (peekCharacter() == NDATA[0]) { 9337fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(NDATA); 9347fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 9357fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson readName(); 9367fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 937bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson } else { 9387fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson throw new XmlPullParserException("Expected entity value or external ID", this, null); 939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 9407fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 941773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson if (generalEntity && processDocDecl) { 942773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson if (documentEntities == null) { 943773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson documentEntities = new HashMap<String, char[]>(); 944773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson } 945773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson documentEntities.put(name, entityValue.toCharArray()); 946773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson } 947773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson 9487fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 9497fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read('>'); 9507fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 9517fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 9527fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private void readNotationDeclaration() throws IOException, XmlPullParserException { 9537fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read(START_NOTATION); 9547fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 9557fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson readName(); 956086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson if (!readExternalId(false, false)) { 9577fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson throw new XmlPullParserException( 9587fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson "Expected external ID or public ID for notation", this, null); 9597fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 9607fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson skip(); 9617fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson read('>'); 962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 964fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private void readEndTag() throws IOException, XmlPullParserException { 965fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson read('<'); 966fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson read('/'); 967fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson name = readName(); // TODO: pass the expected name in as a hint? 968adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project skip(); 969adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project read('>'); 970adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 971fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int sp = (depth - 1) * 4; 972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (depth == 0) { 974fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("read end tag " + name + " with no tags open"); 975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project type = COMMENT; 976adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9793b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson if (name.equals(elementStack[sp + 3])) { 980ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson namespace = elementStack[sp]; 981ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson prefix = elementStack[sp + 1]; 982ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson name = elementStack[sp + 2]; 9833b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson } else if (!relaxed) { 9843b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson throw new XmlPullParserException( 9853b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson "expected: /" + elementStack[sp + 3] + " read: " + name, this, null); 986b211e13cf03c07c92ba29829c581747ba0744767Elliott Hughes } 987adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 988adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 989fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson /** 990fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * Returns the type of the next token. 991fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson */ 9927fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson private int peekType(boolean inDeclaration) throws IOException, XmlPullParserException { 993fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (position >= limit && !fillBuffer(1)) { 994fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return END_DOCUMENT; 995adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 996adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9977fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson switch (buffer[position]) { 9987fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case '&': 9997fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return ENTITY_REF; // & 10007fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case '<': 10017fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (position + 3 >= limit && !fillBuffer(4)) { 1002fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new XmlPullParserException("Dangling <", this, null); 1003fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1004adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 10057fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson switch (buffer[position + 1]) { 10067fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case '/': 10077fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return END_TAG; // </ 10087fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case '?': 1009fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // we're looking for "<?xml " with case insensitivity 1010fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if ((position + 5 < limit || fillBuffer(6)) 1011fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson && (buffer[position + 2] == 'x' || buffer[position + 2] == 'X') 1012fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson && (buffer[position + 3] == 'm' || buffer[position + 3] == 'M') 1013fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson && (buffer[position + 4] == 'l' || buffer[position + 4] == 'L') 1014fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson && (buffer[position + 5] == ' ')) { 10157fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return XML_DECLARATION; // <?xml 1016fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else { 10177fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return PROCESSING_INSTRUCTION; // <? 1018fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 10197fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case '!': 10207fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson switch (buffer[position + 2]) { 10217fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case 'D': 10227fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return DOCDECL; // <!D 10237fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case '[': 10247fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return CDSECT; // <![ 10257fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case '-': 10267fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return COMMENT; // <!- 10277fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case 'E': 10287fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson switch (buffer[position + 3]) { 10297fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case 'L': 10307fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return ELEMENTDECL; // <!EL 10317fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case 'N': 10327fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return ENTITYDECL; // <!EN 10337fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 1034866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes break; 10357fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case 'A': 10367fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return ATTLISTDECL; // <!A 10377fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case 'N': 10387fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return NOTATIONDECL; // <!N 1039fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1040866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes throw new XmlPullParserException("Unexpected <!", this, null); 10417fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson default: 10427fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return START_TAG; // < 1043fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 10447fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson case '%': 10457fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson return inDeclaration ? PARAMETER_ENTITY_REF : TEXT; 10467fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson default: 1047fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return TEXT; 1048adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1049adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1050adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1051ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson /** 1052ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson * Sets name and attributes 1053ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson */ 1054086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson private void parseStartTag(boolean xmldecl, boolean throwOnResolveFailure) 1055086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson throws IOException, XmlPullParserException { 1056ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (!xmldecl) { 1057fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson read('<'); 1058ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1059adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project name = readName(); 1060adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project attributeCount = 0; 1061adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1062adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 1063adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project skip(); 1064adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1065fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (position >= limit && !fillBuffer(1)) { 1066fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed(UNEXPECTED_EOF); 1067fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return; 1068fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1069fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1070fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int c = buffer[position]; 1071adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1072adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (xmldecl) { 1073adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (c == '?') { 1074fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1075adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project read('>'); 1076adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 1077adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1078ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else { 1079adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (c == '/') { 1080adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project degenerated = true; 1081fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1082adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project skip(); 1083adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project read('>'); 1084adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 1085fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else if (c == '>') { 1086fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1087adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 1088adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1089adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1090adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1091adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String attrName = readName(); 1092adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1093fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int i = (attributeCount++) * 4; 1094adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project attributes = ensureCapacity(attributes, i + 4); 109576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson attributes[i] = ""; 109676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson attributes[i + 1] = null; 109776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson attributes[i + 2] = attrName; 1098adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1099adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project skip(); 1100fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (position >= limit && !fillBuffer(1)) { 1101fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed(UNEXPECTED_EOF); 1102fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return; 1103fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1104fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1105fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (buffer[position] == '=') { 1106fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project skip(); 1109fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (position >= limit && !fillBuffer(1)) { 1110fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed(UNEXPECTED_EOF); 1111fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return; 1112fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1113fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson char delimiter = buffer[position]; 1114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1115fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (delimiter == '\'' || delimiter == '"') { 1116fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1117fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else if (relaxed) { 1118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project delimiter = ' '; 1119d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes } else { 1120fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new XmlPullParserException("attr value delimiter missing!", this, null); 1121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1122d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes 1123086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson attributes[i + 3] = readValue(delimiter, true, throwOnResolveFailure, 1124086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson ValueContext.ATTRIBUTE); 1125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 11269349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko if (delimiter != ' ' && peekCharacter() == delimiter) { 1127fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; // end quote 1128ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1129fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else if (relaxed) { 113076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson attributes[i + 3] = attrName; 1131fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else { 1132fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("Attr.value missing f. " + attrName); 113376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson attributes[i + 3] = attrName; 1134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1137fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int sp = depth++ * 4; 11380424d12f9b8a19c4a451282bc8ae974f6109424dNarayan Kamath if (depth == 1) { 11390424d12f9b8a19c4a451282bc8ae974f6109424dNarayan Kamath parsedTopLevelStartTag = true; 11400424d12f9b8a19c4a451282bc8ae974f6109424dNarayan Kamath } 1141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementStack = ensureCapacity(elementStack, sp + 4); 1142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementStack[sp + 3] = name; 1143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (depth >= nspCounts.length) { 1145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int[] bigger = new int[depth + 4]; 1146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(nspCounts, 0, bigger, 0, nspCounts.length); 1147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project nspCounts = bigger; 1148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project nspCounts[depth] = nspCounts[depth - 1]; 1151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1152ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (processNsp) { 1153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project adjustNsp(); 1154ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else { 1155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project namespace = ""; 1156ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 115876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson // For consistency with Expat, add default attributes after fixing namespaces. 115976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (defaultAttributes != null) { 116076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson Map<String, String> elementDefaultAttributes = defaultAttributes.get(name); 116176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (elementDefaultAttributes != null) { 116276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson for (Map.Entry<String, String> entry : elementDefaultAttributes.entrySet()) { 116376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (getAttributeValue(null, entry.getKey()) != null) { 116476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson continue; // an explicit value overrides the default 116576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 116676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 116776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson int i = (attributeCount++) * 4; 116876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson attributes = ensureCapacity(attributes, i + 4); 116976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson attributes[i] = ""; 117076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson attributes[i + 1] = null; 117176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson attributes[i + 2] = entry.getKey(); 117276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson attributes[i + 3] = entry.getValue(); 117376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 117476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 117576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 117676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 1177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementStack[sp] = namespace; 1178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementStack[sp + 1] = prefix; 1179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elementStack[sp + 2] = name; 1180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1182f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes /** 1183fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * Reads an entity reference from the buffer, resolves it, and writes the 1184fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * resolved entity to {@code out}. If the entity cannot be read or resolved, 1185fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * {@code out} will contain the partial entity reference. 1186ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson */ 1187086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson private void readEntity(StringBuilder out, boolean isEntityToken, boolean throwOnResolveFailure, 1188086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson ValueContext valueContext) throws IOException, XmlPullParserException { 1189fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int start = out.length(); 1190fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1191fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (buffer[position++] != '&') { 1192fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new AssertionError(); 1193fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1194f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 1195fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson out.append('&'); 1196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 1198fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int c = peekCharacter(); 1199fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1200b211e13cf03c07c92ba29829c581747ba0744767Elliott Hughes if (c == ';') { 12013b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson out.append(';'); 1202fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1203ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson break; 1204f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 1205fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else if (c >= 128 1206fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || (c >= '0' && c <= '9') 1207fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || (c >= 'a' && c <= 'z') 1208fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || (c >= 'A' && c <= 'Z') 1209fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || c == '_' 1210fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || c == '-' 1211fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || c == '#') { 1212fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1213fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson out.append((char) c); 1214fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1215fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else if (relaxed) { 1216fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // intentionally leave the partial reference in 'out' 1217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 1218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1219fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else { 1220fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new XmlPullParserException("unterminated entity ref", this, null); 1221fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 12243b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson String code = out.substring(start + 1, out.length() - 1); 1225fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1226bbf35ecae9bb5b69fb0d016a57a666d0a9e0f2fcJesse Wilson if (isEntityToken) { 1227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project name = code; 1228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 12303b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson if (code.startsWith("#")) { 12313b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson try { 12323b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson int c = code.startsWith("#x") 12333b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson ? Integer.parseInt(code.substring(2), 16) 12343b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson : Integer.parseInt(code.substring(1)); 12353b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson out.delete(start, out.length()); 12363b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson out.appendCodePoint(c); 12373b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson unresolved = false; 123876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson return; 12393b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson } catch (NumberFormatException notANumber) { 12403b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson throw new XmlPullParserException("Invalid character reference: &" + code); 12413b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson } catch (IllegalArgumentException invalidCodePoint) { 12423b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson throw new XmlPullParserException("Invalid character reference: &" + code); 12433b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson } 124476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 124576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 124676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (valueContext == ValueContext.ENTITY_DECLARATION) { 124776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson // keep the unresolved &code; in the text to resolve later 124876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson return; 124976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 125076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 125176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson String defaultEntity = DEFAULT_ENTITIES.get(code); 125276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (defaultEntity != null) { 12533b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson out.delete(start, out.length()); 12543b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson unresolved = false; 125576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson out.append(defaultEntity); 125676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson return; 125776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 125876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 125976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson char[] resolved; 126076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (documentEntities != null && (resolved = documentEntities.get(code)) != null) { 126176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson out.delete(start, out.length()); 126276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson unresolved = false; 126376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (processDocDecl) { 126476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson pushContentSource(resolved); // parse the entity as XML 126576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } else { 126676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson out.append(resolved); // include the entity value as text 12673b8cee4de39f9ff8199b4c1fd46cc8037fa45d15Jesse Wilson } 126876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson return; 126976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 127076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 1271773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson /* 1272773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson * The parser skipped an external DTD, and now we've encountered an 1273773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson * unknown entity that could have been declared there. Map it to the 1274773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson * empty string. This is dishonest, but it's consistent with Android's 1275773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson * old ExpatPullParser. 1276773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson */ 1277773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson if (systemId != null) { 1278773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson out.delete(start, out.length()); 1279773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson return; 1280773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson } 1281773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson 128276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson // keep the unresolved entity "&code;" in the text for relaxed clients 128376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson unresolved = true; 1284086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson if (throwOnResolveFailure) { 128576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson checkRelaxed("unresolved: &" + code + ";"); 1286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1289ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson /** 12907fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * Where a value is found impacts how that value is interpreted. For 12917fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * example, in attributes, "\n" must be replaced with a space character. In 12927fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * text, "]]>" is forbidden. In entity declarations, named references are 12937fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * not resolved. 12947fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson */ 12957fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson enum ValueContext { 12967fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson ATTRIBUTE, 12977fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson TEXT, 12987fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson ENTITY_DECLARATION 12997fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson } 13007fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson 13017fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson /** 1302fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * Returns the current text or attribute value. This also has the side 1303fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * effect of setting isWhitespace to false if a non-whitespace character is 1304fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * encountered. 1305fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * 13067fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson * @param delimiter {@code <} for text, {@code "} and {@code '} for quoted 1307fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * attributes, or a space for unquoted attributes. 1308ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson */ 1309086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson private String readValue(char delimiter, boolean resolveEntities, boolean throwOnResolveFailure, 13107fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson ValueContext valueContext) throws IOException, XmlPullParserException { 1311fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1312fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson /* 1313fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * This method returns all of the characters from the current position 1314fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * through to an appropriate delimiter. 1315fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * 1316fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * If we're lucky (which we usually are), we'll return a single slice of 1317fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * the buffer. This fast path avoids allocating a string builder. 1318fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * 1319773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson * There are 6 unlucky characters we could encounter: 1320fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * - "&": entities must be resolved. 1321773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson * - "%": parameter entities are unsupported in entity values. 1322fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * - "<": this isn't permitted in attributes unless relaxed. 1323fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * - "]": this requires a lookahead to defend against the forbidden 1324fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * CDATA section delimiter "]]>". 1325fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * - "\r": If a "\r" is followed by a "\n", we discard the "\r". If it 1326fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * isn't followed by "\n", we replace "\r" with either a "\n" 1327fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * in text nodes or a space in attribute values. 1328fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * - "\n": In attribute values, "\n" must be replaced with a space. 1329fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * 1330fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * We could also get unlucky by needing to refill the buffer midway 1331fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * through the text. 1332fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson */ 1333fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1334fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int start = position; 1335fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson StringBuilder result = null; 1336fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1337fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // if a text section was already started, prefix the start 13387fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (valueContext == ValueContext.TEXT && text != null) { 1339fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result = new StringBuilder(); 1340fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result.append(text); 1341fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1342fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1343fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson while (true) { 1344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1345fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson /* 1346fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * Make sure we have at least a single character to read from the 1347fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * buffer. This mutates the buffer, so save the partial result 1348fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * to the slow path string builder first. 1349fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson */ 1350fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (position >= limit) { 1351fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (start < position) { 1352fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (result == null) { 1353fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result = new StringBuilder(); 1354fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1355fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result.append(buffer, start, position - start); 1356fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1357fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (!fillBuffer(1)) { 1358fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return result != null ? result.toString() : ""; 1359fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1360fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson start = position; 1361fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1363fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson char c = buffer[position]; 1364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1365fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (c == delimiter 1366fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || (delimiter == ' ' && (c <= ' ' || c == '>')) 1367fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || c == '&' && !resolveEntities) { 1368ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson break; 1369ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1371fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (c != '\r' 13727fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson && (c != '\n' || valueContext != ValueContext.ATTRIBUTE) 1373fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson && c != '&' 1374fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson && c != '<' 1375773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson && (c != ']' || valueContext != ValueContext.TEXT) 1376773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson && (c != '%' || valueContext != ValueContext.ENTITY_DECLARATION)) { 1377fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson isWhitespace &= (c <= ' '); 1378fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1379fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson continue; 1380ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1382ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson /* 1383fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * We've encountered an unlucky character! Convert from fast 1384fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * path to slow path if we haven't done so already. 1385ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson */ 1386fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (result == null) { 1387fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result = new StringBuilder(); 13886bcf32ab404c39b85d25430f6df16503ef3526cfElliott Hughes } 1389fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result.append(buffer, start, position - start); 1390fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1391fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (c == '\r') { 1392fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if ((position + 1 < limit || fillBuffer(2)) && buffer[position + 1] == '\n') { 1393fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1394fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 13957fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson c = (valueContext == ValueContext.ATTRIBUTE) ? ' ' : '\n'; 1396fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1397fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else if (c == '\n') { 1398fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson c = ' '; 1399fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1400fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else if (c == '&') { 1401fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson isWhitespace = false; // TODO: what if the entity resolves to whitespace? 1402086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson readEntity(result, false, throwOnResolveFailure, valueContext); 1403fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson start = position; 1404fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson continue; 1405fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1406fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else if (c == '<') { 14077fac047a67ee9a0295e4dc798c7c6880ccd83513Jesse Wilson if (valueContext == ValueContext.ATTRIBUTE) { 1408fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("Illegal: \"<\" inside attribute value"); 1409fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1410fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson isWhitespace = false; 1411fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1412fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else if (c == ']') { 1413fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if ((position + 2 < limit || fillBuffer(3)) 1414fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson && buffer[position + 1] == ']' && buffer[position + 2] == '>') { 1415fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("Illegal: \"]]>\" outside CDATA section"); 1416fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1417fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson isWhitespace = false; 1418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1419773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson } else if (c == '%') { 1420773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson throw new XmlPullParserException("This parser doesn't support parameter entities", 1421773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson this, null); 1422773533775fab54079cebc329d54f6286f5ac16f2Jesse Wilson 1423ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else { 1424fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new AssertionError(); 1425ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1427fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1428fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result.append(c); 1429fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson start = position; 1430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1432fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (result == null) { 1433a78c2aac2a73f001aa00971adfae90af4d6726fbJesse Wilson return stringPool.get(buffer, start, position - start); 1434fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else { 1435fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result.append(buffer, start, position - start); 1436fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return result.toString(); 1437ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1440fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private void read(char expected) throws IOException, XmlPullParserException { 1441fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int c = peekCharacter(); 1442fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (c != expected) { 1443fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("expected: '" + expected + "' actual: '" + ((char) c) + "'"); 14449349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko if (c == -1) { 14459349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko return; // On EOF, don't move position beyond limit 14469349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko } 1447fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1448fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1449fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1451fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private void read(char[] chars) throws IOException, XmlPullParserException { 14529349ec01a1bebc3b704b400fb00ccfb42e047a02Vladimir Marko if (position + chars.length > limit && !fillBuffer(chars.length)) { 1453fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("expected: '" + new String(chars) + "' but was EOF"); 1454fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return; 1455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1457fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // TODO: replace with Arrays.equals(buffer, position, delimiter, 0, delimiter.length) 1458fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // when the VM has better method inlining 1459fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson for (int i = 0; i < chars.length; i++) { 1460fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (buffer[position + i] != chars[i]) { 1461fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("expected: \"" + new String(chars) + "\" but was \"" 1462fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson + new String(buffer, position, chars.length) + "...\""); 1463fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1464fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1466fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position += chars.length; 1467fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1469fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson private int peekCharacter() throws IOException, XmlPullParserException { 1470fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (position < limit || fillBuffer(1)) { 1471fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return buffer[position]; 1472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1473fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return -1; 1474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1476ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson /** 1477fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * Returns true once {@code limit - position >= minimum}. If the data is 1478fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * exhausted before that many characters are available, this returns 1479fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * false. 1480ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson */ 148176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private boolean fillBuffer(int minimum) throws IOException, XmlPullParserException { 148276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson // If we've exhausted the current content source, remove it 148376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson while (nextContentSource != null) { 148476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (position < limit) { 148576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson throw new XmlPullParserException("Unbalanced entity!", this, null); 148676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 148776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson popContentSource(); 148876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (limit - position >= minimum) { 148976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson return true; 149076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 149176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 149276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 1493fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // Before clobbering the old characters, update where buffer starts 1494fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson for (int i = 0; i < position; i++) { 1495fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (buffer[i] == '\n') { 1496fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson bufferStartLine++; 1497fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson bufferStartColumn = 0; 1498ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else { 1499fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson bufferStartColumn++; 1500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1501fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 150338e84b835c2101206d846f7ab6fc444914661753Jesse Wilson if (bufferCapture != null) { 150438e84b835c2101206d846f7ab6fc444914661753Jesse Wilson bufferCapture.append(buffer, 0, position); 150538e84b835c2101206d846f7ab6fc444914661753Jesse Wilson } 150638e84b835c2101206d846f7ab6fc444914661753Jesse Wilson 1507fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (limit != position) { 1508fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson limit -= position; 1509fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson System.arraycopy(buffer, position, buffer, 0, limit); 1510fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else { 1511fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson limit = 0; 1512fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1514fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position = 0; 1515fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int total; 1516fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson while ((total = reader.read(buffer, limit, buffer.length - limit)) != -1) { 1517fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson limit += total; 1518fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (limit >= minimum) { 1519fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return true; 1520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1522fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return false; 1523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1525fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson /** 1526fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * Returns an element or attribute name. This is always non-empty for 1527fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * non-relaxed parsers. 1528fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson */ 1529ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson private String readName() throws IOException, XmlPullParserException { 1530fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (position >= limit && !fillBuffer(1)) { 1531fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("name expected"); 1532fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return ""; 1533ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1535fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int start = position; 1536fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson StringBuilder result = null; 1537fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1538fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // read the first character 1539fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson char c = buffer[position]; 1540fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if ((c >= 'a' && c <= 'z') 1541ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson || (c >= 'A' && c <= 'Z') 1542ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson || c == '_' 1543ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson || c == ':' 1544fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || c >= '\u00c0' // TODO: check the XML spec 1545fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || relaxed) { 1546fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1547fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else { 1548fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson checkRelaxed("name expected"); 1549fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return ""; 1550fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1552fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson while (true) { 1553fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson /* 1554fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * Make sure we have at least a single character to read from the 1555fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * buffer. This mutates the buffer, so save the partial result 1556fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson * to the slow path string builder first. 1557fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson */ 1558fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (position >= limit) { 1559fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (result == null) { 1560fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result = new StringBuilder(); 1561fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1562fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result.append(buffer, start, position - start); 1563fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (!fillBuffer(1)) { 1564fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return result.toString(); 1565fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1566fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson start = position; 1567fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1568fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1569fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // read another character 1570fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson c = buffer[position]; 1571fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if ((c >= 'a' && c <= 'z') 1572fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || (c >= 'A' && c <= 'Z') 1573fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || (c >= '0' && c <= '9') 1574fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || c == '_' 1575fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || c == '-' 1576fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || c == ':' 1577fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || c == '.' 1578fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson || c >= '\u00b7') { // TODO: check the XML spec 1579fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1580fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson continue; 1581fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1582fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson 1583fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // we encountered a non-name character. done! 1584fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (result == null) { 1585a78c2aac2a73f001aa00971adfae90af4d6726fbJesse Wilson return stringPool.get(buffer, start, position - start); 1586fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else { 1587fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result.append(buffer, start, position - start); 1588fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return result.toString(); 1589fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1590fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 159376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private void skip() throws IOException, XmlPullParserException { 1594fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson while (position < limit || fillBuffer(1)) { 1595fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int c = buffer[position]; 1596fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (c > ' ') { 1597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 1598ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1599fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position++; 1600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // public part starts here... 1604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setInput(Reader reader) throws XmlPullParserException { 1606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.reader = reader; 1607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project type = START_DOCUMENT; 16098cfc47957f397cc0066cd923711671533f72374bNeil Fuller parsedTopLevelStartTag = false; 1610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project name = null; 1611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project namespace = null; 1612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project degenerated = false; 1613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project attributeCount = -1; 1614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project encoding = null; 1615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project version = null; 1616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project standalone = null; 1617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1618ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (reader == null) { 1619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 1620ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1622fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position = 0; 1623fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson limit = 0; 1624fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson bufferStartLine = 0; 1625fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson bufferStartColumn = 0; 1626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project depth = 0; 162776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson documentEntities = null; 1628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 16306ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson public void setInput(InputStream is, String charset) throws XmlPullParserException { 1631fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson position = 0; 1632fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson limit = 0; 16336ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson boolean detectCharset = (charset == null); 1634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1635ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (is == null) { 1636cff1616012dc0d56c2da9af2b9b1183e76c7e044Elliott Hughes throw new IllegalArgumentException("is == null"); 1637ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 16406ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson if (detectCharset) { 1641fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson // read the four bytes looking for an indication of the encoding in use 1642fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int firstFourBytes = 0; 1643fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson while (limit < 4) { 1644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int i = is.read(); 1645ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (i == -1) { 1646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 1647ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1648fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson firstFourBytes = (firstFourBytes << 8) | i; 1649fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson buffer[limit++] = (char) i; 1650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1652fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (limit == 4) { 1653fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson switch (firstFourBytes) { 16546ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson case 0x00000FEFF: // UTF-32BE BOM 16556ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson charset = "UTF-32BE"; 16566ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson limit = 0; 16576ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson break; 1658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 16596ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson case 0x0FFFE0000: // UTF-32LE BOM 16606ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson charset = "UTF-32LE"; 16616ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson limit = 0; 16626ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson break; 16636ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson 16646ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson case 0x0000003c: // '<' in UTF-32BE 16656ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson charset = "UTF-32BE"; 16666ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson buffer[0] = '<'; 16676ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson limit = 1; 16686ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson break; 16696ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson 16706ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson case 0x03c000000: // '<' in UTF-32LE 16716ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson charset = "UTF-32LE"; 16726ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson buffer[0] = '<'; 16736ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson limit = 1; 16746ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson break; 16756ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson 16766ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson case 0x0003c003f: // "<?" in UTF-16BE 16776ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson charset = "UTF-16BE"; 16786ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson buffer[0] = '<'; 16796ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson buffer[1] = '?'; 16806ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson limit = 2; 16816ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson break; 16826ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson 16836ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson case 0x03c003f00: // "<?" in UTF-16LE 16846ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson charset = "UTF-16LE"; 16856ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson buffer[0] = '<'; 16866ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson buffer[1] = '?'; 16876ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson limit = 2; 16886ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson break; 16896ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson 16906ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson case 0x03c3f786d: // "<?xm" in ASCII etc. 16916ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson while (true) { 16926ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson int i = is.read(); 16936ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson if (i == -1) { 16946ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson break; 16956ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson } 16966ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson buffer[limit++] = (char) i; 16976ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson if (i == '>') { 16986ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson String s = new String(buffer, 0, limit); 16996ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson int i0 = s.indexOf("encoding"); 17006ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson if (i0 != -1) { 17016ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson while (s.charAt(i0) != '"' && s.charAt(i0) != '\'') { 17026ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson i0++; 1703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 17046ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson char deli = s.charAt(i0++); 17056ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson int i1 = s.indexOf(deli, i0); 17066ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson charset = s.substring(i0, i1); 1707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 17086ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson break; 1709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 17106ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson } 17116ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson break; 17126ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson 17136ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson default: 17146ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson // handle a byte order mark followed by something other than <? 17156ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson if ((firstFourBytes & 0x0ffff0000) == 0x0feff0000) { 17166ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson charset = "UTF-16BE"; 17176ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson buffer[0] = (char) ((buffer[2] << 8) | buffer[3]); 17186ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson limit = 1; 17196ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson } else if ((firstFourBytes & 0x0ffff0000) == 0x0fffe0000) { 17206ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson charset = "UTF-16LE"; 17216ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson buffer[0] = (char) ((buffer[3] << 8) | buffer[2]); 17226ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson limit = 1; 17236ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson } else if ((firstFourBytes & 0x0ffffff00) == 0x0efbbbf00) { 17246ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson charset = "UTF-8"; 17256ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson buffer[0] = buffer[3]; 17266ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson limit = 1; 17276ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson } 1728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17326ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson if (charset == null) { 17336ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson charset = "UTF-8"; 1734ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17366ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson int savedLimit = limit; 17376ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson setInput(new InputStreamReader(is, charset)); 17386ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson encoding = charset; 17396ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson limit = savedLimit; 17406ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson 17416ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson /* 17426ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson * Skip the optional BOM if we didn't above. This decrements limit 17436ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson * rather than incrementing position so that <?xml version='1.0'?> 17446ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson * is still at character 0. 17456ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson */ 17466ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson if (!detectCharset && peekCharacter() == 0xfeff) { 17476ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson limit--; 17486ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson System.arraycopy(buffer, 1, buffer, 0, limit); 17496ce8e6ee5da964f724d39655fba0e432cff4c3a6Jesse Wilson } 1750ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } catch (Exception e) { 1751fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new XmlPullParserException("Invalid stream or encoding: " + e, this, e); 1752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1755086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson public void close() throws IOException { 1756086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson if (reader != null) { 1757086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson reader.close(); 1758086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson } 1759086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson } 1760086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson 1761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean getFeature(String feature) { 1762ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature)) { 1763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return processNsp; 176476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } else if (FEATURE_RELAXED.equals(feature)) { 1765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return relaxed; 176676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } else if (FEATURE_PROCESS_DOCDECL.equals(feature)) { 176776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson return processDocDecl; 1768ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else { 1769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 1770ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getInputEncoding() { 1774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return encoding; 1775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void defineEntityReplacementText(String entity, String value) 1778ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson throws XmlPullParserException { 177976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (processDocDecl) { 178076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson throw new IllegalStateException( 178176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson "Entity replacement text may not be defined with DOCTYPE processing enabled."); 178276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 178376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (reader == null) { 178476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson throw new IllegalStateException( 178576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson "Entity replacement text must be defined after setInput()"); 1786ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 178776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (documentEntities == null) { 178876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson documentEntities = new HashMap<String, char[]>(); 178976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 179076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson documentEntities.put(entity, value.toCharArray()); 1791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object getProperty(String property) { 179476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (property.equals(PROPERTY_XMLDECL_VERSION)) { 1795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return version; 179676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } else if (property.equals(PROPERTY_XMLDECL_STANDALONE)) { 1797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return standalone; 179876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } else if (property.equals(PROPERTY_LOCATION)) { 1799d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes return location != null ? location : reader.toString(); 180076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } else { 180176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson return null; 1802ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1805086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson /** 1806086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson * Returns the root element's name if it was declared in the DTD. This 1807086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson * equals the first tag's name for valid documents. 1808086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson */ 1809086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson public String getRootElementName() { 1810086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson return rootElementName; 1811086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson } 1812086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson 1813086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson /** 1814086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson * Returns the document's system ID if it was declared. This is typically a 1815086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson * string like {@code http://www.w3.org/TR/html4/strict.dtd}. 1816086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson */ 1817086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson public String getSystemId() { 1818086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson return systemId; 1819086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson } 1820086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson 1821086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson /** 1822086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson * Returns the document's public ID if it was declared. This is typically a 1823086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson * string like {@code -//W3C//DTD HTML 4.01//EN}. 1824086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson */ 1825086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson public String getPublicId() { 1826086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson return publicId; 1827086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson } 1828086fd0244a54fa5ecf13ea66d49b22b36d7d456eJesse Wilson 1829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int getNamespaceCount(int depth) { 1830ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (depth > this.depth) { 1831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IndexOutOfBoundsException(); 1832ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return nspCounts[depth]; 1834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getNamespacePrefix(int pos) { 1837fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return nspStack[pos * 2]; 1838adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1840adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getNamespaceUri(int pos) { 1841fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return nspStack[(pos * 2) + 1]; 1842adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getNamespace(String prefix) { 1845ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if ("xml".equals(prefix)) { 1846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return "http://www.w3.org/XML/1998/namespace"; 1847ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1848ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if ("xmlns".equals(prefix)) { 1849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return "http://www.w3.org/2000/xmlns/"; 1850ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = (getNamespaceCount(depth) << 1) - 2; i >= 0; i -= 2) { 1853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (prefix == null) { 1854ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (nspStack[i] == null) { 1855adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return nspStack[i + 1]; 1856ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1857ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else if (prefix.equals(nspStack[i])) { 1858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return nspStack[i + 1]; 1859ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 1862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int getDepth() { 1865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return depth; 1866adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1867adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1868adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getPositionDescription() { 1869ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson StringBuilder buf = new StringBuilder(type < TYPES.length ? TYPES[type] : "unknown"); 1870adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf.append(' '); 1871adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1872adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (type == START_TAG || type == END_TAG) { 1873ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (degenerated) { 1874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf.append("(empty) "); 1875ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf.append('<'); 1877ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (type == END_TAG) { 1878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf.append('/'); 1879ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1881ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (prefix != null) { 1882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf.append("{" + namespace + "}" + prefix + ":"); 1883ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf.append(name); 1885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1886fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int cnt = attributeCount * 4; 1887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < cnt; i += 4) { 1888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf.append(' '); 1889ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (attributes[i + 1] != null) { 1890fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson buf.append("{" + attributes[i] + "}" + attributes[i + 1] + ":"); 1891ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf.append(attributes[i + 2] + "='" + attributes[i + 3] + "'"); 1893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf.append('>'); 1896ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else if (type == IGNORABLE_WHITESPACE) { 1897ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson ; 1898ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else if (type != TEXT) { 1899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf.append(getText()); 1900ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else if (isWhitespace) { 1901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf.append("(whitespace)"); 1902ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else { 1903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String text = getText(); 1904ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (text.length() > 16) { 1905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project text = text.substring(0, 16) + "..."; 1906ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf.append(text); 1908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1910fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson buf.append("@" + getLineNumber() + ":" + getColumnNumber()); 1911ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (location != null) { 1912d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes buf.append(" in "); 1913d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes buf.append(location); 1914ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else if (reader != null) { 1915d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes buf.append(" in "); 1916d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes buf.append(reader.toString()); 1917d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes } 1918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return buf.toString(); 1919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int getLineNumber() { 1922fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int result = bufferStartLine; 1923fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson for (int i = 0; i < position; i++) { 1924fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (buffer[i] == '\n') { 1925fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result++; 1926fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1927fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1928fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return result + 1; // the first line is '1' 1929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int getColumnNumber() { 1932fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson int result = bufferStartColumn; 1933fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson for (int i = 0; i < position; i++) { 1934fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (buffer[i] == '\n') { 1935fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result = 0; 1936fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else { 1937fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson result++; 1938fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1939fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1940fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return result + 1; // the first column is '1' 1941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean isWhitespace() throws XmlPullParserException { 1944ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (type != TEXT && type != IGNORABLE_WHITESPACE && type != CDSECT) { 1945fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new XmlPullParserException(ILLEGAL_TYPE, this, null); 1946ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1947adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return isWhitespace; 1948adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getText() { 1951fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (type < TEXT || (type == ENTITY_REF && unresolved)) { 1952fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return null; 1953fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else if (text == null) { 1954fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return ""; 1955fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } else { 1956fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return text; 1957fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1958adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1960adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public char[] getTextCharacters(int[] poslen) { 1961fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson String text = getText(); 1962fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson if (text == null) { 1963fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson poslen[0] = -1; 1964fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson poslen[1] = -1; 1965fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return null; 1966fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson } 1967fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson char[] result = text.toCharArray(); 1968fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson poslen[0] = 0; 1969fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson poslen[1] = result.length; 1970fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return result; 1971adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getNamespace() { 1974adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return namespace; 1975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1976adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getName() { 1978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return name; 1979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1980adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getPrefix() { 1982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return prefix; 1983adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1984adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1985adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean isEmptyElementTag() throws XmlPullParserException { 1986ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (type != START_TAG) { 1987fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new XmlPullParserException(ILLEGAL_TYPE, this, null); 1988ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 1989adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return degenerated; 1990adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1991adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1992adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int getAttributeCount() { 1993adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return attributeCount; 1994adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1995adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1996adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getAttributeType(int index) { 1997adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return "CDATA"; 1998adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1999adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2000adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean isAttributeDefault(int index) { 2001adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 2002adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2003adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2004adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getAttributeNamespace(int index) { 2005ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (index >= attributeCount) { 2006adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IndexOutOfBoundsException(); 2007ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 2008fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return attributes[index * 4]; 2009adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2010adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2011adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getAttributeName(int index) { 2012ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (index >= attributeCount) { 2013adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IndexOutOfBoundsException(); 2014ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 2015fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return attributes[(index * 4) + 2]; 2016adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2017adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2018adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getAttributePrefix(int index) { 2019ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (index >= attributeCount) { 2020adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IndexOutOfBoundsException(); 2021ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 2022fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return attributes[(index * 4) + 1]; 2023adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2024adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2025adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getAttributeValue(int index) { 2026ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (index >= attributeCount) { 2027adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IndexOutOfBoundsException(); 2028ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 2029fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson return attributes[(index * 4) + 3]; 2030adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2031adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2032adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getAttributeValue(String namespace, String name) { 2033fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson for (int i = (attributeCount * 4) - 4; i >= 0; i -= 4) { 2034adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (attributes[i + 2].equals(name) 2035ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson && (namespace == null || attributes[i].equals(namespace))) { 2036adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return attributes[i + 3]; 2037ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 2038adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2039adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2040adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 2041adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2042adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2043adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int getEventType() throws XmlPullParserException { 2044adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return type; 2045adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2046adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2047adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // utility methods to make XML parsing easier ... 2048adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2049adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int nextTag() throws XmlPullParserException, IOException { 2050adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project next(); 2051ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (type == TEXT && isWhitespace) { 2052adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project next(); 2053ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 2054adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2055ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (type != END_TAG && type != START_TAG) { 2056fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new XmlPullParserException("unexpected type", this, null); 2057ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 2058adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2059adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return type; 2060adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2061adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2062adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void require(int type, String namespace, String name) 2063ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson throws XmlPullParserException, IOException { 2064adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (type != this.type 2065ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson || (namespace != null && !namespace.equals(getNamespace())) 2066ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson || (name != null && !name.equals(getName()))) { 2067fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new XmlPullParserException( 2068fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson "expected: " + TYPES[type] + " {" + namespace + "}" + name, this, null); 2069ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 2070adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2071adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2072adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String nextText() throws XmlPullParserException, IOException { 2073ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (type != START_TAG) { 2074fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new XmlPullParserException("precondition: START_TAG", this, null); 2075ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 2076adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2077adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project next(); 2078adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2079adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String result; 2080adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (type == TEXT) { 2081adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = getText(); 2082adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project next(); 2083ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else { 2084adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = ""; 2085ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 2086adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2087ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (type != END_TAG) { 2088fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new XmlPullParserException("END_TAG expected", this, null); 2089ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 2090adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2091adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 2092adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2093adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2094ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson public void setFeature(String feature, boolean value) throws XmlPullParserException { 2095ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature)) { 2096adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project processNsp = value; 209776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } else if (XmlPullParser.FEATURE_PROCESS_DOCDECL.equals(feature)) { 209876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson processDocDecl = value; 209976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } else if (FEATURE_RELAXED.equals(feature)) { 2100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project relaxed = value; 2101ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } else { 2102fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson throw new XmlPullParserException("unsupported feature: " + feature, this, null); 2103ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson } 2104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2106ccd79e2bb784cdbd89e90a0e4301a707091d446dJesse Wilson public void setProperty(String property, Object value) throws XmlPullParserException { 210776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson if (property.equals(PROPERTY_LOCATION)) { 2108fda724de28fe86804e6ef6a0afd7ae5be1529083Jesse Wilson location = String.valueOf(value); 2109d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes } else { 2110d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes throw new XmlPullParserException("unsupported property: " + property); 2111d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes } 2112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 211376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 211476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson /** 211576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * A chain of buffers containing XML content. Each content source contains 211676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * the parser's primary read buffer or the characters of entities actively 211776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * being parsed. 211876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * 211976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <p>For example, note the buffers needed to parse this document: 212076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <pre> {@code 212176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <!DOCTYPE foo [ 212276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <!ENTITY baz "ghi"> 212376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <!ENTITY bar "def &baz; jkl"> 212476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * ]> 212576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <foo>abc &bar; mno</foo> 212676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * }</pre> 212776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * 212876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <p>Things get interesting when the bar entity is encountered. At that 212976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * point two buffers are active: 213076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <ol> 213176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <li>The value for the bar entity, containing {@code "def &baz; jkl"} 213276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <li>The parser's primary read buffer, containing {@code " mno</foo>"} 213376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * </ol> 213476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <p>The parser will return the characters {@code "def "} from the bar 213576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * entity's buffer, and then it will encounter the baz entity. To handle 213676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * that, three buffers will be active: 213776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <ol> 213876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <li>The value for the baz entity, containing {@code "ghi"} 213976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <li>The remaining value for the bar entity, containing {@code " jkl"} 214076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <li>The parser's primary read buffer, containing {@code " mno</foo>"} 214176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * </ol> 214276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * <p>The parser will then return the characters {@code ghi jkl mno} in that 214376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * sequence by reading each buffer in sequence. 214476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson */ 214576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson static class ContentSource { 214676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private final ContentSource next; 214776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private final char[] buffer; 214876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private final int position; 214976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private final int limit; 215076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson ContentSource(ContentSource next, char[] buffer, int position, int limit) { 215176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson this.next = next; 215276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson this.buffer = buffer; 215376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson this.position = position; 215476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson this.limit = limit; 215576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 215676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 215776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 215876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson /** 215976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * Prepends the characters of {@code newBuffer} to be read before the 216076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * current buffer. 216176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson */ 216276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private void pushContentSource(char[] newBuffer) { 216376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson nextContentSource = new ContentSource(nextContentSource, buffer, position, limit); 216476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson buffer = newBuffer; 216576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson position = 0; 216676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson limit = newBuffer.length; 216776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 216876c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson 216976c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson /** 217076c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson * Replaces the current exhausted buffer with the next buffer in the chain. 217176c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson */ 217276c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson private void popContentSource() { 217376c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson buffer = nextContentSource.buffer; 217476c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson position = nextContentSource.position; 217576c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson limit = nextContentSource.limit; 217676c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson nextContentSource = nextContentSource.next; 217776c85883787791ba605a51d7bea3cfc27b5c5d95Jesse Wilson } 2178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 2179