Skip to content

Instantly share code, notes, and snippets.

@lukebitts
Created July 18, 2014 13:32
Show Gist options
  • Save lukebitts/42482ec6066a2bff2e12 to your computer and use it in GitHub Desktop.
Save lukebitts/42482ec6066a2bff2e12 to your computer and use it in GitHub Desktop.
class Resources;
template <class T>
struct ResourceHandle
{
private:
const Resources* _r = nullptr;
std::string _path = "";
public:
ResourceHandle(const Resources* r, std::string path) : _r(r), _path(path) {}
ResourceHandle() {}
const T& get() const;
ResourceHandle<T> wait_load() const;
static ResourceHandle<T> make_handle(const Resources* r, std::string path)
{
return ResourceHandle<T>(r, path);
}
};
struct Resource : public boost::noncopyable
{
static bool Load(Resource* r, std::string path)
{
throw std::runtime_error("Load not implemented for this type.");
}
virtual ~Resource() {}
};
struct TextResource : public Resource
{
public:
std::string text = "";
static bool Load(TextResource* r, std::string path)
{
std::ifstream ifs(path.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
if(!ifs) return false;
std::fstream::pos_type fileSize = ifs.tellg();
ifs.seekg(0, std::ios::beg);
std::vector<char> bytes(fileSize);
ifs.read(&bytes[0], fileSize);
r->text = std::move(std::string(&bytes[0], fileSize));
return true;
}
};
class Resources
{
private:
std::unordered_map<std::string, std::unique_ptr<Resource>> _resources;
template<class T>
T* _get(std::string path) const
{
if(_resources.find(path) != _resources.end())
return static_cast<T*>(_resources.at(path).get());
return nullptr;
}
template <class T>
friend class ResourceHandle;
public:
template <class T, class ... Params>
bool load(std::string path, Params&& ... params)
{
std::unique_ptr<T> t{new T{}};
if(T::Load(t.get(), path, std::forward<Params>(params)...))
{
_resources[path] = std::move(t);
return true;
}
return false;
}
template <class T>
ResourceHandle<T> get(std::string path) const
{
return ResourceHandle<T>(this, path);
}
};
template<class T>
const T& ResourceHandle<T>::get() const
{
static const T default_return{};
auto resource = _r ? static_cast<T*>(_r->_get<T>(_path)) : nullptr;
return resource ? *resource : default_return;
}
template<class T>
ResourceHandle<T> ResourceHandle<T>::wait_load() const
{
while(_r->_get<T>(_path) == nullptr);
return ResourceHandle<T>(*this);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment