blob: e7091da89e782bdf213137b38e38a905ce5087b6 [file] [log] [blame]
// 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 "chrome/common/media_galleries/pmp_test_helper.h"
#include <algorithm>
#include <iterator>
#include "base/file_util.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/media_galleries/picasa_types.h"
namespace picasa {
namespace {
// Flatten a vector of elements into an array of bytes.
template<class T>
std::vector<char> Flatten(const std::vector<T>& elems) {
if (elems.empty())
return std::vector<char>();
const uint8* elems0 = reinterpret_cast<const uint8*>(&elems[0]);
std::vector<char> data_body(elems0, elems0 + sizeof(T) * elems.size());
return data_body;
}
// Custom specialization for std::string.
template<>
std::vector<char> Flatten(const std::vector<std::string>& strings) {
std::vector<char> totalchars;
for (std::vector<std::string>::const_iterator it = strings.begin();
it != strings.end(); ++it) {
std::copy(it->begin(), it->end(), std::back_inserter(totalchars));
totalchars.push_back('\0'); // Add the null termination too.
}
return totalchars;
}
// Returns a new vector with the concatenated contents of |a| and |b|.
std::vector<char> CombinedVectors(const std::vector<char>& a,
const std::vector<char>& b) {
std::vector<char> total;
std::copy(a.begin(), a.end(), std::back_inserter(total));
std::copy(b.begin(), b.end(), std::back_inserter(total));
return total;
}
} // namespace
PmpTestHelper::PmpTestHelper(const std::string& table_name)
: table_name_(table_name) {
}
bool PmpTestHelper::Init(ColumnFileDestination column_file_destination) {
if (!root_dir_.CreateUniqueTempDir() ||
!root_dir_.IsValid() ||
!file_util::CreateDirectory(GetDatabaseDirPath()) ||
!file_util::CreateDirectory(GetTempDirPath())) {
return false;
}
if (column_file_destination == DATABASE_DIRECTORY)
column_file_destination_directory_ = GetDatabaseDirPath();
else if (column_file_destination == TEMPORARY_DIRECTORY)
column_file_destination_directory_ = GetTempDirPath();
else
NOTREACHED();
base::FilePath indicator_path = column_file_destination_directory_.Append(
base::FilePath::FromUTF8Unsafe(table_name_ + "_0"));
return file_util::WriteFile(indicator_path, NULL, 0) == 0;
}
base::FilePath PmpTestHelper::GetDatabaseDirPath() const {
DCHECK(root_dir_.IsValid());
return root_dir_.path().AppendASCII(kPicasaDatabaseDirName);
}
base::FilePath PmpTestHelper::GetTempDirPath() const {
DCHECK(root_dir_.IsValid());
return root_dir_.path().AppendASCII(kPicasaTempDirName);
}
template<class T>
bool PmpTestHelper::WriteColumnFileFromVector(
const std::string& column_name, const PmpFieldType field_type,
const std::vector<T>& elements_vector) const {
std::string file_name = table_name_ + "_" + column_name + "." + kPmpExtension;
base::FilePath path =
column_file_destination_directory_.AppendASCII(file_name);
std::vector<char> data = PmpTestHelper::MakeHeaderAndBody(
field_type, elements_vector.size(), elements_vector);
size_t bytes_written = file_util::WriteFile(path, &data[0], data.size());
return (bytes_written == data.size());
}
// Explicit Instantiation for all the valid types.
template bool PmpTestHelper::WriteColumnFileFromVector<std::string>(
const std::string&, const PmpFieldType,
const std::vector<std::string>&) const;
template bool PmpTestHelper::WriteColumnFileFromVector<uint32>(
const std::string&, const PmpFieldType, const std::vector<uint32>&) const;
template bool PmpTestHelper::WriteColumnFileFromVector<double>(
const std::string&, const PmpFieldType, const std::vector<double>&) const;
template bool PmpTestHelper::WriteColumnFileFromVector<uint8>(
const std::string&, const PmpFieldType, const std::vector<uint8>&) const;
template bool PmpTestHelper::WriteColumnFileFromVector<uint64>(
const std::string&, const PmpFieldType, const std::vector<uint64>&) const;
// Return a vector so we don't have to worry about memory management.
std::vector<char> PmpTestHelper::MakeHeader(const PmpFieldType field_type,
const uint32 row_count) {
std::vector<char> header(picasa::kPmpHeaderSize);
// Copy in magic bytes.
memcpy(&header[picasa::kPmpMagic1Offset], &picasa::kPmpMagic1,
sizeof(picasa::kPmpMagic1));
memcpy(&header[picasa::kPmpMagic2Offset], &picasa::kPmpMagic2,
sizeof(picasa::kPmpMagic2));
memcpy(&header[picasa::kPmpMagic3Offset], &picasa::kPmpMagic3,
sizeof(picasa::kPmpMagic3));
memcpy(&header[picasa::kPmpMagic4Offset], &picasa::kPmpMagic4,
sizeof(picasa::kPmpMagic4));
// Copy in field type.
uint16 field_type_short = static_cast<uint16>(field_type);
memcpy(&header[picasa::kPmpFieldType1Offset], &field_type_short,
sizeof(uint16));
memcpy(&header[picasa::kPmpFieldType2Offset], &field_type_short,
sizeof(uint16));
// Copy in row count.
memcpy(&header[picasa::kPmpRowCountOffset], &row_count, sizeof(uint32));
return header;
}
template<class T>
std::vector<char> PmpTestHelper::MakeHeaderAndBody(
const PmpFieldType field_type, const uint32 row_count,
const std::vector<T>& elems) {
return CombinedVectors(PmpTestHelper::MakeHeader(field_type, row_count),
Flatten(elems));
}
// Explicit Instantiation for all the valid types.
template std::vector<char> PmpTestHelper::MakeHeaderAndBody<std::string>(
const PmpFieldType, const uint32, const std::vector<std::string>&);
template std::vector<char> PmpTestHelper::MakeHeaderAndBody<uint32>(
const PmpFieldType, const uint32, const std::vector<uint32>&);
template std::vector<char> PmpTestHelper::MakeHeaderAndBody<double>(
const PmpFieldType, const uint32, const std::vector<double>&);
template std::vector<char> PmpTestHelper::MakeHeaderAndBody<uint8>(
const PmpFieldType, const uint32, const std::vector<uint8>&);
template std::vector<char> PmpTestHelper::MakeHeaderAndBody<uint64>(
const PmpFieldType, const uint32, const std::vector<uint64>&);
} // namespace picasa