Skip to content

Commit

Permalink
Refactor|Materials: Improved Materials public interface
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed Mar 3, 2013
1 parent 9d5617a commit 205f3fc
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 123 deletions.
62 changes: 13 additions & 49 deletions doomsday/client/include/resource/materials.h
Expand Up @@ -60,34 +60,18 @@ class Materials
typedef struct MaterialVariantSpec VariantSpec;

public:
/**
* Defines a set of one or more material manifests.
*/
typedef QSet<Manifest *> ManifestSet;
typedef ManifestSet ManifestGroup; // Alias

/**
* Flags determining URI validation logic.
*
* @see validateUri()
*/
enum UriValidationFlag
{
/// The scheme component may be empty; signifying "any scheme".
AnyScheme = 0x1
};
Q_DECLARE_FLAGS(UriValidationFlags, UriValidationFlag)
/// The referenced material/manifest was not found. @ingroup errors
DENG2_ERROR(NotFoundError);

/// System subspace schemes.
typedef QMap<String, Scheme *> Schemes;
/// The specified material id was invalid (out of range). @ingroup errors
DENG2_ERROR(UnknownIdError);

/// Manifest groups.
typedef QList<ManifestGroup *> ManifestGroups;
/// An unknown group was referenced. @ingroup errors
DENG2_ERROR(UnknownGroupError);

/// Material instances.
typedef QList<Material *> All;
/// An unknown scheme was referenced. @ingroup errors
DENG2_ERROR(UnknownSchemeError);

public:
/// Base class for all URI validation errors. @ingroup errors
DENG2_ERROR(UriValidationError);

Expand All @@ -100,18 +84,11 @@ class Materials
/// The validation URI specifies an unknown scheme. @ingroup errors
DENG2_SUB_ERROR(UriValidationError, UriUnknownSchemeError);


/// The referenced material/manifest was not found. @ingroup errors
DENG2_ERROR(NotFoundError);

/// The specified material id was invalid (out of range). @ingroup errors
DENG2_ERROR(InvalidMaterialIdError);

/// An unknown group was referenced. @ingroup errors
DENG2_ERROR(UnknownGroupError);

/// An unknown scheme was referenced. @ingroup errors
DENG2_ERROR(UnknownSchemeError);
typedef QSet<Manifest *> ManifestSet;
typedef ManifestSet ManifestGroup; // Alias
typedef QMap<String, Scheme *> Schemes;
typedef QList<ManifestGroup *> ManifestGroups;
typedef QList<Material *> All;

public:
/**
Expand All @@ -137,17 +114,6 @@ class Materials
*/
inline uint size() const { return count(); }

/**
* Validate @a uri to determine if it is well-formed and is usable as a
* search argument.
*
* @param uri Uri to be validated.
* @param flags Validation flags.
*
* @throws UriValidationError if not valid.
*/
void validateUri(Uri const &uri, UriValidationFlags flags = 0) const;

/**
* Determines if a manifest exists for a material on @a path.
* @return @c true if a manifest exists; otherwise @a false.
Expand Down Expand Up @@ -334,8 +300,6 @@ class Materials
DENG2_PRIVATE(d)
};

Q_DECLARE_OPERATORS_FOR_FLAGS(Materials::UriValidationFlags)

} // namespace de

#endif /* LIBDENG_RESOURCE_MATERIALS_H */
127 changes: 53 additions & 74 deletions doomsday/client/src/resource/materials.cpp
Expand Up @@ -272,116 +272,95 @@ MaterialManifest &Materials::toManifest(materialid_t id) const
DENG_ASSERT(0);
}
/// @throw InvalidMaterialIdError The specified material id is invalid.
throw InvalidMaterialIdError("Materials::toManifest", QString("Invalid material ID %1, valid range [1..%2)").arg(id).arg(d->manifestCount + 1));
throw UnknownIdError("Materials::toManifest", QString("Invalid material ID %1, valid range [1..%2)").arg(id).arg(d->manifestCount + 1));
}

void Materials::validateUri(Uri const &uri, UriValidationFlags flags) const
bool Materials::has(Uri const &path) const
{
if(uri.isEmpty())
{
/// @throw UriMissingPathError The URI is missing the required path component.
throw UriMissingPathError("Materials::validateUri", "Missing path in URI \"" + uri.asText() + "\"");
}

if(uri.scheme().isEmpty())
{
if(!flags.testFlag(AnyScheme))
{
/// @throw UriMissingSchemeError The URI is missing the required scheme component.
throw UriMissingSchemeError("Materials::validateUri", "Missing scheme in URI \"" + uri.asText() + "\"");
}
}
else if(!knownScheme(uri.scheme()))
try
{
/// @throw UriUnknownSchemeError The URI specifies an unknown scheme.
throw UriUnknownSchemeError("Materials::validateUri", "Unknown scheme in URI \"" + uri.asText() + "\"");
find(path);
return true;
}
catch(NotFoundError const &)
{} // Ignore this error.
return false;
}

