Skip to content

Commit

Permalink
Refactor|StringPool|libcore: Use C++11 for iterating interned strings…
Browse files Browse the repository at this point in the history
… in StringPool
  • Loading branch information
danij-deng committed Aug 5, 2015
1 parent d801932 commit bf60b9b
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 162 deletions.
50 changes: 22 additions & 28 deletions doomsday/apps/client/src/resource/materialarchive.cpp
Expand Up @@ -94,13 +94,13 @@ static Material *findRecordMaterial(Records &records, SerialId id)
// Time to lookup the material for the record's URI?
if(!records.userValue(id))
{
Material *material = 0;
Material *material = nullptr;
try
{
material = &App_ResourceSystem().material(Uri(records.stringRef(id), RC_NULL));
}
catch(res::System::MissingResourceManifestError const &)
{} // Ignore this error.
{} // Ignore this error.

records.setUserPointer(id, material);
records.setUserValue(id, true);
Expand Down Expand Up @@ -200,34 +200,28 @@ MaterialArchive::MaterialArchive(int useSegments, bool recordSymbolicMaterials)
}
}

struct findUniqueSerialIdWorker_params {
Records *records;
Material *material;
};

static int findUniqueSerialIdWorker(SerialId id, void *parameters)
{
findUniqueSerialIdWorker_params *parm = (findUniqueSerialIdWorker_params*) parameters;

// Is this the material we are looking for?
if(findRecordMaterial(*parm->records, id) == parm->material)
return id;

return 0; // Continue iteration.
}

materialarchive_serialid_t MaterialArchive::findUniqueSerialId(Material *material) const
{
if(!material) return 0; // Invalid.

findUniqueSerialIdWorker_params parm;
parm.records = &d->records;
parm.material = material;

SerialId found = d->records.iterate(findUniqueSerialIdWorker, &parm);
if(found) return found; // Yes. Return existing serial.

return d->records.size() + 1;
materialarchive_serialid_t serialId = 0; // Invalid.
if(material)
{
// Is there already an Id for this Material?
LoopResult found = d->records.forAll([this, &material, &serialId] (SerialId id)
{
if(findRecordMaterial(d->records, id) == material)
{
serialId = id;
return LoopAbort;
}
return LoopContinue;
});
if(!found)
{
// Assign a new Id.
serialId = d->records.size() + 1;
}
}
return serialId;
}

Material *MaterialArchive::find(materialarchive_serialid_t serialId, int group) const
Expand Down
21 changes: 9 additions & 12 deletions doomsday/apps/client/src/resource/resourcesystem.cpp
Expand Up @@ -1996,22 +1996,19 @@ DENG2_PIMPL(ResourceSystem)
modef->shadowRadius = def.getf("shadowRadius");
}

static int destroyModelInRepository(StringPool::Id id, void *context)
{
ModelRepository &modelRepository = *static_cast<ModelRepository *>(context);
if(Model *model = reinterpret_cast<Model *>(modelRepository.userPointer(id)))
{
modelRepository.setUserPointer(id, 0);
delete model;
}
return 0;
}

void clearModelList()
{
if(!modelRepository) return;

modelRepository->iterate(destroyModelInRepository, modelRepository);
modelRepository->forAll([this] (StringPool::Id id)
{
if(auto *model = reinterpret_cast<Model *>(modelRepository->userPointer(id)))
{
modelRepository->setUserPointer(id, nullptr);
delete model;
}
return LoopContinue;
});
}
#endif

Expand Down
57 changes: 16 additions & 41 deletions doomsday/apps/client/src/world/api_mapedit.cpp
Expand Up @@ -57,44 +57,6 @@ static bool editMapInited;
*/
static StringPool *materialDict;

/**
* Either print or count-the-number-of unresolved references in the
* material dictionary.
*
* @param internId Unique id associated with the reference.
* @param context If a uint pointer operate in "count" mode (total written
* here). Else operate in "print" mode.
* @return Always @c 0 (for use as an iterator).
*/
static int printMissingMaterialWorker(StringPool::Id internId, void *context)
{
int *count = (int *)context;

// A valid id?
if(materialDict->string(internId))
{
// Have we resolved this reference yet?
if(!materialDict->userPointer(internId))
{
// An unresolved reference.
if(count)
{
// Count mode.
*count += 1;
}
else
{
// Print mode.
int const refCount = materialDict->userValue(internId);
String const &materialUri = materialDict->string(internId);
LOG_RES_WARNING("Found %4i x unknown material \"%s\"") << refCount << materialUri;
}
}
}

return 0; // Continue iteration.
}

/**
* Destroy the missing material dictionary.
*/
Expand All @@ -112,10 +74,23 @@ static void clearMaterialDict()
*/
static void printMissingMaterialsInDict()
{
if(materialDict)
if(!::materialDict) return;

::materialDict->forAll([] (StringPool::Id id)
{
materialDict->iterate(printMissingMaterialWorker);
}
// A valid id?
if(::materialDict->string(id))
{
// An unresolved reference?
if(!::materialDict->userPointer(id))
{
LOG_RES_WARNING("Found %4i x unknown material \"%s\"")
<< ::materialDict->userValue(id)
<< ::materialDict->string(id);
}
}
return LoopContinue;
});
}

