Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

resources.h

00001 /*
00002   libwftk - Worldforge Toolkit - a widget library
00003   Copyright (C) 2002 Malcolm Walker <malcolm@worldforge.org>
00004   Based on code copyright  (C) 1999-2002  Karsten Laux 
00005 
00006   This library is free software; you can redistribute it and/or
00007   modify it under the terms of the GNU Library General Public
00008   License as published by the Free Software Foundation; either
00009   version 2 of the License, or (at your option) any later version.
00010   
00011   This library is distributed in the hope that it will be useful,
00012   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014   Library General Public License for more details.
00015   
00016   You should have received a copy of the GNU Library General Public
00017   License along with this library; if not, write to the
00018   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019   Boston, MA  02111-1307, SA.
00020 */
00021 
00022 
00023 #ifndef _RESOURCES_H
00024 #define _RESOURCES_H
00025 
00026 #include <wftk/string_hash_map.h>
00027 #include <cassert>
00028 
00029 namespace wftk {
00030 
00032 template<class R>
00033 struct ResDestroy
00034 {
00036   void operator()(const R&) {}
00037 };
00038 
00040 template<class R>
00041 struct ResDestroy<R*>
00042 {
00044   void operator()(R* r) {delete r;}
00045 };
00046 
00048 template<class R>
00049 struct ResInval
00050 {
00052   typedef const R& OutType;
00053 #if 0
00054   // much rather have this, but the compiler gets confused
00056   OutType operator()() const {return r_;}
00057  private:
00058   R r_;
00059 #else
00060   ResInval() : r_(new R()) {}
00061   ~ResInval() {delete r_;}
00063   OutType operator()() const {return *r_;}
00064  private:
00065   R* r_;
00066 #endif
00067 };
00068 
00070 template<class R>
00071 struct ResInval<R*>
00072 {
00074   typedef const R* OutType;
00076   OutType operator()(const std::string&) const {return 0;}
00077 };
00078 
00080 template<class R>
00081 struct ResLoad
00082 {
00084   std::pair<R,bool> operator()(const std::string& filename)
00085   {
00086     R r;
00087     bool result = r.load(filename);
00088     return std::make_pair(r, result);
00089   }
00090 };
00091 
00093 template<class R>
00094 struct ResLoad<R*>
00095 {
00097   std::pair<R*,bool> operator()(const std::string& filename)
00098   {
00099     R* r;
00100     r = new R();
00101     if(!r->load(filename)) {
00102       delete r;
00103       r = 0;
00104     }
00105     return std::make_pair(r, r != 0);
00106   }
00107 };
00108 
00110 template<class R, class Destroy = ResDestroy<R> >
00111 class Resource
00112 {
00113  public:
00115   ~Resource() {Destroy d; d(res_);}
00117   Resource(const R& res) : res_(res), references_(1) {} 
00119   void bind() {++references_;}
00121   void free() {if(--references_ == 0) delete this;}
00123   const R& res() const {return res_;}
00124 
00125  private:
00127   R res_;
00129   int references_;
00130 };
00131 
00133 
00139 template<class R, class Loader = ResLoad<R>, class Invalid = ResInval<R>, class Destroy = ResDestroy<R> >
00140 class ResourceRegistry
00141 {
00142  public:
00144   typedef Resource<R,Destroy> Resource;
00145 
00147   ~ResourceRegistry()
00148   {
00149     for(typename ResourceMap::iterator I = resources_.begin(); I != resources_.end(); ++I)
00150       I->second->free();
00151   }
00153   Resource* load(const std::string& resname, const std::string& spec);
00155   Resource* loadAnonymous(const std::string& spec);
00158   void insert(const std::string& resname, Resource* res)
00159   {
00160     // Make sure the resource name is unique
00161     assert(res);
00162     if(resources_.insert(typename ResourceMap::value_type(resname, res)).second)
00163       res->bind();
00164   }
00166   typename Invalid::OutType find(const std::string& resname) const
00167   {
00168     typename ResourceMap::const_iterator I = resources_.find(resname);
00169     return (I != resources_.end()) ? I->second->res() : inval_(resname);
00170   }
00172   Resource* get(const std::string& resname) const
00173   {
00174     typename ResourceMap::const_iterator I = resources_.find(resname);
00175     return (I != resources_.end()) ? I->second : 0;
00176   }
00178   void unregisterAll()
00179   {
00180     for(typename ResourceMap::iterator I = resources_.begin(); I != resources_.end(); ++I)
00181       I->second->free();
00182     resources_.clear();
00183   }
00184 
00186   typedef typename StringHash<Resource*>::Map ResourceMap;
00187 
00189   typename ResourceMap::const_iterator begin() const {return resources_.begin();}
00191   typename ResourceMap::const_iterator end() const {return resources_.end();}
00193   typename ResourceMap::size_type size() const {return resources_.size();}
00195   bool empty() const {return resources_.empty();}
00196 
00197  private:
00199   ResourceMap resources_;
00201   Loader loader_;
00203   Invalid inval_;
00204 };
00205 
00206 template<class R, class Loader, class Invalid, class Destroy>
00207 Resource<R,Destroy>*
00208 ResourceRegistry<R,Loader,Invalid,Destroy>::load(
00209     const std::string& resname, const std::string& spec)
00210 {
00211   // Make sure the resource name is unique
00212 
00213   std::pair<typename ResourceMap::iterator, bool> result =
00214     resources_.insert(typename ResourceMap::value_type(resname, 0));
00215 
00216   if(!result.second)
00217     return 0;
00218 
00219   // Load the resource
00220 
00221   std::pair<R,bool> load_val = loader_(spec);
00222   if(!load_val.second) {
00223     resources_.erase(result.first);
00224     return 0;
00225   }
00226 
00227   // Actually place the resource in the map and return
00228 
00229   Resource* res = new Resource(load_val.first);
00230   result.first->second = res;
00231   return res;
00232 }
00233 
00234 template<class R, class Loader, class Invalid, class Destroy>
00235 Resource<R,Destroy>*
00236 ResourceRegistry<R,Loader,Invalid,Destroy>::loadAnonymous(const std::string& spec)
00237 {
00238   std::pair<R,bool> load_val = loader_(spec);
00239   return load_val.second ? new Resource(load_val.first) : 0;
00240 }
00241 
00242 } // namespace
00243 
00244 #endif

Generated Tue Aug 9 18:40:26 2005.
Copyright © 1998-2003 by the respective authors.

This document is licensed under the terms of the GNU Free Documentation License and may be freely distributed under the conditions given by this license.