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

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: Make PmpTestHelper stateful and possess the temporary directory. 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 picasaimport {
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_(INVALID_TYPE),
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_) &&
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_ != STRING_TYPE || 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_ != UINT32_TYPE || 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_ != DOUBLE64_TYPE || 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_ != UINT8_TYPE || 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_ != UINT64_TYPE || 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 size_t body_length = length_ - kPmpHeaderSize;
129 size_t expected_body_length = 0;
130 switch (field_type_) {
131 case STRING_TYPE:
132 expected_body_length = IndexStrings();
133 break;
134 case UINT32_TYPE:
135 expected_body_length = rows_ * sizeof(uint32);
136 break;
137 case DOUBLE64_TYPE:
138 expected_body_length = rows_ * sizeof(double);
139 break;
140 case UINT8_TYPE:
141 expected_body_length = rows_ * sizeof(uint8);
142 break;
143 case UINT64_TYPE:
144 expected_body_length = rows_ * sizeof(uint64);
145 break;
146 default:
147 return false;
148 break;
149 }
150
151 if (body_length == expected_body_length && rows_read)
152 *rows_read = rows_;
153 return body_length == expected_body_length;
154 }
155
156 long PmpColumnReader::IndexStrings() {
157 DCHECK(data_.get() != NULL);
158 DCHECK_GE(length_, kPmpHeaderSize);
159
160 strings_.reserve(rows_);
161
162 size_t bytes_parsed = kPmpHeaderSize;
163 const uint8* data_cursor = data_.get() + kPmpHeaderSize;
164
165 while (strings_.size() < rows_) {
166 const uint8* string_end = static_cast<const uint8*>(
167 memchr(data_cursor, '\0', length_ - bytes_parsed));
168
169 // Fail if cannot find null termination. String runs on past file end.
170 if (string_end == NULL)
171 return -1;
172
173 // Length of string. (+1 to include the termination character).
174 ptrdiff_t length_in_bytes = string_end - data_cursor + 1;
175
176 strings_.push_back(reinterpret_cast<const char*>(data_cursor));
177 data_cursor += length_in_bytes;
178 bytes_parsed += length_in_bytes;
179 }
180
181 return bytes_parsed - kPmpHeaderSize;
182 }
183
184 } // namespace picasaimport
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698