1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_i18npool.hxx" 26 /************************************************************************* 27 28 Weighted Levenshtein Distance 29 including wildcards 30 '*' for any number (0 or more) of arbitrary characters 31 '?' for exactly one arbitrary character 32 escapeable with backslash, "\*" or "\?" 33 34 Return: 35 WLD if WLD <= nLimit, else nLimit+1 36 37 or, if bSplitCount: 38 WLD if WLD <= nLimit 39 -WLD if Replace and Insert and Delete <= nLimit 40 else nLimit+1 41 42 Recursive definition of WLD: 43 44 WLD( X(i), Y(j) ) = min( WLD( X(i-1), Y(j-1) ) + p(i,j) , 45 WLD( X(i) , Y(j-1) ) + q , 46 WLD( X(i-1), Y(j) ) + r ) 47 48 X(i) := the first i characters of the word X 49 Y(j) := the first j characters of the word Y 50 p(i,j) := 0 if i-th character of X == j-th character of Y, 51 p else 52 53 Boundary conditions: 54 WLD( X(0), Y(j) ) := j*q (Y created by j inserts) 55 WLD( X(i), Y(0) ) := i*r (Y created by i deletes) 56 WLD( X(0), Y(0) ) := 0 57 58 Instead of recursions a dynamic algorithm is used. 59 60 See also: German computer magazine 61 c't 07/89 pages 192-208 and c't 03/94 pages 230-239 62 63 *************************************************************************/ 64 65 66 #include <string.h> // strlen() 67 68 #if defined( _MSC_VER ) 69 #pragma warning(once: 4068) 70 #endif 71 72 #include "levdis.hxx" 73 74 75 #ifdef erTEST 76 #include <stdlib.h> 77 #include <stdio.h> 78 #include <iostream.h> 79 #endif 80 81 #ifdef SOLARIS 82 #undef min 83 #endif 84 85 #define LEVDISBIG (nLimit + 1) // Returnwert wenn Distanz > nLimit 86 #define LEVDISDOUBLEBUF 2048 // dadrueber wird nicht mehr gedoppelt 87 88 // Balance, aus Geschwindigkeitsgruenden ist dieses keine Funktion 89 // c == cpPattern[jj] == cString[ii] 90 // erst wird bis Fundstelle gesucht, wenn dort die Balance gleich ist, wird 91 // auch nach der Fundstelle verglichen 92 #define LEVDISBALANCE(jj,ii) \ 93 { \ 94 if ( jj != ii ) \ 95 { \ 96 sal_Int32 k; \ 97 if ( jj > 0 ) \ 98 for ( k=0; k < jj; k++ ) \ 99 if ( cpPattern[k] == c ) \ 100 nBalance++; \ 101 if ( ii > 0 ) \ 102 for ( k=0; k < ii; k++ ) \ 103 if ( cString[k] == c ) \ 104 nBalance--; \ 105 if ( !nBalance ) \ 106 { \ 107 for ( k=jj+1; k < nPatternLen; k++ ) \ 108 if ( cpPattern[k] == c ) \ 109 nBalance++; \ 110 for ( k=ii+1; k < nStringLen; k++ ) \ 111 if ( cString[k] == c ) \ 112 nBalance--; \ 113 } \ 114 } \ 115 } 116 117 static sal_Int32 Impl_WLD_StringLen( const sal_Unicode* pStr ) 118 { 119 const sal_Unicode* pTempStr = pStr; 120 while( *pTempStr ) 121 pTempStr++; 122 return (sal_Int32)(pTempStr-pStr); 123 } 124 125 #ifdef erTESTMAT 126 #define erTESTMATMAX 180 127 static int npMatrix[erTESTMATMAX][erTESTMATMAX]; // nearly 64K 128 #endif 129 130 // Distanz von String zu Pattern 131 int WLevDistance::WLD( const sal_Unicode* cString, sal_Int32 nStringLen ) 132 { 133 int nSPMin = 0; // StrafPunkteMinimum 134 int nRepS = 0; // fuer SplitCount 135 136 #ifdef erTESTMAT 137 { 138 for ( sal_Int32 r=0; r<=nStringLen && r < erTESTMATMAX; r++ ) 139 for ( sal_Int32 c=0; c<=nPatternLen && c < erTESTMATMAX; c++ ) 140 npMatrix[r][c] = 99; // Matrix initialisieren, nur visuell 141 } 142 #endif 143 144 // Laengendifferenz von Pattern und String 145 int nLenDiff = nPatternLen - nStars - nStringLen; 146 // mehr Einfuegungen oder Loeschungen noetig als Limit? => raus hier 147 if ( (nLenDiff * nInsQ0 > nLimit) 148 || ((nStars == 0) && (nLenDiff * nDelR0 < -nLimit)) ) 149 return(LEVDISBIG); 150 151 // wenn der zu vergleichende String groesser ist als das bisherige Array 152 // muss dieses angepasst werden 153 if ( nStringLen >= nArrayLen ) 154 { 155 // gib ihm moeglichst mehr, damit nicht gleich naechstesmal 156 // wieder realloziert werden muss 157 if ( nStringLen < LEVDISDOUBLEBUF ) 158 nArrayLen = 2 * nStringLen; 159 else 160 nArrayLen = nStringLen + 1; 161 npDistance = aDisMem.NewMem( nArrayLen ); 162 #ifdef erTEST 163 if ( !npDistance ) 164 { 165 cerr << "DOOM! (Damned, Out Of Memory)" << endl; 166 exit(1); 167 } 168 #endif 169 } 170 171 // Anfangswerte der zweiten Spalte (erstes Pattern-Zeichen) berechnen 172 // die erste Spalte (0-Len Pattern) ist immer 0 .. nStringLen * nInsQ0, 173 // deren Minimum also 0 174 if ( nPatternLen == 0 ) 175 { 176 // Anzahl der Loeschungen, um auf Pattern zu kommen 177 for ( sal_Int32 i=0; i <= nStringLen; i++ ) 178 npDistance[i] = i * nDelR0; 179 } 180 else if ( cpPattern[0] == '*' && bpPatIsWild[0] ) 181 { 182 // statt einem '*' ist alles einsetzbar 183 for ( sal_Int32 i=0; i <= nStringLen; i++ ) 184 npDistance[i] = 0; 185 } 186 else 187 { 188 sal_Unicode c; 189 int nP; 190 c = cpPattern[0]; 191 if ( c == '?' && bpPatIsWild[0] ) 192 nP = 0; // ein '?' kann jedes Zeichen sein 193 else 194 // Minimum von Ersetzen und Loeschen+Einfuegen Gewichtung 195 nP = Min3( nRepP0, nRepP0, nDelR0 + nInsQ0 ); 196 npDistance[0] = nInsQ0; // mit einfachem Einfuegen geht's los 197 npDistance[1] = nInsQ0; 198 npDistance[2] = nInsQ0; 199 int nReplacePos = -1; // tristate Flag 200 int nDelCnt = 0; 201 for ( sal_Int32 i=1; i <= nStringLen; i++, nDelCnt += nDelR0 ) 202 { 203 if ( cString[i-1] == c ) 204 nP = 0; // Replace ab dieser Stelle ist 0 205 // Loeschungen um auf Pattern zu kommen + Replace 206 npDistance[i] = nDelCnt + nP; 207 if ( bSplitCount ) 208 { 209 if ( nReplacePos < 0 && nP ) 210 { // diese Stelle wird ersetzt 211 nRepS++; 212 nReplacePos = i; 213 #ifdef erTESTMAT 214 npMatrix[i][1] = -npDistance[i]; 215 #endif 216 } 217 else if ( nReplacePos > 0 && !nP ) 218 { 219 int nBalance = 0; // gleiche Anzahl c 220 LEVDISBALANCE( 0, i-1 ); 221 if ( !nBalance ) 222 { // einer wurde ersetzt, der ein Insert war 223 nRepS--; 224 #ifdef erTESTMAT 225 npMatrix[nReplacePos][1] = npDistance[nReplacePos]; 226 #endif 227 nReplacePos = 0; 228 } 229 } 230 } 231 } 232 nSPMin = Min3( npDistance[0], npDistance[1], npDistance[2] ); 233 } 234 #ifdef erTESTMAT 235 { 236 for ( sal_Int32 r=0; r<=nStringLen && r < erTESTMATMAX; r++ ) 237 { 238 npMatrix[r][0] = r * nInsQ0; 239 if ( npMatrix[r][1] >= 0) 240 npMatrix[r][1] = npDistance[r]; 241 } 242 } 243 #endif 244 245 // Distanzmatrix berechnen 246 sal_Int32 j = 0; // fuer alle Spalten des Pattern, solange nicht Limit 247 while ( (j < nPatternLen-1) 248 && nSPMin <= (bSplitCount ? 2 * nLimit : nLimit) ) 249 { 250 sal_Unicode c; 251 int nP, nQ, nR, nPij, d1, d2; 252 253 j++; 254 c = cpPattern[j]; 255 if ( bpPatIsWild[j] ) // '*' oder '?' nicht escaped 256 nP = 0; // kann ohne Strafpunkte ersetzt werden 257 else 258 nP = nRepP0; 259 if ( c == '*' && bpPatIsWild[j] ) 260 { 261 nQ = 0; // Einfuegen und Loeschen ohne Strafpunkte 262 nR = 0; 263 } 264 else 265 { 266 nQ = nInsQ0; // normale Gewichtung 267 nR = nDelR0; 268 } 269 d2 = npDistance[0]; 270 // Anzahl Einfuegungen um von Null-String auf Pattern zu kommen erhoehen 271 npDistance[0] = npDistance[0] + nQ; 272 nSPMin = npDistance[0]; 273 int nReplacePos = -1; // tristate Flag 274 // fuer jede Patternspalte den String durchgehen 275 for ( sal_Int32 i=1; i <= nStringLen; i++ ) 276 { 277 d1 = d2; // WLD( X(i-1), Y(j-1) ) 278 d2 = npDistance[i]; // WLD( X(i) , Y(j-1) ) 279 if ( cString[i-1] == c ) 280 { 281 nPij = 0; // p(i,j) 282 if ( nReplacePos < 0 ) 283 { 284 int nBalance = 0; // gleiche Anzahl c 285 LEVDISBALANCE( j, i-1 ); 286 if ( !nBalance ) 287 nReplacePos = 0; // keine Ersetzung mehr 288 } 289 } 290 else 291 nPij = nP; 292 // WLD( X(i), Y(j) ) = min( WLD( X(i-1), Y(j-1) ) + p(i,j) , 293 // WLD( X(i) , Y(j-1) ) + q , 294 // WLD( X(i-1), Y(j) ) + r ) 295 npDistance[i] = Min3( d1 + nPij, d2 + nQ, npDistance[i-1] + nR ); 296 if ( npDistance[i] < nSPMin ) 297 nSPMin = npDistance[i]; 298 if ( bSplitCount ) 299 { 300 if ( nReplacePos < 0 && nPij && npDistance[i] == d1 + nPij ) 301 { // diese Stelle wird ersetzt 302 nRepS++; 303 nReplacePos = i; 304 #ifdef erTESTMAT 305 npMatrix[i][j+1] = -npDistance[i]; 306 #endif 307 } 308 else if ( nReplacePos > 0 && !nPij ) 309 { // Zeichen in String und Pattern gleich. 310 // wenn ab hier die gleiche Anzahl dieses Zeichens 311 // sowohl in Pattern als auch in String ist, und vor 312 // dieser Stelle das Zeichen gleich oft vorkommt, war das 313 // Replace keins. Buchstabendreher werden hier erfasst 314 // und der ReplaceS zurueckgenommen, wodurch das doppelte 315 // Limit zum Tragen kommt. 316 int nBalance = 0; // gleiche Anzahl c 317 LEVDISBALANCE( j, i-1 ); 318 if ( !nBalance ) 319 { // einer wurde ersetzt, der ein Insert war 320 nRepS--; 321 #ifdef erTESTMAT 322 npMatrix[nReplacePos][j+1] = npDistance[nReplacePos]; 323 #endif 324 nReplacePos = 0; 325 } 326 } 327 } 328 } 329 #ifdef erTESTMAT 330 { 331 for ( sal_Int32 r=0; r<=nStringLen && r < erTESTMATMAX; r++ ) 332 if ( npMatrix[r][j+1] >= 0) 333 npMatrix[r][j+1] = npDistance[r]; 334 } 335 #endif 336 } 337 #ifdef erTESTSPLIT 338 printf(" nRepS: %d ", nRepS ); 339 #endif 340 if ( (nSPMin <= nLimit) && (npDistance[nStringLen] <= nLimit) ) 341 return(npDistance[nStringLen]); 342 else 343 { 344 if ( bSplitCount ) 345 { 346 if ( nRepS && nLenDiff > 0 ) 347 nRepS -= nLenDiff; // Inserts wurden mitgezaehlt 348 #ifdef erTESTSPLIT 349 printf(" nRepSdiff: %d ", nRepS ); 350 #endif 351 if ( (nSPMin <= 2 * nLimit) 352 && (npDistance[nStringLen] <= 2 * nLimit) 353 && (nRepS * nRepP0 <= nLimit) ) 354 return( -npDistance[nStringLen] ); 355 return(LEVDISBIG); 356 } 357 return(LEVDISBIG); 358 } 359 } 360 361 362 363 // Berechnung von nLimit, nReplP0, nInsQ0, nDelR0, bSplitCount 364 // aus Userwerten nOtherX, nShorterY, nLongerZ, bRelaxed 365 int WLevDistance::CalcLPQR( int nX, int nY, int nZ, bool bRelaxed ) 366 { 367 int nMin, nMid, nMax; 368 if ( nX < 0 ) nX = 0; // nur positive Werte 369 if ( nY < 0 ) nY = 0; 370 if ( nZ < 0 ) nZ = 0; 371 if ( 0 == (nMin = Min3( nX, nY, nZ )) ) // mindestens einer 0 372 { 373 nMax = Max3( nX, nY, nZ ); // entweder 0 bei drei 0 oder Max 374 if ( 0 == (nMid = Mid3( nX, nY, nZ )) ) // sogar zwei 0 375 nLimit = nMax; // entweder 0 oder einziger >0 376 else // einer 0 377 nLimit = KGV( nMid, nMax ); 378 } 379 else // alle drei nicht 0 380 nLimit = KGV( KGV( nX, nY ), nZ ); 381 nRepP0 = ( nX ? nLimit / nX : nLimit + 1 ); 382 nInsQ0 = ( nY ? nLimit / nY : nLimit + 1 ); 383 nDelR0 = ( nZ ? nLimit / nZ : nLimit + 1 ); 384 bSplitCount = bRelaxed; 385 return( nLimit ); 386 } 387 388 389 390 // Groesster Gemeinsamer Teiler nach Euklid (Kettendivision) 391 // Sonderfall: 0 und irgendwas geben 1 392 int WLevDistance::GGT( int a, int b ) 393 { 394 if ( !a || !b ) 395 return 1; 396 if ( a < 0 ) a = -a; 397 if ( b < 0 ) b = -b; 398 do 399 { 400 if ( a > b ) 401 a -= int(a / b) * b; 402 else 403 b -= int(b / a) * a; 404 } while ( a && b ); 405 return( a ? a : b); 406 } 407 408 409 410 // Kleinstes Gemeinsames Vielfaches: a * b / GGT(a,b) 411 int WLevDistance::KGV( int a, int b ) 412 { 413 if ( a > b ) // Ueberlauf unwahrscheinlicher machen 414 return( (a / GGT(a,b)) * b ); 415 else 416 return( (b / GGT(a,b)) * a ); 417 } 418 419 420 // Minimum von drei Werten 421 inline int WLevDistance::Min3( int x, int y, int z ) 422 { 423 if ( x < y ) 424 return( x < z ? x : z ); 425 else 426 return( y < z ? y : z ); 427 } 428 429 430 431 // mittlerer von drei Werten 432 int WLevDistance::Mid3( int x, int y, int z ) 433 { 434 int min = Min3(x,y,z); 435 if ( x == min ) 436 return( y < z ? y : z); 437 else if ( y == min ) 438 return( x < z ? x : z); 439 else // z == min 440 return( x < y ? x : y); 441 } 442 443 444 445 // Maximum von drei Werten 446 int WLevDistance::Max3( int x, int y, int z ) 447 { 448 if ( x > y ) 449 return( x > z ? x : z ); 450 else 451 return( y > z ? y : z ); 452 } 453 454 455 456 // Daten aus CTor initialisieren 457 void WLevDistance::InitData( const sal_Unicode* cPattern ) 458 { 459 cpPattern = aPatMem.GetcPtr(); 460 bpPatIsWild = aPatMem.GetbPtr(); 461 npDistance = aDisMem.GetPtr(); 462 nStars = 0; 463 const sal_Unicode* cp1 = cPattern; 464 sal_Unicode* cp2 = cpPattern; 465 bool* bp = bpPatIsWild; 466 // Pattern kopieren, Sternchen zaehlen, escaped Jokers 467 while ( *cp1 ) 468 { 469 if ( *cp1 == '\\' ) // maybe escaped 470 { 471 if ( *(cp1+1) == '*' || *(cp1+1) == '?' ) // naechstes Joker? 472 { 473 cp1++; // skip '\\' 474 nPatternLen--; 475 } 476 *bp++ = false; 477 } 478 else if ( *cp1 == '*' || *cp1 == '?' ) // Joker 479 { 480 if ( *cp1 == '*' ) 481 nStars++; // Sternchenzaehler erhoehen 482 *bp++ = true; 483 } 484 else 485 *bp++ = false; 486 *cp2++ = *cp1++; 487 } 488 *cp2 = '\0'; 489 } 490 491 492 // CTor 493 494 #ifdef erTEST 495 496 WLevDistance::WLevDistance( const ::rtl::OUString& rPattern ) : 497 nPatternLen( rPattern.getLength() ), 498 aPatMem( nPatternLen + 1 ), 499 nArrayLen( nPatternLen + 1 ), 500 aDisMem( nArrayLen ), 501 nLimit( LEVDISDEFAULTLIMIT ), 502 nRepP0( LEVDISDEFAULT_P0 ), 503 nInsQ0( LEVDISDEFAULT_Q0 ), 504 nDelR0( LEVDISDEFAULT_R0 ), 505 bSplitCount( false ) 506 { 507 InitData( rPattern.getStr() ); 508 } 509 510 #endif // erTEST 511 512 513 WLevDistance::WLevDistance( const sal_Unicode* cPattern, 514 int nOtherX, int nShorterY, int nLongerZ, 515 bool bRelaxed ) : 516 nPatternLen( Impl_WLD_StringLen(cPattern) ), 517 aPatMem( nPatternLen + 1 ), 518 nArrayLen( nPatternLen + 1 ), 519 aDisMem( nArrayLen ) 520 { 521 InitData( cPattern ); 522 CalcLPQR( nOtherX, nShorterY, nLongerZ, bRelaxed ); 523 } 524 525 526 // CopyCTor 527 WLevDistance::WLevDistance( const WLevDistance& rWLD ) : 528 nPatternLen( rWLD.nPatternLen ), 529 aPatMem( nPatternLen + 1 ), 530 nArrayLen( nPatternLen + 1 ), 531 aDisMem( nArrayLen ), 532 nLimit( rWLD.nLimit ), 533 nRepP0( rWLD.nRepP0 ), 534 nInsQ0( rWLD.nInsQ0 ), 535 nDelR0( rWLD.nDelR0 ), 536 nStars( rWLD.nStars ), 537 bSplitCount( rWLD.bSplitCount ) 538 { 539 cpPattern = aPatMem.GetcPtr(); 540 bpPatIsWild = aPatMem.GetbPtr(); 541 npDistance = aDisMem.GetPtr(); 542 sal_Int32 i; 543 for ( i=0; i<nPatternLen; i++ ) 544 { 545 cpPattern[i] = rWLD.cpPattern[i]; 546 bpPatIsWild[i] = rWLD.bpPatIsWild[i]; 547 } 548 cpPattern[i] = '\0'; 549 } 550 551 552 // DTor 553 WLevDistance::~WLevDistance() 554 { 555 } 556 557 /************************************************************************* 558 * Test 559 *************************************************************************/ 560 561 #ifdef erTEST 562 563 #define LINESIZE 1000 564 typedef char MAXSTRING [LINESIZE+1]; 565 566 #ifdef erTESTMAT 567 568 void WLevDistance::ShowMatrix( const sal_Unicode* cString ) 569 { 570 sal_Int32 r, c, l = Impl_WLD_StringLen(cString); 571 printf(" | "); 572 for ( c=0; c<nPatternLen; c++ ) 573 #error Error: conversion from sal_Unicode to char needed! 574 printf( " %c ", cpPattern[c] ); 575 printf("\n---+---"); 576 for ( c=0; c<nPatternLen; c++ ) 577 printf( "---" ); 578 for ( r=0; r<=l && r < erTESTMATMAX; r++ ) 579 { 580 #error Error: conversion from sal_Unicode to char needed! 581 printf( "\n %c |", ( r==0 ? ' ' : cString[r-1] ) ); 582 for ( c=0; c<=nPatternLen && c < erTESTMATMAX; c++ ) 583 printf( "%2d ", npMatrix[r][c] ); 584 } 585 printf("\n\n"); 586 } 587 588 #endif // erTESTMAT 589 590 // Delimiter fuer Token, \t Tab bleibt fuer immer an der ersten Stelle 591 MAXSTRING cDelim = "\t, ;(){}[]<>&=+-/%!|.\\'\"~"; 592 593 void WLevDistance::ShowTest() 594 { 595 printf(" \n"); 596 #error Error: conversion from sal_Unicode to char needed! 597 printf(" a *cpPattern . . . . : %s\n", cpPattern); 598 printf(" b *bpPatIsWild . . . : "); 599 for ( sal_Int32 i=0; i<nPatternLen; i++ ) 600 printf("%d", bpPatIsWild[i]); 601 printf("\n"); 602 printf(" c nPatternLen . . . : %d\n", (int)nPatternLen); 603 printf(" d nStars . . . . . . : %d\n", nStars); 604 printf(" e nLimit . . . . . . : %d\n", nLimit); 605 printf(" f nRepP0 (Ersetzen) : %d\n", nRepP0); 606 printf(" g nInsQ0 (Einfuegen) : %d\n", nInsQ0); 607 printf(" h nDelR0 (Loeschen) : %d\n", nDelR0); 608 printf(" i bSplitCount . . . : %d\n", bSplitCount); 609 #error Error: conversion from sal_Unicode to char needed! 610 printf(" j cDelim . . . . . . : '%s'\n", cDelim); 611 printf(" ~\n"); 612 } 613 614 inline bool IsDelim( char c ) 615 { 616 char* cp = cDelim; 617 while ( *cp ) 618 if ( *cp++ == c ) 619 return( true ); 620 return( false ); 621 } 622 623 MAXSTRING cString, cLine, cIgString; 624 625 int main( int argc, char **argv ) 626 { 627 int nLim, nP0, nQ0, nR0, nX, nY, nZ; 628 int args = 0; 629 bool IgnoreCase = false, Direct = false, bStrict = false; 630 WLevDistance* pTest; 631 if ( argc < 2 ) 632 { 633 printf("%s Syntax:\n" 634 " ... [-i] cPattern [nOtherX, nShorterY, nLongerZ [bStrict [cDelim]]] [<stdin] [>stdout]\n" 635 " ... -d cPattern [nLimit [nRepP0 nInsQ0 nDelR0 [cDelim]]] [<stdin] [>stdout]\n" 636 , argv[0]); 637 exit(1); 638 } 639 if ( *argv[1] == '-' ) 640 { 641 args++; 642 argc--; 643 switch ( *(argv[1]+1) ) 644 { 645 case 'i': 646 { 647 IgnoreCase = true; 648 char* cp = argv[args+1]; 649 while ( (*cp = tolower( *cp )) != 0 ) 650 cp++; 651 break; 652 } 653 case 'd': 654 Direct = true; 655 break; 656 } 657 } 658 if ( Direct ) 659 { 660 if ( argc > 2 ) 661 nLim = atoi(argv[args+2]); 662 else 663 nLim = LEVDISDEFAULTLIMIT; 664 if ( argc > 3 ) 665 { 666 nP0 = atoi(argv[args+3]); 667 nQ0 = atoi(argv[args+4]); 668 nR0 = atoi(argv[args+5]); 669 } 670 else 671 { 672 nP0 = LEVDISDEFAULT_P0; 673 nQ0 = LEVDISDEFAULT_Q0; 674 nR0 = LEVDISDEFAULT_R0; 675 } 676 if ( argc > 6 ) 677 { 678 strncpy( cDelim+1, argv[args+6], LINESIZE ); // \t Tab always remains 679 cDelim[LINESIZE-1] = 0; 680 } 681 } 682 else 683 { 684 if ( argc > 2 ) 685 { 686 nX = atoi(argv[args+2]); 687 nY = atoi(argv[args+3]); 688 nZ = atoi(argv[args+4]); 689 } 690 else 691 { 692 nX = LEVDISDEFAULT_XOTHER; 693 nY = LEVDISDEFAULT_YSHORTER; 694 nZ = LEVDISDEFAULT_ZLONGER; 695 } 696 if ( argc > 5 ) 697 bStrict = atoi(argv[args+5]); 698 if ( argc > 6 ) 699 { 700 strncpy( cDelim+1, argv[args+6], LINESIZE ); // \t Tab always remains 701 cDelim[LINESIZE-1] = 0; 702 } 703 } 704 if ( Direct ) 705 { 706 #error Error: conversion from char to OUString needed! 707 pTest = new WLevDistance( argv[args+1] ); 708 #ifdef erTESTDEFAULT 709 pTest->ShowTest(); 710 #endif 711 pTest->SetLimit( nLim ); 712 pTest->SetReplaceP0( nP0 ); 713 pTest->SetInsertQ0( nQ0 ); 714 pTest->SetDeleteR0( nR0 ); 715 } 716 else 717 { 718 #error Error: conversion from char to sal_Unicode needed! 719 pTest = new WLevDistance( argv[args+1], nX, nY, nZ, !bStrict ); 720 #ifdef erTESTCCTOR 721 WLevDistance aTmp( *pTest ); 722 aTmp.ShowTest(); 723 #endif 724 nLim = pTest->GetLimit(); 725 } 726 pTest->ShowTest(); 727 do 728 { 729 char* cp1, *cp2; 730 static long unsigned int nLine = 0; 731 cp1 = cLine; 732 cin.getline( cLine, LINESIZE ) ; 733 nLine++; 734 while ( *cp1 ) 735 { 736 while ( *cp1 && IsDelim(*cp1) ) 737 cp1++; 738 cp2 = cString; 739 while ( *cp1 && !IsDelim(*cp1) ) 740 *cp2++ = *cp1++; 741 *cp2 = '\0'; 742 while ( *cp1 && IsDelim(*cp1) ) 743 cp1++; 744 if ( *cString ) 745 { 746 int ret; 747 if ( IgnoreCase ) 748 { 749 char* cpi1 = cString; 750 char* cpi2 = cIgString; 751 while ( *cpi1 ) 752 *cpi2++ = tolower( *cpi1++ ); 753 *cpi2 = '\0'; 754 #error Error: conversion from char to OUString / sal_Unicode,length needed! 755 ret = pTest->WLD( cIgString ); 756 } 757 else 758 #error Error: conversion from char to OUString / sal_Unicode,length needed! 759 ret = pTest->WLD( cString ); 760 #ifdef erTESTMAT 761 printf("\n# %3d : %s\n", ret, cString); 762 #error Error: conversion from char to sal_Unicode needed! 763 pTest->ShowMatrix( cString ); 764 #else 765 if ( ret <= nLim ) 766 printf("# %3d : %s\t(line %lu)\t%s\n", ret, cString, nLine, cLine); 767 #endif 768 } 769 } 770 } while ( !cin.eof() ); 771 return 0; 772 } 773 774 #endif // erTEST 775 776