libStatGen Software
1
|
00001 /* 00002 * Copyright (C) 2010 Regents of the University of Michigan 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #include "StringMap.h" 00019 00020 int StringMap::alloc = 8; 00021 00022 StringMap::StringMap(int startsize) 00023 { 00024 count = 0; 00025 size = (startsize + alloc) / alloc * alloc; 00026 strings = new ::String * [size]; 00027 objects = new void * [size]; 00028 }; 00029 00030 StringMap::~StringMap() 00031 { 00032 for (int i = 0; i < count; i++) 00033 delete strings[i]; 00034 delete [] strings; 00035 delete [] objects; 00036 } 00037 00038 void StringMap::Grow(int newsize) 00039 { 00040 if (newsize >= size) 00041 { 00042 if ((newsize >> 1) >= size) 00043 size = (newsize + alloc) / alloc * alloc; 00044 else 00045 { 00046 size = alloc; 00047 while (size <= newsize) 00048 size *= 2; 00049 } 00050 00051 size = (newsize + alloc) / alloc * alloc; 00052 00053 ::String ** newStrings = new ::String * [size]; 00054 void ** newObjects = new void * [size]; 00055 00056 for (int i = 0; i < count; i++) 00057 { 00058 newStrings[i] = strings[i]; 00059 newObjects[i] = objects[i]; 00060 } 00061 00062 delete [] strings; 00063 delete [] objects; 00064 00065 strings = newStrings; 00066 objects = newObjects; 00067 } 00068 } 00069 00070 int StringMap::Add(const ::String & key, void * object) 00071 { 00072 if (count == 0) 00073 { 00074 Grow(1); 00075 strings[0] = new ::String(key); 00076 objects[0] = object; 00077 return count++; 00078 } 00079 00080 int left = 0; 00081 int right = count - 1; 00082 00083 while (right > left) 00084 { 00085 int probe = (left + right) / 2; 00086 int test = key.SlowCompare(*(strings[probe])); 00087 00088 if (test == 0) 00089 { 00090 objects[probe] = object; 00091 return probe; 00092 } 00093 00094 if (test < 0) 00095 right = probe - 1; 00096 else 00097 left = probe + 1; 00098 } 00099 00100 int insertAt = left; 00101 int test = key.SlowCompare(*(strings[insertAt])); 00102 00103 if (test == 0) 00104 { 00105 objects[insertAt] = object; 00106 return insertAt; 00107 } 00108 00109 if (test > 0) insertAt++; 00110 00111 Grow(count + 1); 00112 00113 if (insertAt < count) 00114 { 00115 for (int i = count; i > insertAt; i--) 00116 { 00117 strings[i] = strings[i - 1]; 00118 objects[i] = objects[i - 1]; 00119 } 00120 } 00121 00122 strings[insertAt] = new ::String(key); 00123 objects[insertAt] = object; 00124 count++; 00125 00126 return insertAt; 00127 } 00128 00129 int StringMap::Find(const ::String & s, void *(*create_object)()) 00130 { 00131 if (!count) 00132 return create_object == NULL ? -1 : Add(s, create_object()); 00133 00134 int left = 0; 00135 int right = count - 1; 00136 00137 while (right > left) 00138 { 00139 int probe = (left + right) / 2; 00140 int test = s.SlowCompare(*(strings[probe])); 00141 00142 if (test == 0) 00143 return probe; 00144 00145 if (test < 0) 00146 right = probe - 1; 00147 else 00148 left = probe + 1; 00149 } 00150 00151 int position = left; 00152 int test = s.SlowCompare(*(strings[left])); 00153 00154 if (test == 0) 00155 return position; 00156 00157 if (create_object == NULL) 00158 return -1; 00159 00160 if (test > 0) 00161 position++; 00162 00163 Grow(count + 1); 00164 00165 if (position < count) 00166 { 00167 for (int i = count; i > position; i--) 00168 { 00169 strings[i] = strings[i - 1]; 00170 objects[i] = objects[i - 1]; 00171 } 00172 } 00173 00174 strings[position] = new ::String(s); 00175 objects[position] = create_object(); 00176 count++; 00177 00178 return position; 00179 } 00180 00181 int StringMap::Find(const ::String & s) const 00182 { 00183 if (!count) return -1; 00184 00185 int left = 0; 00186 int right = count - 1; 00187 00188 while (right > left) 00189 { 00190 int probe = (left + right) / 2; 00191 int test = s.SlowCompare(*(strings[probe])); 00192 00193 if (test == 0) 00194 return probe; 00195 00196 if (test < 0) 00197 right = probe - 1; 00198 else 00199 left = probe + 1; 00200 } 00201 00202 int position = left; 00203 int test = s.SlowCompare(*(strings[left])); 00204 00205 if (test == 0) 00206 return position; 00207 00208 return -1; 00209 } 00210 00211 int StringMap::FindStem(const ::String & stem) const 00212 { 00213 if (!count) return -1; 00214 00215 int left = 0; 00216 int right = count - 1; 00217 00218 while (right > left) 00219 { 00220 int probe = (left + right) / 2; 00221 int test = strings[probe]->SlowCompareToStem(stem); 00222 00223 if (test == 0) 00224 { 00225 if ((left < probe && strings[probe-1]->SlowCompareToStem(stem) == 0) || 00226 (right > probe && strings[probe+1]->SlowCompareToStem(stem) == 0)) 00227 return -2; 00228 00229 return probe; 00230 } 00231 00232 if (test > 0) 00233 right = probe - 1; 00234 else 00235 left = probe + 1; 00236 } 00237 00238 if (strings[left]->SlowCompareToStem(stem) == 0) 00239 return left; 00240 00241 return -1; 00242 } 00243 00244 int StringMap::FindFirstStem(const ::String & stem) const 00245 { 00246 if (!count) return -1; 00247 00248 int left = 0; 00249 int right = count - 1; 00250 00251 while (right > left) 00252 { 00253 int probe = (left + right) / 2; 00254 int test = strings[probe]->SlowCompareToStem(stem); 00255 00256 if (test == 0) 00257 { 00258 while (left < probe && strings[probe-1]->SlowCompareToStem(stem) == 0) 00259 probe--; 00260 00261 return probe; 00262 } 00263 00264 if (test > 0) 00265 right = probe - 1; 00266 else 00267 left = probe + 1; 00268 } 00269 00270 if (strings[left]->SlowCompareToStem(stem) == 0) 00271 return left; 00272 00273 return -1; 00274 } 00275 00276 void * StringMap::CreateMap() 00277 { 00278 return (void *) new StringMap(); 00279 } 00280 00281 void StringMap::Clear() 00282 { 00283 for (int i = 0; i < count; i++) 00284 delete strings[i]; 00285 count = 0; 00286 } 00287 00288 void StringMap::Delete(int index) 00289 { 00290 count--; 00291 00292 delete strings[index]; 00293 00294 for (int i = index; i < count; i++) 00295 { 00296 strings[i] = strings[i+1]; 00297 objects[i] = objects[i+1]; 00298 } 00299 } 00300 00301 // StringIntMap class 00302 // 00303 00304 int StringIntMap::alloc = 8; 00305 00306 StringIntMap::StringIntMap(int startsize) 00307 { 00308 count = 0; 00309 size = (startsize + alloc) / alloc * alloc; 00310 strings = new ::String * [size]; 00311 integers = new int[size]; 00312 }; 00313 00314 StringIntMap::~StringIntMap() 00315 { 00316 for (int i = 0; i < count; i++) 00317 delete strings[i]; 00318 delete [] strings; 00319 delete [] integers; 00320 } 00321 00322 void StringIntMap::Grow(int newsize) 00323 { 00324 if (newsize >= size) 00325 { 00326 if ((newsize >> 1) >= size) 00327 size = (newsize + alloc) / alloc * alloc; 00328 else 00329 { 00330 size = alloc; 00331 while (size <= newsize) 00332 size *= 2; 00333 } 00334 00335 ::String ** newStrings = new ::String * [size]; 00336 int * newIntegers = new int [size]; 00337 00338 for (int i = 0; i < count; i++) 00339 { 00340 newStrings[i] = strings[i]; 00341 newIntegers[i] = integers[i]; 00342 } 00343 00344 delete [] strings; 00345 delete [] integers; 00346 00347 strings = newStrings; 00348 integers = newIntegers; 00349 } 00350 } 00351 00352 int StringIntMap::Add(const ::String & key, int integer) 00353 { 00354 if (count == 0) 00355 { 00356 Grow(1); 00357 strings[0] = new ::String(key); 00358 integers[0] = integer; 00359 return count++; 00360 } 00361 00362 int left = 0; 00363 int right = count - 1; 00364 00365 while (right > left) 00366 { 00367 int probe = (left + right) / 2; 00368 int test = key.SlowCompare(*(strings[probe])); 00369 00370 if (test == 0) 00371 { 00372 integers[probe] = integer; 00373 return probe; 00374 } 00375 00376 if (test < 0) 00377 right = probe - 1; 00378 else 00379 left = probe + 1; 00380 } 00381 00382 int insertAt = left; 00383 int test = key.SlowCompare(*(strings[insertAt])); 00384 00385 if (test == 0) 00386 { 00387 integers[insertAt] = integer; 00388 return insertAt; 00389 } 00390 00391 if (test > 0) insertAt++; 00392 00393 Grow(count + 1); 00394 00395 if (insertAt < count) 00396 { 00397 for (int i = count; i > insertAt; i--) 00398 { 00399 strings[i] = strings[i - 1]; 00400 integers[i] = integers[i - 1]; 00401 } 00402 } 00403 00404 strings[insertAt] = new ::String(key); 00405 integers[insertAt] = integer; 00406 count++; 00407 00408 return insertAt; 00409 } 00410 00411 int StringIntMap::Find(const ::String & s, int defaultValue) 00412 { 00413 if (!count) 00414 return Add(s, defaultValue); 00415 00416 int left = 0; 00417 int right = count - 1; 00418 00419 while (right > left) 00420 { 00421 int probe = (left + right) / 2; 00422 int test = s.SlowCompare(*(strings[probe])); 00423 00424 if (test == 0) 00425 return probe; 00426 00427 if (test < 0) 00428 right = probe - 1; 00429 else 00430 left = probe + 1; 00431 } 00432 00433 int position = left; 00434 int test = s.SlowCompare(*(strings[left])); 00435 00436 if (test == 0) 00437 return position; 00438 00439 if (test > 0) 00440 position++; 00441 00442 Grow(count + 1); 00443 00444 if (position < count) 00445 { 00446 for (int i = count; i > position; i--) 00447 { 00448 strings[i] = strings[i - 1]; 00449 integers[i] = integers[i - 1]; 00450 } 00451 } 00452 00453 strings[position] = new ::String(s); 00454 integers[position] = defaultValue; 00455 count++; 00456 00457 return position; 00458 } 00459 00460 int StringIntMap::Find(const ::String & s) const 00461 { 00462 if (!count) return -1; 00463 00464 int left = 0; 00465 int right = count - 1; 00466 00467 while (right > left) 00468 { 00469 int probe = (left + right) / 2; 00470 int test = s.SlowCompare(*(strings[probe])); 00471 00472 if (test == 0) 00473 return probe; 00474 00475 if (test < 0) 00476 right = probe - 1; 00477 else 00478 left = probe + 1; 00479 } 00480 00481 int position = left; 00482 int test = s.SlowCompare(*(strings[left])); 00483 00484 if (test == 0) 00485 return position; 00486 00487 return -1; 00488 } 00489 00490 int StringIntMap::FindStem(const ::String & stem) const 00491 { 00492 if (!count) return -1; 00493 00494 int left = 0; 00495 int right = count - 1; 00496 00497 while (right > left) 00498 { 00499 int probe = (left + right) / 2; 00500 int test = strings[probe]->SlowCompareToStem(stem); 00501 00502 if (test == 0) 00503 { 00504 if ((left < probe && strings[probe-1]->SlowCompareToStem(stem) == 0) || 00505 (right > probe && strings[probe+1]->SlowCompareToStem(stem) == 0)) 00506 return -2; 00507 00508 return probe; 00509 } 00510 00511 if (test > 0) 00512 right = probe - 1; 00513 else 00514 left = probe + 1; 00515 } 00516 00517 if (strings[left]->SlowCompareToStem(stem) == 0) 00518 return left; 00519 00520 return -1; 00521 } 00522 00523 void StringIntMap::Clear() 00524 { 00525 for (int i = 0; i < count; i++) 00526 delete strings[i]; 00527 count = 0; 00528 } 00529 00530 int StringIntMap::GetCount(const ::String & key) const 00531 { 00532 int index = Find(key); 00533 return index == -1 ? 0 : integers[index]; 00534 } 00535 00536 int StringIntMap::IncrementCount(const ::String & key) 00537 { 00538 int index = Find(key); 00539 00540 if (index != -1) 00541 return ++(integers[index]); 00542 00543 SetInteger(key, 1); 00544 return 1; 00545 } 00546 00547 int StringIntMap::DecrementCount(const ::String & key) 00548 { 00549 int index = Find(key); 00550 00551 if (index != -1) 00552 return --(integers[index]); 00553 00554 SetInteger(key, -1); 00555 return -1; 00556 } 00557 00558 void StringIntMap::Delete(int index) 00559 { 00560 count--; 00561 00562 delete strings[index]; 00563 00564 for (int i = index; i < count; i++) 00565 { 00566 strings[i] = strings[i+1]; 00567 integers[i] = integers[i+1]; 00568 } 00569 } 00570 00571 00572