00001 /** @file rutz/assocarray.cc generic associative arrays, implemented as 00002 a thin wrapper around std::map<rutz::fstring, void*> */ 00003 /////////////////////////////////////////////////////////////////////// 00004 // 00005 // Copyright (c) 2004-2007 University of Southern California 00006 // Rob Peters <rjpeters at usc dot edu> 00007 // 00008 // created: Thu Oct 14 18:42:05 2004 00009 // commit: $Id: assocarray.cc 8274 2007-04-19 17:44:48Z rjpeters $ 00010 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/assocarray.cc $ 00011 // 00012 // -------------------------------------------------------------------- 00013 // 00014 // This file is part of GroovX. 00015 // [http://ilab.usc.edu/rjpeters/groovx/] 00016 // 00017 // GroovX is free software; you can redistribute it and/or modify it 00018 // under the terms of the GNU General Public License as published by 00019 // the Free Software Foundation; either version 2 of the License, or 00020 // (at your option) any later version. 00021 // 00022 // GroovX is distributed in the hope that it will be useful, but 00023 // WITHOUT ANY WARRANTY; without even the implied warranty of 00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00025 // General Public License for more details. 00026 // 00027 // You should have received a copy of the GNU General Public License 00028 // along with GroovX; if not, write to the Free Software Foundation, 00029 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00030 // 00031 /////////////////////////////////////////////////////////////////////// 00032 00033 #ifndef GROOVX_RUTZ_ASSOCARRAY_CC_UTC20050626084020_DEFINED 00034 #define GROOVX_RUTZ_ASSOCARRAY_CC_UTC20050626084020_DEFINED 00035 00036 #include "assocarray.h" 00037 00038 #include "rutz/error.h" 00039 #include "rutz/fstring.h" 00040 #include "rutz/sfmt.h" 00041 00042 #include <algorithm> // for lexicographical_compare() 00043 #include <map> 00044 #include <sstream> 00045 00046 #include "rutz/trace.h" 00047 00048 struct rutz::assoc_array_base::impl 00049 { 00050 impl(kill_func_t* f, const char* descr, bool nocase) 00051 : 00052 values(fstring_cmp(nocase)), 00053 kill_func(f), 00054 key_description(descr) 00055 {} 00056 00057 static bool nocase_char_cmp(char c1, char c2) 00058 { 00059 return toupper(c1) < toupper(c2); 00060 } 00061 00062 struct fstring_cmp 00063 { 00064 fstring_cmp(bool nocase_) : nocase(nocase_) {} 00065 00066 const bool nocase; 00067 00068 bool operator()(const rutz::fstring& s1, 00069 const rutz::fstring& s2) const 00070 { 00071 if (nocase) 00072 { 00073 return std::lexicographical_compare 00074 (s1.c_str(), s1.c_str() + s1.length(), 00075 s2.c_str(), s2.c_str() + s2.length(), 00076 nocase_char_cmp); 00077 } 00078 00079 // else... 00080 return (s1 < s2); 00081 } 00082 }; 00083 00084 typedef std::map<rutz::fstring, void*, fstring_cmp> map_t; 00085 00086 map_t values; 00087 kill_func_t* kill_func; 00088 rutz::fstring key_description; 00089 }; 00090 00091 rutz::assoc_array_base::assoc_array_base(kill_func_t* f, 00092 const char* descr, 00093 bool nocase) : 00094 rep(new impl(f, descr, nocase)) 00095 { 00096 GVX_TRACE("rutz::assoc_array_base::assoc_array_base"); 00097 } 00098 00099 rutz::assoc_array_base::~assoc_array_base() 00100 { 00101 GVX_TRACE("rutz::assoc_array_base::~assoc_array_base"); 00102 clear(); 00103 } 00104 00105 rutz::fstring rutz::assoc_array_base:: 00106 get_known_keys(const char* sep) const 00107 { 00108 std::ostringstream result; 00109 00110 bool first = true; 00111 00112 for (impl::map_t::iterator ii = rep->values.begin(); 00113 ii != rep->values.end(); 00114 ++ii) 00115 { 00116 if (ii->second != 0) 00117 { 00118 if (!first) result << sep; 00119 00120 result << ii->first; 00121 00122 first = false; 00123 } 00124 } 00125 00126 return rutz::fstring(result.str().c_str()); 00127 } 00128 00129 void rutz::assoc_array_base:: 00130 throw_for_key(const char* key, const rutz::file_pos& pos) const 00131 { 00132 throw rutz::error(rutz::sfmt("known keys are:\n\t%s\nunknown %s '%s'", 00133 get_known_keys("\n\t").c_str(), 00134 rep->key_description.c_str(), 00135 key), 00136 pos); 00137 } 00138 00139 void rutz::assoc_array_base:: 00140 throw_for_key(const rutz::fstring& key, const rutz::file_pos& pos) const 00141 { 00142 throw_for_key(key.c_str(), pos); 00143 } 00144 00145 void rutz::assoc_array_base::clear() 00146 { 00147 GVX_TRACE("rutz::assoc_array_base::clear"); 00148 for (impl::map_t::iterator ii = rep->values.begin(); 00149 ii != rep->values.end(); 00150 ++ii) 00151 { 00152 if (rep->kill_func != 0) rep->kill_func(ii->second); 00153 ii->second = 0; 00154 } 00155 00156 delete rep; 00157 } 00158 00159 void* rutz::assoc_array_base::get_value_for_key(const rutz::fstring& key) const 00160 { 00161 GVX_TRACE("rutz::assoc_array_base::get_value_for_key"); 00162 return rep->values[key]; 00163 } 00164 00165 void* rutz::assoc_array_base::get_value_for_key(const char* key) const 00166 { 00167 return get_value_for_key(rutz::fstring(key)); 00168 } 00169 00170 void rutz::assoc_array_base::set_value_for_key(const char* key, void* ptr) 00171 { 00172 GVX_TRACE("rutz::assoc_array_base::set_value_for_key"); 00173 rutz::fstring skey(key); 00174 void*& ptr_slot = rep->values[skey]; 00175 if (rep->kill_func != 0) rep->kill_func(ptr_slot); 00176 ptr_slot = ptr; 00177 } 00178 00179 static const char __attribute__((used)) vcid_groovx_rutz_assocarray_cc_utc20050626084020[] = "$Id: assocarray.cc 8274 2007-04-19 17:44:48Z rjpeters $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/assocarray.cc $"; 00180 #endif // !GROOVX_RUTZ_ASSOCARRAY_CC_UTC20050626084020_DEFINED