Main Page | Namespace List | Class Hierarchy | Class List | 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 Wed Jul 28 17:28:43 2004.
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.