summaryrefslogtreecommitdiffstats
path: root/tools/aapt/StringPool.h
blob: 255bdbfc0a7f7a5bf194702e49501f5ddfff900e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
//
// Copyright 2006 The Android Open Source Project
//
// Build resource files from raw assets.
//

#ifndef STRING_POOL_H
#define STRING_POOL_H

#include "Main.h"
#include "AaptAssets.h"

#include <utils/ResourceTypes.h>
#include <utils/String16.h>
#include <utils/TextOutput.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>

#include <expat.h>

using namespace android;

#define PRINT_STRING_METRICS 0

void strcpy16_htod(uint16_t* dst, const uint16_t* src);

void printStringPool(const ResStringPool* pool);

/**
 * The StringPool class is used as an intermediate representation for
 * generating the string pool resource data structure that can be parsed with
 * ResStringPool in include/utils/ResourceTypes.h.
 */
class StringPool
{
public:
    struct entry {
        entry() : offset(0) { }
        entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { }
        entry(const entry& o) : value(o.value), offset(o.offset),
                hasStyles(o.hasStyles), indices(o.indices),
                configTypeName(o.configTypeName), configs(o.configs) { }

        String16 value;
        size_t offset;
        bool hasStyles;
        Vector<size_t> indices;
        String8 configTypeName;
        Vector<ResTable_config> configs;

        String8 makeConfigsString() const;

        int compare(const entry& o) const;

        inline bool operator<(const entry& o) const { return compare(o) < 0; }
        inline bool operator<=(const entry& o) const { return compare(o) <= 0; }
        inline bool operator==(const entry& o) const { return compare(o) == 0; }
        inline bool operator!=(const entry& o) const { return compare(o) != 0; }
        inline bool operator>=(const entry& o) const { return compare(o) >= 0; }
        inline bool operator>(const entry& o) const { return compare(o) > 0; }
    };

    struct entry_style_span {
        String16 name;
        ResStringPool_span span;
    };

    struct entry_style {
        entry_style() : offset(0) { }

        entry_style(const entry_style& o) : offset(o.offset), spans(o.spans) { }

        size_t offset;
        Vector<entry_style_span> spans;
    };

    /**
     * If 'sorted' is true, then the final strings in the resource data
     * structure will be generated in sorted order.  This allow for fast
     * lookup with ResStringPool::indexOfString() (O(log n)), at the expense
     * of support for styled string entries (which requires the same string
     * be included multiple times in the pool).
     *
     * If 'utf8' is true, strings will be encoded with UTF-8 instead of
     * left in Java's native UTF-16.
     */
    explicit StringPool(bool sorted = false, bool utf8 = false);

    /**
     * Add a new string to the pool.  If mergeDuplicates is true, thenif
     * the string already exists the existing entry for it will be used;
     * otherwise, or if the value doesn't already exist, a new entry is
     * created.
     *
     * Returns the index in the entry array of the new string entry.  Note that
     * if this string pool is sorted, the returned index will not be valid
     * when the pool is finally written.
     */
    ssize_t add(const String16& value, bool mergeDuplicates = false,
            const String8* configTypeName = NULL, const ResTable_config* config = NULL);

    ssize_t add(const String16& value, const Vector<entry_style_span>& spans,
            const String8* configTypeName = NULL, const ResTable_config* config = NULL);

    ssize_t add(const String16& ident, const String16& value,
                bool mergeDuplicates = false,
                const String8* configTypeName = NULL, const ResTable_config* config = NULL);

    status_t addStyleSpan(size_t idx, const String16& name,
                          uint32_t start, uint32_t end);
    status_t addStyleSpans(size_t idx, const Vector<entry_style_span>& spans);
    status_t addStyleSpan(size_t idx, const entry_style_span& span);

    size_t size() const;

    const entry& entryAt(size_t idx) const;

    size_t countIdentifiers() const;

    // Sort the contents of the string block by the configuration associated
    // with each item.  After doing this you can use mapOriginalPosToNewPos()
    // to find out the new position given the position originall returned by
    // add().
    void sortByConfig();

    // For use after sortByConfig() to map from the original position of
    // a string to its new sorted position.
    size_t mapOriginalPosToNewPos(size_t originalPos) const {
        return mOriginalPosToNewPos.itemAt(originalPos);
    }

    sp<AaptFile> createStringBlock();

    status_t writeStringBlock(const sp<AaptFile>& pool);

    /**
     * Find out an offset in the pool for a particular string.  If the string
     * pool is sorted, this can not be called until after createStringBlock()
     * or writeStringBlock() has been called
     * (which determines the offsets).  In the case of a string that appears
     * multiple times in the pool, the first offset will be returned.  Returns
     * -1 if the string does not exist.
     */
    ssize_t offsetForString(const String16& val) const;

    /**
     * Find all of the offsets in the pool for a particular string.  If the
     * string pool is sorted, this can not be called until after
     * createStringBlock() or writeStringBlock() has been called
     * (which determines the offsets).  Returns NULL if the string does not exist.
     */
    const Vector<size_t>* offsetsForString(const String16& val) const;

private:
    static int config_sort(const size_t* lhs, const size_t* rhs, void* state);

    const bool                              mSorted;
    const bool                              mUTF8;

    // The following data structures represent the actual structures
    // that will be generated for the final string pool.

    // Raw array of unique strings, in some arbitrary order.  This is the
    // actual strings that appear in the final string pool, in the order
    // that they will be written.
    Vector<entry>                           mEntries;
    // Array of indices into mEntries, in the order they were
    // added to the pool.  This can be different than mEntries
    // if the same string was added multiple times (it will appear
    // once in mEntries, with multiple occurrences in this array).
    // This is the lookup array that will be written for finding
    // the string for each offset/position in the string pool.
    Vector<size_t>                          mEntryArray;
    // Optional style span information associated with each index of
    // mEntryArray.
    Vector<entry_style>                     mEntryStyleArray;

    // The following data structures are used for book-keeping as the
    // string pool is constructed.

    // Unique set of all the strings added to the pool, mapped to
    // the first index of mEntryArray where the value was added.
    DefaultKeyedVector<String16, ssize_t>   mValues;
    // Unique set of all (optional) identifiers of strings in the
    // pool, mapping to indices in mEntries.
    DefaultKeyedVector<String16, ssize_t>   mIdents;
    // This array maps from the original position a string was placed at
    // in mEntryArray to its new position after being sorted with sortByConfig().
    Vector<size_t>                          mOriginalPosToNewPos;
};

#endif