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

Unified 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 memory issue. Created 7 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: webkit/fileapi/media/picasa/pmp_column_reader.cc
diff --git a/webkit/fileapi/media/picasa/pmp_column_reader.cc b/webkit/fileapi/media/picasa/pmp_column_reader.cc
new file mode 100644
index 0000000000000000000000000000000000000000..82a82625eb28035d596d9920b8081f4cc2e75cff
--- /dev/null
+++ b/webkit/fileapi/media/picasa/pmp_column_reader.cc
@@ -0,0 +1,211 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/fileapi/media/picasa/pmp_column_reader.h"
+
+#include <cstring>
+
+#include "base/files/file_path.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/logging.h"
+#include "webkit/fileapi/media/picasa/pmp_constants.h"
+
+namespace fileapi {
+
+PmpColumnReader::PmpColumnReader(std::string column_name)
+ : column_name_(column_name),
+ data_(NULL),
+ length_(0),
+ rows_(0),
+ strings_(),
+ fieldsize_(0) {
+
vandebo (ex-Chrome) 2013/03/26 01:12:14 nit: extra line
tommycli 2013/03/26 22:30:43 Done.
+}
+
+PmpColumnReader::~PmpColumnReader() {
+ delete[] data_;
vandebo (ex-Chrome) 2013/03/26 01:12:14 This means you probably want to use a scoped objec
tommycli 2013/03/26 22:30:43 Done.
+}
+
+bool PmpColumnReader::ReadFromDisk(uint32* rows_read,
+ const base::FilePath& filepath) {
+ base::MemoryMappedFile file;
+ bool file_initialized = file.Initialize(filepath);
+
+ // If file is not initialized, too small, or too large (50MB), fail out.
+ if (!file_initialized ||
+ file.length() < kPmpHeaderSize ||
+ file.length() > 50*1024*1024) {
vandebo (ex-Chrome) 2013/03/26 01:12:14 Make this a constant as well.
tommycli 2013/03/26 22:30:43 Done.
+ return false;
+ }
+
+ length_ = file.length();
+ if(data_ != NULL) {
+ delete[] data_;
+ }
+ data_ = new uint8[length_];
+ memcpy(data_, file.data(), length_);
+
+ return ParseData(rows_read);
+}
+
+bool PmpColumnReader::ReadFromMemory(uint32* rows_read, const uint8* data,
+ const size_t len) {
+ if(len < kPmpHeaderSize || data == NULL) {
+ return false;
+ }
+
+ length_ = len;
+ if(data_ != NULL) {
+ delete[] data_;
+ }
+ data_ = new uint8[length_];
+ memcpy(data_, data, length_);
+
+ return ParseData(rows_read);
+}
+
+template<class T>
+bool PmpColumnReader::Read(uint32 row, T* target) {
+ DCHECK(data_ != NULL && length_ > kPmpHeaderSize);
+
+ if(sizeof(T) != fieldsize_) {
+ return false;
+ }
+
+ if(row < rows_) {
+ memcpy(target, data_ + kPmpHeaderSize + row*fieldsize_, fieldsize_);
vandebo (ex-Chrome) 2013/03/26 01:12:14 You probably want an explicit reinterpret_cast in
tommycli 2013/03/26 22:30:43 Done.
+ return true;
+ } else {
+ return false;
+ }
+}
+
+template bool PmpColumnReader::Read<uint8>(uint32 row, uint8* target);
+
+template bool PmpColumnReader::Read<uint16>(uint32 row, uint16* target);
+
+template bool PmpColumnReader::Read<uint32>(uint32 row, uint32* target);
+
+template bool PmpColumnReader::Read<uint64>(uint32 row, uint64* target);
+
+template bool PmpColumnReader::Read<double>(uint32 row, double* target);
+
+template<>
+bool PmpColumnReader::Read(uint32 row, std::string* target) {
+ DCHECK(data_ != NULL && length_ > kPmpHeaderSize);
+
+ if(row < rows_) {
+ *target = strings_[row];
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool PmpColumnReader::ParseData(uint32* rows_read) {
+ DCHECK(data_ != NULL);
+ DCHECK(length_ >= kPmpHeaderSize);
+
+ // Check all magic bytes
+ if (memcmp(kPmpMagicO0S4, data_, 4) != 0||
vandebo (ex-Chrome) 2013/03/26 01:12:14 You may want to make a packed struct of the differ
tommycli 2013/03/26 22:30:43 That's a good idea. I may need some help figuring
+ memcmp(kPmpMagicO6S2, data_ + 6, 2) != 0 ||
+ memcmp(kPmpMagicO8S4, data_ + 8, 4) != 0 ||
+ memcmp(kPmpMagicO14S2, data_ + 14, 2) != 0) {
+ return false;
+ }
+
+ // Verify row field type matches
+ if (data_[kPmpFieldTypeFirstOffset] != data_[kPmpFieldTypeSecondOffset]) {
+ return false;
+ }
+
+ // Read the field type and number of rows expected
+ uint16 field_type = data_[kPmpFieldTypeFirstOffset];
+ memcpy(&rows_, &data_[kPmpRowCountOffset], sizeof(uint32));
+
+ // Set the number of rows read. Though it's not valid unless we return true.
+ if(rows_read != NULL) {
+ *rows_read = rows_;
+ }
+
+ switch (field_type) {
+ case 0x00:
vandebo (ex-Chrome) 2013/03/26 01:12:14 Make these constants.
tommycli 2013/03/26 22:30:43 Done.
+ return IndexStrings();
+ break;
+ case 0x01:
+ return SetAndValidateFieldsize<uint32>();
+ break;
+ case 0x02:
+ return SetAndValidateFieldsize<double>();
+ break;
+ case 0x03:
+ return SetAndValidateFieldsize<uint8>();
+ break;
+ case 0x04:
+ return SetAndValidateFieldsize<uint64>();
+ break;
+ case 0x05:
+ return SetAndValidateFieldsize<uint16>();
+ break;
+ case 0x06:
+ return IndexStrings();
+ break;
+ case 0x07:
+ return SetAndValidateFieldsize<uint32>();
+ break;
+ default:
+ return false;
+ break;
+ }
+}
+
+bool PmpColumnReader::IndexStrings() {
+ DCHECK(data_ != NULL);
+ DCHECK(length_ >= kPmpHeaderSize);
+
+ strings_.clear();
+ strings_.reserve(rows_);
+
+ size_t bytes_parsed = kPmpHeaderSize;
+ const uint8* itr = data_ + kPmpHeaderSize;
vandebo (ex-Chrome) 2013/03/26 01:12:14 How is the string encoded? UTF8? unspecified?
tommycli 2013/03/26 22:30:43 Unspecified. I've sent an email to the Picasa ppl
+
+ while (strings_.size() < rows_) {
+ const uint8* ptr_to_str_end = static_cast<const uint8*>(
+ memchr(itr, '\0', length_-bytes_parsed));
vandebo (ex-Chrome) 2013/03/26 01:12:14 spaces around math operators.
tommycli 2013/03/26 22:30:43 Done.
+
+ // fail if cannot find null termination. String runs on past file end.
vandebo (ex-Chrome) 2013/03/26 01:12:14 Capitalize
tommycli 2013/03/26 22:30:43 Done.
+ if(ptr_to_str_end == NULL) {
vandebo (ex-Chrome) 2013/03/26 01:12:14 {}'s around single line conditionals with single l
tommycli 2013/03/26 22:30:43 Done.
+ return false;
+ }
+
+ // Length of string. (+1 to include the termination character)
+ ptrdiff_t len_bytes = ptr_to_str_end - itr + 1;
+
+ strings_.push_back(reinterpret_cast<const char*>(itr));
+ itr += len_bytes;
+ bytes_parsed += len_bytes;
+ }
+
+ // This means the file has more bytes at the end we haven't parsed
+ if(bytes_parsed != length_) {
+ return false;
+ }
+
+ return true;
+}
+
+template<class T>
+bool PmpColumnReader::SetAndValidateFieldsize() {
+ unsigned long calculated_n_rows =
+ (length_ - kPmpHeaderSize)/sizeof(T);
+
+ if(calculated_n_rows == rows_) {
+ fieldsize_ = sizeof(T);
+ return true;
+ } else {
vandebo (ex-Chrome) 2013/03/26 01:12:14 No else in this case.
tommycli 2013/03/26 22:30:43 Done.
+ return false;
+ }
+}
+
+} // namespace

Powered by Google App Engine
This is Rietveld 408576698