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

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 rvalue usage in move operation. 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(std::string column_name)
23 : column_name_(column_name),
24 data_(NULL),
25 length_(0),
26 rows_(0),
27 strings_(),
28 fieldtype_(kPmpFieldTypeInvalid) { }
29
30 PmpColumnReader::~PmpColumnReader() { }
31
32 bool PmpColumnReader::ReadFromFile(const base::FilePath& filepath,
33 uint32* rows_read) {
34 base::MemoryMappedFile file;
35
36 if(!file.Initialize(filepath) ||
37 file.length() < kPmpHeaderSize ||
38 file.length() > kPmpMaxFilesize ||
39 file.data() == NULL) {
40 return false;
41 }
42
43 length_ = file.length();
44 data_.reset(new uint8[length_]);
45 std::copy(file.data(), file.data() + length_, data_.get());
46
47 return ParseData(rows_read);
48 }
49
50 bool PmpColumnReader::ReadString(const uint32 row, std::string* result) const {
51 DCHECK(data_.get() != NULL);
52 DCHECK(length_ > kPmpHeaderSize);
vandebo (ex-Chrome) 2013/03/28 00:56:04 DCHECK_GT
tommycli 2013/03/29 00:16:01 Done.
53
54 if(fieldtype_ == kPmpFieldTypeString && row < rows_) {
55 *result = strings_[row];
56 return true;
57 } else {
vandebo (ex-Chrome) 2013/03/28 00:56:04 Remove else and just return false at the end.
tommycli 2013/03/29 00:16:01 Done.
58 return false;
59 }
60 }
61
62 bool PmpColumnReader::ReadUInt32(const uint32 row, uint32* result) const {
63 return (fieldtype_ == kPmpFieldTypeUInt32 &&
64 ReadPrimitive<uint32>(row, result));
vandebo (ex-Chrome) 2013/03/28 00:56:04 Once you get everything else taken care, can you t
tommycli 2013/03/29 00:16:01 Since we are only using 4 field types, the best al
vandebo (ex-Chrome) 2013/03/29 21:35:07 I think the amount of code duplication is small an
tommycli 2013/04/02 21:12:36 Done.
65 }
66
67 bool PmpColumnReader::ReadDouble64(const uint32 row, double* result) const {
68 return (fieldtype_ == kPmpFieldTypeDouble64 &&
69 ReadPrimitive<double>(row, result));
70 }
71
72 bool PmpColumnReader::ReadUInt8(const uint32 row, uint8* result) const {
73 return (fieldtype_ == kPmpFieldTypeUInt8 &&
74 ReadPrimitive<uint8>(row, result));
75 }
76
77 bool PmpColumnReader::ReadUInt64(const uint32 row, uint64* result) const {
78 return (fieldtype_ == kPmpFieldTypeUInt64 &&
79 ReadPrimitive<uint64>(row, result));
80 }
81
82 template<class T>
83 bool PmpColumnReader::ReadPrimitive(uint32 row, T* result) const {
84 DCHECK(data_.get() != NULL);
85 DCHECK(length_ > kPmpHeaderSize + row*sizeof(T));
86
87 if(row < rows_) {
88 *result = *(reinterpret_cast<T*>(
vandebo (ex-Chrome) 2013/03/28 00:56:04 Is this simpler? *result = reinterpret_cast<T*>(da
tommycli 2013/03/29 00:16:01 Yeah, that's way better thanks.
89 data_.get() + kPmpHeaderSize + row*sizeof(T)));
90 return true;
91 } else {
vandebo (ex-Chrome) 2013/03/28 00:56:04 remove else. and return false at the end.
tommycli 2013/03/29 00:16:01 Done.
92 return false;
93 }
94 }
95
96 bool PmpColumnReader::ParseData(uint32* rows_read) {
97 DCHECK(data_.get() != NULL);
98 DCHECK(length_ >= kPmpHeaderSize);
99
100 // Check all magic bytes.
101 if (memcmp(&kPmpMagic1, &data_[kPmpMagic1Offset], sizeof(kPmpMagic1)) != 0 ||
vandebo (ex-Chrome) 2013/03/28 00:56:04 data_.get() + kPmpMagic1Offset ?
tommycli 2013/03/29 00:16:01 Makes the command no longer fit on one line. Chang
vandebo (ex-Chrome) 2013/03/29 21:35:07 Your call.
tommycli 2013/04/02 21:12:36 Done.
102 memcmp(&kPmpMagic2, &data_[kPmpMagic2Offset], sizeof(kPmpMagic2)) != 0 ||
103 memcmp(&kPmpMagic3, &data_[kPmpMagic3Offset], sizeof(kPmpMagic3)) != 0 ||
104 memcmp(&kPmpMagic4, &data_[kPmpMagic4Offset], sizeof(kPmpMagic4)) != 0) {
105 return false;
106 }
107
108 // Verify row field type matches.
109 if (data_[kPmpFieldType1Offset] != data_[kPmpFieldType2Offset]) {
vandebo (ex-Chrome) 2013/03/28 00:56:04 This only tests the first byte of these two fields
vandebo (ex-Chrome) 2013/03/28 00:56:04 nit: extra {}'s
tommycli 2013/03/29 00:16:01 Whoops, that's just a straight up bug. I've refact
tommycli 2013/03/29 00:16:01 Done.
110 return false;
111 }
112
113 // Read the field type and number of rows expected.
114 fieldtype_ = data_[kPmpFieldType1Offset];
115 rows_ = *(reinterpret_cast<uint32*>(&data_[kPmpRowCountOffset]));
116
117 bool parse_success = false;
118
119 switch (fieldtype_) {
120 case kPmpFieldTypeString:
121 parse_success = IndexStrings();
122 break;
123 case kPmpFieldTypeUInt32:
124 parse_success = ValidatePrimitiveArrayLength<uint32>();
125 break;
126 case kPmpFieldTypeDouble64:
127 parse_success = ValidatePrimitiveArrayLength<double>();
128 break;
129 case kPmpFieldTypeUInt8:
130 parse_success = ValidatePrimitiveArrayLength<uint8>();
131 break;
132 case kPmpFieldTypeUInt64:
133 parse_success = ValidatePrimitiveArrayLength<uint64>();
134 break;
135 default:
136 parse_success = false;
vandebo (ex-Chrome) 2013/03/28 00:56:04 return false;
tommycli 2013/03/29 00:16:01 Done.
137 break;
138 }
139
140 if(parse_success) {
141 // Set the number of rows read. Though it's not valid unless we return true.
142 if(rows_read != NULL) {
vandebo (ex-Chrome) 2013/03/28 00:56:04 nit: extra {}'s
tommycli 2013/03/29 00:16:01 Done.
143 *rows_read = rows_;
144 }
145 return true;
146 }
147
148 return false;
149 }
150
151 bool PmpColumnReader::IndexStrings() {
152 DCHECK(data_.get() != NULL);
153 DCHECK(length_ >= kPmpHeaderSize);
vandebo (ex-Chrome) 2013/03/28 00:56:04 DCHECK_GE
tommycli 2013/03/29 00:16:01 Done.
154
155 strings_.clear();
156 strings_.reserve(rows_);
157
158 size_t bytes_parsed = kPmpHeaderSize;
159 const uint8* itr = data_.get() + kPmpHeaderSize;
160
161 while (strings_.size() < rows_) {
162 const uint8* ptr_to_str_end = static_cast<const uint8*>(
vandebo (ex-Chrome) 2013/03/28 00:56:04 variables should generally not be abbreviations an
tommycli 2013/03/29 00:16:01 Done.
163 memchr(itr, '\0', length_ - bytes_parsed));
164
165 // Fail if cannot find null termination. String runs on past file end.
166 if(ptr_to_str_end == NULL) return false;
vandebo (ex-Chrome) 2013/03/28 00:56:04 two lines.
tommycli 2013/03/29 00:16:01 Done.
167
168 // Length of string. (+1 to include the termination character).
169 ptrdiff_t len_bytes = ptr_to_str_end - itr + 1;
vandebo (ex-Chrome) 2013/03/28 00:56:04 len_bytes = length ?
tommycli 2013/03/29 00:16:01 Done.
170
171 strings_.push_back(reinterpret_cast<const char*>(itr));
172 itr += len_bytes;
173 bytes_parsed += len_bytes;
174 }
175
176 // This means the file has more bytes at the end we haven't parsed.
177 if(bytes_parsed != length_)
178 return false;
179
180 return true;
181 }
182
183 template<class T>
184 bool PmpColumnReader::ValidatePrimitiveArrayLength() {
185 unsigned long calculated_n_rows = (length_ - kPmpHeaderSize) / sizeof(T);
vandebo (ex-Chrome) 2013/03/28 00:56:04 Also check that there's no remainder ?
tommycli 2013/03/29 00:16:01 Whoops. Totally forgot about the whole integer div
186
187 return (calculated_n_rows == rows_);
188 }
189
190 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698