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

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: Missed a change. 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..098a16df0a18dc3905be3769cecab73df63374ee
--- /dev/null
+++ b/webkit/fileapi/media/picasa/pmp_column_reader.cc
@@ -0,0 +1,189 @@
+// 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/file_util.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
+#include "webkit/fileapi/media/picasa/pmp_constants.h"
+
+namespace fileapi {
+
+namespace {
+
+const size_t kPmpMaxFilesize = 50*1024*1024; // Maximum of 50 MB.
+
+} // namespace
+
+PmpColumnReader::PmpColumnReader()
+ : data_(NULL),
+ length_(0),
+ field_type_(kPmpFieldTypeInvalid),
+ rows_(0),
+ strings_() { }
+
+PmpColumnReader::~PmpColumnReader() { }
+
+bool PmpColumnReader::Init(const base::FilePath& filepath, uint32* rows_read) {
+ DCHECK(!data_.get());
+ base::ThreadRestrictions::AssertIOAllowed();
+
+ long int length = 0; // Signed temporary.
+ if (!file_util::GetFileSize(filepath, &length))
+ return false;
+
+ length_ = length;
+
+ if (length_ < kPmpHeaderSize || length_ > kPmpMaxFilesize)
+ return false;
+
+ data_.reset(new uint8[length_]);
+
+ char* data_begin = reinterpret_cast<char*>(data_.get());
+
+ return (file_util::ReadFile(filepath, data_begin, length_) &&
vandebo (ex-Chrome) 2013/04/02 18:10:55 nit: extra ()s
tommycli 2013/04/02 19:05:55 Done.
+ ParseData(rows_read));
+}
+
+bool PmpColumnReader::ReadString(const uint32 row, std::string* result) const {
+ DCHECK(data_.get() != NULL);
+ DCHECK_GT(length_, kPmpHeaderSize + row);
+
+ if (field_type_ != kPmpFieldTypeString || row >= rows_)
+ return false;
+
+ *result = strings_[row];
+ return true;
+}
+
+bool PmpColumnReader::ReadUInt32(const uint32 row, uint32* result) const {
+ DCHECK(data_.get() != NULL);
+ DCHECK_GT(length_, kPmpHeaderSize + row * sizeof(uint32));
+
+ if (field_type_ != kPmpFieldTypeUInt32 || row >= rows_)
+ return false;
+
+ *result = reinterpret_cast<uint32*>(data_.get() + kPmpHeaderSize)[row];
+ return true;
+}
+
+bool PmpColumnReader::ReadDouble64(const uint32 row, double* result) const {
+ DCHECK(data_.get() != NULL);
+ DCHECK_GT(length_, kPmpHeaderSize + row * sizeof(double));
+
+ if (field_type_ != kPmpFieldTypeDouble64 || row >= rows_)
+ return false;
+
+ *result = reinterpret_cast<double*>(data_.get() + kPmpHeaderSize)[row];
+ return true;
+}
+
+bool PmpColumnReader::ReadUInt8(const uint32 row, uint8* result) const {
+ DCHECK(data_.get() != NULL);
+ DCHECK_GT(length_, kPmpHeaderSize + row * sizeof(uint8));
+
+ if (field_type_ != kPmpFieldTypeUInt8 || row >= rows_)
+ return false;
+
+ *result = reinterpret_cast<uint8*>(data_.get() + kPmpHeaderSize)[row];
+ return true;
+}
+
+bool PmpColumnReader::ReadUInt64(const uint32 row, uint64* result) const {
+ DCHECK(data_.get() != NULL);
+ DCHECK_GT(length_, kPmpHeaderSize + row * sizeof(uint64));
+
+ if (field_type_ != kPmpFieldTypeUInt64 || row >= rows_)
+ return false;
+
+ *result = reinterpret_cast<uint64*>(data_.get() + kPmpHeaderSize)[row];
+ return true;
+}
+
+bool PmpColumnReader::ParseData(uint32* rows_read) {
+ DCHECK(data_.get() != NULL);
+ DCHECK_GE(length_, kPmpHeaderSize);
+
+ // Check all magic bytes.
+ if (memcmp(&kPmpMagic1, &data_[kPmpMagic1Offset], sizeof(kPmpMagic1)) != 0 ||
+ memcmp(&kPmpMagic2, &data_[kPmpMagic2Offset], sizeof(kPmpMagic2)) != 0 ||
+ memcmp(&kPmpMagic3, &data_[kPmpMagic3Offset], sizeof(kPmpMagic3)) != 0 ||
+ memcmp(&kPmpMagic4, &data_[kPmpMagic4Offset], sizeof(kPmpMagic4)) != 0) {
+ return false;
+ }
+
+ field_type_ = *(reinterpret_cast<uint16*>(&data_[kPmpFieldType1Offset]));
+
+ // Verify if field type matches second declaration
+ if (field_type_ != *(reinterpret_cast<uint16*>(&data_[kPmpFieldType2Offset])))
+ return false;
+
+ rows_ = *(reinterpret_cast<uint32*>(&data_[kPmpRowCountOffset]));
+
+ bool parse_success = false;
vandebo (ex-Chrome) 2013/04/02 18:10:55 If you have IndexStrings return bytes_parsed, you
tommycli 2013/04/02 19:05:55 Done.
+ size_t body_length = length_ - kPmpHeaderSize;
+ size_t expected_body_length = 0;
+ switch (field_type_) {
+ case kPmpFieldTypeString:
+ parse_success = IndexStrings();
+ break;
+ case kPmpFieldTypeUInt32:
+ expected_body_length = rows_ * sizeof(uint32);
+ parse_success = body_length == expected_body_length;
+ break;
+ case kPmpFieldTypeDouble64:
+ expected_body_length = rows_ * sizeof(double);
+ parse_success = body_length == expected_body_length;
+ break;
+ case kPmpFieldTypeUInt8:
+ expected_body_length = rows_ * sizeof(uint8);
+ parse_success = body_length == expected_body_length;
+ break;
+ case kPmpFieldTypeUInt64:
+ expected_body_length = rows_ * sizeof(uint64);
+ parse_success = body_length == expected_body_length;
+ break;
+ default:
+ return false;
+ break;
+ }
+
+ if (parse_success && rows_read)
+ *rows_read = rows_;
+ return parse_success;
+}
+
+bool PmpColumnReader::IndexStrings() {
+ DCHECK(data_.get() != NULL);
+ DCHECK_GE(length_, kPmpHeaderSize);
+
+ strings_.reserve(rows_);
+
+ size_t bytes_parsed = kPmpHeaderSize;
+ const uint8* body_cursor = data_.get() + kPmpHeaderSize;
vandebo (ex-Chrome) 2013/04/02 18:10:55 nit: body? data_cursor or just cursor.
tommycli 2013/04/02 19:05:55 Done.
+
+ while (strings_.size() < rows_) {
+ const uint8* string_end = static_cast<const uint8*>(
+ memchr(body_cursor, '\0', length_ - bytes_parsed));
+
+ // Fail if cannot find null termination. String runs on past file end.
+ if (string_end == NULL)
+ return false;
+
+ // Length of string. (+1 to include the termination character).
+ ptrdiff_t length_in_bytes = string_end - body_cursor + 1;
+
+ strings_.push_back(reinterpret_cast<const char*>(body_cursor));
+ body_cursor += length_in_bytes;
+ bytes_parsed += length_in_bytes;
+ }
+
+ return bytes_parsed == length_;
+}
+
+} // namespace

Powered by Google App Engine
This is Rietveld 408576698