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