Skip to content

Commit

Permalink
Refactor: PathTree specialization
Browse files Browse the repository at this point in the history
There is now a way to specialize PathTree with custom nodes. libdeng2
provides some basic utilities:

- PathTreeT<> template
- UserDataNode (node with a user value and pointer)
- UserDataPathTree (typedef of PathTreeT<UserDataNode>)
- PathTreeIterator<> template for iterating path tree nodes (Qt style)

Updated engine to use UserDataPathTree and PathTreeIterator<> where
appropriate.
  • Loading branch information
skyjake committed Nov 25, 2012
1 parent 4102d48 commit 0d2d31d
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 110 deletions.
2 changes: 1 addition & 1 deletion doomsday/engine/src/con_data.cpp
Expand Up @@ -40,7 +40,7 @@
// Substrings in CVar names are delimited by this character.
#define CVARDIRECTORY_DELIMITER '-'

typedef de::PathTree CVarDirectory;
typedef de::UserDataPathTree CVarDirectory;

D_CMD(HelpWhat);
D_CMD(HelpApropos);
Expand Down
8 changes: 4 additions & 4 deletions doomsday/engine/src/filesys/fs_scheme.cpp
Expand Up @@ -172,10 +172,10 @@ struct FS1::Scheme::Instance

/// Associated path directory.
/// @todo It should not be necessary for a unique directory per scheme.
PathTree directory;
UserDataPathTree directory;

/// As the directory is relative, this special node serves as the root.
PathTree::Node* rootNode;
UserDataNode* rootNode;

/// Name hash table.
NameHash nameHash;
Expand Down Expand Up @@ -227,7 +227,7 @@ struct FS1::Scheme::Instance
}
}

