Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: ui/base/resource/data_pack.cc

Issue 2989443002: Revert of Add deduplication logic to .pak files (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/base/resource/data_pack.h ('k') | ui/base/resource/data_pack_literal.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/base/resource/data_pack.h" 5 #include "ui/base/resource/data_pack.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
13 #include "base/files/memory_mapped_file.h" 13 #include "base/files/memory_mapped_file.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
16 #include "base/memory/ref_counted_memory.h" 16 #include "base/memory/ref_counted_memory.h"
17 #include "base/metrics/histogram_macros.h" 17 #include "base/metrics/histogram_macros.h"
18 #include "base/stl_util.h" 18 #include "base/stl_util.h"
19 #include "base/strings/string_piece.h" 19 #include "base/strings/string_piece.h"
20 #include "base/synchronization/lock.h" 20 #include "base/synchronization/lock.h"
21 21
22 // For details of the file layout, see 22 // For details of the file layout, see
23 // http://dev.chromium.org/developers/design-documents/linuxresourcesandlocalize dstrings 23 // http://dev.chromium.org/developers/design-documents/linuxresourcesandlocalize dstrings
24 24
25 namespace { 25 namespace {
26 26
27 static const uint32_t kFileFormatV4 = 4; 27 static const uint32_t kFileFormatVersion = 4;
28 static const uint32_t kFileFormatV5 = 5; 28 // Length of file header: version, entry count and text encoding type.
29 // int32(version), int32(resource_count), int8(encoding) 29 static const size_t kHeaderLength = 2 * sizeof(uint32_t) + sizeof(uint8_t);
30 static const size_t kHeaderLengthV4 = 2 * sizeof(uint32_t) + sizeof(uint8_t); 30
31 // int32(version), int8(encoding), 3 bytes padding, 31 #pragma pack(push, 2)
32 // int16(resource_count), int16(alias_count) 32 struct DataPackEntry {
33 static const size_t kHeaderLengthV5 = 33 uint16_t resource_id;
34 sizeof(uint32_t) + sizeof(uint8_t) * 4 + sizeof(uint16_t) * 2; 34 uint32_t file_offset;
35
36 static int CompareById(const void* void_key, const void* void_entry) {
37 uint16_t key = *reinterpret_cast<const uint16_t*>(void_key);
38 const DataPackEntry* entry =
39 reinterpret_cast<const DataPackEntry*>(void_entry);
40 if (key < entry->resource_id) {
41 return -1;
42 } else if (key > entry->resource_id) {
43 return 1;
44 } else {
45 return 0;
46 }
47 }
48 };
49 #pragma pack(pop)
50
51 static_assert(sizeof(DataPackEntry) == 6, "size of entry must be six");
35 52
36 // We're crashing when trying to load a pak file on Windows. Add some error 53 // We're crashing when trying to load a pak file on Windows. Add some error
37 // codes for logging. 54 // codes for logging.
38 // http://crbug.com/58056 55 // http://crbug.com/58056
39 enum LoadErrors { 56 enum LoadErrors {
40 INIT_FAILED = 1, 57 INIT_FAILED = 1,
41 BAD_VERSION, 58 BAD_VERSION,
42 INDEX_TRUNCATED, 59 INDEX_TRUNCATED,
43 ENTRY_NOT_FOUND, 60 ENTRY_NOT_FOUND,
44 HEADER_TRUNCATED, 61 HEADER_TRUNCATED,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 if (!base::ContainsKey(*resource_ids_logged, resource_id)) { 95 if (!base::ContainsKey(*resource_ids_logged, resource_id)) {
79 printf("Resource=%d\n", resource_id); 96 printf("Resource=%d\n", resource_id);
80 resource_ids_logged->insert(resource_id); 97 resource_ids_logged->insert(resource_id);
81 } 98 }
82 } 99 }
83 100
84 } // namespace 101 } // namespace
85 102
86 namespace ui { 103 namespace ui {
87 104
88 #pragma pack(push, 2)
89 struct DataPack::Entry {
90 uint16_t resource_id;
91 uint32_t file_offset;
92
93 static int CompareById(const void* void_key, const void* void_entry) {
94 uint16_t key = *reinterpret_cast<const uint16_t*>(void_key);
95 const Entry* entry = reinterpret_cast<const Entry*>(void_entry);
96 return key - entry->resource_id;
97 }
98 };
99
100 struct DataPack::Alias {
101 uint16_t resource_id;
102 uint16_t entry_index;
103
104 static int CompareById(const void* void_key, const void* void_entry) {
105 uint16_t key = *reinterpret_cast<const uint16_t*>(void_key);
106 const Alias* entry = reinterpret_cast<const Alias*>(void_entry);
107 return key - entry->resource_id;
108 }
109 };
110 #pragma pack(pop)
111
112 // Abstraction of a data source (memory mapped file or in-memory buffer). 105 // Abstraction of a data source (memory mapped file or in-memory buffer).
113 class DataPack::DataSource { 106 class DataPack::DataSource {
114 public: 107 public:
115 virtual ~DataSource() {} 108 virtual ~DataSource() {}
116 109
117 virtual size_t GetLength() const = 0; 110 virtual size_t GetLength() const = 0;
118 virtual const uint8_t* GetData() const = 0; 111 virtual const uint8_t* GetData() const = 0;
119 }; 112 };
120 113
121 class DataPack::MemoryMappedDataSource : public DataPack::DataSource { 114 class DataPack::MemoryMappedDataSource : public DataPack::DataSource {
(...skipping 27 matching lines...) Expand all
149 return reinterpret_cast<const uint8_t*>(buffer_.data()); 142 return reinterpret_cast<const uint8_t*>(buffer_.data());
150 } 143 }
151 144
152 private: 145 private:
153 base::StringPiece buffer_; 146 base::StringPiece buffer_;
154 147
155 DISALLOW_COPY_AND_ASSIGN(BufferDataSource); 148 DISALLOW_COPY_AND_ASSIGN(BufferDataSource);
156 }; 149 };
157 150
158 DataPack::DataPack(ui::ScaleFactor scale_factor) 151 DataPack::DataPack(ui::ScaleFactor scale_factor)
159 : resource_table_(nullptr), 152 : resource_count_(0),
160 resource_count_(0),
161 alias_table_(nullptr),
162 alias_count_(0),
163 text_encoding_type_(BINARY), 153 text_encoding_type_(BINARY),
164 scale_factor_(scale_factor) { 154 scale_factor_(scale_factor) {
165 // Static assert must be within a DataPack member to appease visiblity rules.
166 static_assert(sizeof(Entry) == 6, "size of Entry must be 6");
167 static_assert(sizeof(Alias) == 4, "size of Alias must be 4");
168 } 155 }
169 156
170 DataPack::~DataPack() { 157 DataPack::~DataPack() {
171 } 158 }
172 159
173 bool DataPack::LoadFromPath(const base::FilePath& path) { 160 bool DataPack::LoadFromPath(const base::FilePath& path) {
174 std::unique_ptr<base::MemoryMappedFile> mmap = 161 std::unique_ptr<base::MemoryMappedFile> mmap =
175 base::MakeUnique<base::MemoryMappedFile>(); 162 base::MakeUnique<base::MemoryMappedFile>();
176 if (!mmap->Initialize(path)) { 163 if (!mmap->Initialize(path)) {
177 DLOG(ERROR) << "Failed to mmap datapack"; 164 DLOG(ERROR) << "Failed to mmap datapack";
(...skipping 21 matching lines...) Expand all
199 return false; 186 return false;
200 } 187 }
201 return LoadImpl(base::MakeUnique<MemoryMappedDataSource>(std::move(mmap))); 188 return LoadImpl(base::MakeUnique<MemoryMappedDataSource>(std::move(mmap)));
202 } 189 }
203 190
204 bool DataPack::LoadFromBuffer(base::StringPiece buffer) { 191 bool DataPack::LoadFromBuffer(base::StringPiece buffer) {
205 return LoadImpl(base::MakeUnique<BufferDataSource>(buffer)); 192 return LoadImpl(base::MakeUnique<BufferDataSource>(buffer));
206 } 193 }
207 194
208 bool DataPack::LoadImpl(std::unique_ptr<DataPack::DataSource> data_source) { 195 bool DataPack::LoadImpl(std::unique_ptr<DataPack::DataSource> data_source) {
209 const uint8_t* data = data_source->GetData(); 196 // Sanity check the header of the file.
210 size_t data_length = data_source->GetLength(); 197 if (kHeaderLength > data_source->GetLength()) {
211 // Parse the version and check for truncated header.
212 uint32_t version = 0;
213 if (data_length > sizeof(version))
214 version = reinterpret_cast<const uint32_t*>(data)[0];
215 size_t header_length =
216 version == kFileFormatV4 ? kHeaderLengthV4 : kHeaderLengthV5;
217 if (version == 0 || data_length < header_length) {
218 DLOG(ERROR) << "Data pack file corruption: incomplete file header."; 198 DLOG(ERROR) << "Data pack file corruption: incomplete file header.";
219 LogDataPackError(HEADER_TRUNCATED); 199 LogDataPackError(HEADER_TRUNCATED);
220 return false; 200 return false;
221 } 201 }
222 202
223 // Parse the header of the file. 203 // Parse the header of the file.
224 if (version == kFileFormatV4) { 204 // First uint32_t: version; second: resource count;
225 resource_count_ = reinterpret_cast<const uint32_t*>(data)[1]; 205 const uint32_t* ptr =
226 alias_count_ = 0; 206 reinterpret_cast<const uint32_t*>(data_source->GetData());
227 text_encoding_type_ = static_cast<TextEncodingType>(data[8]); 207 uint32_t version = ptr[0];
228 } else if (version == kFileFormatV5) { 208 if (version != kFileFormatVersion) {
229 // Version 5 added the alias table and changed the header format.
230 text_encoding_type_ = static_cast<TextEncodingType>(data[4]);
231 resource_count_ = reinterpret_cast<const uint16_t*>(data)[4];
232 alias_count_ = reinterpret_cast<const uint16_t*>(data)[5];
233 } else {
234 LOG(ERROR) << "Bad data pack version: got " << version << ", expected " 209 LOG(ERROR) << "Bad data pack version: got " << version << ", expected "
235 << kFileFormatV4 << " or " << kFileFormatV5; 210 << kFileFormatVersion;
236 LogDataPackError(BAD_VERSION); 211 LogDataPackError(BAD_VERSION);
237 return false; 212 return false;
238 } 213 }
214 resource_count_ = ptr[1];
239 215
216 // third: text encoding.
217 const uint8_t* ptr_encoding = reinterpret_cast<const uint8_t*>(ptr + 2);
218 text_encoding_type_ = static_cast<TextEncodingType>(*ptr_encoding);
240 if (text_encoding_type_ != UTF8 && text_encoding_type_ != UTF16 && 219 if (text_encoding_type_ != UTF8 && text_encoding_type_ != UTF16 &&
241 text_encoding_type_ != BINARY) { 220 text_encoding_type_ != BINARY) {
242 LOG(ERROR) << "Bad data pack text encoding: got " << text_encoding_type_ 221 LOG(ERROR) << "Bad data pack text encoding: got " << text_encoding_type_
243 << ", expected between " << BINARY << " and " << UTF16; 222 << ", expected between " << BINARY << " and " << UTF16;
244 LogDataPackError(WRONG_ENCODING); 223 LogDataPackError(WRONG_ENCODING);
245 return false; 224 return false;
246 } 225 }
247 226
248 // Sanity check the file. 227 // Sanity check the file.
249 // 1) Check we have enough entries. There's an extra entry after the last item 228 // 1) Check we have enough entries. There's an extra entry after the last item
250 // which gives the length of the last item. 229 // which gives the length of the last item.
251 size_t resource_table_size = (resource_count_ + 1) * sizeof(Entry); 230 if (kHeaderLength + (resource_count_ + 1) * sizeof(DataPackEntry) >
252 size_t alias_table_size = alias_count_ * sizeof(Alias); 231 data_source->GetLength()) {
253 if (header_length + resource_table_size + alias_table_size > data_length) { 232 LOG(ERROR) << "Data pack file corruption: too short for number of "
254 LOG(ERROR) << "Data pack file corruption: " 233 "entries specified.";
255 << "too short for number of entries.";
256 LogDataPackError(INDEX_TRUNCATED); 234 LogDataPackError(INDEX_TRUNCATED);
257 return false; 235 return false;
258 } 236 }
259
260 resource_table_ = reinterpret_cast<const Entry*>(&data[header_length]);
261 alias_table_ = reinterpret_cast<const Alias*>(
262 &data[header_length + resource_table_size]);
263
264 // 2) Verify the entries are within the appropriate bounds. There's an extra 237 // 2) Verify the entries are within the appropriate bounds. There's an extra
265 // entry after the last item which gives us the length of the last item. 238 // entry after the last item which gives us the length of the last item.
266 for (size_t i = 0; i < resource_count_ + 1; ++i) { 239 for (size_t i = 0; i < resource_count_ + 1; ++i) {
267 if (resource_table_[i].file_offset > data_length) { 240 const DataPackEntry* entry = reinterpret_cast<const DataPackEntry*>(
268 LOG(ERROR) << "Data pack file corruption: " 241 data_source->GetData() + kHeaderLength + (i * sizeof(DataPackEntry)));
269 << "Entry #" << i << " past end."; 242 if (entry->file_offset > data_source->GetLength()) {
270 LogDataPackError(ENTRY_NOT_FOUND); 243 LOG(ERROR) << "Entry #" << i << " in data pack points off end of file. "
271 return false; 244 << "Was the file corrupted?";
272 }
273 }
274
275 // 3) Verify the aliases are within the appropriate bounds.
276 for (size_t i = 0; i < alias_count_; ++i) {
277 if (alias_table_[i].entry_index >= resource_count_) {
278 LOG(ERROR) << "Data pack file corruption: "
279 << "Alias #" << i << " past end.";
280 LogDataPackError(ENTRY_NOT_FOUND); 245 LogDataPackError(ENTRY_NOT_FOUND);
281 return false; 246 return false;
282 } 247 }
283 } 248 }
284 249
285 data_source_ = std::move(data_source); 250 data_source_ = std::move(data_source);
251
286 return true; 252 return true;
287 } 253 }
288 254
289 const DataPack::Entry* DataPack::LookupEntryById(uint16_t resource_id) const {
290 // Search the resource table first as most resources will be in there.
291 const Entry* ret = reinterpret_cast<const Entry*>(
292 bsearch(&resource_id, resource_table_, resource_count_, sizeof(Entry),
293 Entry::CompareById));
294 if (ret == nullptr) {
295 // Search the alias table for the ~10% of entries which are aliases.
296 const Alias* alias = reinterpret_cast<const Alias*>(
297 bsearch(&resource_id, alias_table_, alias_count_, sizeof(Alias),
298 Alias::CompareById));
299 if (alias != nullptr) {
300 ret = &resource_table_[alias->entry_index];
301 }
302 }
303 return ret;
304 }
305
306 bool DataPack::HasResource(uint16_t resource_id) const { 255 bool DataPack::HasResource(uint16_t resource_id) const {
307 return !!LookupEntryById(resource_id); 256 return !!bsearch(&resource_id, data_source_->GetData() + kHeaderLength,
257 resource_count_, sizeof(DataPackEntry),
258 DataPackEntry::CompareById);
308 } 259 }
309 260
310 bool DataPack::GetStringPiece(uint16_t resource_id, 261 bool DataPack::GetStringPiece(uint16_t resource_id,
311 base::StringPiece* data) const { 262 base::StringPiece* data) const {
312 // It won't be hard to make this endian-agnostic, but it's not worth 263 // It won't be hard to make this endian-agnostic, but it's not worth
313 // bothering to do right now. 264 // bothering to do right now.
314 #if defined(__BYTE_ORDER) 265 #if defined(__BYTE_ORDER)
315 // Linux check 266 // Linux check
316 static_assert(__BYTE_ORDER == __LITTLE_ENDIAN, 267 static_assert(__BYTE_ORDER == __LITTLE_ENDIAN,
317 "datapack assumes little endian"); 268 "datapack assumes little endian");
318 #elif defined(__BIG_ENDIAN__) 269 #elif defined(__BIG_ENDIAN__)
319 // Mac check 270 // Mac check
320 #error DataPack assumes little endian 271 #error DataPack assumes little endian
321 #endif 272 #endif
322 273
323 const Entry* target = LookupEntryById(resource_id); 274 const DataPackEntry* target = reinterpret_cast<const DataPackEntry*>(bsearch(
324 if (!target) 275 &resource_id, data_source_->GetData() + kHeaderLength, resource_count_,
276 sizeof(DataPackEntry), DataPackEntry::CompareById));
277 if (!target) {
325 return false; 278 return false;
279 }
326 280
327 const Entry* next_entry = target + 1; 281 const DataPackEntry* next_entry = target + 1;
328 // If the next entry points beyond the end of the file this data pack's entry 282 // If the next entry points beyond the end of the file this data pack's entry
329 // table is corrupt. Log an error and return false. See 283 // table is corrupt. Log an error and return false. See
330 // http://crbug.com/371301. 284 // http://crbug.com/371301.
331 size_t entry_offset = 285 if (next_entry->file_offset > data_source_->GetLength()) {
332 reinterpret_cast<const uint8_t*>(next_entry) - data_source_->GetData(); 286 size_t entry_index = target - reinterpret_cast<const DataPackEntry*>(
333 size_t pak_size = data_source_->GetLength(); 287 data_source_->GetData() + kHeaderLength);
334 if (entry_offset > pak_size || next_entry->file_offset > pak_size) {
335 size_t entry_index = target - resource_table_;
336 LOG(ERROR) << "Entry #" << entry_index << " in data pack points off end " 288 LOG(ERROR) << "Entry #" << entry_index << " in data pack points off end "
337 << "of file. This should have been caught when loading. Was the " 289 << "of file. This should have been caught when loading. Was the "
338 << "file modified?"; 290 << "file modified?";
339 return false; 291 return false;
340 } 292 }
341 293
342 MaybePrintResourceId(resource_id); 294 MaybePrintResourceId(resource_id);
343 size_t length = next_entry->file_offset - target->file_offset; 295 size_t length = next_entry->file_offset - target->file_offset;
344 data->set(reinterpret_cast<const char*>(data_source_->GetData() + 296 data->set(reinterpret_cast<const char*>(data_source_->GetData() +
345 target->file_offset), 297 target->file_offset),
(...skipping 15 matching lines...) Expand all
361 } 313 }
362 314
363 ui::ScaleFactor DataPack::GetScaleFactor() const { 315 ui::ScaleFactor DataPack::GetScaleFactor() const {
364 return scale_factor_; 316 return scale_factor_;
365 } 317 }
366 318
367 #if DCHECK_IS_ON() 319 #if DCHECK_IS_ON()
368 void DataPack::CheckForDuplicateResources( 320 void DataPack::CheckForDuplicateResources(
369 const std::vector<std::unique_ptr<ResourceHandle>>& packs) { 321 const std::vector<std::unique_ptr<ResourceHandle>>& packs) {
370 for (size_t i = 0; i < resource_count_ + 1; ++i) { 322 for (size_t i = 0; i < resource_count_ + 1; ++i) {
371 const uint16_t resource_id = resource_table_[i].resource_id; 323 const DataPackEntry* entry = reinterpret_cast<const DataPackEntry*>(
324 data_source_->GetData() + kHeaderLength + (i * sizeof(DataPackEntry)));
325 const uint16_t resource_id = entry->resource_id;
372 const float resource_scale = GetScaleForScaleFactor(scale_factor_); 326 const float resource_scale = GetScaleForScaleFactor(scale_factor_);
373 for (const auto& handle : packs) { 327 for (const auto& handle : packs) {
374 if (GetScaleForScaleFactor(handle->GetScaleFactor()) != resource_scale) 328 if (GetScaleForScaleFactor(handle->GetScaleFactor()) != resource_scale)
375 continue; 329 continue;
376 DCHECK(!handle->HasResource(resource_id)) << "Duplicate resource " 330 DCHECK(!handle->HasResource(resource_id)) << "Duplicate resource "
377 << resource_id << " with scale " 331 << resource_id << " with scale "
378 << resource_scale; 332 << resource_scale;
379 } 333 }
380 } 334 }
381 } 335 }
382 #endif // DCHECK_IS_ON() 336 #endif // DCHECK_IS_ON()
383 337
384 // static 338 // static
385 bool DataPack::WritePack(const base::FilePath& path, 339 bool DataPack::WritePack(const base::FilePath& path,
386 const std::map<uint16_t, base::StringPiece>& resources, 340 const std::map<uint16_t, base::StringPiece>& resources,
387 TextEncodingType textEncodingType) { 341 TextEncodingType textEncodingType) {
342 FILE* file = base::OpenFile(path, "wb");
343 if (!file)
344 return false;
345
346 if (fwrite(&kFileFormatVersion, sizeof(kFileFormatVersion), 1, file) != 1) {
347 LOG(ERROR) << "Failed to write file version";
348 base::CloseFile(file);
349 return false;
350 }
351
352 // Note: the python version of this function explicitly sorted keys, but
353 // std::map is a sorted associative container, we shouldn't have to do that.
354 uint32_t entry_count = resources.size();
355 if (fwrite(&entry_count, sizeof(entry_count), 1, file) != 1) {
356 LOG(ERROR) << "Failed to write entry count";
357 base::CloseFile(file);
358 return false;
359 }
360
388 if (textEncodingType != UTF8 && textEncodingType != UTF16 && 361 if (textEncodingType != UTF8 && textEncodingType != UTF16 &&
389 textEncodingType != BINARY) { 362 textEncodingType != BINARY) {
390 LOG(ERROR) << "Invalid text encoding type, got " << textEncodingType 363 LOG(ERROR) << "Invalid text encoding type, got " << textEncodingType
391 << ", expected between " << BINARY << " and " << UTF16; 364 << ", expected between " << BINARY << " and " << UTF16;
365 base::CloseFile(file);
392 return false; 366 return false;
393 } 367 }
394 368
395 FILE* file = base::OpenFile(path, "wb"); 369 uint8_t write_buffer = static_cast<uint8_t>(textEncodingType);
396 if (!file) 370 if (fwrite(&write_buffer, sizeof(uint8_t), 1, file) != 1) {
397 return false; 371 LOG(ERROR) << "Failed to write file text resources encoding";
398
399 uint32_t encoding = static_cast<uint32_t>(textEncodingType);
400 // Note: the python version of this function explicitly sorted keys, but
401 // std::map is a sorted associative container, we shouldn't have to do that.
402 uint16_t entry_count = resources.size();
403 // Don't bother computing aliases (revisit if it becomes worth it).
404 uint16_t alias_count = 0;
405
406 if (fwrite(&kFileFormatV5, sizeof(kFileFormatV5), 1, file) != 1 ||
407 fwrite(&encoding, sizeof(uint32_t), 1, file) != 1 ||
408 fwrite(&entry_count, sizeof(entry_count), 1, file) != 1 ||
409 fwrite(&alias_count, sizeof(alias_count), 1, file) != 1) {
410 LOG(ERROR) << "Failed to write header";
411 base::CloseFile(file); 372 base::CloseFile(file);
412 return false; 373 return false;
413 } 374 }
414 375
415 // Each entry is a uint16_t + a uint32_t. We have an extra entry after the 376 // Each entry is a uint16_t + a uint32_t. We have an extra entry after the
416 // last item so we can compute the size of the list item. 377 // last item so we can compute the size of the list item.
417 uint32_t index_length = (entry_count + 1) * sizeof(Entry); 378 uint32_t index_length = (entry_count + 1) * sizeof(DataPackEntry);
418 uint32_t data_offset = kHeaderLengthV5 + index_length; 379 uint32_t data_offset = kHeaderLength + index_length;
419 for (std::map<uint16_t, base::StringPiece>::const_iterator it = 380 for (std::map<uint16_t, base::StringPiece>::const_iterator it =
420 resources.begin(); 381 resources.begin();
421 it != resources.end(); ++it) { 382 it != resources.end(); ++it) {
422 uint16_t resource_id = it->first; 383 uint16_t resource_id = it->first;
423 if (fwrite(&resource_id, sizeof(resource_id), 1, file) != 1 || 384 if (fwrite(&resource_id, sizeof(resource_id), 1, file) != 1) {
424 fwrite(&data_offset, sizeof(data_offset), 1, file) != 1) { 385 LOG(ERROR) << "Failed to write id for " << resource_id;
425 LOG(ERROR) << "Failed to write entry for " << resource_id;
426 base::CloseFile(file); 386 base::CloseFile(file);
427 return false; 387 return false;
428 } 388 }
389
390 if (fwrite(&data_offset, sizeof(data_offset), 1, file) != 1) {
391 LOG(ERROR) << "Failed to write offset for " << resource_id;
392 base::CloseFile(file);
393 return false;
394 }
429 395
430 data_offset += it->second.length(); 396 data_offset += it->second.length();
431 } 397 }
432 398
433 // We place an extra entry after the last item that allows us to read the 399 // We place an extra entry after the last item that allows us to read the
434 // size of the last item. 400 // size of the last item.
435 uint16_t resource_id = 0; 401 uint16_t resource_id = 0;
436 if (fwrite(&resource_id, sizeof(resource_id), 1, file) != 1) { 402 if (fwrite(&resource_id, sizeof(resource_id), 1, file) != 1) {
437 LOG(ERROR) << "Failed to write extra resource id."; 403 LOG(ERROR) << "Failed to write extra resource id.";
438 base::CloseFile(file); 404 base::CloseFile(file);
(...skipping 15 matching lines...) Expand all
454 return false; 420 return false;
455 } 421 }
456 } 422 }
457 423
458 base::CloseFile(file); 424 base::CloseFile(file);
459 425
460 return true; 426 return true;
461 } 427 }
462 428
463 } // namespace ui 429 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/resource/data_pack.h ('k') | ui/base/resource/data_pack_literal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698