blob: 45728dbb1bc5dbe7e8e7bed05c8dce831e7a2474 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //device/libs/android_runtime/android_util_XmlBlock.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
Elliott Hughes8451b252011-04-07 19:17:57 -07005** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008**
Elliott Hughes8451b252011-04-07 19:17:57 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010**
Elliott Hughes8451b252011-04-07 19:17:57 -070011** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015** limitations under the License.
16*/
17
18#define LOG_TAG "XmlBlock"
19
20#include "jni.h"
Elliott Hughes8451b252011-04-07 19:17:57 -070021#include "JNIHelp.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022#include <utils/misc.h>
23#include <android_runtime/AndroidRuntime.h>
24#include <utils/AssetManager.h>
25#include <utils/Log.h>
26
27#include <utils/ResourceTypes.h>
28
29#include <stdio.h>
30
31namespace android {
32
33// ----------------------------------------------------------------------------
34
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035static jint android_content_XmlBlock_nativeCreate(JNIEnv* env, jobject clazz,
36 jbyteArray bArray,
37 jint off, jint len)
38{
39 if (bArray == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -070040 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041 return 0;
42 }
43
44 jsize bLen = env->GetArrayLength(bArray);
45 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Elliott Hughes8451b252011-04-07 19:17:57 -070046 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047 return 0;
48 }
49
50 jbyte* b = env->GetByteArrayElements(bArray, NULL);
51 ResXMLTree* osb = new ResXMLTree(b+off, len, true);
52 env->ReleaseByteArrayElements(bArray, b, 0);
53
54 if (osb == NULL || osb->getError() != NO_ERROR) {
Elliott Hughes8451b252011-04-07 19:17:57 -070055 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056 return 0;
57 }
58
59 return (jint)osb;
60}
61
62static jint android_content_XmlBlock_nativeGetStringBlock(JNIEnv* env, jobject clazz,
63 jint token)
64{
65 ResXMLTree* osb = (ResXMLTree*)token;
66 if (osb == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -070067 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 return 0;
69 }
70
71 return (jint)&osb->getStrings();
72}
73
74static jint android_content_XmlBlock_nativeCreateParseState(JNIEnv* env, jobject clazz,
75 jint token)
76{
77 ResXMLTree* osb = (ResXMLTree*)token;
78 if (osb == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -070079 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 return 0;
81 }
82
83 ResXMLParser* st = new ResXMLParser(*osb);
84 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -070085 jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086 return 0;
87 }
88
89 st->restart();
90
91 return (jint)st;
92}
93
94static jint android_content_XmlBlock_nativeNext(JNIEnv* env, jobject clazz,
95 jint token)
96{
97 ResXMLParser* st = (ResXMLParser*)token;
98 if (st == NULL) {
99 return ResXMLParser::END_DOCUMENT;
100 }
101
102 do {
103 jint code = (jint)st->next();
104 switch (code) {
105 case ResXMLParser::START_TAG:
106 return 2;
107 case ResXMLParser::END_TAG:
108 return 3;
109 case ResXMLParser::TEXT:
110 return 4;
111 case ResXMLParser::START_DOCUMENT:
112 return 0;
113 case ResXMLParser::END_DOCUMENT:
114 return 1;
115 case ResXMLParser::BAD_DOCUMENT:
116 goto bad;
117 }
118 } while (true);
Elliott Hughes8451b252011-04-07 19:17:57 -0700119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120bad:
Elliott Hughes8451b252011-04-07 19:17:57 -0700121 jniThrowException(env, "org/xmlpull/v1/XmlPullParserException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 "Corrupt XML binary file");
123 return ResXMLParser::BAD_DOCUMENT;
124}
125
126static jint android_content_XmlBlock_nativeGetNamespace(JNIEnv* env, jobject clazz,
127 jint token)
128{
129 ResXMLParser* st = (ResXMLParser*)token;
130 if (st == NULL) {
131 return -1;
132 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 return (jint)st->getElementNamespaceID();
135}
136
137static jint android_content_XmlBlock_nativeGetName(JNIEnv* env, jobject clazz,
138 jint token)
139{
140 ResXMLParser* st = (ResXMLParser*)token;
141 if (st == NULL) {
142 return -1;
143 }
144
145 return (jint)st->getElementNameID();
146}
147
148static jint android_content_XmlBlock_nativeGetText(JNIEnv* env, jobject clazz,
149 jint token)
150{
151 ResXMLParser* st = (ResXMLParser*)token;
152 if (st == NULL) {
153 return -1;
154 }
155
156 return (jint)st->getTextID();
157}
158
159static jint android_content_XmlBlock_nativeGetLineNumber(JNIEnv* env, jobject clazz,
160 jint token)
161{
162 ResXMLParser* st = (ResXMLParser*)token;
163 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700164 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 return 0;
166 }
167
168 return (jint)st->getLineNumber();
169}
170
171static jint android_content_XmlBlock_nativeGetAttributeCount(JNIEnv* env, jobject clazz,
172 jint token)
173{
174 ResXMLParser* st = (ResXMLParser*)token;
175 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700176 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177 return 0;
178 }
179
180 return (jint)st->getAttributeCount();
181}
182
183static jint android_content_XmlBlock_nativeGetAttributeNamespace(JNIEnv* env, jobject clazz,
184 jint token, jint idx)
185{
186 ResXMLParser* st = (ResXMLParser*)token;
187 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700188 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 return 0;
190 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 return (jint)st->getAttributeNamespaceID(idx);
193}
194
195static jint android_content_XmlBlock_nativeGetAttributeName(JNIEnv* env, jobject clazz,
196 jint token, jint idx)
197{
198 ResXMLParser* st = (ResXMLParser*)token;
199 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700200 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 return 0;
202 }
203
204 return (jint)st->getAttributeNameID(idx);
205}
206
207static jint android_content_XmlBlock_nativeGetAttributeResource(JNIEnv* env, jobject clazz,
208 jint token, jint idx)
209{
210 ResXMLParser* st = (ResXMLParser*)token;
211 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700212 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 return 0;
214 }
215
216 return (jint)st->getAttributeNameResID(idx);
217}
218
219static jint android_content_XmlBlock_nativeGetAttributeDataType(JNIEnv* env, jobject clazz,
220 jint token, jint idx)
221{
222 ResXMLParser* st = (ResXMLParser*)token;
223 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700224 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 return 0;
226 }
227
228 return (jint)st->getAttributeDataType(idx);
229}
230
231static jint android_content_XmlBlock_nativeGetAttributeData(JNIEnv* env, jobject clazz,
232 jint token, jint idx)
233{
234 ResXMLParser* st = (ResXMLParser*)token;
235 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700236 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 return 0;
238 }
239
240 return (jint)st->getAttributeData(idx);
241}
242
243static jint android_content_XmlBlock_nativeGetAttributeStringValue(JNIEnv* env, jobject clazz,
244 jint token, jint idx)
245{
246 ResXMLParser* st = (ResXMLParser*)token;
247 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700248 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 return 0;
250 }
251
252 return (jint)st->getAttributeValueStringID(idx);
253}
254
255static jint android_content_XmlBlock_nativeGetAttributeIndex(JNIEnv* env, jobject clazz,
256 jint token,
257 jstring ns, jstring name)
258{
259 ResXMLParser* st = (ResXMLParser*)token;
260 if (st == NULL || name == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700261 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262 return 0;
263 }
264
265 const char16_t* ns16 = NULL;
266 jsize nsLen = 0;
267 if (ns) {
268 ns16 = env->GetStringChars(ns, NULL);
269 nsLen = env->GetStringLength(ns);
270 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 const char16_t* name16 = env->GetStringChars(name, NULL);
273 jsize nameLen = env->GetStringLength(name);
274
275 jint idx = (jint)st->indexOfAttribute(ns16, nsLen, name16, nameLen);
276
277 if (ns) {
278 env->ReleaseStringChars(ns, ns16);
279 }
280 env->ReleaseStringChars(name, name16);
281
282 return idx;
283}
284
285static jint android_content_XmlBlock_nativeGetIdAttribute(JNIEnv* env, jobject clazz,
286 jint token)
287{
288 ResXMLParser* st = (ResXMLParser*)token;
289 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700290 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 return 0;
292 }
293
294 ssize_t idx = st->indexOfID();
295 return idx >= 0 ? (jint)st->getAttributeValueStringID(idx) : -1;
296}
297
298static jint android_content_XmlBlock_nativeGetClassAttribute(JNIEnv* env, jobject clazz,
299 jint token)
300{
301 ResXMLParser* st = (ResXMLParser*)token;
302 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700303 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 return 0;
305 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 ssize_t idx = st->indexOfClass();
308 return idx >= 0 ? (jint)st->getAttributeValueStringID(idx) : -1;
309}
310
311static jint android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv* env, jobject clazz,
312 jint token)
313{
314 ResXMLParser* st = (ResXMLParser*)token;
315 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700316 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 return 0;
318 }
319
320 ssize_t idx = st->indexOfStyle();
321 if (idx < 0) {
322 return 0;
323 }
324
325 Res_value value;
326 if (st->getAttributeValue(idx, &value) < 0) {
327 return 0;
328 }
329
Elliott Hughes8451b252011-04-07 19:17:57 -0700330 return value.dataType == value.TYPE_REFERENCE
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 || value.dataType == value.TYPE_ATTRIBUTE
332 ? value.data : 0;
333}
334
335static void android_content_XmlBlock_nativeDestroyParseState(JNIEnv* env, jobject clazz,
336 jint token)
337{
338 ResXMLParser* st = (ResXMLParser*)token;
339 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700340 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 return;
342 }
343
344 delete st;
345}
346
347static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz,
348 jint token)
349{
350 ResXMLTree* osb = (ResXMLTree*)token;
351 if (osb == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700352 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 return;
354 }
355
356 delete osb;
357}
358
359// ----------------------------------------------------------------------------
360
361/*
362 * JNI registration.
363 */
364static JNINativeMethod gXmlBlockMethods[] = {
365 /* name, signature, funcPtr */
366 { "nativeCreate", "([BII)I",
367 (void*) android_content_XmlBlock_nativeCreate },
368 { "nativeGetStringBlock", "(I)I",
369 (void*) android_content_XmlBlock_nativeGetStringBlock },
370 { "nativeCreateParseState", "(I)I",
371 (void*) android_content_XmlBlock_nativeCreateParseState },
372 { "nativeNext", "(I)I",
373 (void*) android_content_XmlBlock_nativeNext },
374 { "nativeGetNamespace", "(I)I",
375 (void*) android_content_XmlBlock_nativeGetNamespace },
376 { "nativeGetName", "(I)I",
377 (void*) android_content_XmlBlock_nativeGetName },
378 { "nativeGetText", "(I)I",
379 (void*) android_content_XmlBlock_nativeGetText },
380 { "nativeGetLineNumber", "(I)I",
381 (void*) android_content_XmlBlock_nativeGetLineNumber },
382 { "nativeGetAttributeCount", "(I)I",
383 (void*) android_content_XmlBlock_nativeGetAttributeCount },
384 { "nativeGetAttributeNamespace","(II)I",
385 (void*) android_content_XmlBlock_nativeGetAttributeNamespace },
386 { "nativeGetAttributeName", "(II)I",
387 (void*) android_content_XmlBlock_nativeGetAttributeName },
388 { "nativeGetAttributeResource", "(II)I",
389 (void*) android_content_XmlBlock_nativeGetAttributeResource },
390 { "nativeGetAttributeDataType", "(II)I",
391 (void*) android_content_XmlBlock_nativeGetAttributeDataType },
392 { "nativeGetAttributeData", "(II)I",
393 (void*) android_content_XmlBlock_nativeGetAttributeData },
394 { "nativeGetAttributeStringValue", "(II)I",
395 (void*) android_content_XmlBlock_nativeGetAttributeStringValue },
396 { "nativeGetAttributeIndex", "(ILjava/lang/String;Ljava/lang/String;)I",
397 (void*) android_content_XmlBlock_nativeGetAttributeIndex },
398 { "nativeGetIdAttribute", "(I)I",
399 (void*) android_content_XmlBlock_nativeGetIdAttribute },
400 { "nativeGetClassAttribute", "(I)I",
401 (void*) android_content_XmlBlock_nativeGetClassAttribute },
402 { "nativeGetStyleAttribute", "(I)I",
403 (void*) android_content_XmlBlock_nativeGetStyleAttribute },
404 { "nativeDestroyParseState", "(I)V",
405 (void*) android_content_XmlBlock_nativeDestroyParseState },
406 { "nativeDestroy", "(I)V",
407 (void*) android_content_XmlBlock_nativeDestroy },
408};
409
410int register_android_content_XmlBlock(JNIEnv* env)
411{
412 return AndroidRuntime::registerNativeMethods(env,
413 "android/content/res/XmlBlock", gXmlBlockMethods, NELEM(gXmlBlockMethods));
414}
415
416}; // namespace android