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 #include "fuzzy/fuzzyphonetic.hpp"
00029 #include "base/list.hpp"
00030 #include "base/map.hpp"
00031 #include "base/vector.hpp"
00032 #include "base/memory.hpp"
00033
00034 BEGIN_TERIMBER_NAMESPACE
00035 #pragma pack(4)
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 namespace fuzzyphonetic
00122 {
00123
00124 const ub1_t empty_code = 0xff;
00125 const ub1_t blank_code = 0xfe;
00126
00127
00128
00129
00130 class metaphone_keeper
00131 {
00132 public:
00133 metaphone_keeper(_list< ub1_t >& backet,
00134 #ifdef DOUBLEMETAPHONE
00135 _list< ub1_t >& backet2,
00136 #endif
00137 byte_allocator& all) : _backet(backet),
00138 #ifdef DOUBLEMETAPHONE
00139 _backet2(backet),
00140 _alternative(false),
00141 #endif
00142 _all(all)
00143 {
00144 clear();
00145 }
00146
00147 inline void clear()
00148 {
00149 _code[0] = _code[1] = _alt[0] = _alt[1] = empty_code;
00150 }
00151
00152 inline void metaph_add()
00153 {
00154 if (_code[0] != empty_code)
00155 {
00156 _backet.push_back(_all, _code[0]);
00157 #ifdef DOUBLEMETAPHONE
00158 _backet2.push_back(_all, _code[0]);
00159 #endif
00160 }
00161 if (_code[1] != empty_code)
00162 {
00163 _backet.push_back(_all, _code[1]);
00164 #ifdef DOUBLEMETAPHONE
00165 _backet2.push_back(_all, _code[1]);
00166 #endif
00167 }
00168 }
00169
00170 inline void metaph_add_alt()
00171 {
00172 if (_code[0] != empty_code)
00173 _backet.push_back(_all, _code[0]);
00174 if (_code[1] != empty_code)
00175 _backet.push_back(_all, _code[1]);
00176
00177 #ifdef DOUBLEMETAPHONE
00178 if (_alt[0] != empty_code)
00179 {
00180 _alternative = true;
00181 if (_alt[0] != blank_code)
00182 {
00183 _backet2.push_back(_all, _alt[0]);
00184 if (_alt[1] != empty_code)
00185 _backet2.push_back(_all, _alt[1]);
00186 }
00187 }
00188 else if (_code[0] != empty_code && _code[0] != blank_code)
00189 {
00190 _backet2.push_back(_all, _code[0]);
00191 if (_code[1] != empty_code)
00192 _backet2.push_back(_all, _code[1]);
00193 }
00194 #endif
00195 }
00196
00197
00198 public:
00199 _list< ub1_t >& _backet;
00200 #ifdef DOUBLEMETAPHONE
00201 bool _alternative;
00202 _list< ub1_t >& _backet2;
00203 #endif
00204 byte_allocator& _all;
00205 ub1_t _code[2];
00206 ub1_t _alt[2];
00207 };
00208
00209
00210
00211 metaphone_key
00212 convert_to_metaphone(const char* word, size_t len, byte_allocator& all)
00213 {
00214 _list< ub1_t > backet
00215 #ifdef DOUBLEMETAPHONE
00216 , backet2
00217 #endif
00218 ;
00219 metaphone_keeper meta(backet
00220 #ifdef DOUBLEMETAPHONE
00221 , backet2
00222 #endif
00223 , all);
00224
00225 metaphone_key ret;
00226
00227 const char* begin = word;
00228 register size_t index = 0;
00229 bool isSG = is_slavo_germanic(word, len);
00230
00231 const size_t slot_size = 8;
00232 register char slot[slot_size] = {0};
00233 register const char* pslot[slot_size] = {0};
00234 const size_t prev4 = 0, prev3 = 1, prev2 = 2, prev = 3, curr = 4, next = 5, next2 = 6, next3 = 7;
00235
00236 register size_t step = 0;
00237 slot[curr] = to_upper(*word);
00238 slot[next] = 1 == len ? 0 : to_upper(*(word + 1));
00239 pslot[curr] = word;
00240 pslot[next] = 1 == len ? 0 : word + 1;
00241
00242 register const char* pend = word + len;
00243
00244
00245 switch (slot[curr])
00246 {
00247 case 'P':
00248 case 'K':
00249 case 'G':
00250
00251 if (len > 1 && slot[next] == 'N')
00252 {
00253 ++word, ++index;
00254 memmove(slot, slot + 1, slot_size - 1);
00255 memmove(pslot, pslot + 1, (slot_size - 1) * sizeof(char*));
00256 }
00257 break;
00258
00259 case 'A':
00260
00261 if (len > 1 && slot[next] == 'E')
00262 {
00263 ++word, ++index;
00264 memmove(slot, slot + 1, slot_size - 1);
00265 memmove(pslot, pslot + 1, (slot_size - 1) * sizeof(char*));
00266 }
00267 break;
00268
00269 case 'W':
00270
00271 if (len > 1 && slot[next] == 'R')
00272 {
00273 ++word, ++index;
00274 memmove(slot, slot + 1, slot_size - 1);
00275 memmove(pslot, pslot + 1, (slot_size - 1) * sizeof(char*));
00276 }
00277 break;
00278
00279 case 'X':
00280 meta._code[0] = S_NOTE;
00281 meta._code[1] = empty_code;
00282 meta.metaph_add();
00283 ++word, ++index;
00284 memmove(slot, slot + 1, slot_size - 1);
00285 memmove(pslot, pslot + 1, (slot_size - 1) * sizeof(char*));
00286 break;
00287 }
00288
00289 while (index < len)
00290 {
00291
00292 slot[curr] = to_upper(*word);
00293 pslot[curr] = word;
00294
00295 if (index + 3 < len)
00296 {
00297 slot[next3] = to_upper(*(word + 3));
00298 slot[next2] = to_upper(*(word + 2));
00299 slot[next] = to_upper(*(word + 1));
00300
00301 pslot[next3] = word + 3;
00302 pslot[next2] = word + 2;
00303 pslot[next] = word + 1;
00304 }
00305 else if (index + 2 < len)
00306 {
00307 slot[next3] = 0;
00308 slot[next2] = to_upper(*(word + 2));
00309 slot[next] = to_upper(*(word + 1));
00310
00311 pslot[next3] = 0;
00312 pslot[next2] = word + 2;
00313 pslot[next] = word + 1;
00314 }
00315 else if (index + 1 < len)
00316 {
00317 slot[next3] = slot[next2] = 0;
00318 slot[next] = to_upper(*(word + 1));
00319
00320 pslot[next3] = pslot[next2] = 0;
00321 pslot[next] = word + 1;
00322 }
00323
00324 meta.clear();
00325
00326
00327 switch (slot[curr])
00328 {
00329 case 0:
00330 step = 1;
00331 break;
00332 case 'A':
00333 case 'E':
00334 case 'I':
00335 case 'O':
00336 case 'U':
00337 case 'Y':
00338
00339 if (slot[prev] == 0)
00340 {
00341 meta._code[0] = A_NOTE;
00342 meta.metaph_add();
00343 }
00344
00345 step = 1;
00346 break;
00347
00348 case 'B':
00349
00350 meta._code[0] = P_NOTE;
00351 meta.metaph_add();
00352
00353 if (slot[next] == 'B')
00354 step = 2;
00355 else
00356 step = 1;
00357
00358 break;
00359
00360 case 'C':
00361
00362 if(slot[prev2] != 0 && !is_vowel(slot[prev2]) && slot[prev] == 'A'
00363 && slot[next] == 'H'
00364 && (slot[next2] != 'I'
00365 && slot[next2] != 'E'
00366 || check_sub_string(pslot[prev2], pend, "BACHER", 6)
00367 || check_sub_string(pslot[prev2], pend, "MACHER", 6)
00368 )
00369 )
00370 {
00371 meta._code[0] = K_NOTE;
00372 meta.metaph_add();
00373 step = 2;
00374 break;
00375 }
00376
00377
00378 if (slot[prev] == 0 && check_sub_string(pslot[next], pend, "AESAR", 5))
00379 {
00380 meta._code[0] = S_NOTE;
00381 meta.metaph_add();
00382 step = 2;
00383 break;
00384 }
00385
00386
00387 if (slot[next] == 'H')
00388 {
00389
00390
00391 if (check_sub_string(pslot[next2], pend, "IA", 2))
00392 {
00393 meta._code[0] = K_NOTE;
00394 meta.metaph_add();
00395 step = 2;
00396 break;
00397 }
00398
00399
00400 if(slot[prev] != 0 && check_sub_string(pslot[next2], pend, "AE", 2))
00401 {
00402 meta._code[0] = K_NOTE;
00403 meta._alt[0] = X_NOTE;
00404 meta.metaph_add_alt();
00405 step = 2;
00406 break;
00407 }
00408
00409
00410
00411 if(slot[prev] == 0 && (check_sub_string(pslot[next2], pend, "ARAC", 5)
00412 || check_sub_string(pslot[next2], pend, "ARIS", 5)
00413 || check_sub_string(pslot[next2], pend, "OR", 3)
00414 || check_sub_string(pslot[next2], pend, "YM", 3)
00415 || check_sub_string(pslot[next2], pend, "IA", 3)
00416 || check_sub_string(pslot[next2], pend, "EM", 3)
00417 )
00418 && !check_sub_string(begin, pend, "CHORE", 5))
00419 {
00420 meta._code[0] = K_NOTE;
00421 meta.metaph_add();
00422 step = 2;
00423 break;
00424 }
00425
00426
00427 if((check_sub_string(begin, pend, "VAN ", 4)
00428 || check_sub_string(begin, pend, "VON ", 4)
00429 || check_sub_string(begin, pend, "SCH", 3))
00430
00431 || slot[prev2] && check_sub_string(pslot[prev2], pend, "ORCHES", 6)
00432 || slot[prev2] && check_sub_string(pslot[prev2], pend, "ARCHIT", 6)
00433 || slot[prev2] && check_sub_string(pslot[prev2], pend, "ORCHID", 6)
00434 || slot[next2] == 'T' || slot[next2] == 'S'
00435 || ((slot[prev] == 'A' || slot[prev] == 'O' || slot[prev] == 'U'|| slot[prev] == 'E'
00436 || slot[prev] == 0)
00437 &&
00438 (slot[next2] == 'L'
00439 || slot[next2] == 'R'
00440 || slot[next2] == 'N'
00441 || slot[next2] == 'M'
00442 || slot[next2] == 'B'
00443 || slot[next2] == 'H'
00444 || slot[next2] == 'F'
00445 || slot[next2] == 'V'
00446 || slot[next2] == 'W'
00447 || slot[next2] == ' ')
00448 )
00449 )
00450
00451 {
00452 meta._code[0] = K_NOTE;
00453 meta.metaph_add();
00454 }
00455 else
00456 {
00457 if (slot[prev] != 0)
00458 {
00459 if (check_sub_string(begin, pend, "MC", 2))
00460 {
00461
00462 meta._code[0] = K_NOTE;
00463 meta.metaph_add();
00464 }
00465 else
00466 {
00467 meta._code[0] = X_NOTE;
00468 meta._alt[0] = K_NOTE;
00469 meta.metaph_add_alt();
00470 }
00471 }
00472 else
00473 {
00474 meta._code[0] = X_NOTE;
00475 meta.metaph_add();
00476 }
00477 }
00478
00479 step = 2;
00480 break;
00481 }
00482
00483
00484 if (slot[next] == 'Z' && !(slot[prev2] == 'W' && slot[prev] == 'I'))
00485 {
00486 meta._code[0] = S_NOTE;
00487 meta._alt[0] = X_NOTE;
00488 meta.metaph_add_alt();
00489 step = 2;
00490 break;
00491 }
00492
00493
00494 if (slot[next] == 'I' && slot[next2] == 'A')
00495 {
00496 meta._code[0] = X_NOTE;
00497 meta.metaph_add();
00498 step = 3;
00499 break;
00500 }
00501
00502
00503 if (slot[next] == 'C' && !(slot[prev2] == 0 && slot[prev] != 0 && to_upper(*begin) == 'M'))
00504 {
00505
00506 if ((slot[next2] == 'I'
00507 || slot[next2] == 'E'
00508 || slot[next2] == 'H')
00509 && !check_sub_string(pslot[next2], pend, "HU", 2)
00510 )
00511 {
00512
00513 if ((slot[prev2] == 0 && slot[prev] == 'A')
00514 || (slot[prev] == 'U'
00515 && (check_sub_string(pslot[next2], pend, "EE", 2)
00516 || check_sub_string(pslot[next2], pend, "ES", 2))
00517 )
00518 )
00519 {
00520 meta._code[0] = K_NOTE;
00521 meta._code[1] = S_NOTE;
00522 meta._alt[0] = K_NOTE;
00523 meta._alt[1] = S_NOTE;
00524 meta.metaph_add_alt();
00525 }
00526 else
00527 {
00528 meta._code[0] = X_NOTE;
00529 meta.metaph_add();
00530 }
00531 step = 3;
00532 break;
00533 }
00534 else
00535 {
00536
00537 meta._code[0] = K_NOTE;
00538 meta.metaph_add();
00539 step = 2;
00540 break;
00541 }
00542 }
00543
00544 if (slot[next] == 'K'
00545 || slot[next] == 'G'
00546 || slot[next] == 'Q'
00547 )
00548 {
00549 meta._code[0] = K_NOTE;
00550 meta.metaph_add();
00551 step = 2;
00552 break;
00553 }
00554
00555 if (slot[next] == 'I'
00556 || slot[next] == 'E'
00557 || slot[next] == 'Y'
00558 )
00559 {
00560
00561 if (slot[next2] == 'O'
00562 || slot[next2] == 'E'
00563 || slot[next2] == 'A'
00564 )
00565 {
00566 meta._code[0] = S_NOTE;
00567 meta._alt[0] = X_NOTE;
00568 meta.metaph_add_alt();
00569 }
00570 else
00571 {
00572 meta._code[0] = S_NOTE;
00573 meta.metaph_add();
00574 }
00575
00576 step = 2;
00577 break;
00578 }
00579
00580 meta._code[0] = K_NOTE;
00581 meta.metaph_add();
00582
00583
00584 if (slot[next] == ' ' && (slot[next2] == 'C' || slot[next2] == 'Q' || slot[next2] == 'G'))
00585 step = 3;
00586 else if ((slot[next] == 'C' || slot[next] == 'Q' || slot[next] == 'G') && !(slot[next] == 'E' || slot[next] == 'I'))
00587 step = 2;
00588 else
00589 step = 1;
00590 break;
00591
00592 case 'D':
00593 if (slot[next] == 'G')
00594 {
00595 if (slot[next2] == 'I'
00596 || slot[next2] == 'E'
00597 || slot[next2] == 'Y'
00598 )
00599 {
00600
00601 meta._code[0] = J_NOTE;
00602 meta.metaph_add();
00603 step = 3;
00604 break;
00605 }
00606 else
00607 {
00608
00609 meta._code[0] = T_NOTE;
00610 meta._code[1] = K_NOTE;
00611 meta.metaph_add();
00612 step = 2;
00613 break;
00614 }
00615 }
00616
00617 if (slot[next] == 'T'
00618 || slot[next] == 'D'
00619 )
00620 {
00621 meta._code[0] = T_NOTE;
00622 meta.metaph_add();
00623 step = 2;
00624 break;
00625 }
00626
00627 meta._code[0] = T_NOTE;
00628 meta.metaph_add();
00629 step = 1;
00630 break;
00631 case 'F':
00632 if (slot[next] == 'F')
00633 step = 2;
00634 else
00635 step = 1;
00636
00637 meta._code[0] = F_NOTE;
00638 meta.metaph_add();
00639 break;
00640 case 'G':
00641 if (slot[next] == 'H')
00642 {
00643 if (slot[prev] != 0 && !is_vowel(slot[prev]))
00644 {
00645 meta._code[0] = K_NOTE;
00646 meta.metaph_add();
00647 step = 2;
00648 break;
00649 }
00650
00651 if (slot[prev3] == 0 && slot[prev] == 0)
00652 {
00653
00654 if(slot[next2] == 'I')
00655 {
00656 meta._code[0] = J_NOTE;
00657 meta.metaph_add();
00658 }
00659 else
00660 {
00661 meta._code[0] = K_NOTE;
00662 meta.metaph_add();
00663 }
00664
00665 step = 2;
00666 break;
00667 }
00668
00669
00670 if (slot[prev2] == 'B'
00671 || slot[prev2] == 'H'
00672 || slot[prev2] == 'D'
00673
00674 || slot[prev3] == 'B'
00675 || slot[prev3] == 'H'
00676 || slot[prev3] == 'D'
00677
00678 || slot[prev4] == 'B'
00679 || slot[prev4] == 'H'
00680 )
00681 {
00682 step = 2;
00683 break;
00684 }
00685 else
00686 {
00687
00688 if (slot[prev2] != 0
00689 && slot[prev] == 'U'
00690 && (slot[prev3] == 'C'
00691 || slot[prev3] == 'G'
00692 || slot[prev3] == 'L'
00693 || slot[prev3] == 'R'
00694 || slot[prev3] == 'T')
00695 )
00696 {
00697 meta._code[0] = F_NOTE;
00698 meta.metaph_add();
00699 }
00700 else if (slot[prev] != 0 && slot[prev] != 'I')
00701 {
00702 meta._code[0] = K_NOTE;
00703 meta.metaph_add();
00704 }
00705
00706 step = 2;
00707 break;
00708 }
00709 }
00710
00711 if (slot[next] == 'N')
00712 {
00713 if (slot[prev] != 0 && slot[prev2] == 0 && is_vowel(*begin) && !isSG)
00714 {
00715 meta._code[0] = K_NOTE;
00716 meta._code[1] = N_NOTE;
00717 meta._alt[0] = N_NOTE;
00718 meta.metaph_add_alt();
00719 }
00720 else
00721 {
00722
00723 if (!check_sub_string(pslot[next2], pend, "EY", 2)
00724 && slot[prev] != 'Y'
00725 && !isSG)
00726 {
00727 meta._code[0] = N_NOTE;
00728 meta._alt[0] = K_NOTE;
00729 meta._alt[1] = N_NOTE;
00730 meta.metaph_add_alt();
00731 }
00732 else
00733 {
00734 meta._code[0] = K_NOTE;
00735 meta._code[1] = N_NOTE;
00736 meta.metaph_add();
00737 }
00738 }
00739
00740 step = 2;
00741 break;
00742 }
00743
00744
00745 if (slot[next] == 'L' && slot[next2] == 'I' && !isSG)
00746 {
00747 meta._code[0] = K_NOTE;
00748 meta._code[1] = L_NOTE;
00749 meta._alt[0] = L_NOTE;
00750 meta.metaph_add_alt();
00751 step = 2;
00752 break;
00753 }
00754
00755
00756 if (slot[prev] == 0
00757 && (slot[next] == 'Y'
00758 || (slot[next] == 'E'
00759 && (slot[next2] == 'S'
00760 || slot[next2] == 'P'
00761 || slot[next2] == 'B'
00762 || slot[next2] == 'L'
00763 || slot[next2] == 'Y'
00764 || slot[next2] == 'I'
00765 || slot[next2] == 'R'
00766 )
00767 )
00768 || (slot[next] == 'I'
00769 && (slot[next2] == 'B'
00770 || slot[next2] == 'L'
00771 || slot[next2] == 'N'
00772 || slot[next2] == 'E'
00773 )
00774 )
00775 )
00776 )
00777 {
00778 meta._code[0] = K_NOTE;
00779 meta._alt[0] = J_NOTE;
00780 meta.metaph_add_alt();
00781 step = 2;
00782 break;
00783 }
00784
00785
00786 if ((slot[next] == 'E' && slot[next2] == 'R'
00787 || slot[next] == 'Y'
00788 )
00789 && !(check_sub_string(begin, pend, "DANGER", 6)
00790 || check_sub_string(begin, pend, "RANGER", 6)
00791 || check_sub_string(begin, pend, "MANGER", 6))
00792 && !(slot[prev] == 'E'
00793 || slot[prev] == 'I')
00794 && !((slot[prev] == 'R' || slot[prev] == 'O') && slot[prev2] == 'G' && slot[prev3] == 'Y')
00795 )
00796 {
00797 meta._code[0] = K_NOTE;
00798 meta._alt[0] = J_NOTE;
00799 meta.metaph_add_alt();
00800 step = 2;
00801 break;
00802 }
00803
00804
00805 if ((slot[next] == 'E'
00806 || slot[next] == 'I'
00807 || slot[next] == 'Y')
00808 || ((slot[prev] == 'A' || slot[prev] == 'O') && slot[next] == 'G' && slot[next2] == 'I')
00809 )
00810 {
00811
00812 if ((check_sub_string(begin, pend, "VAN ", 4)
00813 || check_sub_string(begin, pend, "VON ", 4)
00814 || check_sub_string(begin, pend, "SCH", 3)
00815 )
00816 || (slot[next] == 'E' && slot[next2] == 'T')
00817 )
00818 {
00819 meta._code[0] = K_NOTE;
00820 meta.metaph_add();
00821 }
00822 else
00823 {
00824
00825 if (slot[next] == 'I' && slot[next2] == 'E' && slot[next3] == 'R')
00826 {
00827 meta._code[0] = J_NOTE;
00828 meta.metaph_add();
00829 }
00830 else
00831 {
00832 meta._code[0] = J_NOTE;
00833 meta._alt[0] = K_NOTE;
00834 meta.metaph_add_alt();
00835 }
00836 }
00837
00838 step = 2;
00839 break;
00840 }
00841
00842 if (slot[next] == 'G')
00843 step = 2;
00844 else
00845 step = 1;
00846
00847 meta._code[0] = K_NOTE;
00848 meta.metaph_add();
00849 break;
00850
00851 case 'H':
00852
00853 if ((slot[prev] == 0 || is_vowel(prev))
00854 && is_vowel(next)
00855 )
00856 {
00857 meta._code[0] = H_NOTE;
00858 meta.metaph_add();
00859 step = 2;
00860 }
00861 else
00862 step = 1;
00863
00864 break;
00865
00866 case 'J':
00867
00868 if ((slot[next] == 'O' && slot[next2] == 'S' && slot[next3] == 'E')
00869 || check_sub_string(begin, pend, "SAN J", 5))
00870 {
00871 if (index == 0)
00872 {
00873 meta._code[0] = H_NOTE;
00874 meta.metaph_add();
00875 }
00876 else
00877 {
00878 meta._code[0] = J_NOTE;
00879 meta._alt[0] = H_NOTE;
00880 meta.metaph_add_alt();
00881 }
00882
00883 step = 1;
00884 break;
00885 }
00886 else
00887 {
00888 meta._code[0] = J_NOTE;
00889 meta._alt[0] = A_NOTE;
00890 meta.metaph_add_alt();
00891
00892
00893 if(slot[next] == 'J')
00894 {
00895 step = 2;
00896 }
00897 else
00898 {
00899 step = 1;
00900 }
00901 break;
00902 }
00903
00904 if (slot[prev] == 0 && !(slot[next] == 'O' && slot[next2] == 'S' && slot[next3] == 'E'))
00905 {
00906
00907 meta._code[0] = J_NOTE;
00908 meta._alt[0] = A_NOTE;
00909 meta.metaph_add_alt();
00910 }
00911 else
00912 {
00913
00914 if (is_vowel(prev)
00915 && !isSG
00916 && (slot[next] == 'A'
00917 || slot[next] == 'O')
00918 )
00919 {
00920 meta._code[0] = J_NOTE;
00921 meta._alt[0] = H_NOTE;
00922 meta.metaph_add_alt();
00923 }
00924 else if (index + 1 == len)
00925 {
00926 meta._code[0] = J_NOTE;
00927 meta._alt[0] = blank_code;
00928 meta.metaph_add_alt();
00929 }
00930 else if (!(slot[next] == 'L'
00931 || slot[next] == 'T'
00932 || slot[next] == 'K'
00933 || slot[next] == 'S'
00934 || slot[next] == 'N'
00935 || slot[next] == 'M'
00936 || slot[next] == 'B'
00937 || slot[next] == 'Z'
00938 )
00939 && !(slot[prev] == 'S'
00940 || slot[prev] == 'K'
00941 || slot[prev] == 'L'
00942 )
00943 )
00944 {
00945 meta._code[0] = J_NOTE;
00946 meta.metaph_add();
00947 }
00948 }
00949
00950 if (slot[next] == 'J')
00951 {
00952 step = 2;
00953 }
00954 else
00955 {
00956 step = 1;
00957 }
00958
00959 break;
00960 case 'K':
00961 if (slot[next] == 'K')
00962 {
00963 step = 2;
00964 }
00965 else
00966 {
00967 step = 1;
00968 }
00969
00970 meta._code[0] = K_NOTE;
00971 meta.metaph_add();
00972 break;
00973
00974 case 'L':
00975 if (slot[next] == 'L')
00976 {
00977
00978 if ((index == len - 3
00979 && ((slot[prev] == 'I' && slot[next] == 'L' && (slot[next2] == 'O' || slot[next2] == 'A'))
00980 || (slot[prev] == 'A' && slot[next] == 'L' && slot[next2] == 'E'))
00981 )
00982 || ((check_sub_string(begin + len - 2, pend, "AS", 2)
00983 || check_sub_string(begin + len - 2, pend, "OS", 2)
00984 || to_upper(*(begin + len - 1)) == 'A'
00985 || to_upper(*(begin + len - 1)) == 'O')
00986 && slot[prev] && (slot[prev] == 'A' && slot[next] == 'L' && slot[next2] == 'E'))
00987 )
00988 {
00989 meta._code[0] = L_NOTE;
00990 meta._alt[0] = blank_code;
00991 meta.metaph_add_alt();
00992 step = 2;
00993 break;
00994 }
00995
00996 step = 2;
00997 }
00998 else
00999 step = 1;
01000
01001
01002 meta._code[0] = L_NOTE;
01003 meta.metaph_add();
01004 break;
01005
01006 case 'M':
01007 if ((slot[prev] == 'U' && slot[next] == 'B')
01008 && ((index + 1 == len) || check_sub_string(pslot[next2], pend, "ER", 2))
01009
01010 || slot[next] == 'M'
01011 )
01012 {
01013 step = 2;
01014 }
01015 else
01016 {
01017 step = 1;
01018 }
01019
01020 meta._code[0] = M_NOTE;
01021 meta.metaph_add();
01022 break;
01023
01024 case 'N':
01025 if (slot[next] == 'N')
01026 {
01027 step = 2;
01028 }
01029 else
01030 {
01031 step = 1;
01032 }
01033
01034 meta._code[0] = N_NOTE;
01035 meta.metaph_add();
01036 break;
01037 case 'P':
01038 if (slot[next] == 'H')
01039 {
01040 meta._code[0] = F_NOTE;
01041 meta.metaph_add();
01042 step = 2;
01043 break;
01044 }
01045
01046
01047 if (slot[next] == 'P'
01048 || slot[next] == 'B')
01049 {
01050 step = 2;
01051 }
01052 else
01053 {
01054 step = 1;
01055 }
01056
01057 meta._code[0] = P_NOTE;
01058 meta.metaph_add();
01059 break;
01060
01061 case 'Q':
01062 if (slot[next] == 'Q')
01063 {
01064 step = 2;
01065 }
01066 else
01067 {
01068 step = 1;
01069 }
01070
01071 meta._code[0] = K_NOTE;
01072 meta.metaph_add();
01073 break;
01074
01075 case 'R':
01076
01077 if(index + 1 == len
01078 && !isSG
01079 && (slot[prev2] == 'I' && slot[prev] == 'E')
01080 && !(slot[prev4] == 'M' && slot[prev3] == 'E')
01081 || (slot[prev4] == 'M' && slot[prev3] == 'A')
01082 )
01083 {
01084 meta._alt[0] = R_NOTE;
01085 meta.metaph_add_alt();
01086 }
01087 else
01088 {
01089 meta._code[0] = R_NOTE;
01090 meta.metaph_add();
01091 }
01092
01093 if (slot[next] == 'R')
01094 {
01095 step = 2;
01096 }
01097 else
01098 {
01099 step = 1;
01100 }
01101
01102 break;
01103
01104 case 'S':
01105
01106
01107 if ((slot[prev] == 'I' || slot[prev] == 'Y') && slot[next] == 'L')
01108 {
01109 step = 1;
01110 break;
01111 }
01112
01113
01114 if (slot[prev] == 0 && check_sub_string(pslot[next], pend, "UGAR", 4))
01115 {
01116 meta._code[0] = X_NOTE;
01117 meta._alt[0] = S_NOTE;
01118 meta.metaph_add_alt();
01119 step = 1;
01120 break;
01121 }
01122
01123 if (slot[next] == 'H')
01124 {
01125
01126 if (check_sub_string(pslot[next2], pend, "EIM", 3)
01127 || check_sub_string(pslot[next2], pend, "OEK", 3)
01128 || check_sub_string(pslot[next2], pend, "OLM", 3)
01129 || check_sub_string(pslot[next2], pend, "OLZ", 3)
01130 )
01131 {
01132 meta._code[0] = S_NOTE;
01133 meta.metaph_add();
01134 }
01135 else
01136 {
01137 meta._code[0] = X_NOTE;
01138 meta.metaph_add();
01139 }
01140
01141 step = 2;
01142 break;
01143 }
01144
01145
01146 if (slot[next] == 'I' && (slot[next2] == 'O' || slot[next2] == 'A' && (slot[next3] == 0 || slot[next3] == 'N')))
01147 {
01148 if (!isSG)
01149 {
01150 meta._code[0] = S_NOTE;
01151 meta._alt[0] = X_NOTE;
01152 meta.metaph_add_alt();
01153 }
01154 else
01155 {
01156 meta._code[0] = S_NOTE;
01157 meta.metaph_add();
01158 }
01159
01160 step = 3;
01161 break;
01162 }
01163
01164
01165
01166 if ((slot[prev] == 0
01167 && (slot[next] == 'M'
01168 || slot[next] == 'N'
01169 || slot[next] == 'L'
01170 || slot[next] == 'W'
01171 )
01172 )
01173 || (slot[next] == 'Z')
01174 )
01175 {
01176 meta._code[0] = S_NOTE;
01177 meta._alt[0] = X_NOTE;
01178 meta.metaph_add_alt();
01179
01180 if (slot[next] == 'Z')
01181 {
01182 step = 2;
01183 }
01184 else
01185 {
01186 step = 1;
01187 }
01188
01189 break;
01190 }
01191
01192 if (slot[next] == 'C')
01193 {
01194
01195 if (slot[next2] == 'H')
01196 {
01197
01198 if (check_sub_string(pslot[next3], pend, "OO", 2)
01199 || check_sub_string(pslot[next3], pend, "ER", 2)
01200 || check_sub_string(pslot[next3], pend, "EN", 2)
01201 || check_sub_string(pslot[next3], pend, "UY", 2)
01202 || check_sub_string(pslot[next3], pend, "ED", 2)
01203 || check_sub_string(pslot[next3], pend, "EM", 2)
01204 )
01205 {
01206
01207 if (check_sub_string(pslot[next3], pend, "ER", 2)
01208 || check_sub_string(pslot[next3], pend, "EN", 2)
01209 )
01210 {
01211 meta._code[0] = X_NOTE;
01212 meta._alt[0] = S_NOTE;
01213 meta._alt[1] = K_NOTE;
01214 meta.metaph_add_alt();
01215 }
01216 else
01217 {
01218 meta._code[0] = S_NOTE;
01219 meta._code[1] = K_NOTE;
01220 meta.metaph_add();
01221 }
01222
01223 step = 3;
01224 break;
01225 }
01226 else
01227 {
01228 if (slot[prev] == 0 && !is_vowel(*(begin + 3)) && len > 3 && to_upper(*(begin + 3)) != 'W')
01229 {
01230 meta._code[0] = X_NOTE;
01231 meta._alt[0] = S_NOTE;
01232 meta.metaph_add_alt();
01233 }
01234 else
01235 {
01236 meta._code[0] = X_NOTE;
01237 meta.metaph_add();
01238 }
01239
01240 step = 3;
01241 break;
01242 }
01243 }
01244
01245 if (slot[next2] == 'I'
01246 || slot[next2] == 'E'
01247 || slot[next2] == 'Y'
01248 )
01249 {
01250 meta._code[0] = S_NOTE;
01251 meta.metaph_add();
01252 step = 3;
01253 break;
01254 }
01255
01256 meta._code[0] = S_NOTE;
01257 meta._code[1] = K_NOTE;
01258 meta.metaph_add();
01259 step = 3;
01260 break;
01261 }
01262
01263
01264 if (index + 1 == len && (((slot[prev2] == 'A' || slot[prev2] == 'O') && slot[prev] == 'I')))
01265 {
01266 meta._alt[0] = S_NOTE;
01267 meta.metaph_add_alt();
01268 }
01269 else
01270 {
01271 meta._code[0] = S_NOTE;
01272 meta.metaph_add();
01273 }
01274
01275 if (slot[next] == 'S'
01276 || slot[next] == 'Z')
01277 {
01278 step = 2;
01279 }
01280 else
01281 {
01282 step = 1;
01283 }
01284 break;
01285
01286 case 'T':
01287 if (slot[next] == 'I' && slot[next2] == 'O' && slot[next3] == 'N')
01288 {
01289 meta._code[0] = X_NOTE;
01290 meta.metaph_add();
01291 step = 3;
01292 break;
01293 }
01294
01295 if (slot[next] == 'I' && slot[next2] == 'A'
01296 || slot[next] == 'C' && slot[next2] == 'H')
01297 {
01298 meta._code[0] = X_NOTE;
01299 meta.metaph_add();
01300 step = 3;
01301 break;
01302 }
01303
01304 if (slot[next] == 'H'
01305 || slot[next] == 'T' && slot[next2] == 'H')
01306 {
01307
01308 if (check_sub_string(pslot[next2], pend, "OM", 2)
01309 || check_sub_string(pslot[next2], pend, "AM", 2)
01310 || check_sub_string(begin, pend, "VAN ", 4)
01311 || check_sub_string(begin, pend, "VON ", 4)
01312 || check_sub_string(begin, pend, "SCH", 3)
01313 )
01314 {
01315 meta._code[0] = T_NOTE;
01316 meta.metaph_add();
01317 }
01318 else
01319 {
01320 meta._code[0] = TH_NOTE;
01321 meta._alt[0] = T_NOTE;
01322 meta.metaph_add_alt();
01323 }
01324
01325 step = 2;
01326 break;
01327 }
01328
01329 if (slot[next] == 'T'
01330 || slot[next] == 'D')
01331 {
01332 step = 2;
01333 }
01334 else
01335 {
01336 step = 1;
01337 }
01338
01339 meta._code[0] = T_NOTE;
01340 meta.metaph_add();
01341 break;
01342
01343 case 'V':
01344 if (slot[next] == 'V')
01345 {
01346 step = 2;
01347 }
01348 else
01349 {
01350 step = 1;
01351 }
01352
01353 meta._code[0] = F_NOTE;
01354 meta.metaph_add();
01355 break;
01356
01357 case 'W':
01358
01359 if (slot[next] == 'R')
01360 {
01361 meta._code[0] = R_NOTE;
01362 meta.metaph_add();
01363 step = 2;
01364 break;
01365 }
01366
01367 if (slot[prev] == 0
01368 && (is_vowel(next) || slot[next] == 'H'))
01369 {
01370
01371 if (is_vowel(next))
01372 {
01373 meta._code[0] = A_NOTE;
01374 meta._alt[0] = F_NOTE;
01375 meta.metaph_add_alt();
01376 }
01377 else
01378 {
01379
01380 meta._code[0] = A_NOTE;
01381 meta.metaph_add();
01382 }
01383 }
01384
01385
01386 if ((index + 1 == len && is_vowel(prev))
01387 || (slot[prev] == 'E' && slot[next] == 'S' && slot[next2] == 'K' && slot[next3] == 'I')
01388 || (slot[prev] == 'O' && slot[next] == 'S' && slot[next2] == 'K' && slot[next3] == 'I')
01389 || (slot[prev] == 'O' && slot[next] == 'S' && slot[next2] == 'K' && slot[next3] == 'Y')
01390 || check_sub_string(begin, pend, "SCH", 3)
01391 )
01392 {
01393 meta._code[0] = empty_code;
01394 meta._code[1] = empty_code;
01395 meta._alt[0] = F_NOTE;
01396 meta._alt[1] = empty_code;
01397 meta.metaph_add_alt();
01398 step = 1;
01399 break;
01400 }
01401
01402
01403 if (slot[next] == 'I' && (slot[next2] == 'C' || slot[next2] == 'T') && slot[next3] == 'Z')
01404 {
01405 meta._code[0] = T_NOTE;
01406 meta._code[1] = S_NOTE;
01407 meta._alt[0] = F_NOTE;
01408 meta._alt[1] = X_NOTE;
01409 meta.metaph_add_alt();
01410 step = 4;
01411 break;
01412 }
01413
01414
01415 step = 1;
01416 break;
01417
01418 case 'X':
01419
01420 if (!(index + 1 == len
01421 && (slot[prev3] == 'I' && slot[prev2] == 'A' && slot[prev] == 'U')
01422 || (slot[prev3] == 'E' && slot[prev2] == 'A' && slot[prev] == 'U')
01423 || (slot[prev2] == 'A' && slot[prev] == 'U')
01424 || (slot[prev2] == 'O' && slot[prev] == 'U')
01425 )
01426 )
01427 {
01428 meta._code[0] = K_NOTE;
01429 meta._code[1] = S_NOTE;
01430 meta.metaph_add();
01431 }
01432
01433 if (slot[next] == 'C'
01434 || slot[next] == 'X')
01435 {
01436 step = 2;
01437 }
01438 else
01439 {
01440 step = 1;
01441 }
01442
01443 break;
01444
01445 case 'Z':
01446
01447 if (slot[next] == 'H')
01448 {
01449 meta._code[0] = J_NOTE;
01450 meta.metaph_add();
01451 step = 2;
01452 break;
01453 }
01454 else
01455 {
01456 if ((slot[next] == 'Z' && (slot[next2] == 'O' || slot[next2] == 'I' || slot[next2] == 'A'))
01457 || (isSG && slot[prev] != 0 && slot[prev] != 'T')
01458 )
01459 {
01460 meta._code[0] = S_NOTE;
01461 meta._alt[0] = T_NOTE;
01462 meta._alt[1] = S_NOTE;
01463 meta.metaph_add_alt();
01464 }
01465 else
01466 {
01467 meta._code[0] = S_NOTE;
01468 meta.metaph_add();
01469 }
01470 }
01471
01472 if (slot[next] == 'Z')
01473 {
01474 step = 2;
01475 }
01476 else
01477 {
01478 step = 1;
01479 }
01480 break;
01481
01482 default:
01483 step = 1;
01484 break;
01485 }
01486
01487
01488
01489 assert(step > 0 && step < 7);
01490 memmove(slot, slot + step, slot_size - step);
01491 memmove(pslot, pslot + step, (slot_size - step) * sizeof(char*));
01492 word += step, index += step;
01493 }
01494
01495
01496 ret._length = (ub4_t)backet.size();
01497
01498 if (ret._length)
01499 {
01500 ret._array = (ub1_t*)all.allocate(ret._length);
01501
01502 index = 0;
01503
01504 for (_list< ub1_t >::const_iterator it = backet.begin(); it != backet.end(); ++it, ++index)
01505 {
01506
01507
01508 ret._array[index] = *it;
01509 }
01510 }
01511
01512 return ret;
01513 }
01514
01515
01516 void
01517 convert_to_reflection(const char* word, size_t len, byte_allocator& all, reflection_key& reflection)
01518 {
01519 char* buf = (char*)all.allocate(len + 1);
01520
01521 size_t offset = 0, shift = 0;
01522 register char ch;
01523
01524 while (shift < len)
01525 {
01526 switch (ch = to_upper(word[shift]))
01527 {
01528 case 0:
01529 break;
01530 default:
01531 buf[offset++] = ch;
01532 }
01533
01534 ++shift;
01535 }
01536
01537
01538 buf[offset] = 0;
01539
01540 metaphone_key phonet = convert_to_metaphone(buf, offset, all);
01541
01542 for (size_t i = 0; i < phonet._length; ++i)
01543 {
01544 assert(phonet._array[i] < reflection_key::REFSIZE);
01545
01546 if (reflection._array[phonet._array[i]] < reflection_key::REFMAX)
01547 ++reflection._array[phonet._array[i]];
01548 }
01549 }
01550
01551
01552 }
01553
01554
01555 #pragma pack()
01556 END_TERIMBER_NAMESPACE