19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Copyright 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Build resource files from raw assets.
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "XMLNode.h"
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "ResourceTable.h"
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <host/pseudolocalize.h>
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/ByteOrder.h>
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h>
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h>
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifndef HAVE_MS_C_RUNTIME
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define O_BINARY 0
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define NOISY(x) //x
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define NOISY_PARSE(x) //x
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst char* const RESOURCES_ROOT_NAMESPACE = "http://schemas.android.com/apk/res/";
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst char* const RESOURCES_ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android";
24d9fe8018ffbf94f18a840005e688ad1d712f0225Xavier Ducrohetconst char* const RESOURCES_AUTO_PACKAGE_NAMESPACE = "http://schemas.android.com/apk/res-auto";
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst char* const RESOURCES_ROOT_PRV_NAMESPACE = "http://schemas.android.com/apk/prv/res/";
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst char* const XLIFF_XMLNS = "urn:oasis:names:tc:xliff:document:1.2";
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst char* const ALLOWED_XLIFF_ELEMENTS[] = {
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "bpt",
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "ept",
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "it",
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "ph",
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "g",
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "bx",
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "ex",
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "x"
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool isWhitespace(const char16_t* str)
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (*str != 0 && *str < 128 && isspace(*str)) {
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        str++;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return *str == 0;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const String16 RESOURCES_PREFIX(RESOURCES_ROOT_NAMESPACE);
48e348909c1966c3d192841cc131a32be6ed90da18inazarukstatic const String16 RESOURCES_PREFIX_AUTO_PACKAGE(RESOURCES_AUTO_PACKAGE_NAMESPACE);
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const String16 RESOURCES_PRV_PREFIX(RESOURCES_ROOT_PRV_NAMESPACE);
50f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohetstatic const String16 RESOURCES_TOOLS_NAMESPACE("http://schemas.android.com/tools");
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
52e348909c1966c3d192841cc131a32be6ed90da18inazarukString16 getNamespaceResourcePackage(String16 appPackage, String16 namespaceUri, bool* outIsPublic)
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //printf("%s starts with %s?\n", String8(namespaceUri).string(),
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //       String8(RESOURCES_PREFIX).string());
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t prefixSize;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool isPublic = true;
58e348909c1966c3d192841cc131a32be6ed90da18inazaruk    if(namespaceUri.startsWith(RESOURCES_PREFIX_AUTO_PACKAGE)) {
59e348909c1966c3d192841cc131a32be6ed90da18inazaruk        NOISY(printf("Using default application package: %s -> %s\n", String8(namespaceUri).string(), String8(appPackage).string()));
60e348909c1966c3d192841cc131a32be6ed90da18inazaruk        isPublic = true;
61e348909c1966c3d192841cc131a32be6ed90da18inazaruk        return appPackage;
62e348909c1966c3d192841cc131a32be6ed90da18inazaruk    } else if (namespaceUri.startsWith(RESOURCES_PREFIX)) {
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        prefixSize = RESOURCES_PREFIX.size();
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (namespaceUri.startsWith(RESOURCES_PRV_PREFIX)) {
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        isPublic = false;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        prefixSize = RESOURCES_PRV_PREFIX.size();
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (outIsPublic) *outIsPublic = isPublic; // = true
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String16();
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //printf("YES!\n");
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //printf("namespace: %s\n", String8(String16(namespaceUri, namespaceUri.size()-prefixSize, prefixSize)).string());
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (outIsPublic) *outIsPublic = isPublic;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return String16(namespaceUri, namespaceUri.size()-prefixSize, prefixSize);
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7815fe2cb73b0770316db302f6502f568062d68e74Kenny Rootstatus_t hasSubstitutionErrors(const char* fileName,
7915fe2cb73b0770316db302f6502f568062d68e74Kenny Root                               ResXMLTree* inXml,
8015fe2cb73b0770316db302f6502f568062d68e74Kenny Root                               String16 str16)
8115fe2cb73b0770316db302f6502f568062d68e74Kenny Root{
8215fe2cb73b0770316db302f6502f568062d68e74Kenny Root    const char16_t* str = str16.string();
8315fe2cb73b0770316db302f6502f568062d68e74Kenny Root    const char16_t* p = str;
8415fe2cb73b0770316db302f6502f568062d68e74Kenny Root    const char16_t* end = str + str16.size();
8515fe2cb73b0770316db302f6502f568062d68e74Kenny Root
8615fe2cb73b0770316db302f6502f568062d68e74Kenny Root    bool nonpositional = false;
8715fe2cb73b0770316db302f6502f568062d68e74Kenny Root    int argCount = 0;
8815fe2cb73b0770316db302f6502f568062d68e74Kenny Root
8915fe2cb73b0770316db302f6502f568062d68e74Kenny Root    while (p < end) {
9015fe2cb73b0770316db302f6502f568062d68e74Kenny Root        /*
9115fe2cb73b0770316db302f6502f568062d68e74Kenny Root         * Look for the start of a Java-style substitution sequence.
9215fe2cb73b0770316db302f6502f568062d68e74Kenny Root         */
9315fe2cb73b0770316db302f6502f568062d68e74Kenny Root        if (*p == '%' && p + 1 < end) {
9415fe2cb73b0770316db302f6502f568062d68e74Kenny Root            p++;
9515fe2cb73b0770316db302f6502f568062d68e74Kenny Root
9615fe2cb73b0770316db302f6502f568062d68e74Kenny Root            // A literal percent sign represented by %%
9715fe2cb73b0770316db302f6502f568062d68e74Kenny Root            if (*p == '%') {
9815fe2cb73b0770316db302f6502f568062d68e74Kenny Root                p++;
9915fe2cb73b0770316db302f6502f568062d68e74Kenny Root                continue;
10015fe2cb73b0770316db302f6502f568062d68e74Kenny Root            }
10115fe2cb73b0770316db302f6502f568062d68e74Kenny Root
10215fe2cb73b0770316db302f6502f568062d68e74Kenny Root            argCount++;
10315fe2cb73b0770316db302f6502f568062d68e74Kenny Root
10415fe2cb73b0770316db302f6502f568062d68e74Kenny Root            if (*p >= '0' && *p <= '9') {
10515fe2cb73b0770316db302f6502f568062d68e74Kenny Root                do {
10615fe2cb73b0770316db302f6502f568062d68e74Kenny Root                    p++;
10715fe2cb73b0770316db302f6502f568062d68e74Kenny Root                } while (*p >= '0' && *p <= '9');
10815fe2cb73b0770316db302f6502f568062d68e74Kenny Root                if (*p != '$') {
10915fe2cb73b0770316db302f6502f568062d68e74Kenny Root                    // This must be a size specification instead of position.
11015fe2cb73b0770316db302f6502f568062d68e74Kenny Root                    nonpositional = true;
11115fe2cb73b0770316db302f6502f568062d68e74Kenny Root                }
11215fe2cb73b0770316db302f6502f568062d68e74Kenny Root            } else if (*p == '<') {
11315fe2cb73b0770316db302f6502f568062d68e74Kenny Root                // Reusing last argument; bad idea since it can be re-arranged.
11415fe2cb73b0770316db302f6502f568062d68e74Kenny Root                nonpositional = true;
11515fe2cb73b0770316db302f6502f568062d68e74Kenny Root                p++;
11615fe2cb73b0770316db302f6502f568062d68e74Kenny Root
11715fe2cb73b0770316db302f6502f568062d68e74Kenny Root                // Optionally '$' can be specified at the end.
11815fe2cb73b0770316db302f6502f568062d68e74Kenny Root                if (p < end && *p == '$') {
11915fe2cb73b0770316db302f6502f568062d68e74Kenny Root                    p++;
12015fe2cb73b0770316db302f6502f568062d68e74Kenny Root                }
12115fe2cb73b0770316db302f6502f568062d68e74Kenny Root            } else {
12215fe2cb73b0770316db302f6502f568062d68e74Kenny Root                nonpositional = true;
12315fe2cb73b0770316db302f6502f568062d68e74Kenny Root            }
12415fe2cb73b0770316db302f6502f568062d68e74Kenny Root
12515fe2cb73b0770316db302f6502f568062d68e74Kenny Root            // Ignore flags and widths
12615fe2cb73b0770316db302f6502f568062d68e74Kenny Root            while (p < end && (*p == '-' ||
12715fe2cb73b0770316db302f6502f568062d68e74Kenny Root                    *p == '#' ||
12815fe2cb73b0770316db302f6502f568062d68e74Kenny Root                    *p == '+' ||
12915fe2cb73b0770316db302f6502f568062d68e74Kenny Root                    *p == ' ' ||
13015fe2cb73b0770316db302f6502f568062d68e74Kenny Root                    *p == ',' ||
13115fe2cb73b0770316db302f6502f568062d68e74Kenny Root                    *p == '(' ||
13215fe2cb73b0770316db302f6502f568062d68e74Kenny Root                    (*p >= '0' && *p <= '9'))) {
13315fe2cb73b0770316db302f6502f568062d68e74Kenny Root                p++;
13415fe2cb73b0770316db302f6502f568062d68e74Kenny Root            }
13515fe2cb73b0770316db302f6502f568062d68e74Kenny Root
13615fe2cb73b0770316db302f6502f568062d68e74Kenny Root            /*
13715fe2cb73b0770316db302f6502f568062d68e74Kenny Root             * This is a shortcut to detect strings that are going to Time.format()
13815fe2cb73b0770316db302f6502f568062d68e74Kenny Root             * instead of String.format()
13915fe2cb73b0770316db302f6502f568062d68e74Kenny Root             *
14015fe2cb73b0770316db302f6502f568062d68e74Kenny Root             * Comparison of String.format() and Time.format() args:
14115fe2cb73b0770316db302f6502f568062d68e74Kenny Root             *
14215fe2cb73b0770316db302f6502f568062d68e74Kenny Root             * String: ABC E GH  ST X abcdefgh  nost x
14315fe2cb73b0770316db302f6502f568062d68e74Kenny Root             *   Time:    DEFGHKMS W Za  d   hkm  s w yz
14415fe2cb73b0770316db302f6502f568062d68e74Kenny Root             *
14515fe2cb73b0770316db302f6502f568062d68e74Kenny Root             * Therefore we know it's definitely Time if we have:
14615fe2cb73b0770316db302f6502f568062d68e74Kenny Root             *     DFKMWZkmwyz
14715fe2cb73b0770316db302f6502f568062d68e74Kenny Root             */
14815fe2cb73b0770316db302f6502f568062d68e74Kenny Root            if (p < end) {
14915fe2cb73b0770316db302f6502f568062d68e74Kenny Root                switch (*p) {
15015fe2cb73b0770316db302f6502f568062d68e74Kenny Root                case 'D':
15115fe2cb73b0770316db302f6502f568062d68e74Kenny Root                case 'F':
15215fe2cb73b0770316db302f6502f568062d68e74Kenny Root                case 'K':
15315fe2cb73b0770316db302f6502f568062d68e74Kenny Root                case 'M':
15415fe2cb73b0770316db302f6502f568062d68e74Kenny Root                case 'W':
15515fe2cb73b0770316db302f6502f568062d68e74Kenny Root                case 'Z':
15615fe2cb73b0770316db302f6502f568062d68e74Kenny Root                case 'k':
15715fe2cb73b0770316db302f6502f568062d68e74Kenny Root                case 'm':
15815fe2cb73b0770316db302f6502f568062d68e74Kenny Root                case 'w':
15915fe2cb73b0770316db302f6502f568062d68e74Kenny Root                case 'y':
16015fe2cb73b0770316db302f6502f568062d68e74Kenny Root                case 'z':
16115fe2cb73b0770316db302f6502f568062d68e74Kenny Root                    return NO_ERROR;
16215fe2cb73b0770316db302f6502f568062d68e74Kenny Root                }
16315fe2cb73b0770316db302f6502f568062d68e74Kenny Root            }
16415fe2cb73b0770316db302f6502f568062d68e74Kenny Root        }
16515fe2cb73b0770316db302f6502f568062d68e74Kenny Root
16615fe2cb73b0770316db302f6502f568062d68e74Kenny Root        p++;
16715fe2cb73b0770316db302f6502f568062d68e74Kenny Root    }
16815fe2cb73b0770316db302f6502f568062d68e74Kenny Root
16915fe2cb73b0770316db302f6502f568062d68e74Kenny Root    /*
17015fe2cb73b0770316db302f6502f568062d68e74Kenny Root     * If we have more than one substitution in this string and any of them
17115fe2cb73b0770316db302f6502f568062d68e74Kenny Root     * are not in positional form, give the user an error.
17215fe2cb73b0770316db302f6502f568062d68e74Kenny Root     */
17315fe2cb73b0770316db302f6502f568062d68e74Kenny Root    if (argCount > 1 && nonpositional) {
17415fe2cb73b0770316db302f6502f568062d68e74Kenny Root        SourcePos(String8(fileName), inXml->getLineNumber()).error(
17515fe2cb73b0770316db302f6502f568062d68e74Kenny Root                "Multiple substitutions specified in non-positional format; "
17698ee11ddb7996b332d5e31f8bdff69631c8d3725Eric Fischer                "did you mean to add the formatted=\"false\" attribute?\n");
17715fe2cb73b0770316db302f6502f568062d68e74Kenny Root        return NOT_ENOUGH_DATA;
17815fe2cb73b0770316db302f6502f568062d68e74Kenny Root    }
17915fe2cb73b0770316db302f6502f568062d68e74Kenny Root
18015fe2cb73b0770316db302f6502f568062d68e74Kenny Root    return NO_ERROR;
18115fe2cb73b0770316db302f6502f568062d68e74Kenny Root}
18215fe2cb73b0770316db302f6502f568062d68e74Kenny Root
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t parseStyledString(Bundle* bundle,
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           const char* fileName,
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           ResXMLTree* inXml,
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           const String16& endTag,
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           String16* outString,
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           Vector<StringPool::entry_style_span>* outSpans,
18915fe2cb73b0770316db302f6502f568062d68e74Kenny Root                           bool isFormatted,
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           bool pseudolocalize)
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Vector<StringPool::entry_style_span> spanStack;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String16 curString;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String16 rawString;
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* errorMsg;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int xliffDepth = 0;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool firstTime = true;
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t len;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResXMLTree::event_code_t code;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while ((code=inXml->next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (code == ResXMLTree::TEXT) {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String16 text(inXml->getText(&len));
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (firstTime && text.size() > 0) {
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                firstTime = false;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (text.string()[0] == '@') {
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // If this is a resource reference, don't do the pseudoloc.
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pseudolocalize = false;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (xliffDepth == 0 && pseudolocalize) {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                std::string orig(String8(text).string());
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                std::string pseudo = pseudolocalize_string(orig);
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curString.append(String16(String8(pseudo.c_str())));
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
21715fe2cb73b0770316db302f6502f568062d68e74Kenny Root                if (isFormatted && hasSubstitutionErrors(fileName, inXml, text) != NO_ERROR) {
21815fe2cb73b0770316db302f6502f568062d68e74Kenny Root                    return UNKNOWN_ERROR;
21915fe2cb73b0770316db302f6502f568062d68e74Kenny Root                } else {
22015fe2cb73b0770316db302f6502f568062d68e74Kenny Root                    curString.append(text);
22115fe2cb73b0770316db302f6502f568062d68e74Kenny Root                }
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (code == ResXMLTree::START_TAG) {
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const String16 element16(inXml->getElementName(&len));
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const String8 element8(element16);
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t nslen;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const uint16_t* ns = inXml->getElementNamespace(&nslen);
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ns == NULL) {
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ns = (const uint16_t*)"\0\0";
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                nslen = 0;
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const String8 nspace(String16(ns, nslen));
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (nspace == XLIFF_XMLNS) {
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const int N = sizeof(ALLOWED_XLIFF_ELEMENTS)/sizeof(ALLOWED_XLIFF_ELEMENTS[0]);
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i=0; i<N; i++) {
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (element8 == ALLOWED_XLIFF_ELEMENTS[i]) {
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        xliffDepth++;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // in this case, treat it like it was just text, in other words, do nothing
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // here and silently drop this element
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto moveon;
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                {
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SourcePos(String8(fileName), inXml->getLineNumber()).error(
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            "Found unsupported XLIFF tag <%s>\n",
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            element8.string());
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return UNKNOWN_ERROR;
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectmoveon:
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outSpans == NULL) {
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                SourcePos(String8(fileName), inXml->getLineNumber()).error(
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "Found style tag <%s> where styles are not allowed\n", element8.string());
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return UNKNOWN_ERROR;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!ResTable::collectString(outString, curString.string(),
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                         curString.size(), false, &errorMsg, true)) {
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                SourcePos(String8(fileName), inXml->getLineNumber()).error("%s (in %s)\n",
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        errorMsg, String8(curString).string());
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return UNKNOWN_ERROR;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rawString.append(curString);
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curString = String16();
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            StringPool::entry_style_span span;
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            span.name = element16;
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (size_t ai=0; ai<inXml->getAttributeCount(); ai++) {
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                span.name.append(String16(";"));
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const char16_t* str = inXml->getAttributeName(ai, &len);
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                span.name.append(str, len);
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                span.name.append(String16("="));
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                str = inXml->getAttributeStringValue(ai, &len);
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                span.name.append(str, len);
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //printf("Span: %s\n", String8(span.name).string());
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            span.span.firstChar = span.span.lastChar = outString->size();
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            spanStack.push(span);
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (code == ResXMLTree::END_TAG) {
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t nslen;
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const uint16_t* ns = inXml->getElementNamespace(&nslen);
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ns == NULL) {
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ns = (const uint16_t*)"\0\0";
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                nslen = 0;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const String8 nspace(String16(ns, nslen));
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (nspace == XLIFF_XMLNS) {
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                xliffDepth--;
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!ResTable::collectString(outString, curString.string(),
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                         curString.size(), false, &errorMsg, true)) {
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                SourcePos(String8(fileName), inXml->getLineNumber()).error("%s (in %s)\n",
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        errorMsg, String8(curString).string());
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return UNKNOWN_ERROR;
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rawString.append(curString);
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curString = String16();
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (spanStack.size() == 0) {
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (strcmp16(inXml->getElementName(&len), endTag.string()) != 0) {
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SourcePos(String8(fileName), inXml->getLineNumber()).error(
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            "Found tag %s where <%s> close is expected\n",
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            String8(inXml->getElementName(&len)).string(),
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            String8(endTag).string());
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return UNKNOWN_ERROR;
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            StringPool::entry_style_span span = spanStack.top();
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String16 spanTag;
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ssize_t semi = span.name.findFirst(';');
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (semi >= 0) {
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                spanTag.setTo(span.name.string(), semi);
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                spanTag.setTo(span.name);
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (strcmp16(inXml->getElementName(&len), spanTag.string()) != 0) {
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                SourcePos(String8(fileName), inXml->getLineNumber()).error(
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "Found close tag %s where close tag %s is expected\n",
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        String8(inXml->getElementName(&len)).string(),
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        String8(spanTag).string());
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return UNKNOWN_ERROR;
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool empty = true;
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outString->size() > 0) {
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                span.span.lastChar = outString->size()-1;
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (span.span.lastChar >= span.span.firstChar) {
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    empty = false;
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    outSpans->add(span);
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            spanStack.pop();
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339c87d25215c842cea370c6a86ce67585fa8da4900Eric Fischer            /*
340c87d25215c842cea370c6a86ce67585fa8da4900Eric Fischer             * This warning seems to be just an irritation to most people,
341c87d25215c842cea370c6a86ce67585fa8da4900Eric Fischer             * since it is typically introduced by translators who then never
342c87d25215c842cea370c6a86ce67585fa8da4900Eric Fischer             * see the warning.
343c87d25215c842cea370c6a86ce67585fa8da4900Eric Fischer             */
344c87d25215c842cea370c6a86ce67585fa8da4900Eric Fischer            if (0 && empty) {
345dd931864209eac0b4182d7a0d1ca965fcc3b8c03Marco Nelissen                fprintf(stderr, "%s:%d: warning: empty '%s' span found in text '%s'\n",
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fileName, inXml->getLineNumber(),
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        String8(spanTag).string(), String8(*outString).string());
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (code == ResXMLTree::START_NAMESPACE) {
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // nothing
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (code == ResXMLTree::BAD_DOCUMENT) {
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SourcePos(String8(fileName), inXml->getLineNumber()).error(
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "Error parsing XML\n");
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (outSpans != NULL && outSpans->size() > 0) {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (curString.size() > 0) {
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!ResTable::collectString(outString, curString.string(),
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                         curString.size(), false, &errorMsg, true)) {
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                SourcePos(String8(fileName), inXml->getLineNumber()).error(
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "%s (in %s)\n",
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        errorMsg, String8(curString).string());
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return UNKNOWN_ERROR;
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // There is no style information, so string processing will happen
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // later as part of the overall type conversion.  Return to the
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // client the raw unprocessed text.
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rawString.append(curString);
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        outString->setTo(rawString);
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct namespace_entry {
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 prefix;
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 uri;
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic String8 make_prefix(int depth)
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 prefix;
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int i;
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i=0; i<depth; i++) {
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        prefix.append("  ");
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return prefix;
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic String8 build_namespace(const Vector<namespace_entry>& namespaces,
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const uint16_t* ns)
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 str;
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ns != NULL) {
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        str = String8(ns);
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const size_t N = namespaces.size();
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (size_t i=0; i<N; i++) {
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const namespace_entry& ne = namespaces.itemAt(i);
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ne.uri == str) {
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                str = ne.prefix;
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        str.append(":");
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return str;
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid printXMLBlock(ResXMLTree* block)
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    block->restart();
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Vector<namespace_entry> namespaces;
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResXMLTree::event_code_t code;
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int depth = 0;
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while ((code=block->next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String8 prefix = make_prefix(depth);
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int i;
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (code == ResXMLTree::START_TAG) {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t len;
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const uint16_t* ns16 = block->getElementNamespace(&len);
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 elemNs = build_namespace(namespaces, ns16);
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const uint16_t* com16 = block->getComment(&len);
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (com16) {
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf("%s <!-- %s -->\n", prefix.string(), String8(com16).string());
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("%sE: %s%s (line=%d)\n", prefix.string(), elemNs.string(),
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   String8(block->getElementName(&len)).string(),
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   block->getLineNumber());
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = block->getAttributeCount();
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            depth++;
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            prefix = make_prefix(depth);
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (i=0; i<N; i++) {
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                uint32_t res = block->getAttributeNameResID(i);
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ns16 = block->getAttributeNamespace(i, &len);
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String8 ns = build_namespace(namespaces, ns16);
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String8 name(block->getAttributeName(i, &len));
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf("%sA: ", prefix.string());
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (res) {
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("%s%s(0x%08x)", ns.string(), name.string(), res);
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("%s%s", ns.string(), name.string());
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Res_value value;
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                block->getAttributeValue(i, &value);
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (value.dataType == Res_value::TYPE_NULL) {
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("=(null)");
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (value.dataType == Res_value::TYPE_REFERENCE) {
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("=@0x%x", (int)value.data);
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (value.dataType == Res_value::TYPE_ATTRIBUTE) {
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("=?0x%x", (int)value.data);
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (value.dataType == Res_value::TYPE_STRING) {
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("=\"%s\"",
4619872bf4a2d4ae1e7ded170c8e74d400fe6be9bfbShachar Shemesh                            ResTable::normalizeForOutput(String8(block->getAttributeStringValue(i,
4629872bf4a2d4ae1e7ded170c8e74d400fe6be9bfbShachar Shemesh                                        &len)).string()).string());
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("=(type 0x%x)0x%x", (int)value.dataType, (int)value.data);
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const char16_t* val = block->getAttributeStringValue(i, &len);
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (val != NULL) {
4689872bf4a2d4ae1e7ded170c8e74d400fe6be9bfbShachar Shemesh                    printf(" (Raw: \"%s\")", ResTable::normalizeForOutput(String8(val).string()).
4699872bf4a2d4ae1e7ded170c8e74d400fe6be9bfbShachar Shemesh                            string());
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf("\n");
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (code == ResXMLTree::END_TAG) {
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            depth--;
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (code == ResXMLTree::START_NAMESPACE) {
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            namespace_entry ns;
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t len;
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const uint16_t* prefix16 = block->getNamespacePrefix(&len);
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (prefix16) {
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ns.prefix = String8(prefix16);
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ns.prefix = "<DEF>";
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ns.uri = String8(block->getNamespaceUri(&len));
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            namespaces.push(ns);
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("%sN: %s=%s\n", prefix.string(), ns.prefix.string(),
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ns.uri.string());
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            depth++;
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (code == ResXMLTree::END_NAMESPACE) {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            depth--;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const namespace_entry& ns = namespaces.top();
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t len;
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const uint16_t* prefix16 = block->getNamespacePrefix(&len);
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 pr;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (prefix16) {
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pr = String8(prefix16);
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pr = "<DEF>";
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ns.prefix != pr) {
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                prefix = make_prefix(depth);
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf("%s*** BAD END NS PREFIX: found=%s, expected=%s\n",
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        prefix.string(), pr.string(), ns.prefix.string());
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 uri = String8(block->getNamespaceUri(&len));
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ns.uri != uri) {
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                prefix = make_prefix(depth);
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf("%s *** BAD END NS URI: found=%s, expected=%s\n",
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        prefix.string(), uri.string(), ns.uri.string());
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            namespaces.pop();
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (code == ResXMLTree::TEXT) {
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t len;
514429dad687bcb5f00587e8b91b3a614502907aaa1Shachar Shemesh            printf("%sC: \"%s\"\n", prefix.string(),
515429dad687bcb5f00587e8b91b3a614502907aaa1Shachar Shemesh                    ResTable::normalizeForOutput(String8(block->getText(&len)).string()).string());
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    block->restart();
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t parseXMLResource(const sp<AaptFile>& file, ResXMLTree* outTree,
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                          bool stripAll, bool keepComments,
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                          const char** cDataTags)
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<XMLNode> root = XMLNode::parse(file);
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (root == NULL) {
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    root->removeWhitespace(stripAll, cDataTags);
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY(printf("Input XML from %s:\n", (const char*)file->getPrintableSource()));
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY(root->print());
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<AaptFile> rsc = new AaptFile(String8(), AaptGroupEntry(), String8());
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t err = root->flatten(rsc, !keepComments, false);
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err != NO_ERROR) {
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return err;
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    err = outTree->setTo(rsc->getData(), rsc->getSize(), true);
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err != NO_ERROR) {
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return err;
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY(printf("Output XML:\n"));
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY(printXMLBlock(outTree));
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsp<XMLNode> XMLNode::parse(const sp<AaptFile>& file)
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char buf[16384];
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int fd = open(file->getSourceFile().string(), O_RDONLY | O_BINARY);
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fd < 0) {
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SourcePos(file->getSourceFile(), -1).error("Unable to open file for read: %s",
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                strerror(errno));
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    XML_Parser parser = XML_ParserCreateNS(NULL, 1);
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ParseState state;
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    state.filename = file->getPrintableSource();
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    state.parser = parser;
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    XML_SetUserData(parser, &state);
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    XML_SetElementHandler(parser, startElement, endElement);
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    XML_SetNamespaceDeclHandler(parser, startNamespace, endNamespace);
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    XML_SetCharacterDataHandler(parser, characterData);
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    XML_SetCommentHandler(parser, commentData);
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t len;
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool done;
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    do {
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        len = read(fd, buf, sizeof(buf));
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        done = len < (ssize_t)sizeof(buf);
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (len < 0) {
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SourcePos(file->getSourceFile(), -1).error("Error reading file: %s\n", strerror(errno));
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            close(fd);
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return NULL;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) {
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SourcePos(file->getSourceFile(), (int)XML_GetCurrentLineNumber(parser)).error(
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "Error parsing XML: %s\n", XML_ErrorString(XML_GetErrorCode(parser)));
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            close(fd);
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return NULL;
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } while (!done);
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    XML_ParserFree(parser);
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (state.root == NULL) {
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SourcePos(file->getSourceFile(), -1).error("No XML data generated when parsing");
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    close(fd);
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return state.root;
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectXMLNode::XMLNode(const String8& filename, const String16& s1, const String16& s2, bool isNamespace)
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    : mNextAttributeIndex(0x80000000)
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    , mFilename(filename)
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    , mStartLineNumber(0)
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    , mEndLineNumber(0)
60119138468caf7050d482dc15f35a344eab11bb756Kenny Root    , mUTF8(false)
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (isNamespace) {
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNamespacePrefix = s1;
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNamespaceUri = s2;
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNamespaceUri = s1;
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mElementName = s2;
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectXMLNode::XMLNode(const String8& filename)
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    : mFilename(filename)
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6156a1fadea851db236331b3dfe1f3c1e482556057fMarco Nelissen    memset(&mCharsValue, 0, sizeof(mCharsValue));
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectXMLNode::type XMLNode::getType() const
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mElementName.size() != 0) {
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return TYPE_ELEMENT;
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mNamespaceUri.size() != 0) {
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return TYPE_NAMESPACE;
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return TYPE_CDATA;
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst String16& XMLNode::getNamespacePrefix() const
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mNamespacePrefix;
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst String16& XMLNode::getNamespaceUri() const
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mNamespaceUri;
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst String16& XMLNode::getElementNamespace() const
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mNamespaceUri;
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst String16& XMLNode::getElementName() const
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mElementName;
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst Vector<sp<XMLNode> >& XMLNode::getChildren() const
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mChildren;
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
65462da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackbornconst String8& XMLNode::getFilename() const
65562da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn{
65662da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    return mFilename;
65762da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn}
65862da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst Vector<XMLNode::attribute_entry>&
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    XMLNode::getAttributes() const
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mAttributes;
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
66562da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackbornconst XMLNode::attribute_entry* XMLNode::getAttribute(const String16& ns,
66662da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        const String16& name) const
66762da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn{
66862da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    for (size_t i=0; i<mAttributes.size(); i++) {
66962da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        const attribute_entry& ae(mAttributes.itemAt(i));
67062da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        if (ae.ns == ns && ae.name == name) {
67162da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn            return &ae;
67262da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        }
67362da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    }
67462da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn
67562da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    return NULL;
67662da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn}
67762da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn
6782fee0ed6eb99b211efa06f095a41268a2021214aJeff HamiltonXMLNode::attribute_entry* XMLNode::editAttribute(const String16& ns,
6792fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        const String16& name)
6802fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton{
6812fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton    for (size_t i=0; i<mAttributes.size(); i++) {
6822fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        attribute_entry * ae = &mAttributes.editItemAt(i);
6832fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        if (ae->ns == ns && ae->name == name) {
6842fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton            return ae;
6852fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        }
6862fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton    }
6872fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton
6882fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton    return NULL;
6892fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton}
6902fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst String16& XMLNode::getCData() const
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mChars;
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst String16& XMLNode::getComment() const
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mComment;
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint32_t XMLNode::getStartLineNumber() const
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mStartLineNumber;
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint32_t XMLNode::getEndLineNumber() const
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mEndLineNumber;
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
71162da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackbornsp<XMLNode> XMLNode::searchElement(const String16& tagNamespace, const String16& tagName)
71262da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn{
71362da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    if (getType() == XMLNode::TYPE_ELEMENT
71462da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn            && mNamespaceUri == tagNamespace
71562da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn            && mElementName == tagName) {
71662da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        return this;
71762da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    }
71862da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn
71962da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    for (size_t i=0; i<mChildren.size(); i++) {
72062da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        sp<XMLNode> found = mChildren.itemAt(i)->searchElement(tagNamespace, tagName);
72162da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        if (found != NULL) {
72262da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn            return found;
72362da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        }
72462da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    }
72562da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn
72662da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    return NULL;
72762da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn}
72862da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn
72962da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackbornsp<XMLNode> XMLNode::getChildElement(const String16& tagNamespace, const String16& tagName)
73062da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn{
73162da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    for (size_t i=0; i<mChildren.size(); i++) {
73262da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        sp<XMLNode> child = mChildren.itemAt(i);
73362da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        if (child->getType() == XMLNode::TYPE_ELEMENT
73462da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn                && child->mNamespaceUri == tagNamespace
73562da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn                && child->mElementName == tagName) {
73662da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn            return child;
73762da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        }
73862da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    }
73962da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn
74062da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    return NULL;
74162da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn}
74262da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t XMLNode::addChild(const sp<XMLNode>& child)
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (getType() == TYPE_CDATA) {
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SourcePos(mFilename, child->getStartLineNumber()).error("Child to CDATA node.");
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //printf("Adding child %p to parent %p\n", child.get(), this);
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mChildren.add(child);
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
75462da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackbornstatus_t XMLNode::insertChildAt(const sp<XMLNode>& child, size_t index)
75562da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn{
75662da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    if (getType() == TYPE_CDATA) {
75762da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        SourcePos(mFilename, child->getStartLineNumber()).error("Child to CDATA node.");
75862da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        return UNKNOWN_ERROR;
75962da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    }
76062da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    //printf("Adding child %p to parent %p\n", child.get(), this);
76162da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    mChildren.insertAt(child, index);
76262da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    return NO_ERROR;
76362da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn}
76462da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t XMLNode::addAttribute(const String16& ns, const String16& name,
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                               const String16& value)
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (getType() == TYPE_CDATA) {
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SourcePos(mFilename, getStartLineNumber()).error("Child to CDATA node.");
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
772f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet
773f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet    if (ns != RESOURCES_TOOLS_NAMESPACE) {
774f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        attribute_entry e;
775f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        e.index = mNextAttributeIndex++;
776f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        e.ns = ns;
777f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        e.name = name;
778f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        e.string = value;
779f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        mAttributes.add(e);
780f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        mAttributeOrder.add(e.index, mAttributes.size()-1);
781f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet    }
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid XMLNode::setAttributeResID(size_t attrIdx, uint32_t resId)
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    attribute_entry& e = mAttributes.editItemAt(attrIdx);
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (e.nameResId) {
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAttributeOrder.removeItem(e.nameResId);
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAttributeOrder.removeItem(e.index);
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY(printf("Elem %s %s=\"%s\": set res id = 0x%08x\n",
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8(getElementName()).string(),
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8(mAttributes.itemAt(attrIdx).name).string(),
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8(mAttributes.itemAt(attrIdx).string).string(),
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resId));
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mAttributes.editItemAt(attrIdx).nameResId = resId;
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mAttributeOrder.add(resId, attrIdx);
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t XMLNode::appendChars(const String16& chars)
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (getType() != TYPE_CDATA) {
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SourcePos(mFilename, getStartLineNumber()).error("Adding characters to element node.");
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mChars.append(chars);
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t XMLNode::appendComment(const String16& comment)
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mComment.size() > 0) {
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mComment.append(String16("\n"));
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mComment.append(comment);
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid XMLNode::setStartLineNumber(int32_t line)
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mStartLineNumber = line;
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid XMLNode::setEndLineNumber(int32_t line)
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mEndLineNumber = line;
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid XMLNode::removeWhitespace(bool stripAll, const char** cDataTags)
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //printf("Removing whitespace in %s\n", String8(mElementName).string());
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t N = mChildren.size();
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (cDataTags) {
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String8 tag(mElementName);
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char** p = cDataTags;
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (*p) {
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (tag == *p) {
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stripAll = false;
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<N; i++) {
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sp<XMLNode> node = mChildren.itemAt(i);
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (node->getType() == TYPE_CDATA) {
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This is a CDATA node...
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const char16_t* p = node->mChars.string();
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (*p != 0 && *p < 128 && isspace(*p)) {
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p++;
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //printf("Space ends at %d in \"%s\"\n",
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //       (int)(p-node->mChars.string()),
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //       String8(node->mChars).string());
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (*p == 0) {
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (stripAll) {
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Remove this node!
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mChildren.removeAt(i);
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    N--;
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i--;
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    node->mChars = String16(" ");
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Compact leading/trailing whitespace.
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const char16_t* e = node->mChars.string()+node->mChars.size()-1;
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while (e > p && *e < 128 && isspace(*e)) {
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    e--;
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (p > node->mChars.string()) {
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    p--;
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (e < (node->mChars.string()+node->mChars.size()-1)) {
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    e++;
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (p > node->mChars.string() ||
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    e < (node->mChars.string()+node->mChars.size()-1)) {
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String16 tmp(p, e-p+1);
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    node->mChars = tmp;
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            node->removeWhitespace(stripAll, cDataTags);
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t XMLNode::parseValues(const sp<AaptAssets>& assets,
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                              ResourceTable* table)
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool hasErrors = false;
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (getType() == TYPE_ELEMENT) {
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const size_t N = mAttributes.size();
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String16 defPackage(assets->getPackage());
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (size_t i=0; i<N; i++) {
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attribute_entry& e = mAttributes.editItemAt(i);
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            AccessorCookie ac(SourcePos(mFilename, getStartLineNumber()), String8(e.name),
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8(e.string));
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            table->setCurrentXmlPos(SourcePos(mFilename, getStartLineNumber()));
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!assets->getIncludedResources()
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    .stringToValue(&e.value, &e.string,
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                  e.string.string(), e.string.size(), true, true,
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                  e.nameResId, NULL, &defPackage, table, &ac)) {
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                hasErrors = true;
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NOISY(printf("Attr %s: type=0x%x, str=%s\n",
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   String8(e.name).string(), e.value.dataType,
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   String8(e.string).string()));
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t N = mChildren.size();
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<N; i++) {
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        status_t err = mChildren.itemAt(i)->parseValues(assets, table);
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err != NO_ERROR) {
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            hasErrors = true;
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t XMLNode::assignResourceIds(const sp<AaptAssets>& assets,
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    const ResourceTable* table)
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool hasErrors = false;
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (getType() == TYPE_ELEMENT) {
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String16 attr("attr");
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* errorMsg;
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const size_t N = mAttributes.size();
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (size_t i=0; i<N; i++) {
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const attribute_entry& e = mAttributes.itemAt(i);
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (e.ns.size() <= 0) continue;
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool nsIsPublic;
936e348909c1966c3d192841cc131a32be6ed90da18inazaruk            String16 pkg(getNamespaceResourcePackage(String16(assets->getPackage()), e.ns, &nsIsPublic));
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NOISY(printf("Elem %s %s=\"%s\": namespace(%s) %s ===> %s\n",
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8(getElementName()).string(),
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8(e.name).string(),
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8(e.string).string(),
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8(e.ns).string(),
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    (nsIsPublic) ? "public" : "private",
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8(pkg).string()));
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pkg.size() <= 0) continue;
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            uint32_t res = table != NULL
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ? table->getResId(e.name, &attr, &pkg, &errorMsg, nsIsPublic)
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                : assets->getIncludedResources().
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    identifierForName(e.name.string(), e.name.size(),
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                      attr.string(), attr.size(),
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                      pkg.string(), pkg.size());
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (res != 0) {
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                NOISY(printf("XML attribute name %s: resid=0x%08x\n",
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             String8(e.name).string(), res));
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                setAttributeResID(i, res);
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                SourcePos(mFilename, getStartLineNumber()).error(
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "No resource identifier found for attribute '%s' in package '%s'\n",
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        String8(e.name).string(), String8(pkg).string());
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                hasErrors = true;
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t N = mChildren.size();
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<N; i++) {
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        status_t err = mChildren.itemAt(i)->assignResourceIds(assets, table);
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err < NO_ERROR) {
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            hasErrors = true;
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t XMLNode::flatten(const sp<AaptFile>& dest,
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool stripComments, bool stripRawValues) const
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
977345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown    StringPool strings(mUTF8);
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Vector<uint32_t> resids;
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // First collect just the strings for attribute names that have a
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // resource ID assigned to them.  This ensures that the resource ID
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // array is compact, and makes it easier to deal with attribute names
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // in different namespaces (and thus with different resource IDs).
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    collect_resid_strings(&strings, &resids);
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Next collect all remainibng strings.
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    collect_strings(&strings, &resids, stripComments, stripRawValues);
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0  // No longer compiles
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY(printf("Found strings:\n");
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const size_t N = strings.size();
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (size_t i=0; i<N; i++) {
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("%s\n", String8(strings.entryAt(i).string).string());
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    );
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<AaptFile> stringPool = strings.createStringBlock();
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY(aout << "String pool:"
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project          << HexDump(stringPool->getData(), stringPool->getSize()) << endl);
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResXMLTree_header header;
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    memset(&header, 0, sizeof(header));
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    header.header.type = htods(RES_XML_TYPE);
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    header.header.headerSize = htods(sizeof(header));
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t basePos = dest->getSize();
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dest->writeData(&header, sizeof(header));
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dest->writeData(stringPool->getData(), stringPool->getSize());
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // If we have resource IDs, write them.
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (resids.size() > 0) {
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const size_t resIdsPos = dest->getSize();
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const size_t resIdsSize =
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sizeof(ResChunk_header)+(sizeof(uint32_t)*resids.size());
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ResChunk_header* idsHeader = (ResChunk_header*)
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (((const uint8_t*)dest->editData(resIdsPos+resIdsSize))+resIdsPos);
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        idsHeader->type = htods(RES_XML_RESOURCE_MAP_TYPE);
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        idsHeader->headerSize = htods(sizeof(*idsHeader));
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        idsHeader->size = htodl(resIdsSize);
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t* ids = (uint32_t*)(idsHeader+1);
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (size_t i=0; i<resids.size(); i++) {
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            *ids++ = htodl(resids[i]);
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    flatten_node(strings, dest, stripComments, stripRawValues);
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void* data = dest->editData();
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResXMLTree_header* hd = (ResXMLTree_header*)(((uint8_t*)data)+basePos);
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t size = dest->getSize()-basePos;
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    hd->header.size = htodl(dest->getSize()-basePos);
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY(aout << "XML resource:"
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project          << HexDump(dest->getData(), dest->getSize()) << endl);
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #if PRINT_STRING_METRICS
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fprintf(stderr, "**** total xml size: %d / %d%% strings (in %s)\n",
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest->getSize(), (stringPool->getSize()*100)/dest->getSize(),
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest->getPath().string());
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #endif
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid XMLNode::print(int indent)
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 prefix;
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int i;
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i=0; i<indent; i++) {
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        prefix.append("  ");
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (getType() == TYPE_ELEMENT) {
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String8 elemNs(getNamespaceUri());
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (elemNs.size() > 0) {
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            elemNs.append(":");
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("%s E: %s%s", prefix.string(),
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               elemNs.string(), String8(getElementName()).string());
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int N = mAttributes.size();
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (i=0; i<N; i++) {
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ssize_t idx = mAttributeOrder.valueAt(i);
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (i == 0) {
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf(" / ");
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf(", ");
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const attribute_entry& attr = mAttributes.itemAt(idx);
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 attrNs(attr.ns);
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (attrNs.size() > 0) {
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                attrNs.append(":");
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (attr.nameResId) {
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf("%s%s(0x%08x)", attrNs.string(),
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       String8(attr.name).string(), attr.nameResId);
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf("%s%s", attrNs.string(), String8(attr.name).string());
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("=%s", String8(attr.string).string());
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("\n");
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (getType() == TYPE_NAMESPACE) {
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("%s N: %s=%s\n", prefix.string(),
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               getNamespacePrefix().size() > 0
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ? String8(getNamespacePrefix()).string() : "<DEF>",
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               String8(getNamespaceUri()).string());
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("%s C: \"%s\"\n", prefix.string(), String8(getCData()).string());
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int N = mChildren.size();
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i=0; i<N; i++) {
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mChildren.itemAt(i)->print(indent+1);
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void splitName(const char* name, String16* outNs, String16* outName)
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* p = name;
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (*p != 0 && *p != 1) {
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p++;
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (*p == 0) {
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *outNs = String16();
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *outName = String16(name);
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *outNs = String16(name, (p-name));
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *outName = String16(p+1);
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid XMLCALL
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectXMLNode::startNamespace(void *userData, const char *prefix, const char *uri)
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY_PARSE(printf("Start Namespace: %s %s\n", prefix, uri));
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ParseState* st = (ParseState*)userData;
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<XMLNode> node = XMLNode::newNamespace(st->filename,
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String16(prefix != NULL ? prefix : ""), String16(uri));
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    node->setStartLineNumber(XML_GetCurrentLineNumber(st->parser));
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (st->stack.size() > 0) {
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        st->stack.itemAt(st->stack.size()-1)->addChild(node);
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        st->root = node;
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    st->stack.push(node);
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid XMLCALL
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectXMLNode::startElement(void *userData, const char *name, const char **atts)
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY_PARSE(printf("Start Element: %s\n", name));
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ParseState* st = (ParseState*)userData;
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String16 ns16, name16;
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    splitName(name, &ns16, &name16);
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<XMLNode> node = XMLNode::newElement(st->filename, ns16, name16);
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    node->setStartLineNumber(XML_GetCurrentLineNumber(st->parser));
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (st->pendingComment.size() > 0) {
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node->appendComment(st->pendingComment);
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        st->pendingComment = String16();
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (st->stack.size() > 0) {
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        st->stack.itemAt(st->stack.size()-1)->addChild(node);
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        st->root = node;
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    st->stack.push(node);
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; atts[i]; i += 2) {
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        splitName(atts[i], &ns16, &name16);
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node->addAttribute(ns16, name16, String16(atts[i+1]));
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid XMLCALL
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectXMLNode::characterData(void *userData, const XML_Char *s, int len)
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY_PARSE(printf("CDATA: \"%s\"\n", String8(s, len).string()));
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ParseState* st = (ParseState*)userData;
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<XMLNode> node = NULL;
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (st->stack.size() == 0) {
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<XMLNode> parent = st->stack.itemAt(st->stack.size()-1);
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (parent != NULL && parent->getChildren().size() > 0) {
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node = parent->getChildren()[parent->getChildren().size()-1];
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (node->getType() != TYPE_CDATA) {
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Last node is not CDATA, need to make a new node.
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            node = NULL;
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (node == NULL) {
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node = XMLNode::newCData(st->filename);
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node->setStartLineNumber(XML_GetCurrentLineNumber(st->parser));
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        parent->addChild(node);
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    node->appendChars(String16(s, len));
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid XMLCALL
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectXMLNode::endElement(void *userData, const char *name)
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY_PARSE(printf("End Element: %s\n", name));
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ParseState* st = (ParseState*)userData;
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<XMLNode> node = st->stack.itemAt(st->stack.size()-1);
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    node->setEndLineNumber(XML_GetCurrentLineNumber(st->parser));
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (st->pendingComment.size() > 0) {
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node->appendComment(st->pendingComment);
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        st->pendingComment = String16();
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String16 ns16, name16;
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    splitName(name, &ns16, &name16);
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOG_ALWAYS_FATAL_IF(node->getElementNamespace() != ns16
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || node->getElementName() != name16,
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "Bad end element %s", name);
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    st->stack.pop();
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid XMLCALL
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectXMLNode::endNamespace(void *userData, const char *prefix)
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* nonNullPrefix = prefix != NULL ? prefix : "";
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY_PARSE(printf("End Namespace: %s\n", prefix));
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ParseState* st = (ParseState*)userData;
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<XMLNode> node = st->stack.itemAt(st->stack.size()-1);
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    node->setEndLineNumber(XML_GetCurrentLineNumber(st->parser));
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOG_ALWAYS_FATAL_IF(node->getNamespacePrefix() != String16(nonNullPrefix),
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "Bad end namespace %s", prefix);
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    st->stack.pop();
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid XMLCALL
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectXMLNode::commentData(void *userData, const char *comment)
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NOISY_PARSE(printf("Comment: %s\n", comment));
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ParseState* st = (ParseState*)userData;
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (st->pendingComment.size() > 0) {
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        st->pendingComment.append(String16("\n"));
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    st->pendingComment.append(String16(comment));
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t XMLNode::collect_strings(StringPool* dest, Vector<uint32_t>* outResIds,
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool stripComments, bool stripRawValues) const
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    collect_attr_strings(dest, outResIds, true);
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int i;
1229f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet    if (RESOURCES_TOOLS_NAMESPACE != mNamespaceUri) {
1230f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        if (mNamespacePrefix.size() > 0) {
1231f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            dest->add(mNamespacePrefix, true);
1232f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        }
1233f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        if (mNamespaceUri.size() > 0) {
1234f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            dest->add(mNamespaceUri, true);
1235f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        }
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mElementName.size() > 0) {
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest->add(mElementName, true);
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!stripComments && mComment.size() > 0) {
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest->add(mComment, true);
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int NA = mAttributes.size();
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i=0; i<NA; i++) {
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const attribute_entry& ae = mAttributes.itemAt(i);
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ae.ns.size() > 0) {
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dest->add(ae.ns, true);
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!stripRawValues || ae.needStringValue()) {
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dest->add(ae.string, true);
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ae.value.dataType == Res_value::TYPE_NULL
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || ae.value.dataType == Res_value::TYPE_STRING) {
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dest->add(ae.string, true);
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        */
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mElementName.size() == 0) {
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If not an element, include the CDATA, even if it is empty.
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest->add(mChars, true);
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int NC = mChildren.size();
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i=0; i<NC; i++) {
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mChildren.itemAt(i)->collect_strings(dest, outResIds,
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stripComments, stripRawValues);
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t XMLNode::collect_attr_strings(StringPool* outPool,
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Vector<uint32_t>* outResIds, bool allAttrs) const {
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int NA = mAttributes.size();
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i=0; i<NA; i++) {
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const attribute_entry& attr = mAttributes.itemAt(i);
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t id = attr.nameResId;
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id || allAttrs) {
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // See if we have already assigned this resource ID to a pooled
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // string...
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const Vector<size_t>* indices = outPool->offsetsForString(attr.name);
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ssize_t idx = -1;
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (indices != NULL) {
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const int NJ = indices->size();
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const size_t NR = outResIds->size();
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int j=0; j<NJ; j++) {
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size_t strIdx = indices->itemAt(j);
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (strIdx >= NR) {
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (id == 0) {
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // We don't need to assign a resource ID for this one.
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            idx = strIdx;
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            break;
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Just ignore strings that are out of range of
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // the currently assigned resource IDs...  we add
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // strings as we assign the first ID.
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (outResIds->itemAt(strIdx) == id) {
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        idx = strIdx;
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (idx < 0) {
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                idx = outPool->add(attr.name);
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                NOISY(printf("Adding attr %s (resid 0x%08x) to pool: idx=%d\n",
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        String8(attr.name).string(), id, idx));
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (id != 0) {
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    while ((ssize_t)outResIds->size() <= idx) {
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        outResIds->add(0);
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    outResIds->replaceAt(id, idx);
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attr.namePoolIdx = idx;
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NOISY(printf("String %s offset=0x%08x\n",
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         String8(attr.name).string(), idx));
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t XMLNode::collect_resid_strings(StringPool* outPool,
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Vector<uint32_t>* outResIds) const
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    collect_attr_strings(outPool, outResIds, false);
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int NC = mChildren.size();
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i=0; i<NC; i++) {
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mChildren.itemAt(i)->collect_resid_strings(outPool, outResIds);
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t XMLNode::flatten_node(const StringPool& strings, const sp<AaptFile>& dest,
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool stripComments, bool stripRawValues) const
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResXMLTree_node node;
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResXMLTree_cdataExt cdataExt;
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResXMLTree_namespaceExt namespaceExt;
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResXMLTree_attrExt attrExt;
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const void* extData = NULL;
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t extSize = 0;
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResXMLTree_attribute attr;
1354f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet    bool writeCurrentNode = true;
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t NA = mAttributes.size();
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const size_t NC = mChildren.size();
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t i;
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOG_ALWAYS_FATAL_IF(NA != mAttributeOrder.size(), "Attributes messed up!");
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const String16 id16("id");
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const String16 class16("class");
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const String16 style16("style");
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const type type = getType();
1367f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    memset(&node, 0, sizeof(node));
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    memset(&attr, 0, sizeof(attr));
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    node.header.headerSize = htods(sizeof(node));
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    node.lineNumber = htodl(getStartLineNumber());
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!stripComments) {
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node.comment.index = htodl(
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mComment.size() > 0 ? strings.offsetForString(mComment) : -1);
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //if (mComment.size() > 0) {
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //  printf("Flattening comment: %s\n", String8(mComment).string());
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //}
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node.comment.index = htodl((uint32_t)-1);
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (type == TYPE_ELEMENT) {
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node.header.type = htods(RES_XML_START_ELEMENT_TYPE);
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        extData = &attrExt;
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        extSize = sizeof(attrExt);
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memset(&attrExt, 0, sizeof(attrExt));
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNamespaceUri.size() > 0) {
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attrExt.ns.index = htodl(strings.offsetForString(mNamespaceUri));
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attrExt.ns.index = htodl((uint32_t)-1);
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        attrExt.name.index = htodl(strings.offsetForString(mElementName));
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        attrExt.attributeStart = htods(sizeof(attrExt));
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        attrExt.attributeSize = htods(sizeof(attr));
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        attrExt.attributeCount = htods(NA);
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        attrExt.idIndex = htods(0);
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        attrExt.classIndex = htods(0);
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        attrExt.styleIndex = htods(0);
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (i=0; i<NA; i++) {
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ssize_t idx = mAttributeOrder.valueAt(i);
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const attribute_entry& ae = mAttributes.itemAt(idx);
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ae.ns.size() == 0) {
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (ae.name == id16) {
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    attrExt.idIndex = htods(i+1);
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (ae.name == class16) {
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    attrExt.classIndex = htods(i+1);
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (ae.name == style16) {
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    attrExt.styleIndex = htods(i+1);
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == TYPE_NAMESPACE) {
1412f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        if (mNamespaceUri == RESOURCES_TOOLS_NAMESPACE) {
1413f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            writeCurrentNode = false;
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1415f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            node.header.type = htods(RES_XML_START_NAMESPACE_TYPE);
1416f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            extData = &namespaceExt;
1417f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            extSize = sizeof(namespaceExt);
1418f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            memset(&namespaceExt, 0, sizeof(namespaceExt));
1419f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            if (mNamespacePrefix.size() > 0) {
1420f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet                namespaceExt.prefix.index = htodl(strings.offsetForString(mNamespacePrefix));
1421f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            } else {
1422f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet                namespaceExt.prefix.index = htodl((uint32_t)-1);
1423f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            }
1424f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            namespaceExt.prefix.index = htodl(strings.offsetForString(mNamespacePrefix));
1425f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            namespaceExt.uri.index = htodl(strings.offsetForString(mNamespaceUri));
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOG_ALWAYS_FATAL_IF(NA != 0, "Namespace nodes can't have attributes!");
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == TYPE_CDATA) {
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node.header.type = htods(RES_XML_CDATA_TYPE);
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        extData = &cdataExt;
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        extSize = sizeof(cdataExt);
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memset(&cdataExt, 0, sizeof(cdataExt));
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cdataExt.data.index = htodl(strings.offsetForString(mChars));
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cdataExt.typedData.size = htods(sizeof(cdataExt.typedData));
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cdataExt.typedData.res0 = 0;
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cdataExt.typedData.dataType = mCharsValue.dataType;
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cdataExt.typedData.data = htodl(mCharsValue.data);
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOG_ALWAYS_FATAL_IF(NA != 0, "CDATA nodes can't have attributes!");
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    node.header.size = htodl(sizeof(node) + extSize + (sizeof(attr)*NA));
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1443f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet    if (writeCurrentNode) {
1444f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        dest->writeData(&node, sizeof(node));
1445f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        if (extSize > 0) {
1446f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            dest->writeData(extData, extSize);
1447f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        }
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i=0; i<NA; i++) {
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ssize_t idx = mAttributeOrder.valueAt(i);
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const attribute_entry& ae = mAttributes.itemAt(idx);
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ae.ns.size() > 0) {
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attr.ns.index = htodl(strings.offsetForString(ae.ns));
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attr.ns.index = htodl((uint32_t)-1);
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        attr.name.index = htodl(ae.namePoolIdx);
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!stripRawValues || ae.needStringValue()) {
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attr.rawValue.index = htodl(strings.offsetForString(ae.string));
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attr.rawValue.index = htodl((uint32_t)-1);
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        attr.typedValue.size = htods(sizeof(attr.typedValue));
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ae.value.dataType == Res_value::TYPE_NULL
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || ae.value.dataType == Res_value::TYPE_STRING) {
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attr.typedValue.res0 = 0;
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attr.typedValue.dataType = Res_value::TYPE_STRING;
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attr.typedValue.data = htodl(strings.offsetForString(ae.string));
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attr.typedValue.res0 = 0;
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attr.typedValue.dataType = ae.value.dataType;
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attr.typedValue.data = htodl(ae.value.data);
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest->writeData(&attr, sizeof(attr));
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i=0; i<NC; i++) {
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        status_t err = mChildren.itemAt(i)->flatten_node(strings, dest,
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stripComments, stripRawValues);
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err != NO_ERROR) {
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return err;
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (type == TYPE_ELEMENT) {
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ResXMLTree_endElementExt endElementExt;
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memset(&endElementExt, 0, sizeof(endElementExt));
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node.header.type = htods(RES_XML_END_ELEMENT_TYPE);
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node.header.size = htodl(sizeof(node)+sizeof(endElementExt));
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node.lineNumber = htodl(getEndLineNumber());
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        node.comment.index = htodl((uint32_t)-1);
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        endElementExt.ns.index = attrExt.ns.index;
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        endElementExt.name.index = attrExt.name.index;
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest->writeData(&node, sizeof(node));
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dest->writeData(&endElementExt, sizeof(endElementExt));
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (type == TYPE_NAMESPACE) {
1499f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        if (writeCurrentNode) {
1500f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            node.header.type = htods(RES_XML_END_NAMESPACE_TYPE);
1501f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            node.lineNumber = htodl(getEndLineNumber());
1502f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            node.comment.index = htodl((uint32_t)-1);
1503f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            node.header.size = htodl(sizeof(node)+extSize);
1504f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            dest->writeData(&node, sizeof(node));
1505f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet            dest->writeData(extData, extSize);
1506f8aea99385df8373b6edd6d5dd1d15b7b36b525bXavier Ducrohet        }
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1511