]> Dogcows Code - chaz/yoink/blobdiff - src/moof/resource.hh
remove some deprected stuff
[chaz/yoink] / src / moof / resource.hh
index ed8a7d06f8fd9a8c420d9fab59c0c54de60a0658..9d991053c21b841be3ebc164e6b538244c80bb82 100644 (file)
  * Interface for textures, sounds, and other types of resources.
  */
 
-#include <cstdio>
+#include "config.h"
+
+#include <map>
+#include <stdexcept>
 #include <string>
 #include <vector>
 
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+
+#include <moof/debug.hh>
+
 
 namespace moof {
 
 
+class resource;
+typedef boost::shared_ptr<resource> resource_ptr;
+
+
 /**
- * Generic resource class.  
+ * Generic resource class capable of containing any type of resource,
+ * providing a type-safe interface.
  */
-
 class resource
 {
 public:
 
-       virtual ~resource() {}
-
+       // XXX: this won't be necessary once the existing code is modified to
+       // use the resource handles
+       resource() {}
 
        /**
         * Add a directory to search when looking for resource files.
@@ -42,44 +55,324 @@ public:
         */
        static void add_search_paths(const std::string& paths);
 
-       /**
-        * Add directories to search when looking for resource files.
-        * \param pathList The list of directory paths.
-        */
-       static void add_search_paths(const std::vector<std::string>& pathList);
-
 
        /**
         * Get the path to a resource of a given name.
         * \param path The name of the resource to find.  Upon successful
         * return, this is changed to an absolute path to the resource.
-        * \param prefix A colon-separated list of subdirectories to search.
-        * \param extension A colon-separated list of possible extensions.
         * \return True if a path to a resource was found, false otherwise.
         */
-       static bool find_path(std::string& path,
-                                                 const std::string& prefix = "",
-                                                 const std::string& extension = "");
+       static std::string find_file(const std::string& name);
+
+       static std::string find_file(const std::string& name,
+                                                                const std::string& ext);
 
        /**
-        * Get the path to a resource of a given name and open it if a resource
-        * was found.
-        * \param path The name of the resource to find.  Upon successful
-        * return, this is changed to an absolute path to the resource.
-        * \param prefix A colon-separated list of subdirectories to search.
-        * \param extension A colon-separated list of possible extensions.
-        * \param mode The open mode.
-        * \return The FILE* if the resource was found, 0 otherwise.
+        * Register a type with the extension of files which this type can
+        * load.  If any type has already been registered with the given file
+        * extension, it will be replaced.
+        * \param extension The file extension.
+        */
+       template <class T>
+       static void register_type(const std::string& extension,
+                                                         const std::string& prefix = "")
+       {
+               loader_ptr loader(new specific_loader<T>(prefix));
+               call_registry(extension, loader, set);
+       }
+
+       /**
+        * Unregister the type associated with a file extension.  Resources of
+        * this type will no longer be loadable, although resources which are
+        * already loaded will remain loaded.
+        * \param extension The file extension
+        */
+       static void unregister_type(const std::string& extension)
+       {
+               loader_ptr loader;
+               call_registry(extension, loader, set);
+       }
+
+
+       static resource_ptr load(const std::string& name);
+       static resource_ptr load(const std::string& name,
+                                                        const std::string& ext);
+
+       static resource_ptr reload(std::string& path);
+
+
+       /**
+        * Construct a resource container.
+        * \param ptr A pointer to the underlying resource data.
+        */
+       template <class T>
+       explicit resource(T* ptr) :
+               resource_(ptr),
+               typeinfo_(const_cast<std::type_info*>(&typeid(T))),
+               unloader_(new specific_unloader<T>(ptr)) {}
+
+       /**
+        * Deconstruct a resource container.
+        */
+       virtual ~resource();
+
+
+       /**
+        * Reload the resource data.  This will cause the resource file to be
+        * reread, and the underlying resource data will change.
+        */
+       void reload();
+
+
+       /**
+        * Get whether or not the type of the underlying resource data matches
+        * an expected type.
+        * \return True if the types match, false otherwise.
+        */
+       template <class T>
+       bool check() const
+       {
+               return *typeinfo_ == typeid(T);
+       }
+
+       /**
+        * Get a pointer to the underlying resource data as long as the type of
+        * the resource data matches the expected type.
+        * \return The resource data, or null if there is a type mismatch.
+        */
+       template <class T>
+       T* get() const
+       {
+               if (check<T>()) return (T*)resource_;
+               return 0;
+       }
+
+
+       /**
+        * Reloads some resources which have been modified on disk since they
+        * were loaded.  Hotloading must have been enabled at compile-time.
+        * \return The number of resources reloaded.
+        */
+       static int reload_as_needed();
+
+
+private:
+
+       static resource_ptr load_with_path(const std::string& path);
+
+       class loader
+       {
+       public:
+
+               //loader() {}
+               loader(const std::string& prefix) :
+                       prefix_(prefix) {}
+
+               virtual ~loader() {}
+
+               virtual resource* load(const std::string& path)
+               {
+                       return 0;
+               }
+
+               const std::string& prefix() const
+               {
+                       return prefix_;
+               }
+
+
+       private:
+
+               std::string prefix_;
+       };
+
+       typedef boost::shared_ptr<loader> loader_ptr;
+
+       template <class T>
+       class specific_loader : public loader
+       {
+       public:
+
+               //specific_loader() {}
+               specific_loader(const std::string& prefix) :
+                       loader(prefix) {}
+
+               virtual resource* load(const std::string& path)
+               {
+                       log_info("loading resource of type ", typeid(T).name());
+                       return new resource(new T(path));
+               }
+       };
+
+
+       class unloader
+       {
+       public:
+
+               virtual ~unloader() {};
+       };
+
+       typedef boost::shared_ptr<unloader> unloader_ptr;
+
+       template <class T>
+       class specific_unloader : public unloader
+       {
+       public:
+
+               specific_unloader(T* object = 0) :
+                       object_(object) {}
+
+               virtual ~specific_unloader()
+               {
+                       log_info("unloading resource of type ", typeid(T).name());
+                       delete object_;
+               }
+
+
+       private:
+
+               T* object_;
+       };
+
+
+       void set_loader(const std::string& path, loader_ptr loader)
+       {
+               path_ = path;
+               loader_ = loader;
+       }
+
+
+       void*                   resource_;
+       std::type_info* typeinfo_;
+       unloader_ptr    unloader_;
+
+       std::string             path_;
+       loader_ptr              loader_;
+
+       typedef std::map<std::string,loader_ptr> type_lookup;
+       //typedef boost::shared_ptr<type_lookup> type_lookup_ptr;
+       //static type_lookup_ptr type_lookup_;
+       //static type_lookup type_lookup_;
+       
+       enum registry_action
+       {
+               lookup,
+               set
+       };
+
+       static bool call_registry(const std::string& extension,
+                                                         loader_ptr& loader,
+                                                         registry_action action);
+
+#ifdef USE_HOTLOADING
+       int wd_;
+
+       void set_watch_descriptor(int wd)
+       {
+               wd_ = wd;
+       }
+#endif
+};
+
+
+/**
+ * The resource handle class provides a nicer way to work with resources.
+ * It allows you to work with a resource pointer as if you already know the
+ * type of the resource.
+ */
+template <class T>
+class resource_handle
+{
+public:
+
+       /**
+        * Construct a null resource handle.
+        */
+       resource_handle() {}
+
+       /**
+        * Construct a resource handle.
+        * \param ptr The resource pointer to reference.
+        */
+       resource_handle(resource_ptr ptr) :
+               resource_(ptr) {}
+
+       explicit resource_handle(const std::string& name) :
+               resource_(resource::load(name)) {}
+
+       resource_handle(const std::string& name, const std::string& ext) :
+               resource_(resource::load(name, ext)) {}
+
+
+
+       /**
+        * Get whether or not the handle is dereferenceable to the type of this
+        * handle.  A resource handle is dereferenceable if it is not a null
+        * handle and if its underlying resource is in fact the same type as is
+        * expected by the handle.
+        * \return True if the handle is dereferenceable, false otherwise.
+        */
+       operator bool () const
+       {
+               if (!resource_) return false;
+               return resource_->check<T>();
+       }
+
+
+       /**
+        * Get a pointer to the underlying resource.
+        * \return The pointer, or null if this handle is not dereferenceable.
+        */
+       T* get() const
+       {
+               if (!*this) return 0;
+               return resource_->get<T>();
+       }
+
+       /**
+        * Dereference the handle all the way to the underlying resource.
+        * \return A reference to the resource.
+        * \throws std::runtime_error If this is a null handle.
+        */
+       T& get_reference() const
+       {
+               if (!*this) throw std::runtime_error("dereference null handle");
+               return *(resource_->get<T>());
+       }
+
+
+       /**
+        * Same as get() for getting a pointer to the underlying resources.
+        * \return The pointer, or null if this handle is not dereferenceable.
+        */
+       T* operator -> () const
+       {
+               return get();
+       }
+
+       /**
+        * Same a get_reference() for dereferencing the handle.
+        * \return A reference to the resource.
+        * \throws std::runtime_error If this is a null handle.
+        */
+       T& operator * () const
+       {
+               return get_reference();
+       }
+
+
+       /**
+        * Unload the resource associated with this handle.
         */
-       static FILE* open_file(std::string& path,
-                                                  const std::string& prefix = "",
-                                                  const std::string& extension = "",
-                                                  const std::string& mode = "rb");
+       void unload()
+       {
+               resource_ = resource_ptr();
+       }
 
 
 private:
 
-       static std::vector<std::string> search_paths_;
+       resource_ptr resource_;
 };
 
 
This page took 0.026735 seconds and 4 git commands to generate.