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#ifndef STRING_POOL_H 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define STRING_POOL_H 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "Main.h" 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "AaptAssets.h" 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/ResourceTypes.h> 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String16.h> 158a9cfcc85260eadcc2c17c4a8911c6d93b642f39Jeff Brown#include <utils/TypeHelpers.h> 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h> 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/stat.h> 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h> 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ctype.h> 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h> 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define PRINT_STRING_METRICS 0 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 274bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski#if __cplusplus >= 201103L 28f348c15ecf78e9d58b8238ffcf1d78a279e3a862Dan Albertvoid strcpy16_htod(char16_t* dst, const char16_t* src); 294bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski#endif 304bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinskivoid strcpy16_htod(uint16_t* dst, const char16_t* src); 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid printStringPool(const ResStringPool* pool); 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The StringPool class is used as an intermediate representation for 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * generating the string pool resource data structure that can be parsed with 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ResStringPool in include/utils/ResourceTypes.h. 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass StringPool 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic: 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct entry { 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entry() : offset(0) { } 446c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { } 456c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn entry(const entry& o) : value(o.value), offset(o.offset), 466c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn hasStyles(o.hasStyles), indices(o.indices), 476c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn configTypeName(o.configTypeName), configs(o.configs) { } 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String16 value; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t offset; 516c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn bool hasStyles; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Vector<size_t> indices; 536c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn String8 configTypeName; 546c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn Vector<ResTable_config> configs; 556c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 566c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn String8 makeConfigsString() const; 576c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 586c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn int compare(const entry& o) const; 596c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 606c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn inline bool operator<(const entry& o) const { return compare(o) < 0; } 616c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn inline bool operator<=(const entry& o) const { return compare(o) <= 0; } 626c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn inline bool operator==(const entry& o) const { return compare(o) == 0; } 636c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn inline bool operator!=(const entry& o) const { return compare(o) != 0; } 646c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn inline bool operator>=(const entry& o) const { return compare(o) >= 0; } 656c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn inline bool operator>(const entry& o) const { return compare(o) > 0; } 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct entry_style_span { 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String16 name; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ResStringPool_span span; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct entry_style { 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entry_style() : offset(0) { } 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entry_style(const entry_style& o) : offset(o.offset), spans(o.spans) { } 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t offset; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Vector<entry_style_span> spans; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8319138468caf7050d482dc15f35a344eab11bb756Kenny Root * If 'utf8' is true, strings will be encoded with UTF-8 instead of 8419138468caf7050d482dc15f35a344eab11bb756Kenny Root * left in Java's native UTF-16. 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 86345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown explicit StringPool(bool utf8 = false); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Add a new string to the pool. If mergeDuplicates is true, thenif 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the string already exists the existing entry for it will be used; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * otherwise, or if the value doesn't already exist, a new entry is 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * created. 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 94345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown * Returns the index in the entry array of the new string entry. 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 966c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn ssize_t add(const String16& value, bool mergeDuplicates = false, 976c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn const String8* configTypeName = NULL, const ResTable_config* config = NULL); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 996c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn ssize_t add(const String16& value, const Vector<entry_style_span>& spans, 1006c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn const String8* configTypeName = NULL, const ResTable_config* config = NULL); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t addStyleSpan(size_t idx, const String16& name, 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t start, uint32_t end); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t addStyleSpans(size_t idx, const Vector<entry_style_span>& spans); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t addStyleSpan(size_t idx, const entry_style_span& span); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1076c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // Sort the contents of the string block by the configuration associated 1086c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // with each item. After doing this you can use mapOriginalPosToNewPos() 109345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown // to find out the new position given the position originally returned by 1106c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // add(). 1116c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn void sortByConfig(); 1126c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1136c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // For use after sortByConfig() to map from the original position of 1146c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // a string to its new sorted position. 1156c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn size_t mapOriginalPosToNewPos(size_t originalPos) const { 1166c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn return mOriginalPosToNewPos.itemAt(originalPos); 1176c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 1186c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<AaptFile> createStringBlock(); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t writeStringBlock(const sp<AaptFile>& pool); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Find out an offset in the pool for a particular string. If the string 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * pool is sorted, this can not be called until after createStringBlock() 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or writeStringBlock() has been called 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (which determines the offsets). In the case of a string that appears 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * multiple times in the pool, the first offset will be returned. Returns 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * -1 if the string does not exist. 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t offsetForString(const String16& val) const; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Find all of the offsets in the pool for a particular string. If the 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * string pool is sorted, this can not be called until after 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * createStringBlock() or writeStringBlock() has been called 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (which determines the offsets). Returns NULL if the string does not exist. 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const Vector<size_t>* offsetsForString(const String16& val) const; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprivate: 1420de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert class ConfigSorter 1430de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert { 1440de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert public: 1450de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert explicit ConfigSorter(const StringPool&); 1460de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert bool operator()(size_t l, size_t r); 1470de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert private: 1480de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert const StringPool& pool; 1490de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert }; 1506c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 15119138468caf7050d482dc15f35a344eab11bb756Kenny Root const bool mUTF8; 1526c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1536c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // The following data structures represent the actual structures 1546c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // that will be generated for the final string pool. 1556c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1566c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // Raw array of unique strings, in some arbitrary order. This is the 1576c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // actual strings that appear in the final string pool, in the order 1586c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // that they will be written. 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Vector<entry> mEntries; 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Array of indices into mEntries, in the order they were 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // added to the pool. This can be different than mEntries 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if the same string was added multiple times (it will appear 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // once in mEntries, with multiple occurrences in this array). 1646c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // This is the lookup array that will be written for finding 1656c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // the string for each offset/position in the string pool. 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Vector<size_t> mEntryArray; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Optional style span information associated with each index of 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mEntryArray. 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Vector<entry_style> mEntryStyleArray; 1706c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1716c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // The following data structures are used for book-keeping as the 1726c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // string pool is constructed. 1736c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Unique set of all the strings added to the pool, mapped to 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the first index of mEntryArray where the value was added. 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DefaultKeyedVector<String16, ssize_t> mValues; 1776c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // This array maps from the original position a string was placed at 1786c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // in mEntryArray to its new position after being sorted with sortByConfig(). 1796c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn Vector<size_t> mOriginalPosToNewPos; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1828a9cfcc85260eadcc2c17c4a8911c6d93b642f39Jeff Brown// The entry types are trivially movable because all fields they contain, including 1838a9cfcc85260eadcc2c17c4a8911c6d93b642f39Jeff Brown// the vectors and strings, are trivially movable. 1848a9cfcc85260eadcc2c17c4a8911c6d93b642f39Jeff Brownnamespace android { 1858a9cfcc85260eadcc2c17c4a8911c6d93b642f39Jeff Brown ANDROID_TRIVIAL_MOVE_TRAIT(StringPool::entry); 1868a9cfcc85260eadcc2c17c4a8911c6d93b642f39Jeff Brown ANDROID_TRIVIAL_MOVE_TRAIT(StringPool::entry_style_span); 1878a9cfcc85260eadcc2c17c4a8911c6d93b642f39Jeff Brown ANDROID_TRIVIAL_MOVE_TRAIT(StringPool::entry_style); 1888a9cfcc85260eadcc2c17c4a8911c6d93b642f39Jeff Brown}; 1898a9cfcc85260eadcc2c17c4a8911c6d93b642f39Jeff Brown 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 192