Skip to content

Commit

Permalink
Merge branch 'master' of ssh://github.com/skyjake/Doomsday-Engine
Browse files Browse the repository at this point in the history
  • Loading branch information
skyjake committed Nov 12, 2012
2 parents 838e484 + 8e71558 commit 81994b6
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 66 deletions.
12 changes: 2 additions & 10 deletions doomsday/engine/api/uri.h
Expand Up @@ -63,9 +63,6 @@
#define DEFAULT_PRINTURIFLAGS (UPF_OUTPUT_RESOLVED|UPF_TRANSFORM_PATH_MAKEPRETTY)
///@}

// Range of the fragment hash.
#define URI_PATHNODE_NAMEHASH_SIZE 512

#ifdef __cplusplus
#ifndef DENG2_C_API_ONLY

Expand Down Expand Up @@ -104,13 +101,8 @@ namespace de
/// Type used to represent a path name hash key.
typedef ushort hash_type;

/**
* This is a hash function. It generates from @a name a somewhat-random
* number between @c 0 and @c URI_PATHNODE_NAMEHASH_SIZE
*
* @return The generated hash key.
*/
static hash_type hashPathNodeName(String const& name);
/// Range of a path name hash key; [0..hash_range)
static hash_type const hash_range;

/**
* Path Node represents a name in the URI path hierarchy.
Expand Down
10 changes: 5 additions & 5 deletions doomsday/engine/portable/include/pathtree.h
Expand Up @@ -58,10 +58,6 @@
#define PATHTREE_MULTI_LEAF 0x1 ///< There can be more than one leaf with a given name.
///@}

/// Identifier used with the search and iteration algorithms in place of a
/// hash when the caller does not wish to narrow the set of considered nodes.
#define PATHTREE_NOHASH URI_PATHNODE_NAMEHASH_SIZE

namespace de
{
/**
Expand Down Expand Up @@ -105,6 +101,10 @@ namespace de
/// @return Print-ready name for node @a type.
static String const& nodeTypeName(NodeType type);

/// Identifier used with the search and iteration algorithms in place of a
/// hash when the user does not wish to narrow the set of considered nodes.
static Uri::hash_type const no_hash;

#if _DEBUG
static void debugPrint(PathTree& pathtree, QChar delimiter = '/');
static void debugPrintHashDistribution(PathTree& pathtree);
Expand Down Expand Up @@ -286,7 +286,7 @@ namespace de
* @param parent Used in combination with @a flags= PCF_MATCH_PARENT
* to limit the traversal to only the child nodes of
* this node.
* @param hash If not @c PATHTREE_NOHASH only consider nodes whose
* @param hash If not @c PathTree::no_hash only consider nodes whose
* hashed name matches this.
* @param callback Callback function ptr.
* @param parameters Passed to the callback.
Expand Down
14 changes: 7 additions & 7 deletions doomsday/engine/portable/src/con_data.cpp
Expand Up @@ -126,7 +126,7 @@ static int clearVariable(CVarDirectory::Node& node, void* parameters)

ptr = (void**)var->ptr;
/// @note Multiple vars could be using the same pointer (so only free once).
cvarDirectory->traverse(PCF_NO_BRANCH, NULL, PATHTREE_NOHASH, markVariableUserDataFreed, ptr);
cvarDirectory->traverse(PCF_NO_BRANCH, NULL, CVarDirectory::no_hash, markVariableUserDataFreed, ptr);
M_Free(*ptr); *ptr = Str_Text(emptyStr);
break;

Expand All @@ -135,7 +135,7 @@ static int clearVariable(CVarDirectory::Node& node, void* parameters)

ptr = (void**)var->ptr;
/// @note Multiple vars could be using the same pointer (so only free once).
cvarDirectory->traverse(PCF_NO_BRANCH, NULL, PATHTREE_NOHASH, markVariableUserDataFreed, ptr);
cvarDirectory->traverse(PCF_NO_BRANCH, NULL, CVarDirectory::no_hash, markVariableUserDataFreed, ptr);
Uri_Delete((Uri*)*ptr); *ptr = emptyUri;
break;

Expand Down Expand Up @@ -163,7 +163,7 @@ static void clearVariables(void)
#endif
if(!cvarDirectory) return;

cvarDirectory->traverse(flags, NULL, PATHTREE_NOHASH, clearVariable);
cvarDirectory->traverse(flags, NULL, CVarDirectory::no_hash, clearVariable);
cvarDirectory->clear();
}

Expand Down Expand Up @@ -358,7 +358,7 @@ static void updateKnownWords(void)
countCVarParams.ignoreHidden = true;
if(cvarDirectory)
{
cvarDirectory->traverse(PCF_NO_BRANCH, NULL, PATHTREE_NOHASH, countVariable, &countCVarParams);
cvarDirectory->traverse(PCF_NO_BRANCH, NULL, CVarDirectory::no_hash, countVariable, &countCVarParams);
}

// Build the known words table.
Expand All @@ -385,7 +385,7 @@ static void updateKnownWords(void)
if(0 != countCVarParams.count)
{
/// @note cvars are NOT sorted.
cvarDirectory->traverse(PCF_NO_BRANCH, NULL, PATHTREE_NOHASH, addVariableToKnownWords, &knownWordIdx);
cvarDirectory->traverse(PCF_NO_BRANCH, NULL, CVarDirectory::no_hash, addVariableToKnownWords, &knownWordIdx);
}

// Add aliases?
Expand Down Expand Up @@ -1762,14 +1762,14 @@ D_CMD(PrintVarStats)
{
p.count = 0;
p.type = cvartype_t(i);
cvarDirectory->traverse(PCF_NO_BRANCH, NULL, PATHTREE_NOHASH, countVariable, &p);
cvarDirectory->traverse(PCF_NO_BRANCH, NULL, CVarDirectory::no_hash, countVariable, &p);
Con_Printf("%12s: %u\n", Str_Text(CVar_TypeName(p.type)), p.count);
}
p.count = 0;
p.type = cvartype_t(-1);
p.hidden = true;

cvarDirectory->traverse(PCF_NO_BRANCH, NULL, PATHTREE_NOHASH, countVariable, &p);
cvarDirectory->traverse(PCF_NO_BRANCH, NULL, CVarDirectory::no_hash, countVariable, &p);
numCVars = cvarDirectory->size();
numCVarsHidden = p.count;
}
Expand Down
8 changes: 4 additions & 4 deletions doomsday/engine/portable/src/fonts.cpp
Expand Up @@ -394,7 +394,7 @@ void Fonts_Shutdown(void)

if(fn.repository)
{
fn.repository->traverse(PCF_NO_BRANCH, NULL, PATHTREE_NOHASH, destroyRecordWorker);
fn.repository->traverse(PCF_NO_BRANCH, NULL, FontRepository::no_hash, destroyRecordWorker);
delete fn.repository; fn.repository = 0;
}

Expand Down Expand Up @@ -532,7 +532,7 @@ void Fonts_ClearNamespace(fontnamespaceid_t namespaceId)

if(fn.repository)
{
fn.repository->traverse(PCF_NO_BRANCH, NULL, PATHTREE_NOHASH, destroyFontAndRecordWorker);
fn.repository->traverse(PCF_NO_BRANCH, NULL, FontRepository::no_hash, destroyFontAndRecordWorker);
fn.repository->clear();
}

Expand Down Expand Up @@ -1195,7 +1195,7 @@ static int iterateDirectory(fontnamespaceid_t namespaceId,
FontRepository* directory = repositoryByNamespaceId(fontnamespaceid_t(i));
if(!directory) continue;

result = directory->traverse(PCF_NO_BRANCH, NULL, PATHTREE_NOHASH, callback, parameters);
result = directory->traverse(PCF_NO_BRANCH, NULL, FontRepository::no_hash, callback, parameters);
if(result) break;
}
return result;
Expand Down Expand Up @@ -1327,7 +1327,7 @@ static FontRepository::Node** collectDirectoryNodes(fontnamespaceid_t namespaceI
FontRepository* fontDirectory = repositoryByNamespaceId(fontnamespaceid_t(i));
if(!fontDirectory) continue;

fontDirectory->traverse(PCF_NO_BRANCH | PCF_MATCH_FULL, NULL, PATHTREE_NOHASH, collectDirectoryNodeWorker, (void*)&p);
fontDirectory->traverse(PCF_NO_BRANCH | PCF_MATCH_FULL, NULL, FontRepository::no_hash, collectDirectoryNodeWorker, (void*)&p);
}

if(storage)
Expand Down
22 changes: 12 additions & 10 deletions doomsday/engine/portable/src/pathtree.cpp
Expand Up @@ -311,15 +311,15 @@ static int iteratePathsInHash(PathTree& pathTree, Uri::hash_type hashKey, PathTr
{
int result = 0;

if(hashKey != PATHTREE_NOHASH && hashKey >= URI_PATHNODE_NAMEHASH_SIZE)
if(hashKey != PathTree::no_hash && hashKey >= Uri::hash_range)
{
throw Error("PathTree::iteratePathsInHash", String("Invalid hash %1 (valid range is [0..%2]).").arg(hashKey).arg(URI_PATHNODE_NAMEHASH_SIZE-1));
throw Error("PathTree::iteratePathsInHash", String("Invalid hash %1, valid range is [0..%2).").arg(hashKey).arg(Uri::hash_range-1));
}

PathTree::Nodes const& nodes = pathTree.nodes(type);

// Are we iterating nodes with a known hash?
if(hashKey != PATHTREE_NOHASH)
if(hashKey != PathTree::no_hash)
{
// Yes.
PathTree::Nodes::const_iterator i = nodes.constFind(hashKey);
Expand Down Expand Up @@ -394,7 +394,7 @@ static void printDistributionOverviewElement(const int* colWidths, const char* n
float mean = (signed)sum / total;
variance = ((signed)sumSqr - (signed)sum * mean) / (((signed)total)-1);

coverage = 100 / (float)URI_PATHNODE_NAMEHASH_SIZE * (URI_PATHNODE_NAMEHASH_SIZE - numEmpty);
coverage = 100 / (float)Uri::hash_range * (Uri::hash_range - numEmpty);
collision = 100 / (float) total * numCollisions;
}
else
Expand All @@ -405,7 +405,7 @@ static void printDistributionOverviewElement(const int* colWidths, const char* n
const int* col = colWidths;
Con_Printf("%*s ", *col++, name);
Con_Printf("%*lu ", *col++, (unsigned long)total);
Con_Printf("%*lu", *col++, URI_PATHNODE_NAMEHASH_SIZE - (unsigned long)numEmpty);
Con_Printf("%*lu", *col++, Uri::hash_range - (unsigned long)numEmpty);
Con_Printf(":%-*lu ", *col++, (unsigned long)numEmpty);
Con_Printf("%*lu ", *col++, (unsigned long)maxCollisions);
Con_Printf("%*lu ", *col++, (unsigned long)numCollisions);
Expand Down Expand Up @@ -535,7 +535,7 @@ static void printDistributionHistogram(PathTree* pt, ushort size,
if(0 == total) return;

// Calculate minimum field widths:
hashIndexDigits = M_NumDigits(URI_PATHNODE_NAMEHASH_SIZE);
hashIndexDigits = M_NumDigits(Uri::hash_range);
col = 0;
if(size != 0)
colWidths[col] = 2/*braces*/+hashIndexDigits*2+3/*elipses*/;
Expand Down Expand Up @@ -575,10 +575,10 @@ static void printDistributionHistogram(PathTree* pt, ushort size,
Con_Printf("\n");
Con_PrintRuler();

{ Uri::hash_type from = 0, n = 0, range = (size != 0? URI_PATHNODE_NAMEHASH_SIZE / size: 0);
{ Uri::hash_type from = 0, n = 0, range = (size != 0? Uri::hash_range / size: 0);
memset(nodeCount, 0, sizeof(nodeCount));

for(Uri::hash_type i = 0; i < URI_PATHNODE_NAMEHASH_SIZE; ++i)
for(Uri::hash_type i = 0; i < Uri::hash_range; ++i)
{
pathtree_pathhash_t** phAdr;
phAdr = hashAddressForNodeType(pt, PathTree::Node::Branch);
Expand All @@ -591,7 +591,7 @@ static void printDistributionHistogram(PathTree* pt, ushort size,
for(node = (**phAdr)[i].head; node; node = node->next)
++nodeCount[PT_LEAF];

if(size != 0 && (++n != range && i != URI_PATHNODE_NAMEHASH_SIZE-1))
if(size != 0 && (++n != range && i != Uri::hash_range-1))
continue;

totalForRange = 0;
Expand Down Expand Up @@ -692,7 +692,7 @@ void PathTree::debugPrintHashDistribution(PathTree& /*pt*/)
memset(nodeBucketCollisionsMax, 0, sizeof(nodeBucketCollisionsMax));
memset(nodeBucketEmpty, 0, sizeof(nodeBucketEmpty));

for(Uri::hash_type i = 0; i < URI_PATHNODE_NAMEHASH_SIZE; ++i)
for(Uri::hash_type i = 0; i < Uri::hash_range; ++i)
{
pathtree_pathhash_t** phAdr;
phAdr = hashAddressForNodeType(pt, PathTree::Node::Branch);
Expand Down Expand Up @@ -775,4 +775,6 @@ void PathTree::debugPrintHashDistribution(PathTree& /*pt*/)
}
#endif

Uri::hash_type const PathTree::no_hash = Uri::hash_range;

} // namespace de
33 changes: 25 additions & 8 deletions doomsday/engine/portable/src/resourcenamespace.cpp
Expand Up @@ -81,10 +81,10 @@ struct NameHash
{
public:
/// Type used to represent hash keys.
typedef Uri::hash_type hash_type;
typedef ushort hash_type;

/// Number of buckets in the hash table.
static hash_type const hash_size = 512;
static hash_type const hash_range = 512;

struct Node
{
Expand All @@ -103,7 +103,7 @@ struct NameHash
};

public:
Bucket buckets[hash_size];
Bucket buckets[hash_range];

public:
NameHash()
Expand All @@ -118,7 +118,7 @@ struct NameHash

void clear()
{
for(hash_type hashKey = 0; hashKey < hash_size; ++hashKey)
for(hash_type hashKey = 0; hashKey < hash_range; ++hashKey)
{
while(buckets[hashKey].first)
{
Expand All @@ -129,6 +129,23 @@ struct NameHash
buckets[hashKey].last = 0;
}
}

static hash_type hashName(String const& str)
{
hash_type hashKey = 0;
int op = 0;
for(int i = 0; i < str.length(); ++i)
{
ushort unicode = str.at(i).toLower().unicode();
switch(op)
{
case 0: hashKey ^= unicode; ++op; break;
case 1: hashKey *= unicode; ++op; break;
case 2: hashKey -= unicode; op=0; break;
}
}
return hashKey % hash_range;
}
};

static inline String composeResourceName(String const& filePath)
Expand Down Expand Up @@ -359,7 +376,7 @@ bool ResourceNamespace::add(PathTree::Node& resourceNode)
if(!resourceNode.isLeaf()) return false;

String name = composeResourceName(resourceNode.name());
NameHash::hash_type hashKey = Uri::hashPathNodeName(name) % NameHash::hash_size;
NameHash::hash_type hashKey = NameHash::hashName(name);

// Is this a new resource?
bool isNewNode = false;
Expand Down Expand Up @@ -444,7 +461,7 @@ void ResourceNamespace::debugPrint() const
LOG_DEBUG("[%p]:") << de::dintptr(this);

uint resIdx = 0;
for(NameHash::hash_type key = 0; key < NameHash::hash_size; ++key)
for(NameHash::hash_type key = 0; key < NameHash::hash_range; ++key)
{
NameHash::Bucket& bucket = d->nameHash.buckets[key];
for(NameHash::Node* node = bucket.first; node; node = node->next)
Expand Down Expand Up @@ -475,13 +492,13 @@ int ResourceNamespace::findAll(String searchPath, ResourceList& found)
NameHash::hash_type fromKey, toKey;
if(!name.isEmpty())
{
fromKey = Uri::hashPathNodeName(name) % NameHash::hash_size;
fromKey = NameHash::hashName(name);
toKey = fromKey;
}
else
{
fromKey = 0;
toKey = NameHash::hash_size - 1;
toKey = NameHash::hash_range - 1;
}

for(NameHash::hash_type key = fromKey; key < toKey + 1; ++key)
Expand Down
34 changes: 16 additions & 18 deletions doomsday/engine/portable/src/uri.cpp
Expand Up @@ -55,7 +55,20 @@ ushort Uri::PathNode::hash()
// Is it time to compute the hash?
if(!haveHashKey)
{
hashKey = de::Uri::hashPathNodeName(String(from, length()));
String str = String(from, length());
hashKey = 0;
int op = 0;
for(int i = 0; i < str.length(); ++i)
{
ushort unicode = str.at(i).toLower().unicode();
switch(op)
{
case 0: hashKey ^= unicode; ++op; break;
case 1: hashKey *= unicode; ++op; break;
case 2: hashKey -= unicode; op=0; break;
}
}
hashKey %= hash_range;
haveHashKey = true;
}
return hashKey;
Expand Down Expand Up @@ -454,23 +467,6 @@ Uri::PathNode& Uri::pathNode(int index) const
return *fragment;
}

Uri::hash_type Uri::hashPathNodeName(String const& str)
{
hash_type hashKey = 0;
int op = 0;
for(int i = 0; i < str.length(); ++i)
{
ushort unicode = str.at(i).toLower().unicode();
switch(op)
{
case 0: hashKey ^= unicode; ++op; break;
case 1: hashKey *= unicode; ++op; break;
case 2: hashKey -= unicode; op=0; break;
}
}
return hashKey % URI_PATHNODE_NAMEHASH_SIZE;
}

Uri& Uri::operator = (Uri other)
{
swap(*this, other);
Expand Down Expand Up @@ -689,6 +685,8 @@ void Uri::debugPrint(int indent, int flags, String unresolvedText) const
: "");
}

Uri::hash_type const Uri::hash_range = 512;

#if 0 //#ifdef _DEBUG
LIBDENG_DEFINE_UNITTEST(Uri)
{
Expand Down

0 comments on commit 81994b6

Please sign in to comment.