00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #ifndef __UT_NameManager_h__
00046 #define __UT_NameManager_h__
00047
00048 #include "UT_API.h"
00049 #include "UT_SymbolTable.h"
00050 #include "UT_String.h"
00051
00052 #include <map>
00053 using namespace std;
00054
00055
00056
00057 template < class DATA_TYPE >
00058 class UT_BaseNameCategory
00059 {
00060 public:
00061 UT_BaseNameCategory(const char* base_name, int start_suffix) : myBaseName(base_name, true)
00062 {
00063 myStartSuffix = start_suffix;
00064 }
00065 ~UT_BaseNameCategory() { }
00066
00067 bool add(const char *num_suffix, DATA_TYPE data, unsigned int &num_entries)
00068 {
00069 long index = myStartSuffix;
00070 if(num_suffix && strlen(num_suffix) > 0)
00071 {
00072 UT_String temp_str(num_suffix);
00073 index = temp_str.toInt();
00074 }
00075
00076 pair<typename map<long, DATA_TYPE >::iterator, bool> result = myEntries.insert(typename map<long, DATA_TYPE >::value_type(index, data));
00077 if(result.second)
00078 {
00079 num_entries++;
00080 return true;
00081 }
00082 else
00083 return false;
00084 }
00085
00086 DATA_TYPE find(const char* num_suffix) const
00087 {
00088 long index = myStartSuffix;
00089 if(num_suffix && strlen(num_suffix) > 0)
00090 {
00091 UT_String temp_str(num_suffix);
00092 index = temp_str.toInt();
00093 }
00094 typename map<long, DATA_TYPE >::const_iterator mi = myEntries.find(index);
00095 if(mi == myEntries.end())
00096 return NULL;
00097 else
00098 return mi->second;
00099 }
00100
00101 bool deleteSymbol(const char* num_suffix, unsigned int &num_entries)
00102 {
00103 long index = myStartSuffix;
00104 if(num_suffix && strlen(num_suffix) > 0)
00105 {
00106 UT_String temp_str(num_suffix);
00107 index = temp_str.toInt();
00108 }
00109 typename map<long, DATA_TYPE >::iterator mi = myEntries.find(index);
00110 if(mi != myEntries.end())
00111 {
00112 myEntries.erase(mi);
00113 if(num_entries > 0)
00114 num_entries--;
00115 return true;
00116 }
00117 else
00118 return false;
00119 }
00120
00121 long getLastIndex(void) const
00122 {
00123 if(myEntries.size() > 0)
00124 {
00125 typename map<long, DATA_TYPE >::const_iterator mi = myEntries.end();
00126 mi--;
00127 return mi->first;
00128 }
00129 else
00130 return myStartSuffix;
00131 }
00132
00133 unsigned entries(void) const { return myEntries.size(); }
00134
00135 private:
00136 int myStartSuffix;
00137 UT_String myBaseName;
00138 map<long, DATA_TYPE > myEntries;
00139 };
00140
00141
00142 template < class DATA_TYPE > int
00143 utNMTraverse(UT_Thing &p, const char *name, void *data)
00144 {
00145 void *entry;
00146 UT_Thing *tablep;
00147 UT_BaseNameCategory<DATA_TYPE> *value;
00148
00149 tablep = &p;
00150 entry = *tablep;
00151 value = (UT_BaseNameCategory<DATA_TYPE> *)entry;
00152
00153 delete value;
00154
00155 return 1;
00156 }
00157
00158 template < class DATA_TYPE >
00159 class UT_NameManager
00160 {
00161 public:
00162
00163
00164
00165
00166
00167
00168
00169 UT_NameManager(int suffix_start_number = 2) { myNbrEntries = 0; mySuffixStartNumber = suffix_start_number - 1; }
00170 virtual ~UT_NameManager() { }
00171
00172
00173 unsigned entries() const { return myNbrEntries; }
00174
00175
00176 bool empty() const { return !myNbrEntries; }
00177
00178
00179
00180
00181
00182 bool deleteSymbol(const char *symbol)
00183 {
00184 if(!symbol)
00185 return false;
00186
00187 UT_String temp_symbol(symbol);
00188 UT_String *base = temp_symbol.base();
00189
00190 UT_Thing temp_thing;
00191 UT_BaseNameCategory<DATA_TYPE>* name_cat;
00192 bool did_find = myTable.findSymbol(*base, &temp_thing);
00193 if(!did_find)
00194 {
00195 delete base;
00196 return false;
00197 }
00198
00199 name_cat = (UT_BaseNameCategory<DATA_TYPE>*)(void*)temp_thing;
00200 UT_ASSERT(name_cat);
00201 if(!name_cat)
00202 {
00203 delete base;
00204 return false;
00205 }
00206
00207 bool res = name_cat->deleteSymbol(temp_symbol.suffix(), myNbrEntries);
00208 if(res)
00209 {
00210
00211 if(name_cat->entries() == 0)
00212 {
00213
00214 myTable.deleteSymbol(*base);
00215 delete name_cat;
00216 }
00217 }
00218
00219 delete base;
00220 return res;
00221 }
00222
00223
00224 void clear(void)
00225 {
00226
00227 myTable.traverse(utNMTraverse<DATA_TYPE>, NULL);
00228
00229
00230 myTable.clear();
00231
00232 myNbrEntries = 0;
00233 }
00234
00235
00236
00237
00238 void getUniqueName(const char* orig_name_in, UT_String& unique_name_out) const
00239 {
00240 unique_name_out.setAlwaysDeep(true);
00241
00242 UT_String temp_name(orig_name_in && strlen(orig_name_in) > 0 ? orig_name_in : "name", false);
00243 UT_String *base = temp_name.base();
00244
00245 UT_Thing temp_thing;
00246 UT_BaseNameCategory<DATA_TYPE>* name_cat;
00247 bool did_find = myTable.findSymbol(*base, &temp_thing);
00248 if(!did_find)
00249 {
00250 unique_name_out = temp_name;
00251 delete base;
00252 return;
00253 }
00254
00255 name_cat = (UT_BaseNameCategory<DATA_TYPE>*)(void*)temp_thing;
00256 UT_ASSERT(name_cat);
00257 if(!name_cat)
00258 {
00259 unique_name_out = temp_name;
00260 delete base;
00261 return;
00262 }
00263
00264
00265 if(name_cat->entries() == 0 && mySuffixStartNumber >= 0)
00266 unique_name_out = *base;
00267 else
00268 {
00269 long idx = name_cat->getLastIndex();
00270 idx++;
00271 unique_name_out.sprintf("%s%ld", (const char*)(*base), idx);
00272 }
00273
00274 delete base;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284 bool addSymbol(const char *symbol, DATA_TYPE data)
00285 {
00286 if(!symbol)
00287 return false;
00288
00289 UT_String temp_symbol(symbol);
00290 UT_String *base = temp_symbol.base();
00291
00292
00293 UT_Thing temp_thing;
00294 UT_BaseNameCategory<DATA_TYPE>* name_cat;
00295 bool did_find = myTable.findSymbol(*base, &temp_thing);
00296 if(!did_find)
00297 {
00298
00299 name_cat = new UT_BaseNameCategory<DATA_TYPE>(*base, mySuffixStartNumber);
00300 myTable.addSymbol(*base, (void*)name_cat);
00301 }
00302 else
00303 name_cat = (UT_BaseNameCategory<DATA_TYPE>*)(void*)temp_thing;
00304
00305
00306 delete base;
00307 return name_cat->add(temp_symbol.suffix(), data, myNbrEntries);
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 const char* addSymbolUnique(const char* symbol, DATA_TYPE data, bool make_name_copy = false)
00319 {
00320 bool generated_name = false;
00321 UT_String temp_name(UT_String::ALWAYS_DEEP);
00322 if(findSymbol(symbol) || !symbol)
00323 {
00324
00325 getUniqueName(symbol, temp_name);
00326 generated_name = true;
00327 }
00328 else
00329 temp_name = symbol;
00330
00331
00332 addSymbol(temp_name, data);
00333
00334 if(!make_name_copy)
00335 return NULL;
00336
00337
00338 if(generated_name)
00339 return strdup((const char*)temp_name);
00340 else
00341 return NULL;
00342 }
00343
00344
00345
00346 DATA_TYPE findSymbol(const char *symbol) const
00347 {
00348 if(!symbol)
00349 return NULL;
00350
00351 UT_String temp_symbol(symbol);
00352 UT_String *base = temp_symbol.base();
00353
00354 UT_Thing temp_thing;
00355 UT_BaseNameCategory<DATA_TYPE>* name_cat;
00356 bool did_find = myTable.findSymbol(*base, &temp_thing);
00357 if(!did_find)
00358 return NULL;
00359
00360 name_cat = (UT_BaseNameCategory<DATA_TYPE>*)(void*)temp_thing;
00361 UT_ASSERT(name_cat);
00362 if(!name_cat)
00363 {
00364 delete base;
00365 return NULL;
00366 }
00367
00368 delete base;
00369 return name_cat->find(temp_symbol.suffix());
00370 }
00371
00372 private:
00373
00374 UT_SymbolTable myTable;
00375 unsigned int myNbrEntries;
00376 int mySuffixStartNumber;
00377 };
00378
00379 #endif