1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef AAPT_STRING_POOL_H
18#define AAPT_STRING_POOL_H
19
20#include "util/BigBuffer.h"
21#include "ConfigDescription.h"
22#include "util/StringPiece.h"
23
24#include <functional>
25#include <map>
26#include <memory>
27#include <string>
28#include <vector>
29
30namespace aapt {
31
32struct Span {
33    std::u16string name;
34    uint32_t firstChar;
35    uint32_t lastChar;
36};
37
38struct StyleString {
39    std::u16string str;
40    std::vector<Span> spans;
41};
42
43class StringPool {
44public:
45    struct Context {
46        uint32_t priority;
47        ConfigDescription config;
48    };
49
50    class Entry;
51
52    class Ref {
53    public:
54        Ref();
55        Ref(const Ref&);
56        ~Ref();
57
58        Ref& operator=(const Ref& rhs);
59        const std::u16string* operator->() const;
60        const std::u16string& operator*() const;
61
62        size_t getIndex() const;
63        const Context& getContext() const;
64
65    private:
66        friend class StringPool;
67
68        Ref(Entry* entry);
69
70        Entry* mEntry;
71    };
72
73    class StyleEntry;
74
75    class StyleRef {
76    public:
77        StyleRef();
78        StyleRef(const StyleRef&);
79        ~StyleRef();
80
81        StyleRef& operator=(const StyleRef& rhs);
82        const StyleEntry* operator->() const;
83        const StyleEntry& operator*() const;
84
85        size_t getIndex() const;
86        const Context& getContext() const;
87
88    private:
89        friend class StringPool;
90
91        StyleRef(StyleEntry* entry);
92
93        StyleEntry* mEntry;
94    };
95
96    class Entry {
97    public:
98        std::u16string value;
99        Context context;
100        size_t index;
101
102    private:
103        friend class StringPool;
104        friend class Ref;
105
106        int ref;
107    };
108
109    struct Span {
110        Ref name;
111        uint32_t firstChar;
112        uint32_t lastChar;
113    };
114
115    class StyleEntry {
116    public:
117        Ref str;
118        std::vector<Span> spans;
119
120    private:
121        friend class StringPool;
122        friend class StyleRef;
123
124        int ref;
125    };
126
127    using const_iterator = std::vector<std::unique_ptr<Entry>>::const_iterator;
128
129    static bool flattenUtf8(BigBuffer* out, const StringPool& pool);
130    static bool flattenUtf16(BigBuffer* out, const StringPool& pool);
131
132    StringPool() = default;
133    StringPool(const StringPool&) = delete;
134
135    /**
136     * Adds a string to the pool, unless it already exists. Returns
137     * a reference to the string in the pool.
138     */
139    Ref makeRef(const StringPiece16& str);
140
141    /**
142     * Adds a string to the pool, unless it already exists, with a context
143     * object that can be used when sorting the string pool. Returns
144     * a reference to the string in the pool.
145     */
146    Ref makeRef(const StringPiece16& str, const Context& context);
147
148    /**
149     * Adds a style to the string pool and returns a reference to it.
150     */
151    StyleRef makeRef(const StyleString& str);
152
153    /**
154     * Adds a style to the string pool with a context object that
155     * can be used when sorting the string pool. Returns a reference
156     * to the style in the string pool.
157     */
158    StyleRef makeRef(const StyleString& str, const Context& context);
159
160    /**
161     * Adds a style from another string pool. Returns a reference to the
162     * style in the string pool.
163     */
164    StyleRef makeRef(const StyleRef& ref);
165
166    /**
167     * Moves pool into this one without coalescing strings. When this
168     * function returns, pool will be empty.
169     */
170    void merge(StringPool&& pool);
171
172    /**
173     * Retuns the number of strings in the table.
174     */
175    inline size_t size() const;
176
177    /**
178     * Reserves space for strings and styles as an optimization.
179     */
180    void hintWillAdd(size_t stringCount, size_t styleCount);
181
182    /**
183     * Sorts the strings according to some comparison function.
184     */
185    void sort(const std::function<bool(const Entry&, const Entry&)>& cmp);
186
187    /**
188     * Removes any strings that have no references.
189     */
190    void prune();
191
192private:
193    friend const_iterator begin(const StringPool& pool);
194    friend const_iterator end(const StringPool& pool);
195
196    static bool flatten(BigBuffer* out, const StringPool& pool, bool utf8);
197
198    Ref makeRefImpl(const StringPiece16& str, const Context& context, bool unique);
199
200    std::vector<std::unique_ptr<Entry>> mStrings;
201    std::vector<std::unique_ptr<StyleEntry>> mStyles;
202    std::multimap<StringPiece16, Entry*> mIndexedStrings;
203};
204
205//
206// Inline implementation
207//
208
209inline size_t StringPool::size() const {
210    return mStrings.size();
211}
212
213inline StringPool::const_iterator begin(const StringPool& pool) {
214    return pool.mStrings.begin();
215}
216
217inline StringPool::const_iterator end(const StringPool& pool) {
218    return pool.mStrings.end();
219}
220
221} // namespace aapt
222
223#endif // AAPT_STRING_POOL_H
224