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