blob: 30328299bb84a9d5abdd9ea2879c9e0f6a51c853 [file] [log] [blame]
Adam Lesinski6f6ceb72014-11-14 14:48:12 -08001/*
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
Adam Lesinski52364f72016-01-11 13:10:24 -080017#include "StringPool.h"
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080018
Adam Lesinskicacb28f2016-10-19 12:18:14 -070019#include <algorithm>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080020#include <memory>
21#include <string>
22
Adam Lesinskice5e56e2016-10-21 17:56:45 -070023#include "android-base/logging.h"
24#include "androidfw/ResourceTypes.h"
25
26#include "util/BigBuffer.h"
27#include "util/StringPiece.h"
28#include "util/Util.h"
29
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080030namespace aapt {
31
Adam Lesinskice5e56e2016-10-21 17:56:45 -070032StringPool::Ref::Ref() : entry_(nullptr) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080033
Adam Lesinskice5e56e2016-10-21 17:56:45 -070034StringPool::Ref::Ref(const StringPool::Ref& rhs) : entry_(rhs.entry_) {
35 if (entry_ != nullptr) {
36 entry_->ref_++;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070037 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080038}
39
Adam Lesinskice5e56e2016-10-21 17:56:45 -070040StringPool::Ref::Ref(StringPool::Entry* entry) : entry_(entry) {
41 if (entry_ != nullptr) {
42 entry_->ref_++;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070043 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080044}
45
46StringPool::Ref::~Ref() {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070047 if (entry_ != nullptr) {
48 entry_->ref_--;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070049 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080050}
51
52StringPool::Ref& StringPool::Ref::operator=(const StringPool::Ref& rhs) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070053 if (rhs.entry_ != nullptr) {
54 rhs.entry_->ref_++;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070055 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080056
Adam Lesinskice5e56e2016-10-21 17:56:45 -070057 if (entry_ != nullptr) {
58 entry_->ref_--;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070059 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -070060 entry_ = rhs.entry_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070061 return *this;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080062}
63
Adam Lesinskid0f116b2016-07-08 15:00:32 -070064const std::string* StringPool::Ref::operator->() const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070065 return &entry_->value;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080066}
67
Adam Lesinskice5e56e2016-10-21 17:56:45 -070068const std::string& StringPool::Ref::operator*() const { return entry_->value; }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080069
Adam Lesinskice5e56e2016-10-21 17:56:45 -070070size_t StringPool::Ref::index() const { return entry_->index; }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080071
Adam Lesinskice5e56e2016-10-21 17:56:45 -070072const StringPool::Context& StringPool::Ref::GetContext() const {
73 return entry_->context;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080074}
75
Adam Lesinskice5e56e2016-10-21 17:56:45 -070076StringPool::StyleRef::StyleRef() : entry_(nullptr) {}
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080077
Adam Lesinskicacb28f2016-10-19 12:18:14 -070078StringPool::StyleRef::StyleRef(const StringPool::StyleRef& rhs)
Adam Lesinskice5e56e2016-10-21 17:56:45 -070079 : entry_(rhs.entry_) {
80 if (entry_ != nullptr) {
81 entry_->ref_++;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070082 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080083}
84
Adam Lesinskice5e56e2016-10-21 17:56:45 -070085StringPool::StyleRef::StyleRef(StringPool::StyleEntry* entry) : entry_(entry) {
86 if (entry_ != nullptr) {
87 entry_->ref_++;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070088 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080089}
90
91StringPool::StyleRef::~StyleRef() {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070092 if (entry_ != nullptr) {
93 entry_->ref_--;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070094 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080095}
96
Adam Lesinskicacb28f2016-10-19 12:18:14 -070097StringPool::StyleRef& StringPool::StyleRef::operator=(
98 const StringPool::StyleRef& rhs) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070099 if (rhs.entry_ != nullptr) {
100 rhs.entry_->ref_++;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700101 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800102
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700103 if (entry_ != nullptr) {
104 entry_->ref_--;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700105 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700106 entry_ = rhs.entry_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700107 return *this;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800108}
109
110const StringPool::StyleEntry* StringPool::StyleRef::operator->() const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700111 return entry_;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800112}
113
114const StringPool::StyleEntry& StringPool::StyleRef::operator*() const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700115 return *entry_;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800116}
117
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700118size_t StringPool::StyleRef::index() const { return entry_->str.index(); }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800119
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700120const StringPool::Context& StringPool::StyleRef::GetContext() const {
121 return entry_->str.GetContext();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800122}
123
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700124StringPool::Ref StringPool::MakeRef(const StringPiece& str) {
125 return MakeRefImpl(str, Context{}, true);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800126}
127
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700128StringPool::Ref StringPool::MakeRef(const StringPiece& str,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700129 const Context& context) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700130 return MakeRefImpl(str, context, true);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800131}
132
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700133StringPool::Ref StringPool::MakeRefImpl(const StringPiece& str,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700134 const Context& context, bool unique) {
135 if (unique) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700136 auto iter = indexed_strings_.find(str);
137 if (iter != std::end(indexed_strings_)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700138 return Ref(iter->second);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800139 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700140 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800141
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700142 Entry* entry = new Entry();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700143 entry->value = str.ToString();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700144 entry->context = context;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700145 entry->index = strings_.size();
146 entry->ref_ = 0;
147 strings_.emplace_back(entry);
148 indexed_strings_.insert(std::make_pair(StringPiece(entry->value), entry));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700149 return Ref(entry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800150}
151
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700152StringPool::StyleRef StringPool::MakeRef(const StyleString& str) {
153 return MakeRef(str, Context{});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800154}
155
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700156StringPool::StyleRef StringPool::MakeRef(const StyleString& str,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700157 const Context& context) {
158 Entry* entry = new Entry();
159 entry->value = str.str;
160 entry->context = context;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700161 entry->index = strings_.size();
162 entry->ref_ = 0;
163 strings_.emplace_back(entry);
164 indexed_strings_.insert(std::make_pair(StringPiece(entry->value), entry));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800165
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700166 StyleEntry* style_entry = new StyleEntry();
167 style_entry->str = Ref(entry);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700168 for (const aapt::Span& span : str.spans) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700169 style_entry->spans.emplace_back(
170 Span{MakeRef(span.name), span.first_char, span.last_char});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700171 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700172 style_entry->ref_ = 0;
173 styles_.emplace_back(style_entry);
174 return StyleRef(style_entry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800175}
176
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700177StringPool::StyleRef StringPool::MakeRef(const StyleRef& ref) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700178 Entry* entry = new Entry();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700179 entry->value = *ref.entry_->str;
180 entry->context = ref.entry_->str.entry_->context;
181 entry->index = strings_.size();
182 entry->ref_ = 0;
183 strings_.emplace_back(entry);
184 indexed_strings_.insert(std::make_pair(StringPiece(entry->value), entry));
Adam Lesinski769de982015-04-10 19:43:55 -0700185
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700186 StyleEntry* style_entry = new StyleEntry();
187 style_entry->str = Ref(entry);
188 for (const Span& span : ref.entry_->spans) {
189 style_entry->spans.emplace_back(
190 Span{MakeRef(*span.name), span.first_char, span.last_char});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700191 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700192 style_entry->ref_ = 0;
193 styles_.emplace_back(style_entry);
194 return StyleRef(style_entry);
Adam Lesinski769de982015-04-10 19:43:55 -0700195}
196
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700197void StringPool::Merge(StringPool&& pool) {
198 indexed_strings_.insert(pool.indexed_strings_.begin(),
199 pool.indexed_strings_.end());
200 pool.indexed_strings_.clear();
201 std::move(pool.strings_.begin(), pool.strings_.end(),
202 std::back_inserter(strings_));
203 pool.strings_.clear();
204 std::move(pool.styles_.begin(), pool.styles_.end(),
205 std::back_inserter(styles_));
206 pool.styles_.clear();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800207
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700208 // Assign the indices.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700209 const size_t len = strings_.size();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700210 for (size_t index = 0; index < len; index++) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700211 strings_[index]->index = index;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700212 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800213}
214
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700215void StringPool::HintWillAdd(size_t stringCount, size_t styleCount) {
216 strings_.reserve(strings_.size() + stringCount);
217 styles_.reserve(styles_.size() + styleCount);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800218}
219
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700220void StringPool::Prune() {
221 const auto iter_end = indexed_strings_.end();
222 auto index_iter = indexed_strings_.begin();
223 while (index_iter != iter_end) {
224 if (index_iter->second->ref_ <= 0) {
225 index_iter = indexed_strings_.erase(index_iter);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700226 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700227 ++index_iter;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800228 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700229 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800230
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700231 auto end_iter2 =
232 std::remove_if(strings_.begin(), strings_.end(),
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700233 [](const std::unique_ptr<Entry>& entry) -> bool {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700234 return entry->ref_ <= 0;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700235 });
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800236
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700237 auto end_iter3 =
238 std::remove_if(styles_.begin(), styles_.end(),
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700239 [](const std::unique_ptr<StyleEntry>& entry) -> bool {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700240 return entry->ref_ <= 0;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700241 });
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800242
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700243 // Remove the entries at the end or else we'll be accessing
244 // a deleted string from the StyleEntry.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700245 strings_.erase(end_iter2, strings_.end());
246 styles_.erase(end_iter3, styles_.end());
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700247
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700248 // Reassign the indices.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700249 const size_t len = strings_.size();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700250 for (size_t index = 0; index < len; index++) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700251 strings_[index]->index = index;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700252 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800253}
254
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700255void StringPool::Sort(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700256 const std::function<bool(const Entry&, const Entry&)>& cmp) {
257 std::sort(
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700258 strings_.begin(), strings_.end(),
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700259 [&cmp](const std::unique_ptr<Entry>& a,
260 const std::unique_ptr<Entry>& b) -> bool { return cmp(*a, *b); });
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800261
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700262 // Assign the indices.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700263 const size_t len = strings_.size();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700264 for (size_t index = 0; index < len; index++) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700265 strings_[index]->index = index;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700266 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800267
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700268 // Reorder the styles.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700269 std::sort(styles_.begin(), styles_.end(),
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800270 [](const std::unique_ptr<StyleEntry>& lhs,
271 const std::unique_ptr<StyleEntry>& rhs) -> bool {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700272 return lhs->str.index() < rhs->str.index();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700273 });
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800274}
275
Adam Lesinski24aad162015-04-24 19:19:30 -0700276template <typename T>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700277static T* EncodeLength(T* data, size_t length) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700278 static_assert(std::is_integral<T>::value, "wat.");
Adam Lesinski24aad162015-04-24 19:19:30 -0700279
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700280 constexpr size_t kMask = 1 << ((sizeof(T) * 8) - 1);
281 constexpr size_t kMaxSize = kMask - 1;
282 if (length > kMaxSize) {
283 *data++ = kMask | (kMaxSize & (length >> (sizeof(T) * 8)));
284 }
285 *data++ = length;
286 return data;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800287}
288
Adam Lesinski24aad162015-04-24 19:19:30 -0700289template <typename T>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700290static size_t EncodedLengthUnits(size_t length) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700291 static_assert(std::is_integral<T>::value, "wat.");
Adam Lesinski24aad162015-04-24 19:19:30 -0700292
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700293 constexpr size_t kMask = 1 << ((sizeof(T) * 8) - 1);
294 constexpr size_t kMaxSize = kMask - 1;
295 return length > kMaxSize ? 2 : 1;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800296}
297
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700298bool StringPool::Flatten(BigBuffer* out, const StringPool& pool, bool utf8) {
299 const size_t start_index = out->size();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700300 android::ResStringPool_header* header =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700301 out->NextBlock<android::ResStringPool_header>();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700302 header->header.type = android::RES_STRING_POOL_TYPE;
303 header->header.headerSize = sizeof(*header);
304 header->stringCount = pool.size();
305 if (utf8) {
306 header->flags |= android::ResStringPool_header::UTF8_FLAG;
307 }
308
309 uint32_t* indices =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700310 pool.size() != 0 ? out->NextBlock<uint32_t>(pool.size()) : nullptr;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700311
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700312 uint32_t* style_indices = nullptr;
313 if (!pool.styles_.empty()) {
314 header->styleCount = pool.styles_.back()->str.index() + 1;
315 style_indices = out->NextBlock<uint32_t>(header->styleCount);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700316 }
317
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700318 const size_t before_strings_index = out->size();
319 header->stringsStart = before_strings_index - start_index;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700320
321 for (const auto& entry : pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700322 *indices = out->size() - before_strings_index;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700323 indices++;
324
Adam Lesinski24aad162015-04-24 19:19:30 -0700325 if (utf8) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700326 const std::string& encoded = entry->value;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700327 const ssize_t utf16_length = utf8_to_utf16_length(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700328 reinterpret_cast<const uint8_t*>(entry->value.data()),
329 entry->value.size());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700330 CHECK(utf16_length >= 0);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700331
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700332 const size_t total_size = EncodedLengthUnits<char>(utf16_length) +
333 EncodedLengthUnits<char>(encoded.length()) +
334 encoded.size() + 1;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700335
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700336 char* data = out->NextBlock<char>(total_size);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700337
338 // First encode the UTF16 string length.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700339 data = EncodeLength(data, utf16_length);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700340
341 // Now encode the size of the real UTF8 string.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700342 data = EncodeLength(data, encoded.length());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700343 strncpy(data, encoded.data(), encoded.size());
344
345 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700346 const std::u16string encoded = util::Utf8ToUtf16(entry->value);
347 const ssize_t utf16_length = encoded.size();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700348
349 // Total number of 16-bit words to write.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700350 const size_t total_size =
351 EncodedLengthUnits<char16_t>(utf16_length) + encoded.size() + 1;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700352
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700353 char16_t* data = out->NextBlock<char16_t>(total_size);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700354
355 // Encode the actual UTF16 string length.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700356 data = EncodeLength(data, utf16_length);
357 const size_t byte_length = encoded.size() * sizeof(char16_t);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700358
359 // NOTE: For some reason, strncpy16(data, entry->value.data(),
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700360 // entry->value.size()) truncates the string.
361 memcpy(data, encoded.data(), byte_length);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700362
363 // The null-terminating character is already here due to the block of data
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700364 // being set to 0s on allocation.
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700365 }
366 }
367
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700368 out->Align4();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700369
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700370 if (!pool.styles_.empty()) {
371 const size_t before_styles_index = out->size();
372 header->stylesStart = before_styles_index - start_index;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700373
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700374 size_t current_index = 0;
375 for (const auto& entry : pool.styles_) {
376 while (entry->str.index() > current_index) {
377 style_indices[current_index++] = out->size() - before_styles_index;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700378
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700379 uint32_t* span_offset = out->NextBlock<uint32_t>();
380 *span_offset = android::ResStringPool_span::END;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700381 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700382 style_indices[current_index++] = out->size() - before_styles_index;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700383
384 android::ResStringPool_span* span =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700385 out->NextBlock<android::ResStringPool_span>(entry->spans.size());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700386 for (const auto& s : entry->spans) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700387 span->name.index = s.name.index();
388 span->firstChar = s.first_char;
389 span->lastChar = s.last_char;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700390 span++;
391 }
392
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700393 uint32_t* spanEnd = out->NextBlock<uint32_t>();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700394 *spanEnd = android::ResStringPool_span::END;
Adam Lesinski24aad162015-04-24 19:19:30 -0700395 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800396
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700397 // The error checking code in the platform looks for an entire
398 // ResStringPool_span structure worth of 0xFFFFFFFF at the end
399 // of the style block, so fill in the remaining 2 32bit words
400 // with 0xFFFFFFFF.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700401 const size_t padding_length = sizeof(android::ResStringPool_span) -
402 sizeof(android::ResStringPool_span::name);
403 uint8_t* padding = out->NextBlock<uint8_t>(padding_length);
404 memset(padding, 0xff, padding_length);
405 out->Align4();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700406 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700407 header->header.size = out->size() - start_index;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700408 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800409}
410
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700411bool StringPool::FlattenUtf8(BigBuffer* out, const StringPool& pool) {
412 return Flatten(out, pool, true);
Adam Lesinski24aad162015-04-24 19:19:30 -0700413}
414
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700415bool StringPool::FlattenUtf16(BigBuffer* out, const StringPool& pool) {
416 return Flatten(out, pool, false);
Adam Lesinski24aad162015-04-24 19:19:30 -0700417}
418
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700419} // namespace aapt