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         resource_t(void) throw() : value(NULL) { }
00044 
00045         const char *            value;  // for strings
00046 };
00047 
00048 
00049 typedef std::map<std::string, resource_t> res_map_t;
00050 
00051 
00052 typedef std::map<std::string, smart_ptr<res_map_t> > namespace_map_t;
00053 
00054 
00055 
00056 ////////////////////////////////////////////////////////////////////////////////
00057 //
00058 //      static helper methods
00059 //
00060 ////////////////////////////////////////////////////////////////////////////////
00061 
00062 static namespace_map_t *
00063 getNamespaceMap
00064 (
00065 void
00066 )
00067 throw()
00068 {
00069         // our static (global) map of all resources, keyed by namespace
00070         static namespace_map_t * s_map = NULL;
00071         if (!s_map) {
00072                 s_map = new namespace_map_t;
00073                 ASSERT(s_map, "out of memory");
00074         }
00075         return s_map;
00076 }
00077 
00078 
00079 
00080 static res_map_t *
00081 getResourceMap
00082 (
00083 IN namespace_map_t * nmap,
00084 IN const char * nameSpace,
00085 IN eCreateFlag createBehavior
00086 )
00087 {
00088         ASSERT(nmap, "null");
00089         ASSERT(nameSpace, "null");
00090 
00091         namespace_map_t::iterator i = nmap->find(nameSpace);
00092         if (nmap->end() != i) {
00093                 // found in map!
00094                 res_map_t * rmap = i->second;
00095                 ASSERT(rmap, "null resource map in namespace map");
00096                 return rmap;
00097         }
00098 
00099         // not in map
00100         if (eCreateIfNotExists != createBehavior) {
00101                 // not supposed to create it!
00102                 return NULL;
00103         }
00104 
00105         // we need to create a new entry
00106         smart_ptr<res_map_t> rmap = new res_map_t;
00107         ASSERT(rmap, "out of memory");
00108 
00109         // add this new resource map to the global map and return it
00110         nmap->operator[](nameSpace) = rmap;
00111         return rmap;
00112 }
00113 
00114 
00115 
00116 static res_map_t *
00117 getResourceMap
00118 (
00119 IN const char * nameSpace,
00120 IN eCreateFlag createBehavior
00121 )
00122 {
00123         ASSERT(nameSpace, "null");
00124 
00125         namespace_map_t * nmap = getNamespaceMap();
00126         ASSERT(nmap, "null");
00127 
00128         return getResourceMap(nmap, nameSpace, createBehavior);
00129 }
00130 
00131 
00132 
00133 ////////////////////////////////////////////////////////////////////////////////
00134 //
00135 //      internal-only API (pseudo public)
00136 //
00137 ////////////////////////////////////////////////////////////////////////////////
00138 
00139 
00140 
00141 ////////////////////////////////////////////////////////////////////////////////
00142 //
00143 //      public API
00144 //
00145 ////////////////////////////////////////////////////////////////////////////////
00146 
00147 int
00148 getResourceNamespaceCount
00149 (
00150 void
00151 )
00152 throw()
00153 {
00154         namespace_map_t * nmap = getNamespaceMap();
00155         ASSERT(nmap, "null");
00156 
00157         return nmap->size();
00158 }
00159 
00160 
00161 
00162 const char *
00163 getResourceNamespaceName
00164 (
00165 IN int index
00166 )
00167 throw()
00168 {
00169         namespace_map_t * nmap = getNamespaceMap();
00170         ASSERT(nmap, "null");
00171 
00172         for (namespace_map_t::const_iterator i = nmap->begin();
00173              i != nmap->end(); ++i, --index) {
00174                 if (!index) {
00175                         return i->first.c_str();
00176                 }
00177         }
00178 
00179         return NULL;
00180 }
00181 
00182 
00183 
00184 int
00185 getStringResourceCount
00186 (
00187 IN const char * nameSpace
00188 )
00189 throw()
00190 {
00191         ASSERT(nameSpace, "null");
00192 
00193         res_map_t * rmap = getResourceMap(nameSpace, eNullIfNotExists);
00194         return (rmap) ? rmap->size() : 0;
00195 }
00196 
00197 
00198 
00199 const char *
00200 getStringResourceName
00201 (
00202 IN const char * nameSpace,
00203 IN int index
00204 )
00205 throw()
00206 {
00207         ASSERT(nameSpace, "null");
00208 
00209         res_map_t * rmap = getResourceMap(nameSpace, eNullIfNotExists);
00210         if (!rmap)
00211                 return NULL;
00212 
00213         for (res_map_t::const_iterator i = rmap->begin();
00214              i != rmap->end(); ++i, --index) {
00215                 if (!index) {
00216                         return i->first.c_str();
00217                 }
00218         }
00219 
00220         return NULL;
00221 }
00222 
00223 
00224 
00225 const char *
00226 getStringResource
00227 (
00228 IN const char * nameSpace,
00229 IN const char * name
00230 )
00231 throw()
00232 {
00233         ASSERT(nameSpace, "null");
00234         ASSERT(name, "null");
00235 
00236         res_map_t * rmap = getResourceMap(nameSpace, eNullIfNotExists);
00237         if (!rmap) {
00238                 return NULL;    // no such namespace
00239         }
00240 
00241         res_map_t::const_iterator i = rmap->find(name);
00242         if (rmap->end() == i) {
00243                 return NULL;    // not in map
00244         }
00245 
00246         return i->second.value;
00247 }
00248 
00249 
00250 
00251 void
00252 registerStringResource
00253 (
00254 IN const char * nameSpace,
00255 IN const char * name,
00256 IN const char * value
00257 )
00258 {
00259         ASSERT(nameSpace, "null");
00260         ASSERT(name, "null");
00261         ASSERT(value, "null");
00262 
00263         res_map_t * rmap = getResourceMap(nameSpace, eCreateIfNotExists);
00264         ASSERT(rmap, "should always get a map back");
00265 
00266         resource_t res;
00267         res.value = value;
00268 
00269         // we insert (and possibly overwrite!) the new value
00270         rmap->operator[](name) = res;
00271 }
00272