All pastes #808123 Raw Edit

archivereader.cpp

public cpp v1 · immutable
·published 2007-12-07 08:52 UTC
rendered paste body
/** * @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 ...