StringPool.cpp revision 46fc395386f2277a0425b2c46be08fd91f6554f4
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// Copyright 2006 The Android Open Source Project 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// Build resource files from raw assets. 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt// 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "StringPool.h" 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ResourceTable.h" 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <utils/ByteOrder.h> 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <utils/SortedVector.h> 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if HAVE_PRINTF_ZD 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt# define ZD "%zd" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt# define ZD_TYPE ssize_t 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt# define ZD "%ld" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt# define ZD_TYPE long 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NOISY(x) //x 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid strcpy16_htod(uint16_t* dst, const uint16_t* src) 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*src) { 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char16_t s = htods(*src); 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *dst++ = s; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt src++; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *dst = 0; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid printStringPool(const ResStringPool* pool) 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SortedVector<const void*> uniqueStrings; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t N = pool->size(); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (size_t i=0; i<N; i++) { 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pool->isUTF8()) { 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uniqueStrings.add(pool->string8At(i, &len)); 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uniqueStrings.add(pool->stringAt(i, &len)); 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("String pool of " ZD " unique %s %s strings, " ZD " entries and " 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ZD " styles using " ZD " bytes:\n", 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ZD_TYPE)uniqueStrings.size(), pool->isUTF8() ? "UTF-8" : "UTF-16", 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pool->isSorted() ? "sorted" : "non-sorted", 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ZD_TYPE)N, (ZD_TYPE)pool->styleCount(), (ZD_TYPE)pool->bytes()); 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t NS = pool->size(); 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (size_t s=0; s<NS; s++) { 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt String8 str = pool->string8ObjectAt(s); 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("String #" ZD ": %s\n", (ZD_TYPE) s, str.string()); 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtString8 StringPool::entry::makeConfigsString() const { 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt String8 configStr(configTypeName); 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (configStr.size() > 0) configStr.append(" "); 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (configs.size() > 0) { 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (size_t j=0; j<configs.size(); j++) { 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (j > 0) configStr.append(", "); 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt configStr.append(configs[j].toString()); 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt configStr = "(none)"; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return configStr; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint StringPool::entry::compare(const entry& o) const { 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Strings with styles go first, to reduce the size of the styles array. 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // We don't care about the relative order of these strings. 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hasStyles) { 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return o.hasStyles ? 0 : -1; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (o.hasStyles) { 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Sort unstyled strings by type, then by logical configuration. 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int comp = configTypeName.compare(o.configTypeName); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (comp != 0) { 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return comp; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t LHN = configs.size(); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t RHN = o.configs.size(); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i=0; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (i < LHN && i < RHN) { 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt comp = configs[i].compareLogical(o.configs[i]); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (comp != 0) { 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return comp; 9551b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt } 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i++; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (LHN < RHN) return -1; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (LHN > RHN) return 1; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtStringPool::StringPool(bool utf8) : 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mUTF8(utf8), mValues(-1) 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtssize_t StringPool::add(const String16& value, const Vector<entry_style_span>& spans, 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const String8* configTypeName, const ResTable_config* config) 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssize_t res = add(value, false, configTypeName, config); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res >= 0) { 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addStyleSpans(res, spans); 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtssize_t StringPool::add(const String16& value, 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool mergeDuplicates, const String8* configTypeName, const ResTable_config* config) 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssize_t vidx = mValues.indexOfKey(value); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssize_t pos = vidx >= 0 ? mValues.valueAt(vidx) : -1; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssize_t eidx = pos >= 0 ? mEntryArray.itemAt(pos) : -1; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eidx < 0) { 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eidx = mEntries.add(entry(value)); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eidx < 0) { 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fprintf(stderr, "Failure adding string %s\n", String8(value).string()); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eidx; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (configTypeName != NULL) { 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry& ent = mEntries.editItemAt(eidx); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NOISY(printf("*** adding config type name %s, was %s\n", 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt configTypeName->string(), ent.configTypeName.string())); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ent.configTypeName.size() <= 0) { 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ent.configTypeName = *configTypeName; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (ent.configTypeName != *configTypeName) { 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ent.configTypeName = " "; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config != NULL) { 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Add this to the set of configs associated with the string. 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry& ent = mEntries.editItemAt(eidx); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t addPos; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (addPos=0; addPos<ent.configs.size(); addPos++) { 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cmp = ent.configs.itemAt(addPos).compareLogical(*config); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cmp >= 0) { 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cmp > 0) { 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NOISY(printf("*** inserting config: %s\n", config->toString().string())); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ent.configs.insertAt(*config, addPos); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addPos >= ent.configs.size()) { 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NOISY(printf("*** adding config: %s\n", config->toString().string())); 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ent.configs.add(*config); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const bool first = vidx < 0; 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const bool styled = (pos >= 0 && (size_t)pos < mEntryStyleArray.size()) ? 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mEntryStyleArray[pos].spans.size() : 0; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (first || styled || !mergeDuplicates) { 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = mEntryArray.add(eidx); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (first) { 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vidx = mValues.add(value, pos); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry& ent = mEntries.editItemAt(eidx); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ent.indices.add(pos); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NOISY(printf("Adding string %s to pool: pos=%d eidx=%d vidx=%d\n", 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt String8(value).string(), pos, eidx, vidx)); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatus_t StringPool::addStyleSpan(size_t idx, const String16& name, 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uint32_t start, uint32_t end) 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry_style_span span; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt span.name = name; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt span.span.firstChar = start; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt span.span.lastChar = end; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return addStyleSpan(idx, span); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatus_t StringPool::addStyleSpans(size_t idx, const Vector<entry_style_span>& spans) 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t N=spans.size(); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (size_t i=0; i<N; i++) { 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status_t err = addStyleSpan(idx, spans[i]); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err != NO_ERROR) { 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return err; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NO_ERROR; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatus_t StringPool::addStyleSpan(size_t idx, const entry_style_span& span) 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Place blank entries in the span array up to this index. 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (mEntryStyleArray.size() <= idx) { 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mEntryStyleArray.add(); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry_style& style = mEntryStyleArray.editItemAt(idx); 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt style.spans.add(span); 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mEntries.editItemAt(mEntryArray[idx]).hasStyles = true; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NO_ERROR; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __GLIBC__ 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint StringPool::config_sort(const void* lhs, const void* rhs, void* state) 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint StringPool::config_sort(void* state, const void* lhs, const void* rhs) 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt StringPool* pool = (StringPool*)state; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const entry& lhe = pool->mEntries[pool->mEntryArray[*static_cast<const size_t*>(lhs)]]; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const entry& rhe = pool->mEntries[pool->mEntryArray[*static_cast<const size_t*>(rhs)]]; 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return lhe.compare(rhe); 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid StringPool::sortByConfig() 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LOG_ALWAYS_FATAL_IF(mOriginalPosToNewPos.size() > 0, "Can't sort string pool after already sorted."); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t N = mEntryArray.size(); 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // This is a vector that starts out with a 1:1 mapping to entries 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // in the array, which we will sort to come up with the desired order. 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // At that point it maps from the new position in the array to the 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // original position the entry appeared. 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Vector<size_t> newPosToOriginalPos; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt newPosToOriginalPos.setCapacity(N); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (size_t i=0; i < N; i++) { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt newPosToOriginalPos.add(i); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Sort the array. 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NOISY(printf("SORTING STRINGS BY CONFIGURATION...\n")); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Vector::sort uses insertion sort, which is very slow for this data set. 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Use quicksort instead because we don't need a stable sort here. 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // For more fun, GLibC took qsort_r from BSD but then decided to swap the 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // order the last two parameters. 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __GLIBC__ 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt qsort_r(newPosToOriginalPos.editArray(), N, sizeof(size_t), config_sort, this); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt qsort_r(newPosToOriginalPos.editArray(), N, sizeof(size_t), this, config_sort); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt //newPosToOriginalPos.sort(config_sort, this); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NOISY(printf("DONE SORTING STRINGS BY CONFIGURATION.\n")); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Create the reverse mapping from the original position in the array 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // to the new position where it appears in the sorted array. This is 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // so that clients can re-map any positions they had previously stored. 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mOriginalPosToNewPos = newPosToOriginalPos; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (size_t i=0; i<N; i++) { 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mOriginalPosToNewPos.editItemAt(newPosToOriginalPos[i]) = i; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SortedVector<entry> entries; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (size_t i=0; i<N; i++) { 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("#%d was %d: %s\n", i, newPosToOriginalPos[i], 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mEntries[mEntryArray[newPosToOriginalPos[i]]].makeConfigsString().string()); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entries.add(mEntries[mEntryArray[i]]); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (size_t i=0; i<entries.size(); i++) { 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Sorted config #%d: %s\n", i, 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entries[i].makeConfigsString().string()); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Now we rebuild the arrays. 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Vector<entry> newEntries; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Vector<size_t> newEntryArray; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Vector<entry_style> newEntryStyleArray; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DefaultKeyedVector<size_t, size_t> origOffsetToNewOffset; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (size_t i=0; i<N; i++) { 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // We are filling in new offset 'i'; oldI is where we can find it 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // in the original data structure. 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t oldI = newPosToOriginalPos[i]; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // This is the actual entry associated with the old offset. 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const entry& oldEnt = mEntries[mEntryArray[oldI]]; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // This is the same entry the last time we added it to the 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // new entry array, if any. 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssize_t newIndexOfOffset = origOffsetToNewOffset.indexOfKey(oldI); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t newOffset; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (newIndexOfOffset < 0) { 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // This is the first time we have seen the entry, so add 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // it. 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt newOffset = newEntries.add(oldEnt); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt newEntries.editItemAt(newOffset).indices.clear(); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // We have seen this entry before, use the existing one 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // instead of adding it again. 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt newOffset = origOffsetToNewOffset.valueAt(newIndexOfOffset); 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Update the indices to include this new position. 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt newEntries.editItemAt(newOffset).indices.add(i); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // And add the offset of the entry to the new entry array. 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt newEntryArray.add(newOffset); 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Add any old style to the new style array. 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mEntryStyleArray.size() > 0) { 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (oldI < mEntryStyleArray.size()) { 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt newEntryStyleArray.add(mEntryStyleArray[oldI]); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt newEntryStyleArray.add(entry_style()); 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Now trim any entries at the end of the new style array that are 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // not needed. 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (ssize_t i=newEntryStyleArray.size()-1; i>=0; i--) { 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const entry_style& style = newEntryStyleArray[i]; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (style.spans.size() > 0) { 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // That's it. 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // This one is not needed; remove. 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt newEntryStyleArray.removeAt(i); 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // All done, install the new data structures and upate mValues with 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // the new positions. 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mEntries = newEntries; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mEntryArray = newEntryArray; 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mEntryStyleArray = newEntryStyleArray; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mValues.clear(); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (size_t i=0; i<mEntries.size(); i++) { 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const entry& ent = mEntries[i]; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mValues.add(ent.value, ent.indices[0]); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("FINAL SORTED STRING CONFIGS:\n"); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (size_t i=0; i<mEntries.size(); i++) { 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const entry& ent = mEntries[i]; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("#" ZD " %s: %s\n", (ZD_TYPE)i, ent.makeConfigsString().string(), 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt String8(ent.value).string()); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtsp<AaptFile> StringPool::createStringBlock() 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sp<AaptFile> pool = new AaptFile(String8(), AaptGroupEntry(), 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt String8()); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status_t err = writeStringBlock(pool); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return err == NO_ERROR ? pool : NULL; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define ENCODE_LENGTH(str, chrsz, strSize) \ 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ \ 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t maxMask = 1 << ((chrsz*8)-1); \ 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t maxSize = maxMask-1; \ 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (strSize > maxSize) { \ 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *str++ = maxMask | ((strSize>>(chrsz*8))&maxSize); \ 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } \ 369 *str++ = strSize; \ 370} 371 372status_t StringPool::writeStringBlock(const sp<AaptFile>& pool) 373{ 374 // Allow appending. Sorry this is a little wacky. 375 if (pool->getSize() > 0) { 376 sp<AaptFile> block = createStringBlock(); 377 if (block == NULL) { 378 return UNKNOWN_ERROR; 379 } 380 ssize_t res = pool->writeData(block->getData(), block->getSize()); 381 return (res >= 0) ? (status_t)NO_ERROR : res; 382 } 383 384 // First we need to add all style span names to the string pool. 385 // We do this now (instead of when the span is added) so that these 386 // will appear at the end of the pool, not disrupting the order 387 // our client placed their own strings in it. 388 389 const size_t STYLES = mEntryStyleArray.size(); 390 size_t i; 391 392 for (i=0; i<STYLES; i++) { 393 entry_style& style = mEntryStyleArray.editItemAt(i); 394 const size_t N = style.spans.size(); 395 for (size_t i=0; i<N; i++) { 396 entry_style_span& span = style.spans.editItemAt(i); 397 ssize_t idx = add(span.name, true); 398 if (idx < 0) { 399 fprintf(stderr, "Error adding span for style tag '%s'\n", 400 String8(span.name).string()); 401 return idx; 402 } 403 span.span.name.index = (uint32_t)idx; 404 } 405 } 406 407 const size_t ENTRIES = mEntryArray.size(); 408 409 // Now build the pool of unique strings. 410 411 const size_t STRINGS = mEntries.size(); 412 const size_t preSize = sizeof(ResStringPool_header) 413 + (sizeof(uint32_t)*ENTRIES) 414 + (sizeof(uint32_t)*STYLES); 415 if (pool->editData(preSize) == NULL) { 416 fprintf(stderr, "ERROR: Out of memory for string pool\n"); 417 return NO_MEMORY; 418 } 419 420 const size_t charSize = mUTF8 ? sizeof(uint8_t) : sizeof(char16_t); 421 422 size_t strPos = 0; 423 for (i=0; i<STRINGS; i++) { 424 entry& ent = mEntries.editItemAt(i); 425 const size_t strSize = (ent.value.size()); 426 const size_t lenSize = strSize > (size_t)(1<<((charSize*8)-1))-1 ? 427 charSize*2 : charSize; 428 429 String8 encStr; 430 if (mUTF8) { 431 encStr = String8(ent.value); 432 } 433 434 const size_t encSize = mUTF8 ? encStr.size() : 0; 435 const size_t encLenSize = mUTF8 ? 436 (encSize > (size_t)(1<<((charSize*8)-1))-1 ? 437 charSize*2 : charSize) : 0; 438 439 ent.offset = strPos; 440 441 const size_t totalSize = lenSize + encLenSize + 442 ((mUTF8 ? encSize : strSize)+1)*charSize; 443 444 void* dat = (void*)pool->editData(preSize + strPos + totalSize); 445 if (dat == NULL) { 446 fprintf(stderr, "ERROR: Out of memory for string pool\n"); 447 return NO_MEMORY; 448 } 449 dat = (uint8_t*)dat + preSize + strPos; 450 if (mUTF8) { 451 uint8_t* strings = (uint8_t*)dat; 452 453 ENCODE_LENGTH(strings, sizeof(uint8_t), strSize) 454 455 ENCODE_LENGTH(strings, sizeof(uint8_t), encSize) 456 457 strncpy((char*)strings, encStr, encSize+1); 458 } else { 459 uint16_t* strings = (uint16_t*)dat; 460 461 ENCODE_LENGTH(strings, sizeof(uint16_t), strSize) 462 463 strcpy16_htod(strings, ent.value); 464 } 465 466 strPos += totalSize; 467 } 468 469 // Pad ending string position up to a uint32_t boundary. 470 471 if (strPos&0x3) { 472 size_t padPos = ((strPos+3)&~0x3); 473 uint8_t* dat = (uint8_t*)pool->editData(preSize + padPos); 474 if (dat == NULL) { 475 fprintf(stderr, "ERROR: Out of memory padding string pool\n"); 476 return NO_MEMORY; 477 } 478 memset(dat+preSize+strPos, 0, padPos-strPos); 479 strPos = padPos; 480 } 481 482 // Build the pool of style spans. 483 484 size_t styPos = strPos; 485 for (i=0; i<STYLES; i++) { 486 entry_style& ent = mEntryStyleArray.editItemAt(i); 487 const size_t N = ent.spans.size(); 488 const size_t totalSize = (N*sizeof(ResStringPool_span)) 489 + sizeof(ResStringPool_ref); 490 491 ent.offset = styPos-strPos; 492 uint8_t* dat = (uint8_t*)pool->editData(preSize + styPos + totalSize); 493 if (dat == NULL) { 494 fprintf(stderr, "ERROR: Out of memory for string styles\n"); 495 return NO_MEMORY; 496 } 497 ResStringPool_span* span = (ResStringPool_span*)(dat+preSize+styPos); 498 for (size_t i=0; i<N; i++) { 499 span->name.index = htodl(ent.spans[i].span.name.index); 500 span->firstChar = htodl(ent.spans[i].span.firstChar); 501 span->lastChar = htodl(ent.spans[i].span.lastChar); 502 span++; 503 } 504 span->name.index = htodl(ResStringPool_span::END); 505 506 styPos += totalSize; 507 } 508 509 if (STYLES > 0) { 510 // Add full terminator at the end (when reading we validate that 511 // the end of the pool is fully terminated to simplify error 512 // checking). 513 size_t extra = sizeof(ResStringPool_span)-sizeof(ResStringPool_ref); 514 uint8_t* dat = (uint8_t*)pool->editData(preSize + styPos + extra); 515 if (dat == NULL) { 516 fprintf(stderr, "ERROR: Out of memory for string styles\n"); 517 return NO_MEMORY; 518 } 519 uint32_t* p = (uint32_t*)(dat+preSize+styPos); 520 while (extra > 0) { 521 *p++ = htodl(ResStringPool_span::END); 522 extra -= sizeof(uint32_t); 523 } 524 styPos += extra; 525 } 526 527 // Write header. 528 529 ResStringPool_header* header = 530 (ResStringPool_header*)pool->padData(sizeof(uint32_t)); 531 if (header == NULL) { 532 fprintf(stderr, "ERROR: Out of memory for string pool\n"); 533 return NO_MEMORY; 534 } 535 memset(header, 0, sizeof(*header)); 536 header->header.type = htods(RES_STRING_POOL_TYPE); 537 header->header.headerSize = htods(sizeof(*header)); 538 header->header.size = htodl(pool->getSize()); 539 header->stringCount = htodl(ENTRIES); 540 header->styleCount = htodl(STYLES); 541 if (mUTF8) { 542 header->flags |= htodl(ResStringPool_header::UTF8_FLAG); 543 } 544 header->stringsStart = htodl(preSize); 545 header->stylesStart = htodl(STYLES > 0 ? (preSize+strPos) : 0); 546 547 // Write string index array. 548 549 uint32_t* index = (uint32_t*)(header+1); 550 for (i=0; i<ENTRIES; i++) { 551 entry& ent = mEntries.editItemAt(mEntryArray[i]); 552 *index++ = htodl(ent.offset); 553 NOISY(printf("Writing entry #%d: \"%s\" ent=%d off=%d\n", i, 554 String8(ent.value).string(), 555 mEntryArray[i], ent.offset)); 556 } 557 558 // Write style index array. 559 560 for (i=0; i<STYLES; i++) { 561 *index++ = htodl(mEntryStyleArray[i].offset); 562 } 563 564 return NO_ERROR; 565} 566 567ssize_t StringPool::offsetForString(const String16& val) const 568{ 569 const Vector<size_t>* indices = offsetsForString(val); 570 ssize_t res = indices != NULL && indices->size() > 0 ? indices->itemAt(0) : -1; 571 NOISY(printf("Offset for string %s: %d (%s)\n", String8(val).string(), res, 572 res >= 0 ? String8(mEntries[mEntryArray[res]].value).string() : String8())); 573 return res; 574} 575 576const Vector<size_t>* StringPool::offsetsForString(const String16& val) const 577{ 578 ssize_t pos = mValues.valueFor(val); 579 if (pos < 0) { 580 return NULL; 581 } 582 return &mEntries[mEntryArray[pos]].indices; 583} 584