MaterialManifest &Materials::find(Uri const &uri) const
{
LOG_AS("Materials::find");

try
// Does the user want a manifest in a specific scheme?
if(!uri.scheme().isEmpty())
{
validateUri(uri, AnyScheme);

// Does the user want a manifest in a specific scheme?
if(!uri.scheme().isEmpty())
try
{
return scheme(uri.scheme()).find(uri.path());
}
catch(Scheme::NotFoundError const &)
{} // Ignore, we'll throw our own...
}
else
{
// No, check each scheme in priority order.
foreach(Scheme *scheme, d->schemeCreationOrder)
{
try
{
return scheme(uri.scheme()).find(uri.path());
return scheme->find(uri.path());
}
catch(Scheme::NotFoundError const &)
{} // Ignore, we'll throw our own...
}
else
{
// No, check each scheme in priority order.
foreach(Scheme *scheme, d->schemeCreationOrder)
{
try
{
return scheme->find(uri.path());
}
catch(Scheme::NotFoundError const &)
{} // Ignore, we'll throw our own...
}
}
}
catch(UriValidationError const &er)
{
/// @throw NotFoundError Failed to locate a matching manifest.
throw NotFoundError("Materials::find", er.asText());
}

/// @throw NotFoundError Failed to locate a matching manifest.
throw NotFoundError("Materials::find", "Failed to locate a manifest matching \"" + uri.asText() + "\"");
}

bool Materials::has(Uri const &path) const
{
try
{
find(path);
return true;
}
catch(NotFoundError const &)
{} // Ignore this error.
return false;
}

MaterialManifest &Materials::declare(de::Uri const &uri)
MaterialManifest &Materials::declare(Uri const &uri)
{
LOG_AS("Materials::newManifest");

// Have we already created a manifest for this?
try
// Ensure we have a properly formed URI (but not a URN - this is a resource path).
if(uri.isEmpty())
{
// We require a properly formed URI (but not a URN - this is a resource path).
validateUri(uri, 0);
/// @throw UriMissingPathError The URI is missing the required path component.
throw UriMissingPathError("Materials::declare", "Missing path in URI \"" + uri.asText() + "\"");
}
if(uri.scheme().isEmpty())
{
/// @throw UriMissingSchemeError The URI is missing the required scheme component.
throw UriMissingSchemeError("Materials::declare", "Missing scheme in URI \"" + uri.asText() + "\"");
}
else if(!knownScheme(uri.scheme()))
{
/// @throw UriUnknownSchemeError The URI specifies an unknown scheme.
throw UriUnknownSchemeError("Materials::declare", "Unknown scheme in URI \"" + uri.asText() + "\"");
}

// Do we already have a manifest for this URI?
if(has(uri))
{
return find(uri);
}
catch(NotFoundError const &)
{
// Acquire a new unique identifier for the manifest.
materialid_t const id = ++d->manifestCount;

Manifest *manifest = &scheme(uri.scheme()).insertManifest(uri.path(), id);
// Acquire a new unique identifier for the manifest.
materialid_t const id = ++d->manifestCount;

// Add the new manifest to the id index/map.
if(d->manifestCount > d->manifestIdMapSize)
{
// Allocate more memory.
d->manifestIdMapSize += MANIFESTIDMAP_BLOCK_ALLOC;
d->manifestIdMap = (Manifest **) M_Realloc(d->manifestIdMap, sizeof *d->manifestIdMap * d->manifestIdMapSize);
}
d->manifestIdMap[d->manifestCount - 1] = manifest; /* 1-based index */
Manifest *manifest = &scheme(uri.scheme()).insertManifest(uri.path(), id);

return *manifest;
// Add the new manifest to the id index/map.
if(d->manifestCount > d->manifestIdMapSize)
{
// Allocate more memory.
d->manifestIdMapSize += MANIFESTIDMAP_BLOCK_ALLOC;
d->manifestIdMap = (Manifest **) M_Realloc(d->manifestIdMap, sizeof *d->manifestIdMap * d->manifestIdMapSize);
}
d->manifestIdMap[d->manifestCount - 1] = manifest; /* 1-based index */

return *manifest;
}

void Materials::addMaterial(Material &material)
Expand Down

0 comments on commit 205f3fc

Please sign in to comment.