blob: 3ee5e43ff29b13c829a0c9ed97d054680de5c77c [file] [log] [blame]
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE. */
20
21// Contributors: Paul Hackenberger (unterminated entity handling in relaxed mode)
22
23package org.kxml2.io;
24
Jesse Wilsonccd79e22010-11-04 14:02:20 -070025import java.io.IOException;
26import java.io.InputStream;
27import java.io.InputStreamReader;
28import java.io.Reader;
29import java.util.HashMap;
30import java.util.Map;
31import org.xmlpull.v1.XmlPullParser;
32import org.xmlpull.v1.XmlPullParserException;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080033
Jesse Wilsonccd79e22010-11-04 14:02:20 -070034/**
35 * A pull based XML parser.
36 */
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080037public class KXmlParser implements XmlPullParser {
38
39 private Object location;
Elliott Hughesd21d78f2010-05-13 11:32:57 -070040 static final private String UNEXPECTED_EOF = "Unexpected EOF";
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080041 static final private String ILLEGAL_TYPE = "Wrong event type";
42 static final private int LEGACY = 999;
43 static final private int XML_DECL = 998;
44
45 // general
46
47 private String version;
48 private Boolean standalone;
49
50 private boolean processNsp;
51 private boolean relaxed;
Jesse Wilsonccd79e22010-11-04 14:02:20 -070052 private boolean keepNamespaceAttributes;
53 private Map<String, String> entityMap;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080054 private int depth;
55 private String[] elementStack = new String[16];
56 private String[] nspStack = new String[8];
57 private int[] nspCounts = new int[4];
58
59 // source
60
61 private Reader reader;
62 private String encoding;
63 private char[] srcBuf;
64
65 private int srcPos;
66 private int srcCount;
67
68 private int line;
69 private int column;
70
71 // txtbuffer
72
Elliott Hughesb211e132009-11-09 16:06:42 -080073 /** Target buffer for storing incoming text (including aggregated resolved entities) */
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080074 private char[] txtBuf = new char[128];
Jesse Wilsonccd79e22010-11-04 14:02:20 -070075 /** Write position */
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080076 private int txtPos;
77
78 // Event-related
79
80 private int type;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080081 private boolean isWhitespace;
82 private String namespace;
83 private String prefix;
84 private String name;
85
86 private boolean degenerated;
87 private int attributeCount;
Jesse Wilson1ec94fe2010-02-19 09:22:21 -080088
89 /**
90 * The current element's attributes arranged in groups of 4:
91 * i + 0 = attribute namespace URI
92 * i + 1 = attribute namespace prefix
93 * i + 2 = attribute qualified name (may contain ":", as in "html:h1")
94 * i + 3 = attribute value
95 */
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080096 private String[] attributes = new String[16];
Jesse Wilsonccd79e22010-11-04 14:02:20 -070097
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080098 private String error;
99
Elliott Hughesf33eae72010-05-13 12:36:25 -0700100 /**
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700101 * A separate peek buffer seems simpler than managing wrap around in the first level read
102 * buffer
103 */
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800104 private int[] peek = new int[2];
105 private int peekCount;
106 private boolean wasCR;
107
108 private boolean unresolved;
109 private boolean token;
110
111 public KXmlParser() {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700112 srcBuf = new char[8192];
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800113 }
114
Jesse Wilson1ec94fe2010-02-19 09:22:21 -0800115 /**
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700116 * Retains namespace attributes like {@code xmlns="http://foo"} or {@code xmlns:foo="http:foo"}
117 * in pulled elements. Most applications will only be interested in the effective namespaces of
118 * their elements, so these attributes aren't useful. But for structure preserving wrappers like
119 * DOM, it is necessary to keep the namespace data around.
Jesse Wilson1ec94fe2010-02-19 09:22:21 -0800120 */
121 public void keepNamespaceAttributes() {
122 this.keepNamespaceAttributes = true;
123 }
Jesse Wilson1ec94fe2010-02-19 09:22:21 -0800124
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700125 private boolean isProp(String n1, boolean prop, String n2) {
126 if (!n1.startsWith("http://xmlpull.org/v1/doc/")) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800127 return false;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700128 }
129 if (prop) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800130 return n1.substring(42).equals(n2);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700131 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800132 return n1.substring(40).equals(n2);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700133 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800134 }
135
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700136 private boolean adjustNsp() throws XmlPullParserException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800137 boolean any = false;
138
139 for (int i = 0; i < attributeCount << 2; i += 4) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800140 String attrName = attributes[i + 2];
141 int cut = attrName.indexOf(':');
142 String prefix;
143
144 if (cut != -1) {
145 prefix = attrName.substring(0, cut);
146 attrName = attrName.substring(cut + 1);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700147 } else if (attrName.equals("xmlns")) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800148 prefix = attrName;
149 attrName = null;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700150 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800151 continue;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700152 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800153
154 if (!prefix.equals("xmlns")) {
155 any = true;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700156 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800157 int j = (nspCounts[depth]++) << 1;
158
159 nspStack = ensureCapacity(nspStack, j + 2);
160 nspStack[j] = attrName;
161 nspStack[j + 1] = attributes[i + 3];
162
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700163 if (attrName != null && attributes[i + 3].isEmpty()) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800164 error("illegal empty namespace");
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700165 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800166
Jesse Wilson1ec94fe2010-02-19 09:22:21 -0800167 if (keepNamespaceAttributes) {
Elliott Hughesf33eae72010-05-13 12:36:25 -0700168 // explicitly set the namespace for unprefixed attributes
Jesse Wilson1ec94fe2010-02-19 09:22:21 -0800169 // such as xmlns="http://foo"
170 attributes[i] = "http://www.w3.org/2000/xmlns/";
171 any = true;
172 } else {
173 System.arraycopy(
174 attributes,
175 i + 4,
176 attributes,
177 i,
178 ((--attributeCount) << 2) - i);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800179
Jesse Wilson1ec94fe2010-02-19 09:22:21 -0800180 i -= 4;
181 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800182 }
183 }
184
185 if (any) {
186 for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4) {
187
188 String attrName = attributes[i + 2];
189 int cut = attrName.indexOf(':');
190
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700191 if (cut == 0 && !relaxed) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800192 throw new RuntimeException(
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700193 "illegal attribute name: " + attrName + " at " + this);
194 } else if (cut != -1) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800195 String attrPrefix = attrName.substring(0, cut);
196
197 attrName = attrName.substring(cut + 1);
198
199 String attrNs = getNamespace(attrPrefix);
200
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700201 if (attrNs == null && !relaxed) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800202 throw new RuntimeException(
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700203 "Undefined Prefix: " + attrPrefix + " in " + this);
204 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800205
206 attributes[i] = attrNs;
207 attributes[i + 1] = attrPrefix;
208 attributes[i + 2] = attrName;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800209 }
210 }
211 }
212
213 int cut = name.indexOf(':');
214
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700215 if (cut == 0) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800216 error("illegal tag name: " + name);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700217 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800218
219 if (cut != -1) {
220 prefix = name.substring(0, cut);
221 name = name.substring(cut + 1);
222 }
223
224 this.namespace = getNamespace(prefix);
225
226 if (this.namespace == null) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700227 if (prefix != null) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800228 error("undefined prefix: " + prefix);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700229 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800230 this.namespace = NO_NAMESPACE;
231 }
232
233 return any;
234 }
235
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700236 private String[] ensureCapacity(String[] arr, int required) {
237 if (arr.length >= required) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800238 return arr;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700239 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800240 String[] bigger = new String[required + 16];
241 System.arraycopy(arr, 0, bigger, 0, arr.length);
242 return bigger;
243 }
244
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700245 private void error(String desc) throws XmlPullParserException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800246 if (relaxed) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700247 if (error == null) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800248 error = "ERR: " + desc;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700249 }
250 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800251 exception(desc);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700252 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800253 }
254
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700255 private void exception(String desc) throws XmlPullParserException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800256 throw new XmlPullParserException(
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700257 desc.length() < 100 ? desc : desc.substring(0, 100) + "\n",
258 this,
259 null);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800260 }
261
Elliott Hughesf33eae72010-05-13 12:36:25 -0700262 /**
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700263 * Common base for next() and nextToken(). Clears the state, except from txtPos and whitespace.
264 * Does not set the type variable.
265 */
266 private void nextImpl() throws IOException, XmlPullParserException {
267 if (reader == null) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800268 exception("No Input specified");
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700269 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800270
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700271 if (type == END_TAG) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800272 depth--;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700273 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800274
275 while (true) {
276 attributeCount = -1;
277
Elliott Hughesd21d78f2010-05-13 11:32:57 -0700278 // degenerated needs to be handled before error because of possible
279 // processor expectations(!)
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800280
Elliott Hughesd21d78f2010-05-13 11:32:57 -0700281 if (degenerated) {
282 degenerated = false;
283 type = END_TAG;
284 return;
285 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800286
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800287 if (error != null) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700288 for (int i = 0; i < error.length(); i++) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800289 push(error.charAt(i));
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700290 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800291 error = null;
292 type = COMMENT;
293 return;
294 }
295
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800296 prefix = null;
297 name = null;
298 namespace = null;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800299
300 type = peekType();
301
302 switch (type) {
303
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700304 case ENTITY_REF:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800305 pushEntity();
306 return;
307
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700308 case START_TAG:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800309 parseStartTag(false);
310 return;
311
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700312 case END_TAG:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800313 parseEndTag();
314 return;
315
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700316 case END_DOCUMENT:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800317 return;
318
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700319 case TEXT:
Elliott Hughes6bcf32a2009-11-16 21:23:11 -0800320 pushText('<', !token, false);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800321 if (depth == 0) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700322 if (isWhitespace) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800323 type = IGNORABLE_WHITESPACE;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700324 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800325 }
326 return;
327
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700328 default:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800329 type = parseLegacy(token);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700330 if (type != XML_DECL) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800331 return;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700332 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800333 }
334 }
335 }
336
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700337 private int parseLegacy(boolean push) throws IOException, XmlPullParserException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800338 String req = "";
339 int term;
340 int result;
341 int prev = 0;
342
343 read(); // <
344 int c = read();
345
346 if (c == '?') {
347 if ((peek(0) == 'x' || peek(0) == 'X')
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700348 && (peek(1) == 'm' || peek(1) == 'M')) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800349
350 if (push) {
351 push(peek(0));
352 push(peek(1));
353 }
354 read();
355 read();
356
357 if ((peek(0) == 'l' || peek(0) == 'L') && peek(1) <= ' ') {
358
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700359 if (line != 1 || column > 4) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800360 error("PI must not start with xml");
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700361 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800362
363 parseStartTag(true);
364
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700365 if (attributeCount < 1 || !"version".equals(attributes[2])) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800366 error("version expected");
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700367 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800368
369 version = attributes[3];
370
371 int pos = 1;
372
373 if (pos < attributeCount
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700374 && "encoding".equals(attributes[2 + 4])) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800375 encoding = attributes[3 + 4];
376 pos++;
377 }
378
379 if (pos < attributeCount
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700380 && "standalone".equals(attributes[4 * pos + 2])) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800381 String st = attributes[3 + 4 * pos];
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700382 if ("yes".equals(st)) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800383 standalone = new Boolean(true);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700384 } else if ("no".equals(st)) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800385 standalone = new Boolean(false);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700386 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800387 error("illegal standalone value: " + st);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700388 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800389 pos++;
390 }
391
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700392 if (pos != attributeCount) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800393 error("illegal xmldecl");
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700394 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800395
396 isWhitespace = true;
397 txtPos = 0;
398
399 return XML_DECL;
400 }
401 }
402
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800403 term = '?';
404 result = PROCESSING_INSTRUCTION;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700405 } else if (c == '!') {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800406 if (peek(0) == '-') {
407 result = COMMENT;
408 req = "--";
409 term = '-';
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700410 } else if (peek(0) == '[') {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800411 result = CDSECT;
412 req = "[CDATA[";
413 term = ']';
414 push = true;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700415 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800416 result = DOCDECL;
417 req = "DOCTYPE";
418 term = -1;
419 }
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700420 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800421 error("illegal: <" + c);
422 return COMMENT;
423 }
424
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700425 for (int i = 0; i < req.length(); i++) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800426 read(req.charAt(i));
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700427 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800428
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700429 if (result == DOCDECL) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800430 parseDoctype(push);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700431 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800432 while (true) {
433 c = read();
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700434 if (c == -1) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800435 error(UNEXPECTED_EOF);
436 return COMMENT;
437 }
438
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700439 if (push) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800440 push(c);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700441 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800442
443 if ((term == '?' || c == term)
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700444 && peek(0) == term
445 && peek(1) == '>') {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800446 break;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700447 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800448
449 prev = c;
450 }
451
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700452 if (term == '-' && prev == '-' && !relaxed) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800453 error("illegal comment delimiter: --->");
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700454 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800455
456 read();
457 read();
458
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700459 if (push && term != '?') {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800460 txtPos--;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700461 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800462
463 }
464 return result;
465 }
466
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700467 /**
468 * precondition: &lt! consumed
469 */
470 private void parseDoctype(boolean push) throws IOException, XmlPullParserException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800471 int nesting = 1;
472 boolean quoted = false;
473
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800474 while (true) {
475 int i = read();
476 switch (i) {
477
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700478 case -1:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800479 error(UNEXPECTED_EOF);
480 return;
481
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700482 case '\'':
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800483 quoted = !quoted;
484 break;
485
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700486 case '<':
487 if (!quoted) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800488 nesting++;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700489 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800490 break;
491
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700492 case '>':
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800493 if (!quoted) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700494 if ((--nesting) == 0) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800495 return;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700496 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800497 }
498 break;
499 }
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700500 if (push) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800501 push(i);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700502 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800503 }
504 }
505
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700506 /**
507 * precondition: &lt;/ consumed
508 */
509 private void parseEndTag() throws IOException, XmlPullParserException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800510 read(); // '<'
511 read(); // '/'
512 name = readName();
513 skip();
514 read('>');
515
516 int sp = (depth - 1) << 2;
517
518 if (depth == 0) {
519 error("element stack empty");
520 type = COMMENT;
521 return;
522 }
523
Elliott Hughesb211e132009-11-09 16:06:42 -0800524 if (!relaxed) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700525 if (!name.equals(elementStack[sp + 3])) {
526 error("expected: /" + elementStack[sp + 3] + " read: " + name);
527 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800528
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700529 namespace = elementStack[sp];
530 prefix = elementStack[sp + 1];
531 name = elementStack[sp + 2];
Elliott Hughesb211e132009-11-09 16:06:42 -0800532 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800533 }
534
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700535 private int peekType() throws IOException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800536 switch (peek(0)) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700537 case -1:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800538 return END_DOCUMENT;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700539 case '&':
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800540 return ENTITY_REF;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700541 case '<':
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800542 switch (peek(1)) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700543 case '/':
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800544 return END_TAG;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700545 case '?':
546 case '!':
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800547 return LEGACY;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700548 default:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800549 return START_TAG;
550 }
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700551 default:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800552 return TEXT;
553 }
554 }
555
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700556 private String get(int pos) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800557 return new String(txtBuf, pos, txtPos - pos);
558 }
559
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700560 private void push(int c) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800561 isWhitespace &= c <= ' ';
562
563 if (txtPos == txtBuf.length) {
564 char[] bigger = new char[txtPos * 4 / 3 + 4];
565 System.arraycopy(txtBuf, 0, bigger, 0, txtPos);
566 txtBuf = bigger;
567 }
568
569 txtBuf[txtPos++] = (char) c;
570 }
571
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700572 /**
573 * Sets name and attributes
574 */
575 private void parseStartTag(boolean xmldecl) throws IOException, XmlPullParserException {
576 if (!xmldecl) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800577 read();
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700578 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800579 name = readName();
580 attributeCount = 0;
581
582 while (true) {
583 skip();
584
585 int c = peek(0);
586
587 if (xmldecl) {
588 if (c == '?') {
589 read();
590 read('>');
591 return;
592 }
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700593 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800594 if (c == '/') {
595 degenerated = true;
596 read();
597 skip();
598 read('>');
599 break;
600 }
601
602 if (c == '>' && !xmldecl) {
603 read();
604 break;
605 }
606 }
607
608 if (c == -1) {
609 error(UNEXPECTED_EOF);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800610 return;
611 }
612
613 String attrName = readName();
614
615 if (attrName.length() == 0) {
616 error("attr name expected");
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800617 break;
618 }
619
620 int i = (attributeCount++) << 2;
621
622 attributes = ensureCapacity(attributes, i + 4);
623
624 attributes[i++] = "";
625 attributes[i++] = null;
626 attributes[i++] = attrName;
627
628 skip();
629
630 if (peek(0) != '=') {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700631 if (!relaxed) {
632 error("Attr.value missing f. " + attrName);
Elliott Hughesd21d78f2010-05-13 11:32:57 -0700633 }
Elliott Hughesb211e132009-11-09 16:06:42 -0800634 attributes[i] = attrName;
Elliott Hughesd21d78f2010-05-13 11:32:57 -0700635 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800636 read('=');
637 skip();
638 int delimiter = peek(0);
639
640 if (delimiter != '\'' && delimiter != '"') {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700641 if (!relaxed) {
Elliott Hughesd21d78f2010-05-13 11:32:57 -0700642 error("attr value delimiter missing!");
643 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800644 delimiter = ' ';
Elliott Hughesd21d78f2010-05-13 11:32:57 -0700645 } else {
646 read();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800647 }
Elliott Hughesd21d78f2010-05-13 11:32:57 -0700648
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800649 int p = txtPos;
Elliott Hughes6bcf32a2009-11-16 21:23:11 -0800650 pushText(delimiter, true, true);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800651
652 attributes[i] = get(p);
653 txtPos = p;
654
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700655 if (delimiter != ' ') {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800656 read(); // skip endquote
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700657 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800658 }
659 }
660
661 int sp = depth++ << 2;
662
663 elementStack = ensureCapacity(elementStack, sp + 4);
664 elementStack[sp + 3] = name;
665
666 if (depth >= nspCounts.length) {
667 int[] bigger = new int[depth + 4];
668 System.arraycopy(nspCounts, 0, bigger, 0, nspCounts.length);
669 nspCounts = bigger;
670 }
671
672 nspCounts[depth] = nspCounts[depth - 1];
673
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700674 if (processNsp) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800675 adjustNsp();
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700676 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800677 namespace = "";
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700678 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800679
680 elementStack[sp] = namespace;
681 elementStack[sp + 1] = prefix;
682 elementStack[sp + 2] = name;
683 }
684
Elliott Hughesf33eae72010-05-13 12:36:25 -0700685 /**
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700686 * result: isWhitespace; if the setName parameter is set, the name of the entity is stored in
687 * "name"
688 */
689 private void pushEntity() throws IOException, XmlPullParserException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800690 push(read()); // &
Elliott Hughesf33eae72010-05-13 12:36:25 -0700691
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800692 int pos = txtPos;
693
694 while (true) {
Elliott Hughesb211e132009-11-09 16:06:42 -0800695 int c = peek(0);
696 if (c == ';') {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700697 read();
698 break;
Elliott Hughesb211e132009-11-09 16:06:42 -0800699 }
Elliott Hughesd21d78f2010-05-13 11:32:57 -0700700 if (c < 128 && (c < '0' || c > '9') && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z')
701 && c != '_' && c != '-' && c != '#') {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700702 if (!relaxed) {
Elliott Hughesd21d78f2010-05-13 11:32:57 -0700703 error("unterminated entity ref");
704 }
Elliott Hughesf33eae72010-05-13 12:36:25 -0700705
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800706 return;
707 }
708
Elliott Hughesb211e132009-11-09 16:06:42 -0800709 push(read());
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800710 }
711
712 String code = get(pos);
713 txtPos = pos - 1;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700714 if (token && type == ENTITY_REF) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800715 name = code;
716 }
717
718 if (code.charAt(0) == '#') {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700719 int c = code.charAt(1) == 'x'
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800720 ? Integer.parseInt(code.substring(2), 16)
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700721 : Integer.parseInt(code.substring(1));
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800722 push(c);
723 return;
724 }
725
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700726 String result = entityMap.get(code);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800727
728 unresolved = result == null;
729
730 if (unresolved) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700731 if (!token) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800732 error("unresolved: &" + code + ";");
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700733 }
734 } else {
735 for (int i = 0; i < result.length(); i++) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800736 push(result.charAt(i));
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700737 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800738 }
739 }
740
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700741 /**
742 * types: '<': parse to any token (for nextToken ()) '"': parse to quote ' ': parse to
743 * whitespace or '>'
744 */
745 private void pushText(int delimiter, boolean resolveEntities, boolean inAttributeValue)
746 throws IOException, XmlPullParserException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800747
748 int next = peek(0);
749 int cbrCount = 0;
750
751 while (next != -1 && next != delimiter) { // covers eof, '<', '"'
752
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700753 if (delimiter == ' ' && (next <= ' ' || next == '>')) {
754 break;
755 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800756
757 if (next == '&') {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700758 if (!resolveEntities) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800759 break;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700760 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800761
762 pushEntity();
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700763 } else if (next == '<' && inAttributeValue) {
Elliott Hughes6bcf32a2009-11-16 21:23:11 -0800764 error("Illegal: \"<\" inside attribute value");
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700765 } else if (next == '\n' && type == START_TAG) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800766 read();
767 push(' ');
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700768 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800769 push(read());
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700770 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800771
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700772 /*
773 * "]]>" is allowed in attribute values, but is not allowed in
774 * regular text between markup.
775 */
Elliott Hughes6bcf32a2009-11-16 21:23:11 -0800776 final boolean allowCloseCdata = inAttributeValue;
777 if (!allowCloseCdata && (next == '>' && cbrCount >= 2 && delimiter != ']')) {
778 error("Illegal: \"]]>\" outside CDATA section");
779 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800780
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700781 if (next == ']') {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800782 cbrCount++;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700783 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800784 cbrCount = 0;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700785 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800786
787 next = peek(0);
788 }
789 }
790
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700791 private void read(char c) throws IOException, XmlPullParserException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800792 int a = read();
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700793 if (a != c) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800794 error("expected: '" + c + "' actual: '" + ((char) a) + "'");
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700795 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800796 }
797
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700798 private int read() throws IOException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800799 int result;
800
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700801 if (peekCount == 0) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800802 result = peek(0);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700803 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800804 result = peek[0];
805 peek[0] = peek[1];
806 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800807 peekCount--;
808
809 column++;
810
811 if (result == '\n') {
812
813 line++;
814 column = 1;
815 }
816
817 return result;
818 }
819
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700820 /**
821 * Does never read more than needed
822 */
823 private int peek(int pos) throws IOException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800824 while (pos >= peekCount) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800825 int nw;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700826 if (srcBuf.length <= 1) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800827 nw = reader.read();
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700828 } else if (srcPos < srcCount) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800829 nw = srcBuf[srcPos++];
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700830 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800831 srcCount = reader.read(srcBuf, 0, srcBuf.length);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700832 if (srcCount <= 0) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800833 nw = -1;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700834 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800835 nw = srcBuf[0];
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700836 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800837
838 srcPos = 1;
839 }
840
841 if (nw == '\r') {
842 wasCR = true;
843 peek[peekCount++] = '\n';
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700844 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800845 if (nw == '\n') {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700846 if (!wasCR) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800847 peek[peekCount++] = '\n';
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700848 }
849 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800850 peek[peekCount++] = nw;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700851 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800852
853 wasCR = false;
854 }
855 }
856
857 return peek[pos];
858 }
859
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700860 private String readName() throws IOException, XmlPullParserException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800861 int pos = txtPos;
862 int c = peek(0);
863 if ((c < 'a' || c > 'z')
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700864 && (c < 'A' || c > 'Z')
865 && c != '_'
866 && c != ':'
867 && c < 0x0c0
868 && !relaxed) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800869 error("name expected");
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700870 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800871
872 do {
873 push(read());
874 c = peek(0);
875 }
876 while ((c >= 'a' && c <= 'z')
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700877 || (c >= 'A' && c <= 'Z')
878 || (c >= '0' && c <= '9')
879 || c == '_'
880 || c == '-'
881 || c == ':'
882 || c == '.'
883 || c >= 0x0b7);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800884
885 String result = get(pos);
886 txtPos = pos;
887 return result;
888 }
889
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700890 private void skip() throws IOException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800891 while (true) {
892 int c = peek(0);
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700893 if (c > ' ' || c == -1) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800894 break;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700895 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800896 read();
897 }
898 }
899
900 // public part starts here...
901
902 public void setInput(Reader reader) throws XmlPullParserException {
903 this.reader = reader;
904
905 line = 1;
906 column = 0;
907 type = START_DOCUMENT;
908 name = null;
909 namespace = null;
910 degenerated = false;
911 attributeCount = -1;
912 encoding = null;
913 version = null;
914 standalone = null;
915
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700916 if (reader == null) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800917 return;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700918 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800919
920 srcPos = 0;
921 srcCount = 0;
922 peekCount = 0;
923 depth = 0;
924
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700925 entityMap = new HashMap<String, String>();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800926 entityMap.put("amp", "&");
927 entityMap.put("apos", "'");
928 entityMap.put("gt", ">");
929 entityMap.put("lt", "<");
930 entityMap.put("quot", "\"");
931 }
932
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700933 public void setInput(InputStream is, String _enc) throws XmlPullParserException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800934 srcPos = 0;
935 srcCount = 0;
936 String enc = _enc;
937
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700938 if (is == null) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800939 throw new IllegalArgumentException();
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700940 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800941
942 try {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800943 if (enc == null) {
Elliott Hughesf33eae72010-05-13 12:36:25 -0700944 // read four bytes
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800945
946 int chk = 0;
947
948 while (srcCount < 4) {
949 int i = is.read();
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700950 if (i == -1) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800951 break;
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700952 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800953 chk = (chk << 8) | i;
954 srcBuf[srcCount++] = (char) i;
955 }
956
957 if (srcCount == 4) {
958 switch (chk) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700959 case 0x00000FEFF:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800960 enc = "UTF-32BE";
961 srcCount = 0;
962 break;
963
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700964 case 0x0FFFE0000:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800965 enc = "UTF-32LE";
966 srcCount = 0;
967 break;
968
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700969 case 0x03c:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800970 enc = "UTF-32BE";
971 srcBuf[0] = '<';
972 srcCount = 1;
973 break;
974
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700975 case 0x03c000000:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800976 enc = "UTF-32LE";
977 srcBuf[0] = '<';
978 srcCount = 1;
979 break;
980
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700981 case 0x0003c003f:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800982 enc = "UTF-16BE";
983 srcBuf[0] = '<';
984 srcBuf[1] = '?';
985 srcCount = 2;
986 break;
987
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700988 case 0x03c003f00:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800989 enc = "UTF-16LE";
990 srcBuf[0] = '<';
991 srcBuf[1] = '?';
992 srcCount = 2;
993 break;
994
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700995 case 0x03c3f786d:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800996 while (true) {
997 int i = is.read();
Jesse Wilsonccd79e22010-11-04 14:02:20 -0700998 if (i == -1) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800999 break;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001000 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001001 srcBuf[srcCount++] = (char) i;
1002 if (i == '>') {
1003 String s = new String(srcBuf, 0, srcCount);
1004 int i0 = s.indexOf("encoding");
1005 if (i0 != -1) {
1006 while (s.charAt(i0) != '"'
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001007 && s.charAt(i0) != '\'') {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001008 i0++;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001009 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001010 char deli = s.charAt(i0++);
1011 int i1 = s.indexOf(deli, i0);
1012 enc = s.substring(i0, i1);
1013 }
1014 break;
1015 }
1016 }
1017
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001018 default:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001019 if ((chk & 0x0ffff0000) == 0x0FEFF0000) {
1020 enc = "UTF-16BE";
1021 srcBuf[0] =
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001022 (char) ((srcBuf[2] << 8) | srcBuf[3]);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001023 srcCount = 1;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001024 } else if ((chk & 0x0ffff0000) == 0x0fffe0000) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001025 enc = "UTF-16LE";
1026 srcBuf[0] =
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001027 (char) ((srcBuf[3] << 8) | srcBuf[2]);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001028 srcCount = 1;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001029 } else if ((chk & 0x0ffffff00) == 0x0EFBBBF00) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001030 enc = "UTF-8";
1031 srcBuf[0] = srcBuf[3];
1032 srcCount = 1;
1033 }
1034 }
1035 }
1036 }
1037
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001038 if (enc == null) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001039 enc = "UTF-8";
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001040 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001041
1042 int sc = srcCount;
1043 setInput(new InputStreamReader(is, enc));
1044 encoding = _enc;
1045 srcCount = sc;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001046 } catch (Exception e) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001047 throw new XmlPullParserException(
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001048 "Invalid stream or encoding: " + e.toString(),
1049 this,
1050 e);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001051 }
1052 }
1053
1054 public boolean getFeature(String feature) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001055 if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature)) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001056 return processNsp;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001057 } else if (isProp(feature, false, "relaxed")) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001058 return relaxed;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001059 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001060 return false;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001061 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001062 }
1063
1064 public String getInputEncoding() {
1065 return encoding;
1066 }
1067
1068 public void defineEntityReplacementText(String entity, String value)
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001069 throws XmlPullParserException {
1070 if (entityMap == null) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001071 throw new RuntimeException("entity replacement text must be defined after setInput!");
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001072 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001073 entityMap.put(entity, value);
1074 }
1075
1076 public Object getProperty(String property) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001077 if (isProp(property, true, "xmldecl-version")) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001078 return version;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001079 }
1080 if (isProp(property, true, "xmldecl-standalone")) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001081 return standalone;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001082 }
1083 if (isProp(property, true, "location")) {
Elliott Hughesd21d78f2010-05-13 11:32:57 -07001084 return location != null ? location : reader.toString();
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001085 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001086 return null;
1087 }
1088
1089 public int getNamespaceCount(int depth) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001090 if (depth > this.depth) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001091 throw new IndexOutOfBoundsException();
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001092 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001093 return nspCounts[depth];
1094 }
1095
1096 public String getNamespacePrefix(int pos) {
1097 return nspStack[pos << 1];
1098 }
1099
1100 public String getNamespaceUri(int pos) {
1101 return nspStack[(pos << 1) + 1];
1102 }
1103
1104 public String getNamespace(String prefix) {
1105
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001106 if ("xml".equals(prefix)) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001107 return "http://www.w3.org/XML/1998/namespace";
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001108 }
1109 if ("xmlns".equals(prefix)) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001110 return "http://www.w3.org/2000/xmlns/";
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001111 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001112
1113 for (int i = (getNamespaceCount(depth) << 1) - 2; i >= 0; i -= 2) {
1114 if (prefix == null) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001115 if (nspStack[i] == null) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001116 return nspStack[i + 1];
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001117 }
1118 } else if (prefix.equals(nspStack[i])) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001119 return nspStack[i + 1];
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001120 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001121 }
1122 return null;
1123 }
1124
1125 public int getDepth() {
1126 return depth;
1127 }
1128
1129 public String getPositionDescription() {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001130 StringBuilder buf = new StringBuilder(type < TYPES.length ? TYPES[type] : "unknown");
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001131 buf.append(' ');
1132
1133 if (type == START_TAG || type == END_TAG) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001134 if (degenerated) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001135 buf.append("(empty) ");
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001136 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001137 buf.append('<');
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001138 if (type == END_TAG) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001139 buf.append('/');
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001140 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001141
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001142 if (prefix != null) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001143 buf.append("{" + namespace + "}" + prefix + ":");
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001144 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001145 buf.append(name);
1146
1147 int cnt = attributeCount << 2;
1148 for (int i = 0; i < cnt; i += 4) {
1149 buf.append(' ');
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001150 if (attributes[i + 1] != null) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001151 buf.append(
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001152 "{" + attributes[i] + "}" + attributes[i + 1] + ":");
1153 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001154 buf.append(attributes[i + 2] + "='" + attributes[i + 3] + "'");
1155 }
1156
1157 buf.append('>');
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001158 } else if (type == IGNORABLE_WHITESPACE) {
1159 ;
1160 } else if (type != TEXT) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001161 buf.append(getText());
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001162 } else if (isWhitespace) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001163 buf.append("(whitespace)");
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001164 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001165 String text = getText();
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001166 if (text.length() > 16) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001167 text = text.substring(0, 16) + "...";
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001168 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001169 buf.append(text);
1170 }
1171
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001172 buf.append("@" + line + ":" + column);
1173 if (location != null) {
Elliott Hughesd21d78f2010-05-13 11:32:57 -07001174 buf.append(" in ");
1175 buf.append(location);
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001176 } else if (reader != null) {
Elliott Hughesd21d78f2010-05-13 11:32:57 -07001177 buf.append(" in ");
1178 buf.append(reader.toString());
1179 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001180 return buf.toString();
1181 }
1182
1183 public int getLineNumber() {
1184 return line;
1185 }
1186
1187 public int getColumnNumber() {
1188 return column;
1189 }
1190
1191 public boolean isWhitespace() throws XmlPullParserException {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001192 if (type != TEXT && type != IGNORABLE_WHITESPACE && type != CDSECT) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001193 exception(ILLEGAL_TYPE);
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001194 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001195 return isWhitespace;
1196 }
1197
1198 public String getText() {
1199 return type < TEXT
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001200 || (type == ENTITY_REF && unresolved) ? null : get(0);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001201 }
1202
1203 public char[] getTextCharacters(int[] poslen) {
1204 if (type >= TEXT) {
1205 if (type == ENTITY_REF) {
1206 poslen[0] = 0;
1207 poslen[1] = name.length();
1208 return name.toCharArray();
1209 }
1210 poslen[0] = 0;
1211 poslen[1] = txtPos;
1212 return txtBuf;
1213 }
1214
1215 poslen[0] = -1;
1216 poslen[1] = -1;
1217 return null;
1218 }
1219
1220 public String getNamespace() {
1221 return namespace;
1222 }
1223
1224 public String getName() {
1225 return name;
1226 }
1227
1228 public String getPrefix() {
1229 return prefix;
1230 }
1231
1232 public boolean isEmptyElementTag() throws XmlPullParserException {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001233 if (type != START_TAG) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001234 exception(ILLEGAL_TYPE);
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001235 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001236 return degenerated;
1237 }
1238
1239 public int getAttributeCount() {
1240 return attributeCount;
1241 }
1242
1243 public String getAttributeType(int index) {
1244 return "CDATA";
1245 }
1246
1247 public boolean isAttributeDefault(int index) {
1248 return false;
1249 }
1250
1251 public String getAttributeNamespace(int index) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001252 if (index >= attributeCount) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001253 throw new IndexOutOfBoundsException();
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001254 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001255 return attributes[index << 2];
1256 }
1257
1258 public String getAttributeName(int index) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001259 if (index >= attributeCount) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001260 throw new IndexOutOfBoundsException();
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001261 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001262 return attributes[(index << 2) + 2];
1263 }
1264
1265 public String getAttributePrefix(int index) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001266 if (index >= attributeCount) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001267 throw new IndexOutOfBoundsException();
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001268 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001269 return attributes[(index << 2) + 1];
1270 }
1271
1272 public String getAttributeValue(int index) {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001273 if (index >= attributeCount) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001274 throw new IndexOutOfBoundsException();
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001275 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001276 return attributes[(index << 2) + 3];
1277 }
1278
1279 public String getAttributeValue(String namespace, String name) {
1280
1281 for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4) {
1282 if (attributes[i + 2].equals(name)
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001283 && (namespace == null || attributes[i].equals(namespace))) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001284 return attributes[i + 3];
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001285 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001286 }
1287
1288 return null;
1289 }
1290
1291 public int getEventType() throws XmlPullParserException {
1292 return type;
1293 }
1294
1295 public int next() throws XmlPullParserException, IOException {
1296
1297 txtPos = 0;
1298 isWhitespace = true;
1299 int minType = 9999;
1300 token = false;
1301
1302 do {
1303 nextImpl();
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001304 if (type < minType) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001305 minType = type;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001306 }
Elliott Hughesf33eae72010-05-13 12:36:25 -07001307 // if (curr <= TEXT) type = curr;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001308 }
1309 while (minType > ENTITY_REF // ignorable
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001310 || (minType >= TEXT && peekType() >= TEXT));
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001311
1312 type = minType;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001313 if (type > TEXT) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001314 type = TEXT;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001315 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001316
1317 return type;
1318 }
1319
1320 public int nextToken() throws XmlPullParserException, IOException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001321 isWhitespace = true;
1322 txtPos = 0;
1323
1324 token = true;
1325 nextImpl();
1326 return type;
1327 }
1328
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001329 // utility methods to make XML parsing easier ...
1330
1331 public int nextTag() throws XmlPullParserException, IOException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001332 next();
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001333 if (type == TEXT && isWhitespace) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001334 next();
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001335 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001336
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001337 if (type != END_TAG && type != START_TAG) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001338 exception("unexpected type");
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001339 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001340
1341 return type;
1342 }
1343
1344 public void require(int type, String namespace, String name)
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001345 throws XmlPullParserException, IOException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001346
1347 if (type != this.type
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001348 || (namespace != null && !namespace.equals(getNamespace()))
1349 || (name != null && !name.equals(getName()))) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001350 exception(
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001351 "expected: " + TYPES[type] + " {" + namespace + "}" + name);
1352 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001353 }
1354
1355 public String nextText() throws XmlPullParserException, IOException {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001356 if (type != START_TAG) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001357 exception("precondition: START_TAG");
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001358 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001359
1360 next();
1361
1362 String result;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001363 if (type == TEXT) {
1364 result = getText();
1365 next();
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001366 } else {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001367 result = "";
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001368 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001369
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001370 if (type != END_TAG) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001371 exception("END_TAG expected");
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001372 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001373
1374 return result;
1375 }
1376
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001377 public void setFeature(String feature, boolean value) throws XmlPullParserException {
1378 if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature)) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001379 processNsp = value;
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001380 } else if (isProp(feature, false, "relaxed")) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001381 relaxed = value;
Elliott Hughesd21d78f2010-05-13 11:32:57 -07001382 } else {
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001383 exception("unsupported feature: " + feature);
Elliott Hughesd21d78f2010-05-13 11:32:57 -07001384 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001385 }
1386
Jesse Wilsonccd79e22010-11-04 14:02:20 -07001387 public void setProperty(String property, Object value) throws XmlPullParserException {
1388 if (isProp(property, true, "location")) {
1389 location = value;
1390 } else {
1391 throw new XmlPullParserException("unsupported property: " + property);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001392 }
1393 }
1394}