]> git.saurik.com Git - android/aapt.git/blobdiff - StringPool.cpp
am eed8d0b3: Fix for issue 9656 - custom xml attributes in Android Libraries. do...
[android/aapt.git] / StringPool.cpp
index 715170aedfebfebe39c98c5e42b1b73eb23fc94d..9a0a1c46251bf406e5fa598f79f887b0e1271e11 100644 (file)
@@ -8,6 +8,14 @@
 
 #include <utils/ByteOrder.h>
 
+#if HAVE_PRINTF_ZD
+#  define ZD "%zd"
+#  define ZD_TYPE ssize_t
+#else
+#  define ZD "%ld"
+#  define ZD_TYPE long
+#endif
+
 #define NOISY(x) //x
 
 void strcpy16_htod(uint16_t* dst, const uint16_t* src)
@@ -25,13 +33,17 @@ void printStringPool(const ResStringPool* pool)
     const size_t NS = pool->size();
     for (size_t s=0; s<NS; s++) {
         size_t len;
-        printf("String #%d: %s\n", s,
-                String8(pool->stringAt(s, &len)).string());
+        const char *str = (const char*)pool->string8At(s, &len);
+        if (str == NULL) {
+            str = String8(pool->stringAt(s, &len)).string();
+        }
+
+        printf("String #" ZD ": %s\n", (ZD_TYPE) s, str);
     }
 }
 
-StringPool::StringPool(bool sorted)
-    : mSorted(sorted), mValues(-1), mIdents(-1)
+StringPool::StringPool(bool sorted, bool utf8)
+    : mSorted(sorted), mUTF8(utf8), mValues(-1), mIdents(-1)
 {
 }
 
@@ -165,6 +177,16 @@ sp<AaptFile> StringPool::createStringBlock()
     return err == NO_ERROR ? pool : NULL;
 }
 
+#define ENCODE_LENGTH(str, chrsz, strSize) \
+{ \
+    size_t maxMask = 1 << ((chrsz*8)-1); \
+    size_t maxSize = maxMask-1; \
+    if (strSize > maxSize) { \
+        *str++ = maxMask | ((strSize>>(chrsz*8))&maxSize); \
+    } \
+    *str++ = strSize; \
+}
+
 status_t StringPool::writeStringBlock(const sp<AaptFile>& pool)
 {
     // Allow appending.  Sorry this is a little wacky.
@@ -213,28 +235,53 @@ status_t StringPool::writeStringBlock(const sp<AaptFile>& pool)
         return NO_MEMORY;
     }
 
+    const size_t charSize = mUTF8 ? sizeof(uint8_t) : sizeof(char16_t);
+
     size_t strPos = 0;
     for (i=0; i<STRINGS; i++) {
         entry& ent = mEntries.editItemAt(i);
         const size_t strSize = (ent.value.size());
-        const size_t lenSize = strSize > 0x7fff ? sizeof(uint32_t) : sizeof(uint16_t);
-        const size_t totalSize = lenSize + ((strSize+1)*sizeof(uint16_t));
+        const size_t lenSize = strSize > (size_t)(1<<((charSize*8)-1))-1 ?
+            charSize*2 : charSize;
+
+        String8 encStr;
+        if (mUTF8) {
+            encStr = String8(ent.value);
+        }
+
+        const size_t encSize = mUTF8 ? encStr.size() : 0;
+        const size_t encLenSize = mUTF8 ?
+            (encSize > (size_t)(1<<((charSize*8)-1))-1 ?
+                charSize*2 : charSize) : 0;
 
         ent.offset = strPos;
-        uint16_t* dat = (uint16_t*)pool->editData(preSize + strPos + totalSize);
+
+        const size_t totalSize = lenSize + encLenSize +
+            ((mUTF8 ? encSize : strSize)+1)*charSize;
+
+        void* dat = (void*)pool->editData(preSize + strPos + totalSize);
         if (dat == NULL) {
             fprintf(stderr, "ERROR: Out of memory for string pool\n");
             return NO_MEMORY;
         }
-        dat += (preSize+strPos)/sizeof(uint16_t);
-        if (lenSize > sizeof(uint16_t)) {
-            *dat = htods(0x8000 | ((strSize>>16)&0x7fff));
-            dat++;
+        dat = (uint8_t*)dat + preSize + strPos;
+        if (mUTF8) {
+            uint8_t* strings = (uint8_t*)dat;
+
+            ENCODE_LENGTH(strings, sizeof(uint8_t), strSize)
+
+            ENCODE_LENGTH(strings, sizeof(uint8_t), encSize)
+
+            strncpy((char*)strings, encStr, encSize+1);
+        } else {
+            uint16_t* strings = (uint16_t*)dat;
+
+            ENCODE_LENGTH(strings, sizeof(uint16_t), strSize)
+
+            strcpy16_htod(strings, ent.value);
         }
-        *dat++ = htods(strSize);
-        strcpy16_htod(dat, ent.value);
 
-        strPos += lenSize + (strSize+1)*sizeof(uint16_t);
+        strPos += totalSize;
     }
 
     // Pad ending string position up to a uint32_t boundary.
@@ -312,6 +359,9 @@ status_t StringPool::writeStringBlock(const sp<AaptFile>& pool)
     if (mSorted) {
         header->flags |= htodl(ResStringPool_header::SORTED_FLAG);
     }
+    if (mUTF8) {
+        header->flags |= htodl(ResStringPool_header::UTF8_FLAG);
+    }
     header->stringsStart = htodl(preSize);
     header->stylesStart = htodl(STYLES > 0 ? (preSize+strPos) : 0);