]> git.saurik.com Git - android/aapt.git/blobdiff - XMLNode.cpp
Use "ldrtl" and "ldltr" config qualifiers for RTL / LTR resources
[android/aapt.git] / XMLNode.cpp
index 452549b80b8503eee2e7a270bd86edccb0af23bc..dcbe7db7c54cbf3d23a2b5844edc49e73fc1079e 100644 (file)
@@ -21,6 +21,7 @@
 
 const char* const RESOURCES_ROOT_NAMESPACE = "http://schemas.android.com/apk/res/";
 const char* const RESOURCES_ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android";
 
 const char* const RESOURCES_ROOT_NAMESPACE = "http://schemas.android.com/apk/res/";
 const char* const RESOURCES_ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android";
+const char* const RESOURCES_AUTO_PACKAGE_NAMESPACE = "http://schemas.android.com/apk/res-auto";
 const char* const RESOURCES_ROOT_PRV_NAMESPACE = "http://schemas.android.com/apk/prv/res/";
 
 const char* const XLIFF_XMLNS = "urn:oasis:names:tc:xliff:document:1.2";
 const char* const RESOURCES_ROOT_PRV_NAMESPACE = "http://schemas.android.com/apk/prv/res/";
 
 const char* const XLIFF_XMLNS = "urn:oasis:names:tc:xliff:document:1.2";
@@ -44,15 +45,21 @@ bool isWhitespace(const char16_t* str)
 }
 
 static const String16 RESOURCES_PREFIX(RESOURCES_ROOT_NAMESPACE);
 }
 
 static const String16 RESOURCES_PREFIX(RESOURCES_ROOT_NAMESPACE);
+static const String16 RESOURCES_PREFIX_AUTO_PACKAGE(RESOURCES_AUTO_PACKAGE_NAMESPACE);
 static const String16 RESOURCES_PRV_PREFIX(RESOURCES_ROOT_PRV_NAMESPACE);
 static const String16 RESOURCES_PRV_PREFIX(RESOURCES_ROOT_PRV_NAMESPACE);
