• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.res.android;
2 
3 import static org.robolectric.res.android.Errors.BAD_TYPE;
4 import static org.robolectric.res.android.Errors.NAME_NOT_FOUND;
5 import static org.robolectric.res.android.Errors.NO_ERROR;
6 import static org.robolectric.res.android.ResTable.kDebugStringPoolNoisy;
7 import static org.robolectric.res.android.ResTable.kDebugXMLNoisy;
8 import static org.robolectric.res.android.ResXMLParser.event_code_t.BAD_DOCUMENT;
9 import static org.robolectric.res.android.ResXMLParser.event_code_t.END_DOCUMENT;
10 import static org.robolectric.res.android.ResXMLParser.event_code_t.END_NAMESPACE;
11 import static org.robolectric.res.android.ResXMLParser.event_code_t.END_TAG;
12 import static org.robolectric.res.android.ResXMLParser.event_code_t.FIRST_CHUNK_CODE;
13 import static org.robolectric.res.android.ResXMLParser.event_code_t.START_DOCUMENT;
14 import static org.robolectric.res.android.ResXMLParser.event_code_t.START_NAMESPACE;
15 import static org.robolectric.res.android.ResXMLParser.event_code_t.START_TAG;
16 import static org.robolectric.res.android.ResXMLParser.event_code_t.TEXT;
17 import static org.robolectric.res.android.ResourceTypes.RES_XML_CDATA_TYPE;
18 import static org.robolectric.res.android.ResourceTypes.RES_XML_END_ELEMENT_TYPE;
19 import static org.robolectric.res.android.ResourceTypes.RES_XML_END_NAMESPACE_TYPE;
20 import static org.robolectric.res.android.ResourceTypes.RES_XML_FIRST_CHUNK_TYPE;
21 import static org.robolectric.res.android.ResourceTypes.RES_XML_START_ELEMENT_TYPE;
22 import static org.robolectric.res.android.ResourceTypes.RES_XML_START_NAMESPACE_TYPE;
23 import static org.robolectric.res.android.Util.ALOGI;
24 import static org.robolectric.res.android.Util.ALOGW;
25 import static org.robolectric.res.android.Util.dtohl;
26 import static org.robolectric.res.android.Util.dtohs;
27 import static org.robolectric.res.android.Util.isTruthy;
28 
29 import org.robolectric.res.android.ResourceTypes.ResChunk_header;
30 import org.robolectric.res.android.ResourceTypes.ResXMLTree_attrExt;
31 import org.robolectric.res.android.ResourceTypes.ResXMLTree_attribute;
32 import org.robolectric.res.android.ResourceTypes.ResXMLTree_endElementExt;
33 import org.robolectric.res.android.ResourceTypes.ResXMLTree_node;
34 import org.robolectric.res.android.ResourceTypes.Res_value;
35 
36 public class ResXMLParser {
37 
38   static final int SIZEOF_RESXMLTREE_NAMESPACE_EXT = 4;
39   static final int SIZEOF_RESXMLTREE_NODE = ResChunk_header.SIZEOF + 8;
40   static final int SIZEOF_RESXMLTREE_ATTR_EXT = 20;
41   static final int SIZEOF_RESXMLTREE_CDATA_EXT = 4 + ResourceTypes.Res_value.SIZEOF;
42   static final int SIZEOF_CHAR = 2;
43 
44   public static class event_code_t {
45     public static final int BAD_DOCUMENT = -1;
46     public static final int START_DOCUMENT = 0;
47     public static final int END_DOCUMENT = 1;
48 
49     public static final int FIRST_CHUNK_CODE = RES_XML_FIRST_CHUNK_TYPE;
50 
51     public static final int START_NAMESPACE = RES_XML_START_NAMESPACE_TYPE;
52     public static final int END_NAMESPACE = RES_XML_END_NAMESPACE_TYPE;
53     public static final int START_TAG = RES_XML_START_ELEMENT_TYPE;
54     public static final int END_TAG = RES_XML_END_ELEMENT_TYPE;
55     public static final int TEXT = RES_XML_CDATA_TYPE;
56   }
57 
58   ResXMLTree mTree;
59   int mEventCode;
60   ResXMLTree_node mCurNode;
61   int mCurExt;
62   int mSourceResourceId;
63 
ResXMLParser(ResXMLTree tree)64   public ResXMLParser(ResXMLTree tree) {
65     this.mTree = tree;
66     this.mEventCode = BAD_DOCUMENT;
67   }
68 
restart()69   public void restart() {
70     mCurNode = null;
71     mEventCode = mTree.mError == NO_ERROR ? START_DOCUMENT : BAD_DOCUMENT;
72   }
73 
getStrings()74   public ResStringPool getStrings() {
75     return mTree.mStrings;
76   }
77 
getEventType()78   int getEventType() {
79     return mEventCode;
80   }
81 
next()82   public int next() {
83     if (mEventCode == START_DOCUMENT) {
84       mCurNode = mTree.mRootNode;
85       mCurExt = mTree.mRootExt;
86       return (mEventCode = mTree.mRootCode);
87     } else if (mEventCode >= FIRST_CHUNK_CODE) {
88       return nextNode();
89     }
90     return mEventCode;
91   }
92 
getCommentID()93   int getCommentID() {
94     return mCurNode != null ? dtohl(mCurNode.comment.index) : -1;
95   }
96 
getComment(Ref<Integer> outLen)97   final String getComment(Ref<Integer> outLen) {
98     int id = getCommentID();
99     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : null;
100   }
101 
getLineNumber()102   public int getLineNumber() {
103     return mCurNode != null ? dtohl(mCurNode.lineNumber) : -1;
104   }
105 
getTextID()106   public int getTextID() {
107     if (mEventCode == TEXT) {
108       return dtohl(new ResourceTypes.ResXMLTree_cdataExt(mTree.mBuffer.buf, mCurExt).data.index);
109     }
110     return -1;
111   }
112 
getText(Ref<Integer> outLen)113   final String getText(Ref<Integer> outLen) {
114     int id = getTextID();
115     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : null;
116   }
117 
getTextValue(Res_value outValue)118   int getTextValue(Res_value outValue) {
119     if (mEventCode == TEXT) {
120       // outValue.copyFrom_dtoh(new ResourceTypes.ResXMLTree_cdataExt(mTree.mBuffer.buf,
121       // mCurExt).typedData);
122       return ResourceTypes.Res_value.SIZEOF /* sizeof(Res_value) */;
123     }
124     return BAD_TYPE;
125   }
126 
getNamespacePrefixID()127   int getNamespacePrefixID() {
128     if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) {
129       return dtohl(
130           new ResourceTypes.ResXMLTree_namespaceExt(mTree.mBuffer.buf, mCurExt).prefix.index);
131     }
132     return -1;
133   }
134 
getNamespacePrefix(Ref<Integer> outLen)135   final String getNamespacePrefix(Ref<Integer> outLen) {
136     int id = getNamespacePrefixID();
137     // printf("prefix=%d  event=%s\n", id, mEventCode);
138     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : null;
139   }
140 
getNamespaceUriID()141   int getNamespaceUriID() {
142     if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) {
143       return dtohl(new ResourceTypes.ResXMLTree_namespaceExt(mTree.mBuffer.buf, mCurExt).uri.index);
144     }
145     return -1;
146   }
147 
getNamespaceUri(Ref<Integer> outLen)148   final String getNamespaceUri(Ref<Integer> outLen) {
149     int id = getNamespaceUriID();
150     // printf("uri=%d  event=%s\n", id, mEventCode);
151     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : null;
152   }
153 
getElementNamespaceID()154   public int getElementNamespaceID() {
155     if (mEventCode == START_TAG) {
156       return dtohl(new ResXMLTree_attrExt(mTree.mBuffer.buf, mCurExt).ns.index);
157     }
158     if (mEventCode == END_TAG) {
159       return dtohl(new ResXMLTree_endElementExt(mTree.mBuffer.buf, mCurExt).ns.index);
160     }
161     return -1;
162   }
163 
getElementNamespace(Ref<Integer> outLen)164   final String getElementNamespace(Ref<Integer> outLen) {
165     int id = getElementNamespaceID();
166     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : null;
167   }
168 
getElementNameID()169   public int getElementNameID() {
170     if (mEventCode == START_TAG) {
171       return dtohl(new ResXMLTree_attrExt(mTree.mBuffer.buf, mCurExt).name.index);
172     }
173     if (mEventCode == END_TAG) {
174       return dtohl(new ResXMLTree_endElementExt(mTree.mBuffer.buf, mCurExt).name.index);
175     }
176     return -1;
177   }
178 
getElementName(Ref<Integer> outLen)179   final String getElementName(Ref<Integer> outLen) {
180     int id = getElementNameID();
181     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : null;
182   }
183 
getAttributeCount()184   public int getAttributeCount() {
185     if (mEventCode == START_TAG) {
186       return dtohs(new ResXMLTree_attrExt(mTree.mBuffer.buf, mCurExt).attributeCount);
187     }
188     return 0;
189   }
190 
getAttributeNamespaceID(int idx)191   public int getAttributeNamespaceID(int idx) {
192     if (mEventCode == START_TAG) {
193       ResXMLTree_attrExt tag = new ResXMLTree_attrExt(mTree.mBuffer.buf, mCurExt);
194       if (idx < dtohs(tag.attributeCount)) {
195         //            final ResXMLTree_attribute attr = (ResXMLTree_attribute)
196         //        (((final int8_t*)tag)
197         //        + dtohs(tag.attributeStart())
198         //            + (dtohs(tag.attributeSize())*idx));
199         ResXMLTree_attribute attr = tag.attributeAt(idx);
200         return dtohl(attr.ns.index);
201       }
202     }
203     return -2;
204   }
205 
getAttributeNamespace(int idx, Ref<Integer> outLen)206   final String getAttributeNamespace(int idx, Ref<Integer> outLen) {
207     int id = getAttributeNamespaceID(idx);
208     // printf("attribute namespace=%d  idx=%d  event=%s\n", id, idx, mEventCode);
209     if (kDebugXMLNoisy) {
210       System.out.println(String.format("getAttributeNamespace 0x%x=0x%x\n", idx, id));
211     }
212     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : null;
213   }
214 
getAttributeNamespace8(int idx, Ref<Integer> outLen)215   final String getAttributeNamespace8(int idx, Ref<Integer> outLen) {
216     int id = getAttributeNamespaceID(idx);
217     // printf("attribute namespace=%d  idx=%d  event=%s\n", id, idx, mEventCode);
218     if (kDebugXMLNoisy) {
219       System.out.println(String.format("getAttributeNamespace 0x%x=0x%x\n", idx, id));
220     }
221     return id >= 0 ? mTree.mStrings.string8At(id, outLen) : null;
222   }
223 
getAttributeNameID(int idx)224   public int getAttributeNameID(int idx) {
225     if (mEventCode == START_TAG) {
226       ResXMLTree_attrExt tag = new ResXMLTree_attrExt(mTree.mBuffer.buf, mCurExt);
227       if (idx < dtohs(tag.attributeCount)) {
228         //            final ResXMLTree_attribute attr = (ResXMLTree_attribute)
229         //        (((final int8_t*)tag)
230         //        + dtohs(tag.attributeStart())
231         //            + (dtohs(tag.attributeSize())*idx));
232         ResXMLTree_attribute attr = tag.attributeAt(idx);
233         return dtohl(attr.name.index);
234       }
235     }
236     return -1;
237   }
238 
getAttributeName(int idx, Ref<Integer> outLen)239   final String getAttributeName(int idx, Ref<Integer> outLen) {
240     int id = getAttributeNameID(idx);
241     // printf("attribute name=%d  idx=%d  event=%s\n", id, idx, mEventCode);
242     if (kDebugXMLNoisy) {
243       System.out.println(String.format("getAttributeName 0x%x=0x%x\n", idx, id));
244     }
245     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : null;
246   }
247 
getAttributeName8(int idx, Ref<Integer> outLen)248   final String getAttributeName8(int idx, Ref<Integer> outLen) {
249     int id = getAttributeNameID(idx);
250     // printf("attribute name=%d  idx=%d  event=%s\n", id, idx, mEventCode);
251     if (kDebugXMLNoisy) {
252       System.out.println(String.format("getAttributeName 0x%x=0x%x\n", idx, id));
253     }
254     return id >= 0 ? mTree.mStrings.string8At(id, outLen) : null;
255   }
256 
getAttributeNameResID(int idx)257   public int getAttributeNameResID(int idx) {
258     int id = getAttributeNameID(idx);
259     if (id >= 0 && (int) id < mTree.mNumResIds) {
260       int resId = dtohl(mTree.mResIds[id]);
261       if (mTree.mDynamicRefTable != null) {
262         final Ref<Integer> resIdRef = new Ref<>(resId);
263         mTree.mDynamicRefTable.lookupResourceId(resIdRef);
264         resId = resIdRef.get();
265       }
266       return resId;
267     }
268     return 0;
269   }
270 
getAttributeValueStringID(int idx)271   public int getAttributeValueStringID(int idx) {
272     if (mEventCode == START_TAG) {
273       ResXMLTree_attrExt tag = new ResXMLTree_attrExt(mTree.mBuffer.buf, mCurExt);
274       if (idx < dtohs(tag.attributeCount)) {
275         //            final ResXMLTree_attribute attr = (ResXMLTree_attribute)
276         //        (((final int8_t*)tag)
277         //        + dtohs(tag.attributeStart())
278         //            + (dtohs(tag.attributeSize())*idx));
279         ResXMLTree_attribute attr = tag.attributeAt(idx);
280         return dtohl(attr.rawValue.index);
281       }
282     }
283     return -1;
284   }
285 
getAttributeStringValue(int idx, Ref<Integer> outLen)286   final String getAttributeStringValue(int idx, Ref<Integer> outLen) {
287     int id = getAttributeValueStringID(idx);
288     if (kDebugXMLNoisy) {
289       System.out.println(String.format("getAttributeValue 0x%x=0x%x\n", idx, id));
290     }
291     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : null;
292   }
293 
getAttributeDataType(int idx)294   public int getAttributeDataType(int idx) {
295     if (mEventCode == START_TAG) {
296       final ResXMLTree_attrExt tag = new ResXMLTree_attrExt(mTree.mBuffer.buf, mCurExt);
297       if (idx < dtohs(tag.attributeCount)) {
298         //            final ResXMLTree_attribute attr = (ResXMLTree_attribute)
299         //        (((final int8_t*)tag)
300         //        + dtohs(tag.attributeStart())
301         //            + (dtohs(tag.attributeSize())*idx));
302         ResXMLTree_attribute attr = tag.attributeAt(idx);
303         int type = attr.typedValue.dataType;
304         if (type != DataType.DYNAMIC_REFERENCE.code()) {
305           return type;
306         }
307 
308         // This is a dynamic reference. We adjust those references
309         // to regular references at this level, so lie to the caller.
310         return DataType.REFERENCE.code();
311       }
312     }
313     return DataType.NULL.code();
314   }
315 
getAttributeData(int idx)316   public int getAttributeData(int idx) {
317     if (mEventCode == START_TAG) {
318       ResXMLTree_attrExt tag = new ResXMLTree_attrExt(mTree.mBuffer.buf, mCurExt);
319       if (idx < dtohs(tag.attributeCount)) {
320         //            final ResXMLTree_attribute attr = (ResXMLTree_attribute)
321         //        (((final int8_t*)tag)
322         //        + dtohs(tag.attributeStart)
323         //            + (dtohs(tag.attributeSize)*idx));
324         ResXMLTree_attribute attr = tag.attributeAt(idx);
325         if (attr.typedValue.dataType != DataType.DYNAMIC_REFERENCE.code()
326             || mTree.mDynamicRefTable == null) {
327           return dtohl(attr.typedValue.data);
328         }
329 
330         final Ref<Integer> data = new Ref<>(dtohl(attr.typedValue.data));
331         if (mTree.mDynamicRefTable.lookupResourceId(data) == NO_ERROR) {
332           return data.get();
333         }
334       }
335     }
336     return 0;
337   }
338 
getAttributeValue(int idx, Ref<Res_value> outValue)339   public int getAttributeValue(int idx, Ref<Res_value> outValue) {
340     if (mEventCode == START_TAG) {
341       ResXMLTree_attrExt tag = new ResXMLTree_attrExt(mTree.mBuffer.buf, mCurExt);
342       if (idx < dtohs(tag.attributeCount)) {
343         //            final ResXMLTree_attribute attr = (ResXMLTree_attribute)
344         //        (((final int8_t*)tag)
345         //        + dtohs(tag.attributeStart())
346         //            + (dtohs(tag.attributeSize())*idx));
347         ResXMLTree_attribute attr = tag.attributeAt(idx);
348         outValue.set(attr.typedValue);
349         if (mTree.mDynamicRefTable != null
350             && mTree.mDynamicRefTable.lookupResourceValue(outValue) != NO_ERROR) {
351           return BAD_TYPE;
352         }
353         return ResourceTypes.Res_value.SIZEOF /* sizeof(Res_value) */;
354       }
355     }
356     return BAD_TYPE;
357   }
358 
indexOfAttribute(final String ns, final String attr)359   int indexOfAttribute(final String ns, final String attr) {
360     String nsStr = ns != null ? ns : "";
361     String attrStr = attr;
362     return indexOfAttribute(
363         isTruthy(ns) ? nsStr : null, isTruthy(ns) ? nsStr.length() : 0, attrStr, attrStr.length());
364   }
365 
indexOfAttribute(final String ns, int nsLen, final String attr, int attrLen)366   public int indexOfAttribute(final String ns, int nsLen, final String attr, int attrLen) {
367     if (mEventCode == START_TAG) {
368       if (attr == null) {
369         return NAME_NOT_FOUND;
370       }
371       final int N = getAttributeCount();
372       if (mTree.mStrings.isUTF8()) {
373         String8 ns8 = null, attr8;
374         if (ns != null) {
375           ns8 = new String8(ns, nsLen);
376         }
377         attr8 = new String8(attr, attrLen);
378         if (kDebugStringPoolNoisy) {
379           ALOGI(
380               "indexOfAttribute UTF8 %s (0x%x) / %s (0x%x)",
381               ns8.string(), nsLen, attr8.string(), attrLen);
382         }
383         for (int i = 0; i < N; i++) {
384           final Ref<Integer> curNsLen = new Ref<>(0), curAttrLen = new Ref<>(0);
385           final String curNs = getAttributeNamespace8(i, curNsLen);
386           final String curAttr = getAttributeName8(i, curAttrLen);
387           if (kDebugStringPoolNoisy) {
388             ALOGI(
389                 "  curNs=%s (0x%x), curAttr=%s (0x%x)",
390                 curNs, curNsLen.get(), curAttr, curAttrLen.get());
391           }
392           if (curAttr != null
393               && curNsLen.get() == nsLen
394               && curAttrLen.get() == attrLen
395               && memcmp(attr8.string(), curAttr, attrLen) == 0) {
396             if (ns == null) {
397               if (curNs == null) {
398                 if (kDebugStringPoolNoisy) {
399                   ALOGI("  FOUND!");
400                 }
401                 return i;
402               }
403             } else if (curNs != null) {
404               // printf(" -. ns=%s, curNs=%s\n",
405               //       String8(ns).string(), String8(curNs).string());
406               if (memcmp(ns8.string(), curNs, nsLen) == 0) {
407                 if (kDebugStringPoolNoisy) {
408                   ALOGI("  FOUND!");
409                 }
410                 return i;
411               }
412             }
413           }
414         }
415       } else {
416         if (kDebugStringPoolNoisy) {
417           ALOGI(
418               "indexOfAttribute UTF16 %s (0x%x) / %s (0x%x)",
419               ns /*String8(ns, nsLen).string()*/,
420               nsLen,
421               attr /*String8(attr, attrLen).string()*/,
422               attrLen);
423         }
424         for (int i = 0; i < N; i++) {
425           final Ref<Integer> curNsLen = new Ref<>(0), curAttrLen = new Ref<>(0);
426           final String curNs = getAttributeNamespace(i, curNsLen);
427           final String curAttr = getAttributeName(i, curAttrLen);
428           if (kDebugStringPoolNoisy) {
429             ALOGI(
430                 "  curNs=%s (0x%x), curAttr=%s (0x%x)",
431                 curNs /*String8(curNs, curNsLen).string()*/,
432                 curNsLen.get(),
433                 curAttr /*String8(curAttr, curAttrLen).string()*/,
434                 curAttrLen.get());
435           }
436           if (curAttr != null
437               && curNsLen.get() == nsLen
438               && curAttrLen.get() == attrLen
439               && (memcmp(attr, curAttr, attrLen * SIZEOF_CHAR /*sizeof(char16_t)*/) == 0)) {
440             if (ns == null) {
441               if (curNs == null) {
442                 if (kDebugStringPoolNoisy) {
443                   ALOGI("  FOUND!");
444                 }
445                 return i;
446               }
447             } else if (curNs != null) {
448               // printf(" -. ns=%s, curNs=%s\n",
449               //       String8(ns).string(), String8(curNs).string());
450               if (memcmp(ns, curNs, nsLen * SIZEOF_CHAR /*sizeof(char16_t)*/) == 0) {
451                 if (kDebugStringPoolNoisy) {
452                   ALOGI("  FOUND!");
453                 }
454                 return i;
455               }
456             }
457           }
458         }
459       }
460     }
461 
462     return NAME_NOT_FOUND;
463   }
464 
memcmp(String s1, String s2, int len)465   private int memcmp(String s1, String s2, int len) {
466     for (int i = 0; i < len; i++) {
467       int d = s1.charAt(i) - s2.charAt(i);
468       if (d != 0) {
469         return d;
470       }
471     }
472     return 0;
473   }
474 
indexOfID()475   public int indexOfID() {
476     if (mEventCode == START_TAG) {
477       final int idx = dtohs(new ResXMLTree_attrExt(mTree.mBuffer.buf, mCurExt).idIndex);
478       if (idx > 0) return (idx - 1);
479     }
480     return NAME_NOT_FOUND;
481   }
482 
indexOfClass()483   public int indexOfClass() {
484     if (mEventCode == START_TAG) {
485       final int idx = dtohs(new ResXMLTree_attrExt(mTree.mBuffer.buf, mCurExt).classIndex);
486       if (idx > 0) return (idx - 1);
487     }
488     return NAME_NOT_FOUND;
489   }
490 
indexOfStyle()491   public int indexOfStyle() {
492     if (mEventCode == START_TAG) {
493       final int idx = dtohs(new ResXMLTree_attrExt(mTree.mBuffer.buf, mCurExt).styleIndex);
494       if (idx > 0) return (idx - 1);
495     }
496     return NAME_NOT_FOUND;
497   }
498 
nextNode()499   int nextNode() {
500     if (mEventCode < 0) {
501       return mEventCode;
502     }
503 
504     do {
505       int nextOffset = mCurNode.myOffset() + dtohl(mCurNode.header.size);
506       if (nextOffset >= mTree.mDataLen) {
507         mCurNode = null;
508         return (mEventCode = END_DOCUMENT);
509       }
510 
511       //        final ResXMLTree_node next = (ResXMLTree_node)
512       //      (((final int8_t*)mCurNode) + dtohl(mCurNode.header.size));
513       ResXMLTree_node next = new ResXMLTree_node(mTree.mBuffer.buf, nextOffset);
514       if (kDebugXMLNoisy) {
515         ALOGI("Next node: prev=%s, next=%s\n", mCurNode, next);
516       }
517 
518       if (next.myOffset() >= mTree.mDataLen) {
519         mCurNode = null;
520         return (mEventCode = END_DOCUMENT);
521       }
522 
523       if (mTree.validateNode(next) != NO_ERROR) {
524         mCurNode = null;
525         return (mEventCode = BAD_DOCUMENT);
526       }
527 
528       mCurNode = next;
529       final int headerSize = dtohs(next.header.headerSize);
530       final int totalSize = dtohl(next.header.size);
531       mCurExt = next.myOffset() + headerSize;
532       int minExtSize = 0;
533       int eventCode = dtohs(next.header.type);
534       switch ((mEventCode = eventCode)) {
535         case RES_XML_START_NAMESPACE_TYPE:
536         case RES_XML_END_NAMESPACE_TYPE:
537           minExtSize = SIZEOF_RESXMLTREE_NAMESPACE_EXT /*sizeof(ResXMLTree_namespaceExt)*/;
538           break;
539         case RES_XML_START_ELEMENT_TYPE:
540           minExtSize = SIZEOF_RESXMLTREE_ATTR_EXT /*sizeof(ResXMLTree_attrExt)*/;
541           break;
542         case RES_XML_END_ELEMENT_TYPE:
543           minExtSize = ResXMLTree_endElementExt.SIZEOF /*sizeof(ResXMLTree_endElementExt)*/;
544           break;
545         case RES_XML_CDATA_TYPE:
546           minExtSize = SIZEOF_RESXMLTREE_CDATA_EXT /*sizeof(ResXMLTree_cdataExt)*/;
547           break;
548         default:
549           ALOGW(
550               "Unknown XML block: header type %d in node at %d\n",
551               (int) dtohs(next.header.type), (next.myOffset() - mTree.mHeader.myOffset()));
552           continue;
553       }
554 
555       if ((totalSize - headerSize) < minExtSize) {
556         ALOGW(
557             "Bad XML block: header type 0x%x in node at 0x%x has size %d, need %d\n",
558             (int) dtohs(next.header.type),
559             (next.myOffset() - mTree.mHeader.myOffset()),
560             (int) (totalSize - headerSize),
561             (int) minExtSize);
562         return (mEventCode = BAD_DOCUMENT);
563       }
564 
565       // printf("CurNode=%s, CurExt=%s, headerSize=%d, minExtSize=%d\n",
566       //       mCurNode, mCurExt, headerSize, minExtSize);
567 
568       return eventCode;
569     } while (true);
570   }
571 
getPosition(ResXMLPosition pos)572   void getPosition(ResXMLPosition pos) {
573     pos.eventCode = mEventCode;
574     pos.curNode = mCurNode;
575     pos.curExt = mCurExt;
576   }
577 
setPosition(final ResXMLPosition pos)578   void setPosition(final ResXMLPosition pos) {
579     mEventCode = pos.eventCode;
580     mCurNode = pos.curNode;
581     mCurExt = pos.curExt;
582   }
583 
setSourceResourceId(int resId)584   public void setSourceResourceId(int resId) {
585     mSourceResourceId = resId;
586   }
587 
getSourceResourceId()588   public int getSourceResourceId() {
589     return mSourceResourceId;
590   }
591 
592   static class ResXMLPosition {
593     int eventCode;
594     ResXMLTree_node curNode;
595     int curExt;
596   }
597   ;
598 }
599