00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #if !defined(_XRB_RESOURCELIBRARY_HPP_)
00012 #define _XRB_RESOURCELIBRARY_HPP_
00013
00014 #include "xrb.hpp"
00015
00016 #include <map>
00017 #include <string>
00018
00019 namespace Xrb
00020 {
00021
00022 template <typename T> class Resource;
00023
00065 class ResourceLibrary
00066 {
00067 public:
00068
00069 enum
00070 {
00071 UNSPECIFIED_LOAD_PARAMETER = static_cast<Sint32>(SINT32_LOWER_BOUND)
00072 };
00073
00076 ResourceLibrary ();
00083 ~ResourceLibrary ();
00084
00098 template <typename T>
00099 Resource<T> LoadPath (
00100 T *(*LoadFunction)(std::string const &),
00101 std::string const &path);
00119 template <typename T>
00120 Resource<T> LoadPath (
00121 T *(*LoadFunction)(std::string const &, Sint32),
00122 std::string const &path,
00123 Sint32 load_parameter);
00124
00125 private:
00126
00127
00128 struct ResourceInstanceKey
00129 {
00130
00131 std::string m_path;
00132
00133 Sint32 m_load_parameter;
00134
00135 inline ResourceInstanceKey (
00136 std::string const &path,
00137 Sint32 const load_parameter)
00138 {
00139 m_path = path;
00140 m_load_parameter = load_parameter;
00141 }
00142
00144
00145
00146 struct LessThan
00147 {
00148 bool operator () (
00149 ResourceInstanceKey const &left_operand,
00150 ResourceInstanceKey const &right_operand) const;
00151 };
00153 };
00154
00155 void UnmapKey (ResourceInstanceKey const &key);
00156
00157
00158
00159 class ResourceInstanceBase
00160 {
00161 public:
00162
00163 inline std::string const &Path () const
00164 {
00165 return m_key.m_path;
00166 }
00167 inline Sint32 LoadParameter () const
00168 {
00169 return m_key.m_load_parameter;
00170 }
00171
00172 inline void IncrementReferenceCount ()
00173 {
00174 ASSERT1(m_reference_count < UINT32_UPPER_BOUND);
00175 ++m_reference_count;
00176 }
00177 inline bool DecrementReferenceCount ()
00178 {
00179 ASSERT1(m_reference_count > 0);
00180 --m_reference_count;
00181 if (m_reference_count == 0)
00182 {
00183 m_library->UnmapKey(m_key);
00184
00185
00186 DeleteData();
00187 return true;
00188 }
00189 else
00190 return false;
00191 }
00192
00193 void Print (FILE *fptr) const
00194 {
00195 fprintf(fptr, "\"%s\", ", m_key.m_path.c_str());
00196 if (m_key.m_load_parameter == UNSPECIFIED_LOAD_PARAMETER)
00197 fprintf(stderr, "no load parameter\n");
00198 else
00199 fprintf(stderr, "load parameter = %d\n", m_key.m_load_parameter);
00200 }
00201
00202 protected:
00203
00204 inline ResourceInstanceBase (
00205 ResourceLibrary *const library,
00206 ResourceLibrary::ResourceInstanceKey const &key)
00207 :
00208 m_key(key)
00209 {
00210 ASSERT1(!key.m_path.empty());
00211 m_library = library;
00212 m_reference_count = 0;
00213 }
00214 inline virtual ~ResourceInstanceBase () { }
00215
00216 virtual void DeleteData () = 0;
00217
00218 ResourceInstanceKey m_key;
00219 ResourceLibrary *m_library;
00220 Uint32 m_reference_count;
00221 };
00222
00223
00224 template <typename T>
00225 class ResourceInstance : public ResourceInstanceBase
00226 {
00227 public:
00228
00229 ResourceInstance (
00230 ResourceLibrary *const library,
00231 ResourceLibrary::ResourceInstanceKey const &key,
00232 T *const data)
00233 :
00234 ResourceInstanceBase(library, key)
00235 {
00236 ASSERT1(data != NULL);
00237 m_data = data;
00238 }
00239 ~ResourceInstance ()
00240 {
00241 ASSERT1(m_data == NULL);
00242 }
00243
00244 inline T *Data () const
00245 {
00246 return m_data;
00247 }
00248
00249 protected:
00250
00251 virtual void DeleteData ()
00252 {
00253 DeleteAndNullify(m_data);
00254 }
00255
00256 private:
00257
00258 T *m_data;
00259 };
00260
00261 typedef std::map<
00262 ResourceInstanceKey,
00263 ResourceInstanceBase *,
00264 ResourceInstanceKey::LessThan> InstanceMap;
00265
00266 InstanceMap m_instance_map;
00267
00268
00269 template <typename T> friend class ResourceInstance;
00270
00271 template <typename T> friend class Resource;
00272 };
00273
00306 template <typename T>
00307 class Resource
00308 {
00309 public:
00310
00314 inline Resource ()
00315 {
00316 m_instance = NULL;
00317 }
00323 inline Resource (ResourceLibrary::ResourceInstance<T> *const instance)
00324 {
00325 ASSERT1(instance != NULL);
00326 m_instance = instance;
00327 m_instance->IncrementReferenceCount();
00328 }
00333 inline Resource (Resource<T> const &source)
00334 {
00335 m_instance = source.m_instance;
00336 if (m_instance != NULL)
00337 m_instance->IncrementReferenceCount();
00338 }
00343 inline ~Resource ()
00344 {
00345 if (m_instance != NULL)
00346 {
00347 if (m_instance->DecrementReferenceCount())
00348 DeleteAndNullify(m_instance);
00349 }
00350 }
00351
00356 void operator = (Resource<T> const &source)
00357 {
00358 if (m_instance != NULL)
00359 if (m_instance->DecrementReferenceCount())
00360 Delete(m_instance);
00361 m_instance = source.m_instance;
00362 if (m_instance != NULL)
00363 m_instance->IncrementReferenceCount();
00364 }
00369 inline bool operator == (Resource<T> const &operand) const
00370 {
00371 return m_instance == operand.m_instance;
00372 }
00378 inline bool operator != (Resource<T> const &operand) const
00379 {
00380 return m_instance != operand.m_instance;
00381 }
00385 inline T const *operator * () const
00386 {
00387 ASSERT1(m_instance != NULL);
00388 return m_instance->Data();
00389 }
00394 inline T const *operator -> () const
00395 {
00396 ASSERT1(m_instance != NULL);
00397 return m_instance->Data();
00398 }
00399
00404 inline bool IsValid () const
00405 {
00406 return m_instance != NULL;
00407 }
00411 inline std::string const &Path () const
00412 {
00413 ASSERT1(m_instance != NULL);
00414 return m_instance->Path();
00415 }
00425 inline Sint32 LoadParameter () const
00426 {
00427 ASSERT1(m_instance != NULL);
00428 return m_instance->LoadParameter();
00429 }
00430
00434 void Release ()
00435 {
00436 if (m_instance != NULL)
00437 {
00438 if (m_instance->DecrementReferenceCount())
00439 DeleteAndNullify(m_instance);
00440 }
00441 }
00442
00443 private:
00444
00445 ResourceLibrary::ResourceInstance<T> *m_instance;
00446 };
00447
00448 template <typename T>
00449 Resource<T> ResourceLibrary::LoadPath (
00450 T *(*LoadFunction)(std::string const &),
00451 std::string const &path)
00452 {
00453 Resource<T> invalid_resource;
00454
00455 if (path.empty())
00456 return invalid_resource;
00457
00458 ResourceInstanceKey const key(path, UNSPECIFIED_LOAD_PARAMETER);
00459
00460
00461 InstanceMap::iterator it = m_instance_map.find(key);
00462
00463 if (it != m_instance_map.end())
00464 {
00465 ASSERT1(it->second != NULL);
00466
00467 ASSERT1(
00468 dynamic_cast<ResourceInstance<T> *>(it->second) != NULL &&
00469 "You probably are trying to load a currently loaded "
00470 "resource using a different type or method");
00471 return Resource<T>(dynamic_cast<ResourceInstance<T> *>(it->second));
00472 }
00473
00474
00475 else
00476 {
00477
00478 T *data = LoadFunction(path);
00479
00480
00481
00482 if (data != NULL)
00483 {
00484
00485
00486
00487
00488
00489
00490 ResourceInstance<T> *instance =
00491 new ResourceInstance<T>(this, key, data);
00492 m_instance_map[key] = instance;
00493 return Resource<T>(instance);
00494 }
00495 else
00496 {
00497 fprintf(
00498 stderr,
00499 "ResourceLibrary * FAILURE while "
00500 "loading \"%s\", no load parameter\n",
00501 path.c_str());
00502
00503 return invalid_resource;
00504 }
00505 }
00506 }
00507
00508 template <typename T>
00509 Resource<T> ResourceLibrary::LoadPath (
00510 T *(*LoadFunction)(std::string const &, Sint32),
00511 std::string const &path,
00512 Sint32 const load_parameter)
00513 {
00514 ASSERT1(load_parameter != UNSPECIFIED_LOAD_PARAMETER &&
00515 "You may not use that load parameter (it is reserved)");
00516
00517 Resource<T> invalid_resource;
00518
00519 if (path.empty())
00520 return invalid_resource;
00521
00522 ResourceInstanceKey const key(path, load_parameter);
00523
00524
00525 InstanceMap::iterator it = m_instance_map.find(key);
00526
00527 if (it != m_instance_map.end())
00528 {
00529 ASSERT1(it->second != NULL);
00530
00531 ASSERT1(
00532 dynamic_cast<ResourceInstance<T> *>(it->second) != NULL &&
00533 "You probably are trying to load a currently loaded "
00534 "resource using a different type or method");
00535 return Resource<T>(dynamic_cast<ResourceInstance<T> *>(it->second));
00536 }
00537
00538
00539 else
00540 {
00541
00542 T *data = LoadFunction(path, load_parameter);
00543
00544
00545
00546 if (data != NULL)
00547 {
00548
00549
00550
00551
00552
00553
00554
00555 ResourceInstance<T> *instance =
00556 new ResourceInstance<T>(this, key, data);
00557 m_instance_map[key] = instance;
00558 return Resource<T>(instance);
00559 }
00560 else
00561 {
00562 fprintf(
00563 stderr,
00564 "ResourceLibrary * FAILURE while "
00565 "loading \"%s\", load parameter = %d\n",
00566 path.c_str(),
00567 load_parameter);
00568
00569 return invalid_resource;
00570 }
00571 }
00572 }
00573
00574 }
00575
00576 #endif // !defined(_XRB_RESOURCELIBRARY_HPP_)
00577