}
}
-StringPool::StringPool(bool sorted)
- : mSorted(sorted), mValues(-1), mIdents(-1)
+StringPool::StringPool(bool sorted, bool utf8)
+ : mSorted(sorted), mUTF8(utf8), mValues(-1), mIdents(-1)
{
}
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.
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)&0x7ffff));
- 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.
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);