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

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: Missed a change. 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/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h"
12 #include "base/threading/thread_restrictions.h"
13 #include "webkit/fileapi/media/picasa/pmp_constants.h"
14
15 namespace fileapi {
16
17 namespace {
18
19 const size_t kPmpMaxFilesize = 50*1024*1024; // Maximum of 50 MB.
20
21 } // namespace
22
23 PmpColumnReader::PmpColumnReader()
24 : data_(NULL),
25 length_(0),
26 field_type_(kPmpFieldTypeInvalid),
27 rows_(0),
28 strings_() { }
29
30 PmpColumnReader::~PmpColumnReader() { }
31
32 bool PmpColumnReader::Init(const base::FilePath& filepath, uint32* rows_read) {
33 DCHECK(!data_.get());
34 base::ThreadRestrictions::AssertIOAllowed();
35
36 long int length = 0; // Signed temporary.
37 if (!file_util::GetFileSize(filepath, &length))
38 return false;
39
40 length_ = length;
41
42 if (length_ < kPmpHeaderSize || length_ > kPmpMaxFilesize)
43 return false;
44
45 data_.reset(new uint8[length_]);
46
47 char* data_begin = reinterpret_cast<char*>(data_.get());
48
49 return (file_util::ReadFile(filepath, data_begin, length_) &&
vandebo (ex-Chrome) 2013/04/02 18:10:55 nit: extra ()s
tommycli 2013/04/02 19:05:55 Done.
50 ParseData(rows_read));
51 }
52
53 bool PmpColumnReader::ReadString(const uint32 row, std::string* result) const {
54 DCHECK(data_.get() != NULL);
55 DCHECK_GT(length_, kPmpHeaderSize + row);
56
57 if (field_type_ != kPmpFieldTypeString || row >= rows_)
58 return false;
59
60 *result = strings_[row];
61 return true;
62 }
63
64 bool PmpColumnReader::ReadUInt32(const uint32 row, uint32* result) const {
65 DCHECK(data_.get() != NULL);
66 DCHECK_GT(length_, kPmpHeaderSize + row * sizeof(uint32));
67
68 if (field_type_ != kPmpFieldTypeUInt32 || row >= rows_)
69 return false;
70
71 *result = reinterpret_cast<uint32*>(data_.get() + kPmpHeaderSize)[row];
72 return true;
73 }
74
75 bool PmpColumnReader::ReadDouble64(const uint32 row, double* result) const {
76 DCHECK(data_.get() != NULL);
77 DCHECK_GT(length_, kPmpHeaderSize + row * sizeof(double));
78
79 if (field_type_ != kPmpFieldTypeDouble64 || row >= rows_)
80 return false;
81
82 *result = reinterpret_cast<double*>(data_.get() + kPmpHeaderSize)[row];
83 return true;
84 }
85
86 bool PmpColumnReader::ReadUInt8(const uint32 row, uint8* result) const {
87 DCHECK(data_.get() != NULL);
88 DCHECK_GT(length_, kPmpHeaderSize + row * sizeof(uint8));
89
90 if (field_type_ != kPmpFieldTypeUInt8 || row >= rows_)
91 return false;
92
93 *result = reinterpret_cast<uint8*>(data_.get() + kPmpHeaderSize)[row];
94 return true;
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 return false;
103
104 *result = reinterpret_cast<uint64*>(data_.get() + kPmpHeaderSize)[row];
105 return true;
106 }
107
108 bool PmpColumnReader::ParseData(uint32* rows_read) {
109 DCHECK(data_.get() != NULL);
110 DCHECK_GE(length_, kPmpHeaderSize);
111
112 // Check all magic bytes.
113 if (memcmp(&kPmpMagic1, &data_[kPmpMagic1Offset], sizeof(kPmpMagic1)) != 0 ||
114 memcmp(&kPmpMagic2, &data_[kPmpMagic2Offset], sizeof(kPmpMagic2)) != 0 ||
115 memcmp(&kPmpMagic3, &data_[kPmpMagic3Offset], sizeof(kPmpMagic3)) != 0 ||
116 memcmp(&kPmpMagic4, &data_[kPmpMagic4Offset], sizeof(kPmpMagic4)) != 0) {
117 return false;
118 }
119
120 field_type_ = *(reinterpret_cast<uint16*>(&data_[kPmpFieldType1Offset]));
121
122 // Verify if field type matches second declaration
123 if (field_type_ != *(reinterpret_cast<uint16*>(&data_[kPmpFieldType2Offset])))
124 return false;
125
126 rows_ = *(reinterpret_cast<uint32*>(&data_[kPmpRowCountOffset]));
127
128 bool parse_success = false;
vandebo (ex-Chrome) 2013/04/02 18:10:55 If you have IndexStrings return bytes_parsed, you
tommycli 2013/04/02 19:05:55 Done.
129 size_t body_length = length_ - kPmpHeaderSize;
130 size_t expected_body_length = 0;
131 switch (field_type_) {
132 case kPmpFieldTypeString:
133 parse_success = IndexStrings();
134 break;
135 case kPmpFieldTypeUInt32:
136 expected_body_length = rows_ * sizeof(uint32);
137 parse_success = body_length == expected_body_length;
138 break;
139 case kPmpFieldTypeDouble64:
140 expected_body_length = rows_ * sizeof(double);
141 parse_success = body_length == expected_body_length;
142 break;
143 case kPmpFieldTypeUInt8:
144 expected_body_length = rows_ * sizeof(uint8);
145 parse_success = body_length == expected_body_length;
146 break;
147 case kPmpFieldTypeUInt64:
148 expected_body_length = rows_ * sizeof(uint64);
149 parse_success = body_length == expected_body_length;
150 break;
151 default:
152 return false;
153 break;
154 }
155
156 if (parse_success && rows_read)
157 *rows_read = rows_;
158 return parse_success;
159 }
160
161 bool PmpColumnReader::IndexStrings() {
162 DCHECK(data_.get() != NULL);
163 DCHECK_GE(length_, kPmpHeaderSize);
164
165 strings_.reserve(rows_);
166
167 size_t bytes_parsed = kPmpHeaderSize;
168 const uint8* body_cursor = data_.get() + kPmpHeaderSize;
vandebo (ex-Chrome) 2013/04/02 18:10:55 nit: body? data_cursor or just cursor.
tommycli 2013/04/02 19:05:55 Done.
169
170 while (strings_.size() < rows_) {
171 const uint8* string_end = static_cast<const uint8*>(
172 memchr(body_cursor, '\0', length_ - bytes_parsed));
173
174 // Fail if cannot find null termination. String runs on past file end.
175 if (string_end == NULL)
176 return false;
177
178 // Length of string. (+1 to include the termination character).
179 ptrdiff_t length_in_bytes = string_end - body_cursor + 1;
180
181 strings_.push_back(reinterpret_cast<const char*>(body_cursor));
182 body_cursor += length_in_bytes;
183 bytes_parsed += length_in_bytes;
184 }
185
186 return bytes_parsed == length_;
187 }
188
189 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698