Home | History | Annotate | Download | only in aapt
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <androidfw/ResourceTypes.h>
     18 #include <utils/String8.h>
     19 
     20 #include "AaptXml.h"
     21 
     22 using namespace android;
     23 
     24 namespace AaptXml {
     25 
     26 static String8 getStringAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex,
     27         String8* outError) {
     28     Res_value value;
     29     if (tree.getAttributeValue(attrIndex, &value) < 0) {
     30         if (outError != NULL) {
     31             *outError = "could not find attribute at index";
     32         }
     33         return String8();
     34     }
     35 
     36     if (value.dataType != Res_value::TYPE_STRING) {
     37         if (outError != NULL) {
     38             *outError = "attribute is not a string value";
     39         }
     40         return String8();
     41     }
     42 
     43     size_t len;
     44     const char16_t* str = tree.getAttributeStringValue(attrIndex, &len);
     45     return str ? String8(str, len) : String8();
     46 }
     47 
     48 static int32_t getIntegerAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex,
     49     int32_t defValue, String8* outError) {
     50     Res_value value;
     51     if (tree.getAttributeValue(attrIndex, &value) < 0) {
     52         if (outError != NULL) {
     53             *outError = "could not find attribute at index";
     54         }
     55         return defValue;
     56     }
     57 
     58     if (value.dataType < Res_value::TYPE_FIRST_INT
     59             || value.dataType > Res_value::TYPE_LAST_INT) {
     60         if (outError != NULL) {
     61             *outError = "attribute is not an integer value";
     62         }
     63         return defValue;
     64     }
     65     return value.data;
     66 }
     67 
     68 
     69 ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) {
     70     size_t attrCount = tree.getAttributeCount();
     71     for (size_t i = 0; i < attrCount; i++) {
     72         if (tree.getAttributeNameResID(i) == attrRes) {
     73             return (ssize_t)i;
     74         }
     75     }
     76     return -1;
     77 }
     78 
     79 String8 getAttribute(const ResXMLTree& tree, const char* ns,
     80         const char* attr, String8* outError) {
     81     ssize_t idx = tree.indexOfAttribute(ns, attr);
     82     if (idx < 0) {
     83         return String8();
     84     }
     85     return getStringAttributeAtIndex(tree, idx, outError);
     86 }
     87 
     88 String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) {
     89     ssize_t idx = indexOfAttribute(tree, attrRes);
     90     if (idx < 0) {
     91         return String8();
     92     }
     93     return getStringAttributeAtIndex(tree, idx, outError);
     94 }
     95 
     96 String8 getResolvedAttribute(const ResTable& resTable, const ResXMLTree& tree,
     97         uint32_t attrRes, String8* outError) {
     98     ssize_t idx = indexOfAttribute(tree, attrRes);
     99     if (idx < 0) {
    100         return String8();
    101     }
    102     Res_value value;
    103     if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
    104         if (value.dataType == Res_value::TYPE_STRING) {
    105             size_t len;
    106             const char16_t* str = tree.getAttributeStringValue(idx, &len);
    107             return str ? String8(str, len) : String8();
    108         }
    109         resTable.resolveReference(&value, 0);
    110         if (value.dataType != Res_value::TYPE_STRING) {
    111             if (outError != NULL) {
    112                 *outError = "attribute is not a string value";
    113             }
    114             return String8();
    115         }
    116     }
    117     size_t len;
    118     const Res_value* value2 = &value;
    119     const char16_t* str = resTable.valueToString(value2, 0, NULL, &len);
    120     return str ? String8(str, len) : String8();
    121 }
    122 
    123 int32_t getIntegerAttribute(const ResXMLTree& tree, const char* ns,
    124         const char* attr, int32_t defValue, String8* outError) {
    125     ssize_t idx = tree.indexOfAttribute(ns, attr);
    126     if (idx < 0) {
    127         return defValue;
    128     }
    129     return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
    130 }
    131 
    132 int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, int32_t defValue,
    133         String8* outError) {
    134     ssize_t idx = indexOfAttribute(tree, attrRes);
    135     if (idx < 0) {
    136         return defValue;
    137     }
    138     return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
    139 }
    140 
    141 int32_t getResolvedIntegerAttribute(const ResTable& resTable, const ResXMLTree& tree,
    142         uint32_t attrRes, int32_t defValue, String8* outError) {
    143     ssize_t idx = indexOfAttribute(tree, attrRes);
    144     if (idx < 0) {
    145         return defValue;
    146     }
    147     Res_value value;
    148     if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
    149         if (value.dataType == Res_value::TYPE_REFERENCE) {
    150             resTable.resolveReference(&value, 0);
    151         }
    152         if (value.dataType < Res_value::TYPE_FIRST_INT
    153                 || value.dataType > Res_value::TYPE_LAST_INT) {
    154             if (outError != NULL) {
    155                 *outError = "attribute is not an integer value";
    156             }
    157             return defValue;
    158         }
    159     }
    160     return value.data;
    161 }
    162 
    163 void getResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
    164         uint32_t attrRes, Res_value* outValue, String8* outError) {
    165     ssize_t idx = indexOfAttribute(tree, attrRes);
    166     if (idx < 0) {
    167         if (outError != NULL) {
    168             *outError = "attribute could not be found";
    169         }
    170         return;
    171     }
    172     if (tree.getAttributeValue(idx, outValue) != NO_ERROR) {
    173         if (outValue->dataType == Res_value::TYPE_REFERENCE) {
    174             resTable.resolveReference(outValue, 0);
    175         }
    176         // The attribute was found and was resolved if need be.
    177         return;
    178     }
    179     if (outError != NULL) {
    180         *outError = "error getting resolved resource attribute";
    181     }
    182 }
    183 
    184 } // namespace AaptXml
    185