// AT TOP:#include <iostream>#include <cstring>#include <string>#include <vector>#include <map>using namespace std;#include <boost/shared_ptr.hpp>using namespace boost;#include "archivereader.h"#include <strigi/strigiconfig.h>// [ ... ]/** * @brief A cache for entries that have already been found. * @internal * * The cache is stored in a tree, sorted on the path in the URL * (with @c / as the delimiter). */class ArchiveEntryCache {public: class SubEntry; typedef boost::shared_ptr<ArchiveEntryCache::SubEntry> SubEntryPtr; class RootSubEntry; typedef boost::shared_ptr<ArchiveEntryCache::RootSubEntry> RootSubEntryPtr; /** * @brief Represents an entry in the cache. */ class SubEntry { public: /** The cached information about this entry. */ EntryInfo entry; /** A list of subentries of this entry. */ //can't define staticly constructed object while object is being defined std::map<std::string, ArchiveEntryCache::SubEntryPtr> entries; /** * @brief The number of entries in the cache below and including * this one. * * @return the size of the tree rooted at this node */ int32_t count() const; /** Constructor */ SubEntry() { } /** Destructor */ virtual ~SubEntry() {} }; /** * @brief Represents a top-level entry in the cache */ class RootSubEntry : public SubEntry { public: /** Constructor */ RootSubEntry() : SubEntry(), indexed(false) { } /** Whether this entry and its subentries have been indexed yet */ bool indexed; }; /** * @brief The cache itself. * * Contains all the root entries in the cache. */ std::map<std::string, ArchiveEntryCache::RootSubEntryPtr> cache; // most vexing - this doesn't seem to be defined anywhere // and yet... it compiles. Why? Perhaps because it isn't // called from anywhere... // You'd have thought you'd get a warning, though. // Go figure. std::vector<EntryInfo> entries(const std::string& url); /** * @brief Find an entry in the cache by its URL * * @param url the url of the entry * @return a pointer to the entry, if it is in the cache, * 0 if the entry is not in the cache */ const ArchiveEntryCache::SubEntryPtr findEntry(const std::string& url) const; /** * @brief Finds the root subentry in the cache of the given url, * if it is in the cache * * This finds the RootSubEntry (tree root) that the SubEntry for the * given url either is or should be stored under. If there is no * suitable RootSubEntry in the cache, cache.end() is returned. * * @param url the url of the object to find the root entry for * @return an iterator to the root entry */ std::map<std::string, RootSubEntryPtr>::const_iterator findRootEntry(const string& url) const; /** * @brief Print a text representation of the cache to stdout. * For debugging purposes. */ void print() const; static SubEntryPtr nullSubEntryPtr; static RootSubEntryPtr nullRootSubEntryPtr;};ArchiveEntryCache::SubEntryPtr nullSubEntryPtr = ArchiveEntryCache::SubEntryPtr();ArchiveEntryCache::RootSubEntryPtr nullRootSubEntryPtr = ArchiveEntryCache::RootSubEntryPtr();voidArchiveEntryCache::print() const { std::map<std::string, ArchiveEntryCache::RootSubEntryPtr>::const_iterator j; for (j = cache.begin(); j != cache.end(); ++j) { std::cout << "x" << j->first.c_str() << " " << endl; std::map<std::string, SubEntryPtr>::const_iterator i; for (i = j->second->entries.begin(); i != j->second->entries.end(); ++i) { std::cout << "- s " << i->second->entry.filename.c_str() << " " << endl; } std::cout << endl; }}int32_tArchiveEntryCache::SubEntry::count() const { int32_t count = 1; std::map<std::string, SubEntryPtr>::const_iterator i; for (i = entries.begin(); i != entries.end(); ++i) { count += i->second->count(); } return count;}std::map<string, ArchiveEntryCache::RootSubEntryPtr>::const_iteratorArchiveEntryCache::findRootEntry(const string& url) const { std::string n = url; std::string::size_type p = n.size(); std::map<std::string, ArchiveEntryCache::RootSubEntryPtr>::const_iterator i; do { i = cache.find(n); if (i != cache.end()) { // it's a root entry in the cache - we're done return i; } // remove the last element in the path, and look for that p = n.rfind('/'); if (p != string::npos) { n = n.substr(0, p); } } while (p != string::npos); // couldn't find it return cache.end();}const ArchiveEntryCache::SubEntryPtrArchiveEntryCache::findEntry(const string& url) const { std::map<std::string, ArchiveEntryCache::RootSubEntryPtr>::const_iterator ei = findRootEntry(url); if (ei == cache.end()) return ArchiveEntryCache::nullSubEntryPtr; if (ei->first == url) { return ei->second; } ArchiveEntryCache::SubEntryPtr e = ei->second; map<std::string, ArchiveEntryCache::SubEntryPtr>::const_iterator i; size_t p = ei->first.length(); std::string name; do { size_t np = url.find('/', p+1); name.clear(); if (np == string::npos) { name = url.substr(p+1); } else { name = url.substr(p+1, np-p-1); } i = e->entries.find(name); if (i == e->entries.end()) { e = ArchiveEntryCache::nullSubEntryPtr; } else { e = i->second; p = np; } if (p == url.length()) { return e; } } while(e && p != string::npos); return e;}// and so on ...