PathTree::Node* addDirectoryPathNodes(String path)
UserDataNode* addDirectoryPathNodes(String path)
{
if(path.isEmpty()) return 0;

Expand Down Expand Up @@ -283,7 +283,7 @@ struct FS1::Scheme::Instance
String filePath, bool /*isFolder*/, int flags)
{
// Add this path to the directory.
PathTree::Node* node = addDirectoryPathNodes(filePath);
UserDataNode* node = addDirectoryPathNodes(filePath);
if(!node) return;

if(!node->isLeaf())
Expand Down
4 changes: 2 additions & 2 deletions doomsday/engine/src/resource/fonts.cpp
Expand Up @@ -40,7 +40,7 @@
#include "resource/fonts.h"
#include "resource/bitmapfont.h"

typedef de::PathTree FontRepository;
typedef de::UserDataPathTree FontRepository;

/**
* FontRecord. Stores metadata for a unique Font in the collection.
Expand Down Expand Up @@ -98,7 +98,7 @@ static inline FontRepository* repositoryBySchemeId(fontschemeid_t id)
return schemes[id - FONTSCHEME_FIRST].repository;
}

static fontschemeid_t schemeIdForRepository(FontRepository& pt)
static fontschemeid_t schemeIdForRepository(de::PathTree const &pt)
{
for(uint i = uint(FONTSCHEME_FIRST); i <= uint(FONTSCHEME_LAST); ++i)
{
Expand Down
21 changes: 12 additions & 9 deletions doomsday/engine/src/resource/materials.cpp
Expand Up @@ -47,7 +47,7 @@
/// Number of elements to block-allocate in the material index to materialbind map.
#define MATERIALS_BINDINGMAP_BLOCK_ALLOC (32)

typedef de::PathTree MaterialRepository;
typedef de::UserDataPathTree MaterialRepository;

/**
* Contains extended info about a material binding (see MaterialBind).
Expand Down Expand Up @@ -248,7 +248,7 @@ static inline MaterialRepository& schemeById(materialschemeid_t id)
return *schemes[id-MATERIALSCHEME_FIRST];
}

static materialschemeid_t schemeIdForDirectory(MaterialRepository& directory)
static materialschemeid_t schemeIdForDirectory(de::PathTree const &directory)
{
for(uint i = uint(MATERIALSCHEME_FIRST); i <= uint(MATERIALSCHEME_LAST); ++i)
{
Expand Down Expand Up @@ -582,13 +582,14 @@ static void destroyBindings(void)
{
if(!schemes[i]) continue;

DENG2_FOR_EACH_CONST(MaterialRepository::Nodes, nodeIt, schemes[i]->leafNodes())
de::PathTreeIterator<MaterialRepository> iter(schemes[i]->leafNodes());
while(iter.hasNext())
{
MaterialBind* mb = reinterpret_cast<MaterialBind*>((*nodeIt)->userPointer());
MaterialBind* mb = reinterpret_cast<MaterialBind*>(iter.next().userPointer());
if(mb)
{
// Detach our user data from this node.
(*nodeIt)->setUserPointer(0);
iter.value().setUserPointer(0);
delete mb;
}
}
Expand Down Expand Up @@ -681,9 +682,10 @@ void Materials_ClearDefinitionLinks(void)
{
MaterialRepository& matDirectory = schemeById(materialschemeid_t(i));

DENG2_FOR_EACH_CONST(MaterialRepository::Nodes, nodeIt, matDirectory.leafNodes())
de::PathTreeIterator<MaterialRepository> iter(matDirectory.leafNodes());
while(iter.hasNext())
{
MaterialBind* mb = reinterpret_cast<MaterialBind*>((*nodeIt)->userPointer());
MaterialBind* mb = reinterpret_cast<MaterialBind*>(iter.next().userPointer());
if(mb)
{
clearBindingDefinitionLinks(mb);
Expand Down Expand Up @@ -1515,9 +1517,10 @@ static MaterialRepository::Node** collectDirectoryNodes(materialschemeid_t schem
{
MaterialRepository& matDirectory = schemeById(materialschemeid_t(i));

DENG2_FOR_EACH_CONST(MaterialRepository::Nodes, nodeIt, matDirectory.leafNodes())
de::PathTreeIterator<MaterialRepository> iter(matDirectory.leafNodes());
while(iter.hasNext())
{
MaterialRepository::Node& node = **nodeIt;
MaterialRepository::Node& node = iter.next();
if(!like.isEmpty())
{
de::String path = node.composePath();
Expand Down
42 changes: 24 additions & 18 deletions doomsday/engine/src/resource/textures.cpp
Expand Up @@ -39,7 +39,7 @@
#include <de/memory.h>
#include <de/memoryzone.h>

typedef de::PathTree TextureRepository;
typedef de::UserDataPathTree TextureRepository;

/**
* POD object. Contains metadata for a unique Texture in the collection.
Expand Down Expand Up @@ -107,7 +107,7 @@ static inline TextureRepository& schemeById(textureschemeid_t id)
return *schemes[id-TEXTURESCHEME_FIRST].directory;
}

static textureschemeid_t schemeIdForDirectory(TextureRepository const& directory)
static textureschemeid_t schemeIdForDirectory(de::PathTree const &directory)
{
for(uint i = uint(TEXTURESCHEME_FIRST); i <= uint(TEXTURESCHEME_LAST); ++i)
{
Expand Down Expand Up @@ -449,9 +449,10 @@ void Textures_Shutdown(void)

if(tn->directory)
{
DENG2_FOR_EACH_CONST(TextureRepository::Nodes, nodeIt, tn->directory->leafNodes())
de::PathTreeIterator<TextureRepository> iter(tn->directory->leafNodes());
while(iter.hasNext())
{
destroyRecord(*reinterpret_cast<TextureRepository::Node*>(*nodeIt));
destroyRecord(iter.next());
}
delete tn->directory; tn->directory = 0;
}
Expand Down Expand Up @@ -613,9 +614,10 @@ void Textures_ClearScheme(textureschemeid_t schemeId)
textureschemeid_t iter = textureschemeid_t(i);
TextureScheme* tn = &schemes[iter - TEXTURESCHEME_FIRST];

DENG2_FOR_EACH_CONST(TextureRepository::Nodes, nodeIt, tn->directory->leafNodes())
de::PathTreeIterator<TextureRepository> it(tn->directory->leafNodes());
while(it.hasNext())
{
TextureRepository::Node& node = **nodeIt;
TextureRepository::Node& node = it.next();
destroyBoundTexture(node);
destroyRecord(node);
}
Expand Down Expand Up @@ -663,9 +665,10 @@ static void findUniqueIdBounds(TextureScheme* tn, int* minId, int* maxId)
if(minId) *minId = DDMAXINT;
if(maxId) *maxId = DDMININT;

DENG2_FOR_EACH_CONST(TextureRepository::Nodes, i, tn->directory->leafNodes())
de::PathTreeIterator<TextureRepository> iter(tn->directory->leafNodes());
while(iter.hasNext())
{
TextureRecord const* record = reinterpret_cast<TextureRecord*>((*i)->userPointer());
TextureRecord const* record = reinterpret_cast<TextureRecord*>(iter.next().userPointer());
if(!record) continue;

if(minId && record->uniqueId < *minId) *minId = record->uniqueId;
Expand Down Expand Up @@ -710,9 +713,10 @@ static void rebuildUniqueIdMap(textureschemeid_t schemeId)
{
memset(tn->uniqueIdMap, NOTEXTUREID, sizeof(*tn->uniqueIdMap) * tn->uniqueIdMapSize);

DENG2_FOR_EACH_CONST(TextureRepository::Nodes, i, tn->directory->leafNodes())
de::PathTreeIterator<TextureRepository> iter(tn->directory->leafNodes());
while(iter.hasNext())
{
TextureRepository::Node& node = **i;
TextureRepository::Node& node = iter.next();
TextureRecord const* record = reinterpret_cast<TextureRecord*>(node.userPointer());
if(!record) continue;
linkRecordInUniqueIdMap(record, tn, findBindIdForDirectoryNode(node));
Expand Down Expand Up @@ -1108,9 +1112,10 @@ int Textures_Iterate2(textureschemeid_t schemeId,
{
TextureRepository& directory = schemeById(textureschemeid_t(i));

DENG2_FOR_EACH_CONST(TextureRepository::Nodes, nodeIt, directory.leafNodes())
de::PathTreeIterator<TextureRepository> iter(directory.leafNodes());
while(iter.hasNext())
{
TextureRecord* record = reinterpret_cast<TextureRecord*>((*nodeIt)->userPointer());
TextureRecord* record = reinterpret_cast<TextureRecord*>(iter.next().userPointer());
if(!record || !record->texture) continue;

int result = callback(record->texture, parameters);
Expand Down Expand Up @@ -1146,10 +1151,10 @@ int Textures_IterateDeclared2(textureschemeid_t schemeId,
{
TextureRepository& directory = schemeById(textureschemeid_t(i));

DENG2_FOR_EACH_CONST(TextureRepository::Nodes, nodeIt, directory.leafNodes())
de::PathTreeIterator<TextureRepository> iter(directory.leafNodes());
while(iter.hasNext())
{
TextureRepository::Node& node = **nodeIt;
TextureRecord* record = reinterpret_cast<TextureRecord*>(node.userPointer());
TextureRecord* record = reinterpret_cast<TextureRecord*>(iter.next().userPointer());
if(!record) continue;

// If we have bound a texture it can provide the id.
Expand All @@ -1159,7 +1164,7 @@ int Textures_IterateDeclared2(textureschemeid_t schemeId,

// Otherwise look it up.
if(!validTextureId(textureId))
textureId = findBindIdForDirectoryNode(node);
textureId = findBindIdForDirectoryNode(iter.value());

// Sanity check.
DENG2_ASSERT(validTextureId(textureId));
Expand Down Expand Up @@ -1261,9 +1266,10 @@ static TextureRepository::Node** collectDirectoryNodes(textureschemeid_t schemeI
{
TextureRepository& directory = schemeById(textureschemeid_t(i));

DENG2_FOR_EACH_CONST(TextureRepository::Nodes, nodeIt, directory.leafNodes())
de::PathTreeIterator<TextureRepository> iter(directory.leafNodes());
while(iter.hasNext())
{
TextureRepository::Node& node = **nodeIt;
TextureRepository::Node& node = iter.next();
if(!like.isEmpty())
{
de::String path = node.composePath();
Expand Down
12 changes: 6 additions & 6 deletions doomsday/engine/src/resource/wad.cpp
Expand Up @@ -181,10 +181,10 @@ struct Wad::Instance
size_t arcRecordsOffset;

/// Directory containing structure and info records for all lumps.
PathTree* lumpDirectory;
UserDataPathTree* lumpDirectory;

/// LUT which maps logical lump indices to PathTreeNodes.
typedef std::vector<PathTree::Node*> LumpNodeLut;
typedef std::vector<UserDataNode*> LumpNodeLut;
LumpNodeLut* lumpNodeLut;

/// Lump data cache.
Expand Down Expand Up @@ -221,7 +221,7 @@ struct Wad::Instance
if(lumpCache) delete lumpCache;
}

static int clearWadFileWorker(PathTree::Node& node, void* /*parameters*/)
static int clearWadFileWorker(UserDataNode& node, void* /*parameters*/)
{
WadFile* lump = reinterpret_cast<WadFile*>(node.userPointer());
if(lump)
Expand Down Expand Up @@ -313,7 +313,7 @@ struct Wad::Instance
Str_Reserve(Str_Init(&absPath), LUMPNAME_T_LASTINDEX + 4/*.lmp*/);

// Intialize the directory.
lumpDirectory = new PathTree(PathTree::MultiLeaf);
lumpDirectory = new UserDataPathTree(PathTree::MultiLeaf);

// Build our runtime representation from the archived lump directory.
wadlumprecord_t const* arcRecord = arcRecords;
Expand All @@ -335,7 +335,7 @@ struct Wad::Instance
littleEndianByteOrder.toNative(arcRecord->size),
littleEndianByteOrder.toNative(arcRecord->size)),
self);
PathTree::Node* node = lumpDirectory->insert(Path(Str_Text(&absPath)));
UserDataNode* node = lumpDirectory->insert(Path(Str_Text(&absPath)));
node->setUserPointer(lump);
}