+static const String16 RESOURCES_TOOLS_NAMESPACE("http://schemas.android.com/tools");
 
 
-String16 getNamespaceResourcePackage(String16 namespaceUri, bool* outIsPublic)
+String16 getNamespaceResourcePackage(String16 appPackage, String16 namespaceUri, bool* outIsPublic)
 {
     //printf("%s starts with %s?\n", String8(namespaceUri).string(),
     //       String8(RESOURCES_PREFIX).string());
     size_t prefixSize;
     bool isPublic = true;
 {
     //printf("%s starts with %s?\n", String8(namespaceUri).string(),
     //       String8(RESOURCES_PREFIX).string());
     size_t prefixSize;
     bool isPublic = true;
-    if (namespaceUri.startsWith(RESOURCES_PREFIX)) {
+    if(namespaceUri.startsWith(RESOURCES_PREFIX_AUTO_PACKAGE)) {
+        NOISY(printf("Using default application package: %s -> %s\n", String8(namespaceUri).string(), String8(appPackage).string()));
+        isPublic = true;
+        return appPackage;
+    } else if (namespaceUri.startsWith(RESOURCES_PREFIX)) {
         prefixSize = RESOURCES_PREFIX.size();
     } else if (namespaceUri.startsWith(RESOURCES_PRV_PREFIX)) {
         isPublic = false;
         prefixSize = RESOURCES_PREFIX.size();
     } else if (namespaceUri.startsWith(RESOURCES_PRV_PREFIX)) {
         isPublic = false;
@@ -166,7 +173,7 @@ status_t hasSubstitutionErrors(const char* fileName,
     if (argCount > 1 && nonpositional) {
         SourcePos(String8(fileName), inXml->getLineNumber()).error(
                 "Multiple substitutions specified in non-positional format; "
     if (argCount > 1 && nonpositional) {
         SourcePos(String8(fileName), inXml->getLineNumber()).error(
                 "Multiple substitutions specified in non-positional format; "
-                "did you mean to add the formatted=\"true\" attribute?\n");
+                "did you mean to add the formatted=\"false\" attribute?\n");
         return NOT_ENOUGH_DATA;
     }
 
         return NOT_ENOUGH_DATA;
     }
 
@@ -203,13 +210,9 @@ status_t parseStyledString(Bundle* bundle,
                 }
             }
             if (xliffDepth == 0 && pseudolocalize) {
                 }
             }
             if (xliffDepth == 0 && pseudolocalize) {
-#ifdef ENABLE_PSEUDOLOCALIZE
                 std::string orig(String8(text).string());
                 std::string pseudo = pseudolocalize_string(orig);
                 curString.append(String16(String8(pseudo.c_str())));
                 std::string orig(String8(text).string());
                 std::string pseudo = pseudolocalize_string(orig);
                 curString.append(String16(String8(pseudo.c_str())));
-#else
-                assert(false);
-#endif
             } else {
                 if (isFormatted && hasSubstitutionErrors(fileName, inXml, text) != NO_ERROR) {
                     return UNKNOWN_ERROR;
             } else {
                 if (isFormatted && hasSubstitutionErrors(fileName, inXml, text) != NO_ERROR) {
                     return UNKNOWN_ERROR;
@@ -455,13 +458,15 @@ void printXMLBlock(ResXMLTree* block)
                     printf("=?0x%x", (int)value.data);
                 } else if (value.dataType == Res_value::TYPE_STRING) {
                     printf("=\"%s\"",
                     printf("=?0x%x", (int)value.data);
                 } else if (value.dataType == Res_value::TYPE_STRING) {
                     printf("=\"%s\"",
-                           String8(block->getAttributeStringValue(i, &len)).string());
+                            ResTable::normalizeForOutput(String8(block->getAttributeStringValue(i,
+                                        &len)).string()).string());
                 } else {
                     printf("=(type 0x%x)0x%x", (int)value.dataType, (int)value.data);
                 }
                 const char16_t* val = block->getAttributeStringValue(i, &len);
                 if (val != NULL) {
                 } else {
                     printf("=(type 0x%x)0x%x", (int)value.dataType, (int)value.data);
                 }
                 const char16_t* val = block->getAttributeStringValue(i, &len);
                 if (val != NULL) {
-                    printf(" (Raw: \"%s\")", String8(val).string());
+                    printf(" (Raw: \"%s\")", ResTable::normalizeForOutput(String8(val).string()).
+                            string());
                 }
                 printf("\n");
             }
                 }
                 printf("\n");
             }
@@ -506,7 +511,8 @@ void printXMLBlock(ResXMLTree* block)
             namespaces.pop();
         } else if (code == ResXMLTree::TEXT) {
             size_t len;
             namespaces.pop();
         } else if (code == ResXMLTree::TEXT) {
             size_t len;
-            printf("%sC: \"%s\"\n", prefix.string(), String8(block->getText(&len)).string());
+            printf("%sC: \"%s\"\n", prefix.string(),
+                    ResTable::normalizeForOutput(String8(block->getText(&len)).string()).string());
         }
     }
 
         }
     }
 
@@ -763,13 +769,16 @@ status_t XMLNode::addAttribute(const String16& ns, const String16& name,
         SourcePos(mFilename, getStartLineNumber()).error("Child to CDATA node.");
         return UNKNOWN_ERROR;
     }
         SourcePos(mFilename, getStartLineNumber()).error("Child to CDATA node.");
         return UNKNOWN_ERROR;
     }
-    attribute_entry e;
-    e.index = mNextAttributeIndex++;
-    e.ns = ns;
-    e.name = name;
-    e.string = value;
-    mAttributes.add(e);
-    mAttributeOrder.add(e.index, mAttributes.size()-1);
+
+    if (ns != RESOURCES_TOOLS_NAMESPACE) {
+        attribute_entry e;
+        e.index = mNextAttributeIndex++;
+        e.ns = ns;
+        e.name = name;
+        e.string = value;
+        mAttributes.add(e);
+        mAttributeOrder.add(e.index, mAttributes.size()-1);
+    }
     return NO_ERROR;
 }
 
     return NO_ERROR;
 }
 
