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

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: Remove unused constant. Created 7 years, 8 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 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 namespace {
17
18 const size_t kPmpMaxFilesize = 50*1024*1024; // Maximum of 50 MB.
19
20 } // namespace
21
22 PmpColumnReader::PmpColumnReader()
23 : data_(NULL),
24 length_(0),
25 rows_(0),
26 strings_(),
27 field_type_(kPmpFieldTypeInvalid) { }
28
29 PmpColumnReader::~PmpColumnReader() { }
30
31 bool PmpColumnReader::InitFromFile(const base::FilePath& filepath,
32 uint32* rows_read) {
33 base::MemoryMappedFile file;
vandebo (ex-Chrome) 2013/03/29 21:35:07 So using a memory mapped file means you need enoug
vandebo (ex-Chrome) 2013/03/29 21:35:07 Add a DCHECK that we're on the FILE thread?
tommycli 2013/04/01 22:19:18 Done.
tommycli 2013/04/01 22:19:18 Done.
34
35 if(!file.Initialize(filepath) ||
vandebo (ex-Chrome) 2013/03/29 21:35:07 nit: s/if(/if (/g
tommycli 2013/04/01 22:19:18 Done.
36 file.length() < kPmpHeaderSize ||
37 file.length() > kPmpMaxFilesize ||
38 file.data() == NULL) {
39 return false;
40 }
41
42 length_ = file.length();
43 data_.reset(new uint8[length_]);
44 std::copy(file.data(), file.data() + length_, data_.get());
45
46 return ParseData(rows_read);
47 }
48
49 bool PmpColumnReader::ReadString(const uint32 row, std::string* result) const {
50 DCHECK(data_.get() != NULL);
51 DCHECK_GT(length_, kPmpHeaderSize + row);
52
53 if(field_type_ == kPmpFieldTypeString && row < rows_) {
vandebo (ex-Chrome) 2013/03/29 21:35:07 We like early exits of functions, especially when
tommycli 2013/04/01 22:19:18 Nice. That's definitely an improvement.
54 *result = strings_[row];
55 return true;
56 }
57
58 return false;
59 }
60
61 bool PmpColumnReader::ReadUInt32(const uint32 row, uint32* result) const {
62 DCHECK(data_.get() != NULL);
63 DCHECK_GT(length_, kPmpHeaderSize + row*sizeof(uint32));
vandebo (ex-Chrome) 2013/03/29 21:35:07 nit: space around math operators: row * sizeof()
tommycli 2013/04/01 22:19:18 Done.
64
65 if(field_type_ == kPmpFieldTypeUInt32 && row < rows_) {
66 *result = reinterpret_cast<uint32*>(data_.get() + kPmpHeaderSize)[row];
67 return true;
68 }
69
70 return false;
71 }
72
73 bool PmpColumnReader::ReadDouble64(const uint32 row, double* result) const {
74 DCHECK(data_.get() != NULL);
75 DCHECK_GT(length_, kPmpHeaderSize + row*sizeof(double));
76
77 if(field_type_ == kPmpFieldTypeDouble64 && row < rows_) {
78 *result = reinterpret_cast<double*>(data_.get() + kPmpHeaderSize)[row];
79 return true;
80 }
81
82 return false;
83 }
84
85 bool PmpColumnReader::ReadUInt8(const uint32 row, uint8* result) const {
86 DCHECK(data_.get() != NULL);
87 DCHECK_GT(length_, kPmpHeaderSize + row*sizeof(uint8));
88
89 if(field_type_ == kPmpFieldTypeUInt8 && row < rows_) {
90 *result = reinterpret_cast<uint8*>(data_.get() + kPmpHeaderSize)[row];
91 return true;
92 }
93
94 return false;
95 }
96
97 bool PmpColumnReader::ReadUInt64(const uint32 row, uint64* result) const {
98 DCHECK(data_.get() != NULL);
99 DCHECK_GT(length_, kPmpHeaderSize + row*sizeof(uint64));
100
101 if(field_type_ == kPmpFieldTypeUInt64 && row < rows_) {
102 *result = reinterpret_cast<uint64*>(data_.get() + kPmpHeaderSize)[row];
103 return true;
104 }
105
106 return false;
107 }
108
109 bool PmpColumnReader::ParseData(uint32* rows_read) {
110 DCHECK(data_.get() != NULL);
111 DCHECK_GE(length_, kPmpHeaderSize);
112
113 // Check all magic bytes.
114 if (memcmp(&kPmpMagic1, &data_[kPmpMagic1Offset], sizeof(kPmpMagic1)) != 0 ||
115 memcmp(&kPmpMagic2, &data_[kPmpMagic2Offset], sizeof(kPmpMagic2)) != 0 ||
116 memcmp(&kPmpMagic3, &data_[kPmpMagic3Offset], sizeof(kPmpMagic3)) != 0 ||
117 memcmp(&kPmpMagic4, &data_[kPmpMagic4Offset], sizeof(kPmpMagic4)) != 0) {
118 return false;
119 }
120
121 // Read the field type
vandebo (ex-Chrome) 2013/03/29 21:35:07 nit: remove redundant comment.
tommycli 2013/04/01 22:19:18 Done.
122 field_type_ = *(reinterpret_cast<uint16*>(&data_[kPmpFieldType1Offset]));
123
124 // Verify if field type matches second declaration
125 if (field_type_ != *(reinterpret_cast<uint16*>(&data_[kPmpFieldType2Offset])))
126 return false;
127
128 // Read the number of rows expected.
vandebo (ex-Chrome) 2013/03/29 21:35:07 nit: redundant comment.
tommycli 2013/04/01 22:19:18 Done.
129 rows_ = *(reinterpret_cast<uint32*>(&data_[kPmpRowCountOffset]));
130
131 bool parse_success = false;
132
vandebo (ex-Chrome) 2013/03/29 21:35:07 nit: extra line.
tommycli 2013/04/01 22:19:18 Done.
133 switch (field_type_) {
134 case kPmpFieldTypeString:
135 parse_success = IndexStrings();
136 break;
137 case kPmpFieldTypeUInt32:
138 parse_success = ValidatePrimitiveArrayLength<uint32>();
139 break;
140 case kPmpFieldTypeDouble64:
141 parse_success = ValidatePrimitiveArrayLength<double>();
142 break;
143 case kPmpFieldTypeUInt8:
144 parse_success = ValidatePrimitiveArrayLength<uint8>();
145 break;
146 case kPmpFieldTypeUInt64:
147 parse_success = ValidatePrimitiveArrayLength<uint64>();
148 break;
149 default:
150 return false;
151 break;
152 }
153
154 if(parse_success) {
vandebo (ex-Chrome) 2013/03/29 21:35:07 if (parse_success && rows_read) *rows_read = row
tommycli 2013/04/01 22:19:18 That's ninja.
155 // Set the number of rows read. Though it's not valid unless we return true.
156 if(rows_read != NULL)
157 *rows_read = rows_;
158 return true;
159 }
160
161 return false;
162 }
163
164 bool PmpColumnReader::IndexStrings() {
165 DCHECK(data_.get() != NULL);
166 DCHECK_GE(length_, kPmpHeaderSize);
167
168 strings_.clear();
vandebo (ex-Chrome) 2013/03/29 21:35:07 not needed
tommycli 2013/04/01 22:19:18 Done.
169 strings_.reserve(rows_);
170
171 size_t bytes_parsed = kPmpHeaderSize;
172 const uint8* itr = data_.get() + kPmpHeaderSize;
vandebo (ex-Chrome) 2013/03/29 21:35:07 nit: We usually use it for iterators... though thi
tommycli 2013/04/01 22:19:18 Done.
173
174 while (strings_.size() < rows_) {
175 const uint8* string_end = static_cast<const uint8*>(
176 memchr(itr, '\0', length_ - bytes_parsed));
177
178 // Fail if cannot find null termination. String runs on past file end.
179 if(string_end == NULL)
180 return false;
181
182 // Length of string. (+1 to include the termination character).
183 ptrdiff_t length_in_bytes = string_end - itr + 1;
vandebo (ex-Chrome) 2013/03/29 21:35:07 Any word back from Picasa folks on the string enco
tommycli 2013/04/01 22:19:18 I fwded you email from them.
vandebo (ex-Chrome) 2013/04/02 18:10:55 You got an non-answer back. Can you peek into the
tommycli 2013/04/02 21:12:36 Done.
184
185 strings_.push_back(reinterpret_cast<const char*>(itr));
186 itr += length_in_bytes;
187 bytes_parsed += length_in_bytes;
188 }
189
190 // This means the file has more bytes at the end we haven't parsed.
vandebo (ex-Chrome) 2013/03/29 21:35:07 redundant comment.
tommycli 2013/04/01 22:19:18 Done.
191 if(bytes_parsed != length_)
192 return false;
vandebo (ex-Chrome) 2013/03/29 21:35:07 return bytes_parsed == length_;
tommycli 2013/04/01 22:19:18 Done.
193
194 return true;
195 }
196
197 template<class T>
198 bool PmpColumnReader::ValidatePrimitiveArrayLength() {
vandebo (ex-Chrome) 2013/03/29 21:35:07 I think you can inline this template without much
tommycli 2013/04/01 22:19:18 Done.
199 size_t body_length = length_ - kPmpHeaderSize;
200 size_t expected_body_length = rows_ * sizeof(T);
201
202 return body_length == expected_body_length;
203 }
204
205 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698