resources.cpp

Go to the documentation of this file.
00001 /*
00002  * resources.cpp
00003  *
00004  * Copyright (C) 2010  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Resource APIs
00032  */
00033 
00034 // includes --------------------------------------------------------------------
00035 #include "resources.h"          // always include our own header first!
00036 #include "resources-internal.h"
00037 
00038 #include "threadsafe/smart_ptr.h"
00039 
00040 
00041 
00042 struct resource_t {
00043         // constructor, manipulators
00044         resource_t(void) throw() { this->clear(); }
00045         void clear(void) throw() {
00046                         name.clear();
00047                         value = NULL;
00048                         bytes = 0;
00049                 }
00050 
00051         // data fields
00052         std::string             name;   // name of resource
00053         const byte_t *          value;  // someone else owns data
00054         int                     bytes;  // size of value array
00055 };
00056 
00057 
00058 typedef std::map<std::string, resource_t> res_map_t;
00059 
00060 
00061 struct res_namespace_t {
00062         // constructor, manipulators
00063         res_namespace_t(void) throw() { this->clear(); }
00064         void clear(void) throw() {
00065                         name.clear();
00066                         resources.clear();
00067                 }
00068 
00069         // data fields
00070         std::string             name;   // name of namespace
00071         res_map_t               resources;// resource map in namespace
00072 };
00073 
00074 
00075 typedef std::map<std::string, smart_ptr<res_namespace_t> > namespace_map_t;
00076 
00077 
00078 
00079 ////////////////////////////////////////////////////////////////////////////////
00080 //
00081 //      static helper methods
00082 //
00083 ////////////////////////////////////////////////////////////////////////////////
00084 
00085 static namespace_map_t *
00086 getNamespaceMap
00087 (
00088 void
00089 )
00090 throw()
00091 {
00092         // our static (global) map of all resources, keyed by namespace
00093         static namespace_map_t * s_map = NULL;
00094         if (!s_map) {
00095                 s_map = new namespace_map_t;
00096                 ASSERT(s_map, "out of memory");
00097         }
00098         return s_map;
00099 }
00100 
00101 
00102 
00103 static res_map_t *
00104 getResourceMap
00105 (
00106 IN namespace_map_t * nmap,
00107 IN const char * nameSpace,
00108 IN eCreateFlag createBehavior
00109 )
00110 {
00111         ASSERT(nmap, "null");
00112         ASSERT(nameSpace, "null");
00113 
00114         namespace_map_t::iterator i = nmap->find(nameSpace);
00115         if (nmap->end() != i) {
00116                 // found in map!
00117                 res_namespace_t * rmap = i->second;
00118                 ASSERT(rmap, "null namespace in namespace map");
00119                 return &rmap->resources;
00120         }
00121 
00122         // not in map
00123         if (eCreateIfNotExists != createBehavior) {
00124                 // not supposed to create it!
00125                 return NULL;
00126         }
00127 
00128         // we need to create a new entry
00129         smart_ptr<res_namespace_t> rmap = new res_namespace_t;
00130         ASSERT(rmap, "out of memory");
00131         rmap->name = nameSpace;         // copy namespace name
00132 
00133         // add this new resource map to the global map and return it
00134         nmap->operator[](nameSpace) = rmap;
00135         return &rmap->resources;
00136 }
00137 
00138 
00139 
00140 static res_map_t *
00141 getResourceMap
00142 (
00143 IN const char * nameSpace,
00144 IN eCreateFlag createBehavior
00145 )
00146 {
00147         ASSERT(nameSpace, "null");
00148 
00149         namespace_map_t * nmap = getNamespaceMap();
00150         ASSERT(nmap, "null");
00151 
00152         return getResourceMap(nmap, nameSpace, createBehavior);
00153 }
00154 
00155 
00156 
00157 ////////////////////////////////////////////////////////////////////////////////
00158 //
00159 //      internal-only API (pseudo public)
00160 //
00161 ////////////////////////////////////////////////////////////////////////////////
00162 
00163 
00164 
00165 ////////////////////////////////////////////////////////////////////////////////
00166 //
00167 //      public API
00168 //
00169 ////////////////////////////////////////////////////////////////////////////////
00170 
00171 int
00172 getResourceNamespaceCount
00173 (
00174 void
00175 )
00176 throw()
00177 {
00178         namespace_map_t * nmap = getNamespaceMap();
00179         ASSERT(nmap, "null");
00180 
00181         return nmap->size();
00182 }
00183 
00184 
00185 
00186 const char *
00187 getResourceNamespaceName
00188 (
00189 IN int index
00190 )
00191 throw()
00192 {
00193         namespace_map_t * nmap = getNamespaceMap();
00194         ASSERT(nmap, "null");
00195 
00196         for (namespace_map_t::const_iterator i = nmap->begin();
00197              i != nmap->end(); ++i, --index) {
00198                 if (!index) {
00199                         const res_namespace_t * rmap = i->second;
00200                         ASSERT(rmap, "null record in namespace map");
00201                         return rmap->name.c_str();
00202                 }
00203         }
00204 
00205         return NULL;
00206 }
00207 
00208 
00209 
00210 int
00211 getResourceCount
00212 (
00213 IN const char * nameSpace
00214 )
00215 throw()
00216 {
00217         ASSERT(nameSpace, "null");
00218 
00219         res_map_t * rmap = getResourceMap(nameSpace, eNullIfNotExists);
00220         return (rmap) ? rmap->size() : 0;
00221 }
00222 
00223 
00224 
00225 const char *
00226 getResourceName
00227 (
00228 IN const char * nameSpace,
00229 IN int index
00230 )
00231 throw()
00232 {
00233         ASSERT(nameSpace, "null");
00234 
00235         res_map_t * rmap = getResourceMap(nameSpace, eNullIfNotExists);
00236         if (!rmap)
00237                 return false;
00238 
00239         for (res_map_t::const_iterator i = rmap->begin();
00240              i != rmap->end(); ++i, --index) {
00241                 if (!index) {
00242                         const resource_t& res = i->second;
00243                         return res.name.c_str();
00244                 }
00245         }
00246 
00247         return false;
00248 }
00249 
00250 
00251 
00252 int
00253 getResourceSize
00254 (
00255 IN const char * nameSpace,
00256 IN const char * name
00257 )
00258 throw()
00259 {
00260         ASSERT(nameSpace, "null");
00261         ASSERT(name, "null");
00262 
00263         res_map_t * rmap = getResourceMap(nameSpace, eNullIfNotExists);
00264         if (!rmap)
00265                 return false;
00266 
00267         res_map_t::const_iterator i = rmap->find(name);
00268         if (rmap->end() == i) {
00269                 // resource not found!
00270                 return 0;
00271         }
00272 
00273         const resource_t& res = i->second;
00274         return res.bytes;
00275 }
00276 
00277 
00278 
00279 const byte_t *
00280 getResourceData
00281 (
00282 IN const char * nameSpace,
00283 IN const char * name
00284 )
00285 throw()
00286 {
00287         ASSERT(nameSpace, "null");
00288         ASSERT(name, "null");
00289 
00290         res_map_t * rmap = getResourceMap(nameSpace, eNullIfNotExists);
00291         if (!rmap) {
00292                 return NULL;    // no such namespace
00293         }
00294 
00295         res_map_t::const_iterator i = rmap->find(name);
00296         if (rmap->end() == i) {
00297                 return NULL;    // not in map
00298         }
00299 
00300         return i->second.value;
00301 }
00302 
00303 
00304 
00305 void
00306 registerResource
00307 (
00308 IN const char * nameSpace,
00309 IN const char * name,
00310 IN const byte_t * value,
00311 IN int bytes
00312 )
00313 {
00314         ASSERT(nameSpace, "null");
00315         ASSERT(name, "null");
00316         ASSERT(value, "null");
00317         ASSERT(bytes > 0, "invalid byte count: %d", bytes);
00318 
00319         res_map_t * rmap = getResourceMap(nameSpace, eCreateIfNotExists);
00320         ASSERT(rmap, "should always get a map back");
00321 
00322         resource_t res;
00323         res.name = name;
00324         res.value = value;
00325         res.bytes = bytes;
00326 
00327         // we insert (and possibly overwrite!) the new value
00328         rmap->operator[](name) = res;
00329 }
00330