tagDictionary.cpp
Engine/source/core/tagDictionary.cpp
Public Variables
Public Functions
hashDefine(StringTableEntry define, S32 tsize)
Detailed Description
Public Variables
TagDictionary tagDictionary
Public Functions
hashDefine(StringTableEntry define, S32 tsize)
hashId(S32 id, S32 tsize)
idCompare(const void * in_p1, const void * in_p2)
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "core/strings/stringFunctions.h" 25#include "core/tagDictionary.h" 26#include "core/stream/stream.h" 27 28namespace { 29const char TAG_ASCII_HEADER[] = "// Auto-Generated by TagDictionary class"; 30} // namespace 31 32TagDictionary tagDictionary; 33 34TagDictionary::TagDictionary() 35{ 36 numBuckets = 29; 37 defineHashBuckets = (TagEntry **) dMalloc(numBuckets * sizeof(TagEntry *)); 38 idHashBuckets = (TagEntry **) dMalloc(numBuckets * sizeof(TagEntry *)); 39 40 S32 i; 41 for(i = 0; i < numBuckets; i++) 42 { 43 defineHashBuckets[i] = NULL; 44 idHashBuckets[i] = NULL; 45 } 46 numEntries = 0; 47 entryChain = NULL; 48} 49 50TagDictionary::~TagDictionary() 51{ 52 dFree(defineHashBuckets); 53 dFree(idHashBuckets); 54} 55 56//------------------------------------------------------------------------------ 57 58static inline S32 hashId(S32 id, S32 tsize) 59{ 60 return id % tsize; 61} 62 63static inline S32 hashDefine(StringTableEntry define, S32 tsize) 64{ 65 return ((S32)((dsize_t)define) >> 2) % tsize; 66} 67 68//------------------------------------------------------------------------------ 69 70bool TagDictionary::addEntry(S32 value, StringTableEntry define, StringTableEntry string) 71{ 72 if(!value) 73 return false; 74//#pragma message "put console prints back" 75 if(idToDefine(value)) 76 { 77 AssertWarn(false, avar("Error: id %d already defined to a tag.", value)); 78 //Con::printf("Error: id %d already defined to a tag.", value); 79 return false; 80 } 81 S32 tempTag; 82 if((tempTag = defineToId(define)) != 0) 83 { 84 AssertWarn(false, avar("Error: define %s already defined to tag %d.", define, tempTag)); 85 //Con::printf("Error: define %s already defined to tag %d.", define, tempTag); 86 return false; 87 } 88 TagEntry *newEntry = (TagEntry *) mempool.alloc(sizeof(TagEntry)); 89 90 newEntry->id = value; 91 newEntry->define = define; 92 newEntry->string = string; 93 94 numEntries++; 95 if(numEntries > numBuckets) 96 { 97 numBuckets = numBuckets * 2 + 1; 98 defineHashBuckets = (TagEntry **) dRealloc(defineHashBuckets, numBuckets * sizeof(TagEntry *)); 99 idHashBuckets = (TagEntry **) dRealloc(idHashBuckets, numBuckets * sizeof(TagEntry *)); 100 S32 i; 101 for(i = 0; i < numBuckets; i++) 102 { 103 defineHashBuckets[i] = NULL; 104 idHashBuckets[i] = NULL; 105 } 106 TagEntry *walk = entryChain; 107 108 while(walk) 109 { 110 S32 index = hashId(walk->id, numBuckets); 111 walk->idHashLink = idHashBuckets[index]; 112 idHashBuckets[index] = walk; 113 114 index = hashDefine(walk->define, numBuckets); 115 walk->defineHashLink = defineHashBuckets[index]; 116 defineHashBuckets[index] = walk; 117 118 walk = walk->chain; 119 } 120 } 121 newEntry->chain = entryChain; 122 entryChain = newEntry; 123 124 S32 index = hashId(newEntry->id, numBuckets); 125 newEntry->idHashLink = idHashBuckets[index]; 126 idHashBuckets[index] = newEntry; 127 128 index = hashDefine(newEntry->define, numBuckets); 129 newEntry->defineHashLink = defineHashBuckets[index]; 130 defineHashBuckets[index] = newEntry; 131 return true; 132} 133 134//------------------------------------------------------------------------------ 135 136bool TagDictionary::writeHeader(Stream& io_sio) 137{ 138 char buff[15000]; 139 Vector<S32> v; 140 141 TagEntry *walk = entryChain; 142 while(walk) 143 { 144 v.push_back(walk->id); 145 walk = walk->chain; 146 } 147 148 sortIdVector(v); 149 150 io_sio.write( sizeof(TAG_ASCII_HEADER)-1, TAG_ASCII_HEADER); 151 io_sio.write( 4, "\r\n\r\n"); 152 153 char exclude[256]; 154 char tempBuf[256]; 155 dSprintf(exclude, sizeof(exclude), "_TD%10.10u_H_", Platform::getVirtualMilliseconds() / 4); 156 157 dSprintf(tempBuf, sizeof(tempBuf), "#ifndef %s\r\n", exclude); 158 io_sio.write(dStrlen(tempBuf), tempBuf); 159 dSprintf(tempBuf, sizeof(tempBuf), "#define %s\r\n\r\n", exclude); 160 io_sio.write(dStrlen(tempBuf), tempBuf); 161 162 for (U32 i = 0; i < v.size(); i++) 163 { 164 dSprintf(buff, sizeof(buff), "#define %s (%d)\r\n", idToDefine(v[i]), v[i]); 165 io_sio.write(dStrlen(buff), buff); 166 } 167 168 dSprintf(tempBuf, sizeof(tempBuf), "\r\n#endif // %s\r\n", exclude); 169 io_sio.write(dStrlen(tempBuf), tempBuf); 170 171 return (io_sio.getStatus() == Stream::Ok); 172} 173 174//------------------------------------------------------------------------------ 175 176StringTableEntry TagDictionary::defineToString(StringTableEntry tag) 177{ 178 S32 index = hashDefine(tag, numBuckets); 179 if (index < 0) return NULL; 180 TagEntry *walk = defineHashBuckets[index]; 181 while(walk) 182 { 183 if(walk->define == tag) 184 return walk->string; 185 walk = walk->defineHashLink; 186 } 187 return NULL; 188} 189 190S32 TagDictionary::defineToId(StringTableEntry tag) 191{ 192 S32 index = hashDefine(tag, numBuckets); 193 if (index < 0) return 0; 194 TagEntry *walk = defineHashBuckets[index]; 195 while(walk) 196 { 197 if(walk->define == tag) 198 return walk->id; 199 walk = walk->defineHashLink; 200 } 201 return 0; 202} 203 204StringTableEntry TagDictionary::idToString(S32 id) 205{ 206 S32 index = hashId(id, numBuckets); 207 if (index < 0) return NULL; 208 TagEntry *walk = idHashBuckets[index]; 209 while(walk) 210 { 211 if(walk->id == id) 212 return walk->string; 213 walk = walk->idHashLink; 214 } 215 return NULL; 216} 217 218StringTableEntry TagDictionary::idToDefine(S32 id) 219{ 220 S32 index = hashId(id, numBuckets); 221 if (index < 0) return NULL; 222 TagEntry *walk = idHashBuckets[index]; 223 while(walk) 224 { 225 if(walk->id == id) 226 return walk->define; 227 walk = walk->idHashLink; 228 } 229 return NULL; 230} 231 232//------------------------------------------------------------------------------ 233 234void TagDictionary::findIDs(Vector<S32>& out_v, 235 const S32 in_minID, 236 const S32 in_maxID ) 237{ 238 //locate all IDs that lie in between minID and maxID 239 240 TagEntry *walk = entryChain; 241 while(walk) 242 { 243 if(walk->id > in_minID && walk->id < in_maxID) 244 out_v.push_back(walk->id); 245 walk = walk->chain; 246 } 247 sortIdVector(out_v); 248} 249 250 251//------------------------------------------------------------------------------ 252void TagDictionary::findStrings(Vector<S32>& out_v, const char* in_pPattern) 253{ 254 //locate all strings that match the pattern 255 // 256 TagEntry *walk = entryChain; 257 while(walk) 258 { 259 if (match(in_pPattern, walk->string)) 260 out_v.push_back(walk->id); 261 walk = walk->chain; 262 } 263 sortIdVector(out_v); 264} 265 266 267//------------------------------------------------------------------------------ 268void TagDictionary::findDefines(Vector<S32>& out_v, const char* in_pPattern) 269{ 270 //locate all define strings that match the pattern and add their ID 271 //to the given vector 272 // 273 TagEntry *walk = entryChain; 274 while(walk) 275 { 276 if (match(in_pPattern, walk->define)) 277 out_v.push_back(walk->id); 278 walk = walk->chain; 279 } 280 sortIdVector(out_v); 281} 282 283//------------------------------------------------------------------------------ 284 285bool TagDictionary::match(const char* pattern, const char* str) 286{ 287 //quick and dirty recursive DOS-style wild-card string matcher 288 // 289 switch (*pattern) { 290 case '\0': 291 return !*str; 292 293 case '*': 294 return match(pattern+1, str) || (*str && match(pattern, str+1)); 295 296 case '?': 297 return *str && match(pattern+1, str+1); 298 299 default: 300 return (*pattern == *str) && match(pattern+1, str+1); 301 } 302} 303 304//------------------------------------------------------------------------------ 305 306static S32 QSORT_CALLBACK idCompare(const void *in_p1, const void *in_p2) 307{ 308 return *((S32 *) in_p1) - *((S32 *) in_p2); 309} 310 311void TagDictionary::sortIdVector(Vector<S32>& out_v) 312{ 313 dQsort(out_v.address(), out_v.size(), sizeof(S32), idCompare); 314} 315 316