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

Side by Side Diff: app/data_pack.cc

Issue 6263008: Move ResourceBundle, DataPack to ui/base (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « app/data_pack.h ('k') | app/data_pack_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "app/data_pack.h"
6
7 #include <errno.h>
8
9 #include "base/file_util.h"
10 #include "base/logging.h"
11 #include "base/metrics/histogram.h"
12 #include "base/ref_counted_memory.h"
13 #include "base/string_piece.h"
14
15 // For details of the file layout, see
16 // http://dev.chromium.org/developers/design-documents/linuxresourcesandlocalize dstrings
17
18 namespace {
19
20 // A word is four bytes.
21 static const size_t kWord = 4;
22
23 static const uint32 kFileFormatVersion = 1;
24 // Length of file header: version and entry count.
25 static const size_t kHeaderLength = 2 * sizeof(uint32);
26
27 struct DataPackEntry {
28 uint32 resource_id;
29 uint32 file_offset;
30 uint32 length;
31
32 static int CompareById(const void* void_key, const void* void_entry) {
33 uint32 key = *reinterpret_cast<const uint32*>(void_key);
34 const DataPackEntry* entry =
35 reinterpret_cast<const DataPackEntry*>(void_entry);
36 if (key < entry->resource_id) {
37 return -1;
38 } else if (key > entry->resource_id) {
39 return 1;
40 } else {
41 return 0;
42 }
43 }
44 };
45
46 COMPILE_ASSERT(sizeof(DataPackEntry) == 12, size_of_header_must_be_twelve);
47
48 // We're crashing when trying to load a pak file on Windows. Add some error
49 // codes for logging.
50 // http://crbug.com/58056
51 enum LoadErrors {
52 INIT_FAILED = 1,
53 BAD_VERSION,
54 INDEX_TRUNCATED,
55 ENTRY_NOT_FOUND,
56
57 LOAD_ERRORS_COUNT,
58 };
59
60 } // anonymous namespace
61
62 namespace app {
63
64 // In .cc for MemoryMappedFile dtor.
65 DataPack::DataPack() : resource_count_(0) {
66 }
67 DataPack::~DataPack() {
68 }
69
70 bool DataPack::Load(const FilePath& path) {
71 mmap_.reset(new file_util::MemoryMappedFile);
72 if (!mmap_->Initialize(path)) {
73 DLOG(ERROR) << "Failed to mmap datapack";
74 UMA_HISTOGRAM_ENUMERATION("DataPack.Load", INIT_FAILED,
75 LOAD_ERRORS_COUNT);
76 return false;
77 }
78
79 // Parse the header of the file.
80 // First uint32: version; second: resource count.
81 const uint32* ptr = reinterpret_cast<const uint32*>(mmap_->data());
82 uint32 version = ptr[0];
83 if (version != kFileFormatVersion) {
84 LOG(ERROR) << "Bad data pack version: got " << version << ", expected "
85 << kFileFormatVersion;
86 UMA_HISTOGRAM_ENUMERATION("DataPack.Load", BAD_VERSION,
87 LOAD_ERRORS_COUNT);
88 mmap_.reset();
89 return false;
90 }
91 resource_count_ = ptr[1];
92
93 // Sanity check the file.
94 // 1) Check we have enough entries.
95 if (kHeaderLength + resource_count_ * sizeof(DataPackEntry) >
96 mmap_->length()) {
97 LOG(ERROR) << "Data pack file corruption: too short for number of "
98 "entries specified.";
99 UMA_HISTOGRAM_ENUMERATION("DataPack.Load", INDEX_TRUNCATED,
100 LOAD_ERRORS_COUNT);
101 mmap_.reset();
102 return false;
103 }
104 // 2) Verify the entries are within the appropriate bounds.
105 for (size_t i = 0; i < resource_count_; ++i) {
106 const DataPackEntry* entry = reinterpret_cast<const DataPackEntry*>(
107 mmap_->data() + kHeaderLength + (i * sizeof(DataPackEntry)));
108 if (entry->file_offset + entry->length > mmap_->length()) {
109 LOG(ERROR) << "Entry #" << i << " in data pack points off end of file. "
110 << "Was the file corrupted?";
111 UMA_HISTOGRAM_ENUMERATION("DataPack.Load", ENTRY_NOT_FOUND,
112 LOAD_ERRORS_COUNT);
113 mmap_.reset();
114 return false;
115 }
116 }
117
118 return true;
119 }
120
121 bool DataPack::GetStringPiece(uint32 resource_id,
122 base::StringPiece* data) const {
123 // It won't be hard to make this endian-agnostic, but it's not worth
124 // bothering to do right now.
125 #if defined(__BYTE_ORDER)
126 // Linux check
127 COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN,
128 datapack_assumes_little_endian);
129 #elif defined(__BIG_ENDIAN__)
130 // Mac check
131 #error DataPack assumes little endian
132 #endif
133
134 DataPackEntry* target = reinterpret_cast<DataPackEntry*>(
135 bsearch(&resource_id, mmap_->data() + kHeaderLength, resource_count_,
136 sizeof(DataPackEntry), DataPackEntry::CompareById));
137 if (!target) {
138 return false;
139 }
140
141 data->set(mmap_->data() + target->file_offset, target->length);
142 return true;
143 }
144
145 RefCountedStaticMemory* DataPack::GetStaticMemory(uint32 resource_id) const {
146 base::StringPiece piece;
147 if (!GetStringPiece(resource_id, &piece))
148 return NULL;
149
150 return new RefCountedStaticMemory(
151 reinterpret_cast<const unsigned char*>(piece.data()), piece.length());
152 }
153
154 // static
155 bool DataPack::WritePack(const FilePath& path,
156 const std::map<uint32, base::StringPiece>& resources) {
157 FILE* file = file_util::OpenFile(path, "wb");
158 if (!file)
159 return false;
160
161 if (fwrite(&kFileFormatVersion, 1, kWord, file) != kWord) {
162 LOG(ERROR) << "Failed to write file version";
163 file_util::CloseFile(file);
164 return false;
165 }
166
167 // Note: the python version of this function explicitly sorted keys, but
168 // std::map is a sorted associative container, we shouldn't have to do that.
169 uint32 entry_count = resources.size();
170 if (fwrite(&entry_count, 1, kWord, file) != kWord) {
171 LOG(ERROR) << "Failed to write entry count";
172 file_util::CloseFile(file);
173 return false;
174 }
175
176 // Each entry is 3 uint32s.
177 uint32 index_length = entry_count * 3 * kWord;
178 uint32 data_offset = kHeaderLength + index_length;
179 for (std::map<uint32, base::StringPiece>::const_iterator it =
180 resources.begin();
181 it != resources.end(); ++it) {
182 if (fwrite(&it->first, 1, kWord, file) != kWord) {
183 LOG(ERROR) << "Failed to write id for " << it->first;
184 file_util::CloseFile(file);
185 return false;
186 }
187
188 if (fwrite(&data_offset, 1, kWord, file) != kWord) {
189 LOG(ERROR) << "Failed to write offset for " << it->first;
190 file_util::CloseFile(file);
191 return false;
192 }
193
194 uint32 len = it->second.length();
195 if (fwrite(&len, 1, kWord, file) != kWord) {
196 LOG(ERROR) << "Failed to write length for " << it->first;
197 file_util::CloseFile(file);
198 return false;
199 }
200
201 data_offset += len;
202 }
203
204 for (std::map<uint32, base::StringPiece>::const_iterator it =
205 resources.begin();
206 it != resources.end(); ++it) {
207 if (fwrite(it->second.data(), it->second.length(), 1, file) != 1) {
208 LOG(ERROR) << "Failed to write data for " << it->first;
209 file_util::CloseFile(file);
210 return false;
211 }
212 }
213
214 file_util::CloseFile(file);
215
216 return true;
217 }
218
219 } // namespace app
OLDNEW
« no previous file with comments | « app/data_pack.h ('k') | app/data_pack_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698