@@ -924,7 +933,7 @@ status_t XMLNode::assignResourceIds(const sp<AaptAssets>& assets,
             const attribute_entry& e = mAttributes.itemAt(i);
             if (e.ns.size() <= 0) continue;
             bool nsIsPublic;
             const attribute_entry& e = mAttributes.itemAt(i);
             if (e.ns.size() <= 0) continue;
             bool nsIsPublic;
-            String16 pkg(getNamespaceResourcePackage(e.ns, &nsIsPublic));
+            String16 pkg(getNamespaceResourcePackage(String16(assets->getPackage()), e.ns, &nsIsPublic));
             NOISY(printf("Elem %s %s=\"%s\": namespace(%s) %s ===> %s\n",
                     String8(getElementName()).string(),
                     String8(e.name).string(),
             NOISY(printf("Elem %s %s=\"%s\": namespace(%s) %s ===> %s\n",
                     String8(getElementName()).string(),
                     String8(e.name).string(),
@@ -965,7 +974,7 @@ status_t XMLNode::assignResourceIds(const sp<AaptAssets>& assets,
 status_t XMLNode::flatten(const sp<AaptFile>& dest,
         bool stripComments, bool stripRawValues) const
 {
 status_t XMLNode::flatten(const sp<AaptFile>& dest,
         bool stripComments, bool stripRawValues) const
 {
-    StringPool strings = StringPool(false, mUTF8);
+    StringPool strings(mUTF8);
     Vector<uint32_t> resids;
     
     // First collect just the strings for attribute names that have a
     Vector<uint32_t> resids;
     
     // First collect just the strings for attribute names that have a
@@ -1217,11 +1226,13 @@ status_t XMLNode::collect_strings(StringPool* dest, Vector<uint32_t>* outResIds,
     collect_attr_strings(dest, outResIds, true);
     
     int i;
     collect_attr_strings(dest, outResIds, true);
     
     int i;
-    if (mNamespacePrefix.size() > 0) {
-        dest->add(mNamespacePrefix, true);
-    }
-    if (mNamespaceUri.size() > 0) {
-        dest->add(mNamespaceUri, true);
+    if (RESOURCES_TOOLS_NAMESPACE != mNamespaceUri) {
+        if (mNamespacePrefix.size() > 0) {
+            dest->add(mNamespacePrefix, true);
+        }
+        if (mNamespaceUri.size() > 0) {
+            dest->add(mNamespaceUri, true);
+        }
     }
     if (mElementName.size() > 0) {
         dest->add(mElementName, true);
     }
     if (mElementName.size() > 0) {
         dest->add(mElementName, true);
@@ -1340,6 +1351,7 @@ status_t XMLNode::flatten_node(const StringPool& strings, const sp<AaptFile>& de
     const void* extData = NULL;
     size_t extSize = 0;
     ResXMLTree_attribute attr;
     const void* extData = NULL;
     size_t extSize = 0;
     ResXMLTree_attribute attr;
+    bool writeCurrentNode = true;
 
     const size_t NA = mAttributes.size();
     const size_t NC = mChildren.size();
 
     const size_t NA = mAttributes.size();
     const size_t NC = mChildren.size();
@@ -1352,7 +1364,7 @@ status_t XMLNode::flatten_node(const StringPool& strings, const sp<AaptFile>& de
     const String16 style16("style");
 
     const type type = getType();
     const String16 style16("style");
 
     const type type = getType();
-    
+
     memset(&node, 0, sizeof(node));
     memset(&attr, 0, sizeof(attr));
     node.header.headerSize = htods(sizeof(node));
     memset(&node, 0, sizeof(node));
     memset(&attr, 0, sizeof(attr));
     node.header.headerSize = htods(sizeof(node));
@@ -1397,17 +1409,21 @@ status_t XMLNode::flatten_node(const StringPool& strings, const sp<AaptFile>& de
             }
         }
     } else if (type == TYPE_NAMESPACE) {
             }
         }
     } else if (type == TYPE_NAMESPACE) {
-        node.header.type = htods(RES_XML_START_NAMESPACE_TYPE);
-        extData = &namespaceExt;
-        extSize = sizeof(namespaceExt);
-        memset(&namespaceExt, 0, sizeof(namespaceExt));
-        if (mNamespacePrefix.size() > 0) {
-            namespaceExt.prefix.index = htodl(strings.offsetForString(mNamespacePrefix));
+        if (mNamespaceUri == RESOURCES_TOOLS_NAMESPACE) {
+            writeCurrentNode = false;
         } else {
         } else {
-            namespaceExt.prefix.index = htodl((uint32_t)-1);
+            node.header.type = htods(RES_XML_START_NAMESPACE_TYPE);
+            extData = &namespaceExt;
+            extSize = sizeof(namespaceExt);
+            memset(&namespaceExt, 0, sizeof(namespaceExt));
+            if (mNamespacePrefix.size() > 0) {
+                namespaceExt.prefix.index = htodl(strings.offsetForString(mNamespacePrefix));
+            } else {
+                namespaceExt.prefix.index = htodl((uint32_t)-1);
+            }
+            namespaceExt.prefix.index = htodl(strings.offsetForString(mNamespacePrefix));
+            namespaceExt.uri.index = htodl(strings.offsetForString(mNamespaceUri));
         }
         }
-        namespaceExt.prefix.index = htodl(strings.offsetForString(mNamespacePrefix));
-        namespaceExt.uri.index = htodl(strings.offsetForString(mNamespaceUri));
         LOG_ALWAYS_FATAL_IF(NA != 0, "Namespace nodes can't have attributes!");
     } else if (type == TYPE_CDATA) {
         node.header.type = htods(RES_XML_CDATA_TYPE);
         LOG_ALWAYS_FATAL_IF(NA != 0, "Namespace nodes can't have attributes!");
     } else if (type == TYPE_CDATA) {
         node.header.type = htods(RES_XML_CDATA_TYPE);
@@ -1424,9 +1440,11 @@ status_t XMLNode::flatten_node(const StringPool& strings, const sp<AaptFile>& de
 
     node.header.size = htodl(sizeof(node) + extSize + (sizeof(attr)*NA));
 
 
     node.header.size = htodl(sizeof(node) + extSize + (sizeof(attr)*NA));
 
-    dest->writeData(&node, sizeof(node));
-    if (extSize > 0) {
-        dest->writeData(extData, extSize);
+    if (writeCurrentNode) {
+        dest->writeData(&node, sizeof(node));
+        if (extSize > 0) {
+            dest->writeData(extData, extSize);
+        }
     }
 
     for (i=0; i<NA; i++) {
     }
 
     for (i=0; i<NA; i++) {
@@ -1478,12 +1496,14 @@ status_t XMLNode::flatten_node(const StringPool& strings, const sp<AaptFile>& de
         dest->writeData(&node, sizeof(node));
         dest->writeData(&endElementExt, sizeof(endElementExt));
     } else if (type == TYPE_NAMESPACE) {
         dest->writeData(&node, sizeof(node));
         dest->writeData(&endElementExt, sizeof(endElementExt));
     } else if (type == TYPE_NAMESPACE) {
-        node.header.type = htods(RES_XML_END_NAMESPACE_TYPE);
-        node.lineNumber = htodl(getEndLineNumber());
-        node.comment.index = htodl((uint32_t)-1);
-        node.header.size = htodl(sizeof(node)+extSize);
-        dest->writeData(&node, sizeof(node));
-        dest->writeData(extData, extSize);
+        if (writeCurrentNode) {
+            node.header.type = htods(RES_XML_END_NAMESPACE_TYPE);
+            node.lineNumber = htodl(getEndLineNumber());
+            node.comment.index = htodl((uint32_t)-1);
+            node.header.size = htodl(sizeof(node)+extSize);
+            dest->writeData(&node, sizeof(node));
+            dest->writeData(extData, extSize);
+        }
     }
 
     return NO_ERROR;
     }
 
     return NO_ERROR;