1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Build resource files from raw assets. 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "StringPool.h" 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/ByteOrder.h> 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/SortedVector.h> 100de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert 110de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert#include <algorithm> 120de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert 130de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert#include "ResourceTable.h" 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 152412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe// SSIZE: mingw does not have signed size_t == ssize_t. 16b12f2410c7bdbf90bd8a77b897846ee2763e3037Elliott Hughes#if !defined(_WIN32) 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# define ZD "%zd" 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# define ZD_TYPE ssize_t 192412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe# define SSIZE(x) x 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#else 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# define ZD "%ld" 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# define ZD_TYPE long 232412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe# define SSIZE(x) (signed size_t)x 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 262412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe// Set to true for noisy debug output. 272412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampestatic const bool kIsDebug = false; 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 294bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski#if __cplusplus >= 201103L 30f348c15ecf78e9d58b8238ffcf1d78a279e3a862Dan Albertvoid strcpy16_htod(char16_t* dst, const char16_t* src) 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (*src) { 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char16_t s = htods(*src); 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *dst++ = s; 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski src++; 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *dst = 0; 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 394bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski#endif 404bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski 414bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinskivoid strcpy16_htod(uint16_t* dst, const char16_t* src) 424bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski{ 434bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski while (*src) { 444bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski uint16_t s = htods(static_cast<uint16_t>(*src)); 454bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski *dst++ = s; 464bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski src++; 474bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski } 484bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski *dst = 0; 494bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski} 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid printStringPool(const ResStringPool* pool) 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 5325e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski if (pool->getError() == NO_INIT) { 5425e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski printf("String pool is unitialized.\n"); 5525e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski return; 5625e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski } else if (pool->getError() != NO_ERROR) { 5725e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski printf("String pool is corrupt/invalid.\n"); 5825e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski return; 5925e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski } 6025e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SortedVector<const void*> uniqueStrings; 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = pool->size(); 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (pool->isUTF8()) { 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uniqueStrings.add(pool->string8At(i, &len)); 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uniqueStrings.add(pool->stringAt(i, &len)); 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("String pool of " ZD " unique %s %s strings, " ZD " entries and " 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZD " styles using " ZD " bytes:\n", 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (ZD_TYPE)uniqueStrings.size(), pool->isUTF8() ? "UTF-8" : "UTF-16", 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski pool->isSorted() ? "sorted" : "non-sorted", 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (ZD_TYPE)N, (ZD_TYPE)pool->styleCount(), (ZD_TYPE)pool->bytes()); 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NS = pool->size(); 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t s=0; s<NS; s++) { 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 str = pool->string8ObjectAt(s); 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("String #" ZD ": %s\n", (ZD_TYPE) s, str.string()); 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiString8 StringPool::entry::makeConfigsString() const { 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 configStr(configTypeName); 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (configStr.size() > 0) configStr.append(" "); 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (configs.size() > 0) { 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t j=0; j<configs.size(); j++) { 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (j > 0) configStr.append(", "); 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski configStr.append(configs[j].toString()); 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski configStr = "(none)"; 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return configStr; 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint StringPool::entry::compare(const entry& o) const { 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Strings with styles go first, to reduce the size of the styles array. 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // We don't care about the relative order of these strings. 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasStyles) { 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return o.hasStyles ? 0 : -1; 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (o.hasStyles) { 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Sort unstyled strings by type, then by logical configuration. 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int comp = configTypeName.compare(o.configTypeName); 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (comp != 0) { 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return comp; 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t LHN = configs.size(); 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t RHN = o.configs.size(); 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t i=0; 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (i < LHN && i < RHN) { 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski comp = configs[i].compareLogical(o.configs[i]); 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (comp != 0) { 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return comp; 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski i++; 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (LHN < RHN) return -1; 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else if (LHN > RHN) return 1; 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiStringPool::StringPool(bool utf8) : 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mUTF8(utf8), mValues(-1) 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t StringPool::add(const String16& value, const Vector<entry_style_span>& spans, 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String8* configTypeName, const ResTable_config* config) 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t res = add(value, false, configTypeName, config); 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (res >= 0) { 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski addStyleSpans(res, spans); 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return res; 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t StringPool::add(const String16& value, 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool mergeDuplicates, const String8* configTypeName, const ResTable_config* config) 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t vidx = mValues.indexOfKey(value); 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t pos = vidx >= 0 ? mValues.valueAt(vidx) : -1; 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t eidx = pos >= 0 ? mEntryArray.itemAt(pos) : -1; 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (eidx < 0) { 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski eidx = mEntries.add(entry(value)); 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (eidx < 0) { 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Failure adding string %s\n", String8(value).string()); 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return eidx; 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (configTypeName != NULL) { 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry& ent = mEntries.editItemAt(eidx); 1602412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 1612412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("*** adding config type name %s, was %s\n", 1622412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe configTypeName->string(), ent.configTypeName.string()); 1632412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (ent.configTypeName.size() <= 0) { 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ent.configTypeName = *configTypeName; 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (ent.configTypeName != *configTypeName) { 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ent.configTypeName = " "; 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (config != NULL) { 172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Add this to the set of configs associated with the string. 173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry& ent = mEntries.editItemAt(eidx); 174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t addPos; 175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (addPos=0; addPos<ent.configs.size(); addPos++) { 176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int cmp = ent.configs.itemAt(addPos).compareLogical(*config); 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (cmp >= 0) { 178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (cmp > 0) { 1792412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 1802412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("*** inserting config: %s\n", config->toString().string()); 1812412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ent.configs.insertAt(*config, addPos); 183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (addPos >= ent.configs.size()) { 1882412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 1892412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("*** adding config: %s\n", config->toString().string()); 1902412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ent.configs.add(*config); 192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const bool first = vidx < 0; 196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const bool styled = (pos >= 0 && (size_t)pos < mEntryStyleArray.size()) ? 197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mEntryStyleArray[pos].spans.size() : 0; 198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (first || styled || !mergeDuplicates) { 199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski pos = mEntryArray.add(eidx); 200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (first) { 201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski vidx = mValues.add(value, pos); 202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry& ent = mEntries.editItemAt(eidx); 204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ent.indices.add(pos); 205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2072412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 2082412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Adding string %s to pool: pos=%zd eidx=%zd vidx=%zd\n", 2092412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe String8(value).string(), SSIZE(pos), SSIZE(eidx), SSIZE(vidx)); 2102412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 2112412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe 212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return pos; 213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t StringPool::addStyleSpan(size_t idx, const String16& name, 216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t start, uint32_t end) 217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry_style_span span; 219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski span.name = name; 220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski span.span.firstChar = start; 221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski span.span.lastChar = end; 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return addStyleSpan(idx, span); 223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t StringPool::addStyleSpans(size_t idx, const Vector<entry_style_span>& spans) 226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N=spans.size(); 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = addStyleSpan(idx, spans[i]); 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t StringPool::addStyleSpan(size_t idx, const entry_style_span& span) 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Place blank entries in the span array up to this index. 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (mEntryStyleArray.size() <= idx) { 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mEntryStyleArray.add(); 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry_style& style = mEntryStyleArray.editItemAt(idx); 245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski style.spans.add(span); 246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mEntries.editItemAt(mEntryArray[idx]).hasStyles = true; 247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2500de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan AlbertStringPool::ConfigSorter::ConfigSorter(const StringPool& pool) : pool(pool) 2510de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert{ 2520de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert} 2530de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert 2540de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albertbool StringPool::ConfigSorter::operator()(size_t l, size_t r) 255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2560de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert const StringPool::entry& lhe = pool.mEntries[pool.mEntryArray[l]]; 2570de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert const StringPool::entry& rhe = pool.mEntries[pool.mEntryArray[r]]; 2580de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert return lhe.compare(rhe) < 0; 259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid StringPool::sortByConfig() 262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LOG_ALWAYS_FATAL_IF(mOriginalPosToNewPos.size() > 0, "Can't sort string pool after already sorted."); 264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = mEntryArray.size(); 266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This is a vector that starts out with a 1:1 mapping to entries 268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // in the array, which we will sort to come up with the desired order. 269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // At that point it maps from the new position in the array to the 270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // original position the entry appeared. 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<size_t> newPosToOriginalPos; 272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski newPosToOriginalPos.setCapacity(N); 273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i < N; i++) { 274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski newPosToOriginalPos.add(i); 275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Sort the array. 2782412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 2792412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("SORTING STRINGS BY CONFIGURATION...\n"); 2802412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 2810de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert ConfigSorter sorter(*this); 2820de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert std::sort(newPosToOriginalPos.begin(), newPosToOriginalPos.end(), sorter); 2832412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 2842412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("DONE SORTING STRINGS BY CONFIGURATION.\n"); 2852412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Create the reverse mapping from the original position in the array 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to the new position where it appears in the sorted array. This is 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // so that clients can re-map any positions they had previously stored. 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOriginalPosToNewPos = newPosToOriginalPos; 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOriginalPosToNewPos.editItemAt(newPosToOriginalPos[i]) = i; 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SortedVector<entry> entries; 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("#%d was %d: %s\n", i, newPosToOriginalPos[i], 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mEntries[mEntryArray[newPosToOriginalPos[i]]].makeConfigsString().string()); 301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entries.add(mEntries[mEntryArray[i]]); 302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<entries.size(); i++) { 305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Sorted config #%d: %s\n", i, 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entries[i].makeConfigsString().string()); 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Now we rebuild the arrays. 311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<entry> newEntries; 312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<size_t> newEntryArray; 313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<entry_style> newEntryStyleArray; 314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DefaultKeyedVector<size_t, size_t> origOffsetToNewOffset; 315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // We are filling in new offset 'i'; oldI is where we can find it 318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // in the original data structure. 319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t oldI = newPosToOriginalPos[i]; 320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This is the actual entry associated with the old offset. 321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const entry& oldEnt = mEntries[mEntryArray[oldI]]; 322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This is the same entry the last time we added it to the 323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // new entry array, if any. 324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t newIndexOfOffset = origOffsetToNewOffset.indexOfKey(oldI); 325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t newOffset; 326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (newIndexOfOffset < 0) { 327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This is the first time we have seen the entry, so add 328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // it. 329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski newOffset = newEntries.add(oldEnt); 330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski newEntries.editItemAt(newOffset).indices.clear(); 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // We have seen this entry before, use the existing one 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // instead of adding it again. 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski newOffset = origOffsetToNewOffset.valueAt(newIndexOfOffset); 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Update the indices to include this new position. 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski newEntries.editItemAt(newOffset).indices.add(i); 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // And add the offset of the entry to the new entry array. 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski newEntryArray.add(newOffset); 340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Add any old style to the new style array. 341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mEntryStyleArray.size() > 0) { 342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (oldI < mEntryStyleArray.size()) { 343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski newEntryStyleArray.add(mEntryStyleArray[oldI]); 344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski newEntryStyleArray.add(entry_style()); 346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Now trim any entries at the end of the new style array that are 351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // not needed. 352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (ssize_t i=newEntryStyleArray.size()-1; i>=0; i--) { 353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const entry_style& style = newEntryStyleArray[i]; 354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (style.spans.size() > 0) { 355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // That's it. 356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This one is not needed; remove. 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski newEntryStyleArray.removeAt(i); 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // All done, install the new data structures and upate mValues with 363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the new positions. 364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mEntries = newEntries; 365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mEntryArray = newEntryArray; 366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mEntryStyleArray = newEntryStyleArray; 367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mValues.clear(); 368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<mEntries.size(); i++) { 369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const entry& ent = mEntries[i]; 370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mValues.add(ent.value, ent.indices[0]); 371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0 374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("FINAL SORTED STRING CONFIGS:\n"); 375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<mEntries.size(); i++) { 376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const entry& ent = mEntries[i]; 377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("#" ZD " %s: %s\n", (ZD_TYPE)i, ent.makeConfigsString().string(), 378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(ent.value).string()); 379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<AaptFile> StringPool::createStringBlock() 384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptFile> pool = new AaptFile(String8(), AaptGroupEntry(), 386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8()); 387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = writeStringBlock(pool); 388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err == NO_ERROR ? pool : NULL; 389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#define ENCODE_LENGTH(str, chrsz, strSize) \ 392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ \ 393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t maxMask = 1 << ((chrsz*8)-1); \ 394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t maxSize = maxMask-1; \ 395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strSize > maxSize) { \ 396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *str++ = maxMask | ((strSize>>(chrsz*8))&maxSize); \ 397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } \ 398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *str++ = strSize; \ 399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t StringPool::writeStringBlock(const sp<AaptFile>& pool) 402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Allow appending. Sorry this is a little wacky. 404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (pool->getSize() > 0) { 405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptFile> block = createStringBlock(); 406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (block == NULL) { 407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t res = pool->writeData(block->getData(), block->getSize()); 410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (res >= 0) ? (status_t)NO_ERROR : res; 411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // First we need to add all style span names to the string pool. 414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // We do this now (instead of when the span is added) so that these 415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // will appear at the end of the pool, not disrupting the order 416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // our client placed their own strings in it. 417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t STYLES = mEntryStyleArray.size(); 419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t i; 420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<STYLES; i++) { 422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry_style& style = mEntryStyleArray.editItemAt(i); 423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = style.spans.size(); 424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry_style_span& span = style.spans.editItemAt(i); 426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = add(span.name, true); 427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Error adding span for style tag '%s'\n", 429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(span.name).string()); 430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return idx; 431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski span.span.name.index = (uint32_t)idx; 433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t ENTRIES = mEntryArray.size(); 437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Now build the pool of unique strings. 439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t STRINGS = mEntries.size(); 441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t preSize = sizeof(ResStringPool_header) 442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski + (sizeof(uint32_t)*ENTRIES) 443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski + (sizeof(uint32_t)*STYLES); 444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (pool->editData(preSize) == NULL) { 445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Out of memory for string pool\n"); 446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_MEMORY; 447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4494bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski const size_t charSize = mUTF8 ? sizeof(uint8_t) : sizeof(uint16_t); 450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t strPos = 0; 452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<STRINGS; i++) { 453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry& ent = mEntries.editItemAt(i); 454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t strSize = (ent.value.size()); 455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t lenSize = strSize > (size_t)(1<<((charSize*8)-1))-1 ? 456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski charSize*2 : charSize; 457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 encStr; 459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mUTF8) { 460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski encStr = String8(ent.value); 461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t encSize = mUTF8 ? encStr.size() : 0; 464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t encLenSize = mUTF8 ? 465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (encSize > (size_t)(1<<((charSize*8)-1))-1 ? 466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski charSize*2 : charSize) : 0; 467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ent.offset = strPos; 469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t totalSize = lenSize + encLenSize + 471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ((mUTF8 ? encSize : strSize)+1)*charSize; 472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski void* dat = (void*)pool->editData(preSize + strPos + totalSize); 474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dat == NULL) { 475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Out of memory for string pool\n"); 476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_MEMORY; 477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dat = (uint8_t*)dat + preSize + strPos; 479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mUTF8) { 480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint8_t* strings = (uint8_t*)dat; 481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ENCODE_LENGTH(strings, sizeof(uint8_t), strSize) 483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ENCODE_LENGTH(strings, sizeof(uint8_t), encSize) 485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strncpy((char*)strings, encStr, encSize+1); 487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 488f348c15ecf78e9d58b8238ffcf1d78a279e3a862Dan Albert char16_t* strings = (char16_t*)dat; 489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 490f348c15ecf78e9d58b8238ffcf1d78a279e3a862Dan Albert ENCODE_LENGTH(strings, sizeof(char16_t), strSize) 491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strcpy16_htod(strings, ent.value); 493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strPos += totalSize; 496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Pad ending string position up to a uint32_t boundary. 499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strPos&0x3) { 501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t padPos = ((strPos+3)&~0x3); 502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint8_t* dat = (uint8_t*)pool->editData(preSize + padPos); 503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dat == NULL) { 504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Out of memory padding string pool\n"); 505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_MEMORY; 506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski memset(dat+preSize+strPos, 0, padPos-strPos); 508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strPos = padPos; 509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Build the pool of style spans. 512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t styPos = strPos; 514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<STYLES; i++) { 515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry_style& ent = mEntryStyleArray.editItemAt(i); 516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = ent.spans.size(); 517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t totalSize = (N*sizeof(ResStringPool_span)) 518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski + sizeof(ResStringPool_ref); 519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ent.offset = styPos-strPos; 521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint8_t* dat = (uint8_t*)pool->editData(preSize + styPos + totalSize); 522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dat == NULL) { 523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Out of memory for string styles\n"); 524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_MEMORY; 525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResStringPool_span* span = (ResStringPool_span*)(dat+preSize+styPos); 527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski span->name.index = htodl(ent.spans[i].span.name.index); 529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski span->firstChar = htodl(ent.spans[i].span.firstChar); 530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski span->lastChar = htodl(ent.spans[i].span.lastChar); 531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski span++; 532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski span->name.index = htodl(ResStringPool_span::END); 534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski styPos += totalSize; 536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (STYLES > 0) { 539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Add full terminator at the end (when reading we validate that 540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the end of the pool is fully terminated to simplify error 541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // checking). 542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t extra = sizeof(ResStringPool_span)-sizeof(ResStringPool_ref); 543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint8_t* dat = (uint8_t*)pool->editData(preSize + styPos + extra); 544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dat == NULL) { 545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Out of memory for string styles\n"); 546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_MEMORY; 547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t* p = (uint32_t*)(dat+preSize+styPos); 549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (extra > 0) { 550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *p++ = htodl(ResStringPool_span::END); 551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski extra -= sizeof(uint32_t); 552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski styPos += extra; 554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write header. 557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResStringPool_header* header = 559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (ResStringPool_header*)pool->padData(sizeof(uint32_t)); 560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (header == NULL) { 561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Out of memory for string pool\n"); 562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_MEMORY; 563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski memset(header, 0, sizeof(*header)); 565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->header.type = htods(RES_STRING_POOL_TYPE); 566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->header.headerSize = htods(sizeof(*header)); 567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->header.size = htodl(pool->getSize()); 568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->stringCount = htodl(ENTRIES); 569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->styleCount = htodl(STYLES); 570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mUTF8) { 571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->flags |= htodl(ResStringPool_header::UTF8_FLAG); 572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->stringsStart = htodl(preSize); 574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->stylesStart = htodl(STYLES > 0 ? (preSize+strPos) : 0); 575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write string index array. 577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t* index = (uint32_t*)(header+1); 579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<ENTRIES; i++) { 580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry& ent = mEntries.editItemAt(mEntryArray[i]); 581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *index++ = htodl(ent.offset); 5822412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 5832412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Writing entry #%zu: \"%s\" ent=%zu off=%zu\n", 5842412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe i, 5852412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe String8(ent.value).string(), 5862412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe mEntryArray[i], 5872412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe ent.offset); 5882412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write style index array. 592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<STYLES; i++) { 594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *index++ = htodl(mEntryStyleArray[i].offset); 595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskissize_t StringPool::offsetForString(const String16& val) const 601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Vector<size_t>* indices = offsetsForString(val); 603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t res = indices != NULL && indices->size() > 0 ? indices->itemAt(0) : -1; 6042412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 6052412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Offset for string %s: %zd (%s)\n", String8(val).string(), SSIZE(res), 6062412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe res >= 0 ? String8(mEntries[mEntryArray[res]].value).string() : String8()); 6072412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return res; 609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst Vector<size_t>* StringPool::offsetsForString(const String16& val) const 612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t pos = mValues.valueFor(val); 614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (pos < 0) { 615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return &mEntries[mEntryArray[pos]].indices; 618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 619