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/path_service.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/common/media_galleries/pmp_constants.h"
14 #include "chrome/utility/media_galleries/pmp_column_reader.h"
20 // |variant_time| is specified as the number of days from Dec 30, 1899.
21 base::Time
TimeFromMicrosoftVariantTime(double variant_time
) {
22 base::TimeDelta variant_delta
= base::TimeDelta::FromMicroseconds(
23 static_cast<int64
>(variant_time
* base::Time::kMicrosecondsPerDay
));
25 return base::Time::FromLocalExploded(kPmpVariantTimeEpoch
) + variant_delta
;
30 PicasaAlbumTableReader::PicasaAlbumTableReader(
31 const AlbumTableFiles
& table_files
)
32 : table_files_(table_files
),
36 PicasaAlbumTableReader::~PicasaAlbumTableReader() {
37 CloseAlbumTableFiles(&table_files_
);
40 const std::vector
<AlbumInfo
>& PicasaAlbumTableReader::folders() const {
45 const std::vector
<AlbumInfo
>& PicasaAlbumTableReader::albums() const {
50 bool PicasaAlbumTableReader::Init() {
54 if (table_files_
.indicator_file
== base::kInvalidPlatformFileValue
)
57 PmpColumnReader category_column
, date_column
, filename_column
, name_column
,
58 token_column
, uid_column
;
59 if (!category_column
.ReadFile(table_files_
.category_file
, PMP_TYPE_UINT32
) ||
60 !date_column
.ReadFile(table_files_
.date_file
, PMP_TYPE_DOUBLE64
) ||
61 !filename_column
.ReadFile(table_files_
.filename_file
, PMP_TYPE_STRING
) ||
62 !name_column
.ReadFile(table_files_
.name_file
, PMP_TYPE_STRING
) ||
63 !token_column
.ReadFile(table_files_
.token_file
, PMP_TYPE_STRING
) ||
64 !uid_column
.ReadFile(table_files_
.uid_file
, PMP_TYPE_STRING
)) {
68 // In the PMP format, columns can be different lengths. The number of rows
69 // in the table is max of all the columns, and short columns are NULL padded.
71 row_count
= std::max(row_count
, category_column
.rows_read());
72 row_count
= std::max(row_count
, date_column
.rows_read());
73 row_count
= std::max(row_count
, filename_column
.rows_read());
74 row_count
= std::max(row_count
, name_column
.rows_read());
75 row_count
= std::max(row_count
, token_column
.rows_read());
76 row_count
= std::max(row_count
, uid_column
.rows_read());
78 for (uint32 i
= 0; i
< row_count
; i
++) {
79 uint32 category
= kAlbumCategoryInvalid
;
83 // PMP tables often contain 'garbage' rows of deleted or auto-generated
84 // album-like entities. We ignore those rows.
85 if (!category_column
.ReadUInt32(i
, &category
) ||
86 !date_column
.ReadDouble64(i
, &date
) ||
87 !name_column
.ReadString(i
, &name
) || name
.empty() ||
88 !uid_column
.ReadString(i
, &uid
) || uid
.empty()) {
92 base::Time timestamp
= TimeFromMicrosoftVariantTime(date
);
94 if (category
== kAlbumCategoryAlbum
) {
96 if (!token_column
.ReadString(i
, &token
) || token
.empty() ||
97 !StartsWithASCII(token
, kAlbumTokenPrefix
, false)) {
101 albums_
.push_back(AlbumInfo(name
, timestamp
, uid
, base::FilePath()));
102 } else if (category
== kAlbumCategoryFolder
) {
103 std::string filename
;
104 if (!filename_column
.ReadString(i
, &filename
) || filename
.empty())
107 base::FilePath path
=
108 base::FilePath(base::FilePath::FromUTF8Unsafe(filename
));
110 folders_
.push_back(AlbumInfo(name
, timestamp
, uid
, path
));
118 } // namespace picasa