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(AlbumTableFiles table_files
)
31 : table_files_(table_files
.Pass()),
35 PicasaAlbumTableReader::~PicasaAlbumTableReader() {
38 const std::vector
<AlbumInfo
>& PicasaAlbumTableReader::folders() const {
43 const std::vector
<AlbumInfo
>& PicasaAlbumTableReader::albums() const {
48 bool PicasaAlbumTableReader::Init() {
52 if (!table_files_
.indicator_file
.IsValid())
55 PmpColumnReader category_column
, date_column
, filename_column
, name_column
,
56 token_column
, uid_column
;
57 if (!category_column
.ReadFile(&table_files_
.category_file
, PMP_TYPE_UINT32
) ||
58 !date_column
.ReadFile(&table_files_
.date_file
, PMP_TYPE_DOUBLE64
) ||
59 !filename_column
.ReadFile(&table_files_
.filename_file
, PMP_TYPE_STRING
) ||
60 !name_column
.ReadFile(&table_files_
.name_file
, PMP_TYPE_STRING
) ||
61 !token_column
.ReadFile(&table_files_
.token_file
, PMP_TYPE_STRING
) ||
62 !uid_column
.ReadFile(&table_files_
.uid_file
, PMP_TYPE_STRING
)) {
66 // In the PMP format, columns can be different lengths. The number of rows
67 // in the table is max of all the columns, and short columns are NULL padded.
69 row_count
= std::max(row_count
, category_column
.rows_read());
70 row_count
= std::max(row_count
, date_column
.rows_read());
71 row_count
= std::max(row_count
, filename_column
.rows_read());
72 row_count
= std::max(row_count
, name_column
.rows_read());
73 row_count
= std::max(row_count
, token_column
.rows_read());
74 row_count
= std::max(row_count
, uid_column
.rows_read());
76 for (uint32 i
= 0; i
< row_count
; i
++) {
77 uint32 category
= kAlbumCategoryInvalid
;
81 // PMP tables often contain 'garbage' rows of deleted or auto-generated
82 // album-like entities. We ignore those rows.
83 if (!category_column
.ReadUInt32(i
, &category
) ||
84 !date_column
.ReadDouble64(i
, &date
) ||
85 !name_column
.ReadString(i
, &name
) || name
.empty() ||
86 !uid_column
.ReadString(i
, &uid
) || uid
.empty()) {
90 base::Time timestamp
= TimeFromMicrosoftVariantTime(date
);
92 if (category
== kAlbumCategoryAlbum
) {
94 if (!token_column
.ReadString(i
, &token
) || token
.empty() ||
95 !StartsWithASCII(token
, kAlbumTokenPrefix
, false)) {
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