celestia/src/celutil/resmanager.h

134 lines
3.5 KiB
C++

// resmanager.h
//
// Copyright (C) 2001 Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _CELUTIL_RESMANAGER_H_
#define _CELUTIL_RESMANAGER_H_
#include <vector>
#include <map>
#include <celutil/reshandle.h>
#include <celcompat/filesystem.h>
enum ResourceState {
ResourceNotLoaded = 0,
ResourceLoaded = 1,
ResourceLoadingFailed = 2,
};
template<class T> class ResourceInfo
{
public:
ResourceInfo() : state(ResourceNotLoaded), resource(nullptr) {};
virtual ~ResourceInfo() {};
virtual fs::path resolve(const fs::path&) = 0;
virtual T* load(const fs::path&) = 0;
typedef T ResourceType;
ResourceState state;
fs::path resolvedName;
T* resource;
};
template<class T> class ResourceManager
{
private:
fs::path baseDir;
public:
ResourceManager();
ResourceManager(const fs::path& _baseDir) : baseDir(_baseDir) {};
~ResourceManager() = default;
typedef typename T::ResourceType ResourceType;
private:
typedef std::vector<T> ResourceTable;
typedef std::map<T, ResourceHandle> ResourceHandleMap;
typedef std::map<fs::path, ResourceType*> NameMap;
typedef typename ResourceHandleMap::value_type ResourceHandleMapValue;
typedef typename NameMap::value_type NameMapValue;
ResourceTable resources;
ResourceHandleMap handles;
NameMap loadedResources;
public:
ResourceHandle getHandle(const T& info)
{
typename ResourceHandleMap::iterator iter = handles.find(info);
if (iter != handles.end())
{
return iter->second;
}
else
{
ResourceHandle h = handles.size();
resources.push_back(info);
handles.insert(ResourceHandleMapValue(info, h));
return h;
}
}
ResourceType* find(ResourceHandle h)
{
if (h >= (int) handles.size() || h < 0)
{
return nullptr;
}
else
{
if (resources[h].state == ResourceNotLoaded)
{
resources[h].resolvedName = resources[h].resolve(baseDir);
typename NameMap::iterator iter =
loadedResources.find(resources[h].resolvedName);
if (iter != loadedResources.end())
{
resources[h].resource = iter->second;
resources[h].state = ResourceLoaded;
}
else
{
resources[h].resource = resources[h].load(resources[h].resolvedName);
if (resources[h].resource == nullptr)
{
resources[h].state = ResourceLoadingFailed;
}
else
{
resources[h].state = ResourceLoaded;
loadedResources.insert(NameMapValue(resources[h].resolvedName, resources[h].resource));
}
}
}
if (resources[h].state == ResourceLoaded)
return resources[h].resource;
else
return nullptr;
}
}
const T* getResourceInfo(ResourceHandle h)
{
if (h >= (int) handles.size() || h < 0)
return nullptr;
else
return &resources[h];
}
};
#endif // _CELUTIL_RESMANAGER_H_