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> 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h> 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/stat.h> 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h> 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ctype.h> 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h> 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define PRINT_STRING_METRICS 0 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 264bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski#if __cplusplus >= 201103L 27f348c15ecf78e9d58b8238ffcf1d78a279e3a862Dan Albertvoid strcpy16_htod(char16_t* dst, const char16_t* src); 284bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski#endif 294bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinskivoid strcpy16_htod(uint16_t* dst, const char16_t* src); 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid printStringPool(const ResStringPool* pool); 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The StringPool class is used as an intermediate representation for 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * generating the string pool resource data structure that can be parsed with 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ResStringPool in include/utils/ResourceTypes.h. 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass StringPool 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic: 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct entry { 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entry() : offset(0) { } 438bd37ba458633ee7b2aeec0a7593817000aa84b2Chih-Hung Hsieh explicit entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { } 446c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn entry(const entry& o) : value(o.value), offset(o.offset), 456c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn hasStyles(o.hasStyles), indices(o.indices), 466c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn configTypeName(o.configTypeName), configs(o.configs) { } 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String16 value; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t offset; 506c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn bool hasStyles; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Vector<size_t> indices; 526c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn String8 configTypeName; 536c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn Vector<ResTable_config> configs; 546c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 556c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn String8 makeConfigsString() const; 566c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 576c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn int compare(const entry& o) const; 586c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 596c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn inline bool operator<(const entry& o) const { return compare(o) < 0; } 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; } 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct entry_style_span { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String16 name; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ResStringPool_span span; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct entry_style { 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entry_style() : offset(0) { } 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project entry_style(const entry_style& o) : offset(o.offset), spans(o.spans) { } 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t offset; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Vector<entry_style_span> spans; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8219138468caf7050d482dc15f35a344eab11bb756Kenny Root * If 'utf8' is true, strings will be encoded with UTF-8 instead of 8319138468caf7050d482dc15f35a344eab11bb756Kenny Root * left in Java's native UTF-16. 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 85345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown explicit StringPool(bool utf8 = false); 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Add a new string to the pool. If mergeDuplicates is true, thenif 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the string already exists the existing entry for it will be used; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * otherwise, or if the value doesn't already exist, a new entry is 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * created. 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 93345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown * Returns the index in the entry array of the new string entry. 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 956c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn ssize_t add(const String16& value, bool mergeDuplicates = false, 966c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn const String8* configTypeName = NULL, const ResTable_config* config = NULL); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 986c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn ssize_t add(const String16& value, const Vector<entry_style_span>& spans, 996c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn const String8* configTypeName = NULL, const ResTable_config* config = NULL); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t addStyleSpan(size_t idx, const String16& name, 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t start, uint32_t end); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t addStyleSpans(size_t idx, const Vector<entry_style_span>& spans); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t addStyleSpan(size_t idx, const entry_style_span& span); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1066c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // Sort the contents of the string block by the configuration associated 1076c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // with each item. After doing this you can use mapOriginalPosToNewPos() 108345b7eb8749d6954942fd4e961fff9f2f854934cJeff Brown // to find out the new position given the position originally returned by 1096c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // add(). 1106c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn void sortByConfig(); 1116c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1126c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // For use after sortByConfig() to map from the original position of 1136c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // a string to its new sorted position. 1146c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn size_t mapOriginalPosToNewPos(size_t originalPos) const { 1156c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn return mOriginalPosToNewPos.itemAt(originalPos); 1166c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn } 1176c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<AaptFile> createStringBlock(); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t writeStringBlock(const sp<AaptFile>& pool); 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Find out an offset in the pool for a particular string. If the string 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * pool is sorted, this can not be called until after createStringBlock() 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or writeStringBlock() has been called 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (which determines the offsets). In the case of a string that appears 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * multiple times in the pool, the first offset will be returned. Returns 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * -1 if the string does not exist. 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t offsetForString(const String16& val) const; 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Find all of the offsets in the pool for a particular string. If the 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * string pool is sorted, this can not be called until after 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * createStringBlock() or writeStringBlock() has been called 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (which determines the offsets). Returns NULL if the string does not exist. 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const Vector<size_t>* offsetsForString(const String16& val) const; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprivate: 1410de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert class ConfigSorter 1420de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert { 1430de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert public: 1440de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert explicit ConfigSorter(const StringPool&); 1450de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert bool operator()(size_t l, size_t r); 1460de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert private: 1470de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert const StringPool& pool; 1480de19adc80d8caeac8ab5da79e70ed4adb18b1c1Dan Albert }; 1496c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 15019138468caf7050d482dc15f35a344eab11bb756Kenny Root const bool mUTF8; 1516c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1526c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // The following data structures represent the actual structures 1536c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // that will be generated for the final string pool. 1546c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1556c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // Raw array of unique strings, in some arbitrary order. This is the 1566c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // actual strings that appear in the final string pool, in the order 1576c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // that they will be written. 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Vector<entry> mEntries; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Array of indices into mEntries, in the order they were 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // added to the pool. This can be different than mEntries 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if the same string was added multiple times (it will appear 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // once in mEntries, with multiple occurrences in this array). 1636c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // This is the lookup array that will be written for finding 1646c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // the string for each offset/position in the string pool. 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Vector<size_t> mEntryArray; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Optional style span information associated with each index of 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mEntryArray. 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Vector<entry_style> mEntryStyleArray; 1696c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1706c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // The following data structures are used for book-keeping as the 1716c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // string pool is constructed. 1726c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Unique set of all the strings added to the pool, mapped to 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the first index of mEntryArray where the value was added. 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DefaultKeyedVector<String16, ssize_t> mValues; 1766c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // This array maps from the original position a string was placed at 1776c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn // in mEntryArray to its new position after being sorted with sortByConfig(). 1786c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn Vector<size_t> mOriginalPosToNewPos; 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 183