diff --git a/doomsday/engine/engine.pro b/doomsday/engine/engine.pro index 5e8e4cd1fa..b405643358 100644 --- a/doomsday/engine/engine.pro +++ b/doomsday/engine/engine.pro @@ -556,7 +556,7 @@ SOURCES += \ portable/src/p_sight.c \ portable/src/p_think.c \ portable/src/p_ticker.c \ - portable/src/pathmap.c \ + portable/src/pathmap.cpp \ portable/src/pathtree.cpp \ portable/src/pathtreenode.cpp \ portable/src/plane.c \ diff --git a/doomsday/engine/portable/include/pathmap.h b/doomsday/engine/portable/include/pathmap.h index e9396c9123..5179ef27b8 100644 --- a/doomsday/engine/portable/include/pathmap.h +++ b/doomsday/engine/portable/include/pathmap.h @@ -65,7 +65,7 @@ typedef struct pathmapfragment_s { * * @return The resultant hash key. */ -typedef ushort (*hashpathfragmentcallback_t)(char const* path, size_t len, char delimiter); +typedef ushort (*hashpathfragmentfunc_t)(char const* path, size_t len, char delimiter); typedef struct pathmap_s { char const* path; ///< The mapped path. @@ -88,8 +88,13 @@ typedef struct pathmap_s { ///< Head of the linked list of "extra" fragments, in reverse order. PathMapFragment* extraFragments; - /// Path fragment hashing callback. - hashpathfragmentcallback_t hashFragmentCallback; + /// Fragment hashing function. + hashpathfragmentfunc_t hashFragmentFunc; + +#ifdef __cplusplus + pathmap_s(hashpathfragmentfunc_t hashFragmentFunc, char const* path, char delimiter = '/'); + ~pathmap_s(); +#endif } PathMap; /** @@ -108,8 +113,8 @@ typedef struct pathmap_s { * * @return Pointer to "this" instance for caller convenience. */ -PathMap* PathMap_Initialize2(PathMap* pathMap, hashpathfragmentcallback_t hashFragmentCallback, char const* path, char delimiter); -PathMap* PathMap_Initialize(PathMap* pathMap, hashpathfragmentcallback_t hashFragmentCallback, char const* path/*, delimiter = '/'*/); +PathMap* PathMap_Initialize2(PathMap* pathMap, hashpathfragmentfunc_t hashFragmentFunc, char const* path, char delimiter); +PathMap* PathMap_Initialize(PathMap* pathMap, hashpathfragmentfunc_t hashFragmentFunc, char const* path/*, delimiter = '/'*/); /** * Destroy @a pathMap releasing any resources acquired for it. diff --git a/doomsday/engine/portable/include/pathtree.h b/doomsday/engine/portable/include/pathtree.h index 05ff93761a..47fd41604b 100644 --- a/doomsday/engine/portable/include/pathtree.h +++ b/doomsday/engine/portable/include/pathtree.h @@ -145,8 +145,14 @@ class PathTree /// @return Parent of this node else @c NULL Node* parent() const; + /// @return @c true iff this node is a leaf. + bool isLeaf() const; + /// @return Type of this node. - NodeType type() const; + inline NodeType type() const + { + return isLeaf()? Leaf : Branch; + } /// @return Name for this node's path fragment. ddstring_t const* name() const; @@ -181,7 +187,7 @@ class PathTree * allow for further optimizations elsewhere (in the file system * for example) -ds */ - int comparePath(PathMap* candidatePath, int flags) const; + int comparePath(PathMap& candidatePath, int flags) const; /** * Composes and/or calculates the length of the composed path for this node. diff --git a/doomsday/engine/portable/src/fs_main.cpp b/doomsday/engine/portable/src/fs_main.cpp index f2e0a4d845..fc47781099 100644 --- a/doomsday/engine/portable/src/fs_main.cpp +++ b/doomsday/engine/portable/src/fs_main.cpp @@ -926,8 +926,7 @@ int FS1::findAllPaths(char const* rawSearchPattern, int flags, FS1::PathList& fo // if not already absolute. F_PrependBasePath(searchPattern, searchPattern); - PathMap patternMap; - PathMap_Initialize(&patternMap, PathTree::hashPathFragment, Str_Text(searchPattern)); + PathMap patternMap = PathMap(PathTree::hashPathFragment, Str_Text(searchPattern)); /* * Check the Zip directory. @@ -946,7 +945,7 @@ int FS1::findAllPaths(char const* rawSearchPattern, int flags, FS1::PathList& fo } else { - patternMatched = node.comparePath(&patternMap, PCF_MATCH_FULL); + patternMatched = node.comparePath(patternMap, PCF_MATCH_FULL); } if(!patternMatched) continue; @@ -957,11 +956,9 @@ int FS1::findAllPaths(char const* rawSearchPattern, int flags, FS1::PathList& fo filePath = lump.composePath(); } - found.push_back(PathListItem(Str_Text(filePath), node.type() == PathTree::Branch? A_SUBDIR : 0)); + found.push_back(PathListItem(Str_Text(filePath), !node.isLeaf()? A_SUBDIR : 0)); } - PathMap_Destroy(&patternMap); - /* * Check the dir/WAD direcs. */ diff --git a/doomsday/engine/portable/src/lumpindex.cpp b/doomsday/engine/portable/src/lumpindex.cpp index 7fc09bdf6e..04137f64d7 100644 --- a/doomsday/engine/portable/src/lumpindex.cpp +++ b/doomsday/engine/portable/src/lumpindex.cpp @@ -385,34 +385,24 @@ lumpnum_t LumpIndex::indexForPath(char const* path) DENG_ASSERT(d->hashMap); // Perform the search. - bool builtSearchPattern = false; - PathMap searchPattern; int hash = PathTree::hashPathFragment(path, strlen(path)) % d->hashMap->size(); - int idx; - for(idx = (*d->hashMap)[hash].head; idx != -1; idx = (*d->hashMap)[idx].next) + if((*d->hashMap)[hash].head == -1) return -1; + + PathMap searchPattern = PathMap(PathTree::hashPathFragment, path); + + for(int idx = (*d->hashMap)[hash].head; idx != -1; idx = (*d->hashMap)[idx].next) { File1 const& lump = *d->lumps[idx]; PathTree::Node const& node = lump.directoryNode(); - // Time to build the pattern? - if(!builtSearchPattern) - { - PathMap_Initialize(&searchPattern, PathTree::hashPathFragment, path); - builtSearchPattern = true; - } + if(!node.comparePath(searchPattern, 0)) continue; - if(node.comparePath(&searchPattern, 0)) - { - // This is the lump we are looking for. - break; - } + // This is the lump we are looking for. + return idx; } - if(builtSearchPattern) - PathMap_Destroy(&searchPattern); - - return idx; + return -1; } void LumpIndex::print(LumpIndex const& index) diff --git a/doomsday/engine/portable/src/pathmap.c b/doomsday/engine/portable/src/pathmap.cpp similarity index 69% rename from doomsday/engine/portable/src/pathmap.c rename to doomsday/engine/portable/src/pathmap.cpp index e598cfe6e6..d9b15a6485 100644 --- a/doomsday/engine/portable/src/pathmap.c +++ b/doomsday/engine/portable/src/pathmap.cpp @@ -1,8 +1,9 @@ /** - * @file pathmap.c + * @file pathmap.cpp + * * Fragment map of a delimited string @ingroup fs * - * @authors Copyright © 2011-2012 Daniel Swanson + * @author Copyright © 2011-2012 Daniel Swanson * * @par License * GPL: http://www.gnu.org/licenses/gpl.html @@ -26,37 +27,32 @@ #include #include -static ushort PathMap_HashFragment(PathMap* pm, PathMapFragment* fragment) +static ushort PathMap_HashFragment(PathMap& pm, PathMapFragment& fragment) { - DENG_ASSERT(pm && fragment); // Is it time to compute the hash for this fragment? - if(fragment->hash == PATHTREE_NOHASH) + if(fragment.hash == PATHTREE_NOHASH) { - size_t fragmentLength = (fragment->to - fragment->from) + 1; - fragment->hash = pm->hashFragmentCallback(fragment->from, fragmentLength, pm->delimiter); + size_t fragmentLength = (fragment.to - fragment.from) + 1; + fragment.hash = pm.hashFragmentFunc(fragment.from, fragmentLength, pm.delimiter); } - return fragment->hash; + return fragment.hash; } /// @return @c true iff @a fragment comes from the static fragment buffer /// allocated along with @a pm. -static __inline boolean PathMap_IsStaticFragment(PathMap const* pm, PathMapFragment const* fragment) +static inline bool PathMap_IsStaticFragment(PathMap const& pm, PathMapFragment const& fragment) { - DENG_ASSERT(pm && fragment); - return fragment >= pm->fragmentBuffer && - fragment < (pm->fragmentBuffer + sizeof(*pm->fragmentBuffer) * PATHMAP_FRAGMENTBUFFER_SIZE); + return &fragment >= pm.fragmentBuffer && + &fragment < (pm.fragmentBuffer + sizeof(*pm.fragmentBuffer) * PATHMAP_FRAGMENTBUFFER_SIZE); } -static PathMapFragment* PathMap_AllocFragment(PathMap* pm) +static PathMapFragment* PathMap_AllocFragment(PathMap& pm) { - PathMapFragment* fragment; - - DENG_ASSERT(pm); - // Retrieve another fragment. - if(pm->fragmentCount < PATHMAP_FRAGMENTBUFFER_SIZE) + PathMapFragment* fragment; + if(pm.fragmentCount < PATHMAP_FRAGMENTBUFFER_SIZE) { - fragment = pm->fragmentBuffer + pm->fragmentCount; + fragment = pm.fragmentBuffer + pm.fragmentCount; } else { @@ -72,56 +68,52 @@ static PathMapFragment* PathMap_AllocFragment(PathMap* pm) fragment->parent = NULL; // There is now one more fragment in the map. - pm->fragmentCount += 1; + pm.fragmentCount += 1; return fragment; } -static void PathMap_MapAllFragments(PathMap* pm, char const* path, size_t pathLen) +static void PathMap_MapAllFragments(PathMap& pm, char const* path, size_t pathLen) { PathMapFragment* fragment = NULL; char const* begin = path; char const* to = begin + pathLen - 1; char const* from; - size_t i; - - DENG_ASSERT(pm); - pm->fragmentCount = 0; - pm->extraFragments = NULL; + pm.fragmentCount = 0; + pm.extraFragments = NULL; if(pathLen == 0) return; // Skip over any trailing delimiters. - for(i = pathLen; *to && *to == pm->delimiter && i-- > 0; to--) + for(size_t i = pathLen; *to && *to == pm.delimiter && i-- > 0; to--) {} // Scan for discreet fragments in the path, in reverse order. - for(;;) + forever { // Find the start of the next path fragment. - for(from = to; from > begin && !(*from == pm->delimiter); from--) + for(from = to; from > begin && !(*from == pm.delimiter); from--) {} - { PathMapFragment* newFragment = PathMap_AllocFragment(pm); + PathMapFragment* newFragment = PathMap_AllocFragment(pm); // If this is an "extra" fragment, link it to the tail of the list. - if(!PathMap_IsStaticFragment(pm, newFragment)) + if(!PathMap_IsStaticFragment(pm, *newFragment)) { - if(!pm->extraFragments) + if(!pm.extraFragments) { - pm->extraFragments = newFragment; + pm.extraFragments = newFragment; } else { - fragment->parent = pm->extraFragments; + fragment->parent = pm.extraFragments; } } fragment = newFragment; - } - fragment->from = (*from == pm->delimiter? from + 1 : from); + fragment->from = (*from == pm.delimiter? from + 1 : from); fragment->to = to; // Are there no more parent directories? @@ -133,28 +125,37 @@ static void PathMap_MapAllFragments(PathMap* pm, char const* path, size_t pathLe } // Deal with the special case of a Unix style zero-length root name. - if(*begin == pm->delimiter) + if(*begin == pm.delimiter) { fragment = PathMap_AllocFragment(pm); fragment->from = fragment->to = ""; } } -static void PathMap_ClearFragments(PathMap* pm) +static void PathMap_ClearFragments(PathMap& pm) { - DENG_ASSERT(pm); - while(pm->extraFragments) + while(pm.extraFragments) { - PathMapFragment* next = pm->extraFragments->parent; - M_Free(pm->extraFragments); - pm->extraFragments = next; + PathMapFragment* next = pm.extraFragments->parent; + M_Free(pm.extraFragments); + pm.extraFragments = next; } } +pathmap_s::pathmap_s(hashpathfragmentfunc_t hashFragmentFunc, char const* path, char delimiter) +{ + PathMap_Initialize2(this, hashFragmentFunc, path, delimiter); +} + +pathmap_s::~pathmap_s() +{ + PathMap_Destroy(this); +} + PathMap* PathMap_Initialize2(PathMap* pm, - hashpathfragmentcallback_t hashFragmentCallback, char const* path, char delimiter) + hashpathfragmentfunc_t hashFragmentFunc, char const* path, char delimiter) { - DENG_ASSERT(pm && hashFragmentCallback); + DENG_ASSERT(pm && hashFragmentFunc); #if _DEBUG // Perform unit tests. @@ -163,10 +164,10 @@ PathMap* PathMap_Initialize2(PathMap* pm, pm->path = path; pm->delimiter = delimiter; - pm->hashFragmentCallback = hashFragmentCallback; + pm->hashFragmentFunc = hashFragmentFunc; // Create the fragment map of the path. - PathMap_MapAllFragments(pm, pm->path, pm->path? strlen(pm->path) : 0); + PathMap_MapAllFragments(*pm, pm->path, pm->path? strlen(pm->path) : 0); // Hash the first (i.e., rightmost) fragment right away. PathMap_Fragment(pm, 0); @@ -175,14 +176,15 @@ PathMap* PathMap_Initialize2(PathMap* pm, } PathMap* PathMap_Initialize(PathMap* pm, - hashpathfragmentcallback_t hashFragmentCallback, char const* path) + hashpathfragmentfunc_t hashFragmentCallback, char const* path) { return PathMap_Initialize2(pm, hashFragmentCallback, path, '/'); } void PathMap_Destroy(PathMap* pm) { - PathMap_ClearFragments(pm); + DENG_ASSERT(pm); + PathMap_ClearFragments(*pm); } uint PathMap_Size(PathMap* pm) @@ -193,12 +195,11 @@ uint PathMap_Size(PathMap* pm) PathMapFragment* PathMap_Fragment(PathMap* pm, uint idx) { - PathMapFragment* fragment; - DENG_ASSERT(pm); if(idx >= pm->fragmentCount) return NULL; + PathMapFragment* fragment; if(idx < PATHMAP_FRAGMENTBUFFER_SIZE) { fragment = pm->fragmentBuffer + idx; @@ -212,26 +213,23 @@ PathMapFragment* PathMap_Fragment(PathMap* pm, uint idx) fragment = fragment->parent; } } - PathMap_HashFragment(pm, fragment); + PathMap_HashFragment(*pm, *fragment); return fragment; } #if _DEBUG static ushort hashPathFragment(char const* fragment, size_t len, char delimiter) { - ushort key = 0; - char const* c; - int op; - DENG2_ASSERT(fragment); // Skip over any trailing delimiters. - c = fragment + len - 1; + char const* c = fragment + len - 1; while(c >= fragment && *c && *c == delimiter) { c--; } // Compose the hash. - op = 0; + int op = 0; + ushort key = 0; for(; c >= fragment && *c && *c != delimiter; c--) { switch(op) @@ -246,22 +244,23 @@ static ushort hashPathFragment(char const* fragment, size_t len, char delimiter) void PathMap_Test(void) { - static boolean alreadyTested = false; + static bool alreadyTested = false; PathMapFragment const* fragment; size_t len; - PathMap pm; if(alreadyTested) return; alreadyTested = true; // Test a zero-length path. - PathMap_Initialize(&pm, hashPathFragment, ""); + { + PathMap pm = PathMap(hashPathFragment, ""); DENG_ASSERT(PathMap_Size(&pm) == 0); - PathMap_Destroy(&pm); + } // Test a Windows style path with a drive plus file path. - PathMap_Initialize(&pm, hashPathFragment, "c:/something.ext"); + { + PathMap pm = PathMap(hashPathFragment, "c:/something.ext"); DENG_ASSERT(PathMap_Size(&pm) == 2); fragment = PathMap_Fragment(&pm, 0); @@ -273,11 +272,11 @@ void PathMap_Test(void) len = fragment->to - fragment->from; DENG_ASSERT(len == 1); DENG_ASSERT(!strncmp(fragment->from, "c:", len+1)); - - PathMap_Destroy(&pm); + } // Test a Unix style path with a zero-length root node name. - PathMap_Initialize(&pm, hashPathFragment, "/something.ext"); + { + PathMap pm = PathMap(hashPathFragment, "/something.ext"); DENG_ASSERT(PathMap_Size(&pm) == 2); fragment = PathMap_Fragment(&pm, 0); @@ -289,11 +288,11 @@ void PathMap_Test(void) len = fragment->to - fragment->from; DENG_ASSERT(len == 0); DENG_ASSERT(!strncmp(fragment->from, "", len)); - - PathMap_Destroy(&pm); + } // Test a relative directory. - PathMap_Initialize(&pm, hashPathFragment, "some/dir/structure/"); + { + PathMap pm = PathMap(hashPathFragment, "some/dir/structure/"); DENG_ASSERT(PathMap_Size(&pm) == 3); fragment = PathMap_Fragment(&pm, 0); @@ -310,7 +309,6 @@ void PathMap_Test(void) len = fragment->to - fragment->from; DENG_ASSERT(len == 3); DENG_ASSERT(!strncmp(fragment->from, "some", len+1)); - - PathMap_Destroy(&pm); + } } #endif diff --git a/doomsday/engine/portable/src/pathtree.cpp b/doomsday/engine/portable/src/pathtree.cpp index 94bcae8bad..2419a0f607 100644 --- a/doomsday/engine/portable/src/pathtree.cpp +++ b/doomsday/engine/portable/src/pathtree.cpp @@ -362,8 +362,7 @@ PathTree::Node& PathTree::find(int flags, const char* searchPath, char delimiter PathTree::Node* foundNode = NULL; if(searchPath && searchPath[0] && d->size) { - PathMap mappedSearchPath; - PathMap_Initialize2(&mappedSearchPath, PathTree_HashPathFragment2, searchPath, delimiter); + PathMap mappedSearchPath = PathMap(PathTree_HashPathFragment2, searchPath, delimiter); ushort hash = PathMap_Fragment(&mappedSearchPath, 0)->hash; if(!(flags & PCF_NO_LEAF)) @@ -372,7 +371,7 @@ PathTree::Node& PathTree::find(int flags, const char* searchPath, char delimiter PathTree::Nodes::iterator i = nodes.find(hash); for(; i != nodes.end() && i.key() == hash; ++i) { - if((*i)->comparePath(&mappedSearchPath, flags)) + if((*i)->comparePath(mappedSearchPath, flags)) { // This is the node we're looking for - stop iteration. foundNode = *i; @@ -388,7 +387,7 @@ PathTree::Node& PathTree::find(int flags, const char* searchPath, char delimiter PathTree::Nodes::iterator i = nodes.find(hash); for(; i != nodes.end() && i.key() == hash; ++i) { - if((*i)->comparePath(&mappedSearchPath, flags)) + if((*i)->comparePath(mappedSearchPath, flags)) { // This is the node we're looking for - stop iteration. foundNode = *i; @@ -396,8 +395,6 @@ PathTree::Node& PathTree::find(int flags, const char* searchPath, char delimiter } } } - - PathMap_Destroy(&mappedSearchPath); } if(!foundNode) throw NotFoundError("PathTree::find", String("No paths found matching \"") + searchPath + "\""); @@ -1061,65 +1058,6 @@ int PathTree_Iterate_Const(const PathTree* pt, int flags, PathTreeNode const* pa return PathTree_Iterate2_Const(pt, flags, parent, hash, callback, 0/* no params */); } -typedef struct { - int flags; /// @see pathComparisonFlags - PathMap* mappedSearchPath; - void* parameters; - pathtree_searchcallback_t callback; - PathTreeNode* foundNode; -} searchworker_params_t; - -static int searchWorker(PathTreeNode* node, void* parameters) -{ - searchworker_params_t* p = (searchworker_params_t*)parameters; - DENG2_ASSERT(node && parameters); - if(p->callback(node, p->flags, p->mappedSearchPath, p->parameters)) - { - p->foundNode = node; - return 1; // Stop iteration. - } - return 0; // Continue iteration. -} - -PathTreeNode* PathTree_Search2(PathTree* pt, int flags, PathMap* mappedSearchPath, - pathtree_searchcallback_t callback, void* parameters) -{ - DENG2_ASSERT(pt); - if(callback) - { - searchworker_params_t p; - p.flags = flags; - p.mappedSearchPath = mappedSearchPath; - p.parameters = parameters; - p.callback = callback; - p.foundNode = NULL; - - ushort hash = PathMap_Fragment(mappedSearchPath, 0)->hash; - if(!(flags & PCF_NO_LEAF)) - { - if(iteratePathsInHash(pt, hash, de::PathTree::Leaf, flags, NULL, searchWorker, (void*)&p)) - { - return p.foundNode; - } - } - - if(!(flags & PCF_NO_BRANCH)) - { - if(iteratePathsInHash(pt, hash, de::PathTree::Branch, flags, NULL, searchWorker, (void*)&p)) - { - return p.foundNode; - } - } - } - return 0; // Not found. -} - -PathTreeNode* PathTree_Search(PathTree* pt, int flags, - PathMap* mappedSearchPath, pathtree_searchcallback_t callback) -{ - return PathTree_Search2(pt, flags, mappedSearchPath, callback, NULL); -} - PathTreeNode* PathTree_Find2(PathTree* pt, int flags, char const* searchPath, char delimiter) { SELF(pt); diff --git a/doomsday/engine/portable/src/pathtreenode.cpp b/doomsday/engine/portable/src/pathtreenode.cpp index 9d556e0fc5..9b9a448128 100644 --- a/doomsday/engine/portable/src/pathtreenode.cpp +++ b/doomsday/engine/portable/src/pathtreenode.cpp @@ -27,12 +27,12 @@ namespace de { struct PathTree::Node::Instance { + /// @c true = this is a leaf node. + bool isLeaf; + /// PathTree which owns this node. PathTree& tree; - /// Symbolic node type. - PathTree::NodeType type; - /// Unique identifier for the path fragment this node represents, /// in the owning PathTree. PathTree::FragmentId fragmentId; @@ -46,9 +46,9 @@ struct PathTree::Node::Instance /// User-specified value associated with this node. int userValue; - Instance(PathTree& _tree, PathTree::NodeType _type, PathTree::FragmentId _fragmentId, + Instance(PathTree& _tree, bool _isLeaf, PathTree::FragmentId _fragmentId, PathTree::Node* _parent) - : tree(_tree), type(_type), fragmentId(_fragmentId), parent(_parent), + : isLeaf(_isLeaf), tree(_tree), fragmentId(_fragmentId), parent(_parent), userPointer(0), userValue(0) {} }; @@ -56,7 +56,7 @@ struct PathTree::Node::Instance PathTree::Node::Node(PathTree& tree, PathTree::NodeType type, PathTree::FragmentId fragmentId, PathTree::Node* parent, void* userPointer, int userValue) { - d = new Instance(tree, type, fragmentId, parent); + d = new Instance(tree, type == PathTree::Leaf, fragmentId, parent); setUserPointer(userPointer); setUserValue(userValue); } @@ -66,6 +66,11 @@ PathTree::Node::~Node() delete d; } +bool PathTree::Node::isLeaf() const +{ + return d->isLeaf; +} + PathTree& PathTree::Node::tree() const { return d->tree; @@ -76,9 +81,9 @@ PathTree::Node* PathTree::Node::parent() const return d->parent; } -PathTree::NodeType PathTree::Node::type() const +PathTree::FragmentId PathTree::Node::fragmentId() const { - return d->type; + return d->fragmentId; } ddstring_t const* PathTree::Node::name() const @@ -91,9 +96,26 @@ ushort PathTree::Node::hash() const return tree().fragmentHash(d->fragmentId); } -PathTree::FragmentId PathTree::Node::fragmentId() const +void* PathTree::Node::userPointer() const { - return d->fragmentId; + return d->userPointer; +} + +int PathTree::Node::userValue() const +{ + return d->userValue; +} + +PathTree::Node& PathTree::Node::setUserPointer(void* ptr) +{ + d->userPointer = ptr; + return *this; +} + +PathTree::Node& PathTree::Node::setUserValue(int value) +{ + d->userValue = value; + return *this; } static int matchPathFragment(char const* string, char const* pattern) @@ -135,13 +157,13 @@ static int matchPathFragment(char const* string, char const* pattern) /// @note This routine is also used as an iteration callback, so only return /// a non-zero value when the node is a match for the search term. -int PathTree::Node::comparePath(PathMap* searchPattern, int flags) const +int PathTree::Node::comparePath(PathMap& searchPattern, int flags) const { - if(((flags & PCF_NO_LEAF) && type() == PathTree::Leaf) || - ((flags & PCF_NO_BRANCH) && type() == PathTree::Branch)) + if(((flags & PCF_NO_LEAF) && isLeaf()) || + ((flags & PCF_NO_BRANCH) && !isLeaf())) return false; - PathMapFragment const* sfragment = PathMap_Fragment(searchPattern, 0); + PathMapFragment const* sfragment = PathMap_Fragment(&searchPattern, 0); if(!sfragment) return false; // Hmm... //#ifdef _DEBUG @@ -151,12 +173,12 @@ int PathTree::Node::comparePath(PathMap* searchPattern, int flags) const //#endif // In reverse order, compare path fragments in the search term. - uint fragmentCount = PathMap_Size(searchPattern); + uint fragmentCount = PathMap_Size(&searchPattern); PathTree::Node const* node = this; for(uint i = 0; i < fragmentCount; ++i) { - if(i == 0 && node->type() == PathTree::Leaf) + if(i == 0 && node->isLeaf()) { char buf[256]; qsnprintf(buf, 256, "%*s", sfragment->to - sfragment->from + 1, sfragment->from); @@ -206,7 +228,7 @@ int PathTree::Node::comparePath(PathMap* searchPattern, int flags) const // So far so good. Move one directory level upwards. node = node->parent(); - sfragment = PathMap_Fragment(searchPattern, i+1); + sfragment = PathMap_Fragment(&searchPattern, i + 1); } EXIT_POINT(6); return false; @@ -296,7 +318,7 @@ ddstring_t* PathTree::Node::composePath(ddstring_t* path, int* length, char deli parm.delimiter = delimiter; // Include a terminating path delimiter for branches. - if(delimiter && type() == PathTree::Branch) + if(delimiter && !isLeaf()) parm.length += 1; // A single character. if(parm.composedPath) @@ -308,7 +330,7 @@ ddstring_t* PathTree::Node::composePath(ddstring_t* path, int* length, char deli pathConstructor(parm, *this); // Terminating delimiter for branches. - if(parm.composedPath && delimiter && type() == PathTree::Branch) + if(parm.composedPath && delimiter && !isLeaf()) Str_AppendCharWithoutAllocs(parm.composedPath, delimiter); DENG2_ASSERT(!parm.composedPath || Str_Size(parm.composedPath) == parm.length); @@ -322,28 +344,6 @@ ddstring_t* PathTree::Node::composePath(ddstring_t* path, int* length, char deli return path; } -void* PathTree::Node::userPointer() const -{ - return d->userPointer; -} - -int PathTree::Node::userValue() const -{ - return d->userValue; -} - -PathTree::Node& PathTree::Node::setUserPointer(void* ptr) -{ - d->userPointer = ptr; - return *this; -} - -PathTree::Node& PathTree::Node::setUserValue(int value) -{ - d->userValue = value; - return *this; -} - } // namespace de /** @@ -391,7 +391,8 @@ ushort PathTreeNode_Hash(PathTreeNode const* node) int PathTreeNode_ComparePath(PathTreeNode* node, PathMap* candidatePath, int flags) { SELF(node); - return self->comparePath(candidatePath, flags); + DENG_ASSERT(candidatePath); + return self->comparePath(*candidatePath, flags); } ddstring_t* PathTreeNode_ComposePath2(PathTreeNode const* node, diff --git a/doomsday/engine/portable/src/resourcenamespace.cpp b/doomsday/engine/portable/src/resourcenamespace.cpp index 006e047400..e699e057f0 100644 --- a/doomsday/engine/portable/src/resourcenamespace.cpp +++ b/doomsday/engine/portable/src/resourcenamespace.cpp @@ -268,14 +268,14 @@ struct ResourceNamespace::Instance // This node is purely symbolic, its only necessary for our internal use. if(!rootNode) { - rootNode = directory.insert("./", '/'); + rootNode = directory.insert("./"); } if(path == &buf) Str_Free(&buf); return rootNode; } - PathTree::Node* node = directory.insert(Str_Text(path), '/'); + PathTree::Node* node = directory.insert(Str_Text(path)); if(path == &buf) Str_Free(&buf); @@ -284,37 +284,34 @@ struct ResourceNamespace::Instance void addDirectoryChildNodes(PathTree::Node& node, int flags) { - if(PathTree::Branch == node.type()) + if(!node.isLeaf()) { // Compose the search pattern. - ddstring_t searchPattern; Str_InitStd(&searchPattern); - node.composePath(&searchPattern, NULL, '/'); + AutoStr* searchPattern = node.composePath(AutoStr_NewStd(), NULL, '/'); // We're interested in *everything*. - Str_AppendChar(&searchPattern, '*'); + Str_AppendChar(searchPattern, '*'); // Process this search. FS1::PathList found; - if(App_FileSystem()->findAllPaths(Str_Text(&searchPattern), flags, found)) + if(App_FileSystem()->findAllPaths(Str_Text(searchPattern), flags, found)) { DENG2_FOR_EACH_CONST(FS1::PathList, i, found) { QByteArray foundPathUtf8 = i->path.toUtf8(); ddstring_t foundPath; Str_InitStatic(&foundPath, foundPathUtf8.constData()); - bool isDirectory = !!(i->attrib & A_SUBDIR); + bool isFolder = !!(i->attrib & A_SUBDIR); addDirectoryPathNodesAndMaybeDescendBranch(!(flags & SPF_NO_DESCEND), - &foundPath, isDirectory, flags); + &foundPath, isFolder, flags); } } - - Str_Free(&searchPattern); } } /** - * @param filePath Possibly-relative path to an element in the virtual file system. - * @param isFolder @c true if @a filePath is a folder in the virtual file system. - * @param nodeType Type of element, either a branch (directory) or a leaf (file). + * @param filePath Possibly-relative path to an element in the virtual file system. + * @param isFolder @c true if @a filePath is a folder in the virtual file system. + * @param nodeType Type of element, either a branch (directory) or a leaf (file). */ void addDirectoryPathNodesAndMaybeDescendBranch(bool descendBranches, ddstring_t const* filePath, bool /*isFolder*/, int flags) @@ -323,7 +320,7 @@ struct ResourceNamespace::Instance PathTree::Node* node = addDirectoryPathNodes(filePath); if(node) { - if(PathTree::Branch == node->type()) + if(!node->isLeaf()) { // Descend into this subdirectory? if(descendBranches) @@ -416,7 +413,7 @@ void ResourceNamespace::rebuild() bool ResourceNamespace::add(PathTree::Node& resourceNode) { // We are only interested in leafs (i.e., files and not folders). - if(resourceNode.type() != PathTree::Leaf) return false; + if(!resourceNode.isLeaf()) return false; AutoStr* name = composeResourceName(resourceNode.name()); NameHash::key_type key = hashResourceName(name); diff --git a/doomsday/engine/portable/src/sys_reslocator.cpp b/doomsday/engine/portable/src/sys_reslocator.cpp index 992185620d..0062a7fc15 100644 --- a/doomsday/engine/portable/src/sys_reslocator.cpp +++ b/doomsday/engine/portable/src/sys_reslocator.cpp @@ -207,21 +207,16 @@ static de::PathTree::Node* findResourceInNamespace(ResourceNamespace& rnamespace if(rnamespace.findAll(searchPath, foundResources)) { // There is at least one name-matched (perhaps partially) resource. - PathMap searchPattern; - PathMap_Initialize2(&searchPattern, de::PathTree::hashPathFragment, Str_Text(searchPath), delimiter); + PathMap searchPattern = PathMap(de::PathTree::hashPathFragment, Str_Text(searchPath), delimiter); DENG2_FOR_EACH_CONST(ResourceNamespace::ResourceList, i, foundResources) { de::PathTree::Node* node = *i; - if(!node->comparePath(&searchPattern, PCF_NO_BRANCH)) continue; + if(!node->comparePath(searchPattern, PCF_NO_BRANCH)) continue; // This is the resource we are looking for. - found = node; - break; + return node; } - - // Cleanup. - PathMap_Destroy(&searchPattern); } return found; }