1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/utility/media_galleries/pmp_column_reader.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <cstring> 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/file_util.h" 10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/files/file.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/threading/thread_restrictions.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace picasa { 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochCOMPILE_ASSERT(sizeof(double) == 8, double_must_be_8_bytes_long); 19a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)const int64 kPmpMaxFilesize = 50*1024*1024; // Arbitrary maximum of 50 MB. 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PmpColumnReader::PmpColumnReader() 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : length_(0), 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) field_type_(PMP_TYPE_INVALID), 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rows_read_(0) {} 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PmpColumnReader::~PmpColumnReader() {} 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool PmpColumnReader::ReadFile(base::File* file, 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const PmpFieldType expected_type) { 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!data_.get()); 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!file->IsValid()) 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::File::Info info; 39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!file->GetInfo(&info)) 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch length_ = info.size; 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (length_ < kPmpHeaderSize || length_ > kPmpMaxFilesize) 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data_.reset(new uint8[length_]); 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) char* data_begin = reinterpret_cast<char*>(data_.get()); 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 50a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(length_ < kint32max); // ReadFile expects an int. 51a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bool success = file->Read(0, data_begin, length_) && 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ParseData(expected_type); 54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // If any of the reading or parsing fails, prevent Read* calls. 56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!success) 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rows_read_ = 0; 58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 59a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return success; 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool PmpColumnReader::ReadString(const uint32 row, std::string* result) const { 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(data_.get() != NULL); 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (field_type_ != PMP_TYPE_STRING || row >= rows_read_) 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 68a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK_LT(row, strings_.size()); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *result = strings_[row]; 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool PmpColumnReader::ReadUInt32(const uint32 row, uint32* result) const { 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(data_.get() != NULL); 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (field_type_ != PMP_TYPE_UINT32 || row >= rows_read_) 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *result = reinterpret_cast<uint32*>(data_.get() + kPmpHeaderSize)[row]; 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool PmpColumnReader::ReadDouble64(const uint32 row, double* result) const { 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(data_.get() != NULL); 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (field_type_ != PMP_TYPE_DOUBLE64 || row >= rows_read_) 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *result = reinterpret_cast<double*>(data_.get() + kPmpHeaderSize)[row]; 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool PmpColumnReader::ReadUInt8(const uint32 row, uint8* result) const { 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(data_.get() != NULL); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (field_type_ != PMP_TYPE_UINT8 || row >= rows_read_) 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *result = reinterpret_cast<uint8*>(data_.get() + kPmpHeaderSize)[row]; 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool PmpColumnReader::ReadUInt64(const uint32 row, uint64* result) const { 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(data_.get() != NULL); 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (field_type_ != PMP_TYPE_UINT64 || row >= rows_read_) 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *result = reinterpret_cast<uint64*>(data_.get() + kPmpHeaderSize)[row]; 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochuint32 PmpColumnReader::rows_read() const { 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(data_.get() != NULL); 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return rows_read_; 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool PmpColumnReader::ParseData(const PmpFieldType expected_type) { 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(data_.get() != NULL); 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(length_, kPmpHeaderSize); 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check all magic bytes. 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (memcmp(&kPmpMagic1, &data_[kPmpMagic1Offset], sizeof(kPmpMagic1)) != 0 || 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcmp(&kPmpMagic2, &data_[kPmpMagic2Offset], sizeof(kPmpMagic2)) != 0 || 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcmp(&kPmpMagic3, &data_[kPmpMagic3Offset], sizeof(kPmpMagic3)) != 0 || 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcmp(&kPmpMagic4, &data_[kPmpMagic4Offset], sizeof(kPmpMagic4)) != 0) { 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint16 field_type_data = 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *(reinterpret_cast<uint16*>(&data_[kPmpFieldType1Offset])); 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Verify if field type matches second declaration 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (field_type_data != 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *(reinterpret_cast<uint16*>(&data_[kPmpFieldType2Offset]))) { 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) field_type_ = static_cast<PmpFieldType>(field_type_data); 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (field_type_ != expected_type) 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rows_read_ = *(reinterpret_cast<uint32*>(&data_[kPmpRowCountOffset])); 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 146a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Sanity check against malicious row field. 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (rows_read_ > (kPmpMaxFilesize - kPmpHeaderSize)) 148a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return false; 149a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 150a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK_GE(length_, kPmpHeaderSize); 151a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) int64 body_length = length_ - kPmpHeaderSize; 152a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) int64 expected_body_length = 0; 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (field_type_) { 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case PMP_TYPE_STRING: 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) expected_body_length = IndexStrings(); 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case PMP_TYPE_UINT32: 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch expected_body_length = static_cast<int64>(rows_read_) * sizeof(uint32); 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case PMP_TYPE_DOUBLE64: 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch expected_body_length = static_cast<int64>(rows_read_) * sizeof(double); 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case PMP_TYPE_UINT8: 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch expected_body_length = static_cast<int64>(rows_read_) * sizeof(uint8); 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case PMP_TYPE_UINT64: 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch expected_body_length = static_cast<int64>(rows_read_) * sizeof(uint64); 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) default: 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return body_length == expected_body_length; 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 177a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)int64 PmpColumnReader::IndexStrings() { 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(data_.get() != NULL); 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(length_, kPmpHeaderSize); 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch strings_.reserve(rows_read_); 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 183a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) int64 bytes_parsed = kPmpHeaderSize; 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const uint8* data_cursor = data_.get() + kPmpHeaderSize; 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch while (strings_.size() < rows_read_) { 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const uint8* string_end = static_cast<const uint8*>( 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memchr(data_cursor, '\0', length_ - bytes_parsed)); 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Fail if cannot find null termination. String runs on past file end. 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (string_end == NULL) 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return -1; 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Length of string. (+1 to include the termination character). 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ptrdiff_t length_in_bytes = string_end - data_cursor + 1; 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) strings_.push_back(reinterpret_cast<const char*>(data_cursor)); 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data_cursor += length_in_bytes; 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bytes_parsed += length_in_bytes; 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return bytes_parsed - kPmpHeaderSize; 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace picasa 206