Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 | |
| OLD | NEW |