1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/utility/media_galleries/picasa_album_table_reader.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/common/media_galleries/pmp_constants.h"
13 #include "chrome/utility/media_galleries/pmp_column_reader.h"
19 // |variant_time| is specified as the number of days from Dec 30, 1899.
20 base::Time
TimeFromMicrosoftVariantTime(double variant_time
) {
21 base::TimeDelta variant_delta
= base::TimeDelta::FromMicroseconds(
22 static_cast<int64
>(variant_time
* base::Time::kMicrosecondsPerDay
));
24 return base::Time::FromLocalExploded(kPmpVariantTimeEpoch
) + variant_delta
;
29 PicasaAlbumTableReader::PicasaAlbumTableReader(AlbumTableFiles table_files
)
30 : table_files_(table_files
.Pass()),
34 PicasaAlbumTableReader::~PicasaAlbumTableReader() {
37 const std::vector
<AlbumInfo
>& PicasaAlbumTableReader::folders() const {
42 const std::vector
<AlbumInfo
>& PicasaAlbumTableReader::albums() const {
47 bool PicasaAlbumTableReader::Init() {
51 if (!table_files_
.indicator_file
.IsValid())
54 PmpColumnReader category_column
, date_column
, filename_column
, name_column
,
55 token_column
, uid_column
;
56 if (!category_column
.ReadFile(&table_files_
.category_file
, PMP_TYPE_UINT32
) ||
57 !date_column
.ReadFile(&table_files_
.date_file
, PMP_TYPE_DOUBLE64
) ||
58 !filename_column
.ReadFile(&table_files_
.filename_file
, PMP_TYPE_STRING
) ||
59 !name_column
.ReadFile(&table_files_
.name_file
, PMP_TYPE_STRING
) ||
60 !token_column
.ReadFile(&table_files_
.token_file
, PMP_TYPE_STRING
) ||
61 !uid_column
.ReadFile(&table_files_
.uid_file
, PMP_TYPE_STRING
)) {
65 // In the PMP format, columns can be different lengths. The number of rows
66 // in the table is max of all the columns, and short columns are NULL padded.
68 row_count
= std::max(row_count
, category_column
.rows_read());
69 row_count
= std::max(row_count
, date_column
.rows_read());
70 row_count
= std::max(row_count
, filename_column
.rows_read());
71 row_count
= std::max(row_count
, name_column
.rows_read());
72 row_count
= std::max(row_count
, token_column
.rows_read());
73 row_count
= std::max(row_count
, uid_column
.rows_read());
75 for (uint32 i
= 0; i
< row_count
; i
++) {
76 uint32 category
= kAlbumCategoryInvalid
;
80 // PMP tables often contain 'garbage' rows of deleted or auto-generated
81 // album-like entities. We ignore those rows.
82 if (!category_column
.ReadUInt32(i
, &category
) ||
83 !date_column
.ReadDouble64(i
, &date
) ||
84 !name_column
.ReadString(i
, &name
) || name
.empty() ||
85 !uid_column
.ReadString(i
, &uid
) || uid
.empty()) {
89 base::Time timestamp
= TimeFromMicrosoftVariantTime(date
);
91 if (category
== kAlbumCategoryAlbum
) {
93 if (!token_column
.ReadString(i
, &token
) || token
.empty() ||
94 !base::StartsWith(token
, kAlbumTokenPrefix
,
95 base::CompareCase::INSENSITIVE_ASCII
)) {
99 albums_
.push_back(AlbumInfo(name
, timestamp
, uid
, base::FilePath()));
100 } else if (category
== kAlbumCategoryFolder
) {
101 std::string filename
;
102 if (!filename_column
.ReadString(i
, &filename
) || filename
.empty())
105 base::FilePath path
=
106 base::FilePath(base::FilePath::FromUTF8Unsafe(filename
));
108 folders_
.push_back(AlbumInfo(name
, timestamp
, uid
, path
));
116 } // namespace picasa