]> Dogcows Code - chaz/yoink/blob - src/moof/resource.hh
use only triangles; no quads
[chaz/yoink] / src / moof / resource.hh
1
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
9 *
10 **************************************************************************/
11
12 #ifndef _MOOF_RESOURCE_HH_
13 #define _MOOF_RESOURCE_HH_
14
15 /**
16 * \file resource.hh
17 * Interface for textures, sounds, and other types of resources.
18 */
19
20 #include "config.h"
21
22 #include <map>
23 #include <stdexcept>
24 #include <string>
25 #include <vector>
26
27 #include <boost/shared_ptr.hpp>
28 #include <boost/function.hpp>
29
30 #include <moof/debug.hh>
31
32
33 namespace moof {
34
35
36 class resource;
37 typedef boost::shared_ptr<resource> resource_ptr;
38
39
40 /**
41 * Generic resource class capable of containing any type of resource,
42 * providing a type-safe interface.
43 */
44 class resource
45 {
46 public:
47
48 // XXX: this won't be necessary once the existing code is modified to
49 // use the resource handles
50 resource() {}
51
52 /**
53 * Add a directory to search when looking for resource files.
54 * \param paths A colon-separated list of directory paths.
55 */
56 static void add_search_paths(const std::string& paths);
57
58
59 /**
60 * Get the path to a resource of a given name.
61 * \param path The name of the resource to find. Upon successful
62 * return, this is changed to an absolute path to the resource.
63 * \return True if a path to a resource was found, false otherwise.
64 */
65 static std::string find_file(const std::string& name);
66
67 static std::string find_file(const std::string& name,
68 const std::string& ext);
69
70 /**
71 * Register a type with the extension of files which this type can
72 * load. If any type has already been registered with the given file
73 * extension, it will be replaced.
74 * \param extension The file extension.
75 */
76 template <class T>
77 static void register_type(const std::string& extension,
78 const std::string& prefix = "")
79 {
80 loader_ptr loader(new specific_loader<T>(prefix));
81 call_registry(extension, loader, set);
82 }
83
84 /**
85 * Unregister the type associated with a file extension. Resources of
86 * this type will no longer be loadable, although resources which are
87 * already loaded will remain loaded.
88 * \param extension The file extension
89 */
90 static void unregister_type(const std::string& extension)
91 {
92 loader_ptr loader;
93 call_registry(extension, loader, set);
94 }
95
96
97 static resource_ptr load(const std::string& name);
98 static resource_ptr load(const std::string& name,
99 const std::string& ext);
100
101 static resource_ptr reload(std::string& path);
102
103
104 /**
105 * Construct a resource container.
106 * \param ptr A pointer to the underlying resource data.
107 */
108 template <class T>
109 explicit resource(T* ptr) :
110 resource_(ptr),
111 typeinfo_(const_cast<std::type_info*>(&typeid(T))),
112 unloader_(new specific_unloader<T>(ptr)) {}
113
114 /**
115 * Deconstruct a resource container.
116 */
117 virtual ~resource();
118
119
120 /**
121 * Reload the resource data. This will cause the resource file to be
122 * reread, and the underlying resource data will change.
123 */
124 void reload();
125
126
127 /**
128 * Get whether or not the type of the underlying resource data matches
129 * an expected type.
130 * \return True if the types match, false otherwise.
131 */
132 template <class T>
133 bool check() const
134 {
135 return *typeinfo_ == typeid(T);
136 }
137
138 /**
139 * Get a pointer to the underlying resource data as long as the type of
140 * the resource data matches the expected type.
141 * \return The resource data, or null if there is a type mismatch.
142 */
143 template <class T>
144 T* get() const
145 {
146 if (check<T>()) return (T*)resource_;
147 return 0;
148 }
149
150
151 /**
152 * Reloads some resources which have been modified on disk since they
153 * were loaded. Hotloading must have been enabled at compile-time.
154 * \return The number of resources reloaded.
155 */
156 static int reload_as_needed();
157
158
159 private:
160
161 static resource_ptr load_with_path(const std::string& path);
162
163 class loader
164 {
165 public:
166
167 //loader() {}
168 loader(const std::string& prefix) :
169 prefix_(prefix) {}
170
171 virtual ~loader() {}
172
173 virtual resource* load(const std::string& path)
174 {
175 return 0;
176 }
177
178 const std::string& prefix() const
179 {
180 return prefix_;
181 }
182
183
184 private:
185
186 std::string prefix_;
187 };
188
189 typedef boost::shared_ptr<loader> loader_ptr;
190
191 template <class T>
192 class specific_loader : public loader
193 {
194 public:
195
196 //specific_loader() {}
197 specific_loader(const std::string& prefix) :
198 loader(prefix) {}
199
200 virtual resource* load(const std::string& path)
201 {
202 log_info("loading resource of type ", typeid(T).name());
203 return new resource(new T(path));
204 }
205 };
206
207
208 class unloader
209 {
210 public:
211
212 virtual ~unloader() {};
213 };
214
215 typedef boost::shared_ptr<unloader> unloader_ptr;
216
217 template <class T>
218 class specific_unloader : public unloader
219 {
220 public:
221
222 specific_unloader(T* object = 0) :
223 object_(object) {}
224
225 virtual ~specific_unloader()
226 {
227 log_info("unloading resource of type ", typeid(T).name());
228 delete object_;
229 }
230
231
232 private:
233
234 T* object_;
235 };
236
237
238 void set_loader(const std::string& path, loader_ptr loader)
239 {
240 path_ = path;
241 loader_ = loader;
242 }
243
244
245 void* resource_;
246 std::type_info* typeinfo_;
247 unloader_ptr unloader_;
248
249 std::string path_;
250 loader_ptr loader_;
251
252 typedef std::map<std::string,loader_ptr> type_lookup;
253 //typedef boost::shared_ptr<type_lookup> type_lookup_ptr;
254 //static type_lookup_ptr type_lookup_;
255 //static type_lookup type_lookup_;
256
257 enum registry_action
258 {
259 lookup,
260 set
261 };
262
263 static bool call_registry(const std::string& extension,
264 loader_ptr& loader,
265 registry_action action);
266
267 #ifdef USE_HOTLOADING
268 int wd_;
269
270 void set_watch_descriptor(int wd)
271 {
272 wd_ = wd;
273 }
274 #endif
275 };
276
277
278 /**
279 * The resource handle class provides a nicer way to work with resources.
280 * It allows you to work with a resource pointer as if you already know the
281 * type of the resource.
282 */
283 template <class T>
284 class resource_handle
285 {
286 public:
287
288 /**
289 * Construct a null resource handle.
290 */
291 resource_handle() {}
292
293 /**
294 * Construct a resource handle.
295 * \param ptr The resource pointer to reference.
296 */
297 resource_handle(resource_ptr ptr) :
298 resource_(ptr) {}
299
300 explicit resource_handle(const std::string& name) :
301 resource_(resource::load(name)) {}
302
303 resource_handle(const std::string& name, const std::string& ext) :
304 resource_(resource::load(name, ext)) {}
305
306
307
308 /**
309 * Get whether or not the handle is dereferenceable to the type of this
310 * handle. A resource handle is dereferenceable if it is not a null
311 * handle and if its underlying resource is in fact the same type as is
312 * expected by the handle.
313 * \return True if the handle is dereferenceable, false otherwise.
314 */
315 operator bool () const
316 {
317 if (!resource_) return false;
318 return resource_->check<T>();
319 }
320
321
322 /**
323 * Get a pointer to the underlying resource.
324 * \return The pointer, or null if this handle is not dereferenceable.
325 */
326 T* get() const
327 {
328 if (!*this) return 0;
329 return resource_->get<T>();
330 }
331
332 /**
333 * Dereference the handle all the way to the underlying resource.
334 * \return A reference to the resource.
335 * \throws std::runtime_error If this is a null handle.
336 */
337 T& get_reference() const
338 {
339 if (!*this) throw std::runtime_error("dereference null handle");
340 return *(resource_->get<T>());
341 }
342
343
344 /**
345 * Same as get() for getting a pointer to the underlying resources.
346 * \return The pointer, or null if this handle is not dereferenceable.
347 */
348 T* operator -> () const
349 {
350 return get();
351 }
352
353 /**
354 * Same a get_reference() for dereferencing the handle.
355 * \return A reference to the resource.
356 * \throws std::runtime_error If this is a null handle.
357 */
358 T& operator * () const
359 {
360 return get_reference();
361 }
362
363
364 /**
365 * Unload the resource associated with this handle.
366 */
367 void unload()
368 {
369 resource_ = resource_ptr();
370 }
371
372
373 private:
374
375 resource_ptr resource_;
376 };
377
378
379 } // namespace moof
380
381 #endif // _MOOF_RESOURCE_HH_
382
This page took 0.044502 seconds and 4 git commands to generate.