ResourceTable.cpp revision 27f69f4e06961fdecd1078b2292d764a157e5e1c
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    }
28a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
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            if (!attr.hasErrors) {
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (enumOrFlagsComment.size() == 0) {
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append(mayOrMust(attr.type,
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS));
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append((attr.type&ResTable_map::TYPE_ENUM)
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       ? String16(" be one of the following constant values.")
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       : String16(" be one or more (separated by '|') of the following constant values."));
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append(String16("</p>\n<table>\n"
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<colgroup align=\"left\" />\n"
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<colgroup align=\"left\" />\n"
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<colgroup align=\"left\" />\n"
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                "<tr><th>Constant</th><th>Value</th><th>Description</th></tr>"));
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("\n<tr><td><code>"));
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(itemIdent);
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("</code></td><td>"));
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(value);
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("</td><td>"));
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (block.getComment(&len)) {
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    enumOrFlagsComment.append(String16(block.getComment(&len)));
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                enumOrFlagsComment.append(String16("</td></tr>"));
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = outTable->addBag(SourcePos(in->getPrintableSource(), block.getLineNumber()),
512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       myPackage,
513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       attr16, attr.ident, String16(""),
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       itemIdent, value, NULL, NULL, false, true);
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err != NO_ERROR) {
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    attr.hasErrors = true;
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (code == ResXMLTree::END_TAG) {
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), attr16.string()) == 0) {
521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                break;
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if ((attr.type&ResTable_map::TYPE_ENUM) != 0) {
524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (strcmp16(block.getElementName(&len), enum16.string()) != 0) {
525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("Found tag </%s> where </enum> is expected\n",
527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(block.getElementName(&len)).string());
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return UNKNOWN_ERROR;
529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (strcmp16(block.getElementName(&len), flag16.string()) != 0) {
532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber())
533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            .error("Found tag </%s> where </flag> is expected\n",
534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(block.getElementName(&len)).string());
535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return UNKNOWN_ERROR;
536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!attr.hasErrors && attr.added) {
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        appendTypeInfo(outTable, myPackage, attr16, attr.ident, attr.type, gFormatFlags);
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!attr.hasErrors && enumOrFlagsComment.size() > 0) {
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        enumOrFlagsComment.append(String16("\n</table>"));
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outTable->appendTypeComment(myPackage, attr16, attr.ident, enumOrFlagsComment);
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool localeIsDefined(const ResTable_config& config)
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return config.locale == 0;
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t parseAndAddBag(Bundle* bundle,
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& in,
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResXMLTree* block,
562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const ResTable_config& config,
563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& myPackage,
564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& curType,
565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& ident,
566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& parentIdent,
567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& itemIdent,
568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t curFormat,
569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool isFormatted,
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& product,
571a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        PseudolocalizationMethod pseudolocalize,
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const bool overwrite,
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* outTable)
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 item16("item");
577a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 str;
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<StringPool::entry_style_span> spans;
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = parseStyledString(bundle, in->getPrintableSource().string(),
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block, item16, &str, &spans, isFormatted,
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            pseudolocalize);
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Adding resource bag entry l=%c%c c=%c%c orien=%d d=%d "
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 " pid=%s, bag=%s, id=%s: %s\n",
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.language[0], config.language[1],
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.country[0], config.country[1],
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.orientation, config.density,
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(parentIdent).string(),
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(ident).string(),
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(itemIdent).string(),
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(str).string()));
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = outTable->addBag(SourcePos(in->getPrintableSource(), block->getLineNumber()),
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           myPackage, curType, ident, parentIdent, itemIdent, str,
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           &spans, &config, overwrite, false, curFormat);
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns true if needle is one of the elements in the comma-separated list
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * haystack, false otherwise.
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool isInProductList(const String16& needle, const String16& haystack) {
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t *needle2 = needle.string();
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t *haystack2 = haystack.string();
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t needlesize = needle.size();
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (*haystack2 != '\0') {
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (strncmp16(haystack2, needle2, needlesize) == 0) {
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (haystack2[needlesize] == '\0' || haystack2[needlesize] == ',') {
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return true;
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (*haystack2 != '\0' && *haystack2 != ',') {
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            haystack2++;
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (*haystack2 == ',') {
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            haystack2++;
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
6308ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski/*
6318ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski * A simple container that holds a resource type and name. It is ordered first by type then
6328ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski * by name.
6338ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski */
6348ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinskistruct type_ident_pair_t {
6358ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    String16 type;
6368ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    String16 ident;
6378ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
6388ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    type_ident_pair_t() { };
6398ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    type_ident_pair_t(const String16& t, const String16& i) : type(t), ident(i) { }
6408ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    type_ident_pair_t(const type_ident_pair_t& o) : type(o.type), ident(o.ident) { }
6418ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    inline bool operator < (const type_ident_pair_t& o) const {
6428ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        int cmp = compare_type(type, o.type);
6438ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        if (cmp < 0) {
6448ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            return true;
6458ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        } else if (cmp > 0) {
6468ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            return false;
6478ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        } else {
6488ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            return strictly_order_type(ident, o.ident);
6498ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        }
6508ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    }
6518ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski};
6528ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
6538ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t parseAndAddEntry(Bundle* bundle,
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const sp<AaptFile>& in,
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResXMLTree* block,
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const ResTable_config& config,
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& myPackage,
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& curType,
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& ident,
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& curTag,
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool curIsStyled,
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        int32_t curFormat,
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        bool isFormatted,
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const String16& product,
666a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        PseudolocalizationMethod pseudolocalize,
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const bool overwrite,
6688ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        KeyedVector<type_ident_pair_t, bool>* skippedResourceNames,
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResourceTable* outTable)
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err;
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 str;
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<StringPool::entry_style_span> spans;
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = parseStyledString(bundle, in->getPrintableSource().string(), block,
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            curTag, &str, curIsStyled ? &spans : NULL,
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            isFormatted, pseudolocalize);
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err < NO_ERROR) {
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * If a product type was specified on the command line
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * and also in the string, and the two are not the same,
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * return without adding the string.
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char *bundleProduct = bundle->getProduct();
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundleProduct == NULL) {
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bundleProduct = "";
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (product.size() != 0) {
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /*
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * If the command-line-specified product is empty, only "default"
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * matches.  Other variants are skipped.  This is so generation
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         * of the R.java file when the product is not known is predictable.
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         */
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bundleProduct[0] == '\0') {
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(String16("default").string(), product.string()) != 0) {
7038ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                /*
7048ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                 * This string has a product other than 'default'. Do not add it,
7058ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                 * but record it so that if we do not see the same string with
7068ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                 * product 'default' or no product, then report an error.
7078ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                 */
7088ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                skippedResourceNames->replaceValueFor(
7098ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        type_ident_pair_t(curType, ident), true);
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return NO_ERROR;
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            /*
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * The command-line product is not empty.
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * If the product for this string is on the command-line list,
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * it matches.  "default" also matches, but only if nothing
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             * else has matched already.
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski             */
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (isInProductList(product, String16(bundleProduct))) {
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ;
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(String16("default").string(), product.string()) == 0 &&
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       !outTable->hasBagOrEntry(myPackage, curType, ident, config)) {
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ;
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return NO_ERROR;
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Adding resource entry l=%c%c c=%c%c orien=%d d=%d id=%s: %s\n",
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.language[0], config.language[1],
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.country[0], config.country[1],
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 config.orientation, config.density,
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(ident).string(), String8(str).string()));
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    err = outTable->addEntry(SourcePos(in->getPrintableSource(), block->getLineNumber()),
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             myPackage, curType, ident, str, &spans, &config,
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             false, curFormat, overwrite);
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t compileResourceFile(Bundle* bundle,
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const sp<AaptAssets>& assets,
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const sp<AaptFile>& in,
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const ResTable_config& defParams,
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             const bool overwrite,
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             ResourceTable* outTable)
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree block;
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = parseXMLResource(in, &block, false, true);
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Top-level tag.
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 resources16("resources");
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Identifier declaration tags.
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 declare_styleable16("declare-styleable");
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 attr16("attr");
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Data creation organizational tags.
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 string16("string");
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 drawable16("drawable");
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 color16("color");
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 bool16("bool");
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 integer16("integer");
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 dimen16("dimen");
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 fraction16("fraction");
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 style16("style");
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 plurals16("plurals");
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 array16("array");
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 string_array16("string-array");
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 integer_array16("integer-array");
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 public16("public");
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 public_padding16("public-padding");
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 private_symbols16("private-symbols");
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 java_symbol16("java-symbol");
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 add_resource16("add-resource");
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 skip16("skip");
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 eat_comment16("eat-comment");
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Data creation tags.
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 bag16("bag");
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 item16("item");
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Attribute type constants.
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 enum16("enum");
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // plural values
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 other16("other");
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityOther16("^other");
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 zero16("zero");
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityZero16("^zero");
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 one16("one");
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityOne16("^one");
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 two16("two");
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityTwo16("^two");
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 few16("few");
802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityFew16("^few");
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 many16("many");
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 quantityMany16("^many");
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // useful attribute names and special values
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 name16("name");
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 translatable16("translatable");
809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 formatted16("formatted");
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 false16("false");
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 myPackage(assets->getPackage());
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors = false;
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool fileIsTranslatable = true;
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strstr(in->getPrintableSource().string(), "donottranslate") != NULL) {
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fileIsTranslatable = false;
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DefaultKeyedVector<String16, uint32_t> nextPublicId(0);
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
8238ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // Stores the resource names that were skipped. Typically this happens when
8248ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // AAPT is invoked without a product specified and a resource has no
8258ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // 'default' product attribute.
8268ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    KeyedVector<type_ident_pair_t, bool> skippedResourceNames;
8278ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResXMLTree::event_code_t code;
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    do {
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        code = block.next();
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } while (code == ResXMLTree::START_NAMESPACE);
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t len;
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (code != ResXMLTree::START_TAG) {
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "No start tag found\n");
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (strcmp16(block.getElementName(&len), resources16.string()) != 0) {
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Invalid start tag %s\n", String8(block.getElementName(&len)).string());
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_config curParams(defParams);
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_config pseudoParams(curParams);
848a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoParams.language[0] = 'e';
849a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoParams.language[1] = 'n';
850a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoParams.country[0] = 'X';
851a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoParams.country[1] = 'A';
852a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
853a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    ResTable_config pseudoBidiParams(curParams);
854a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoBidiParams.language[0] = 'a';
855a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoBidiParams.language[1] = 'r';
856a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoBidiParams.country[0] = 'X';
857a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        pseudoBidiParams.country[1] = 'B';
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
85947843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    // We should skip resources for pseudolocales if they were
86047843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    // already added automatically. This is a fix for a transition period when
86147843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    // manually pseudolocalized resources may be expected.
86247843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    // TODO: remove this check after next SDK version release.
86347843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    if ((bundle->getPseudolocalize() & PSEUDO_ACCENTED &&
86447843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk         curParams.locale == pseudoParams.locale) ||
86547843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk        (bundle->getPseudolocalize() & PSEUDO_BIDI &&
86647843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk         curParams.locale == pseudoBidiParams.locale)) {
86747843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk        SourcePos(in->getPrintableSource(), 0).warning(
86847843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk                "Resource file %s is skipped as pseudolocalization"
86947843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk                " was done automatically.",
87047843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk                in->getPrintableSource().string());
87147843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk        return NO_ERROR;
87247843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk    }
87347843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (code == ResXMLTree::START_TAG) {
876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16* curTag = NULL;
877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 curType;
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int32_t curFormat = ResTable_map::TYPE_ANY;
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsBag = false;
880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsBagReplaceOnOverwrite = false;
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsStyled = false;
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsPseudolocalizable = false;
883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool curIsFormatted = fileIsTranslatable;
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool localHasErrors = false;
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        && code != ResXMLTree::BAD_DOCUMENT) {
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        && code != ResXMLTree::BAD_DOCUMENT) {
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), public16.string()) == 0) {
909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 type;
912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <public>\n");
915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type = String16(block.getAttributeStringValue(typeIdx, &len));
918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <public>\n");
923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t ident = 0;
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t identIdx = block.indexOfAttribute(NULL, "id");
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (identIdx >= 0) {
930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const char16_t* identStr = block.getAttributeStringValue(identIdx, &len);
931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value identValue;
932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!ResTable::stringToInt(identStr, len, &identValue)) {
933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Given 'id' attribute is not an integer: %s\n",
934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getAttributeStringValue(identIdx, &len)).string());
935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ident = identValue.data;
938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        nextPublicId.replaceValueFor(type, ident+1);
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (nextPublicId.indexOfKey(type) < 0) {
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("No 'id' attribute supplied <public>,"
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " and no previous id defined in this file.\n");
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (!localHasErrors) {
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ident = nextPublicId.valueFor(type);
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    nextPublicId.replaceValueFor(type, ident+1);
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addPublic(srcPos, myPackage, type, name, ident);
951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err < NO_ERROR) {
952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8(type), srcPos);
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->makeSymbolPublic(String8(name), srcPos);
962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 comment(
963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block.getComment(&len) ? block.getComment(&len) : nulStr);
964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->appendComment(String8(name), comment, srcPos);
965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Unable to create symbols!\n");
967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), public16.string()) == 0) {
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 type;
984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <public-padding>\n");
987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type = String16(block.getAttributeStringValue(typeIdx, &len));
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <public-padding>\n");
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t start = 0;
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t startIdx = block.indexOfAttribute(NULL, "start");
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (startIdx >= 0) {
1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const char16_t* startStr = block.getAttributeStringValue(startIdx, &len);
1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value startValue;
1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!ResTable::stringToInt(startStr, len, &startValue)) {
1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Given 'start' attribute is not an integer: %s\n",
1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getAttributeStringValue(startIdx, &len)).string());
1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        start = startValue.data;
1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (nextPublicId.indexOfKey(type) < 0) {
1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("No 'start' attribute supplied <public-padding>,"
1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " and no previous id defined in this file.\n");
1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (!localHasErrors) {
1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    start = nextPublicId.valueFor(type);
1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t end = 0;
1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t endIdx = block.indexOfAttribute(NULL, "end");
1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (endIdx >= 0) {
1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const char16_t* endStr = block.getAttributeStringValue(endIdx, &len);
1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value endValue;
1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!ResTable::stringToInt(endStr, len, &endValue)) {
1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Given 'end' attribute is not an integer: %s\n",
1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getAttributeStringValue(endIdx, &len)).string());
1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        end = endValue.data;
1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("No 'end' attribute supplied <public-padding>\n");
1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (end >= start) {
1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    nextPublicId.replaceValueFor(type, end+1);
1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("Padding start '%ul' is after end '%ul'\n",
1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            start, end);
1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 comment(
1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    block.getComment(&len) ? block.getComment(&len) : nulStr);
1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (uint32_t curIdent=start; curIdent<=end; curIdent++) {
1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (localHasErrors) {
1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 curName(name);
1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    char buf[64];
1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sprintf(buf, "%d", (int)(end-curIdent+1));
1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curName.append(String16(buf));
1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addEntry(srcPos, myPackage, type, curName,
1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                             String16("padding"), NULL, &curParams, false,
1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                             ResTable_map::TYPE_STRING, overwrite);
1058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err < NO_ERROR) {
1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->addPublic(srcPos, myPackage, type,
1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            curName, curIdent);
1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err < NO_ERROR) {
1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8(type), srcPos);
1071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->makeSymbolPublic(String8(curName), srcPos);
1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols->appendComment(String8(curName), comment, srcPos);
1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Unable to create symbols!\n");
1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) {
1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 pkg;
1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t pkgIdx = block.indexOfAttribute(NULL, "package");
1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (pkgIdx < 0) {
1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "A 'package' attribute is required for <private-symbols>\n");
1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                pkg = String16(block.getAttributeStringValue(pkgIdx, &len));
1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    assets->setSymbolsPrivatePackage(String8(pkg));
1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) {
1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), java_symbol16.string()) == 0) {
1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 type;
1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <public>\n");
1119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                type = String16(block.getAttributeStringValue(typeIdx, &len));
1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <public>\n");
1127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
1130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<AaptSymbols> symbols = assets->getJavaSymbolsFor(String8("R"));
1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (symbols != NULL) {
1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols = symbols->addNestedSymbol(String8(type), srcPos);
1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (symbols != NULL) {
1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols->makeSymbolJavaSymbol(String8(name), srcPos);
1137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 comment(
1138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        block.getComment(&len) ? block.getComment(&len) : nulStr);
1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols->appendComment(String8(name), comment, srcPos);
1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("Unable to create symbols!\n");
1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), java_symbol16.string()) == 0) {
1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) {
1156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 typeName;
1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (typeIdx < 0) {
1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'type' attribute is required for <add-resource>\n");
1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                typeName = String16(block.getAttributeStringValue(typeIdx, &len));
1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (nameIdx < 0) {
1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <add-resource>\n");
1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                name = String16(block.getAttributeStringValue(nameIdx, &len));
1173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outTable->canAddEntry(srcPos, myPackage, typeName, name);
1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::END_TAG) {
1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) {
1179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) {
1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 ident;
1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t identIdx = block.indexOfAttribute(NULL, "name");
1190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (identIdx < 0) {
1191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    srcPos.error("A 'name' attribute is required for <declare-styleable>\n");
1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ident = String16(block.getAttributeStringValue(identIdx, &len));
1195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8("styleable"), srcPos);
1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<AaptSymbols> styleSymbols = symbols;
1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols != NULL) {
1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        symbols = symbols->addNestedSymbol(String8(ident), srcPos);
1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (symbols == NULL) {
1206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        srcPos.error("Unable to create symbols!\n");
1207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return UNKNOWN_ERROR;
1208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 comment(
1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        block.getComment(&len) ? block.getComment(&len) : nulStr);
1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    styleSymbols->appendComment(String8(ident), comment, srcPos);
1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    symbols = NULL;
1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::START_TAG) {
1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            while ((code=block.next()) != ResXMLTree::END_DOCUMENT
1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                   && code != ResXMLTree::BAD_DOCUMENT) {
1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (code == ResXMLTree::END_TAG) {
1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        break;
1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    }
1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            continue;
1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            while ((code=block.next()) != ResXMLTree::END_DOCUMENT
1231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                   && code != ResXMLTree::BAD_DOCUMENT) {
1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (code == ResXMLTree::END_TAG) {
1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) {
1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        break;
1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    }
1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            continue;
1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (strcmp16(block.getElementName(&len), attr16.string()) != 0) {
1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Tag <%s> can not appear inside <declare-styleable>, only <attr>\n",
1242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(block.getElementName(&len)).string());
1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return UNKNOWN_ERROR;
1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 comment(
1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block.getComment(&len) ? block.getComment(&len) : nulStr);
1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 itemIdent;
1249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        err = compileAttribute(in, block, myPackage, outTable, &itemIdent, true);
1250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err != NO_ERROR) {
1251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (symbols != NULL) {
1255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos srcPos(String8(in->getPrintableSource()), block.getLineNumber());
1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            symbols->addSymbol(String8(itemIdent), 0, srcPos);
1257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            symbols->appendComment(String8(itemIdent), comment, srcPos);
1258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            //printf("Attribute %s comment: %s\n", String8(itemIdent).string(),
1259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            //     String8(comment).string());
1260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (code == ResXMLTree::END_TAG) {
1262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) {
1263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            break;
1264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "Found tag </%s> where </attr> is expected\n",
1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(block.getElementName(&len)).string());
1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return UNKNOWN_ERROR;
1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), attr16.string()) == 0) {
1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = compileAttribute(in, block, myPackage, outTable, NULL);
1276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err != NO_ERROR) {
1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = true;
1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), item16.string()) == 0) {
1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &item16;
1283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t attri = block.indexOfAttribute(NULL, "type");
1284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (attri >= 0) {
1285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curType = String16(block.getAttributeStringValue(attri, &len));
1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ssize_t formatIdx = block.indexOfAttribute(NULL, "format");
1287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (formatIdx >= 0) {
1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 formatStr = String16(block.getAttributeStringValue(
1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                formatIdx, &len));
1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        curFormat = parse_flags(formatStr.string(), formatStr.size(),
1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                gFormatFlags);
1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (curFormat == 0) {
1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Tag <item> 'format' attribute value \"%s\" not valid\n",
1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(formatStr).string());
1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "A 'type' attribute is required for <item>\n");
1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsStyled = true;
1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), string16.string()) == 0) {
1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Note the existence and locale of every string we process
130791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath                char rawLocale[RESTABLE_MAX_LOCALE_LEN];
130891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath                curParams.getBcp47Locale(rawLocale);
1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 locale(rawLocale);
1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 name;
1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 translatable;
1312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 formatted;
1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                size_t n = block.getAttributeCount();
1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t i = 0; i < n; i++) {
1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    size_t length;
1317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const uint16_t* attr = block.getAttributeName(i, &length);
1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (strcmp16(attr, name16.string()) == 0) {
1319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        name.setTo(block.getAttributeStringValue(i, &length));
1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (strcmp16(attr, translatable16.string()) == 0) {
1321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        translatable.setTo(block.getAttributeStringValue(i, &length));
1322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (strcmp16(attr, formatted16.string()) == 0) {
1323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        formatted.setTo(block.getAttributeStringValue(i, &length));
1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (name.size() > 0) {
1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (translatable == false16) {
1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        curIsFormatted = false;
1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // Untranslatable strings must only exist in the default [empty] locale
1331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (locale.size() > 0) {
1332a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).warning(
1333a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                    "string '%s' marked untranslatable but exists in locale '%s'\n",
1334a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                    String8(name).string(),
1335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    locale.string());
1336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // hasErrors = localHasErrors = true;
1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // Intentionally empty block:
1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            //
1340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // Don't add untranslatable strings to the localization table; that
1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // way if we later see localizations of them, they'll be flagged as
1342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            // having no default translation.
1343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
1345a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        outTable->addLocalization(
1346a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                name,
1347a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                locale,
1348a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                SourcePos(in->getPrintableSource(), block.getLineNumber()));
1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (formatted == false16) {
1352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        curIsFormatted = false;
1353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &string16;
1357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = string16;
1358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
1359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsStyled = true;
136084410b054c7db0b6685a0f15cb2d1ffcb264f6c9Igor Viarheichyk                curIsPseudolocalizable = fileIsTranslatable && (translatable != false16);
1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), drawable16.string()) == 0) {
1362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &drawable16;
1363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = drawable16;
1364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_COLOR;
1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), color16.string()) == 0) {
1366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &color16;
1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = color16;
1368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_COLOR;
1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), bool16.string()) == 0) {
1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &bool16;
1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = bool16;
1372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_BOOLEAN;
1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), integer16.string()) == 0) {
1374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &integer16;
1375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = integer16;
1376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_INTEGER;
1377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), dimen16.string()) == 0) {
1378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &dimen16;
1379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = dimen16;
1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_DIMENSION;
1381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), fraction16.string()) == 0) {
1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &fraction16;
1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = fraction16;
1384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_FRACTION;
1385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), bag16.string()) == 0) {
1386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &bag16;
1387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t attri = block.indexOfAttribute(NULL, "type");
1389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (attri >= 0) {
1390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curType = String16(block.getAttributeStringValue(attri, &len));
1391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "A 'type' attribute is required for <bag>\n");
1394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), style16.string()) == 0) {
1397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &style16;
1398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = style16;
1399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), plurals16.string()) == 0) {
1401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &plurals16;
1402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = plurals16;
1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1404a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                curIsPseudolocalizable = fileIsTranslatable;
1405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), array16.string()) == 0) {
1406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &array16;
1407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = array16;
1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBagReplaceOnOverwrite = true;
1410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t formatIdx = block.indexOfAttribute(NULL, "format");
1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (formatIdx >= 0) {
1412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 formatStr = String16(block.getAttributeStringValue(
1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            formatIdx, &len));
1414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    curFormat = parse_flags(formatStr.string(), formatStr.size(),
1415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            gFormatFlags);
1416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (curFormat == 0) {
1417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "Tag <array> 'format' attribute value \"%s\" not valid\n",
1419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(formatStr).string());
1420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), string_array16.string()) == 0) {
1424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Check whether these strings need valid formats.
1425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // (simplified form of what string16 does above)
1426a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                bool isTranslatable = false;
1427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                size_t n = block.getAttributeCount();
14289a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath
14299a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                // Pseudolocalizable by default, unless this string array isn't
14309a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                // translatable.
1431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t i = 0; i < n; i++) {
1432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    size_t length;
1433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const uint16_t* attr = block.getAttributeName(i, &length);
1434a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    if (strcmp16(attr, formatted16.string()) == 0) {
14359a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                        const uint16_t* value = block.getAttributeStringValue(i, &length);
14369a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                        if (strcmp16(value, false16.string()) == 0) {
1437a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            curIsFormatted = false;
14389a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath                        }
1439a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    } else if (strcmp16(attr, translatable16.string()) == 0) {
1440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const uint16_t* value = block.getAttributeStringValue(i, &length);
1441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(value, false16.string()) == 0) {
1442a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            isTranslatable = false;
1443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &string_array16;
1448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = array16;
1449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
1450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBagReplaceOnOverwrite = true;
1452a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                curIsPseudolocalizable = isTranslatable && fileIsTranslatable;
1453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else if (strcmp16(block.getElementName(&len), integer_array16.string()) == 0) {
1454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curTag = &integer_array16;
1455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curType = array16;
1456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_INTEGER;
1457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBag = true;
1458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                curIsBagReplaceOnOverwrite = true;
1459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "Found tag %s where item is expected\n",
1462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(block.getElementName(&len)).string());
1463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
1464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 ident;
1467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ssize_t identIdx = block.indexOfAttribute(NULL, "name");
1468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (identIdx >= 0) {
1469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ident = String16(block.getAttributeStringValue(identIdx, &len));
1470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "A 'name' attribute is required for <%s>\n",
1473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(*curTag).string());
1474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasErrors = localHasErrors = true;
1475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 product;
1478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            identIdx = block.indexOfAttribute(NULL, "product");
1479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (identIdx >= 0) {
1480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                product = String16(block.getAttributeStringValue(identIdx, &len));
1481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 comment(block.getComment(&len) ? block.getComment(&len) : nulStr);
1484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (curIsBag) {
1486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Figure out the parent of this bag...
1487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 parentIdent;
1488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t parentIdentIdx = block.indexOfAttribute(NULL, "parent");
1489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (parentIdentIdx >= 0) {
1490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    parentIdent = String16(block.getAttributeStringValue(parentIdentIdx, &len));
1491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
1492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ssize_t sep = ident.findLast('.');
1493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (sep >= 0) {
1494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        parentIdent.setTo(ident, sep);
1495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!localHasErrors) {
1499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    err = outTable->startBag(SourcePos(in->getPrintableSource(),
1500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            block.getLineNumber()), myPackage, curType, ident,
1501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            parentIdent, &curParams,
1502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            overwrite, curIsBagReplaceOnOverwrite);
1503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR) {
1504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        hasErrors = localHasErrors = true;
1505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ssize_t elmIndex = 0;
1509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                char elmIndexStr[14];
1510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                while ((code=block.next()) != ResXMLTree::END_DOCUMENT
1511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        && code != ResXMLTree::BAD_DOCUMENT) {
1512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (code == ResXMLTree::START_TAG) {
1514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), item16.string()) != 0) {
1515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Tag <%s> can not appear inside <%s>, only <item>\n",
1517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(block.getElementName(&len)).string(),
1518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(*curTag).string());
1519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return UNKNOWN_ERROR;
1520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String16 itemIdent;
1523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (curType == array16) {
1524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            sprintf(elmIndexStr, "^index_%d", (int)elmIndex++);
1525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            itemIdent = String16(elmIndexStr);
1526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else if (curType == plurals16) {
1527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "quantity");
1528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (itemIdentIdx >= 0) {
1529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String16 quantity16(block.getAttributeStringValue(itemIdentIdx, &len));
1530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                if (quantity16 == other16) {
1531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityOther16;
1532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == zero16) {
1534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityZero16;
1535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == one16) {
1537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityOne16;
1538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == two16) {
1540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityTwo16;
1541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == few16) {
1543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityFew16;
1544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else if (quantity16 == many16) {
1546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    itemIdent = quantityMany16;
1547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                else {
1549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            "Illegal 'quantity' attribute is <item> inside <plurals>\n");
1551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    hasErrors = localHasErrors = true;
1552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                }
1553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else {
1554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        "A 'quantity' attribute is required for <item> inside <plurals>\n");
1556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasErrors = localHasErrors = true;
1557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        } else {
1559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "name");
1560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (itemIdentIdx >= 0) {
1561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                itemIdent = String16(block.getAttributeStringValue(itemIdentIdx, &len));
1562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            } else {
1563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        "A 'name' attribute is required for <item>\n");
1565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                hasErrors = localHasErrors = true;
1566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ResXMLParser::ResXMLPosition parserPosition;
1570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        block.getPosition(&parserPosition);
1571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType,
1573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                ident, parentIdent, itemIdent, curFormat, curIsFormatted,
1574a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                product, NO_PSEUDOLOCALIZATION, overwrite, outTable);
1575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err == NO_ERROR) {
1576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            if (curIsPseudolocalizable && localeIsDefined(curParams)
1577a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    && bundle->getPseudolocalize() > 0) {
1578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                // pseudolocalize here
1579a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) ==
1580a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                   PSEUDO_ACCENTED) {
1581a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    block.setPosition(parserPosition);
1582a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage,
1583a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            curType, ident, parentIdent, itemIdent, curFormat,
1584a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            curIsFormatted, product, PSEUDO_ACCENTED,
1585a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            overwrite, outTable);
1586a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                }
1587a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                if ((PSEUDO_BIDI & bundle->getPseudolocalize()) ==
1588a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                   PSEUDO_BIDI) {
1589a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    block.setPosition(parserPosition);
1590a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    err = parseAndAddBag(bundle, in, &block, pseudoBidiParams, myPackage,
1591a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            curType, ident, parentIdent, itemIdent, curFormat,
1592a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            curIsFormatted, product, PSEUDO_BIDI,
1593a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                            overwrite, outTable);
1594a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                }
1595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
1596a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        }
1597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err != NO_ERROR) {
1598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else if (code == ResXMLTree::END_TAG) {
1601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (strcmp16(block.getElementName(&len), curTag->string()) != 0) {
1602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    "Found tag </%s> where </%s> is expected\n",
1604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(block.getElementName(&len)).string(),
1605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    String8(*curTag).string());
1606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return UNKNOWN_ERROR;
1607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
1609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
1612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ResXMLParser::ResXMLPosition parserPosition;
1613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                block.getPosition(&parserPosition);
1614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident,
1616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        *curTag, curIsStyled, curFormat, curIsFormatted,
1617a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        product, NO_PSEUDOLOCALIZATION, overwrite, &skippedResourceNames, outTable);
1618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR?
1620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasErrors = localHasErrors = true;
1621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                else if (err == NO_ERROR) {
1623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (curIsPseudolocalizable && localeIsDefined(curParams)
1624a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            && bundle->getPseudolocalize() > 0) {
1625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // pseudolocalize here
1626a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) ==
1627a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                           PSEUDO_ACCENTED) {
1628a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            block.setPosition(parserPosition);
1629a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
1630a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    ident, *curTag, curIsStyled, curFormat,
1631a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    curIsFormatted, product,
1632a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    PSEUDO_ACCENTED, overwrite, &skippedResourceNames, outTable);
1633a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        }
1634a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        if ((PSEUDO_BIDI & bundle->getPseudolocalize()) ==
1635a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                           PSEUDO_BIDI) {
1636a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            block.setPosition(parserPosition);
1637a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            err = parseAndAddEntry(bundle, in, &block, pseudoBidiParams,
1638a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    myPackage, curType, ident, *curTag, curIsStyled, curFormat,
1639a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    curIsFormatted, product,
1640a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                    PSEUDO_BIDI, overwrite, &skippedResourceNames, outTable);
1641a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        }
1642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (err != NO_ERROR) {
1643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            hasErrors = localHasErrors = true;
1644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
1645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
1646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (comment.size() > 0) {
1651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("Comment for @%s:%s/%s: %s\n", String8(myPackage).string(),
1652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       String8(curType).string(), String8(ident).string(),
1653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       String8(comment).string());
1654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!localHasErrors) {
1657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outTable->appendComment(myPackage, curType, ident, comment, false);
1658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        else if (code == ResXMLTree::END_TAG) {
1661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (strcmp16(block.getElementName(&len), resources16.string()) != 0) {
1662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "Unexpected end tag %s\n", String8(block.getElementName(&len)).string());
1664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
1665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        else if (code == ResXMLTree::START_NAMESPACE || code == ResXMLTree::END_NAMESPACE) {
1668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        else if (code == ResXMLTree::TEXT) {
1670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (isWhitespace(block.getText(&len))) {
1671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
1672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
1674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "Found text \"%s\" where item tag is expected\n",
1675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(block.getText(&len)).string());
1676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
16808ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // For every resource defined, there must be exist one variant with a product attribute
16818ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // set to 'default' (or no product attribute at all).
16828ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // We check to see that for every resource that was ignored because of a mismatched
16838ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    // product attribute, some product variant of that resource was processed.
16848ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    for (size_t i = 0; i < skippedResourceNames.size(); i++) {
16858ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        if (skippedResourceNames[i]) {
16868ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            const type_ident_pair_t& p = skippedResourceNames.keyAt(i);
16878ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            if (!outTable->hasBagOrEntry(myPackage, p.type, p.ident)) {
16888ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                const char* bundleProduct =
16898ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        (bundle->getProduct() == NULL) ? "" : bundle->getProduct();
16908ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                fprintf(stderr, "In resource file %s: %s\n",
16918ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        in->getPrintableSource().string(),
16928ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        curParams.toString().string());
16938ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
16948ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                fprintf(stderr, "\t%s '%s' does not match product %s.\n"
16958ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        "\tYou may have forgotten to include a 'default' product variant"
16968ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        " of the resource.\n",
16978ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        String8(p.type).string(), String8(p.ident).string(),
16988ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                        bundleProduct[0] == 0 ? "default" : bundleProduct);
16998ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                return UNKNOWN_ERROR;
17008ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski            }
17018ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski        }
17028ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski    }
17038ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski
1704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
1705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1707833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam LesinskiResourceTable::ResourceTable(Bundle* bundle, const String16& assetsPackage, ResourceTable::PackageType type)
1708833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    : mAssetsPackage(assetsPackage)
1709833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    , mPackageType(type)
1710833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    , mTypeIdOffset(0)
1711833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    , mNumLocal(0)
1712833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    , mBundle(bundle)
1713833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski{
1714833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    ssize_t packageId = -1;
1715833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    switch (mPackageType) {
1716833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        case App:
1717833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        case AppFeature:
1718833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            packageId = 0x7f;
1719833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            break;
1720833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1721833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        case System:
1722833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            packageId = 0x01;
1723833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            break;
1724833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1725833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        case SharedLibrary:
1726833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            packageId = 0x00;
1727833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            break;
1728833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1729833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        default:
1730833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            assert(0);
1731833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            break;
1732833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    }
1733833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    sp<Package> package = new Package(mAssetsPackage, packageId);
1734833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    mPackages.add(assetsPackage, package);
1735833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    mOrderedPackages.add(package);
1736833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1737833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    // Every resource table always has one first entry, the bag attributes.
1738833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const SourcePos unknown(String8("????"), 0);
1739833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    getType(mAssetsPackage, String16("attr"), unknown);
1740833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski}
1741833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1742833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinskistatic uint32_t findLargestTypeIdForPackage(const ResTable& table, const String16& packageName) {
1743833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const size_t basePackageCount = table.getBasePackageCount();
1744833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    for (size_t i = 0; i < basePackageCount; i++) {
1745833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (packageName == table.getBasePackageName(i)) {
1746833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            return table.getLastTypeIdForPackage(i);
1747833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
1748833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    }
1749833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    return 0;
1750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets)
1753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = assets->buildIncludedResources(bundle);
1755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
1756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
1757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mAssets = assets;
1760833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    mTypeIdOffset = findLargestTypeIdForPackage(assets->getIncludedResources(), mAssetsPackage);
1761833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1762833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    const String8& featureAfter = bundle->getFeatureAfterPackage();
1763833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    if (!featureAfter.isEmpty()) {
1764833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        AssetManager featureAssetManager;
1765833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (!featureAssetManager.addAssetPath(featureAfter, NULL)) {
1766833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            fprintf(stderr, "ERROR: Feature package '%s' not found.\n",
1767833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    featureAfter.string());
1768833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            return UNKNOWN_ERROR;
1769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1771833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        const ResTable& featureTable = featureAssetManager.getResources(false);
1772833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        mTypeIdOffset = max(mTypeIdOffset,
1773833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                findLargestTypeIdForPackage(featureTable, mAssetsPackage));
1774833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    }
1775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
1777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addPublic(const SourcePos& sourcePos,
1780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& package,
1781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
1782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name,
1783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const uint32_t ident)
1784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sourcePos.error("Error declaring public resource %s/%s for included package %s\n",
1791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8(type).string(), String8(name).string(),
1792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8(package).string());
1793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = getType(package, type, sourcePos);
1797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) {
1798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return t->addPublic(sourcePos, name, ident);
1801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addEntry(const SourcePos& sourcePos,
1804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& package,
1805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& type,
1806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& name,
1807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& value,
1808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const Vector<StringPool::entry_style_span>* style,
1809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const ResTable_config* params,
1810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const bool doSetIndex,
1811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const int32_t format,
1812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const bool overwrite)
1813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1819833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        sourcePos.error("Resource entry %s/%s is already defined in package %s.",
1820833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                String8(type).string(), String8(name).string(), String8(package).string());
1821833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return UNKNOWN_ERROR;
1822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = getEntry(package, type, name, sourcePos, overwrite,
1825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           params, doSetIndex);
1826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
1827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = e->setItem(sourcePos, value, style, format, overwrite);
1830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err == NO_ERROR) {
1831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mNumLocal++;
1832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
1834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::startBag(const SourcePos& sourcePos,
1837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& package,
1838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& type,
1839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& name,
1840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& bagParent,
1841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const ResTable_config* params,
1842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool overlay,
1843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool replace, bool isId)
1844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t result = NO_ERROR;
1846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Check for adding entries in other packages...  for now we do
1848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // nothing.  We need to do the right thing here to support skinning.
1849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    .identifierForName(name.string(), name.size(),
1851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       type.string(), type.size(),
1852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       package.string(), package.size());
1853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1854833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        sourcePos.error("Resource entry %s/%s is already defined in package %s.",
1855833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                String8(type).string(), String8(name).string(), String8(package).string());
1856833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return UNKNOWN_ERROR;
1857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1858833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
1859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (overlay && !mBundle->getAutoAddOverlay() && !hasBagOrEntry(package, type, name)) {
1860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool canAdd = false;
1861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mPackages.valueFor(package);
1862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p != NULL) {
1863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getTypes().valueFor(type);
1864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t != NULL) {
1865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (t->getCanAddEntries().indexOf(name) >= 0) {
1866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    canAdd = true;
1867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!canAdd) {
1871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Resource does not already exist in overlay at '%s'; use <add-resource> to add.\n",
1872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(name).string());
1873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
1874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = getEntry(package, type, name, sourcePos, overlay, params);
1877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
1878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If a parent is explicitly specified, set it.
1882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bagParent.size() > 0) {
1883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        e->setParent(bagParent);
1884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ((result = e->makeItABag(sourcePos)) != NO_ERROR) {
1887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return result;
1888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (overlay && replace) {
1891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return e->emptyBag(sourcePos);
1892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return result;
1894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addBag(const SourcePos& sourcePos,
1897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& package,
1898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& type,
1899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& name,
1900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& bagParent,
1901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& bagKey,
1902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const String16& value,
1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const Vector<StringPool::entry_style_span>* style,
1904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               const ResTable_config* params,
1905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                               bool replace, bool isId, const int32_t format)
1906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Check for adding entries in other packages...  for now we do
1908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // nothing.  We need to do the right thing here to support skinning.
1909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
1915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0
1918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (name == String16("left")) {
1919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Adding bag left: file=%s, line=%d, type=%s\n",
1920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               sourcePos.file.striing(), sourcePos.line, String8(type).string());
1921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
1923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = getEntry(package, type, name, sourcePos, replace, params);
1924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
1925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
1926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If a parent is explicitly specified, set it.
1929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bagParent.size() > 0) {
1930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        e->setParent(bagParent);
1931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const bool first = e->getBag().indexOfKey(bagKey) < 0;
1934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = e->addToBag(sourcePos, bagKey, value, style, replace, isId, format);
1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err == NO_ERROR && first) {
1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mNumLocal++;
1937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
1939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& package,
1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
1943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name) const
1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First look for this in the included resources...
1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) return true;
1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& package,
1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name,
1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const ResTable_config& config) const
1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First look for this in the included resources...
1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size());
1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
1982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
1983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
1984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
1985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) {
1986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<Entry> e = c->getEntries().valueFor(config);
1987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (e != NULL) {
1988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return true;
1989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
1990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
1991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
1992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
1993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
1995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& ref,
1998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16* defType,
1999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16* defPackage)
2000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 package, type, name;
2002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!ResTable::expandResourceRef(ref.string(), ref.size(), &package, &type, &name,
2003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                defType, defPackage ? defPackage:&mAssetsPackage, NULL)) {
2004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
2005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasBagOrEntry(package, type, name);
2007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::appendComment(const String16& package,
2010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& type,
2011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& name,
2012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& comment,
2013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  bool onlyIfEmpty)
2014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
2016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
2021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
2022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
2023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
2024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) {
2025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                c->appendComment(comment, onlyIfEmpty);
2026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return true;
2027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::appendTypeComment(const String16& package,
2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      const String16& type,
2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      const String16& name,
2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      const String16& comment)
2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p != NULL) {
2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = p->getTypes().valueFor(type);
2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != NULL) {
2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> c =  t->getConfigs().valueFor(name);
2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (c != NULL) {
2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                c->appendTypeComment(comment);
2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return true;
2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::canAddEntry(const SourcePos& pos,
2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& package, const String16& type, const String16& name)
2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = getType(package, type, pos);
2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t != NULL) {
2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t->canAddEntry(name);
2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisize_t ResourceTable::size() const {
2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mPackages.size();
2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisize_t ResourceTable::numLocalResources() const {
2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mNumLocal;
2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasResources() const {
2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mNumLocal > 0;
2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
207727f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinskisp<AaptFile> ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
207827f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski        const bool isBase)
2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8());
208127f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski    status_t err = flatten(bundle, filter, data, isBase);
2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err == NO_ERROR ? data : NULL;
2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiinline uint32_t ResourceTable::getResId(const sp<Package>& p,
2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const sp<Type>& t,
2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        uint32_t nameId)
2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return makeResId(p->getAssignedId(), t->getIndex(), nameId);
2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getResId(const String16& package,
2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& type,
2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16& name,
2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool onlyPublic) const
2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t id = ResourceIdCache::lookup(package, type, name, onlyPublic);
2098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (id != 0) return id;     // cache hit
2099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First look for this in the included resources...
2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t specFlags = 0;
2102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t rid = mAssets->getIncludedResources()
2103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        .identifierForName(name.string(), name.size(),
2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           type.string(), type.size(),
2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           package.string(), package.size(),
2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           &specFlags);
2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (rid != 0) {
2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (onlyPublic) {
2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if ((specFlags & ResTable_typeSpec::SPEC_PUBLIC) == 0) {
2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return 0;
2111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2114833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return ResourceIdCache::store(package, type, name, onlyPublic, rid);
2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2117833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2118833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    if (p == NULL) return 0;
2119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = p->getTypes().valueFor(type);
2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) return 0;
2121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c =  t->getConfigs().valueFor(name);
2122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) return 0;
2123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t ei = c->getEntryIndex();
2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ei < 0) return 0;
2125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return ResourceIdCache::store(package, type, name, onlyPublic,
2127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            getResId(p, t, ei));
2128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getResId(const String16& ref,
2131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16* defType,
2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const String16* defPackage,
2133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 const char** outErrorMsg,
2134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                 bool onlyPublic) const
2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 package, type, name;
2137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool refOnlyPublic = true;
2138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!ResTable::expandResourceRef(
2139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ref.string(), ref.size(), &package, &type, &name,
2140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        defType, defPackage ? defPackage:&mAssetsPackage,
2141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outErrorMsg, &refOnlyPublic)) {
2142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: ref=%s\n",
2143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     String8(ref).string()));
2144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: defType=%s\n",
2145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     defType ? String8(*defType).string() : "NULL"));
2146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: defPackage=%s\n",
2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     defPackage ? String8(*defPackage).string() : "NULL"));
2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanding resource: ref=%s\n", String8(ref).string()));
2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(printf("Expanded resource: p=%s, t=%s, n=%s, res=0\n",
2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     String8(package).string(), String8(type).string(),
2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     String8(name).string()));
2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return 0;
2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t res = getResId(package, type, name, onlyPublic && refOnlyPublic);
2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(printf("Expanded resource: p=%s, t=%s, n=%s, res=%d\n",
2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(package).string(), String8(type).string(),
2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                 String8(name).string(), res));
2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (res == 0) {
2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outErrorMsg)
2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            *outErrorMsg = "No resource found that matches the given name";
2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return res;
2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::isValidResourceName(const String16& s)
2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const char16_t* p = s.string();
2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool first = true;
2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (*p) {
2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if ((*p >= 'a' && *p <= 'z')
2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            || (*p >= 'A' && *p <= 'Z')
2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            || *p == '_'
2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            || (!first && *p >= '0' && *p <= '9')) {
2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            first = false;
2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p++;
2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::stringToValue(Res_value* outValue, StringPool* pool,
2184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const String16& str,
2185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  bool preserveSpaces, bool coerceType,
2186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  uint32_t attrID,
2187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const Vector<StringPool::entry_style_span>* style,
2188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  String16* outStr, void* accessorCookie,
2189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  uint32_t attrType, const String8* configTypeName,
2190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  const ConfigDescription* config)
2191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 finalStr;
2193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool res = true;
2195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (style == NULL || style->size() == 0) {
2196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Text is not styled so it can be any type...  let's figure it out.
2197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        res = mAssets->getIncludedResources()
2198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            .stringToValue(outValue, &finalStr, str.string(), str.size(), preserveSpaces,
2199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            coerceType, attrID, NULL, &mAssetsPackage, this,
2200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                           accessorCookie, attrType);
2201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
2202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Styled text can only be a string, and while collecting the style
2203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // information we have already processed that string!
2204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->size = sizeof(Res_value);
2205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->res0 = 0;
2206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->dataType = outValue->TYPE_STRING;
2207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        outValue->data = 0;
2208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        finalStr = str;
2209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!res) {
2212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
2213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (outValue->dataType == outValue->TYPE_STRING) {
2216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Should do better merging styles.
2217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (pool) {
2218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 configStr;
2219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (config != NULL) {
2220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configStr = config->toString();
2221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configStr = "(null)";
2223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            NOISY(printf("Adding to pool string style #%d config %s: %s\n",
2225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    style != NULL ? style->size() : 0,
2226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    configStr.string(), String8(finalStr).string()));
2227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (style != NULL && style->size() > 0) {
2228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outValue->data = pool->add(finalStr, *style, configTypeName, config);
2229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outValue->data = pool->add(finalStr, true, configTypeName, config);
2231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
2233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Caller will fill this in later.
2234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            outValue->data = 0;
2235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (outStr) {
2238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            *outStr = finalStr;
2239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return true;
2244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getCustomResource(
2247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16& package, const String16& type, const String16& name) const
2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getCustomResource: %s %s %s\n", String8(package).string(),
2250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //       String8(type).string(), String8(name).string());
2251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = mPackages.valueFor(package);
2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) return 0;
2253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = p->getTypes().valueFor(type);
2254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) return 0;
2255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c =  t->getConfigs().valueFor(name);
2256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) return 0;
2257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t ei = c->getEntryIndex();
2258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ei < 0) return 0;
2259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return getResId(p, t, ei);
2260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getCustomResourceWithCreation(
2263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& package, const String16& type, const String16& name,
2264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const bool createIfNotFound)
2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t resId = getCustomResource(package, type, name);
2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (resId != 0 || !createIfNotFound) {
2268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return resId;
2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2271f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    if (mAssetsPackage != package) {
2272833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        mCurrentXmlPos.error("creating resource for external package %s: %s/%s.",
2273f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                String8(package).string(), String8(type).string(), String8(name).string());
2274833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (package == String16("android")) {
2275833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            mCurrentXmlPos.printf("did you mean to use @+id instead of @+android:id?");
2276833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
2277833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return 0;
2278f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    }
2279f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
2280f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    String16 value("false");
2281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t status = addEntry(mCurrentXmlPos, package, type, name, value, NULL, NULL, true);
2282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (status == NO_ERROR) {
2283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        resId = getResId(package, type, name);
2284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return resId;
2285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return 0;
2287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getRemappedPackage(uint32_t origPackage) const
2290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return origPackage;
2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeType(uint32_t attrID, uint32_t* outType)
2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeType #%08x\n", attrID);
2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_TYPE, &value)) {
2299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("getAttributeType #%08x (%s): #%08x\n", attrID,
2300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //       String8(getEntry(attrID)->getName()).string(), value.data);
2301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outType = value.data;
2302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeMin(uint32_t attrID, uint32_t* outMin)
2308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeMin #%08x\n", attrID);
2310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_MIN, &value)) {
2312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outMin = value.data;
2313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeMax(uint32_t attrID, uint32_t* outMax)
2319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeMax #%08x\n", attrID);
2321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_MAX, &value)) {
2323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        *outMax = value.data;
2324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getAttributeL10N(uint32_t attrID)
2330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeL10N #%08x\n", attrID);
2332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value value;
2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (getItemValue(attrID, ResTable_map::ATTR_L10N, &value)) {
2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return value.data;
2335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return ResTable_map::L10N_NOT_REQUIRED;
2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getLocalizationSetting()
2340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return mBundle->getRequireLocalization();
2342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::reportError(void* accessorCookie, const char* fmt, ...)
2345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (accessorCookie != NULL && fmt != NULL) {
2347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AccessorCookie* ac = (AccessorCookie*)accessorCookie;
2348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int retval=0;
2349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        char buf[1024];
2350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        va_list ap;
2351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        va_start(ap, fmt);
2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        retval = vsnprintf(buf, sizeof(buf), fmt, ap);
2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        va_end(ap);
2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ac->sourcePos.error("Error: %s (at '%s' with value '%s').\n",
2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            buf, ac->attr.string(), ac->value.string());
2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeKeys(
2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t attrID, Vector<String16>* outKeys)
2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(attrID);
2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e != NULL) {
2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = e->getBag().size();
2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16& key = e->getBag().keyAt(i);
2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (key.size() > 0 && key.string()[0] != '^') {
2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                outKeys->add(key);
2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeEnum(
2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t attrID, const char16_t* name, size_t nameLen,
2378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value* outValue)
2379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeEnum #%08x %s\n", attrID, String8(name, nameLen).string());
2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 nameStr(name, nameLen);
2382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(attrID);
2383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e != NULL) {
2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = e->getBag().size();
2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //printf("Comparing %s to %s\n", String8(name, nameLen).string(),
2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //       String8(e->getBag().keyAt(i)).string());
2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (e->getBag().keyAt(i) == nameStr) {
2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return getItemValue(attrID, e->getBag().valueAt(i).bagKeyId, outValue);
2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeFlags(
2397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t attrID, const char16_t* name, size_t nameLen,
2398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Res_value* outValue)
2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    outValue->dataType = Res_value::TYPE_INT_HEX;
2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    outValue->data = 0;
2402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("getAttributeFlags #%08x %s\n", attrID, String8(name, nameLen).string());
2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String16 nameStr(name, nameLen);
2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(attrID);
2406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e != NULL) {
2407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = e->getBag().size();
2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char16_t* end = name + nameLen;
2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char16_t* pos = name;
2411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (pos < end) {
2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char16_t* start = pos;
2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (pos < end && *pos != '|') {
2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                pos++;
2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 nameStr(start, pos-start);
2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t i;
2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (i=0; i<N; i++) {
2420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Comparing \"%s\" to \"%s\"\n", String8(nameStr).string(),
2421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //       String8(e->getBag().keyAt(i)).string());
2422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (e->getBag().keyAt(i) == nameStr) {
2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    Res_value val;
2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    bool got = getItemValue(attrID, e->getBag().valueAt(i).bagKeyId, &val);
2425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (!got) {
2426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return false;
2427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    //printf("Got value: 0x%08x\n", val.data);
2429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    outValue->data |= val.data;
2430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    break;
2431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (i >= N) {
2435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Didn't find this flag identifier.
2436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return false;
2437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            pos++;
2439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
2442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return false;
2444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::assignResourceIds()
2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t pi;
2450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t firstError = NO_ERROR;
2451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // First generate all bag attributes and assign indices.
2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p == NULL || p->getTypes().size() == 0) {
2456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Empty, skip!
2457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2460833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        // This has no sense for packages being built as AppFeature (aka with a non-zero offset).
2461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = p->applyPublicTypeOrder();
2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR && firstError == NO_ERROR) {
2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            firstError = err;
2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Generate attributes...
2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getOrderedTypes().size();
2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t ti;
2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (ti=0; ti<N; ti++) {
2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t N = c->getEntries().size();
2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = c->getEntries().valueAt(ei);
2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e == NULL) {
2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    status_t err = e->generateAttributes(this, p->getName());
2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR && firstError == NO_ERROR) {
2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        firstError = err;
2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2494833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        uint32_t typeIdOffset = 0;
2495833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        if (mPackageType == AppFeature && p->getName() == mAssetsPackage) {
2496833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            typeIdOffset = mTypeIdOffset;
2497833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        }
2498833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const SourcePos unknown(String8("????"), 0);
2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> attr = p->getType(String16("attr"), unknown);
2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Assign indices...
250343a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        const size_t typeCount = p->getOrderedTypes().size();
250443a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        for (size_t ti = 0; ti < typeCount; ti++) {
2505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
250943a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski
2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = t->applyPublicEntryOrder();
2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR && firstError == NO_ERROR) {
2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                firstError = err;
2513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2516833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            t->setIndex(ti + 1 + typeIdOffset);
2517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            LOG_ALWAYS_FATAL_IF(ti == 0 && attr != t,
2519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "First type is not attr!");
2520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ei=0; ei<N; ei++) {
2522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ei);
2523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                c->setEntryIndex(ei);
2527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Assign resource IDs to keys in bags...
253143a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        for (size_t ti = 0; ti < typeCount; ti++) {
2532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                //printf("Ordered config #%d: %p\n", ci, c.get());
2540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t N = c->getEntries().size();
2541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = c->getEntries().valueAt(ei);
2543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e == NULL) {
2544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    status_t err = e->assignResourceIds(this, p->getName());
2547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR && firstError == NO_ERROR) {
2548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        firstError = err;
2549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return firstError;
2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) {
2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t pi;
2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p->getTypes().size() == 0) {
2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Empty, skip!
2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getOrderedTypes().size();
2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t ti;
2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (ti=0; ti<N; ti++) {
2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<AaptSymbols> typeSymbols;
2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            typeSymbols = outSymbols->addNestedSymbol(String8(t->getName()), t->getPos());
2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t rid = getResId(p, t, ci);
2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (rid == 0) {
2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return UNKNOWN_ERROR;
2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2588833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                if (Res_GETPACKAGE(rid) + 1 == p->getAssignedId()) {
2589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    typeSymbols->addSymbol(String8(c->getName()), rid, c->getPos());
2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String16 comment(c->getComment());
2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    typeSymbols->appendComment(String8(c->getName()), comment, c->getPos());
25938ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                    //printf("Type symbol [%08x] %s comment: %s\n", rid,
25948ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski                    //        String8(c->getName()).string(), String8(comment).string());
2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    comment = c->getTypeComment();
2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    typeSymbols->appendTypeComment(String8(c->getName()), comment);
2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
2606a01a9374fd386f3a8773528d7a49bc5315492dffAdam LesinskiResourceTable::addLocalization(const String16& name, const String8& locale, const SourcePos& src)
2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2608a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski    mLocalizations[name][locale] = src;
2609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*!
2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Flag various sorts of localization problems.  '+' indicates checks already implemented;
2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * '-' indicates checks that will be implemented in the future.
2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A localized string for which no default-locale version exists => warning
2617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A string for which no version in an explicitly-requested locale exists => warning
2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A localized translation of an translateable="false" string => warning
2619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * - A localized string not provided in every locale used by the table
2620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
2621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t
2622282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResourceTable::validateLocalizations(void)
2623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = NO_ERROR;
2625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String8 defaultLocale;
2626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // For all strings...
2628a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski    for (map<String16, map<String8, SourcePos> >::iterator nameIter = mLocalizations.begin();
2629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         nameIter != mLocalizations.end();
2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski         nameIter++) {
2631a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski        const map<String8, SourcePos>& configSrcMap = nameIter->second;
2632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Look for strings with no default localization
2634a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski        if (configSrcMap.count(defaultLocale) == 0) {
2635a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            SourcePos().warning("string '%s' has no default translation.",
2636a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    String8(nameIter->first).string());
2637a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            if (mBundle->getVerbose()) {
2638a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                for (map<String8, SourcePos>::const_iterator locales = configSrcMap.begin();
2639a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    locales != configSrcMap.end();
2640a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    locales++) {
2641a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    locales->second.printf("locale %s found", locales->first.string());
2642a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                }
2643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // !!! TODO: throw an error here in some circumstances
2645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Check that all requested localizations are present for this string
2648fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski        if (mBundle->getConfigurations().size() > 0 && mBundle->getRequireLocalization()) {
2649fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski            const char* allConfigs = mBundle->getConfigurations().string();
2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* start = allConfigs;
2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const char* comma;
2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2653a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            set<String8> missingConfigs;
2654a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            AaptLocaleValue locale;
2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            do {
2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8 config;
2657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                comma = strchr(start, ',');
2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (comma != NULL) {
2659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    config.setTo(start, comma - start);
2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    start = comma + 1;
2661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    config.setTo(start);
2663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2665a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                if (!locale.initFromFilterString(config)) {
2666a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    continue;
2667a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                }
2668a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski
2669a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                // don't bother with the pseudolocale "en_XA" or "ar_XB"
2670a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                if (config != "en_XA" && config != "ar_XB") {
2671a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    if (configSrcMap.find(config) == configSrcMap.end()) {
2672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // okay, no specific localization found.  it's possible that we are
2673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // requiring a specific regional localization [e.g. de_DE] but there is an
2674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // available string in the generic language localization [e.g. de];
2675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // consider that string to have fulfilled the localization requirement.
2676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8 region(config.string(), 2);
2677a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        if (configSrcMap.find(region) == configSrcMap.end() &&
2678a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                                configSrcMap.count(defaultLocale) == 0) {
2679a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                            missingConfigs.insert(config);
2680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
2681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2683a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            } while (comma != NULL);
2684a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski
2685a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            if (!missingConfigs.empty()) {
2686a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                String8 configStr;
2687a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                for (set<String8>::iterator iter = missingConfigs.begin();
2688a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                     iter != missingConfigs.end();
2689a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                     iter++) {
2690a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                    configStr.appendFormat(" %s", iter->string());
2691a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                }
2692a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                SourcePos().warning("string '%s' is missing %u required localizations:%s",
2693a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        String8(nameIter->first).string(),
2694a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        (unsigned int)missingConfigs.size(),
2695a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski                        configStr.string());
2696a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski            }
2697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
2701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
2702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
270327f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinskistatus_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
270427f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski        const sp<AaptFile>& dest,
270527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski        const bool isBase)
2706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
2707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const ConfigDescription nullConfig;
2708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
2710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t pi;
2711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const static String16 mipmap16("mipmap");
2713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool useUTF8 = !bundle->getUTF16StringsOption();
2715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2716de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    // The libraries this table references.
2717de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    Vector<sp<Package> > libraryPackages;
27186022debdbcc4498736580640c6287b57872617a2Adam Lesinski    const ResTable& table = mAssets->getIncludedResources();
27196022debdbcc4498736580640c6287b57872617a2Adam Lesinski    const size_t basePackageCount = table.getBasePackageCount();
27206022debdbcc4498736580640c6287b57872617a2Adam Lesinski    for (size_t i = 0; i < basePackageCount; i++) {
27216022debdbcc4498736580640c6287b57872617a2Adam Lesinski        size_t packageId = table.getBasePackageId(i);
27226022debdbcc4498736580640c6287b57872617a2Adam Lesinski        String16 packageName(table.getBasePackageName(i));
27236022debdbcc4498736580640c6287b57872617a2Adam Lesinski        if (packageId > 0x01 && packageId != 0x7f &&
27246022debdbcc4498736580640c6287b57872617a2Adam Lesinski                packageName != String16("android")) {
27256022debdbcc4498736580640c6287b57872617a2Adam Lesinski            libraryPackages.add(sp<Package>(new Package(packageName, packageId)));
27266022debdbcc4498736580640c6287b57872617a2Adam Lesinski        }
27276022debdbcc4498736580640c6287b57872617a2Adam Lesinski    }
2728de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
2729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Iterate through all data, collecting all values (strings,
2730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // references, etc).
2731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    StringPool valueStrings(useUTF8);
2732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<Entry> > allEntries;
2733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p->getTypes().size() == 0) {
2736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        StringPool typeStrings(useUTF8);
2740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        StringPool keyStrings(useUTF8);
2741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2742833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        ssize_t stringsAdded = 0;
2743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getOrderedTypes().size();
2744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t ti=0; ti<N; ti++) {
2745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getOrderedTypes().itemAt(ti);
2746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
2747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                typeStrings.add(String16("<empty>"), false);
2748833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                stringsAdded++;
2749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
2750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2751833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
2752833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            while (stringsAdded < t->getIndex() - 1) {
2753833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                typeStrings.add(String16("<empty>"), false);
2754833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                stringsAdded++;
2755833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            }
2756833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski
2757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16 typeName(t->getName());
2758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            typeStrings.add(typeName, false);
2759833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            stringsAdded++;
2760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // This is a hack to tweak the sorting order of the final strings,
2762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // to put stuff that is generally not language-specific first.
2763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String8 configTypeName(typeName);
2764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (configTypeName == "drawable" || configTypeName == "layout"
2765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "color" || configTypeName == "anim"
2766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "interpolator" || configTypeName == "animator"
2767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "xml" || configTypeName == "menu"
2768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    || configTypeName == "mipmap" || configTypeName == "raw") {
2769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configTypeName = "1complex";
2770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
2771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configTypeName = "2value";
2772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
277427f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            // mipmaps don't get filtered, so they will
277527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            // allways end up in the base. Make sure they
277627f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            // don't end up in a split.
277727f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            if (typeName == mipmap16 && !isBase) {
277827f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                continue;
277927f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            }
278027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski
2781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const bool filterable = (typeName != mipmap16);
2782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t->getOrderedConfigs().size();
2784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<N; ci++) {
2785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
2786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
2787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
2788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t N = c->getEntries().size();
2790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ConfigDescription config = c->getEntries().keyAt(ei);
2792fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                    if (filterable && !filter->match(config)) {
2793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = c->getEntries().valueAt(ei);
2796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e == NULL) {
2797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        continue;
2798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    e->setNameIndex(keyStrings.add(e->getName(), true));
2800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // If this entry has no values for other configs,
2802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // and is the default config, then it is special.  Otherwise
2803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // we want to add it with the config info.
2804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    ConfigDescription* valueConfig = NULL;
2805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (N != 1 || config == nullConfig) {
2806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        valueConfig = &config;
2807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    status_t err = e->prepareFlatten(&valueStrings, this,
2810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            &configTypeName, &config);
2811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (err != NO_ERROR) {
2812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        return err;
2813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    allEntries.add(e);
2815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p->setTypeStrings(typeStrings.createStringBlock());
2820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        p->setKeyStrings(keyStrings.createStringBlock());
2821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (bundle->getOutputAPKFile() != NULL) {
2824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Now we want to sort the value strings for better locality.  This will
2825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // cause the positions of the strings to change, so we need to go back
2826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // through out resource entries and update them accordingly.  Only need
2827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // to do this if actually writing the output file.
2828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        valueStrings.sortByConfig();
2829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (pi=0; pi<allEntries.size(); pi++) {
2830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            allEntries[pi]->remapStringValue(&valueStrings);
2831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
2833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t strAmt = 0;
2835de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
2836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Now build the array of package chunks.
2837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<AaptFile> > flatPackages;
2838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<N; pi++) {
2839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> p = mOrderedPackages.itemAt(pi);
2840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p->getTypes().size() == 0) {
2841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Empty, skip!
2842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            continue;
2843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = p->getTypeStrings().size();
2846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t baseSize = sizeof(ResTable_package);
2848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Start the package data.
2850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8());
2851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResTable_package* header = (ResTable_package*)data->editData(baseSize);
2852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (header == NULL) {
2853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_package\n");
2854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return NO_MEMORY;
2855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(header, 0, sizeof(*header));
2857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->header.type = htods(RES_TABLE_PACKAGE_TYPE);
2858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->header.headerSize = htods(sizeof(*header));
2859833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        header->id = htodl(static_cast<uint32_t>(p->getAssignedId()));
2860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strcpy16_htod(header->name, p->getName().string());
2861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Write the string blocks.
2863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t typeStringsStart = data->getSize();
2864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<AaptFile> strFile = p->getTypeStringsData();
2865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ssize_t amt = data->writeData(strFile->getData(), strFile->getSize());
2866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #if PRINT_STRING_METRICS
2867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "**** type strings: %d\n", amt);
2868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #endif
2869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strAmt += amt;
2870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (amt < 0) {
2871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return amt;
2872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t keyStringsStart = data->getSize();
2874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strFile = p->getKeyStringsData();
2875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        amt = data->writeData(strFile->getData(), strFile->getSize());
2876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #if PRINT_STRING_METRICS
2877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "**** key strings: %d\n", amt);
2878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #endif
2879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        strAmt += amt;
2880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (amt < 0) {
2881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return amt;
2882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
2883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
288427f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski        if (isBase) {
288527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            status_t err = flattenLibraryTable(data, libraryPackages);
288627f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            if (err != NO_ERROR) {
288727f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                fprintf(stderr, "ERROR: failed to write library table\n");
288827f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                return err;
288927f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            }
2890de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        }
2891de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
2892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Build the type chunks inside of this package.
2893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t ti=0; ti<N; ti++) {
2894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Retrieve them in the same order as the type string block.
2895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
2896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String16 typeName(p->getTypeStrings().stringAt(ti, &len));
2897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = p->getTypes().valueFor(typeName);
2898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            LOG_ALWAYS_FATAL_IF(t == NULL && typeName != String16("<empty>"),
2899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                "Type name %s not found",
2900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                String8(typeName).string());
2901833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            if (t == NULL) {
2902833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                continue;
2903833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            }
2904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const bool filterable = (typeName != mipmap16);
290527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            const bool skipEntireType = (typeName == mipmap16 && !isBase);
2906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = t != NULL ? t->getOrderedConfigs().size() : 0;
2908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Until a non-NO_ENTRY value has been written for a resource,
2910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // that resource is invalid; validResources[i] represents
2911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // the item at t->getOrderedConfigs().itemAt(i).
2912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Vector<bool> validResources;
2913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            validResources.insertAt(false, 0, N);
2914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // First write the typeSpec chunk, containing information about
2916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // each resource entry in this type.
2917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            {
2918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t typeSpecSize = sizeof(ResTable_typeSpec) + sizeof(uint32_t)*N;
2919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t typeSpecStart = data->getSize();
2920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ResTable_typeSpec* tsHeader = (ResTable_typeSpec*)
2921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData(typeSpecStart+typeSpecSize)) + typeSpecStart);
2922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (tsHeader == NULL) {
2923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(stderr, "ERROR: out of memory creating ResTable_typeSpec\n");
2924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NO_MEMORY;
2925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                memset(tsHeader, 0, sizeof(*tsHeader));
2927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->header.type = htods(RES_TABLE_TYPE_SPEC_TYPE);
2928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->header.headerSize = htods(sizeof(*tsHeader));
2929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->header.size = htodl(typeSpecSize);
2930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->id = ti+1;
2931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tsHeader->entryCount = htodl(N);
2932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                uint32_t* typeSpecFlags = (uint32_t*)
2934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData())
2935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        + typeSpecStart + sizeof(ResTable_typeSpec));
2936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                memset(typeSpecFlags, 0, sizeof(uint32_t)*N);
2937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
2939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei);
2940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (cl->getPublic()) {
2941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        typeSpecFlags[ei] |= htodl(ResTable_typeSpec::SPEC_PUBLIC);
2942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
294327f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski
294427f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                    if (skipEntireType) {
294527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                        continue;
294627f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                    }
294727f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski
2948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const size_t CN = cl->getEntries().size();
2949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    for (size_t ci=0; ci<CN; ci++) {
2950fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                        if (filterable && !filter->match(cl->getEntries().keyAt(ci))) {
2951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            continue;
2952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
2953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        for (size_t cj=ci+1; cj<CN; cj++) {
2954fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                            if (filterable && !filter->match(cl->getEntries().keyAt(cj))) {
2955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                continue;
2956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            }
2957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            typeSpecFlags[ei] |= htodl(
2958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                cl->getEntries().keyAt(ci).diff(cl->getEntries().keyAt(cj)));
2959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
2960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
2961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
2962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
2963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
296427f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            if (skipEntireType) {
296527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski                continue;
296627f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski            }
296727f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski
2968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // We need to write one type chunk for each configuration for
2969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // which we have entries in this type.
2970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NC = t->getUniqueConfigs().size();
2971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t typeSize = sizeof(ResTable_type) + sizeof(uint32_t)*N;
2973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t ci=0; ci<NC; ci++) {
2975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ConfigDescription config = t->getUniqueConfigs().itemAt(ci);
2976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
2977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                NOISY(printf("Writing config %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
2978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
2979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "sw%ddp w%ddp h%ddp dir:%d\n",
2980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      ti+1,
2981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.mcc, config.mnc,
2982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.language[0] ? config.language[0] : '-',
2983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.language[1] ? config.language[1] : '-',
2984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.country[0] ? config.country[0] : '-',
2985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.country[1] ? config.country[1] : '-',
2986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.orientation,
2987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.uiMode,
2988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.touchscreen,
2989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.density,
2990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.keyboard,
2991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.inputFlags,
2992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.navigation,
2993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenWidth,
2994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenHeight,
2995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.smallestScreenWidthDp,
2996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenWidthDp,
2997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.screenHeightDp,
2998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config.layoutDirection));
2999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3000fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski                if (filterable && !filter->match(config)) {
3001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
3002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                const size_t typeStart = data->getSize();
3005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                ResTable_type* tHeader = (ResTable_type*)
3007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData(typeStart+typeSize)) + typeStart);
3008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (tHeader == NULL) {
3009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(stderr, "ERROR: out of memory creating ResTable_type\n");
3010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NO_MEMORY;
3011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                memset(tHeader, 0, sizeof(*tHeader));
3014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->header.type = htods(RES_TABLE_TYPE_TYPE);
3015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->header.headerSize = htods(sizeof(*tHeader));
3016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->id = ti+1;
3017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->entryCount = htodl(N);
3018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->entriesStart = htodl(typeSize);
3019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->config = config;
3020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                NOISY(printf("Writing type %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
3021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
3022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                     "sw%ddp w%ddp h%ddp dir:%d\n",
3023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      ti+1,
3024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.mcc, tHeader->config.mnc,
3025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.language[0] ? tHeader->config.language[0] : '-',
3026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.language[1] ? tHeader->config.language[1] : '-',
3027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.country[0] ? tHeader->config.country[0] : '-',
3028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.country[1] ? tHeader->config.country[1] : '-',
3029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.orientation,
3030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.uiMode,
3031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.touchscreen,
3032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.density,
3033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.keyboard,
3034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.inputFlags,
3035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.navigation,
3036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenWidth,
3037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenHeight,
3038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.smallestScreenWidthDp,
3039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenWidthDp,
3040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.screenHeightDp,
3041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      tHeader->config.layoutDirection));
3042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->config.swapHtoD();
3043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Build the entries inside of this type.
3045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (size_t ei=0; ei<N; ei++) {
3046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei);
3047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<Entry> e = cl->getEntries().valueFor(config);
3048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    // Set the offset for this entry in its type.
3050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    uint32_t* index = (uint32_t*)
3051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        (((uint8_t*)data->editData())
3052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            + typeStart + sizeof(ResTable_type));
3053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (e != NULL) {
3054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        index[ei] = htodl(data->getSize()-typeStart-typeSize);
3055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        // Create the entry.
3057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ssize_t amt = e->flatten(bundle, data, cl->getPublic());
3058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (amt < 0) {
3059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            return amt;
3060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
3061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        validResources.editItemAt(ei) = true;
3062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
3063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        index[ei] = htodl(ResTable_type::NO_ENTRY);
3064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // Fill in the rest of the type information.
3068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader = (ResTable_type*)
3069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    (((uint8_t*)data->editData()) + typeStart);
3070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                tHeader->header.size = htodl(data->getSize()-typeStart);
3071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3073833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            // If we're building splits, then each invocation of the flattening
3074833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            // step will have 'missing' entries. Don't warn/error for this case.
3075833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski            if (bundle->getSplitConfigurations().isEmpty()) {
3076833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                bool missing_entry = false;
3077833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                const char* log_prefix = bundle->getErrorOnMissingConfigEntry() ?
3078833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                        "error" : "warning";
3079833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                for (size_t i = 0; i < N; ++i) {
3080833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    if (!validResources[i]) {
3081833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                        sp<ConfigList> c = t->getOrderedConfigs().itemAt(i);
3082833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                        fprintf(stderr, "%s: no entries written for %s/%s (0x%08x)\n", log_prefix,
3083833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                                String8(typeName).string(), String8(c->getName()).string(),
3084833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                                Res_MAKEID(p->getAssignedId() - 1, ti, i));
3085833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                        missing_entry = true;
3086833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    }
3087833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                }
3088833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                if (bundle->getErrorOnMissingConfigEntry() && missing_entry) {
3089833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    fprintf(stderr, "Error: Missing entries, quit!\n");
3090833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski                    return NOT_ENOUGH_DATA;
3091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3092cd28bd37ea2d88dd72930f032ca73daaad5744b4Ying Wang            }
3093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Fill in the rest of the package information.
3096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header = (ResTable_package*)data->editData();
3097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->header.size = htodl(data->getSize());
3098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->typeStrings = htodl(typeStringsStart);
3099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->lastPublicType = htodl(p->getTypeStrings().size());
3100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->keyStrings = htodl(keyStringsStart);
3101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header->lastPublicKey = htodl(p->getKeyStrings().size());
3102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        flatPackages.add(data);
3104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // And now write out the final chunks.
3107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t dataStart = dest->getSize();
3108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    {
3110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // blah
3111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResTable_header header;
3112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(&header, 0, sizeof(header));
3113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.header.type = htods(RES_TABLE_TYPE);
3114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.header.headerSize = htods(sizeof(header));
3115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.packageCount = htodl(flatPackages.size());
3116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = dest->writeData(&header, sizeof(header));
3117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_header\n");
3119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t strStart = dest->getSize();
3124fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski    status_t err = valueStrings.writeStringBlock(dest);
3125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
3127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t amt = (dest->getSize()-strStart);
3130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    strAmt += amt;
3131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #if PRINT_STRING_METRICS
3132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stderr, "**** value strings: %d\n", amt);
3133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stderr, "**** total strings: %d\n", strAmt);
3134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #endif
3135de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (pi=0; pi<flatPackages.size(); pi++) {
3137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = dest->writeData(flatPackages[pi]->getData(),
3138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                              flatPackages[pi]->getSize());
3139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating package chunk for ResTable_header\n");
3141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_header* header = (ResTable_header*)
3146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        (((uint8_t*)dest->getData()) + dataStart);
3147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    header->header.size = htodl(dest->getSize() - dataStart);
3148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(aout << "Resource table:"
3150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski          << HexDump(dest->getData(), dest->getSize()) << endl);
3151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #if PRINT_STRING_METRICS
3153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stderr, "**** total resource table size: %d / %d%% strings\n",
3154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        dest->getSize(), (strAmt*100)/dest->getSize());
3155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #endif
3156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3160de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinskistatus_t ResourceTable::flattenLibraryTable(const sp<AaptFile>& dest, const Vector<sp<Package> >& libs) {
3161de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    // Write out the library table if necessary
3162de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    if (libs.size() > 0) {
3163de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        NOISY(fprintf(stderr, "Writing library reference table\n"));
3164de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3165de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        const size_t libStart = dest->getSize();
3166de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        const size_t count = libs.size();
31676022debdbcc4498736580640c6287b57872617a2Adam Lesinski        ResTable_lib_header* libHeader = (ResTable_lib_header*) dest->editDataInRange(
31686022debdbcc4498736580640c6287b57872617a2Adam Lesinski                libStart, sizeof(ResTable_lib_header));
3169de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3170de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        memset(libHeader, 0, sizeof(*libHeader));
3171de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        libHeader->header.type = htods(RES_TABLE_LIBRARY_TYPE);
3172de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        libHeader->header.headerSize = htods(sizeof(*libHeader));
3173de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        libHeader->header.size = htodl(sizeof(*libHeader) + (sizeof(ResTable_lib_entry) * count));
3174de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        libHeader->count = htodl(count);
3175de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3176de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        // Write the library entries
3177de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        for (size_t i = 0; i < count; i++) {
3178de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            const size_t entryStart = dest->getSize();
3179de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            sp<Package> libPackage = libs[i];
3180de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            NOISY(fprintf(stderr, "  Entry %s -> 0x%02x\n",
3181de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski                        String8(libPackage->getName()).string(),
3182de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski                        (uint8_t)libPackage->getAssignedId()));
3183de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
31846022debdbcc4498736580640c6287b57872617a2Adam Lesinski            ResTable_lib_entry* entry = (ResTable_lib_entry*) dest->editDataInRange(
31856022debdbcc4498736580640c6287b57872617a2Adam Lesinski                    entryStart, sizeof(ResTable_lib_entry));
3186de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            memset(entry, 0, sizeof(*entry));
3187de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            entry->packageId = htodl(libPackage->getAssignedId());
3188de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski            strcpy16_htod(entry->packageName, libPackage->getName().string());
3189de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski        }
3190de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    }
3191de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski    return NO_ERROR;
3192de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski}
3193de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski
3194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::writePublicDefinitions(const String16& package, FILE* fp)
3195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(fp,
3197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "<!-- This file contains <public> resource definitions for all\n"
3198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "     resources that were generated from the source data. -->\n"
3199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "\n"
3200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "<resources>\n");
3201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    writePublicDefinitions(package, fp, true);
3203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    writePublicDefinitions(package, fp, false);
3204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(fp,
3206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "\n"
3207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    "</resources>\n");
3208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::writePublicDefinitions(const String16& package, FILE* fp, bool pub)
3211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool didHeader = false;
3213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> pkg = mPackages.valueFor(package);
3215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (pkg != NULL) {
3216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t NT = pkg->getOrderedTypes().size();
3217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<NT; i++) {
3218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<Type> t = pkg->getOrderedTypes().itemAt(i);
3219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (t == NULL) {
3220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                continue;
3221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            bool didType = false;
3224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t NC = t->getOrderedConfigs().size();
3226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (size_t j=0; j<NC; j++) {
3227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<ConfigList> c = t->getOrderedConfigs().itemAt(j);
3228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c == NULL) {
3229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
3230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (c->getPublic() != pub) {
3233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    continue;
3234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!didType) {
3237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    fprintf(fp, "\n");
3238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    didType = true;
3239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!didHeader) {
3241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (pub) {
3242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"  <!-- PUBLIC SECTION.  These resources have been declared public.\n");
3243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"       Changes to these definitions will break binary compatibility. -->\n\n");
3244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    } else {
3245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"  <!-- PRIVATE SECTION.  These resources have not been declared public.\n");
3246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        fprintf(fp,"       You can make them public my moving these lines into a file in res/values. -->\n\n");
3247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    didHeader = true;
3249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (!pub) {
3251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    const size_t NE = c->getEntries().size();
3252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    for (size_t k=0; k<NE; k++) {
3253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        const SourcePos& pos = c->getEntries().valueAt(k)->getPos();
3254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        if (pos.file != "") {
3255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            fprintf(fp,"  <!-- Declared at %s:%d -->\n",
3256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    pos.file.string(), pos.line);
3257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        }
3258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(fp, "  <public type=\"%s\" name=\"%s\" id=\"0x%08x\" />\n",
3261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(t->getName()).string(),
3262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(c->getName()).string(),
3263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        getResId(pkg, t, c->getEntryIndex()));
3264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3269282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResourceTable::Item::Item(const SourcePos& _sourcePos,
3270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          bool _isId,
3271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          const String16& _value,
3272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          const Vector<StringPool::entry_style_span>* _style,
3273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          int32_t _format)
3274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    : sourcePos(_sourcePos)
3275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , isId(_isId)
3276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , value(_value)
3277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , format(_format)
3278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , bagKeyId(0)
3279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    , evaluating(false)
3280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (_style) {
3282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        style = *_style;
3283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::makeItABag(const SourcePos& sourcePos)
3287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_BAG) {
3289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
3290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_UNKNOWN) {
3292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mType = TYPE_BAG;
3293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NO_ERROR;
3294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sourcePos.error("Resource entry %s is already defined as a single item.\n"
3296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "%s:%d: Originally defined here.\n",
3297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(),
3298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mItem.sourcePos.file.string(), mItem.sourcePos.line);
3299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return UNKNOWN_ERROR;
3300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::setItem(const SourcePos& sourcePos,
3303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       const String16& value,
3304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       const Vector<StringPool::entry_style_span>* style,
3305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       int32_t format,
3306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                       const bool overwrite)
3307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Item item(sourcePos, false, value, style);
3309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_BAG) {
331143a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        if (mBag.size() == 0) {
331243a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski            sourcePos.error("Resource entry %s is already defined as a bag.",
331343a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                    String8(mName).string());
331443a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        } else {
331543a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski            const Item& item(mBag.valueAt(0));
331643a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski            sourcePos.error("Resource entry %s is already defined as a bag.\n"
331743a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                            "%s:%d: Originally defined here.\n",
331843a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                            String8(mName).string(),
331943a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                            item.sourcePos.file.string(), item.sourcePos.line);
332043a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski        }
3321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if ( (mType != TYPE_UNKNOWN) && (overwrite == false) ) {
3324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sourcePos.error("Resource entry %s is already defined.\n"
3325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "%s:%d: Originally defined here.\n",
3326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(mName).string(),
3327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        mItem.sourcePos.file.string(), mItem.sourcePos.line);
3328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mType = TYPE_ITEM;
3332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mItem = item;
3333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mItemFormat = format;
3334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::addToBag(const SourcePos& sourcePos,
3338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const String16& key, const String16& value,
3339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const Vector<StringPool::entry_style_span>* style,
3340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        bool replace, bool isId, int32_t format)
3341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = makeItABag(sourcePos);
3343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
3345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Item item(sourcePos, isId, value, style, format);
3348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // XXX NOTE: there is an error if you try to have a bag with two keys,
3350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // one an attr and one an id, with the same name.  Not something we
3351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // currently ever have to worry about.
3352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t origKey = mBag.indexOfKey(key);
3353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (origKey >= 0) {
3354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!replace) {
3355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const Item& item(mBag.valueAt(origKey));
3356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Resource entry %s already has bag item %s.\n"
3357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "%s:%d: Originally defined here.\n",
3358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(key).string(),
3359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    item.sourcePos.file.string(), item.sourcePos.line);
3360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("Replacing %s with %s\n",
3363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //       String8(mBag.valueFor(key).value).string(), String8(value).string());
3364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mBag.replaceValueFor(key, item);
3365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mBag.add(key, item);
3368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::emptyBag(const SourcePos& sourcePos)
3372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = makeItABag(sourcePos);
3374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return err;
3376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mBag.clear();
3379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::generateAttributes(ResourceTable* table,
3383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                  const String16& package)
3384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 attr16("attr");
3386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const String16 id16("id");
3387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mBag.size();
3388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
3389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& key = mBag.keyAt(i);
3390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Item& it = mBag.valueAt(i);
3391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.isId) {
3392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!table->hasBagOrEntry(key, &id16, &package)) {
3393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String16 value("false");
339443a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                NOISY(fprintf(stderr, "Generating %s:id/%s\n",
339543a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                        String8(package).string(),
339643a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski                        String8(key).string()));
3397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                status_t err = table->addEntry(SourcePos(String8("<generated>"), 0), package,
3398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               id16, key, value);
3399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (err != NO_ERROR) {
3400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return err;
3401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else if (!table->hasBagOrEntry(key, &attr16, &package)) {
3404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 1
3406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             fprintf(stderr, "ERROR: Bag attribute '%s' has not been defined.\n",
3407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//                     String8(key).string());
3408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             const Item& item(mBag.valueAt(i));
3409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             fprintf(stderr, "Referenced from file %s line %d\n",
3410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//                     item.sourcePos.file.string(), item.sourcePos.line);
3411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//             return UNKNOWN_ERROR;
3412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#else
3413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            char numberStr[16];
3414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sprintf(numberStr, "%d", ResTable_map::TYPE_ANY);
3415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            status_t err = table->addBag(SourcePos("<generated>", 0), package,
3416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                         attr16, key, String16(""),
3417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                         String16("^type"),
3418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                         String16(numberStr), NULL, NULL);
3419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
3420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return err;
3421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
3423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::assignResourceIds(ResourceTable* table,
3429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const String16& package)
3430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasErrors = false;
3432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_BAG) {
3434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* errorMsg;
3435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16 style16("style");
3436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16 attr16("attr");
3437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16 id16("id");
3438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mParentId = 0;
3439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mParent.size() > 0) {
3440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mParentId = table->getResId(mParent, &style16, NULL, &errorMsg);
3441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (mParentId == 0) {
3442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mPos.error("Error retrieving parent for item: %s '%s'.\n",
3443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        errorMsg, String8(mParent).string());
3444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasErrors = true;
3445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = mBag.size();
3448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16& key = mBag.keyAt(i);
3450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Item& it = mBag.editValueAt(i);
3451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            it.bagKeyId = table->getResId(key,
3452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    it.isId ? &id16 : &attr16, NULL, &errorMsg);
3453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //printf("Bag key of %s: #%08x\n", String8(key).string(), it.bagKeyId);
3454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (it.bagKeyId == 0) {
3455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                it.sourcePos.error("Error: %s: %s '%s'.\n", errorMsg,
3456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(it.isId ? id16 : attr16).string(),
3457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(key).string());
3458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasErrors = true;
3459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
3463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::prepareFlatten(StringPool* strings, ResourceTable* table,
3466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String8* configTypeName, const ConfigDescription* config)
3467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_ITEM) {
3469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Item& it = mItem;
3470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        AccessorCookie ac(it.sourcePos, String8(mName), String8(it.value));
3471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!table->stringToValue(&it.parsedValue, strings,
3472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  it.value, false, true, 0,
3473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  &it.style, NULL, &ac, mItemFormat,
3474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                  configTypeName, config)) {
3475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (mType == TYPE_BAG) {
3478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = mBag.size();
3479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String16& key = mBag.keyAt(i);
3481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Item& it = mBag.editValueAt(i);
3482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AccessorCookie ac(it.sourcePos, String8(key), String8(it.value));
3483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (!table->stringToValue(&it.parsedValue, strings,
3484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      it.value, false, true, it.bagKeyId,
3485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      &it.style, NULL, &ac, it.format,
3486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                      configTypeName, config)) {
3487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
3488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPos.error("Error: entry %s is not a single item or a bag.\n",
3492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                   String8(mName).string());
3493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::remapStringValue(StringPool* strings)
3499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mType == TYPE_ITEM) {
3501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Item& it = mItem;
3502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.parsedValue.dataType == Res_value::TYPE_STRING) {
3503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            it.parsedValue.data = strings->mapOriginalPosToNewPos(it.parsedValue.data);
3504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else if (mType == TYPE_BAG) {
3506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = mBag.size();
3507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Item& it = mBag.editValueAt(i);
3509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (it.parsedValue.dataType == Res_value::TYPE_STRING) {
3510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                it.parsedValue.data = strings->mapOriginalPosToNewPos(it.parsedValue.data);
3511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPos.error("Error: entry %s is not a single item or a bag.\n",
3515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                   String8(mName).string());
3516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t ResourceTable::Entry::flatten(Bundle* bundle, const sp<AaptFile>& data, bool isPublic)
3522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t amt = 0;
3524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResTable_entry header;
3525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    memset(&header, 0, sizeof(header));
3526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    header.size = htods(sizeof(header));
3527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const type ty = this != NULL ? mType : TYPE_ITEM;
3528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (this != NULL) {
3529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (ty == TYPE_BAG) {
3530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            header.flags |= htods(header.FLAG_COMPLEX);
3531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (isPublic) {
3533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            header.flags |= htods(header.FLAG_PUBLIC);
3534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        header.key.index = htodl(mNameIndex);
3536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (ty != TYPE_BAG) {
3538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = data->writeData(&header, sizeof(header));
3539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_entry\n");
3541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Item& it = mItem;
3545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Res_value par;
3546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memset(&par, 0, sizeof(par));
3547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.size = htods(it.parsedValue.size);
3548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.dataType = it.parsedValue.dataType;
3549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.res0 = it.parsedValue.res0;
3550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        par.data = htodl(it.parsedValue.data);
3551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #if 0
3552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Writing item (%s): type=%d, data=0x%x, res0=0x%x\n",
3553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               String8(mName).string(), it.parsedValue.dataType,
3554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski               it.parsedValue.data, par.res0);
3555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        #endif
3556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        err = data->writeData(&par, it.parsedValue.size);
3557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating Res_value\n");
3559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        amt += it.parsedValue.size;
3562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t N = mBag.size();
3564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t i;
3565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Create correct ordering of items.
3566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        KeyedVector<uint32_t, const Item*> items;
3567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (i=0; i<N; i++) {
3568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const Item& it = mBag.valueAt(i);
3569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            items.add(it.bagKeyId, &it);
3570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        N = items.size();
3572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResTable_map_entry mapHeader;
3574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        memcpy(&mapHeader, &header, sizeof(header));
3575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapHeader.size = htods(sizeof(mapHeader));
3576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapHeader.parent.ident = htodl(mParentId);
3577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mapHeader.count = htodl(N);
3578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        status_t err = data->writeData(&mapHeader, sizeof(mapHeader));
3579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (err != NO_ERROR) {
3580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "ERROR: out of memory creating ResTable_entry\n");
3581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return err;
3582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (i=0; i<N; i++) {
3585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const Item& it = *items.valueAt(i);
3586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            ResTable_map map;
3587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.name.ident = htodl(it.bagKeyId);
3588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.size = htods(it.parsedValue.size);
3589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.dataType = it.parsedValue.dataType;
3590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.res0 = it.parsedValue.res0;
3591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            map.value.data = htodl(it.parsedValue.data);
3592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            err = data->writeData(&map, sizeof(map));
3593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (err != NO_ERROR) {
3594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "ERROR: out of memory creating Res_value\n");
3595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return err;
3596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            amt += sizeof(map);
3598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return amt;
3601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::ConfigList::appendComment(const String16& comment,
3604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                              bool onlyIfEmpty)
3605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
3607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
3608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (onlyIfEmpty && mComment.size() > 0) {
3610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
3611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mComment.size() > 0) {
3613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mComment.append(String16("\n"));
3614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mComment.append(comment);
3616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::ConfigList::appendTypeComment(const String16& comment)
3619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (comment.size() <= 0) {
3621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
3622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mTypeComment.size() > 0) {
3624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mTypeComment.append(String16("\n"));
3625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mTypeComment.append(comment);
3627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Type::addPublic(const SourcePos& sourcePos,
3630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const String16& name,
3631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                        const uint32_t ident)
3632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #if 0
3634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t entryIdx = Res_GETENTRY(ident);
3635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (entryIdx < 0) {
3636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sourcePos.error("Public resource %s/%s has an invalid 0 identifier (0x%08x).\n",
3637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String8(mName).string(), String8(name).string(), ident);
3638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    #endif
3641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int32_t typeIdx = Res_GETTYPE(ident);
3643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (typeIdx >= 0) {
3644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        typeIdx++;
3645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mPublicIndex > 0 && mPublicIndex != typeIdx) {
3646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Public resource %s/%s has conflicting type codes for its"
3647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    " public identifiers (0x%x vs 0x%x).\n",
3648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(name).string(),
3649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mPublicIndex, typeIdx);
3650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPublicIndex = typeIdx;
3653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mFirstPublicSourcePos == NULL) {
3656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mFirstPublicSourcePos = new SourcePos(sourcePos);
3657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (mPublic.indexOfKey(name) < 0) {
3660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPublic.add(name, Public(sourcePos, String16(), ident));
3661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
3662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Public& p = mPublic.editValueFor(name);
3663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (p.ident != ident) {
3664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Public resource %s/%s has conflicting public identifiers"
3665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    " (0x%08x vs 0x%08x).\n"
3666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "%s:%d: Originally defined here.\n",
3667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(name).string(), p.ident, ident,
3668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    p.sourcePos.file.string(), p.sourcePos.line);
3669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return UNKNOWN_ERROR;
3670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::Type::canAddEntry(const String16& name)
3677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mCanAddEntries.add(name);
3679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Entry> ResourceTable::Type::getEntry(const String16& entry,
3682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       const SourcePos& sourcePos,
3683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       const ResTable_config* config,
3684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       bool doSetIndex,
3685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       bool overlay,
3686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       bool autoAddOverlay)
3687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int pos = -1;
3689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c = mConfigs.valueFor(entry);
3690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) {
3691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (overlay && !autoAddOverlay && mCanAddEntries.indexOf(entry) < 0) {
3692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sourcePos.error("Resource at %s appears in overlay but not"
3693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " in the base package; use <add-resource> to add.\n",
3694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(entry).string());
3695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return NULL;
3696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        c = new ConfigList(entry, sourcePos);
3698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mConfigs.add(entry, c);
3699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        pos = (int)mOrderedConfigs.size();
3700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedConfigs.add(c);
3701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (doSetIndex) {
3702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c->setEntryIndex(pos);
3703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ConfigDescription cdesc;
3707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (config) cdesc = *config;
3708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = c->getEntries().valueFor(cdesc);
3710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
3711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (config != NULL) {
3712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            NOISY(printf("New entry at %s:%d: imsi:%d/%d lang:%c%c cnt:%c%c "
3713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "orien:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
3714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "sw%ddp w%ddp h%ddp dir:%d\n",
3715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      sourcePos.file.string(), sourcePos.line,
3716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->mcc, config->mnc,
3717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->language[0] ? config->language[0] : '-',
3718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->language[1] ? config->language[1] : '-',
3719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->country[0] ? config->country[0] : '-',
3720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->country[1] ? config->country[1] : '-',
3721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->orientation,
3722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->touchscreen,
3723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->density,
3724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->keyboard,
3725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->inputFlags,
3726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->navigation,
3727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenWidth,
3728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenHeight,
3729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->smallestScreenWidthDp,
3730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenWidthDp,
3731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->screenHeightDp,
3732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      config->layoutDirection));
3733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
3734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            NOISY(printf("New entry at %s:%d: NULL config\n",
3735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                      sourcePos.file.string(), sourcePos.line));
3736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        e = new Entry(entry, sourcePos);
3738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        c->addEntry(cdesc, e);
3739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        /*
3740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (doSetIndex) {
3741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (pos < 0) {
3742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                for (pos=0; pos<(int)mOrderedConfigs.size(); pos++) {
3743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    if (mOrderedConfigs[pos] == c) {
3744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        break;
3745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    }
3746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (pos >= (int)mOrderedConfigs.size()) {
3748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sourcePos.error("Internal error: config not found in mOrderedConfigs when adding entry");
3749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return NULL;
3750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            e->setEntryIndex(pos);
3753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        */
3755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mUniqueConfigs.add(cdesc);
3758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return e;
3760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Type::applyPublicEntryOrder()
3763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = mOrderedConfigs.size();
3765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<ConfigList> > origOrder(mOrderedConfigs);
3766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasError = false;
3767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
3769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedConfigs.replaceAt(NULL, i);
3771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t NP = mPublic.size();
3774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("Ordering %d configs from %d public defs\n", N, NP);
3775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t j;
3776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (j=0; j<NP; j++) {
3777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const String16& name = mPublic.keyAt(j);
3778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Public& p = mPublic.valueAt(j);
3779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int32_t idx = Res_GETENTRY(p.ident);
3780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //printf("Looking for entry \"%s\"/\"%s\" (0x%08x) in %d...\n",
3781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //       String8(mName).string(), String8(name).string(), p.ident, N);
3782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool found = false;
3783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (i=0; i<N; i++) {
3784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<ConfigList> e = origOrder.itemAt(i);
3785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            //printf("#%d: \"%s\"\n", i, String8(e->getName()).string());
3786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (e->getName() == name) {
3787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (idx >= (int32_t)mOrderedConfigs.size()) {
3788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    p.sourcePos.error("Public entry identifier 0x%x entry index "
3789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "is larger than available symbols (index %d, total symbols %d).\n",
3790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            p.ident, idx, mOrderedConfigs.size());
3791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasError = true;
3792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else if (mOrderedConfigs.itemAt(idx) == NULL) {
3793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    e->setPublic(true);
3794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    e->setPublicSourcePos(p.sourcePos);
3795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    mOrderedConfigs.replaceAt(e, idx);
3796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    origOrder.removeAt(i);
3797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    N--;
3798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    found = true;
3799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    break;
3800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                } else {
3801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    sp<ConfigList> oe = mOrderedConfigs.itemAt(idx);
3802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    p.sourcePos.error("Multiple entry names declared for public entry"
3804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            " identifier 0x%x in type %s (%s vs %s).\n"
3805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            "%s:%d: Originally defined here.",
3806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            idx+1, String8(mName).string(),
3807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(oe->getName()).string(),
3808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            String8(name).string(),
3809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            oe->getPublicSourcePos().file.string(),
3810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            oe->getPublicSourcePos().line);
3811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    hasError = true;
3812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
3813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!found) {
3817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p.sourcePos.error("Public symbol %s/%s declared here is not defined.",
3818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(mName).string(), String8(name).string());
3819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasError = true;
3820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //printf("Copying back in %d non-public configs, have %d\n", N, origOrder.size());
3824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (N != origOrder.size()) {
3826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        printf("Internal error: remaining private symbol count mismatch\n");
3827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        N = origOrder.size();
3828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    j = 0;
3831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<ConfigList> e = origOrder.itemAt(i);
3833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // There will always be enough room for the remaining entries.
3834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (mOrderedConfigs.itemAt(j) != NULL) {
3835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            j++;
3836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedConfigs.replaceAt(e, j);
3838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        j++;
3839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return hasError ? UNKNOWN_ERROR : NO_ERROR;
3842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3844833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam LesinskiResourceTable::Package::Package(const String16& name, size_t packageId)
3845833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    : mName(name), mPackageId(packageId),
3846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      mTypeStringsMapping(0xffffffff),
3847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski      mKeyStringsMapping(0xffffffff)
3848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Type> ResourceTable::Package::getType(const String16& type,
3852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                        const SourcePos& sourcePos,
3853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                        bool doSetIndex)
3854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = mTypes.valueFor(type);
3856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) {
3857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t = new Type(type, sourcePos);
3858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mTypes.add(type, t);
3859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedTypes.add(t);
3860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (doSetIndex) {
3861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // For some reason the type's index is set to one plus the index
3862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // in the mOrderedTypes list, rather than just the index.
3863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            t->setIndex(mOrderedTypes.size());
3864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return t;
3867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setTypeStrings(const sp<AaptFile>& data)
3870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = setStrings(data, &mTypeStrings, &mTypeStringsMapping);
3872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: Type string data is corrupt!\n");
387457079519f4610715e4c0668c641575d10f3d4461Adam Lesinski        return err;
3875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
387657079519f4610715e4c0668c641575d10f3d4461Adam Lesinski
387757079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    // Retain a reference to the new data after we've successfully replaced
387857079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    // all uses of the old reference (in setStrings() ).
387957079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    mTypeStringsData = data;
388057079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    return NO_ERROR;
3881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setKeyStrings(const sp<AaptFile>& data)
3884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = setStrings(data, &mKeyStrings, &mKeyStringsMapping);
3886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err != NO_ERROR) {
3887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "ERROR: Key string data is corrupt!\n");
388857079519f4610715e4c0668c641575d10f3d4461Adam Lesinski        return err;
3889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
389057079519f4610715e4c0668c641575d10f3d4461Adam Lesinski
389157079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    // Retain a reference to the new data after we've successfully replaced
389257079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    // all uses of the old reference (in setStrings() ).
389357079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    mKeyStringsData = data;
389457079519f4610715e4c0668c641575d10f3d4461Adam Lesinski    return NO_ERROR;
3895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setStrings(const sp<AaptFile>& data,
3898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            ResStringPool* strings,
3899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            DefaultKeyedVector<String16, uint32_t>* mappings)
3900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (data->getData() == NULL) {
3902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return UNKNOWN_ERROR;
3903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NOISY(aout << "Setting restable string pool: "
3906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski          << HexDump(data->getData(), data->getSize()) << endl);
3907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t err = strings->setTo(data->getData(), data->getSize());
3909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (err == NO_ERROR) {
3910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const size_t N = strings->size();
3911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (size_t i=0; i<N; i++) {
3912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t len;
3913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mappings->add(String16(strings->stringAt(i, &len)), i);
3914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return err;
3917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::applyPublicTypeOrder()
3920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t N = mOrderedTypes.size();
3922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<sp<Type> > origOrder(mOrderedTypes);
3923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t i;
3925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedTypes.replaceAt(NULL, i);
3927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = origOrder.itemAt(i);
3931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int32_t idx = t->getPublicIndex();
3932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (idx > 0) {
3933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            idx--;
3934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            while (idx >= (int32_t)mOrderedTypes.size()) {
3935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mOrderedTypes.add();
3936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (mOrderedTypes.itemAt(idx) != NULL) {
3938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                sp<Type> ot = mOrderedTypes.itemAt(idx);
3939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                t->getFirstPublicSourcePos().error("Multiple type names declared for public type"
3940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        " identifier 0x%x (%s vs %s).\n"
3941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "%s:%d: Originally defined here.",
3942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        idx, String8(ot->getName()).string(),
3943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        String8(t->getName()).string(),
3944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ot->getFirstPublicSourcePos().file.string(),
3945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        ot->getFirstPublicSourcePos().line);
3946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return UNKNOWN_ERROR;
3947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
3948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            mOrderedTypes.replaceAt(t, idx);
3949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            origOrder.removeAt(i);
3950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            i--;
3951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            N--;
3952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t j=0;
3956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (i=0; i<N; i++) {
3957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Type> t = origOrder.itemAt(i);
3958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // There will always be enough room for the remaining types.
3959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (mOrderedTypes.itemAt(j) != NULL) {
3960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            j++;
3961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
3962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mOrderedTypes.replaceAt(t, j);
3963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NO_ERROR;
3966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Package> ResourceTable::getPackage(const String16& package)
3969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3970833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    if (package != mAssetsPackage) {
3971833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski        return NULL;
3972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3973833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    return mPackages.valueFor(package);
3974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Type> ResourceTable::getType(const String16& package,
3977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               const String16& type,
3978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               const SourcePos& sourcePos,
3979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                               bool doSetIndex)
3980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p = getPackage(package);
3982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) {
3983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
3984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
3985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return p->getType(type, sourcePos, doSetIndex);
3986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
3987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Entry> ResourceTable::getEntry(const String16& package,
3989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const String16& type,
3990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const String16& name,
3991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const SourcePos& sourcePos,
3992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 bool overlay,
3993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 const ResTable_config* config,
3994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                 bool doSetIndex)
3995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
3996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = getType(package, type, sourcePos, doSetIndex);
3997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (t == NULL) {
3998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
3999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return t->getEntry(name, sourcePos, config, doSetIndex, overlay, mBundle->getAutoAddOverlay());
4001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<const ResourceTable::Entry> ResourceTable::getEntry(uint32_t resID,
4004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                                       const ResTable_config* config) const
4005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4006833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    size_t pid = Res_GETPACKAGE(resID)+1;
4007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = mOrderedPackages.size();
4008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Package> p;
4009833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski    for (size_t i = 0; i < N; i++) {
4010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        sp<Package> check = mOrderedPackages[i];
4011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (check->getAssignedId() == pid) {
4012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            p = check;
4013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            break;
4014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (p == NULL) {
4018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Package not found for resource #%08x\n", resID);
4019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int tid = Res_GETTYPE(resID);
4023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (tid < 0 || tid >= (int)p->getOrderedTypes().size()) {
4024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Type not found for resource #%08x\n", resID);
4025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Type> t = p->getOrderedTypes()[tid];
4028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int eid = Res_GETENTRY(resID);
4030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (eid < 0 || eid >= (int)t->getOrderedConfigs().size()) {
4031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID);
4032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<ConfigList> c = t->getOrderedConfigs()[eid];
4036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) {
4037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID);
4038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ConfigDescription cdesc;
4042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (config) cdesc = *config;
4043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<Entry> e = c->getEntries().valueFor(cdesc);
4044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (c == NULL) {
4045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "warning: Entry configuration not found for resource #%08x\n", resID);
4046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return e;
4050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst ResourceTable::Item* ResourceTable::getItem(uint32_t resID, uint32_t attrID) const
4053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<const Entry> e = getEntry(resID);
4055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (e == NULL) {
4056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return NULL;
4057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const size_t N = e->getBag().size();
4060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    for (size_t i=0; i<N; i++) {
4061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const Item& it = e->getBag().valueAt(i);
4062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.bagKeyId == 0) {
4063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "warning: ID not yet assigned to '%s' in bag '%s'\n",
4064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getName()).string(),
4065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getBag().keyAt(i)).string());
4066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (it.bagKeyId == attrID) {
4068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return &it;
4069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NULL;
4073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getItemValue(
4076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    uint32_t resID, uint32_t attrID, Res_value* outValue)
4077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
4078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Item* item = getItem(resID, attrID);
4079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
4080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool res = false;
4081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (item != NULL) {
4082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (item->evaluating) {
4083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            sp<const Entry> e = getEntry(resID);
4084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const size_t N = e->getBag().size();
4085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            size_t i;
4086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (i=0; i<N; i++) {
4087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if (&e->getBag().valueAt(i) == item) {
4088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    break;
4089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
4090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
4091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            fprintf(stderr, "warning: Circular reference detected in key '%s' of bag '%s'\n",
4092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getName()).string(),
4093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    String8(e->getBag().keyAt(i)).string());
4094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
4095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
4096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        item->evaluating = true;
4097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        res = stringToValue(outValue, NULL, item->value, false, false, item->bagKeyId);
4098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NOISY(
4099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res) {
4100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("getItemValue of #%08x[#%08x] (%s): type=#%08x, data=#%08x\n",
4101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       resID, attrID, String8(getEntry(resID)->getName()).string(),
4102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       outValue->dataType, outValue->data);
4103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
4104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                printf("getItemValue of #%08x[#%08x]: failed\n",
4105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                       resID, attrID);
4106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
4107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        );
4108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        item->evaluating = false;
4109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
4110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return res;
4111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
4112