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 "StringPool.h" 86c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn#include "ResourceTable.h" 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/ByteOrder.h> 116c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn#include <utils/SortedVector.h> 12fe75d62eba3935d2d1a4a7790fc7459ded241ad3Jeff Brown#include <cutils/qsort_r_compat.h> 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael#if HAVE_PRINTF_ZD 15f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael# define ZD "%zd" 16f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael# define ZD_TYPE ssize_t 17f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael#else 18f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael# define ZD "%ld" 19f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael# define ZD_TYPE long 20f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael#endif 21f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define NOISY(x) //x 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid strcpy16_htod(uint16_t* dst, const uint16_t* src) 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (*src) { 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char16_t s = htods(*src); 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *dst++ = s; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project src++; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *dst = 0; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid printStringPool(const ResStringPool* pool) 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 366c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn SortedVector<const void*> uniqueStrings; 376c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn const size_t N = pool->size(); 386c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn for (size_t i=0; i<N; i++) { 396c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn size_t len; 406c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (pool->isUTF8()) { 416c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn uniqueStrings.add(pool->string8At(i, &len)); 426c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } else { 436c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn uniqueStrings.add(pool->stringAt(i, &len)); 446c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 456c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 466c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 476c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn printf("String pool of " ZD " unique %s %s strings, " ZD " entries and " 486c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn ZD " styles using " ZD " bytes:\n", 496c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn (ZD_TYPE)uniqueStrings.size(), pool->isUTF8() ? "UTF-8" : "UTF-16", 506c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn pool->isSorted() ? "sorted" : "non-sorted", 516c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn (ZD_TYPE)N, (ZD_TYPE)pool->styleCount(), (ZD_TYPE)pool->bytes()); 526c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const size_t NS = pool->size(); 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (size_t s=0; s<NS; s++) { 556c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn String8 str = pool->string8ObjectAt(s); 566c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn printf("String #" ZD ": %s\n", (ZD_TYPE) s, str.string()); 576c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 586c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn} 596c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 606c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne HackbornString8 StringPool::entry::makeConfigsString() const { 616c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn String8 configStr(configTypeName); 626c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (configStr.size() > 0) configStr.append(" "); 636c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (configs.size() > 0) { 646c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn for (size_t j=0; j<configs.size(); j++) { 656c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (j > 0) configStr.append(", "); 666c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn configStr.append(configs[j].toString()); 67780d2a1b714724d85227141c76b3c64f543f00b4Kenny Root } 686c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } else { 696c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn configStr = "(none)"; 706c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 716c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn return configStr; 726c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn} 73780d2a1b714724d85227141c76b3c64f543f00b4Kenny Root 746c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackbornint StringPool::entry::compare(const entry& o) const { 7561361f376b47d45966b1ca0d24d51622304c93c3Jeff Brown // Strings with styles go first, to reduce the size of the styles array. 7661361f376b47d45966b1ca0d24d51622304c93c3Jeff Brown // We don't care about the relative order of these strings. 776c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (hasStyles) { 786c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn return o.hasStyles ? 0 : -1; 796c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 806c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (o.hasStyles) { 816c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn return 1; 826c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 8361361f376b47d45966b1ca0d24d51622304c93c3Jeff Brown 8461361f376b47d45966b1ca0d24d51622304c93c3Jeff Brown // Sort unstyled strings by type, then by logical configuration. 856c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn int comp = configTypeName.compare(o.configTypeName); 866c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (comp != 0) { 876c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn return comp; 886c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 896c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn const size_t LHN = configs.size(); 906c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn const size_t RHN = o.configs.size(); 916c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn size_t i=0; 926c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn while (i < LHN && i < RHN) { 936c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn comp = configs[i].compareLogical(o.configs[i]); 946c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (comp != 0) { 956c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn return comp; 966c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 976c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn i++; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 996c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (LHN < RHN) return -1; 1006c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn else if (LHN > RHN) return 1; 1016c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn return 0; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 104345b7eb8749d6954942fd4e961fff9f2f854934cJeff BrownStringPool::StringPool(bool utf8) : 105345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown mUTF8(utf8), mValues(-1) 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1096c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackbornssize_t StringPool::add(const String16& value, const Vector<entry_style_span>& spans, 1106c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn const String8* configTypeName, const ResTable_config* config) 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 112345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown ssize_t res = add(value, false, configTypeName, config); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res >= 0) { 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addStyleSpans(res, spans); 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return res; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 119345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brownssize_t StringPool::add(const String16& value, 1206c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn bool mergeDuplicates, const String8* configTypeName, const ResTable_config* config) 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t vidx = mValues.indexOfKey(value); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t pos = vidx >= 0 ? mValues.valueAt(vidx) : -1; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t eidx = pos >= 0 ? mEntryArray.itemAt(pos) : -1; 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (eidx < 0) { 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eidx = mEntries.add(entry(value)); 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (eidx < 0) { 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr, "Failure adding string %s\n", String8(value).string()); 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return eidx; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1336c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (configTypeName != NULL) { 1346c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn entry& ent = mEntries.editItemAt(eidx); 1356c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn NOISY(printf("*** adding config type name %s, was %s\n", 1366c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn configTypeName->string(), ent.configTypeName.string())); 1376c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (ent.configTypeName.size() <= 0) { 1386c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn ent.configTypeName = *configTypeName; 1396c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } else if (ent.configTypeName != *configTypeName) { 1406c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn ent.configTypeName = " "; 1416c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 1426c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 1436c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1446c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (config != NULL) { 1456c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // Add this to the set of configs associated with the string. 1466c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn entry& ent = mEntries.editItemAt(eidx); 1476c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn size_t addPos; 1486c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn for (addPos=0; addPos<ent.configs.size(); addPos++) { 1496c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn int cmp = ent.configs.itemAt(addPos).compareLogical(*config); 1506c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (cmp >= 0) { 1516c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (cmp > 0) { 1526c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn NOISY(printf("*** inserting config: %s\n", config->toString().string())); 1536c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn ent.configs.insertAt(*config, addPos); 1546c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 1556c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn break; 1566c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 1576c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 1586c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (addPos >= ent.configs.size()) { 1596c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn NOISY(printf("*** adding config: %s\n", config->toString().string())); 1606c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn ent.configs.add(*config); 1616c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 1626c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 1636c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const bool first = vidx < 0; 165db6e67d8ec081f43bcf14155741e268a38915719Ben Gruver const bool styled = (pos >= 0 && (size_t)pos < mEntryStyleArray.size()) ? 166db6e67d8ec081f43bcf14155741e268a38915719Ben Gruver mEntryStyleArray[pos].spans.size() : 0; 167db6e67d8ec081f43bcf14155741e268a38915719Ben Gruver if (first || styled || !mergeDuplicates) { 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos = mEntryArray.add(eidx); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (first) { 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vidx = mValues.add(value, pos); 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 172345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown entry& ent = mEntries.editItemAt(eidx); 173345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown ent.indices.add(pos); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NOISY(printf("Adding string %s to pool: pos=%d eidx=%d vidx=%d\n", 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String8(value).string(), pos, eidx, vidx)); 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return pos; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t StringPool::addStyleSpan(size_t idx, const String16& name, 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t start, uint32_t end) 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entry_style_span span; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project span.name = name; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project span.span.firstChar = start; 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project span.span.lastChar = end; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return addStyleSpan(idx, span); 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t StringPool::addStyleSpans(size_t idx, const Vector<entry_style_span>& spans) 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const size_t N=spans.size(); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (size_t i=0; i<N; i++) { 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t err = addStyleSpan(idx, spans[i]); 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != NO_ERROR) { 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return err; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t StringPool::addStyleSpan(size_t idx, const entry_style_span& span) 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Place blank entries in the span array up to this index. 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (mEntryStyleArray.size() <= idx) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEntryStyleArray.add(); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entry_style& style = mEntryStyleArray.editItemAt(idx); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style.spans.add(span); 2136c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn mEntries.editItemAt(mEntryArray[idx]).hasStyles = true; 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 217c9fd9263feedac32e4f5b1f13a3246347efdc25fJeff Brownint StringPool::config_sort(void* state, const void* lhs, const void* rhs) 2186c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn{ 2196c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn StringPool* pool = (StringPool*)state; 220c9fd9263feedac32e4f5b1f13a3246347efdc25fJeff Brown const entry& lhe = pool->mEntries[pool->mEntryArray[*static_cast<const size_t*>(lhs)]]; 221c9fd9263feedac32e4f5b1f13a3246347efdc25fJeff Brown const entry& rhe = pool->mEntries[pool->mEntryArray[*static_cast<const size_t*>(rhs)]]; 2226c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn return lhe.compare(rhe); 2236c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn} 2246c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 2256c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackbornvoid StringPool::sortByConfig() 2266c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn{ 2276c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn LOG_ALWAYS_FATAL_IF(mOriginalPosToNewPos.size() > 0, "Can't sort string pool after already sorted."); 2286c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 2296c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn const size_t N = mEntryArray.size(); 2306c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 2316c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // This is a vector that starts out with a 1:1 mapping to entries 2326c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // in the array, which we will sort to come up with the desired order. 2336c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // At that point it maps from the new position in the array to the 2346c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // original position the entry appeared. 2356c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn Vector<size_t> newPosToOriginalPos; 236c9fd9263feedac32e4f5b1f13a3246347efdc25fJeff Brown newPosToOriginalPos.setCapacity(N); 237c9fd9263feedac32e4f5b1f13a3246347efdc25fJeff Brown for (size_t i=0; i < N; i++) { 2386c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn newPosToOriginalPos.add(i); 2396c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 2406c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 2416c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // Sort the array. 2426c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn NOISY(printf("SORTING STRINGS BY CONFIGURATION...\n")); 243c9fd9263feedac32e4f5b1f13a3246347efdc25fJeff Brown // Vector::sort uses insertion sort, which is very slow for this data set. 244c9fd9263feedac32e4f5b1f13a3246347efdc25fJeff Brown // Use quicksort instead because we don't need a stable sort here. 245fe75d62eba3935d2d1a4a7790fc7459ded241ad3Jeff Brown qsort_r_compat(newPosToOriginalPos.editArray(), N, sizeof(size_t), this, config_sort); 246c9fd9263feedac32e4f5b1f13a3246347efdc25fJeff Brown //newPosToOriginalPos.sort(config_sort, this); 2476c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn NOISY(printf("DONE SORTING STRINGS BY CONFIGURATION.\n")); 2486c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 2496c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // Create the reverse mapping from the original position in the array 2506c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // to the new position where it appears in the sorted array. This is 2516c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // so that clients can re-map any positions they had previously stored. 2526c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn mOriginalPosToNewPos = newPosToOriginalPos; 2536c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn for (size_t i=0; i<N; i++) { 2546c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn mOriginalPosToNewPos.editItemAt(newPosToOriginalPos[i]) = i; 2556c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 2566c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 2576c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn#if 0 2586c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn SortedVector<entry> entries; 2596c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 2606c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn for (size_t i=0; i<N; i++) { 2616c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn printf("#%d was %d: %s\n", i, newPosToOriginalPos[i], 2626c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn mEntries[mEntryArray[newPosToOriginalPos[i]]].makeConfigsString().string()); 2636c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn entries.add(mEntries[mEntryArray[i]]); 2646c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 2656c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 2666c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn for (size_t i=0; i<entries.size(); i++) { 2676c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn printf("Sorted config #%d: %s\n", i, 2686c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn entries[i].makeConfigsString().string()); 2696c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 2706c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn#endif 2716c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 2726c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // Now we rebuild the arrays. 2736c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn Vector<entry> newEntries; 2746c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn Vector<size_t> newEntryArray; 2756c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn Vector<entry_style> newEntryStyleArray; 2766c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn DefaultKeyedVector<size_t, size_t> origOffsetToNewOffset; 2776c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 2786c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn for (size_t i=0; i<N; i++) { 2796c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // We are filling in new offset 'i'; oldI is where we can find it 2806c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // in the original data structure. 2816c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn size_t oldI = newPosToOriginalPos[i]; 2826c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // This is the actual entry associated with the old offset. 2836c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn const entry& oldEnt = mEntries[mEntryArray[oldI]]; 2846c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // This is the same entry the last time we added it to the 2856c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // new entry array, if any. 2866c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn ssize_t newIndexOfOffset = origOffsetToNewOffset.indexOfKey(oldI); 2876c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn size_t newOffset; 2886c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (newIndexOfOffset < 0) { 2896c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // This is the first time we have seen the entry, so add 2906c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // it. 2916c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn newOffset = newEntries.add(oldEnt); 2926c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn newEntries.editItemAt(newOffset).indices.clear(); 2936c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } else { 2946c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // We have seen this entry before, use the existing one 2956c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // instead of adding it again. 2966c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn newOffset = origOffsetToNewOffset.valueAt(newIndexOfOffset); 2976c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 2986c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // Update the indices to include this new position. 2996c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn newEntries.editItemAt(newOffset).indices.add(i); 3006c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // And add the offset of the entry to the new entry array. 3016c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn newEntryArray.add(newOffset); 3026c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // Add any old style to the new style array. 3036c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (mEntryStyleArray.size() > 0) { 3046c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (oldI < mEntryStyleArray.size()) { 3056c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn newEntryStyleArray.add(mEntryStyleArray[oldI]); 3066c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } else { 3076c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn newEntryStyleArray.add(entry_style()); 3086c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 3096c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 3106c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 3116c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 3126c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // Now trim any entries at the end of the new style array that are 3136c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // not needed. 3146c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn for (ssize_t i=newEntryStyleArray.size()-1; i>=0; i--) { 3156c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn const entry_style& style = newEntryStyleArray[i]; 3166c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn if (style.spans.size() > 0) { 3176c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // That's it. 3186c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn break; 3196c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 3206c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // This one is not needed; remove. 3216c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn newEntryStyleArray.removeAt(i); 3226c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 3236c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 3246c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // All done, install the new data structures and upate mValues with 3256c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // the new positions. 3266c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn mEntries = newEntries; 3276c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn mEntryArray = newEntryArray; 3286c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn mEntryStyleArray = newEntryStyleArray; 3296c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn mValues.clear(); 3306c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn for (size_t i=0; i<mEntries.size(); i++) { 3316c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn const entry& ent = mEntries[i]; 3326c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn mValues.add(ent.value, ent.indices[0]); 3336c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 3346c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 3356c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn#if 0 3366c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn printf("FINAL SORTED STRING CONFIGS:\n"); 3376c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn for (size_t i=0; i<mEntries.size(); i++) { 3386c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn const entry& ent = mEntries[i]; 3396c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn printf("#" ZD " %s: %s\n", (ZD_TYPE)i, ent.makeConfigsString().string(), 3406c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn String8(ent.value).string()); 3416c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 3426c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn#endif 3436c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn} 3446c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsp<AaptFile> StringPool::createStringBlock() 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<AaptFile> pool = new AaptFile(String8(), AaptGroupEntry(), 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String8()); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t err = writeStringBlock(pool); 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return err == NO_ERROR ? pool : NULL; 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35319138468caf7050d482dc15f35a344eab11bb756Kenny Root#define ENCODE_LENGTH(str, chrsz, strSize) \ 35419138468caf7050d482dc15f35a344eab11bb756Kenny Root{ \ 35519138468caf7050d482dc15f35a344eab11bb756Kenny Root size_t maxMask = 1 << ((chrsz*8)-1); \ 35619138468caf7050d482dc15f35a344eab11bb756Kenny Root size_t maxSize = maxMask-1; \ 35719138468caf7050d482dc15f35a344eab11bb756Kenny Root if (strSize > maxSize) { \ 35819138468caf7050d482dc15f35a344eab11bb756Kenny Root *str++ = maxMask | ((strSize>>(chrsz*8))&maxSize); \ 35919138468caf7050d482dc15f35a344eab11bb756Kenny Root } \ 36019138468caf7050d482dc15f35a344eab11bb756Kenny Root *str++ = strSize; \ 36119138468caf7050d482dc15f35a344eab11bb756Kenny Root} 36219138468caf7050d482dc15f35a344eab11bb756Kenny Root 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t StringPool::writeStringBlock(const sp<AaptFile>& pool) 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Allow appending. Sorry this is a little wacky. 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pool->getSize() > 0) { 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<AaptFile> block = createStringBlock(); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (block == NULL) { 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return UNKNOWN_ERROR; 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t res = pool->writeData(block->getData(), block->getSize()); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (res >= 0) ? (status_t)NO_ERROR : res; 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // First we need to add all style span names to the string pool. 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We do this now (instead of when the span is added) so that these 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // will appear at the end of the pool, not disrupting the order 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // our client placed their own strings in it. 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const size_t STYLES = mEntryStyleArray.size(); 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t i; 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (i=0; i<STYLES; i++) { 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entry_style& style = mEntryStyleArray.editItemAt(i); 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const size_t N = style.spans.size(); 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (size_t i=0; i<N; i++) { 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entry_style_span& span = style.spans.editItemAt(i); 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t idx = add(span.name, true); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (idx < 0) { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr, "Error adding span for style tag '%s'\n", 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String8(span.name).string()); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return idx; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project span.span.name.index = (uint32_t)idx; 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 398345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown const size_t ENTRIES = mEntryArray.size(); 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Now build the pool of unique strings. 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const size_t STRINGS = mEntries.size(); 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const size_t preSize = sizeof(ResStringPool_header) 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + (sizeof(uint32_t)*ENTRIES) 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + (sizeof(uint32_t)*STYLES); 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pool->editData(preSize) == NULL) { 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr, "ERROR: Out of memory for string pool\n"); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_MEMORY; 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41119138468caf7050d482dc15f35a344eab11bb756Kenny Root const size_t charSize = mUTF8 ? sizeof(uint8_t) : sizeof(char16_t); 41219138468caf7050d482dc15f35a344eab11bb756Kenny Root 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t strPos = 0; 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (i=0; i<STRINGS; i++) { 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entry& ent = mEntries.editItemAt(i); 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const size_t strSize = (ent.value.size()); 41719138468caf7050d482dc15f35a344eab11bb756Kenny Root const size_t lenSize = strSize > (size_t)(1<<((charSize*8)-1))-1 ? 41819138468caf7050d482dc15f35a344eab11bb756Kenny Root charSize*2 : charSize; 41919138468caf7050d482dc15f35a344eab11bb756Kenny Root 42019138468caf7050d482dc15f35a344eab11bb756Kenny Root String8 encStr; 42119138468caf7050d482dc15f35a344eab11bb756Kenny Root if (mUTF8) { 42219138468caf7050d482dc15f35a344eab11bb756Kenny Root encStr = String8(ent.value); 42319138468caf7050d482dc15f35a344eab11bb756Kenny Root } 42419138468caf7050d482dc15f35a344eab11bb756Kenny Root 42519138468caf7050d482dc15f35a344eab11bb756Kenny Root const size_t encSize = mUTF8 ? encStr.size() : 0; 42619138468caf7050d482dc15f35a344eab11bb756Kenny Root const size_t encLenSize = mUTF8 ? 42719138468caf7050d482dc15f35a344eab11bb756Kenny Root (encSize > (size_t)(1<<((charSize*8)-1))-1 ? 42819138468caf7050d482dc15f35a344eab11bb756Kenny Root charSize*2 : charSize) : 0; 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ent.offset = strPos; 43119138468caf7050d482dc15f35a344eab11bb756Kenny Root 43219138468caf7050d482dc15f35a344eab11bb756Kenny Root const size_t totalSize = lenSize + encLenSize + 43319138468caf7050d482dc15f35a344eab11bb756Kenny Root ((mUTF8 ? encSize : strSize)+1)*charSize; 43419138468caf7050d482dc15f35a344eab11bb756Kenny Root 43519138468caf7050d482dc15f35a344eab11bb756Kenny Root void* dat = (void*)pool->editData(preSize + strPos + totalSize); 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dat == NULL) { 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr, "ERROR: Out of memory for string pool\n"); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_MEMORY; 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 44019138468caf7050d482dc15f35a344eab11bb756Kenny Root dat = (uint8_t*)dat + preSize + strPos; 44119138468caf7050d482dc15f35a344eab11bb756Kenny Root if (mUTF8) { 44219138468caf7050d482dc15f35a344eab11bb756Kenny Root uint8_t* strings = (uint8_t*)dat; 44319138468caf7050d482dc15f35a344eab11bb756Kenny Root 44419138468caf7050d482dc15f35a344eab11bb756Kenny Root ENCODE_LENGTH(strings, sizeof(uint8_t), strSize) 44519138468caf7050d482dc15f35a344eab11bb756Kenny Root 44619138468caf7050d482dc15f35a344eab11bb756Kenny Root ENCODE_LENGTH(strings, sizeof(uint8_t), encSize) 44719138468caf7050d482dc15f35a344eab11bb756Kenny Root 44819138468caf7050d482dc15f35a344eab11bb756Kenny Root strncpy((char*)strings, encStr, encSize+1); 44919138468caf7050d482dc15f35a344eab11bb756Kenny Root } else { 45019138468caf7050d482dc15f35a344eab11bb756Kenny Root uint16_t* strings = (uint16_t*)dat; 45119138468caf7050d482dc15f35a344eab11bb756Kenny Root 45219138468caf7050d482dc15f35a344eab11bb756Kenny Root ENCODE_LENGTH(strings, sizeof(uint16_t), strSize) 45319138468caf7050d482dc15f35a344eab11bb756Kenny Root 45419138468caf7050d482dc15f35a344eab11bb756Kenny Root strcpy16_htod(strings, ent.value); 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 45719138468caf7050d482dc15f35a344eab11bb756Kenny Root strPos += totalSize; 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Pad ending string position up to a uint32_t boundary. 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (strPos&0x3) { 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t padPos = ((strPos+3)&~0x3); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint8_t* dat = (uint8_t*)pool->editData(preSize + padPos); 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dat == NULL) { 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr, "ERROR: Out of memory padding string pool\n"); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_MEMORY; 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(dat+preSize+strPos, 0, padPos-strPos); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strPos = padPos; 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Build the pool of style spans. 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t styPos = strPos; 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (i=0; i<STYLES; i++) { 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entry_style& ent = mEntryStyleArray.editItemAt(i); 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const size_t N = ent.spans.size(); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const size_t totalSize = (N*sizeof(ResStringPool_span)) 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + sizeof(ResStringPool_ref); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ent.offset = styPos-strPos; 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint8_t* dat = (uint8_t*)pool->editData(preSize + styPos + totalSize); 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dat == NULL) { 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr, "ERROR: Out of memory for string styles\n"); 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_MEMORY; 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ResStringPool_span* span = (ResStringPool_span*)(dat+preSize+styPos); 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (size_t i=0; i<N; i++) { 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project span->name.index = htodl(ent.spans[i].span.name.index); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project span->firstChar = htodl(ent.spans[i].span.firstChar); 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project span->lastChar = htodl(ent.spans[i].span.lastChar); 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project span++; 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project span->name.index = htodl(ResStringPool_span::END); 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project styPos += totalSize; 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (STYLES > 0) { 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Add full terminator at the end (when reading we validate that 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the end of the pool is fully terminated to simplify error 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // checking). 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t extra = sizeof(ResStringPool_span)-sizeof(ResStringPool_ref); 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint8_t* dat = (uint8_t*)pool->editData(preSize + styPos + extra); 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dat == NULL) { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr, "ERROR: Out of memory for string styles\n"); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_MEMORY; 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t* p = (uint32_t*)(dat+preSize+styPos); 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (extra > 0) { 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *p++ = htodl(ResStringPool_span::END); 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extra -= sizeof(uint32_t); 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project styPos += extra; 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Write header. 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ResStringPool_header* header = 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (ResStringPool_header*)pool->padData(sizeof(uint32_t)); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (header == NULL) { 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fprintf(stderr, "ERROR: Out of memory for string pool\n"); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_MEMORY; 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(header, 0, sizeof(*header)); 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project header->header.type = htods(RES_STRING_POOL_TYPE); 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project header->header.headerSize = htods(sizeof(*header)); 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project header->header.size = htodl(pool->getSize()); 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project header->stringCount = htodl(ENTRIES); 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project header->styleCount = htodl(STYLES); 53219138468caf7050d482dc15f35a344eab11bb756Kenny Root if (mUTF8) { 53319138468caf7050d482dc15f35a344eab11bb756Kenny Root header->flags |= htodl(ResStringPool_header::UTF8_FLAG); 53419138468caf7050d482dc15f35a344eab11bb756Kenny Root } 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project header->stringsStart = htodl(preSize); 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project header->stylesStart = htodl(STYLES > 0 ? (preSize+strPos) : 0); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Write string index array. 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t* index = (uint32_t*)(header+1); 541345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown for (i=0; i<ENTRIES; i++) { 542345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown entry& ent = mEntries.editItemAt(mEntryArray[i]); 543345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown *index++ = htodl(ent.offset); 544345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown NOISY(printf("Writing entry #%d: \"%s\" ent=%d off=%d\n", i, 545345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown String8(ent.value).string(), 546345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown mEntryArray[i], ent.offset)); 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Write style index array. 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 551345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown for (i=0; i<STYLES; i++) { 552345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown *index++ = htodl(mEntryStyleArray[i].offset); 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectssize_t StringPool::offsetForString(const String16& val) const 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const Vector<size_t>* indices = offsetsForString(val); 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t res = indices != NULL && indices->size() > 0 ? indices->itemAt(0) : -1; 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NOISY(printf("Offset for string %s: %d (%s)\n", String8(val).string(), res, 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project res >= 0 ? String8(mEntries[mEntryArray[res]].value).string() : String8())); 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return res; 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst Vector<size_t>* StringPool::offsetsForString(const String16& val) const 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t pos = mValues.valueFor(val); 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pos < 0) { 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return &mEntries[mEntryArray[pos]].indices; 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 575