1*d57664e9SAndroid Build Coastguard Worker // 2*d57664e9SAndroid Build Coastguard Worker // Copyright 2006 The Android Open Source Project 3*d57664e9SAndroid Build Coastguard Worker // 4*d57664e9SAndroid Build Coastguard Worker // Build resource files from raw assets. 5*d57664e9SAndroid Build Coastguard Worker // 6*d57664e9SAndroid Build Coastguard Worker 7*d57664e9SAndroid Build Coastguard Worker #ifndef STRING_POOL_H 8*d57664e9SAndroid Build Coastguard Worker #define STRING_POOL_H 9*d57664e9SAndroid Build Coastguard Worker 10*d57664e9SAndroid Build Coastguard Worker #include "Main.h" 11*d57664e9SAndroid Build Coastguard Worker #include "AaptAssets.h" 12*d57664e9SAndroid Build Coastguard Worker 13*d57664e9SAndroid Build Coastguard Worker #include <androidfw/ResourceTypes.h> 14*d57664e9SAndroid Build Coastguard Worker #include <utils/String16.h> 15*d57664e9SAndroid Build Coastguard Worker 16*d57664e9SAndroid Build Coastguard Worker #include <sys/types.h> 17*d57664e9SAndroid Build Coastguard Worker #include <sys/stat.h> 18*d57664e9SAndroid Build Coastguard Worker #include <fcntl.h> 19*d57664e9SAndroid Build Coastguard Worker #include <ctype.h> 20*d57664e9SAndroid Build Coastguard Worker #include <errno.h> 21*d57664e9SAndroid Build Coastguard Worker 22*d57664e9SAndroid Build Coastguard Worker using namespace android; 23*d57664e9SAndroid Build Coastguard Worker 24*d57664e9SAndroid Build Coastguard Worker #define PRINT_STRING_METRICS 0 25*d57664e9SAndroid Build Coastguard Worker 26*d57664e9SAndroid Build Coastguard Worker #if __cplusplus >= 201103L 27*d57664e9SAndroid Build Coastguard Worker void strcpy16_htod(char16_t* dst, const char16_t* src); 28*d57664e9SAndroid Build Coastguard Worker #endif 29*d57664e9SAndroid Build Coastguard Worker void strcpy16_htod(uint16_t* dst, const char16_t* src); 30*d57664e9SAndroid Build Coastguard Worker 31*d57664e9SAndroid Build Coastguard Worker void printStringPool(const ResStringPool* pool); 32*d57664e9SAndroid Build Coastguard Worker 33*d57664e9SAndroid Build Coastguard Worker /** 34*d57664e9SAndroid Build Coastguard Worker * The StringPool class is used as an intermediate representation for 35*d57664e9SAndroid Build Coastguard Worker * generating the string pool resource data structure that can be parsed with 36*d57664e9SAndroid Build Coastguard Worker * ResStringPool in include/utils/ResourceTypes.h. 37*d57664e9SAndroid Build Coastguard Worker */ 38*d57664e9SAndroid Build Coastguard Worker class StringPool 39*d57664e9SAndroid Build Coastguard Worker { 40*d57664e9SAndroid Build Coastguard Worker public: 41*d57664e9SAndroid Build Coastguard Worker struct entry { entryentry42*d57664e9SAndroid Build Coastguard Worker entry() : offset(0) { } entryentry43*d57664e9SAndroid Build Coastguard Worker explicit entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { } entryentry44*d57664e9SAndroid Build Coastguard Worker entry(const entry& o) : value(o.value), offset(o.offset), 45*d57664e9SAndroid Build Coastguard Worker hasStyles(o.hasStyles), indices(o.indices), 46*d57664e9SAndroid Build Coastguard Worker configTypeName(o.configTypeName), configs(o.configs) { } 47*d57664e9SAndroid Build Coastguard Worker 48*d57664e9SAndroid Build Coastguard Worker String16 value; 49*d57664e9SAndroid Build Coastguard Worker size_t offset; 50*d57664e9SAndroid Build Coastguard Worker bool hasStyles; 51*d57664e9SAndroid Build Coastguard Worker Vector<size_t> indices; 52*d57664e9SAndroid Build Coastguard Worker String8 configTypeName; 53*d57664e9SAndroid Build Coastguard Worker Vector<ResTable_config> configs; 54*d57664e9SAndroid Build Coastguard Worker 55*d57664e9SAndroid Build Coastguard Worker String8 makeConfigsString() const; 56*d57664e9SAndroid Build Coastguard Worker 57*d57664e9SAndroid Build Coastguard Worker int compare(const entry& o) const; 58*d57664e9SAndroid Build Coastguard Worker 59*d57664e9SAndroid Build Coastguard Worker inline bool operator<(const entry& o) const { return compare(o) < 0; } 60*d57664e9SAndroid Build Coastguard Worker inline bool operator<=(const entry& o) const { return compare(o) <= 0; } 61*d57664e9SAndroid Build Coastguard Worker inline bool operator==(const entry& o) const { return compare(o) == 0; } 62*d57664e9SAndroid Build Coastguard Worker inline bool operator!=(const entry& o) const { return compare(o) != 0; } 63*d57664e9SAndroid Build Coastguard Worker inline bool operator>=(const entry& o) const { return compare(o) >= 0; } 64*d57664e9SAndroid Build Coastguard Worker inline bool operator>(const entry& o) const { return compare(o) > 0; } 65*d57664e9SAndroid Build Coastguard Worker }; 66*d57664e9SAndroid Build Coastguard Worker 67*d57664e9SAndroid Build Coastguard Worker struct entry_style_span { 68*d57664e9SAndroid Build Coastguard Worker String16 name; 69*d57664e9SAndroid Build Coastguard Worker ResStringPool_span span; 70*d57664e9SAndroid Build Coastguard Worker }; 71*d57664e9SAndroid Build Coastguard Worker 72*d57664e9SAndroid Build Coastguard Worker struct entry_style { entry_styleentry_style73*d57664e9SAndroid Build Coastguard Worker entry_style() : offset(0) { } 74*d57664e9SAndroid Build Coastguard Worker entry_styleentry_style75*d57664e9SAndroid Build Coastguard Worker entry_style(const entry_style& o) : offset(o.offset), spans(o.spans) { } 76*d57664e9SAndroid Build Coastguard Worker 77*d57664e9SAndroid Build Coastguard Worker size_t offset; 78*d57664e9SAndroid Build Coastguard Worker Vector<entry_style_span> spans; 79*d57664e9SAndroid Build Coastguard Worker }; 80*d57664e9SAndroid Build Coastguard Worker 81*d57664e9SAndroid Build Coastguard Worker /** 82*d57664e9SAndroid Build Coastguard Worker * If 'utf8' is true, strings will be encoded with UTF-8 instead of 83*d57664e9SAndroid Build Coastguard Worker * left in Java's native UTF-16. 84*d57664e9SAndroid Build Coastguard Worker */ 85*d57664e9SAndroid Build Coastguard Worker explicit StringPool(bool utf8 = false); 86*d57664e9SAndroid Build Coastguard Worker 87*d57664e9SAndroid Build Coastguard Worker /** 88*d57664e9SAndroid Build Coastguard Worker * Add a new string to the pool. If mergeDuplicates is true, thenif 89*d57664e9SAndroid Build Coastguard Worker * the string already exists the existing entry for it will be used; 90*d57664e9SAndroid Build Coastguard Worker * otherwise, or if the value doesn't already exist, a new entry is 91*d57664e9SAndroid Build Coastguard Worker * created. 92*d57664e9SAndroid Build Coastguard Worker * 93*d57664e9SAndroid Build Coastguard Worker * Returns the index in the entry array of the new string entry. 94*d57664e9SAndroid Build Coastguard Worker */ 95*d57664e9SAndroid Build Coastguard Worker ssize_t add(const String16& value, bool mergeDuplicates = false, 96*d57664e9SAndroid Build Coastguard Worker const String8* configTypeName = NULL, const ResTable_config* config = NULL); 97*d57664e9SAndroid Build Coastguard Worker 98*d57664e9SAndroid Build Coastguard Worker ssize_t add(const String16& value, const Vector<entry_style_span>& spans, 99*d57664e9SAndroid Build Coastguard Worker const String8* configTypeName = NULL, const ResTable_config* config = NULL); 100*d57664e9SAndroid Build Coastguard Worker 101*d57664e9SAndroid Build Coastguard Worker status_t addStyleSpan(size_t idx, const String16& name, 102*d57664e9SAndroid Build Coastguard Worker uint32_t start, uint32_t end); 103*d57664e9SAndroid Build Coastguard Worker status_t addStyleSpans(size_t idx, const Vector<entry_style_span>& spans); 104*d57664e9SAndroid Build Coastguard Worker status_t addStyleSpan(size_t idx, const entry_style_span& span); 105*d57664e9SAndroid Build Coastguard Worker 106*d57664e9SAndroid Build Coastguard Worker // Sort the contents of the string block by the configuration associated 107*d57664e9SAndroid Build Coastguard Worker // with each item. After doing this you can use mapOriginalPosToNewPos() 108*d57664e9SAndroid Build Coastguard Worker // to find out the new position given the position originally returned by 109*d57664e9SAndroid Build Coastguard Worker // add(). 110*d57664e9SAndroid Build Coastguard Worker void sortByConfig(); 111*d57664e9SAndroid Build Coastguard Worker 112*d57664e9SAndroid Build Coastguard Worker // For use after sortByConfig() to map from the original position of 113*d57664e9SAndroid Build Coastguard Worker // a string to its new sorted position. mapOriginalPosToNewPos(size_t originalPos)114*d57664e9SAndroid Build Coastguard Worker size_t mapOriginalPosToNewPos(size_t originalPos) const { 115*d57664e9SAndroid Build Coastguard Worker return mOriginalPosToNewPos.itemAt(originalPos); 116*d57664e9SAndroid Build Coastguard Worker } 117*d57664e9SAndroid Build Coastguard Worker 118*d57664e9SAndroid Build Coastguard Worker sp<AaptFile> createStringBlock(); 119*d57664e9SAndroid Build Coastguard Worker 120*d57664e9SAndroid Build Coastguard Worker status_t writeStringBlock(const sp<AaptFile>& pool); 121*d57664e9SAndroid Build Coastguard Worker 122*d57664e9SAndroid Build Coastguard Worker /** 123*d57664e9SAndroid Build Coastguard Worker * Find out an offset in the pool for a particular string. If the string 124*d57664e9SAndroid Build Coastguard Worker * pool is sorted, this can not be called until after createStringBlock() 125*d57664e9SAndroid Build Coastguard Worker * or writeStringBlock() has been called 126*d57664e9SAndroid Build Coastguard Worker * (which determines the offsets). In the case of a string that appears 127*d57664e9SAndroid Build Coastguard Worker * multiple times in the pool, the first offset will be returned. Returns 128*d57664e9SAndroid Build Coastguard Worker * -1 if the string does not exist. 129*d57664e9SAndroid Build Coastguard Worker */ 130*d57664e9SAndroid Build Coastguard Worker ssize_t offsetForString(const String16& val) const; 131*d57664e9SAndroid Build Coastguard Worker 132*d57664e9SAndroid Build Coastguard Worker /** 133*d57664e9SAndroid Build Coastguard Worker * Find all of the offsets in the pool for a particular string. If the 134*d57664e9SAndroid Build Coastguard Worker * string pool is sorted, this can not be called until after 135*d57664e9SAndroid Build Coastguard Worker * createStringBlock() or writeStringBlock() has been called 136*d57664e9SAndroid Build Coastguard Worker * (which determines the offsets). Returns NULL if the string does not exist. 137*d57664e9SAndroid Build Coastguard Worker */ 138*d57664e9SAndroid Build Coastguard Worker const Vector<size_t>* offsetsForString(const String16& val) const; 139*d57664e9SAndroid Build Coastguard Worker 140*d57664e9SAndroid Build Coastguard Worker private: 141*d57664e9SAndroid Build Coastguard Worker class ConfigSorter 142*d57664e9SAndroid Build Coastguard Worker { 143*d57664e9SAndroid Build Coastguard Worker public: 144*d57664e9SAndroid Build Coastguard Worker explicit ConfigSorter(const StringPool&); 145*d57664e9SAndroid Build Coastguard Worker bool operator()(size_t l, size_t r); 146*d57664e9SAndroid Build Coastguard Worker private: 147*d57664e9SAndroid Build Coastguard Worker const StringPool& pool; 148*d57664e9SAndroid Build Coastguard Worker }; 149*d57664e9SAndroid Build Coastguard Worker 150*d57664e9SAndroid Build Coastguard Worker const bool mUTF8; 151*d57664e9SAndroid Build Coastguard Worker 152*d57664e9SAndroid Build Coastguard Worker // The following data structures represent the actual structures 153*d57664e9SAndroid Build Coastguard Worker // that will be generated for the final string pool. 154*d57664e9SAndroid Build Coastguard Worker 155*d57664e9SAndroid Build Coastguard Worker // Raw array of unique strings, in some arbitrary order. This is the 156*d57664e9SAndroid Build Coastguard Worker // actual strings that appear in the final string pool, in the order 157*d57664e9SAndroid Build Coastguard Worker // that they will be written. 158*d57664e9SAndroid Build Coastguard Worker Vector<entry> mEntries; 159*d57664e9SAndroid Build Coastguard Worker // Array of indices into mEntries, in the order they were 160*d57664e9SAndroid Build Coastguard Worker // added to the pool. This can be different than mEntries 161*d57664e9SAndroid Build Coastguard Worker // if the same string was added multiple times (it will appear 162*d57664e9SAndroid Build Coastguard Worker // once in mEntries, with multiple occurrences in this array). 163*d57664e9SAndroid Build Coastguard Worker // This is the lookup array that will be written for finding 164*d57664e9SAndroid Build Coastguard Worker // the string for each offset/position in the string pool. 165*d57664e9SAndroid Build Coastguard Worker Vector<size_t> mEntryArray; 166*d57664e9SAndroid Build Coastguard Worker // Optional style span information associated with each index of 167*d57664e9SAndroid Build Coastguard Worker // mEntryArray. 168*d57664e9SAndroid Build Coastguard Worker Vector<entry_style> mEntryStyleArray; 169*d57664e9SAndroid Build Coastguard Worker 170*d57664e9SAndroid Build Coastguard Worker // The following data structures are used for book-keeping as the 171*d57664e9SAndroid Build Coastguard Worker // string pool is constructed. 172*d57664e9SAndroid Build Coastguard Worker 173*d57664e9SAndroid Build Coastguard Worker // Unique set of all the strings added to the pool, mapped to 174*d57664e9SAndroid Build Coastguard Worker // the first index of mEntryArray where the value was added. 175*d57664e9SAndroid Build Coastguard Worker DefaultKeyedVector<String16, ssize_t> mValues; 176*d57664e9SAndroid Build Coastguard Worker // This array maps from the original position a string was placed at 177*d57664e9SAndroid Build Coastguard Worker // in mEntryArray to its new position after being sorted with sortByConfig(). 178*d57664e9SAndroid Build Coastguard Worker Vector<size_t> mOriginalPosToNewPos; 179*d57664e9SAndroid Build Coastguard Worker }; 180*d57664e9SAndroid Build Coastguard Worker 181*d57664e9SAndroid Build Coastguard Worker #endif 182*d57664e9SAndroid Build Coastguard Worker 183