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

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: More formatting/ style changes. 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..7f2521344c88b616bae19f79cbb21c1e45d66be2
--- /dev/null
+++ b/webkit/fileapi/media/picasa/pmp_column_reader.cc
@@ -0,0 +1,182 @@
+// Copyright 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/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) { }
+
+PmpColumnReader::~PmpColumnReader() { }
+
+bool PmpColumnReader::ReadFromMemory(uint32* rows_read, const uint8* data,
+ const size_t len) {
+ 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.
+ return false;
+ }
+
+ length_ = len;
+ data_.reset(new uint8[length_]);
+ std::copy(data, data + length_, data_.get());
+
+ return ParseData(rows_read);
+}
+
+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.
+ DCHECK(data_.get() != NULL);
+ DCHECK(length_ > kPmpHeaderSize);
+
+ if(row < rows_) {
vandebo (ex-Chrome) 2013/03/27 00:06:19 Check the field type?
tommycli 2013/03/27 19:34:30 Done.
+ *target = strings_[row];
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool PmpColumnReader::ReadUInt32(const uint32 row, uint32* target) const {
+ return ReadPrimitive<uint32>(row, target);
+}
+
+bool PmpColumnReader::ReadDouble64(const uint32 row, double* target) const {
+ return ReadPrimitive<double>(row, target);
+}
+
+bool PmpColumnReader::ReadUInt8(const uint32 row, uint8* target) const {
+ return ReadPrimitive<uint8>(row, target);
+}
+
+bool PmpColumnReader::ReadUInt64(const uint32 row, uint64* target) const {
+ return ReadPrimitive<uint64>(row, target);
+}
+
+template<class T>
+bool PmpColumnReader::ReadPrimitive(uint32 row, T* target) const {
+ DCHECK(data_.get() != NULL);
+ DCHECK(length_ > kPmpHeaderSize);
+
+ if(sizeof(T) != fieldsize_) {
+ return false;
+ }
+
+ if(row < rows_) {
+ *target = *(reinterpret_cast<T*>(
+ data_.get() + kPmpHeaderSize + row*fieldsize_));
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool PmpColumnReader::ParseData(uint32* rows_read) {
+ DCHECK(data_.get() != NULL);
+ DCHECK(length_ >= kPmpHeaderSize);
+
+ // Check all magic bytes.
+ if (memcmp(kPmpMagicO0S4, data_.get(), 4) != 0||
+ memcmp(kPmpMagicO6S2, data_.get() + 6, 2) != 0 ||
+ memcmp(kPmpMagicO8S4, data_.get() + 8, 4) != 0 ||
+ memcmp(kPmpMagicO14S2, data_.get() + 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];
+ rows_ = *(reinterpret_cast<uint32*>(&data_[kPmpRowCountOffset]));
+
+ bool parse_success = false;
+
+ switch (field_type) {
+ case kPmpFieldTypeString:
+ parse_success = IndexStrings();
+ break;
+ case kPmpFieldTypeUInt32:
+ parse_success = SetAndValidateFieldsize<uint32>();
+ break;
+ case kPmpFieldTypeDouble64:
+ parse_success = SetAndValidateFieldsize<double>();
+ break;
+ case kPmpFieldTypeUInt8:
+ parse_success = SetAndValidateFieldsize<uint8>();
+ break;
+ case kPmpFieldTypeUInt64:
+ parse_success = SetAndValidateFieldsize<uint64>();
+ break;
+ default:
+ parse_success = false;
+ break;
+ }
+
+ if(parse_success) {
+ // Set the number of rows read. Though it's not valid unless we return true.
+ if(rows_read != NULL) {
+ *rows_read = rows_;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool PmpColumnReader::IndexStrings() {
+ DCHECK(data_.get() != NULL);
+ DCHECK(length_ >= kPmpHeaderSize);
+
+ strings_.clear();
+ strings_.reserve(rows_);
+
+ size_t bytes_parsed = kPmpHeaderSize;
+ const uint8* itr = data_.get() + kPmpHeaderSize;
+
+ while (strings_.size() < rows_) {
+ const uint8* ptr_to_str_end = static_cast<const uint8*>(
+ memchr(itr, '\0', length_ - bytes_parsed));
+
+ // Fail if cannot find null termination. String runs on past file end.
+ if(ptr_to_str_end == NULL) 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;
vandebo (ex-Chrome) 2013/03/27 00:06:19 return false on next line.
tommycli 2013/03/27 19:34:30 Done.
+
+ 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;
+ }
+
+ return false;
+}
+
+} // namespace

Powered by Google App Engine
This is Rietveld 408576698