ResourceTable.cpp revision 282e181b58cf72b6ca770dc7ca5f91f135444502
1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Build resource files from raw assets.
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceTable.h"
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h"
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h"
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceIdCache.h"
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <androidfw/ResourceTypes.h>
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/ByteOrder.h>
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <stdarg.h>
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#define NOISY(x) //x
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t compileXmlFile(const sp<AaptAssets>& assets,
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& target,
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* table,
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int options)
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<XMLNode> root = XMLNode::parse(target);
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (root == NULL) {
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return compileXmlFile(assets, root, target, table, options);
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t compileXmlFile(const sp<AaptAssets>& assets,
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& target,
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& outTarget,
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* table,
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int options)
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<XMLNode> root = XMLNode::parse(target);
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (root == NULL) {
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return compileXmlFile(assets, root, outTarget, table, options);
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t compileXmlFile(const sp<AaptAssets>& assets,
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<XMLNode>& root,
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& target,
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* table,
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int options)
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((options&XML_COMPILE_STRIP_WHITESPACE) != 0) {
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        root->removeWhitespace(true, NULL);
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else  if ((options&XML_COMPILE_COMPACT_WHITESPACE) != 0) {
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        root->removeWhitespace(false, NULL);
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((options&XML_COMPILE_UTF8) != 0) {
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        root->setUTF8(true);
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors = false;
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((options&XML_COMPILE_ASSIGN_ATTRIBUTE_IDS) != 0) {
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = root->assignResourceIds(assets, table);
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasErrors = true;
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = root->parseValues(assets, table);
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        hasErrors = true;
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (hasErrors) {
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Input XML Resource:\n"));
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(root->print());
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = root->flatten(target,
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            (options&XML_COMPILE_STRIP_COMMENTS) != 0,
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            (options&XML_COMPILE_STRIP_RAW_VALUES) != 0);
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Output XML Resource:\n"));
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(ResXMLTree tree;
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        tree.setTo(target->getData(), target->getSize());
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printXMLBlock(&tree));
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    target->setCompressionMethod(ZipEntry::kCompressDeflated);
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#undef NOISY
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#define NOISY(x) //x
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistruct flag_entry
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t* name;
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t nameLen;
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t value;
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char* description;
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t referenceArray[] =
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'r', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e' };
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t stringArray[] =
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 's', 't', 'r', 'i', 'n', 'g' };
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t integerArray[] =
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'i', 'n', 't', 'e', 'g', 'e', 'r' };
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t booleanArray[] =
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'b', 'o', 'o', 'l', 'e', 'a', 'n' };
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t colorArray[] =
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'c', 'o', 'l', 'o', 'r' };
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t floatArray[] =
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'f', 'l', 'o', 'a', 't' };
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t dimensionArray[] =
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n' };
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t fractionArray[] =
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'f', 'r', 'a', 'c', 't', 'i', 'o', 'n' };
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t enumArray[] =
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'e', 'n', 'u', 'm' };
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t flagsArray[] =
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { 'f', 'l', 'a', 'g', 's' };
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const flag_entry gFormatFlags[] = {
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { referenceArray, sizeof(referenceArray)/2, ResTable_map::TYPE_REFERENCE,
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a reference to another resource, in the form \"<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>\"\n"
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "or to a theme attribute in the form \"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>\"."},
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { stringArray, sizeof(stringArray)/2, ResTable_map::TYPE_STRING,
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a string value, using '\\\\;' to escape characters such as '\\\\n' or '\\\\uxxxx' for a unicode character." },
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { integerArray, sizeof(integerArray)/2, ResTable_map::TYPE_INTEGER,
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "an integer value, such as \"<code>100</code>\"." },
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { booleanArray, sizeof(booleanArray)/2, ResTable_map::TYPE_BOOLEAN,
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a boolean value, either \"<code>true</code>\" or \"<code>false</code>\"." },
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { colorArray, sizeof(colorArray)/2, ResTable_map::TYPE_COLOR,
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a color value, in the form of \"<code>#<i>rgb</i></code>\", \"<code>#<i>argb</i></code>\",\n"
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "\"<code>#<i>rrggbb</i></code>\", or \"<code>#<i>aarrggbb</i></code>\"." },
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { floatArray, sizeof(floatArray)/2, ResTable_map::TYPE_FLOAT,
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a floating point value, such as \"<code>1.2</code>\"."},
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { dimensionArray, sizeof(dimensionArray)/2, ResTable_map::TYPE_DIMENSION,
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a dimension value, which is a floating point number appended with a unit such as \"<code>14.5sp</code>\".\n"
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),\n"
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "in (inches), mm (millimeters)." },
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { fractionArray, sizeof(fractionArray)/2, ResTable_map::TYPE_FRACTION,
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "a fractional value, which is a floating point number appended with either % or %p, such as \"<code>14.5%</code>\".\n"
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "The % suffix always means a percentage of the base size; the optional %p suffix provides a size relative to\n"
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      "some parent container." },
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { enumArray, sizeof(enumArray)/2, ResTable_map::TYPE_ENUM, NULL },
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { flagsArray, sizeof(flagsArray)/2, ResTable_map::TYPE_FLAGS, NULL },
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { NULL, 0, 0, NULL }
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t suggestedArray[] = { 's', 'u', 'g', 'g', 'e', 's', 't', 'e', 'd' };
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const flag_entry l10nRequiredFlags[] = {
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { suggestedArray, sizeof(suggestedArray)/2, ResTable_map::L10N_SUGGESTED, NULL },
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    { NULL, 0, 0, NULL }
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t nulStr[] = { 0 };
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic uint32_t parse_flags(const char16_t* str, size_t len,
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const flag_entry* flags, bool* outError = NULL)
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (len > 0 && isspace(*str)) {
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        str++;
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        len--;
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (len > 0 && isspace(str[len-1])) {
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        len--;
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t* const end = str + len;
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t value = 0;
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (str < end) {
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char16_t* div = str;
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (div < end && *div != '|') {
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            div++;
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const flag_entry* cur = flags;
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (cur->name) {
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strzcmp16(cur->name, cur->nameLen, str, div-str) == 0) {
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                value |= cur->value;
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            cur++;
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!cur->name) {
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (outError) *outError = true;
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        str = div < end ? div+1 : div;
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outError) *outError = false;
206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return value;
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String16 mayOrMust(int type, int flags)
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((type&(~flags)) == 0) {
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return String16("<p>Must");
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return String16("<p>May");
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void appendTypeInfo(ResourceTable* outTable, const String16& pkg,
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& typeName, const String16& ident, int type,
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const flag_entry* flags)
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hadType = false;
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (flags->name) {
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if ((type&flags->value) != 0 && flags->description != NULL) {
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 fullMsg(mayOrMust(type, flags->value));
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fullMsg.append(String16(" be "));
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fullMsg.append(String16(flags->description));
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            outTable->appendTypeComment(pkg, typeName, ident, fullMsg);
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hadType = true;
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        flags++;
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (hadType && (type&ResTable_map::TYPE_REFERENCE) == 0) {
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outTable->appendTypeComment(pkg, typeName, ident,
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16("<p>This may also be a reference to a resource (in the form\n"
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                         "\"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>\") or\n"
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                         "theme attribute (in the form\n"
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                         "\"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>\")\n"
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                         "containing a value of this type."));
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistruct PendingAttribute
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 myPackage;
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const SourcePos sourcePos;
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const bool appendComment;
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t type;
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 ident;
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 comment;
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors;
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool added;
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PendingAttribute(String16 _package, const sp<AaptFile>& in,
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResXMLTree& block, bool _appendComment)
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        : myPackage(_package)
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , sourcePos(in->getPrintableSource(), block.getLineNumber())
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , appendComment(_appendComment)
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , type(ResTable_map::TYPE_ANY)
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , hasErrors(false)
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        , added(false)
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    {
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t createIfNeeded(ResourceTable* outTable)
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    {
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (added || hasErrors) {
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return NO_ERROR;
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        added = true;
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 attr16("attr");
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outTable->hasBagOrEntry(myPackage, attr16, ident)) {
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Attribute \"%s\" has already been defined\n",
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(ident).string());
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasErrors = true;
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        char numberStr[16];
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sprintf(numberStr, "%d", type);
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = outTable->addBag(sourcePos, myPackage,
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr16, ident, String16(""),
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16("^type"),
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16(numberStr), NULL, NULL);
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasErrors = true;
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outTable->appendComment(myPackage, attr16, ident, comment, appendComment);
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("Attribute %s comment: %s\n", String8(ident).string(),
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //     String8(comment).string());
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic status_t compileAttribute(const sp<AaptFile>& in,
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 ResXMLTree& block,
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& myPackage,
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 ResourceTable* outTable,
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 String16* outIdent = NULL,
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool inStyleable = false)
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    PendingAttribute attr(myPackage, in, block, inStyleable);
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 attr16("attr");
308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 id16("id");
309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Attribute type constants.
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 enum16("enum");
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 flag16("flag");
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree::event_code_t code;
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t identIdx = block.indexOfAttribute(NULL, "name");
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (identIdx >= 0) {
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.ident = String16(block.getAttributeStringValue(identIdx, &len));
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outIdent) {
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            *outIdent = attr.ident;
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.sourcePos.error("A 'name' attribute is required for <attr>\n");
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.hasErrors = true;
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    attr.comment = String16(
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            block.getComment(&len) ? block.getComment(&len) : nulStr);
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t typeIdx = block.indexOfAttribute(NULL, "format");
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (typeIdx >= 0) {
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 typeStr = String16(block.getAttributeStringValue(typeIdx, &len));
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.type = parse_flags(typeStr.string(), typeStr.size(), gFormatFlags);
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (attr.type == 0) {
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.sourcePos.error("Tag <attr> 'format' attribute value \"%s\" not valid\n",
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(typeStr).string());
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (!inStyleable) {
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Attribute definitions outside of styleables always define the
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // attribute as a generic value.
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("Attribute %s: type=0x%08x\n", String8(attr.ident).string(), attr.type);
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t minIdx = block.indexOfAttribute(NULL, "min");
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (minIdx >= 0) {
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 val = String16(block.getAttributeStringValue(minIdx, &len));
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!ResTable::stringToInt(val.string(), val.size(), NULL)) {
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.sourcePos.error("Tag <attr> 'min' attribute must be a number, not \"%s\"\n",
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(val).string());
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!attr.hasErrors) {
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident,
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16(""), String16("^min"), String16(val), NULL, NULL);
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t maxIdx = block.indexOfAttribute(NULL, "max");
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (maxIdx >= 0) {
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 val = String16(block.getAttributeStringValue(maxIdx, &len));
371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!ResTable::stringToInt(val.string(), val.size(), NULL)) {
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.sourcePos.error("Tag <attr> 'max' attribute must be a number, not \"%s\"\n",
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(val).string());
374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!attr.hasErrors) {
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident,
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16(""), String16("^max"), String16(val), NULL, NULL);
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((minIdx >= 0 || maxIdx >= 0) && (attr.type&ResTable_map::TYPE_INTEGER) == 0) {
385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.sourcePos.error("Tag <attr> must have format=integer attribute if using max or min\n");
386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.hasErrors = true;
387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t l10nIdx = block.indexOfAttribute(NULL, "localization");
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (l10nIdx >= 0) {
391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const uint16_t* str = block.getAttributeStringValue(l10nIdx, &len);
392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool error;
393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        uint32_t l10n_required = parse_flags(str, len, l10nRequiredFlags, &error);
394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (error) {
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.sourcePos.error("Tag <attr> 'localization' attribute value \"%s\" not valid\n",
396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(str).string());
397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.hasErrors = true;
398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        attr.createIfNeeded(outTable);
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!attr.hasErrors) {
401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char buf[11];
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sprintf(buf, "%d", l10n_required);
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident,
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16(""), String16("^l10n"), String16(buf), NULL, NULL);
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 enumOrFlagsComment;
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code == ResXMLTree::START_TAG) {
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            uint32_t localType = 0;
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), enum16.string()) == 0) {
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                localType = ResTable_map::TYPE_ENUM;
418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), flag16.string()) == 0) {
419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                localType = ResTable_map::TYPE_FLAGS;
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber())
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        .error("Tag <%s> can not appear inside <attr>, only <enum> or <flag>\n",
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(block.getElementName(&len)).string());
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            attr.createIfNeeded(outTable);
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (attr.type == ResTable_map::TYPE_ANY) {
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // No type was explicitly stated, so supplying enum tags
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // implicitly creates an enum or flag.
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.type = 0;
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if ((attr.type&(ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS)) == 0) {
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Wasn't originally specified as an enum, so update its type.
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.type |= localType;
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!attr.hasErrors) {
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    char numberStr[16];
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sprintf(numberStr, "%d", attr.type);
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addBag(SourcePos(in->getPrintableSource(), block.getLineNumber()),
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            myPackage, attr16, attr.ident, String16(""),
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String16("^type"), String16(numberStr), NULL, NULL, true);
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR) {
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        attr.hasErrors = true;
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if ((uint32_t)(attr.type&(ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS)) != localType) {
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (localType == ResTable_map::TYPE_ENUM) {
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("<enum> attribute can not be used inside a flags format\n");
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    attr.hasErrors = true;
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("<flag> attribute can not be used inside a enum format\n");
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    attr.hasErrors = true;
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 itemIdent;
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "name");
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (itemIdentIdx >= 0) {
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                itemIdent = String16(block.getAttributeStringValue(itemIdentIdx, &len));
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber())
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        .error("A 'name' attribute is required for <enum> or <flag>\n");
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 value;
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t valueIdx = block.indexOfAttribute(NULL, "value");
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (valueIdx >= 0) {
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                value = String16(block.getAttributeStringValue(valueIdx, &len));
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber())
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        .error("A 'value' attribute is required for <enum> or <flag>\n");
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!attr.hasErrors && !ResTable::stringToInt(value.string(), value.size(), NULL)) {
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber())
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        .error("Tag <enum> or <flag> 'value' attribute must be a number,"
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        " not \"%s\"\n",
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(value).string());
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                attr.hasErrors = true;
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Make sure an id is defined for this enum/flag identifier...
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!attr.hasErrors && !outTable->hasBagOrEntry(itemIdent, &id16, &myPackage)) {
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = outTable->startBag(SourcePos(in->getPrintableSource(), block.getLineNumber()),
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                         myPackage, id16, itemIdent, String16(), NULL);
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err != NO_ERROR) {
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    attr.hasErrors = true;
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!attr.hasErrors) {
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (enumOrFlagsComment.size() == 0) {
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append(mayOrMust(attr.type,
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS));
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append((attr.type&ResTable_map::TYPE_ENUM)
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       ? String16(" be one of the following constant values.")
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       : String16(" be one or more (separated by '|') of the following constant values."));
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append(String16("</p>\n<table>\n"
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<colgroup align=\"left\" />\n"
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<colgroup align=\"left\" />\n"
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<colgroup align=\"left\" />\n"
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<tr><th>Constant</th><th>Value</th><th>Description</th></tr>"));
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("\n<tr><td><code>"));
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(itemIdent);
512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("</code></td><td>"));
513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(value);
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("</td><td>"));
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (block.getComment(&len)) {
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append(String16(block.getComment(&len)));
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("</td></tr>"));
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = outTable->addBag(SourcePos(in->getPrintableSource(), block.getLineNumber()),
521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       myPackage,
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       attr16, attr.ident, String16(""),
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       itemIdent, value, NULL, NULL, false, true);
524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err != NO_ERROR) {
525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    attr.hasErrors = true;
526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (code == ResXMLTree::END_TAG) {
529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), attr16.string()) == 0) {
530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if ((attr.type&ResTable_map::TYPE_ENUM) != 0) {
533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (strcmp16(block.getElementName(&len), enum16.string()) != 0) {
534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("Found tag </%s> where </enum> is expected\n",
536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(block.getElementName(&len)).string());
537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return UNKNOWN_ERROR;
538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (strcmp16(block.getElementName(&len), flag16.string()) != 0) {
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("Found tag </%s> where </flag> is expected\n",
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(block.getElementName(&len)).string());
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return UNKNOWN_ERROR;
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!attr.hasErrors && attr.added) {
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        appendTypeInfo(outTable, myPackage, attr16, attr.ident, attr.type, gFormatFlags);
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!attr.hasErrors && enumOrFlagsComment.size() > 0) {
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        enumOrFlagsComment.append(String16("\n</table>"));
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outTable->appendTypeComment(myPackage, attr16, attr.ident, enumOrFlagsComment);
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool localeIsDefined(const ResTable_config& config)
564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return config.locale == 0;
566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t parseAndAddBag(Bundle* bundle,
569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& in,
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResXMLTree* block,
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const ResTable_config& config,
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& myPackage,
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& curType,
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& ident,
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& parentIdent,
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& itemIdent,
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t curFormat,
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool isFormatted,
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& product,
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool pseudolocalize,
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const bool overwrite,
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* outTable)
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 item16("item");
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 str;
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<StringPool::entry_style_span> spans;
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = parseStyledString(bundle, in->getPrintableSource().string(),
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block, item16, &str, &spans, isFormatted,
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            pseudolocalize);
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Adding resource bag entry l=%c%c c=%c%c orien=%d d=%d "
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 " pid=%s, bag=%s, id=%s: %s\n",
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.language[0], config.language[1],
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.country[0], config.country[1],
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.orientation, config.density,
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(parentIdent).string(),
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(ident).string(),
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(itemIdent).string(),
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(str).string()));
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = outTable->addBag(SourcePos(in->getPrintableSource(), block->getLineNumber()),
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           myPackage, curType, ident, parentIdent, itemIdent, str,
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           &spans, &config, overwrite, false, curFormat);
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns true if needle is one of the elements in the comma-separated list
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * haystack, false otherwise.
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool isInProductList(const String16& needle, const String16& haystack) {
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t *needle2 = needle.string();
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t *haystack2 = haystack.string();
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t needlesize = needle.size();
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (*haystack2 != '\0') {
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strncmp16(haystack2, needle2, needlesize) == 0) {
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (haystack2[needlesize] == '\0' || haystack2[needlesize] == ',') {
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return true;
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (*haystack2 != '\0' && *haystack2 != ',') {
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            haystack2++;
630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (*haystack2 == ',') {
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            haystack2++;
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t parseAndAddEntry(Bundle* bundle,
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& in,
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResXMLTree* block,
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const ResTable_config& config,
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& myPackage,
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& curType,
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& ident,
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& curTag,
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool curIsStyled,
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t curFormat,
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool isFormatted,
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& product,
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool pseudolocalize,
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const bool overwrite,
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* outTable)
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 str;
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<StringPool::entry_style_span> spans;
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = parseStyledString(bundle, in->getPrintableSource().string(), block,
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            curTag, &str, curIsStyled ? &spans : NULL,
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            isFormatted, pseudolocalize);
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < NO_ERROR) {
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * If a product type was specified on the command line
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * and also in the string, and the two are not the same,
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * return without adding the string.
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char *bundleProduct = bundle->getProduct();
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundleProduct == NULL) {
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bundleProduct = "";
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (product.size() != 0) {
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /*
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * If the command-line-specified product is empty, only "default"
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * matches.  Other variants are skipped.  This is so generation
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * of the R.java file when the product is not known is predictable.
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundleProduct[0] == '\0') {
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(String16("default").string(), product.string()) != 0) {
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return NO_ERROR;
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            /*
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * The command-line product is not empty.
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * If the product for this string is on the command-line list,
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * it matches.  "default" also matches, but only if nothing
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * else has matched already.
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             */
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (isInProductList(product, String16(bundleProduct))) {
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ;
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(String16("default").string(), product.string()) == 0 &&
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       !outTable->hasBagOrEntry(myPackage, curType, ident, config)) {
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ;
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return NO_ERROR;
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Adding resource entry l=%c%c c=%c%c orien=%d d=%d id=%s: %s\n",
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.language[0], config.language[1],
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.country[0], config.country[1],
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.orientation, config.density,
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(ident).string(), String8(str).string()));
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = outTable->addEntry(SourcePos(in->getPrintableSource(), block->getLineNumber()),
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             myPackage, curType, ident, str, &spans, &config,
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             false, curFormat, overwrite);
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t compileResourceFile(Bundle* bundle,
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const sp<AaptAssets>& assets,
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const sp<AaptFile>& in,
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const ResTable_config& defParams,
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const bool overwrite,
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             ResourceTable* outTable)
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree block;
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = parseXMLResource(in, &block, false, true);
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Top-level tag.
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 resources16("resources");
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Identifier declaration tags.
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 declare_styleable16("declare-styleable");
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 attr16("attr");
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Data creation organizational tags.
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 string16("string");
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 drawable16("drawable");
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 color16("color");
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 bool16("bool");
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 integer16("integer");
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 dimen16("dimen");
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 fraction16("fraction");
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 style16("style");
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 plurals16("plurals");
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 array16("array");
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 string_array16("string-array");
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 integer_array16("integer-array");
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 public16("public");
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 public_padding16("public-padding");
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 private_symbols16("private-symbols");
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 java_symbol16("java-symbol");
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 add_resource16("add-resource");
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 skip16("skip");
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 eat_comment16("eat-comment");
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Data creation tags.
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 bag16("bag");
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 item16("item");
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Attribute type constants.
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 enum16("enum");
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // plural values
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 other16("other");
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityOther16("^other");
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 zero16("zero");
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityZero16("^zero");
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 one16("one");
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityOne16("^one");
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 two16("two");
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityTwo16("^two");
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 few16("few");
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityFew16("^few");
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 many16("many");
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityMany16("^many");
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // useful attribute names and special values
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 name16("name");
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 translatable16("translatable");
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 formatted16("formatted");
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 false16("false");
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 myPackage(assets->getPackage());
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors = false;
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool fileIsTranslatable = true;
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strstr(in->getPrintableSource().string(), "donottranslate") != NULL) {
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fileIsTranslatable = false;
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DefaultKeyedVector<String16, uint32_t> nextPublicId(0);
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree::event_code_t code;
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    do {
802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        code = block.next();
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } while (code == ResXMLTree::START_NAMESPACE);
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (code != ResXMLTree::START_TAG) {
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "No start tag found\n");
809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strcmp16(block.getElementName(&len), resources16.string()) != 0) {
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Invalid start tag %s\n", String8(block.getElementName(&len)).string());
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_config curParams(defParams);
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_config pseudoParams(curParams);
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        pseudoParams.language[0] = 'z';
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        pseudoParams.language[1] = 'z';
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        pseudoParams.country[0] = 'Z';
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        pseudoParams.country[1] = 'Z';
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code == ResXMLTree::START_TAG) {
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16* curTag = NULL;
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 curType;
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int32_t curFormat = ResTable_map::TYPE_ANY;
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsBag = false;
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsBagReplaceOnOverwrite = false;
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsStyled = false;
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsPseudolocalizable = false;
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsFormatted = fileIsTranslatable;
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool localHasErrors = false;
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        && code != ResXMLTree::BAD_DOCUMENT) {
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        && code != ResXMLTree::BAD_DOCUMENT) {
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), public16.string()) == 0) {
860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 type;
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <public>\n");
866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type = String16(block.getAttributeStringValue(typeIdx, &len));
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <public>\n");
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t ident = 0;
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t identIdx = block.indexOfAttribute(NULL, "id");
880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (identIdx >= 0) {
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const char16_t* identStr = block.getAttributeStringValue(identIdx, &len);
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value identValue;
883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!ResTable::stringToInt(identStr, len, &identValue)) {
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Given 'id' attribute is not an integer: %s\n",
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getAttributeStringValue(identIdx, &len)).string());
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ident = identValue.data;
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        nextPublicId.replaceValueFor(type, ident+1);
890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (nextPublicId.indexOfKey(type) < 0) {
892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("No 'id' attribute supplied <public>,"
893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " and no previous id defined in this file.\n");
894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (!localHasErrors) {
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ident = nextPublicId.valueFor(type);
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    nextPublicId.replaceValueFor(type, ident+1);
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addPublic(srcPos, myPackage, type, name, ident);
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err < NO_ERROR) {
903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8(type), srcPos);
910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->makeSymbolPublic(String8(name), srcPos);
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 comment(
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block.getComment(&len) ? block.getComment(&len) : nulStr);
915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->appendComment(String8(name), comment, srcPos);
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Unable to create symbols!\n");
918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), public16.string()) == 0) {
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 type;
935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <public-padding>\n");
938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type = String16(block.getAttributeStringValue(typeIdx, &len));
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <public-padding>\n");
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t start = 0;
951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t startIdx = block.indexOfAttribute(NULL, "start");
952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (startIdx >= 0) {
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const char16_t* startStr = block.getAttributeStringValue(startIdx, &len);
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value startValue;
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!ResTable::stringToInt(startStr, len, &startValue)) {
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Given 'start' attribute is not an integer: %s\n",
957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getAttributeStringValue(startIdx, &len)).string());
958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        start = startValue.data;
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (nextPublicId.indexOfKey(type) < 0) {
963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("No 'start' attribute supplied <public-padding>,"
964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " and no previous id defined in this file.\n");
965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (!localHasErrors) {
967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    start = nextPublicId.valueFor(type);
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t end = 0;
971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t endIdx = block.indexOfAttribute(NULL, "end");
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (endIdx >= 0) {
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const char16_t* endStr = block.getAttributeStringValue(endIdx, &len);
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value endValue;
975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!ResTable::stringToInt(endStr, len, &endValue)) {
976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Given 'end' attribute is not an integer: %s\n",
977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getAttributeStringValue(endIdx, &len)).string());
978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        end = endValue.data;
981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("No 'end' attribute supplied <public-padding>\n");
984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (end >= start) {
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    nextPublicId.replaceValueFor(type, end+1);
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("Padding start '%ul' is after end '%ul'\n",
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            start, end);
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 comment(
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    block.getComment(&len) ? block.getComment(&len) : nulStr);
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (uint32_t curIdent=start; curIdent<=end; curIdent++) {
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (localHasErrors) {
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 curName(name);
1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    char buf[64];
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sprintf(buf, "%d", (int)(end-curIdent+1));
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curName.append(String16(buf));
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addEntry(srcPos, myPackage, type, curName,
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                             String16("padding"), NULL, &curParams, false,
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                             ResTable_map::TYPE_STRING, overwrite);
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err < NO_ERROR) {
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addPublic(srcPos, myPackage, type,
1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            curName, curIdent);
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err < NO_ERROR) {
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8(type), srcPos);
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->makeSymbolPublic(String8(curName), srcPos);
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->appendComment(String8(curName), comment, srcPos);
1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Unable to create symbols!\n");
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) {
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 pkg;
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t pkgIdx = block.indexOfAttribute(NULL, "package");
1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (pkgIdx < 0) {
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "A 'package' attribute is required for <private-symbols>\n");
1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                pkg = String16(block.getAttributeStringValue(pkgIdx, &len));
1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    assets->setSymbolsPrivatePackage(String8(pkg));
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) {
1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), java_symbol16.string()) == 0) {
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 type;
1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <public>\n");
1070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type = String16(block.getAttributeStringValue(typeIdx, &len));
1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <public>\n");
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<AaptSymbols> symbols = assets->getJavaSymbolsFor(String8("R"));
1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (symbols != NULL) {
1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols = symbols->addNestedSymbol(String8(type), srcPos);
1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (symbols != NULL) {
1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols->makeSymbolJavaSymbol(String8(name), srcPos);
1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 comment(
1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        block.getComment(&len) ? block.getComment(&len) : nulStr);
1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols->appendComment(String8(name), comment, srcPos);
1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("Unable to create symbols!\n");
1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), java_symbol16.string()) == 0) {
1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) {
1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
1108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 typeName;
1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <add-resource>\n");
1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                typeName = String16(block.getAttributeStringValue(typeIdx, &len));
1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
1119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
1120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <add-resource>\n");
1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
1124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outTable->canAddEntry(srcPos, myPackage, typeName, name);
1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) {
1130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) {
1137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
1138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 ident;
1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t identIdx = block.indexOfAttribute(NULL, "name");
1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (identIdx < 0) {
1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <declare-styleable>\n");
1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ident = String16(block.getAttributeStringValue(identIdx, &len));
1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8("styleable"), srcPos);
1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptSymbols> styleSymbols = symbols;
1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8(ident), srcPos);
1155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols == NULL) {
1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Unable to create symbols!\n");
1158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return UNKNOWN_ERROR;
1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 comment(
1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        block.getComment(&len) ? block.getComment(&len) : nulStr);
1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    styleSymbols->appendComment(String8(ident), comment, srcPos);
1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols = NULL;
1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::START_TAG) {
1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            while ((code=block.next()) != ResXMLTree::END_DOCUMENT
1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                   && code != ResXMLTree::BAD_DOCUMENT) {
1173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (code == ResXMLTree::END_TAG) {
1174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        break;
1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    }
1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            continue;
1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            while ((code=block.next()) != ResXMLTree::END_DOCUMENT
1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                   && code != ResXMLTree::BAD_DOCUMENT) {
1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (code == ResXMLTree::END_TAG) {
1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        break;
1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    }
1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            continue;
1190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (strcmp16(block.getElementName(&len), attr16.string()) != 0) {
1191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Tag <%s> can not appear inside <declare-styleable>, only <attr>\n",
1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(block.getElementName(&len)).string());
1194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return UNKNOWN_ERROR;
1195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 comment(
1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block.getComment(&len) ? block.getComment(&len) : nulStr);
1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 itemIdent;
1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        err = compileAttribute(in, block, myPackage, outTable, &itemIdent, true);
1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err != NO_ERROR) {
1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (symbols != NULL) {
1206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos srcPos(String8(in->getPrintableSource()), block.getLineNumber());
1207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            symbols->addSymbol(String8(itemIdent), 0, srcPos);
1208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            symbols->appendComment(String8(itemIdent), comment, srcPos);
1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            //printf("Attribute %s comment: %s\n", String8(itemIdent).string(),
1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            //     String8(comment).string());
1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (code == ResXMLTree::END_TAG) {
1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) {
1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "Found tag </%s> where </attr> is expected\n",
1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getElementName(&len)).string());
1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return UNKNOWN_ERROR;
1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), attr16.string()) == 0) {
1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = compileAttribute(in, block, myPackage, outTable, NULL);
1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err != NO_ERROR) {
1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = true;
1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), item16.string()) == 0) {
1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &item16;
1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t attri = block.indexOfAttribute(NULL, "type");
1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (attri >= 0) {
1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curType = String16(block.getAttributeStringValue(attri, &len));
1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ssize_t formatIdx = block.indexOfAttribute(NULL, "format");
1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (formatIdx >= 0) {
1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 formatStr = String16(block.getAttributeStringValue(
1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                formatIdx, &len));
1241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        curFormat = parse_flags(formatStr.string(), formatStr.size(),
1242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                gFormatFlags);
1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (curFormat == 0) {
1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Tag <item> 'format' attribute value \"%s\" not valid\n",
1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(formatStr).string());
1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "A 'type' attribute is required for <item>\n");
1253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsStyled = true;
1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), string16.string()) == 0) {
1257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Note the existence and locale of every string we process
1258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                char rawLocale[16];
1259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curParams.getLocale(rawLocale);
1260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 locale(rawLocale);
1261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 translatable;
1263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 formatted;
1264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                size_t n = block.getAttributeCount();
1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t i = 0; i < n; i++) {
1267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    size_t length;
1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const uint16_t* attr = block.getAttributeName(i, &length);
1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (strcmp16(attr, name16.string()) == 0) {
1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        name.setTo(block.getAttributeStringValue(i, &length));
1271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (strcmp16(attr, translatable16.string()) == 0) {
1272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        translatable.setTo(block.getAttributeStringValue(i, &length));
1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (strcmp16(attr, formatted16.string()) == 0) {
1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        formatted.setTo(block.getAttributeStringValue(i, &length));
1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (name.size() > 0) {
1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (translatable == false16) {
1280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        curIsFormatted = false;
1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // Untranslatable strings must only exist in the default [empty] locale
1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (locale.size() > 0) {
1283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(stderr, "aapt: warning: string '%s' in %s marked untranslatable but exists"
1284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    " in locale '%s'\n", String8(name).string(),
1285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    bundle->getResourceSourceDirs()[0],
1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    locale.string());
1287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // hasErrors = localHasErrors = true;
1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // Intentionally empty block:
1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            //
1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // Don't add untranslatable strings to the localization table; that
1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // way if we later see localizations of them, they'll be flagged as
1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // having no default translation.
1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        outTable->addLocalization(name, locale);
1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (formatted == false16) {
1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        curIsFormatted = false;
1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &string16;
1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = string16;
1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
1307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsStyled = true;
1308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsPseudolocalizable = true;
1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), drawable16.string()) == 0) {
1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &drawable16;
1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = drawable16;
1312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_COLOR;
1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), color16.string()) == 0) {
1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &color16;
1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = color16;
1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_COLOR;
1317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), bool16.string()) == 0) {
1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &bool16;
1319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = bool16;
1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_BOOLEAN;
1321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), integer16.string()) == 0) {
1322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &integer16;
1323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = integer16;
1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_INTEGER;
1325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), dimen16.string()) == 0) {
1326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &dimen16;
1327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = dimen16;
1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_DIMENSION;
1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), fraction16.string()) == 0) {
1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &fraction16;
1331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = fraction16;
1332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_FRACTION;
1333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), bag16.string()) == 0) {
1334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &bag16;
1335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t attri = block.indexOfAttribute(NULL, "type");
1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (attri >= 0) {
1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curType = String16(block.getAttributeStringValue(attri, &len));
1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "A 'type' attribute is required for <bag>\n");
1342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), style16.string()) == 0) {
1345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &style16;
1346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = style16;
1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), plurals16.string()) == 0) {
1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &plurals16;
1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = plurals16;
1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), array16.string()) == 0) {
1353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &array16;
1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = array16;
1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBagReplaceOnOverwrite = true;
1357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t formatIdx = block.indexOfAttribute(NULL, "format");
1358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (formatIdx >= 0) {
1359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 formatStr = String16(block.getAttributeStringValue(
1360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            formatIdx, &len));
1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curFormat = parse_flags(formatStr.string(), formatStr.size(),
1362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            gFormatFlags);
1363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (curFormat == 0) {
1364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "Tag <array> 'format' attribute value \"%s\" not valid\n",
1366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(formatStr).string());
1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), string_array16.string()) == 0) {
1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Check whether these strings need valid formats.
1372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // (simplified form of what string16 does above)
1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                size_t n = block.getAttributeCount();
1374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t i = 0; i < n; i++) {
1375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    size_t length;
1376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const uint16_t* attr = block.getAttributeName(i, &length);
1377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (strcmp16(attr, translatable16.string()) == 0
1378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            || strcmp16(attr, formatted16.string()) == 0) {
1379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const uint16_t* value = block.getAttributeStringValue(i, &length);
1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(value, false16.string()) == 0) {
1381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            curIsFormatted = false;
1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &string_array16;
1388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = array16;
1389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
1390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBagReplaceOnOverwrite = true;
1392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsPseudolocalizable = true;
1393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), integer_array16.string()) == 0) {
1394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &integer_array16;
1395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = array16;
1396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_INTEGER;
1397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBagReplaceOnOverwrite = true;
1399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "Found tag %s where item is expected\n",
1402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(block.getElementName(&len)).string());
1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
1404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 ident;
1407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t identIdx = block.indexOfAttribute(NULL, "name");
1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (identIdx >= 0) {
1409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ident = String16(block.getAttributeStringValue(identIdx, &len));
1410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "A 'name' attribute is required for <%s>\n",
1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(*curTag).string());
1414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasErrors = localHasErrors = true;
1415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 product;
1418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            identIdx = block.indexOfAttribute(NULL, "product");
1419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (identIdx >= 0) {
1420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                product = String16(block.getAttributeStringValue(identIdx, &len));
1421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 comment(block.getComment(&len) ? block.getComment(&len) : nulStr);
1424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (curIsBag) {
1426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Figure out the parent of this bag...
1427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 parentIdent;
1428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t parentIdentIdx = block.indexOfAttribute(NULL, "parent");
1429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (parentIdentIdx >= 0) {
1430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    parentIdent = String16(block.getAttributeStringValue(parentIdentIdx, &len));
1431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ssize_t sep = ident.findLast('.');
1433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (sep >= 0) {
1434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        parentIdent.setTo(ident, sep);
1435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
1439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->startBag(SourcePos(in->getPrintableSource(),
1440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block.getLineNumber()), myPackage, curType, ident,
1441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            parentIdent, &curParams,
1442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            overwrite, curIsBagReplaceOnOverwrite);
1443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR) {
1444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t elmIndex = 0;
1449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                char elmIndexStr[14];
1450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT
1451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        && code != ResXMLTree::BAD_DOCUMENT) {
1452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::START_TAG) {
1454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), item16.string()) != 0) {
1455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Tag <%s> can not appear inside <%s>, only <item>\n",
1457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(block.getElementName(&len)).string(),
1458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(*curTag).string());
1459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return UNKNOWN_ERROR;
1460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 itemIdent;
1463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (curType == array16) {
1464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            sprintf(elmIndexStr, "^index_%d", (int)elmIndex++);
1465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            itemIdent = String16(elmIndexStr);
1466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (curType == plurals16) {
1467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "quantity");
1468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (itemIdentIdx >= 0) {
1469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String16 quantity16(block.getAttributeStringValue(itemIdentIdx, &len));
1470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (quantity16 == other16) {
1471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityOther16;
1472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == zero16) {
1474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityZero16;
1475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == one16) {
1477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityOne16;
1478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == two16) {
1480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityTwo16;
1481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == few16) {
1483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityFew16;
1484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == many16) {
1486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityMany16;
1487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else {
1489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            "Illegal 'quantity' attribute is <item> inside <plurals>\n");
1491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    hasErrors = localHasErrors = true;
1492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else {
1494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        "A 'quantity' attribute is required for <item> inside <plurals>\n");
1496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasErrors = localHasErrors = true;
1497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "name");
1500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (itemIdentIdx >= 0) {
1501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                itemIdent = String16(block.getAttributeStringValue(itemIdentIdx, &len));
1502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else {
1503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        "A 'name' attribute is required for <item>\n");
1505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasErrors = localHasErrors = true;
1506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResXMLParser::ResXMLPosition parserPosition;
1510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        block.getPosition(&parserPosition);
1511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType,
1513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                ident, parentIdent, itemIdent, curFormat, curIsFormatted,
1514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                product, false, overwrite, outTable);
1515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err == NO_ERROR) {
1516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (curIsPseudolocalizable && localeIsDefined(curParams)
1517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    && bundle->getPseudolocalize()) {
1518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // pseudolocalize here
1519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 1
1520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                block.setPosition(parserPosition);
1521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage,
1522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        curType, ident, parentIdent, itemIdent, curFormat,
1523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        curIsFormatted, product, true, overwrite, outTable);
1524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err != NO_ERROR) {
1528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (code == ResXMLTree::END_TAG) {
1531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), curTag->string()) != 0) {
1532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Found tag </%s> where </%s> is expected\n",
1534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(block.getElementName(&len)).string(),
1535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(*curTag).string());
1536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return UNKNOWN_ERROR;
1537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ResXMLParser::ResXMLPosition parserPosition;
1543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                block.getPosition(&parserPosition);
1544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident,
1546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        *curTag, curIsStyled, curFormat, curIsFormatted,
1547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        product, false, overwrite, outTable);
1548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR?
1550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                else if (err == NO_ERROR) {
1553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (curIsPseudolocalizable && localeIsDefined(curParams)
1554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            && bundle->getPseudolocalize()) {
1555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // pseudolocalize here
1556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        block.setPosition(parserPosition);
1557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
1558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                ident, *curTag, curIsStyled, curFormat,
1559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                curIsFormatted, product,
1560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                true, overwrite, outTable);
1561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err != NO_ERROR) {
1562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (comment.size() > 0) {
1570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("Comment for @%s:%s/%s: %s\n", String8(myPackage).string(),
1571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       String8(curType).string(), String8(ident).string(),
1572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       String8(comment).string());
1573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!localHasErrors) {
1576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outTable->appendComment(myPackage, curType, ident, comment, false);
1577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        else if (code == ResXMLTree::END_TAG) {
1580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), resources16.string()) != 0) {
1581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "Unexpected end tag %s\n", String8(block.getElementName(&len)).string());
1583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
1584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        else if (code == ResXMLTree::START_NAMESPACE || code == ResXMLTree::END_NAMESPACE) {
1587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        else if (code == ResXMLTree::TEXT) {
1589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (isWhitespace(block.getText(&len))) {
1590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "Found text \"%s\" where item tag is expected\n",
1594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(block.getText(&len)).string());
1595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
1600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1602282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResourceTable::ResourceTable(Bundle* bundle, const String16& assetsPackage)
1603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    : mAssetsPackage(assetsPackage), mNextPackageId(1), mHaveAppPackage(false),
1604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      mIsAppPackage(!bundle->getExtending()),
1605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      mNumLocal(0),
1606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      mBundle(bundle)
1607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets)
1611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = assets->buildIncludedResources(bundle);
1613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
1614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
1615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // For future reference to included resources.
1618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mAssets = assets;
1619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ResTable& incl = assets->getIncludedResources();
1621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Retrieve all the packages.
1623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = incl.getBasePackageCount();
1624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t phase=0; phase<2; phase++) {
1625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
1626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 name(incl.getBasePackageName(i));
1627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            uint32_t id = incl.getBasePackageId(i);
1628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // First time through: only add base packages (id
1629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // is not 0); second time through add the other
1630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // packages.
1631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (phase != 0) {
1632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (id != 0) {
1633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // Skip base packages -- already one.
1634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    id = 0;
1635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // Assign a dynamic id.
1637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    id = mNextPackageId;
1638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (id != 0) {
1640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (id == 127) {
1641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (mHaveAppPackage) {
1642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(stderr, "Included resources have two application packages!\n");
1643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return UNKNOWN_ERROR;
1644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mHaveAppPackage = true;
1646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (mNextPackageId > id) {
1648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(stderr, "Included base package ID %d already in use!\n", id);
1649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return UNKNOWN_ERROR;
1650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (id != 0) {
1653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                NOISY(printf("Including package %s with ID=%d\n",
1654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             String8(name).string(), id));
1655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<Package> p = new Package(name, id);
1656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mPackages.add(name, p);
1657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mOrderedPackages.add(p);
1658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (id >= mNextPackageId) {
1660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mNextPackageId = id+1;
1661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Every resource table always has one first entry, the bag attributes.
1667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const SourcePos unknown(String8("????"), 0);
1668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> attr = getType(mAssetsPackage, String16("attr"), unknown);
1669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
1671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addPublic(const SourcePos& sourcePos,
1674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& package,
1675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
1676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name,
1677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const uint32_t ident)
1678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sourcePos.error("Error declaring public resource %s/%s for included package %s\n",
1685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8(type).string(), String8(name).string(),
1686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8(package).string());
1687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = getType(package, type, sourcePos);
1691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) {
1692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return t->addPublic(sourcePos, name, ident);
1695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addEntry(const SourcePos& sourcePos,
1698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& package,
1699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& type,
1700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& name,
1701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& value,
1702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const Vector<StringPool::entry_style_span>* style,
1703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const ResTable_config* params,
1704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const bool doSetIndex,
1705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const int32_t format,
1706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const bool overwrite)
1707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Check for adding entries in other packages...  for now we do
1709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // nothing.  We need to do the right thing here to support skinning.
1710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
1716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (name == String16("left")) {
1720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Adding entry left: file=%s, line=%d, type=%s, value=%s\n",
1721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               sourcePos.file.string(), sourcePos.line, String8(type).string(),
1722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               String8(value).string());
1723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = getEntry(package, type, name, sourcePos, overwrite,
1727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           params, doSetIndex);
1728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
1729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = e->setItem(sourcePos, value, style, format, overwrite);
1732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err == NO_ERROR) {
1733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mNumLocal++;
1734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
1736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::startBag(const SourcePos& sourcePos,
1739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& package,
1740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& type,
1741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& name,
1742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& bagParent,
1743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const ResTable_config* params,
1744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool overlay,
1745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool replace, bool isId)
1746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = NO_ERROR;
1748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Check for adding entries in other packages...  for now we do
1750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // nothing.  We need to do the right thing here to support skinning.
1751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    .identifierForName(name.string(), name.size(),
1753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       type.string(), type.size(),
1754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       package.string(), package.size());
1755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
1757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (name == String16("left")) {
1761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Adding bag left: file=%s, line=%d, type=%s\n",
1762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               sourcePos.file.striing(), sourcePos.line, String8(type).string());
1763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (overlay && !mBundle->getAutoAddOverlay() && !hasBagOrEntry(package, type, name)) {
1766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool canAdd = false;
1767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mPackages.valueFor(package);
1768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p != NULL) {
1769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getTypes().valueFor(type);
1770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t != NULL) {
1771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (t->getCanAddEntries().indexOf(name) >= 0) {
1772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    canAdd = true;
1773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!canAdd) {
1777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Resource does not already exist in overlay at '%s'; use <add-resource> to add.\n",
1778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(name).string());
1779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = getEntry(package, type, name, sourcePos, overlay, params);
1783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
1784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If a parent is explicitly specified, set it.
1788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bagParent.size() > 0) {
1789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        e->setParent(bagParent);
1790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((result = e->makeItABag(sourcePos)) != NO_ERROR) {
1793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return result;
1794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (overlay && replace) {
1797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return e->emptyBag(sourcePos);
1798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return result;
1800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addBag(const SourcePos& sourcePos,
1803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& package,
1804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& type,
1805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& name,
1806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& bagParent,
1807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& bagKey,
1808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& value,
1809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const Vector<StringPool::entry_style_span>* style,
1810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const ResTable_config* params,
1811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               bool replace, bool isId, const int32_t format)
1812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Check for adding entries in other packages...  for now we do
1814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // nothing.  We need to do the right thing here to support skinning.
1815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
1821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (name == String16("left")) {
1825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Adding bag left: file=%s, line=%d, type=%s\n",
1826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               sourcePos.file.striing(), sourcePos.line, String8(type).string());
1827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = getEntry(package, type, name, sourcePos, replace, params);
1830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
1831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If a parent is explicitly specified, set it.
1835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bagParent.size() > 0) {
1836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        e->setParent(bagParent);
1837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const bool first = e->getBag().indexOfKey(bagKey) < 0;
1840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = e->addToBag(sourcePos, bagKey, value, style, replace, isId, format);
1841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err == NO_ERROR && first) {
1842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mNumLocal++;
1843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
1845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& package,
1848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
1849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name) const
1850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First look for this in the included resources...
1852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
1858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
1861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
1862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
1863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
1864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
1865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) return true;
1866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
1870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& package,
1873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
1874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name,
1875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const ResTable_config& config) const
1876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First look for this in the included resources...
1878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
1884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
1887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
1888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
1889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
1890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
1891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) {
1892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<Entry> e = c->getEntries().valueFor(config);
1893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (e != NULL) {
1894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return true;
1895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
1901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& ref,
1904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16* defType,
1905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16* defPackage)
1906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 package, type, name;
1908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!ResTable::expandResourceRef(ref.string(), ref.size(), &package, &type, &name,
1909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                defType, defPackage ? defPackage:&mAssetsPackage, NULL)) {
1910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
1911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasBagOrEntry(package, type, name);
1913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::appendComment(const String16& package,
1916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
1917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name,
1918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& comment,
1919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  bool onlyIfEmpty)
1920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
1922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
1923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
1926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
1927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
1928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
1929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
1930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) {
1931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                c->appendComment(comment, onlyIfEmpty);
1932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return true;
1933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
1937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::appendTypeComment(const String16& package,
1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      const String16& type,
1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      const String16& name,
1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      const String16& comment)
1943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
1945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) {
1954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                c->appendTypeComment(comment);
1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return true;
1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::canAddEntry(const SourcePos& pos,
1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& package, const String16& type, const String16& name)
1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = getType(package, type, pos);
1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t != NULL) {
1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t->canAddEntry(name);
1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisize_t ResourceTable::size() const {
1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mPackages.size();
1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisize_t ResourceTable::numLocalResources() const {
1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mNumLocal;
1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasResources() const {
1980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mNumLocal > 0;
1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<AaptFile> ResourceTable::flatten(Bundle* bundle)
1984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8());
1986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = flatten(bundle, data);
1987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err == NO_ERROR ? data : NULL;
1988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiinline uint32_t ResourceTable::getResId(const sp<Package>& p,
1991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const sp<Type>& t,
1992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        uint32_t nameId)
1993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return makeResId(p->getAssignedId(), t->getIndex(), nameId);
1995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getResId(const String16& package,
1998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& type,
1999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& name,
2000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool onlyPublic) const
2001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t id = ResourceIdCache::lookup(package, type, name, onlyPublic);
2003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (id != 0) return id;     // cache hit
2004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) return 0;
2007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First look for this in the included resources...
2009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t specFlags = 0;
2010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
2011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
2012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
2013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size(),
2014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           &specFlags);
2015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
2016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (onlyPublic) {
2017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if ((specFlags & ResTable_typeSpec::SPEC_PUBLIC) == 0) {
2018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return 0;
2019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (Res_INTERNALID(rid)) {
2023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return ResourceIdCache::store(package, type, name, onlyPublic, rid);
2024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return ResourceIdCache::store(package, type, name, onlyPublic,
2026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                Res_MAKEID(p->getAssignedId()-1, Res_GETTYPE(rid), Res_GETENTRY(rid)));
2027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = p->getTypes().valueFor(type);
2030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) return 0;
2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c =  t->getConfigs().valueFor(name);
2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) return 0;
2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t ei = c->getEntryIndex();
2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ei < 0) return 0;
2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return ResourceIdCache::store(package, type, name, onlyPublic,
2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            getResId(p, t, ei));
2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getResId(const String16& ref,
2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16* defType,
2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16* defPackage,
2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const char** outErrorMsg,
2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool onlyPublic) const
2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 package, type, name;
2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool refOnlyPublic = true;
2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!ResTable::expandResourceRef(
2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ref.string(), ref.size(), &package, &type, &name,
2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        defType, defPackage ? defPackage:&mAssetsPackage,
2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outErrorMsg, &refOnlyPublic)) {
2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: ref=%s\n",
2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     String8(ref).string()));
2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: defType=%s\n",
2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     defType ? String8(*defType).string() : "NULL"));
2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: defPackage=%s\n",
2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     defPackage ? String8(*defPackage).string() : "NULL"));
2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: ref=%s\n", String8(ref).string()));
2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanded resource: p=%s, t=%s, n=%s, res=0\n",
2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     String8(package).string(), String8(type).string(),
2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     String8(name).string()));
2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 0;
2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t res = getResId(package, type, name, onlyPublic && refOnlyPublic);
2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Expanded resource: p=%s, t=%s, n=%s, res=%d\n",
2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(package).string(), String8(type).string(),
2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(name).string(), res));
2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (res == 0) {
2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outErrorMsg)
2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            *outErrorMsg = "No resource found that matches the given name";
2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return res;
2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::isValidResourceName(const String16& s)
2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t* p = s.string();
2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool first = true;
2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (*p) {
2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if ((*p >= 'a' && *p <= 'z')
2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            || (*p >= 'A' && *p <= 'Z')
2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            || *p == '_'
2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            || (!first && *p >= '0' && *p <= '9')) {
2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            first = false;
2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p++;
2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::stringToValue(Res_value* outValue, StringPool* pool,
2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& str,
2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  bool preserveSpaces, bool coerceType,
2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  uint32_t attrID,
2097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const Vector<StringPool::entry_style_span>* style,
2098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  String16* outStr, void* accessorCookie,
2099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  uint32_t attrType, const String8* configTypeName,
2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const ConfigDescription* config)
2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 finalStr;
2103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool res = true;
2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (style == NULL || style->size() == 0) {
2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Text is not styled so it can be any type...  let's figure it out.
2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        res = mAssets->getIncludedResources()
2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            .stringToValue(outValue, &finalStr, str.string(), str.size(), preserveSpaces,
2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            coerceType, attrID, NULL, &mAssetsPackage, this,
2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           accessorCookie, attrType);
2111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
2112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Styled text can only be a string, and while collecting the style
2113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // information we have already processed that string!
2114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->size = sizeof(Res_value);
2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->res0 = 0;
2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->dataType = outValue->TYPE_STRING;
2117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->data = 0;
2118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        finalStr = str;
2119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!res) {
2122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
2123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outValue->dataType == outValue->TYPE_STRING) {
2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Should do better merging styles.
2127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pool) {
2128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 configStr;
2129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (config != NULL) {
2130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configStr = config->toString();
2131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configStr = "(null)";
2133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            NOISY(printf("Adding to pool string style #%d config %s: %s\n",
2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    style != NULL ? style->size() : 0,
2136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    configStr.string(), String8(finalStr).string()));
2137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (style != NULL && style->size() > 0) {
2138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outValue->data = pool->add(finalStr, *style, configTypeName, config);
2139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outValue->data = pool->add(finalStr, true, configTypeName, config);
2141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Caller will fill this in later.
2144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            outValue->data = 0;
2145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outStr) {
2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            *outStr = finalStr;
2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getCustomResource(
2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16& package, const String16& type, const String16& name) const
2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getCustomResource: %s %s %s\n", String8(package).string(),
2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //       String8(type).string(), String8(name).string());
2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) return 0;
2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = p->getTypes().valueFor(type);
2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) return 0;
2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c =  t->getConfigs().valueFor(name);
2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) return 0;
2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t ei = c->getEntryIndex();
2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ei < 0) return 0;
2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return getResId(p, t, ei);
2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getCustomResourceWithCreation(
2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& package, const String16& type, const String16& name,
2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const bool createIfNotFound)
2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t resId = getCustomResource(package, type, name);
2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (resId != 0 || !createIfNotFound) {
2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return resId;
2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 value("false");
2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t status = addEntry(mCurrentXmlPos, package, type, name, value, NULL, NULL, true);
2183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (status == NO_ERROR) {
2184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        resId = getResId(package, type, name);
2185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return resId;
2186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return 0;
2188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getRemappedPackage(uint32_t origPackage) const
2191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return origPackage;
2193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeType(uint32_t attrID, uint32_t* outType)
2196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeType #%08x\n", attrID);
2198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_TYPE, &value)) {
2200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("getAttributeType #%08x (%s): #%08x\n", attrID,
2201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //       String8(getEntry(attrID)->getName()).string(), value.data);
2202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outType = value.data;
2203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeMin(uint32_t attrID, uint32_t* outMin)
2209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeMin #%08x\n", attrID);
2211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_MIN, &value)) {
2213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outMin = value.data;
2214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeMax(uint32_t attrID, uint32_t* outMax)
2220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeMax #%08x\n", attrID);
2222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_MAX, &value)) {
2224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outMax = value.data;
2225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getAttributeL10N(uint32_t attrID)
2231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeL10N #%08x\n", attrID);
2233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_L10N, &value)) {
2235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return value.data;
2236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return ResTable_map::L10N_NOT_REQUIRED;
2238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getLocalizationSetting()
2241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mBundle->getRequireLocalization();
2243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::reportError(void* accessorCookie, const char* fmt, ...)
2246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (accessorCookie != NULL && fmt != NULL) {
2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AccessorCookie* ac = (AccessorCookie*)accessorCookie;
2249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int retval=0;
2250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        char buf[1024];
2251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        va_list ap;
2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        va_start(ap, fmt);
2253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retval = vsnprintf(buf, sizeof(buf), fmt, ap);
2254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        va_end(ap);
2255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ac->sourcePos.error("Error: %s (at '%s' with value '%s').\n",
2256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            buf, ac->attr.string(), ac->value.string());
2257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeKeys(
2261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t attrID, Vector<String16>* outKeys)
2262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(attrID);
2264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e != NULL) {
2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = e->getBag().size();
2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16& key = e->getBag().keyAt(i);
2268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (key.size() > 0 && key.string()[0] != '^') {
2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outKeys->add(key);
2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeEnum(
2278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t attrID, const char16_t* name, size_t nameLen,
2279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value* outValue)
2280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeEnum #%08x %s\n", attrID, String8(name, nameLen).string());
2282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 nameStr(name, nameLen);
2283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(attrID);
2284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e != NULL) {
2285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = e->getBag().size();
2286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
2287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //printf("Comparing %s to %s\n", String8(name, nameLen).string(),
2288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //       String8(e->getBag().keyAt(i)).string());
2289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (e->getBag().keyAt(i) == nameStr) {
2290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return getItemValue(attrID, e->getBag().valueAt(i).bagKeyId, outValue);
2291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeFlags(
2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t attrID, const char16_t* name, size_t nameLen,
2299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value* outValue)
2300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    outValue->dataType = Res_value::TYPE_INT_HEX;
2302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    outValue->data = 0;
2303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeFlags #%08x %s\n", attrID, String8(name, nameLen).string());
2305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 nameStr(name, nameLen);
2306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(attrID);
2307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e != NULL) {
2308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = e->getBag().size();
2309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char16_t* end = name + nameLen;
2311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char16_t* pos = name;
2312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (pos < end) {
2313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char16_t* start = pos;
2314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (pos < end && *pos != '|') {
2315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                pos++;
2316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 nameStr(start, pos-start);
2319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t i;
2320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (i=0; i<N; i++) {
2321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Comparing \"%s\" to \"%s\"\n", String8(nameStr).string(),
2322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //       String8(e->getBag().keyAt(i)).string());
2323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (e->getBag().keyAt(i) == nameStr) {
2324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value val;
2325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    bool got = getItemValue(attrID, e->getBag().valueAt(i).bagKeyId, &val);
2326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!got) {
2327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return false;
2328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    //printf("Got value: 0x%08x\n", val.data);
2330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    outValue->data |= val.data;
2331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    break;
2332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (i >= N) {
2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Didn't find this flag identifier.
2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return false;
2338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            pos++;
2340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::assignResourceIds()
2348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
2350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t pi;
2351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t firstError = NO_ERROR;
2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First generate all bag attributes and assign indices.
2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p == NULL || p->getTypes().size() == 0) {
2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Empty, skip!
2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = p->applyPublicTypeOrder();
2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR && firstError == NO_ERROR) {
2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            firstError = err;
2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Generate attributes...
2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getOrderedTypes().size();
2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t ti;
2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (ti=0; ti<N; ti++) {
2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t N = c->getEntries().size();
2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = c->getEntries().valueAt(ei);
2383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e == NULL) {
2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    status_t err = e->generateAttributes(this, p->getName());
2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR && firstError == NO_ERROR) {
2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        firstError = err;
2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const SourcePos unknown(String8("????"), 0);
2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> attr = p->getType(String16("attr"), unknown);
2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Assign indices...
2398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (ti=0; ti<N; ti++) {
2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = t->applyPublicEntryOrder();
2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR && firstError == NO_ERROR) {
2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                firstError = err;
2406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            t->setIndex(ti+1);
2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            LOG_ALWAYS_FATAL_IF(ti == 0 && attr != t,
2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "First type is not attr!");
2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ei=0; ei<N; ei++) {
2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ei);
2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                c->setEntryIndex(ei);
2420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Assign resource IDs to keys in bags...
2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (ti=0; ti<N; ti++) {
2425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Ordered config #%d: %p\n", ci, c.get());
2433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t N = c->getEntries().size();
2434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = c->getEntries().valueAt(ei);
2436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e == NULL) {
2437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    status_t err = e->assignResourceIds(this, p->getName());
2440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR && firstError == NO_ERROR) {
2441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        firstError = err;
2442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return firstError;
2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) {
2451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
2452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t pi;
2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p->getTypes().size() == 0) {
2457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Empty, skip!
2458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getOrderedTypes().size();
2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t ti;
2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (ti=0; ti<N; ti++) {
2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<AaptSymbols> typeSymbols;
2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            typeSymbols = outSymbols->addNestedSymbol(String8(t->getName()), t->getPos());
2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t rid = getResId(p, t, ci);
2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (rid == 0) {
2479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return UNKNOWN_ERROR;
2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (Res_GETPACKAGE(rid) == (size_t)(p->getAssignedId()-1)) {
2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    typeSymbols->addSymbol(String8(c->getName()), rid, c->getPos());
2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 comment(c->getComment());
2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    typeSymbols->appendComment(String8(c->getName()), comment, c->getPos());
2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    //printf("Type symbol %s comment: %s\n", String8(e->getName()).string(),
2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    //     String8(comment).string());
2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    comment = c->getTypeComment();
2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    typeSymbols->appendTypeComment(String8(c->getName()), comment);
2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
2492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    printf("**** NO MATCH: 0x%08x vs 0x%08x\n",
2493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           Res_GETPACKAGE(rid), p->getAssignedId());
2494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
2495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
2504282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResourceTable::addLocalization(const String16& name, const String8& locale)
2505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mLocalizations[name].insert(locale);
2507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*!
2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Flag various sorts of localization problems.  '+' indicates checks already implemented;
2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * '-' indicates checks that will be implemented in the future.
2513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
2514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A localized string for which no default-locale version exists => warning
2515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A string for which no version in an explicitly-requested locale exists => warning
2516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A localized translation of an translateable="false" string => warning
2517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * - A localized string not provided in every locale used by the table
2518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t
2520282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResourceTable::validateLocalizations(void)
2521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = NO_ERROR;
2523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String8 defaultLocale;
2524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // For all strings...
2526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (map<String16, set<String8> >::iterator nameIter = mLocalizations.begin();
2527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         nameIter != mLocalizations.end();
2528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         nameIter++) {
2529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const set<String8>& configSet = nameIter->second;   // naming convenience
2530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Look for strings with no default localization
2532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (configSet.count(defaultLocale) == 0) {
2533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stdout, "aapt: warning: string '%s' has no default translation in %s; found:",
2534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(nameIter->first).string(), mBundle->getResourceSourceDirs()[0]);
2535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (set<String8>::const_iterator locales = configSet.begin();
2536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 locales != configSet.end();
2537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 locales++) {
2538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stdout, " %s", (*locales).string());
2539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stdout, "\n");
2541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // !!! TODO: throw an error here in some circumstances
2542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Check that all requested localizations are present for this string
2545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mBundle->getConfigurations() != NULL && mBundle->getRequireLocalization()) {
2546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* allConfigs = mBundle->getConfigurations();
2547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* start = allConfigs;
2548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* comma;
2549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            do {
2551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 config;
2552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                comma = strchr(start, ',');
2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (comma != NULL) {
2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    config.setTo(start, comma - start);
2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    start = comma + 1;
2556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
2557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    config.setTo(start);
2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // don't bother with the pseudolocale "zz_ZZ"
2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (config != "zz_ZZ") {
2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (configSet.find(config) == configSet.end()) {
2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // okay, no specific localization found.  it's possible that we are
2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // requiring a specific regional localization [e.g. de_DE] but there is an
2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // available string in the generic language localization [e.g. de];
2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // consider that string to have fulfilled the localization requirement.
2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 region(config.string(), 2);
2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (configSet.find(region) == configSet.end()) {
2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (configSet.count(defaultLocale) == 0) {
2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                fprintf(stdout, "aapt: warning: "
2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        "**** string '%s' has no default or required localization "
2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        "for '%s' in %s\n",
2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        String8(nameIter->first).string(),
2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        config.string(),
2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        mBundle->getResourceSourceDirs()[0]);
2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski           } while (comma != NULL);
2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest)
2588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResourceFilter filter;
2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = filter.parse(bundle->getConfigurations());
2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
2593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ConfigDescription nullConfig;
2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t pi;
2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const static String16 mipmap16("mipmap");
2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool useUTF8 = !bundle->getUTF16StringsOption();
2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Iterate through all data, collecting all values (strings,
2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // references, etc).
2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    StringPool valueStrings(useUTF8);
2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<Entry> > allEntries;
2608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p->getTypes().size() == 0) {
2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Empty, skip!
2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        StringPool typeStrings(useUTF8);
2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        StringPool keyStrings(useUTF8);
2617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getOrderedTypes().size();
2619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t ti=0; ti<N; ti++) {
2620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                typeStrings.add(String16("<empty>"), false);
2623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16 typeName(t->getName());
2626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            typeStrings.add(typeName, false);
2627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // This is a hack to tweak the sorting order of the final strings,
2629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // to put stuff that is generally not language-specific first.
2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 configTypeName(typeName);
2631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (configTypeName == "drawable" || configTypeName == "layout"
2632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "color" || configTypeName == "anim"
2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "interpolator" || configTypeName == "animator"
2634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "xml" || configTypeName == "menu"
2635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "mipmap" || configTypeName == "raw") {
2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configTypeName = "1complex";
2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configTypeName = "2value";
2639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const bool filterable = (typeName != mipmap16);
2642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t N = c->getEntries().size();
2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ConfigDescription config = c->getEntries().keyAt(ei);
2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (filterable && !filter.match(config)) {
2653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = c->getEntries().valueAt(ei);
2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e == NULL) {
2657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    e->setNameIndex(keyStrings.add(e->getName(), true));
2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // If this entry has no values for other configs,
2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // and is the default config, then it is special.  Otherwise
2663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // we want to add it with the config info.
2664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ConfigDescription* valueConfig = NULL;
2665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (N != 1 || config == nullConfig) {
2666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        valueConfig = &config;
2667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    status_t err = e->prepareFlatten(&valueStrings, this,
2670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            &configTypeName, &config);
2671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR) {
2672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return err;
2673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    allEntries.add(e);
2675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p->setTypeStrings(typeStrings.createStringBlock());
2680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p->setKeyStrings(keyStrings.createStringBlock());
2681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getOutputAPKFile() != NULL) {
2684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Now we want to sort the value strings for better locality.  This will
2685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // cause the positions of the strings to change, so we need to go back
2686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // through out resource entries and update them accordingly.  Only need
2687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // to do this if actually writing the output file.
2688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        valueStrings.sortByConfig();
2689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (pi=0; pi<allEntries.size(); pi++) {
2690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            allEntries[pi]->remapStringValue(&valueStrings);
2691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t strAmt = 0;
2695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Now build the array of package chunks.
2697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<AaptFile> > flatPackages;
2698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p->getTypes().size() == 0) {
2701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Empty, skip!
2702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getTypeStrings().size();
2706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t baseSize = sizeof(ResTable_package);
2708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Start the package data.
2710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8());
2711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResTable_package* header = (ResTable_package*)data->editData(baseSize);
2712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (header == NULL) {
2713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_package\n");
2714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return NO_MEMORY;
2715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(header, 0, sizeof(*header));
2717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->header.type = htods(RES_TABLE_PACKAGE_TYPE);
2718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->header.headerSize = htods(sizeof(*header));
2719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->id = htodl(p->getAssignedId());
2720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strcpy16_htod(header->name, p->getName().string());
2721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Write the string blocks.
2723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t typeStringsStart = data->getSize();
2724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptFile> strFile = p->getTypeStringsData();
2725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ssize_t amt = data->writeData(strFile->getData(), strFile->getSize());
2726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #if PRINT_STRING_METRICS
2727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "**** type strings: %d\n", amt);
2728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #endif
2729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strAmt += amt;
2730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (amt < 0) {
2731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return amt;
2732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t keyStringsStart = data->getSize();
2734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strFile = p->getKeyStringsData();
2735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        amt = data->writeData(strFile->getData(), strFile->getSize());
2736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #if PRINT_STRING_METRICS
2737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "**** key strings: %d\n", amt);
2738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #endif
2739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strAmt += amt;
2740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (amt < 0) {
2741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return amt;
2742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Build the type chunks inside of this package.
2745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t ti=0; ti<N; ti++) {
2746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Retrieve them in the same order as the type string block.
2747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
2748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 typeName(p->getTypeStrings().stringAt(ti, &len));
2749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getTypes().valueFor(typeName);
2750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            LOG_ALWAYS_FATAL_IF(t == NULL && typeName != String16("<empty>"),
2751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "Type name %s not found",
2752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(typeName).string());
2753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const bool filterable = (typeName != mipmap16);
2755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t != NULL ? t->getOrderedConfigs().size() : 0;
2757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Until a non-NO_ENTRY value has been written for a resource,
2759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // that resource is invalid; validResources[i] represents
2760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // the item at t->getOrderedConfigs().itemAt(i).
2761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<bool> validResources;
2762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            validResources.insertAt(false, 0, N);
2763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // First write the typeSpec chunk, containing information about
2765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // each resource entry in this type.
2766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            {
2767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t typeSpecSize = sizeof(ResTable_typeSpec) + sizeof(uint32_t)*N;
2768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t typeSpecStart = data->getSize();
2769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ResTable_typeSpec* tsHeader = (ResTable_typeSpec*)
2770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData(typeSpecStart+typeSpecSize)) + typeSpecStart);
2771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (tsHeader == NULL) {
2772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(stderr, "ERROR: out of memory creating ResTable_typeSpec\n");
2773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NO_MEMORY;
2774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                memset(tsHeader, 0, sizeof(*tsHeader));
2776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->header.type = htods(RES_TABLE_TYPE_SPEC_TYPE);
2777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->header.headerSize = htods(sizeof(*tsHeader));
2778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->header.size = htodl(typeSpecSize);
2779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->id = ti+1;
2780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->entryCount = htodl(N);
2781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t* typeSpecFlags = (uint32_t*)
2783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData())
2784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        + typeSpecStart + sizeof(ResTable_typeSpec));
2785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                memset(typeSpecFlags, 0, sizeof(uint32_t)*N);
2786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei);
2789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (cl->getPublic()) {
2790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        typeSpecFlags[ei] |= htodl(ResTable_typeSpec::SPEC_PUBLIC);
2791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const size_t CN = cl->getEntries().size();
2793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    for (size_t ci=0; ci<CN; ci++) {
2794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (filterable && !filter.match(cl->getEntries().keyAt(ci))) {
2795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            continue;
2796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
2797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t cj=ci+1; cj<CN; cj++) {
2798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (filterable && !filter.match(cl->getEntries().keyAt(cj))) {
2799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                continue;
2800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
2801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            typeSpecFlags[ei] |= htodl(
2802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                cl->getEntries().keyAt(ci).diff(cl->getEntries().keyAt(cj)));
2803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
2804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // We need to write one type chunk for each configuration for
2809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // which we have entries in this type.
2810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NC = t->getUniqueConfigs().size();
2811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t typeSize = sizeof(ResTable_type) + sizeof(uint32_t)*N;
2813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<NC; ci++) {
2815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ConfigDescription config = t->getUniqueConfigs().itemAt(ci);
2816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                NOISY(printf("Writing config %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
2818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
2819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "sw%ddp w%ddp h%ddp dir:%d\n",
2820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      ti+1,
2821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.mcc, config.mnc,
2822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.language[0] ? config.language[0] : '-',
2823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.language[1] ? config.language[1] : '-',
2824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.country[0] ? config.country[0] : '-',
2825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.country[1] ? config.country[1] : '-',
2826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.orientation,
2827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.uiMode,
2828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.touchscreen,
2829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.density,
2830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.keyboard,
2831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.inputFlags,
2832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.navigation,
2833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenWidth,
2834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenHeight,
2835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.smallestScreenWidthDp,
2836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenWidthDp,
2837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenHeightDp,
2838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.layoutDirection));
2839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (filterable && !filter.match(config)) {
2841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t typeStart = data->getSize();
2845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ResTable_type* tHeader = (ResTable_type*)
2847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData(typeStart+typeSize)) + typeStart);
2848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (tHeader == NULL) {
2849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(stderr, "ERROR: out of memory creating ResTable_type\n");
2850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NO_MEMORY;
2851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                memset(tHeader, 0, sizeof(*tHeader));
2854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->header.type = htods(RES_TABLE_TYPE_TYPE);
2855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->header.headerSize = htods(sizeof(*tHeader));
2856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->id = ti+1;
2857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->entryCount = htodl(N);
2858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->entriesStart = htodl(typeSize);
2859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->config = config;
2860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                NOISY(printf("Writing type %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
2861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
2862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "sw%ddp w%ddp h%ddp dir:%d\n",
2863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      ti+1,
2864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.mcc, tHeader->config.mnc,
2865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.language[0] ? tHeader->config.language[0] : '-',
2866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.language[1] ? tHeader->config.language[1] : '-',
2867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.country[0] ? tHeader->config.country[0] : '-',
2868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.country[1] ? tHeader->config.country[1] : '-',
2869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.orientation,
2870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.uiMode,
2871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.touchscreen,
2872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.density,
2873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.keyboard,
2874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.inputFlags,
2875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.navigation,
2876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenWidth,
2877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenHeight,
2878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.smallestScreenWidthDp,
2879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenWidthDp,
2880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenHeightDp,
2881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.layoutDirection));
2882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->config.swapHtoD();
2883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Build the entries inside of this type.
2885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei);
2887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = cl->getEntries().valueFor(config);
2888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // Set the offset for this entry in its type.
2890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    uint32_t* index = (uint32_t*)
2891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        (((uint8_t*)data->editData())
2892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            + typeStart + sizeof(ResTable_type));
2893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e != NULL) {
2894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        index[ei] = htodl(data->getSize()-typeStart-typeSize);
2895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // Create the entry.
2897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ssize_t amt = e->flatten(bundle, data, cl->getPublic());
2898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (amt < 0) {
2899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return amt;
2900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
2901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        validResources.editItemAt(ei) = true;
2902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
2903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        index[ei] = htodl(ResTable_type::NO_ENTRY);
2904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Fill in the rest of the type information.
2908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader = (ResTable_type*)
2909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData()) + typeStart);
2910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->header.size = htodl(data->getSize()-typeStart);
2911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t i = 0; i < N; ++i) {
2914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!validResources[i]) {
2915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<ConfigList> c = t->getOrderedConfigs().itemAt(i);
2916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(stderr, "warning: no entries written for %s/%s\n",
2917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(typeName).string(), String8(c->getName()).string());
2918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Fill in the rest of the package information.
2923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header = (ResTable_package*)data->editData();
2924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->header.size = htodl(data->getSize());
2925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->typeStrings = htodl(typeStringsStart);
2926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->lastPublicType = htodl(p->getTypeStrings().size());
2927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->keyStrings = htodl(keyStringsStart);
2928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->lastPublicKey = htodl(p->getKeyStrings().size());
2929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        flatPackages.add(data);
2931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // And now write out the final chunks.
2934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t dataStart = dest->getSize();
2935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    {
2937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // blah
2938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResTable_header header;
2939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(&header, 0, sizeof(header));
2940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.header.type = htods(RES_TABLE_TYPE);
2941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.header.headerSize = htods(sizeof(header));
2942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.packageCount = htodl(flatPackages.size());
2943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = dest->writeData(&header, sizeof(header));
2944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
2945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_header\n");
2946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
2947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t strStart = dest->getSize();
2951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = valueStrings.writeStringBlock(dest);
2952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
2953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
2954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t amt = (dest->getSize()-strStart);
2957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    strAmt += amt;
2958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #if PRINT_STRING_METRICS
2959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stderr, "**** value strings: %d\n", amt);
2960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stderr, "**** total strings: %d\n", strAmt);
2961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #endif
2962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<flatPackages.size(); pi++) {
2964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = dest->writeData(flatPackages[pi]->getData(),
2965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                              flatPackages[pi]->getSize());
2966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
2967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating package chunk for ResTable_header\n");
2968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
2969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_header* header = (ResTable_header*)
2973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        (((uint8_t*)dest->getData()) + dataStart);
2974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    header->header.size = htodl(dest->getSize() - dataStart);
2975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(aout << "Resource table:"
2977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski          << HexDump(dest->getData(), dest->getSize()) << endl);
2978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #if PRINT_STRING_METRICS
2980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stderr, "**** total resource table size: %d / %d%% strings\n",
2981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest->getSize(), (strAmt*100)/dest->getSize());
2982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #endif
2983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::writePublicDefinitions(const String16& package, FILE* fp)
2988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(fp,
2990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "<!-- This file contains <public> resource definitions for all\n"
2991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "     resources that were generated from the source data. -->\n"
2992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "\n"
2993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "<resources>\n");
2994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    writePublicDefinitions(package, fp, true);
2996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    writePublicDefinitions(package, fp, false);
2997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(fp,
2999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "\n"
3000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "</resources>\n");
3001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::writePublicDefinitions(const String16& package, FILE* fp, bool pub)
3004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool didHeader = false;
3006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> pkg = mPackages.valueFor(package);
3008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (pkg != NULL) {
3009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t NT = pkg->getOrderedTypes().size();
3010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<NT; i++) {
3011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = pkg->getOrderedTypes().itemAt(i);
3012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
3013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
3014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool didType = false;
3017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NC = t->getOrderedConfigs().size();
3019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t j=0; j<NC; j++) {
3020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(j);
3021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
3022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
3023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c->getPublic() != pub) {
3026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
3027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!didType) {
3030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(fp, "\n");
3031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    didType = true;
3032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!didHeader) {
3034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (pub) {
3035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"  <!-- PUBLIC SECTION.  These resources have been declared public.\n");
3036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"       Changes to these definitions will break binary compatibility. -->\n\n");
3037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
3038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"  <!-- PRIVATE SECTION.  These resources have not been declared public.\n");
3039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"       You can make them public my moving these lines into a file in res/values. -->\n\n");
3040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    didHeader = true;
3042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!pub) {
3044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const size_t NE = c->getEntries().size();
3045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    for (size_t k=0; k<NE; k++) {
3046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const SourcePos& pos = c->getEntries().valueAt(k)->getPos();
3047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (pos.file != "") {
3048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(fp,"  <!-- Declared at %s:%d -->\n",
3049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    pos.file.string(), pos.line);
3050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
3051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(fp, "  <public type=\"%s\" name=\"%s\" id=\"0x%08x\" />\n",
3054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(t->getName()).string(),
3055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(c->getName()).string(),
3056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        getResId(pkg, t, c->getEntryIndex()));
3057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3062282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResourceTable::Item::Item(const SourcePos& _sourcePos,
3063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          bool _isId,
3064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          const String16& _value,
3065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          const Vector<StringPool::entry_style_span>* _style,
3066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          int32_t _format)
3067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    : sourcePos(_sourcePos)
3068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , isId(_isId)
3069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , value(_value)
3070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , format(_format)
3071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , bagKeyId(0)
3072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , evaluating(false)
3073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (_style) {
3075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        style = *_style;
3076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::makeItABag(const SourcePos& sourcePos)
3080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_BAG) {
3082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
3083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_UNKNOWN) {
3085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mType = TYPE_BAG;
3086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
3087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sourcePos.error("Resource entry %s is already defined as a single item.\n"
3089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "%s:%d: Originally defined here.\n",
3090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(),
3091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mItem.sourcePos.file.string(), mItem.sourcePos.line);
3092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return UNKNOWN_ERROR;
3093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::setItem(const SourcePos& sourcePos,
3096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       const String16& value,
3097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       const Vector<StringPool::entry_style_span>* style,
3098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       int32_t format,
3099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       const bool overwrite)
3100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Item item(sourcePos, false, value, style);
3102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_BAG) {
3104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Item& item(mBag.valueAt(0));
3105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sourcePos.error("Resource entry %s is already defined as a bag.\n"
3106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "%s:%d: Originally defined here.\n",
3107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(mName).string(),
3108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        item.sourcePos.file.string(), item.sourcePos.line);
3109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ( (mType != TYPE_UNKNOWN) && (overwrite == false) ) {
3112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sourcePos.error("Resource entry %s is already defined.\n"
3113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "%s:%d: Originally defined here.\n",
3114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(mName).string(),
3115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mItem.sourcePos.file.string(), mItem.sourcePos.line);
3116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mType = TYPE_ITEM;
3120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mItem = item;
3121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mItemFormat = format;
3122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::addToBag(const SourcePos& sourcePos,
3126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const String16& key, const String16& value,
3127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const Vector<StringPool::entry_style_span>* style,
3128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        bool replace, bool isId, int32_t format)
3129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = makeItABag(sourcePos);
3131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
3133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Item item(sourcePos, isId, value, style, format);
3136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // XXX NOTE: there is an error if you try to have a bag with two keys,
3138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // one an attr and one an id, with the same name.  Not something we
3139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // currently ever have to worry about.
3140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t origKey = mBag.indexOfKey(key);
3141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (origKey >= 0) {
3142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!replace) {
3143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const Item& item(mBag.valueAt(origKey));
3144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Resource entry %s already has bag item %s.\n"
3145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "%s:%d: Originally defined here.\n",
3146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(key).string(),
3147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    item.sourcePos.file.string(), item.sourcePos.line);
3148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("Replacing %s with %s\n",
3151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //       String8(mBag.valueFor(key).value).string(), String8(value).string());
3152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mBag.replaceValueFor(key, item);
3153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mBag.add(key, item);
3156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::emptyBag(const SourcePos& sourcePos)
3160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = makeItABag(sourcePos);
3162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
3164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mBag.clear();
3167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::generateAttributes(ResourceTable* table,
3171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                  const String16& package)
3172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 attr16("attr");
3174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 id16("id");
3175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mBag.size();
3176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
3177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& key = mBag.keyAt(i);
3178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Item& it = mBag.valueAt(i);
3179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.isId) {
3180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!table->hasBagOrEntry(key, &id16, &package)) {
3181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 value("false");
3182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                status_t err = table->addEntry(SourcePos(String8("<generated>"), 0), package,
3183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               id16, key, value);
3184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err != NO_ERROR) {
3185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return err;
3186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (!table->hasBagOrEntry(key, &attr16, &package)) {
3189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 1
3191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             fprintf(stderr, "ERROR: Bag attribute '%s' has not been defined.\n",
3192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//                     String8(key).string());
3193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             const Item& item(mBag.valueAt(i));
3194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             fprintf(stderr, "Referenced from file %s line %d\n",
3195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//                     item.sourcePos.file.string(), item.sourcePos.line);
3196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             return UNKNOWN_ERROR;
3197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#else
3198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char numberStr[16];
3199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sprintf(numberStr, "%d", ResTable_map::TYPE_ANY);
3200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            status_t err = table->addBag(SourcePos("<generated>", 0), package,
3201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                         attr16, key, String16(""),
3202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                         String16("^type"),
3203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                         String16(numberStr), NULL, NULL);
3204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
3205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return err;
3206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
3208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::assignResourceIds(ResourceTable* table,
3214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const String16& package)
3215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors = false;
3217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_BAG) {
3219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* errorMsg;
3220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16 style16("style");
3221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16 attr16("attr");
3222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16 id16("id");
3223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mParentId = 0;
3224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mParent.size() > 0) {
3225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mParentId = table->getResId(mParent, &style16, NULL, &errorMsg);
3226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (mParentId == 0) {
3227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mPos.error("Error retrieving parent for item: %s '%s'.\n",
3228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        errorMsg, String8(mParent).string());
3229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasErrors = true;
3230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = mBag.size();
3233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16& key = mBag.keyAt(i);
3235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Item& it = mBag.editValueAt(i);
3236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            it.bagKeyId = table->getResId(key,
3237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    it.isId ? &id16 : &attr16, NULL, &errorMsg);
3238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //printf("Bag key of %s: #%08x\n", String8(key).string(), it.bagKeyId);
3239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (it.bagKeyId == 0) {
3240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                it.sourcePos.error("Error: %s: %s '%s'.\n", errorMsg,
3241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(it.isId ? id16 : attr16).string(),
3242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(key).string());
3243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasErrors = true;
3244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
3248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::prepareFlatten(StringPool* strings, ResourceTable* table,
3251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8* configTypeName, const ConfigDescription* config)
3252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_ITEM) {
3254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Item& it = mItem;
3255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AccessorCookie ac(it.sourcePos, String8(mName), String8(it.value));
3256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!table->stringToValue(&it.parsedValue, strings,
3257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  it.value, false, true, 0,
3258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  &it.style, NULL, &ac, mItemFormat,
3259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  configTypeName, config)) {
3260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (mType == TYPE_BAG) {
3263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = mBag.size();
3264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16& key = mBag.keyAt(i);
3266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Item& it = mBag.editValueAt(i);
3267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AccessorCookie ac(it.sourcePos, String8(key), String8(it.value));
3268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!table->stringToValue(&it.parsedValue, strings,
3269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      it.value, false, true, it.bagKeyId,
3270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      &it.style, NULL, &ac, it.format,
3271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      configTypeName, config)) {
3272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
3273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPos.error("Error: entry %s is not a single item or a bag.\n",
3277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                   String8(mName).string());
3278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::remapStringValue(StringPool* strings)
3284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_ITEM) {
3286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Item& it = mItem;
3287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.parsedValue.dataType == Res_value::TYPE_STRING) {
3288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            it.parsedValue.data = strings->mapOriginalPosToNewPos(it.parsedValue.data);
3289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (mType == TYPE_BAG) {
3291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = mBag.size();
3292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Item& it = mBag.editValueAt(i);
3294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (it.parsedValue.dataType == Res_value::TYPE_STRING) {
3295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                it.parsedValue.data = strings->mapOriginalPosToNewPos(it.parsedValue.data);
3296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPos.error("Error: entry %s is not a single item or a bag.\n",
3300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                   String8(mName).string());
3301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t ResourceTable::Entry::flatten(Bundle* bundle, const sp<AaptFile>& data, bool isPublic)
3307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t amt = 0;
3309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_entry header;
3310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    memset(&header, 0, sizeof(header));
3311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    header.size = htods(sizeof(header));
3312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const type ty = this != NULL ? mType : TYPE_ITEM;
3313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (this != NULL) {
3314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (ty == TYPE_BAG) {
3315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            header.flags |= htods(header.FLAG_COMPLEX);
3316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (isPublic) {
3318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            header.flags |= htods(header.FLAG_PUBLIC);
3319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.key.index = htodl(mNameIndex);
3321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ty != TYPE_BAG) {
3323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = data->writeData(&header, sizeof(header));
3324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_entry\n");
3326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Item& it = mItem;
3330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Res_value par;
3331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(&par, 0, sizeof(par));
3332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.size = htods(it.parsedValue.size);
3333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.dataType = it.parsedValue.dataType;
3334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.res0 = it.parsedValue.res0;
3335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.data = htodl(it.parsedValue.data);
3336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #if 0
3337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Writing item (%s): type=%d, data=0x%x, res0=0x%x\n",
3338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               String8(mName).string(), it.parsedValue.dataType,
3339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               it.parsedValue.data, par.res0);
3340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #endif
3341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = data->writeData(&par, it.parsedValue.size);
3342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating Res_value\n");
3344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        amt += it.parsedValue.size;
3347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t N = mBag.size();
3349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t i;
3350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Create correct ordering of items.
3351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        KeyedVector<uint32_t, const Item*> items;
3352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (i=0; i<N; i++) {
3353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const Item& it = mBag.valueAt(i);
3354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            items.add(it.bagKeyId, &it);
3355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        N = items.size();
3357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResTable_map_entry mapHeader;
3359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memcpy(&mapHeader, &header, sizeof(header));
3360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapHeader.size = htods(sizeof(mapHeader));
3361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapHeader.parent.ident = htodl(mParentId);
3362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapHeader.count = htodl(N);
3363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = data->writeData(&mapHeader, sizeof(mapHeader));
3364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_entry\n");
3366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (i=0; i<N; i++) {
3370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const Item& it = *items.valueAt(i);
3371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResTable_map map;
3372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.name.ident = htodl(it.bagKeyId);
3373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.size = htods(it.parsedValue.size);
3374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.dataType = it.parsedValue.dataType;
3375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.res0 = it.parsedValue.res0;
3376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.data = htodl(it.parsedValue.data);
3377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = data->writeData(&map, sizeof(map));
3378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
3379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: out of memory creating Res_value\n");
3380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return err;
3381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            amt += sizeof(map);
3383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return amt;
3386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::ConfigList::appendComment(const String16& comment,
3389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                              bool onlyIfEmpty)
3390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
3392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
3393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (onlyIfEmpty && mComment.size() > 0) {
3395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
3396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mComment.size() > 0) {
3398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mComment.append(String16("\n"));
3399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mComment.append(comment);
3401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::ConfigList::appendTypeComment(const String16& comment)
3404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
3406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
3407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mTypeComment.size() > 0) {
3409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mTypeComment.append(String16("\n"));
3410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mTypeComment.append(comment);
3412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Type::addPublic(const SourcePos& sourcePos,
3415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const String16& name,
3416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const uint32_t ident)
3417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #if 0
3419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t entryIdx = Res_GETENTRY(ident);
3420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (entryIdx < 0) {
3421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sourcePos.error("Public resource %s/%s has an invalid 0 identifier (0x%08x).\n",
3422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8(mName).string(), String8(name).string(), ident);
3423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #endif
3426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t typeIdx = Res_GETTYPE(ident);
3428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (typeIdx >= 0) {
3429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        typeIdx++;
3430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mPublicIndex > 0 && mPublicIndex != typeIdx) {
3431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Public resource %s/%s has conflicting type codes for its"
3432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    " public identifiers (0x%x vs 0x%x).\n",
3433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(name).string(),
3434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mPublicIndex, typeIdx);
3435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPublicIndex = typeIdx;
3438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mFirstPublicSourcePos == NULL) {
3441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mFirstPublicSourcePos = new SourcePos(sourcePos);
3442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mPublic.indexOfKey(name) < 0) {
3445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPublic.add(name, Public(sourcePos, String16(), ident));
3446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Public& p = mPublic.editValueFor(name);
3448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p.ident != ident) {
3449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Public resource %s/%s has conflicting public identifiers"
3450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    " (0x%08x vs 0x%08x).\n"
3451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "%s:%d: Originally defined here.\n",
3452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(name).string(), p.ident, ident,
3453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    p.sourcePos.file.string(), p.sourcePos.line);
3454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::Type::canAddEntry(const String16& name)
3462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mCanAddEntries.add(name);
3464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Entry> ResourceTable::Type::getEntry(const String16& entry,
3467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       const SourcePos& sourcePos,
3468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       const ResTable_config* config,
3469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       bool doSetIndex,
3470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       bool overlay,
3471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       bool autoAddOverlay)
3472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int pos = -1;
3474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c = mConfigs.valueFor(entry);
3475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) {
3476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (overlay && !autoAddOverlay && mCanAddEntries.indexOf(entry) < 0) {
3477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Resource at %s appears in overlay but not"
3478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " in the base package; use <add-resource> to add.\n",
3479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(entry).string());
3480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return NULL;
3481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        c = new ConfigList(entry, sourcePos);
3483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mConfigs.add(entry, c);
3484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        pos = (int)mOrderedConfigs.size();
3485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedConfigs.add(c);
3486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (doSetIndex) {
3487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c->setEntryIndex(pos);
3488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ConfigDescription cdesc;
3492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (config) cdesc = *config;
3493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = c->getEntries().valueFor(cdesc);
3495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
3496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (config != NULL) {
3497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            NOISY(printf("New entry at %s:%d: imsi:%d/%d lang:%c%c cnt:%c%c "
3498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "orien:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
3499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "sw%ddp w%ddp h%ddp dir:%d\n",
3500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      sourcePos.file.string(), sourcePos.line,
3501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->mcc, config->mnc,
3502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->language[0] ? config->language[0] : '-',
3503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->language[1] ? config->language[1] : '-',
3504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->country[0] ? config->country[0] : '-',
3505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->country[1] ? config->country[1] : '-',
3506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->orientation,
3507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->touchscreen,
3508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->density,
3509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->keyboard,
3510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->inputFlags,
3511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->navigation,
3512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenWidth,
3513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenHeight,
3514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->smallestScreenWidthDp,
3515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenWidthDp,
3516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenHeightDp,
3517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->layoutDirection));
3518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
3519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            NOISY(printf("New entry at %s:%d: NULL config\n",
3520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      sourcePos.file.string(), sourcePos.line));
3521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        e = new Entry(entry, sourcePos);
3523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        c->addEntry(cdesc, e);
3524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /*
3525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (doSetIndex) {
3526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (pos < 0) {
3527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (pos=0; pos<(int)mOrderedConfigs.size(); pos++) {
3528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (mOrderedConfigs[pos] == c) {
3529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
3530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (pos >= (int)mOrderedConfigs.size()) {
3533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sourcePos.error("Internal error: config not found in mOrderedConfigs when adding entry");
3534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NULL;
3535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            e->setEntryIndex(pos);
3538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        */
3540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mUniqueConfigs.add(cdesc);
3543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return e;
3545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Type::applyPublicEntryOrder()
3548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = mOrderedConfigs.size();
3550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<ConfigList> > origOrder(mOrderedConfigs);
3551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasError = false;
3552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
3554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedConfigs.replaceAt(NULL, i);
3556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t NP = mPublic.size();
3559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("Ordering %d configs from %d public defs\n", N, NP);
3560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t j;
3561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (j=0; j<NP; j++) {
3562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& name = mPublic.keyAt(j);
3563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Public& p = mPublic.valueAt(j);
3564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int32_t idx = Res_GETENTRY(p.ident);
3565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("Looking for entry \"%s\"/\"%s\" (0x%08x) in %d...\n",
3566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //       String8(mName).string(), String8(name).string(), p.ident, N);
3567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool found = false;
3568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (i=0; i<N; i++) {
3569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> e = origOrder.itemAt(i);
3570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //printf("#%d: \"%s\"\n", i, String8(e->getName()).string());
3571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (e->getName() == name) {
3572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (idx >= (int32_t)mOrderedConfigs.size()) {
3573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    p.sourcePos.error("Public entry identifier 0x%x entry index "
3574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "is larger than available symbols (index %d, total symbols %d).\n",
3575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            p.ident, idx, mOrderedConfigs.size());
3576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasError = true;
3577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (mOrderedConfigs.itemAt(idx) == NULL) {
3578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    e->setPublic(true);
3579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    e->setPublicSourcePos(p.sourcePos);
3580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mOrderedConfigs.replaceAt(e, idx);
3581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    origOrder.removeAt(i);
3582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    N--;
3583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    found = true;
3584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    break;
3585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
3586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<ConfigList> oe = mOrderedConfigs.itemAt(idx);
3587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    p.sourcePos.error("Multiple entry names declared for public entry"
3589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " identifier 0x%x in type %s (%s vs %s).\n"
3590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "%s:%d: Originally defined here.",
3591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            idx+1, String8(mName).string(),
3592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(oe->getName()).string(),
3593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(name).string(),
3594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            oe->getPublicSourcePos().file.string(),
3595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            oe->getPublicSourcePos().line);
3596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasError = true;
3597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!found) {
3602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p.sourcePos.error("Public symbol %s/%s declared here is not defined.",
3603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(name).string());
3604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasError = true;
3605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("Copying back in %d non-public configs, have %d\n", N, origOrder.size());
3609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (N != origOrder.size()) {
3611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Internal error: remaining private symbol count mismatch\n");
3612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        N = origOrder.size();
3613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    j = 0;
3616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<ConfigList> e = origOrder.itemAt(i);
3618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // There will always be enough room for the remaining entries.
3619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (mOrderedConfigs.itemAt(j) != NULL) {
3620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            j++;
3621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedConfigs.replaceAt(e, j);
3623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        j++;
3624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasError ? UNKNOWN_ERROR : NO_ERROR;
3627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3629282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResourceTable::Package::Package(const String16& name, ssize_t includedId)
3630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    : mName(name), mIncludedId(includedId),
3631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      mTypeStringsMapping(0xffffffff),
3632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      mKeyStringsMapping(0xffffffff)
3633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Type> ResourceTable::Package::getType(const String16& type,
3637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                        const SourcePos& sourcePos,
3638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                        bool doSetIndex)
3639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = mTypes.valueFor(type);
3641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) {
3642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t = new Type(type, sourcePos);
3643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mTypes.add(type, t);
3644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedTypes.add(t);
3645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (doSetIndex) {
3646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // For some reason the type's index is set to one plus the index
3647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // in the mOrderedTypes list, rather than just the index.
3648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            t->setIndex(mOrderedTypes.size());
3649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return t;
3652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setTypeStrings(const sp<AaptFile>& data)
3655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mTypeStringsData = data;
3657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = setStrings(data, &mTypeStrings, &mTypeStringsMapping);
3658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: Type string data is corrupt!\n");
3660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
3662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setKeyStrings(const sp<AaptFile>& data)
3665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mKeyStringsData = data;
3667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = setStrings(data, &mKeyStrings, &mKeyStringsMapping);
3668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: Key string data is corrupt!\n");
3670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
3672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setStrings(const sp<AaptFile>& data,
3675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            ResStringPool* strings,
3676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            DefaultKeyedVector<String16, uint32_t>* mappings)
3677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (data->getData() == NULL) {
3679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(aout << "Setting restable string pool: "
3683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski          << HexDump(data->getData(), data->getSize()) << endl);
3684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = strings->setTo(data->getData(), data->getSize());
3686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err == NO_ERROR) {
3687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = strings->size();
3688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
3690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mappings->add(String16(strings->stringAt(i, &len)), i);
3691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
3694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::applyPublicTypeOrder()
3697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = mOrderedTypes.size();
3699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<Type> > origOrder(mOrderedTypes);
3700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
3702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedTypes.replaceAt(NULL, i);
3704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = origOrder.itemAt(i);
3708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int32_t idx = t->getPublicIndex();
3709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (idx > 0) {
3710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            idx--;
3711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (idx >= (int32_t)mOrderedTypes.size()) {
3712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mOrderedTypes.add();
3713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (mOrderedTypes.itemAt(idx) != NULL) {
3715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<Type> ot = mOrderedTypes.itemAt(idx);
3716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                t->getFirstPublicSourcePos().error("Multiple type names declared for public type"
3717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        " identifier 0x%x (%s vs %s).\n"
3718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "%s:%d: Originally defined here.",
3719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        idx, String8(ot->getName()).string(),
3720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(t->getName()).string(),
3721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ot->getFirstPublicSourcePos().file.string(),
3722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ot->getFirstPublicSourcePos().line);
3723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
3724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mOrderedTypes.replaceAt(t, idx);
3726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            origOrder.removeAt(i);
3727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            i--;
3728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            N--;
3729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t j=0;
3733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = origOrder.itemAt(i);
3735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // There will always be enough room for the remaining types.
3736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (mOrderedTypes.itemAt(j) != NULL) {
3737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            j++;
3738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedTypes.replaceAt(t, j);
3740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Package> ResourceTable::getPackage(const String16& package)
3746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
3748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) {
3749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mIsAppPackage) {
3750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (mHaveAppPackage) {
3751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "Adding multiple application package resources; only one is allowed.\n"
3752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "Use -x to create extended resources.\n");
3753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return NULL;
3754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mHaveAppPackage = true;
3756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p = new Package(package, 127);
3757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
3758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p = new Package(package, mNextPackageId);
3759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("*** NEW PACKAGE: \"%s\" id=%d\n",
3761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //       String8(package).string(), p->getAssignedId());
3762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPackages.add(package, p);
3763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedPackages.add(p);
3764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mNextPackageId++;
3765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return p;
3767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Type> ResourceTable::getType(const String16& package,
3770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               const String16& type,
3771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               const SourcePos& sourcePos,
3772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               bool doSetIndex)
3773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = getPackage(package);
3775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) {
3776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
3777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return p->getType(type, sourcePos, doSetIndex);
3779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Entry> ResourceTable::getEntry(const String16& package,
3782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const String16& type,
3783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const String16& name,
3784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const SourcePos& sourcePos,
3785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 bool overlay,
3786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const ResTable_config* config,
3787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 bool doSetIndex)
3788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = getType(package, type, sourcePos, doSetIndex);
3790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) {
3791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
3792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return t->getEntry(name, sourcePos, config, doSetIndex, overlay, mBundle->getAutoAddOverlay());
3794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<const ResourceTable::Entry> ResourceTable::getEntry(uint32_t resID,
3797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       const ResTable_config* config) const
3798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int pid = Res_GETPACKAGE(resID)+1;
3800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
3801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
3802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p;
3803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> check = mOrderedPackages[i];
3805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (check->getAssignedId() == pid) {
3806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p = check;
3807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            break;
3808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) {
3812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Package not found for resource #%08x\n", resID);
3813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
3814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int tid = Res_GETTYPE(resID);
3817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tid < 0 || tid >= (int)p->getOrderedTypes().size()) {
3818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Type not found for resource #%08x\n", resID);
3819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
3820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = p->getOrderedTypes()[tid];
3822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int eid = Res_GETENTRY(resID);
3824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (eid < 0 || eid >= (int)t->getOrderedConfigs().size()) {
3825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID);
3826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
3827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c = t->getOrderedConfigs()[eid];
3830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) {
3831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID);
3832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
3833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ConfigDescription cdesc;
3836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (config) cdesc = *config;
3837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = c->getEntries().valueFor(cdesc);
3838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) {
3839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Entry configuration not found for resource #%08x\n", resID);
3840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
3841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return e;
3844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst ResourceTable::Item* ResourceTable::getItem(uint32_t resID, uint32_t attrID) const
3847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(resID);
3849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
3850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
3851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = e->getBag().size();
3854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
3855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Item& it = e->getBag().valueAt(i);
3856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.bagKeyId == 0) {
3857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "warning: ID not yet assigned to '%s' in bag '%s'\n",
3858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getName()).string(),
3859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getBag().keyAt(i)).string());
3860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.bagKeyId == attrID) {
3862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return &it;
3863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NULL;
3867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getItemValue(
3870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t resID, uint32_t attrID, Res_value* outValue)
3871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Item* item = getItem(resID, attrID);
3873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool res = false;
3875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (item != NULL) {
3876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (item->evaluating) {
3877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<const Entry> e = getEntry(resID);
3878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = e->getBag().size();
3879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t i;
3880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (i=0; i<N; i++) {
3881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (&e->getBag().valueAt(i) == item) {
3882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    break;
3883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "warning: Circular reference detected in key '%s' of bag '%s'\n",
3886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getName()).string(),
3887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getBag().keyAt(i)).string());
3888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
3889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        item->evaluating = true;
3891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        res = stringToValue(outValue, NULL, item->value, false, false, item->bagKeyId);
3892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(
3893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res) {
3894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("getItemValue of #%08x[#%08x] (%s): type=#%08x, data=#%08x\n",
3895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       resID, attrID, String8(getEntry(resID)->getName()).string(),
3896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       outValue->dataType, outValue->data);
3897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
3898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("getItemValue of #%08x[#%08x]: failed\n",
3899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       resID, attrID);
3900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        );
3902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        item->evaluating = false;
3903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return res;
3905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3906