StringMap.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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