/**
Expand Down
60 changes: 29 additions & 31 deletions doomsday/apps/client/src/world/entitydef.cpp
Expand Up @@ -40,27 +40,26 @@ static StringPool *entityDefs;
typedef std::map<int, StringPool::Id> EntityDefIdMap;
static EntityDefIdMap entityDefIdMap;

static int clearEntityDefsWorker(StringPool::Id id, void * /*parameters*/)
static void clearEntityDefs()
{
MapEntityDef *def = static_cast<MapEntityDef *>( entityDefs->userPointer(id) );
DENG2_ASSERT(def);
for(uint i = 0; i < def->numProps; ++i)
if(!::entityDefs) return;

::entityDefs->forAll([] (StringPool::Id id)
{
MapEntityPropertyDef *prop = def->props + i;
M_Free(prop->name);
}
M_Free(def->props);
delete def;
return false; // Continue iteration.
}
auto *def = static_cast<MapEntityDef *>( ::entityDefs->userPointer(id) );
DENG2_ASSERT(def);
for(duint i = 0; i < def->numProps; ++i)
{
M_Free(def->props[i].name);
}
M_Free(def->props);
delete def;

static void clearEntityDefs(void)
{
if(!entityDefs) return;
return LoopContinue;
});
delete ::entityDefs; ::entityDefs = nullptr;

entityDefs->iterate(clearEntityDefsWorker, 0/*no parameters*/);
delete entityDefs; entityDefs = 0;
entityDefIdMap.clear();
::entityDefIdMap.clear();
}

MapEntityDef *P_MapEntityDef(int id)
Expand All @@ -71,7 +70,7 @@ MapEntityDef *P_MapEntityDef(int id)
StringPool::Id id = i->second;
return static_cast<MapEntityDef *>( entityDefs->userPointer(id) );
}
return 0; // Not found.
return nullptr; // Not found.
}

MapEntityDef *P_MapEntityDefByName(char const *name)
Expand All @@ -81,26 +80,25 @@ MapEntityDef *P_MapEntityDefByName(char const *name)
StringPool::Id id = entityDefs->isInterned(String(name));
return static_cast<MapEntityDef *>( entityDefs->userPointer(id) );
}
return 0; // Not found.
}

static int P_NameForMapEntityDefWorker(StringPool::Id id, void *parameters)
{
MapEntityDef *def = static_cast<MapEntityDef *>( parameters );
if(entityDefs->userPointer(id) == def) return id;
return 0; // Continue iteration.
return nullptr; // Not found.
}

AutoStr *P_NameForMapEntityDef(MapEntityDef *def)
{
String name; // Not found.
if(def)
{
StringPool::Id id = entityDefs->iterate(P_NameForMapEntityDefWorker, def);
String const& name = entityDefs->string(id);
QByteArray nameUtf8 = name.toUtf8();
return AutoStr_FromText(nameUtf8.constData());
::entityDefs->forAll([&def, &name] (StringPool::Id id)
{
if(::entityDefs->userPointer(id) == def)
{
name = ::entityDefs->string(id);
return LoopAbort;
}
return LoopContinue;
});
}
return AutoStr_NewStd();
return AutoStr_FromText(name.toUtf8().constData());
}

int MapEntityDef_Property(MapEntityDef *def, int propertyId,
Expand Down
21 changes: 8 additions & 13 deletions doomsday/sdk/libcore/include/de/data/stringpool.h
@@ -1,8 +1,6 @@
/**
* @file stringpool.h
* Pool of strings (case insensitive).
/** @file stringpool.h Pool of strings (case insensitive).
*
* @author Copyright © 2010-2013 Daniel Swanson <danij@dengine.net>
* @author Copyright © 2010-2015 Daniel Swanson <danij@dengine.net>
* @author Copyright © 2012-2013 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
Expand All @@ -25,6 +23,7 @@
#include "../libcore.h"
#include "../ISerializable"
#include "../String"
#include <functional>

namespace de {

Expand Down Expand Up @@ -216,19 +215,15 @@ class DENG2_PUBLIC StringPool : public ISerializable
* Iterate over all strings in the pool making a callback for each. Iteration
* ends when all strings have been processed or a callback returns non-zero.
*
* @param callback Callback to make for each iteration.
* @param data User data to be passed to the callback.
*
* @return @c 0 iff iteration completed wholly. Otherwise the non-zero value
* returned by @a callback.
* @param func Callback to make for each string.
*/
int iterate(int (*callback)(Id, void *), void *data = 0) const;
LoopResult forAll(std::function<LoopResult (Id)> func) const;

// Implements ISerializable.
void operator >> (Writer &to) const;
void operator << (Reader &from);

#if _DEBUG
#ifdef DENG2_DEBUG
/**
* Print contents of the pool. For debug.
* @param pool StringPool instance.
Expand All @@ -240,6 +235,6 @@ class DENG2_PUBLIC StringPool : public ISerializable
DENG2_PRIVATE(d)
};

} // namespace de
} // namespace de

#endif /* LIBDENG2_STRINGPOOL_H */
#endif // LIBDENG2_STRINGPOOL_H

0 comments on commit bf60b9b

Please sign in to comment.