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

Side by Side Diff: webkit/fileapi/media/picasa/pmp_column_reader.cc

Issue 12704024: Simple PMP reader to parse Picasa's metadata (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix memory issue. Created 7 years, 9 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
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 "webkit/fileapi/media/picasa/pmp_column_reader.h"
6
7 #include <cstring>
8
9 #include "base/files/file_path.h"
10 #include "base/files/memory_mapped_file.h"
11 #include "base/logging.h"
12 #include "webkit/fileapi/media/picasa/pmp_constants.h"
13
14 namespace fileapi {
15
16 PmpColumnReader::PmpColumnReader(std::string column_name)
17 : column_name_(column_name),
18 data_(NULL),
19 length_(0),
20 rows_(0),
21 strings_(),
22 fieldsize_(0) {
23
vandebo (ex-Chrome) 2013/03/26 01:12:14 nit: extra line
tommycli 2013/03/26 22:30:43 Done.
24 }
25
26 PmpColumnReader::~PmpColumnReader() {
27 delete[] data_;
vandebo (ex-Chrome) 2013/03/26 01:12:14 This means you probably want to use a scoped objec
tommycli 2013/03/26 22:30:43 Done.
28 }
29
30 bool PmpColumnReader::ReadFromDisk(uint32* rows_read,
31 const base::FilePath& filepath) {
32 base::MemoryMappedFile file;
33 bool file_initialized = file.Initialize(filepath);
34
35 // If file is not initialized, too small, or too large (50MB), fail out.
36 if (!file_initialized ||
37 file.length() < kPmpHeaderSize ||
38 file.length() > 50*1024*1024) {
vandebo (ex-Chrome) 2013/03/26 01:12:14 Make this a constant as well.
tommycli 2013/03/26 22:30:43 Done.
39 return false;
40 }
41
42 length_ = file.length();
43 if(data_ != NULL) {
44 delete[] data_;
45 }
46 data_ = new uint8[length_];
47 memcpy(data_, file.data(), length_);
48
49 return ParseData(rows_read);
50 }
51
52 bool PmpColumnReader::ReadFromMemory(uint32* rows_read, const uint8* data,
53 const size_t len) {
54 if(len < kPmpHeaderSize || data == NULL) {
55 return false;
56 }
57
58 length_ = len;
59 if(data_ != NULL) {
60 delete[] data_;
61 }
62 data_ = new uint8[length_];
63 memcpy(data_, data, length_);
64
65 return ParseData(rows_read);
66 }
67
68 template<class T>
69 bool PmpColumnReader::Read(uint32 row, T* target) {
70 DCHECK(data_ != NULL && length_ > kPmpHeaderSize);
71
72 if(sizeof(T) != fieldsize_) {
73 return false;
74 }
75
76 if(row < rows_) {
77 memcpy(target, data_ + kPmpHeaderSize + row*fieldsize_, fieldsize_);
vandebo (ex-Chrome) 2013/03/26 01:12:14 You probably want an explicit reinterpret_cast in
tommycli 2013/03/26 22:30:43 Done.
78 return true;
79 } else {
80 return false;
81 }
82 }
83
84 template bool PmpColumnReader::Read<uint8>(uint32 row, uint8* target);
85
86 template bool PmpColumnReader::Read<uint16>(uint32 row, uint16* target);
87
88 template bool PmpColumnReader::Read<uint32>(uint32 row, uint32* target);
89
90 template bool PmpColumnReader::Read<uint64>(uint32 row, uint64* target);
91
92 template bool PmpColumnReader::Read<double>(uint32 row, double* target);
93
94 template<>
95 bool PmpColumnReader::Read(uint32 row, std::string* target) {
96 DCHECK(data_ != NULL && length_ > kPmpHeaderSize);
97
98 if(row < rows_) {
99 *target = strings_[row];
100 return true;
101 } else {
102 return false;
103 }
104 }
105
106 bool PmpColumnReader::ParseData(uint32* rows_read) {
107 DCHECK(data_ != NULL);
108 DCHECK(length_ >= kPmpHeaderSize);
109
110 // Check all magic bytes
111 if (memcmp(kPmpMagicO0S4, data_, 4) != 0||
vandebo (ex-Chrome) 2013/03/26 01:12:14 You may want to make a packed struct of the differ
tommycli 2013/03/26 22:30:43 That's a good idea. I may need some help figuring
112 memcmp(kPmpMagicO6S2, data_ + 6, 2) != 0 ||
113 memcmp(kPmpMagicO8S4, data_ + 8, 4) != 0 ||
114 memcmp(kPmpMagicO14S2, data_ + 14, 2) != 0) {
115 return false;
116 }
117
118 // Verify row field type matches
119 if (data_[kPmpFieldTypeFirstOffset] != data_[kPmpFieldTypeSecondOffset]) {
120 return false;
121 }
122
123 // Read the field type and number of rows expected
124 uint16 field_type = data_[kPmpFieldTypeFirstOffset];
125 memcpy(&rows_, &data_[kPmpRowCountOffset], sizeof(uint32));
126
127 // Set the number of rows read. Though it's not valid unless we return true.
128 if(rows_read != NULL) {
129 *rows_read = rows_;
130 }
131
132 switch (field_type) {
133 case 0x00:
vandebo (ex-Chrome) 2013/03/26 01:12:14 Make these constants.
tommycli 2013/03/26 22:30:43 Done.
134 return IndexStrings();
135 break;
136 case 0x01:
137 return SetAndValidateFieldsize<uint32>();
138 break;
139 case 0x02:
140 return SetAndValidateFieldsize<double>();
141 break;
142 case 0x03:
143 return SetAndValidateFieldsize<uint8>();
144 break;
145 case 0x04:
146 return SetAndValidateFieldsize<uint64>();
147 break;
148 case 0x05:
149 return SetAndValidateFieldsize<uint16>();
150 break;
151 case 0x06:
152 return IndexStrings();
153 break;
154 case 0x07:
155 return SetAndValidateFieldsize<uint32>();
156 break;
157 default:
158 return false;
159 break;
160 }
161 }
162
163 bool PmpColumnReader::IndexStrings() {
164 DCHECK(data_ != NULL);
165 DCHECK(length_ >= kPmpHeaderSize);
166
167 strings_.clear();
168 strings_.reserve(rows_);
169
170 size_t bytes_parsed = kPmpHeaderSize;
171 const uint8* itr = data_ + kPmpHeaderSize;
vandebo (ex-Chrome) 2013/03/26 01:12:14 How is the string encoded? UTF8? unspecified?
tommycli 2013/03/26 22:30:43 Unspecified. I've sent an email to the Picasa ppl
172
173 while (strings_.size() < rows_) {
174 const uint8* ptr_to_str_end = static_cast<const uint8*>(
175 memchr(itr, '\0', length_-bytes_parsed));
vandebo (ex-Chrome) 2013/03/26 01:12:14 spaces around math operators.
tommycli 2013/03/26 22:30:43 Done.
176
177 // fail if cannot find null termination. String runs on past file end.
vandebo (ex-Chrome) 2013/03/26 01:12:14 Capitalize
tommycli 2013/03/26 22:30:43 Done.
178 if(ptr_to_str_end == NULL) {
vandebo (ex-Chrome) 2013/03/26 01:12:14 {}'s around single line conditionals with single l
tommycli 2013/03/26 22:30:43 Done.
179 return false;
180 }
181
182 // Length of string. (+1 to include the termination character)
183 ptrdiff_t len_bytes = ptr_to_str_end - itr + 1;
184
185 strings_.push_back(reinterpret_cast<const char*>(itr));
186 itr += len_bytes;
187 bytes_parsed += len_bytes;
188 }
189
190 // This means the file has more bytes at the end we haven't parsed
191 if(bytes_parsed != length_) {
192 return false;
193 }
194
195 return true;
196 }
197
198 template<class T>
199 bool PmpColumnReader::SetAndValidateFieldsize() {
200 unsigned long calculated_n_rows =
201 (length_ - kPmpHeaderSize)/sizeof(T);
202
203 if(calculated_n_rows == rows_) {
204 fieldsize_ = sizeof(T);
205 return true;
206 } else {
vandebo (ex-Chrome) 2013/03/26 01:12:14 No else in this case.
tommycli 2013/03/26 22:30:43 Done.
207 return false;
208 }
209 }
210
211 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698