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/logging.h" | |
| 11 #include "webkit/fileapi/media/picasa/pmp_constants.h" | |
| 12 | |
| 13 namespace fileapi { | |
| 14 | |
| 15 PmpColumnReader::PmpColumnReader(std::string column_name) | |
| 16 : column_name_(column_name), | |
| 17 data_(NULL), | |
| 18 length_(0), | |
| 19 rows_(0), | |
| 20 strings_(), | |
| 21 fieldsize_(0) { } | |
| 22 | |
| 23 PmpColumnReader::~PmpColumnReader() { } | |
| 24 | |
| 25 bool PmpColumnReader::ReadFromMemory(uint32* rows_read, const uint8* data, | |
| 26 const size_t len) { | |
| 27 if(len < kPmpHeaderSize || data == NULL) { | |
|
vandebo (ex-Chrome)
2013/03/27 00:06:19
nit: omit {}'s here.
tommycli
2013/03/27 19:34:30
Done.
| |
| 28 return false; | |
| 29 } | |
| 30 | |
| 31 length_ = len; | |
| 32 data_.reset(new uint8[length_]); | |
| 33 std::copy(data, data + length_, data_.get()); | |
| 34 | |
| 35 return ParseData(rows_read); | |
| 36 } | |
| 37 | |
| 38 bool PmpColumnReader::ReadString(const uint32 row, std::string* target) const { | |
|
vandebo (ex-Chrome)
2013/03/27 00:06:19
const std::string*
tommycli
2013/03/27 19:34:30
I use operator= on it.
| |
| 39 DCHECK(data_.get() != NULL); | |
| 40 DCHECK(length_ > kPmpHeaderSize); | |
| 41 | |
| 42 if(row < rows_) { | |
|
vandebo (ex-Chrome)
2013/03/27 00:06:19
Check the field type?
tommycli
2013/03/27 19:34:30
Done.
| |
| 43 *target = strings_[row]; | |
| 44 return true; | |
| 45 } else { | |
| 46 return false; | |
| 47 } | |
| 48 } | |
| 49 | |
| 50 bool PmpColumnReader::ReadUInt32(const uint32 row, uint32* target) const { | |
| 51 return ReadPrimitive<uint32>(row, target); | |
| 52 } | |
| 53 | |
| 54 bool PmpColumnReader::ReadDouble64(const uint32 row, double* target) const { | |
| 55 return ReadPrimitive<double>(row, target); | |
| 56 } | |
| 57 | |
| 58 bool PmpColumnReader::ReadUInt8(const uint32 row, uint8* target) const { | |
| 59 return ReadPrimitive<uint8>(row, target); | |
| 60 } | |
| 61 | |
| 62 bool PmpColumnReader::ReadUInt64(const uint32 row, uint64* target) const { | |
| 63 return ReadPrimitive<uint64>(row, target); | |
| 64 } | |
| 65 | |
| 66 template<class T> | |
| 67 bool PmpColumnReader::ReadPrimitive(uint32 row, T* target) const { | |
| 68 DCHECK(data_.get() != NULL); | |
| 69 DCHECK(length_ > kPmpHeaderSize); | |
| 70 | |
| 71 if(sizeof(T) != fieldsize_) { | |
| 72 return false; | |
| 73 } | |
| 74 | |
| 75 if(row < rows_) { | |
| 76 *target = *(reinterpret_cast<T*>( | |
| 77 data_.get() + kPmpHeaderSize + row*fieldsize_)); | |
| 78 return true; | |
| 79 } else { | |
| 80 return false; | |
| 81 } | |
| 82 } | |
| 83 | |
| 84 bool PmpColumnReader::ParseData(uint32* rows_read) { | |
| 85 DCHECK(data_.get() != NULL); | |
| 86 DCHECK(length_ >= kPmpHeaderSize); | |
| 87 | |
| 88 // Check all magic bytes. | |
| 89 if (memcmp(kPmpMagicO0S4, data_.get(), 4) != 0|| | |
| 90 memcmp(kPmpMagicO6S2, data_.get() + 6, 2) != 0 || | |
| 91 memcmp(kPmpMagicO8S4, data_.get() + 8, 4) != 0 || | |
| 92 memcmp(kPmpMagicO14S2, data_.get() + 14, 2) != 0) { | |
| 93 return false; | |
| 94 } | |
| 95 | |
| 96 // Verify row field type matches. | |
| 97 if (data_[kPmpFieldTypeFirstOffset] != data_[kPmpFieldTypeSecondOffset]) { | |
| 98 return false; | |
| 99 } | |
| 100 | |
| 101 // Read the field type and number of rows expected. | |
| 102 uint16 field_type = data_[kPmpFieldTypeFirstOffset]; | |
| 103 rows_ = *(reinterpret_cast<uint32*>(&data_[kPmpRowCountOffset])); | |
| 104 | |
| 105 bool parse_success = false; | |
| 106 | |
| 107 switch (field_type) { | |
| 108 case kPmpFieldTypeString: | |
| 109 parse_success = IndexStrings(); | |
| 110 break; | |
| 111 case kPmpFieldTypeUInt32: | |
| 112 parse_success = SetAndValidateFieldsize<uint32>(); | |
| 113 break; | |
| 114 case kPmpFieldTypeDouble64: | |
| 115 parse_success = SetAndValidateFieldsize<double>(); | |
| 116 break; | |
| 117 case kPmpFieldTypeUInt8: | |
| 118 parse_success = SetAndValidateFieldsize<uint8>(); | |
| 119 break; | |
| 120 case kPmpFieldTypeUInt64: | |
| 121 parse_success = SetAndValidateFieldsize<uint64>(); | |
| 122 break; | |
| 123 default: | |
| 124 parse_success = false; | |
| 125 break; | |
| 126 } | |
| 127 | |
| 128 if(parse_success) { | |
| 129 // Set the number of rows read. Though it's not valid unless we return true. | |
| 130 if(rows_read != NULL) { | |
| 131 *rows_read = rows_; | |
| 132 } | |
| 133 return true; | |
| 134 } | |
| 135 | |
| 136 return false; | |
| 137 } | |
| 138 | |
| 139 bool PmpColumnReader::IndexStrings() { | |
| 140 DCHECK(data_.get() != NULL); | |
| 141 DCHECK(length_ >= kPmpHeaderSize); | |
| 142 | |
| 143 strings_.clear(); | |
| 144 strings_.reserve(rows_); | |
| 145 | |
| 146 size_t bytes_parsed = kPmpHeaderSize; | |
| 147 const uint8* itr = data_.get() + kPmpHeaderSize; | |
| 148 | |
| 149 while (strings_.size() < rows_) { | |
| 150 const uint8* ptr_to_str_end = static_cast<const uint8*>( | |
| 151 memchr(itr, '\0', length_ - bytes_parsed)); | |
| 152 | |
| 153 // Fail if cannot find null termination. String runs on past file end. | |
| 154 if(ptr_to_str_end == NULL) return false; | |
| 155 | |
| 156 // Length of string. (+1 to include the termination character). | |
| 157 ptrdiff_t len_bytes = ptr_to_str_end - itr + 1; | |
| 158 | |
| 159 strings_.push_back(reinterpret_cast<const char*>(itr)); | |
| 160 itr += len_bytes; | |
| 161 bytes_parsed += len_bytes; | |
| 162 } | |
| 163 | |
| 164 // This means the file has more bytes at the end we haven't parsed. | |
| 165 if(bytes_parsed != length_) return false; | |
|
vandebo (ex-Chrome)
2013/03/27 00:06:19
return false on next line.
tommycli
2013/03/27 19:34:30
Done.
| |
| 166 | |
| 167 return true; | |
| 168 } | |
| 169 | |
| 170 template<class T> | |
| 171 bool PmpColumnReader::SetAndValidateFieldsize() { | |
| 172 unsigned long calculated_n_rows = (length_ - kPmpHeaderSize) / sizeof(T); | |
| 173 | |
| 174 if(calculated_n_rows == rows_) { | |
| 175 fieldsize_ = sizeof(T); | |
| 176 return true; | |
| 177 } | |
| 178 | |
| 179 return false; | |
| 180 } | |
| 181 | |
| 182 } // namespace | |
| OLD | NEW |