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