1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Build resource files from raw assets.
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef STRING_POOL_H
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#define STRING_POOL_H
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Main.h"
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "AaptAssets.h"
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <androidfw/ResourceTypes.h>
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/String16.h>
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/TypeHelpers.h>
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <sys/types.h>
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <sys/stat.h>
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <fcntl.h>
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <ctype.h>
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <errno.h>
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <libexpat/expat.h>
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing namespace android;
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#define PRINT_STRING_METRICS 0
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
294bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski#if __cplusplus >= 201103L
304bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinskivoid strcpy16_htod(char16_t* dst, const char16_t* src);
314bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski#endif
324bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinskivoid strcpy16_htod(uint16_t* dst, const char16_t* src);
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid printStringPool(const ResStringPool* pool);
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/**
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The StringPool class is used as an intermediate representation for
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * generating the string pool resource data structure that can be parsed with
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * ResStringPool in include/utils/ResourceTypes.h.
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass StringPool
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic:
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    struct entry {
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry() : offset(0) { }
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { }
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry(const entry& o) : value(o.value), offset(o.offset),
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                hasStyles(o.hasStyles), indices(o.indices),
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                configTypeName(o.configTypeName), configs(o.configs) { }
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 value;
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t offset;
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        bool hasStyles;
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Vector<size_t> indices;
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 configTypeName;
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Vector<ResTable_config> configs;
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String8 makeConfigsString() const;
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int compare(const entry& o) const;
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        inline bool operator<(const entry& o) const { return compare(o) < 0; }
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        inline bool operator<=(const entry& o) const { return compare(o) <= 0; }
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        inline bool operator==(const entry& o) const { return compare(o) == 0; }
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        inline bool operator!=(const entry& o) const { return compare(o) != 0; }
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        inline bool operator>=(const entry& o) const { return compare(o) >= 0; }
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        inline bool operator>(const entry& o) const { return compare(o) > 0; }
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    };
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    struct entry_style_span {
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String16 name;
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResStringPool_span span;
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    };
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    struct entry_style {
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry_style() : offset(0) { }
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        entry_style(const entry_style& o) : offset(o.offset), spans(o.spans) { }
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        size_t offset;
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Vector<entry_style_span> spans;
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    };
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * If 'utf8' is true, strings will be encoded with UTF-8 instead of
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * left in Java's native UTF-16.
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    explicit StringPool(bool utf8 = false);
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Add a new string to the pool.  If mergeDuplicates is true, thenif
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * the string already exists the existing entry for it will be used;
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * otherwise, or if the value doesn't already exist, a new entry is
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * created.
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns the index in the entry array of the new string entry.
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t add(const String16& value, bool mergeDuplicates = false,
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String8* configTypeName = NULL, const ResTable_config* config = NULL);
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t add(const String16& value, const Vector<entry_style_span>& spans,
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            const String8* configTypeName = NULL, const ResTable_config* config = NULL);
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t addStyleSpan(size_t idx, const String16& name,
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                          uint32_t start, uint32_t end);
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t addStyleSpans(size_t idx, const Vector<entry_style_span>& spans);
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t addStyleSpan(size_t idx, const entry_style_span& span);
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Sort the contents of the string block by the configuration associated
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // with each item.  After doing this you can use mapOriginalPosToNewPos()
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // to find out the new position given the position originally returned by
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // add().
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void sortByConfig();
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // For use after sortByConfig() to map from the original position of
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // a string to its new sorted position.
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t mapOriginalPosToNewPos(size_t originalPos) const {
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mOriginalPosToNewPos.itemAt(originalPos);
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sp<AaptFile> createStringBlock();
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    status_t writeStringBlock(const sp<AaptFile>& pool);
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Find out an offset in the pool for a particular string.  If the string
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * pool is sorted, this can not be called until after createStringBlock()
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * or writeStringBlock() has been called
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * (which determines the offsets).  In the case of a string that appears
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * multiple times in the pool, the first offset will be returned.  Returns
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * -1 if the string does not exist.
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ssize_t offsetForString(const String16& val) const;
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Find all of the offsets in the pool for a particular string.  If the
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * string pool is sorted, this can not be called until after
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * createStringBlock() or writeStringBlock() has been called
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * (which determines the offsets).  Returns NULL if the string does not exist.
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const Vector<size_t>* offsetsForString(const String16& val) const;
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiprivate:
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    static int config_sort(void* state, const void* lhs, const void* rhs);
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const bool                              mUTF8;
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // The following data structures represent the actual structures
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // that will be generated for the final string pool.
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Raw array of unique strings, in some arbitrary order.  This is the
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // actual strings that appear in the final string pool, in the order
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // that they will be written.
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<entry>                           mEntries;
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Array of indices into mEntries, in the order they were
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // added to the pool.  This can be different than mEntries
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // if the same string was added multiple times (it will appear
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // once in mEntries, with multiple occurrences in this array).
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // This is the lookup array that will be written for finding
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the string for each offset/position in the string pool.
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<size_t>                          mEntryArray;
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Optional style span information associated with each index of
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // mEntryArray.
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<entry_style>                     mEntryStyleArray;
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // The following data structures are used for book-keeping as the
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // string pool is constructed.
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Unique set of all the strings added to the pool, mapped to
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the first index of mEntryArray where the value was added.
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DefaultKeyedVector<String16, ssize_t>   mValues;
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // This array maps from the original position a string was placed at
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // in mEntryArray to its new position after being sorted with sortByConfig().
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Vector<size_t>                          mOriginalPosToNewPos;
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// The entry types are trivially movable because all fields they contain, including
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// the vectors and strings, are trivially movable.
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskinamespace android {
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ANDROID_TRIVIAL_MOVE_TRAIT(StringPool::entry);
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ANDROID_TRIVIAL_MOVE_TRAIT(StringPool::entry_style_span);
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ANDROID_TRIVIAL_MOVE_TRAIT(StringPool::entry_style);
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
187