Expand All @@ -345,7 +345,7 @@ struct Wad::Instance
delete[] arcRecords;
}

static int buildLumpNodeLutWorker(PathTree::Node& node, void* parameters)
static int buildLumpNodeLutWorker(UserDataNode& node, void* parameters)
{
Instance* wadInst = (Instance*)parameters;
WadFile* lump = reinterpret_cast<WadFile*>(node.userPointer());
Expand Down
12 changes: 6 additions & 6 deletions doomsday/engine/src/resource/zip.cpp
Expand Up @@ -228,10 +228,10 @@ struct Zip::Instance
Zip* self;

/// Directory containing structure and info records for all lumps.
PathTree* lumpDirectory;
UserDataPathTree* lumpDirectory;

/// LUT which maps logical lump indices to PathTreeNodes.
typedef std::vector<PathTree::Node*> LumpNodeLut;
typedef std::vector<UserDataNode*> LumpNodeLut;
LumpNodeLut* lumpNodeLut;

/// Lump data cache.
Expand All @@ -253,7 +253,7 @@ struct Zip::Instance
if(lumpCache) delete lumpCache;
}

static int clearZipFileWorker(PathTree::Node& node, void* /*parameters*/)
static int clearZipFileWorker(UserDataNode& node, void* /*parameters*/)
{
ZipFile* rec = reinterpret_cast<ZipFile*>(node.userPointer());
if(rec)
Expand Down Expand Up @@ -376,7 +376,7 @@ struct Zip::Instance
if(entryCount == 0) break;

// Intialize the directory.
lumpDirectory = new PathTree(PathTree::MultiLeaf);
lumpDirectory = new UserDataPathTree(PathTree::MultiLeaf);
}

// Position the read cursor at the start of the buffered central centralDirectory.
Expand Down Expand Up @@ -470,7 +470,7 @@ struct Zip::Instance
lumpIdx, baseOffset, ULONG(header->size),
compressedSize),
self);
PathTree::Node* node = lumpDirectory->insert(filePath);
UserDataNode* node = lumpDirectory->insert(filePath);
node->setUserPointer(record);

lumpIdx++;
Expand All @@ -481,7 +481,7 @@ struct Zip::Instance
M_Free(centralDirectory);
}

static int buildLumpNodeLutWorker(PathTree::Node& node, void* parameters)
static int buildLumpNodeLutWorker(UserDataNode& node, void* parameters)
{
Instance* zipInst = (Instance*)parameters;
ZipFile* lumpRecord = reinterpret_cast<ZipFile*>(node.userPointer());
Expand Down

0 comments on commit 0d2d31d

Please sign in to comment.