root/chrome/utility/media_galleries/picasa_albums_indexer.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. albums_images_
  2. HandleTriplet
  3. ParseFolderINI

// 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/utility/media_galleries/picasa_albums_indexer.h"

#include <algorithm>
#include <utility>
#include <vector>

#include "base/ini_parser.h"
#include "base/logging.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"

namespace picasa {

namespace {

const char kAlbumSectionHeader[] = ".album:";
const char kAlbumsKey[] = "albums";
const int kMaxDedupeNumber = 1000;  // Chosen arbitrarily.

class PicasaINIParser : public base::INIParser {
 public:
  PicasaINIParser(
      const base::FilePath& folder_path, AlbumImagesMap* albums_images)
      : folder_path_(folder_path),
        albums_images_(albums_images) {
  }
  virtual ~PicasaINIParser() {}

 private:
  virtual void HandleTriplet(const std::string& section,
                             const std::string& key,
                             const std::string& value) OVERRIDE {
    if (key != kAlbumsKey)
      return;

    // [.album:*] sections ignored as we get that data from the PMP files.
    if (section.find(kAlbumSectionHeader) == 0)
      return;

    std::vector<std::string> containing_albums;
    base::SplitString(value, ',', &containing_albums);
    for (std::vector<std::string>::iterator it = containing_albums.begin();
         it != containing_albums.end(); ++it) {
      AlbumImagesMap::iterator album_map_it = albums_images_->find(*it);

      // Ignore entry if the album uid is not listed among in |album_uids|
      // in the constructor. Happens if the PMP and INI files are inconsistent.
      if (album_map_it == albums_images_->end())
        continue;

      base::FilePath filename = base::FilePath::FromUTF8Unsafe(section);
      AlbumImages& album_images = album_map_it->second;

      // If filename is first of its name in album, simply add.
      if (album_images.insert(
              std::make_pair(section, folder_path_.Append(filename))).second) {
        continue;
      }

      // Otherwise, de-dupe by appending a number starting at (1).
      for (int i = 1; i < kMaxDedupeNumber; ++i) {
        std::string deduped_filename =
            filename.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", i))
                .AsUTF8Unsafe();

        // Attempt to add the de-duped name.
        if (album_images.insert(
                std::make_pair(deduped_filename, folder_path_.Append(filename)))
                .second) {
          break;
        }
      }
    }
  }

  const base::FilePath folder_path_;
  AlbumImagesMap* const albums_images_;
};

}  // namespace

PicasaAlbumsIndexer::PicasaAlbumsIndexer(const AlbumUIDSet& album_uids) {
  // Create an entry in the map for the valid album uids.
  for (AlbumUIDSet::const_iterator it = album_uids.begin();
       it != album_uids.end(); ++it) {
    albums_images_[*it] = AlbumImages();
  }
}

PicasaAlbumsIndexer::~PicasaAlbumsIndexer() {}

void PicasaAlbumsIndexer::ParseFolderINI(
    const std::vector<picasa::FolderINIContents>& folders_inis) {
  // Make a copy for sorting
  std::vector<picasa::FolderINIContents> folders_inis_sorted = folders_inis;

  // Sort here so image names are deduplicated in a stable ordering.
  std::sort(folders_inis_sorted.begin(), folders_inis_sorted.end());

  for (std::vector<picasa::FolderINIContents>::const_iterator it =
           folders_inis_sorted.begin();
       it != folders_inis_sorted.end();
       ++it) {
    PicasaINIParser parser(it->folder_path, &albums_images_);
    parser.Parse(it->ini_contents);
  }
}

}  // namespace picasa

/* [<][>][^][v][top][bottom][index][help] */