| /* //device/libs/android_runtime/android_util_XmlBlock.cpp |
| ** |
| ** Copyright 2006, The Android Open Source Project |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| #define LOG_TAG "XmlBlock" |
| |
| #include "jni.h" |
| #include "JNIHelp.h" |
| #include <core_jni_helpers.h> |
| #include <androidfw/AssetManager.h> |
| #include <androidfw/ResourceTypes.h> |
| #include <utils/Log.h> |
| #include <utils/misc.h> |
| |
| #include <stdio.h> |
| |
| namespace android { |
| |
| // ---------------------------------------------------------------------------- |
| |
| static jlong android_content_XmlBlock_nativeCreate(JNIEnv* env, jobject clazz, |
| jbyteArray bArray, |
| jint off, jint len) |
| { |
| if (bArray == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| jsize bLen = env->GetArrayLength(bArray); |
| if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) { |
| jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL); |
| return 0; |
| } |
| |
| jbyte* b = env->GetByteArrayElements(bArray, NULL); |
| ResXMLTree* osb = new ResXMLTree(); |
| osb->setTo(b+off, len, true); |
| env->ReleaseByteArrayElements(bArray, b, 0); |
| |
| if (osb->getError() != NO_ERROR) { |
| jniThrowException(env, "java/lang/IllegalArgumentException", NULL); |
| return 0; |
| } |
| |
| return reinterpret_cast<jlong>(osb); |
| } |
| |
| static jlong android_content_XmlBlock_nativeGetStringBlock(JNIEnv* env, jobject clazz, |
| jlong token) |
| { |
| ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token); |
| if (osb == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| return reinterpret_cast<jlong>(&osb->getStrings()); |
| } |
| |
| static jlong android_content_XmlBlock_nativeCreateParseState(JNIEnv* env, jobject clazz, |
| jlong token) |
| { |
| ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token); |
| if (osb == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| ResXMLParser* st = new ResXMLParser(*osb); |
| if (st == NULL) { |
| jniThrowException(env, "java/lang/OutOfMemoryError", NULL); |
| return 0; |
| } |
| |
| st->restart(); |
| |
| return reinterpret_cast<jlong>(st); |
| } |
| |
| static jint android_content_XmlBlock_nativeNext(JNIEnv* env, jobject clazz, |
| jlong token) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| return ResXMLParser::END_DOCUMENT; |
| } |
| |
| do { |
| ResXMLParser::event_code_t code = st->next(); |
| switch (code) { |
| case ResXMLParser::START_TAG: |
| return 2; |
| case ResXMLParser::END_TAG: |
| return 3; |
| case ResXMLParser::TEXT: |
| return 4; |
| case ResXMLParser::START_DOCUMENT: |
| return 0; |
| case ResXMLParser::END_DOCUMENT: |
| return 1; |
| case ResXMLParser::BAD_DOCUMENT: |
| goto bad; |
| default: |
| break; |
| } |
| } while (true); |
| |
| bad: |
| jniThrowException(env, "org/xmlpull/v1/XmlPullParserException", |
| "Corrupt XML binary file"); |
| return ResXMLParser::BAD_DOCUMENT; |
| } |
| |
| static jint android_content_XmlBlock_nativeGetNamespace(JNIEnv* env, jobject clazz, |
| jlong token) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| return -1; |
| } |
| |
| return static_cast<jint>(st->getElementNamespaceID()); |
| } |
| |
| static jint android_content_XmlBlock_nativeGetName(JNIEnv* env, jobject clazz, |
| jlong token) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| return -1; |
| } |
| |
| return static_cast<jint>(st->getElementNameID()); |
| } |
| |
| static jint android_content_XmlBlock_nativeGetText(JNIEnv* env, jobject clazz, |
| jlong token) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| return -1; |
| } |
| |
| return static_cast<jint>(st->getTextID()); |
| } |
| |
| static jint android_content_XmlBlock_nativeGetLineNumber(JNIEnv* env, jobject clazz, |
| jlong token) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| return static_cast<jint>(st->getLineNumber()); |
| } |
| |
| static jint android_content_XmlBlock_nativeGetAttributeCount(JNIEnv* env, jobject clazz, |
| jlong token) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| return static_cast<jint>(st->getAttributeCount()); |
| } |
| |
| static jint android_content_XmlBlock_nativeGetAttributeNamespace(JNIEnv* env, jobject clazz, |
| jlong token, jint idx) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| return static_cast<jint>(st->getAttributeNamespaceID(idx)); |
| } |
| |
| static jint android_content_XmlBlock_nativeGetAttributeName(JNIEnv* env, jobject clazz, |
| jlong token, jint idx) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| return static_cast<jint>(st->getAttributeNameID(idx)); |
| } |
| |
| static jint android_content_XmlBlock_nativeGetAttributeResource(JNIEnv* env, jobject clazz, |
| jlong token, jint idx) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| return static_cast<jint>(st->getAttributeNameResID(idx)); |
| } |
| |
| static jint android_content_XmlBlock_nativeGetAttributeDataType(JNIEnv* env, jobject clazz, |
| jlong token, jint idx) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| return static_cast<jint>(st->getAttributeDataType(idx)); |
| } |
| |
| static jint android_content_XmlBlock_nativeGetAttributeData(JNIEnv* env, jobject clazz, |
| jlong token, jint idx) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| return static_cast<jint>(st->getAttributeData(idx)); |
| } |
| |
| static jint android_content_XmlBlock_nativeGetAttributeStringValue(JNIEnv* env, jobject clazz, |
| jlong token, jint idx) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| return static_cast<jint>(st->getAttributeValueStringID(idx)); |
| } |
| |
| static jint android_content_XmlBlock_nativeGetAttributeIndex(JNIEnv* env, jobject clazz, |
| jlong token, |
| jstring ns, jstring name) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL || name == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| const char16_t* ns16 = NULL; |
| jsize nsLen = 0; |
| if (ns) { |
| ns16 = reinterpret_cast<const char16_t*>(env->GetStringChars(ns, NULL)); |
| nsLen = env->GetStringLength(ns); |
| } |
| |
| const char16_t* name16 = reinterpret_cast<const char16_t*>( |
| env->GetStringChars(name, NULL)); |
| jsize nameLen = env->GetStringLength(name); |
| |
| jint idx = static_cast<jint>(st->indexOfAttribute(ns16, nsLen, name16, nameLen)); |
| |
| if (ns) { |
| env->ReleaseStringChars(ns, reinterpret_cast<const jchar*>(ns16)); |
| } |
| env->ReleaseStringChars(name, reinterpret_cast<const jchar*>(name16)); |
| |
| return idx; |
| } |
| |
| static jint android_content_XmlBlock_nativeGetIdAttribute(JNIEnv* env, jobject clazz, |
| jlong token) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| ssize_t idx = st->indexOfID(); |
| return idx >= 0 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1; |
| } |
| |
| static jint android_content_XmlBlock_nativeGetClassAttribute(JNIEnv* env, jobject clazz, |
| jlong token) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| ssize_t idx = st->indexOfClass(); |
| return idx >= 0 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1; |
| } |
| |
| static jint android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv* env, jobject clazz, |
| jlong token) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return 0; |
| } |
| |
| ssize_t idx = st->indexOfStyle(); |
| if (idx < 0) { |
| return 0; |
| } |
| |
| Res_value value; |
| if (st->getAttributeValue(idx, &value) < 0) { |
| return 0; |
| } |
| |
| return value.dataType == value.TYPE_REFERENCE |
| || value.dataType == value.TYPE_ATTRIBUTE |
| ? value.data : 0; |
| } |
| |
| static void android_content_XmlBlock_nativeDestroyParseState(JNIEnv* env, jobject clazz, |
| jlong token) |
| { |
| ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); |
| if (st == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return; |
| } |
| |
| delete st; |
| } |
| |
| static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz, |
| jlong token) |
| { |
| ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token); |
| if (osb == NULL) { |
| jniThrowNullPointerException(env, NULL); |
| return; |
| } |
| |
| delete osb; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| /* |
| * JNI registration. |
| */ |
| static const JNINativeMethod gXmlBlockMethods[] = { |
| /* name, signature, funcPtr */ |
| { "nativeCreate", "([BII)J", |
| (void*) android_content_XmlBlock_nativeCreate }, |
| { "nativeGetStringBlock", "(J)J", |
| (void*) android_content_XmlBlock_nativeGetStringBlock }, |
| { "nativeCreateParseState", "(J)J", |
| (void*) android_content_XmlBlock_nativeCreateParseState }, |
| { "nativeNext", "(J)I", |
| (void*) android_content_XmlBlock_nativeNext }, |
| { "nativeGetNamespace", "(J)I", |
| (void*) android_content_XmlBlock_nativeGetNamespace }, |
| { "nativeGetName", "(J)I", |
| (void*) android_content_XmlBlock_nativeGetName }, |
| { "nativeGetText", "(J)I", |
| (void*) android_content_XmlBlock_nativeGetText }, |
| { "nativeGetLineNumber", "(J)I", |
| (void*) android_content_XmlBlock_nativeGetLineNumber }, |
| { "nativeGetAttributeCount", "(J)I", |
| (void*) android_content_XmlBlock_nativeGetAttributeCount }, |
| { "nativeGetAttributeNamespace","(JI)I", |
| (void*) android_content_XmlBlock_nativeGetAttributeNamespace }, |
| { "nativeGetAttributeName", "(JI)I", |
| (void*) android_content_XmlBlock_nativeGetAttributeName }, |
| { "nativeGetAttributeResource", "(JI)I", |
| (void*) android_content_XmlBlock_nativeGetAttributeResource }, |
| { "nativeGetAttributeDataType", "(JI)I", |
| (void*) android_content_XmlBlock_nativeGetAttributeDataType }, |
| { "nativeGetAttributeData", "(JI)I", |
| (void*) android_content_XmlBlock_nativeGetAttributeData }, |
| { "nativeGetAttributeStringValue", "(JI)I", |
| (void*) android_content_XmlBlock_nativeGetAttributeStringValue }, |
| { "nativeGetAttributeIndex", "(JLjava/lang/String;Ljava/lang/String;)I", |
| (void*) android_content_XmlBlock_nativeGetAttributeIndex }, |
| { "nativeGetIdAttribute", "(J)I", |
| (void*) android_content_XmlBlock_nativeGetIdAttribute }, |
| { "nativeGetClassAttribute", "(J)I", |
| (void*) android_content_XmlBlock_nativeGetClassAttribute }, |
| { "nativeGetStyleAttribute", "(J)I", |
| (void*) android_content_XmlBlock_nativeGetStyleAttribute }, |
| { "nativeDestroyParseState", "(J)V", |
| (void*) android_content_XmlBlock_nativeDestroyParseState }, |
| { "nativeDestroy", "(J)V", |
| (void*) android_content_XmlBlock_nativeDestroy }, |
| }; |
| |
| int register_android_content_XmlBlock(JNIEnv* env) |
| { |
| return RegisterMethodsOrDie(env, |
| "android/content/res/XmlBlock", gXmlBlockMethods, NELEM(gXmlBlockMethods)); |
| } |
| |
| }; // namespace android |