Skip to content

Commit

Permalink
Refactor|libdeng2: Archive and ZipArchive use PathTree for indexing
Browse files Browse the repository at this point in the history
Todo: PathTree does not yet allow removing nodes from the tree, which
is required by Archive.
  • Loading branch information
skyjake committed Nov 26, 2012
1 parent 0d2d31d commit e4fff12
Show file tree
Hide file tree
Showing 10 changed files with 673 additions and 596 deletions.
75 changes: 42 additions & 33 deletions doomsday/libdeng2/include/de/data/archive.h
Expand Up @@ -26,10 +26,9 @@
#include "../String"
#include "../Time"
#include "../File"
#include "../Zeroed"
#include "../PathTree"

#include <QSet>
#include <QMap>
#include <set>

namespace de
{
Expand Down Expand Up @@ -74,14 +73,17 @@ namespace de
public:
/// Base class for format-related errors. @ingroup errors
DENG2_ERROR(FormatError);


/// Provided path was not valid. @ingroup errors
DENG2_ERROR(InvalidPathError);

/// The requested entry does not exist in the archive. @ingroup errors
DENG2_ERROR(NotFoundError);

/// There is an error related to content processing. @ingroup errors
DENG2_ERROR(ContentError);

typedef QSet<String> Names;
typedef std::set<String> Names; // alphabetical order

public:
/**
Expand Down Expand Up @@ -131,27 +133,28 @@ namespace de
*
* @return @c true or @c false.
*/
bool has(String const &path) const;
bool has(Path const &path) const;

/**
* List the files in a specific folder of the archive.
*
* @param folder Folder path to look in.
* @param names Entry names collected in a set. The names are relative to a
* @a folder and are in alphabetical order.
*
* @return Entry names collected in a set. The names are relative to a
* @a folder.
* @return Number of names returned in @a names.
*/
Names listFiles(String const &folder = "") const;
dint listFiles(Names &names, Path const &folder = Path()) const;

/**
* List the folders in a specific folder of the archive.
*
* @param folder Folder path to look in.
*
* @return Folder entry names collected in a set. The names are
* relative to @a folder.
* @param names Folder entry names collected in a set. The names are
* relative to @a folder and are in alphabetical order.
* @return Number of names returned in @a names.
*/
Names listFolders(String const &folder = "") const;
dint listFolders(Names &names, Path const &folder = Path()) const;

/**
* Returns information about the specified path.
Expand All @@ -160,7 +163,7 @@ namespace de
*
* @return Type, size, and other metadata about the entry.
*/
File::Status status(String const &path) const;
File::Status status(Path const &path) const;

/**
* Returns the deserialized data of an entry for read-only access. The
Expand All @@ -176,7 +179,7 @@ namespace de
*
* @return Immutable contents of the entry.
*/
Block const &entryBlock(String const &path) const;
Block const &entryBlock(Path const &path) const;

/**
* Returns the deserialized data of an entry for read and write access.
Expand All @@ -191,7 +194,7 @@ namespace de
*
* @return Modifiable contents of the entry.
*/
Block &entryBlock(String const &path);
Block &entryBlock(Path const &path);

/**
* Adds an entry to the archive. The entry will not be committed to the
Expand All @@ -200,15 +203,15 @@ namespace de
* @param path Path of the entry within the archive.
* @param data Data of the entry.
*/
void add(String const &path, IByteArray const &data);
void add(Path const &path, IByteArray const &data);

/**
* Removes an entry from the archive. If there is deserialized data for
* the entry in memory, it will be deleted.
*
* @param path Path of the entry.
*/
void remove(String const &path);
void remove(Path const &path);

/**
* Clears the index of the archive. All entries are deleted.
Expand Down Expand Up @@ -240,7 +243,7 @@ namespace de
* Interface for derived classes:
*/
/// Base class for archive entries.
struct Entry
struct Entry : public PathTree::Node
{
dsize offset; ///< Offset from the start of the source array.
dsize size; ///< Deserialized size.
Expand All @@ -252,10 +255,15 @@ namespace de
Block *data;

/// Cached copy of the serialized data. Can be @c NULL. Entry has ownership.
mutable Block *dataInArchive;
Block mutable *dataInArchive;

Entry() : offset(0), size(0), sizeInArchive(0), maybeChanged(false),
data(0), dataInArchive(0)
Entry(PathTree::NodeArgs const &args) : Node(args),
offset(0),
size(0),
sizeInArchive(0),
maybeChanged(false),
data(0),
dataInArchive(0)
{}

virtual ~Entry()
Expand All @@ -266,15 +274,14 @@ namespace de
}
};

typedef QMap<String, Entry *> Index;

/**
* Constructs a new entry. Subclass can extend Entry with more data if
* necessary.
* Sets the index used by the Archive. A concrete subclass must call
* this in their constructor; Archive does not create an index on its
* own.
*
* @return New entry, ownership given to the caller.
* @param tree PathTree with entries of suitable type. Ownership given to Archive.
*/
virtual Entry *newEntry() = 0;
void setIndex(PathTree *tree);

/**
* Reads an entry from the source archive. The implementation of this
Expand All @@ -285,23 +292,25 @@ namespace de
* @param path Path of the entry within the archive.
* @param data Data is written here.
*/
virtual void readFromSource(Entry const *entry, String const &path, IBlock &data) const = 0;
virtual void readFromSource(Entry const &entry, Path const &path, IBlock &data) const = 0;

/**
* Inserts an entry into the archive's index.
* Inserts an entry into the archive's index. If the path already
* exists in the index, the old entry is deleted first.
*
* @param path Path of the entry.
* @param entry Entry to insert. Ownership given to Archive.
*
* @return Inserted entry.
*/
void insertToIndex(String const &path, Entry *entry);
Entry &insertEntry(Path const &path);

/**
* Returns the full entry index so that derived classes can iterate the
* entries.
*
* @return Entry index.
*/
Index const &index() const;
PathTree const &index() const;

private:
struct Instance;
Expand Down
8 changes: 8 additions & 0 deletions doomsday/libdeng2/include/de/data/path.h
Expand Up @@ -145,6 +145,14 @@ class DENG2_PUBLIC Path : public ISerializable, public LogEntry::Arg::Base
*/
Path(String const &path, QChar sep = '/');

/**
* Construct a path from a UTF-8 C-style string.
*
* @param nullTerminatedCStr Path to be parsed. All white space is included in the path.
* @param sep Character used to separate path segments.
*/
Path(char const *nullTerminatedCStr, char sep = '/');

/**
* Construct a path by duplicating @a other.
*/
Expand Down

0 comments on commit e4fff12

Please sign in to comment.