merged tag ooo/OOO330_m14
[LibreOffice.git] / i18npool / source / search / levdis.cxx
blobaa889a6d35813d399970ea42831899fa92c68ce9
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_i18npool.hxx"
30 /*************************************************************************
32 Weighted Levenshtein Distance
33 including wildcards
34 '*' for any number (0 or more) of arbitrary characters
35 '?' for exactly one arbitrary character
36 escapeable with backslash, "\*" or "\?"
38 Return:
39 WLD if WLD <= nLimit, else nLimit+1
41 or, if bSplitCount:
42 WLD if WLD <= nLimit
43 -WLD if Replace and Insert and Delete <= nLimit
44 else nLimit+1
46 Recursive definition of WLD:
48 WLD( X(i), Y(j) ) = min( WLD( X(i-1), Y(j-1) ) + p(i,j) ,
49 WLD( X(i) , Y(j-1) ) + q ,
50 WLD( X(i-1), Y(j) ) + r )
52 X(i) := the first i characters of the word X
53 Y(j) := the first j characters of the word Y
54 p(i,j) := 0 if i-th character of X == j-th character of Y,
55 p else
57 Boundary conditions:
58 WLD( X(0), Y(j) ) := j*q (Y created by j inserts)
59 WLD( X(i), Y(0) ) := i*r (Y created by i deletes)
60 WLD( X(0), Y(0) ) := 0
62 Instead of recursions a dynamic algorithm is used.
64 See also: German computer magazine
65 c't 07/89 pages 192-208 and c't 03/94 pages 230-239
67 *************************************************************************/
70 #include <string.h> // strlen()
72 #if defined( _MSC_VER )
73 #pragma warning(once: 4068)
74 #endif
76 #include "levdis.hxx"
79 #ifdef erTEST
80 #include <stdlib.h>
81 #include <stdio.h>
82 #include <iostream.h>
83 #endif
85 #ifdef SOLARIS
86 #undef min
87 #endif
89 #define LEVDISBIG (nLimit + 1) // Returnwert wenn Distanz > nLimit
90 #define LEVDISDOUBLEBUF 2048 // dadrueber wird nicht mehr gedoppelt
92 // Balance, aus Geschwindigkeitsgruenden ist dieses keine Funktion
93 // c == cpPattern[jj] == cString[ii]
94 // erst wird bis Fundstelle gesucht, wenn dort die Balance gleich ist, wird
95 // auch nach der Fundstelle verglichen
96 #define LEVDISBALANCE(jj,ii) \
97 { \
98 if ( jj != ii ) \
99 { \
100 register sal_Int32 k; \
101 if ( jj > 0 ) \
102 for ( k=0; k < jj; k++ ) \
103 if ( cpPattern[k] == c ) \
104 nBalance++; \
105 if ( ii > 0 ) \
106 for ( k=0; k < ii; k++ ) \
107 if ( cString[k] == c ) \
108 nBalance--; \
109 if ( !nBalance ) \
111 for ( k=jj+1; k < nPatternLen; k++ ) \
112 if ( cpPattern[k] == c ) \
113 nBalance++; \
114 for ( k=ii+1; k < nStringLen; k++ ) \
115 if ( cString[k] == c ) \
116 nBalance--; \
121 static sal_Int32 Impl_WLD_StringLen( const sal_Unicode* pStr )
123 const sal_Unicode* pTempStr = pStr;
124 while( *pTempStr )
125 pTempStr++;
126 return (sal_Int32)(pTempStr-pStr);
129 #ifdef erTESTMAT
130 #define erTESTMATMAX 180
131 static int npMatrix[erTESTMATMAX][erTESTMATMAX]; // nearly 64K
132 #endif
134 // Distanz von String zu Pattern
135 int WLevDistance::WLD( const sal_Unicode* cString, sal_Int32 nStringLen )
137 int nSPMin = 0; // StrafPunkteMinimum
138 int nRepS = 0; // fuer SplitCount
140 #ifdef erTESTMAT
142 for ( sal_Int32 r=0; r<=nStringLen && r < erTESTMATMAX; r++ )
143 for ( sal_Int32 c=0; c<=nPatternLen && c < erTESTMATMAX; c++ )
144 npMatrix[r][c] = 99; // Matrix initialisieren, nur visuell
146 #endif
148 // Laengendifferenz von Pattern und String
149 int nLenDiff = nPatternLen - nStars - nStringLen;
150 // mehr Einfuegungen oder Loeschungen noetig als Limit? => raus hier
151 if ( (nLenDiff * nInsQ0 > nLimit)
152 || ((nStars == 0) && (nLenDiff * nDelR0 < -nLimit)) )
153 return(LEVDISBIG);
155 // wenn der zu vergleichende String groesser ist als das bisherige Array
156 // muss dieses angepasst werden
157 if ( nStringLen >= nArrayLen )
159 // gib ihm moeglichst mehr, damit nicht gleich naechstesmal
160 // wieder realloziert werden muss
161 if ( nStringLen < LEVDISDOUBLEBUF )
162 nArrayLen = 2 * nStringLen;
163 else
164 nArrayLen = nStringLen + 1;
165 npDistance = aDisMem.NewMem( nArrayLen );
166 #ifdef erTEST
167 if ( !npDistance )
169 cerr << "DOOM! (Damned, Out Of Memory)" << endl;
170 exit(1);
172 #endif
175 // Anfangswerte der zweiten Spalte (erstes Pattern-Zeichen) berechnen
176 // die erste Spalte (0-Len Pattern) ist immer 0 .. nStringLen * nInsQ0,
177 // deren Minimum also 0
178 if ( nPatternLen == 0 )
180 // Anzahl der Loeschungen, um auf Pattern zu kommen
181 for ( sal_Int32 i=0; i <= nStringLen; i++ )
182 npDistance[i] = i * nDelR0;
184 else if ( cpPattern[0] == '*' && bpPatIsWild[0] )
186 // statt einem '*' ist alles einsetzbar
187 for ( sal_Int32 i=0; i <= nStringLen; i++ )
188 npDistance[i] = 0;
190 else
192 sal_Unicode c;
193 int nP;
194 c = cpPattern[0];
195 if ( c == '?' && bpPatIsWild[0] )
196 nP = 0; // ein '?' kann jedes Zeichen sein
197 else
198 // Minimum von Ersetzen und Loeschen+Einfuegen Gewichtung
199 nP = Min3( nRepP0, nRepP0, nDelR0 + nInsQ0 );
200 npDistance[0] = nInsQ0; // mit einfachem Einfuegen geht's los
201 npDistance[1] = nInsQ0;
202 npDistance[2] = nInsQ0;
203 int nReplacePos = -1; // tristate Flag
204 int nDelCnt = 0;
205 for ( sal_Int32 i=1; i <= nStringLen; i++, nDelCnt += nDelR0 )
207 if ( cString[i-1] == c )
208 nP = 0; // Replace ab dieser Stelle ist 0
209 // Loeschungen um auf Pattern zu kommen + Replace
210 npDistance[i] = nDelCnt + nP;
211 if ( bSplitCount )
213 if ( nReplacePos < 0 && nP )
214 { // diese Stelle wird ersetzt
215 nRepS++;
216 nReplacePos = i;
217 #ifdef erTESTMAT
218 npMatrix[i][1] = -npDistance[i];
219 #endif
221 else if ( nReplacePos > 0 && !nP )
223 int nBalance = 0; // gleiche Anzahl c
224 LEVDISBALANCE( 0, i-1 );
225 if ( !nBalance )
226 { // einer wurde ersetzt, der ein Insert war
227 nRepS--;
228 #ifdef erTESTMAT
229 npMatrix[nReplacePos][1] = npDistance[nReplacePos];
230 #endif
231 nReplacePos = 0;
236 nSPMin = Min3( npDistance[0], npDistance[1], npDistance[2] );
238 #ifdef erTESTMAT
240 for ( sal_Int32 r=0; r<=nStringLen && r < erTESTMATMAX; r++ )
242 npMatrix[r][0] = r * nInsQ0;
243 if ( npMatrix[r][1] >= 0)
244 npMatrix[r][1] = npDistance[r];
247 #endif
249 // Distanzmatrix berechnen
250 sal_Int32 j = 0; // fuer alle Spalten des Pattern, solange nicht Limit
251 while ( (j < nPatternLen-1)
252 && nSPMin <= (bSplitCount ? 2 * nLimit : nLimit) )
254 sal_Unicode c;
255 int nP, nQ, nR, nPij, d1, d2;
257 j++;
258 c = cpPattern[j];
259 if ( bpPatIsWild[j] ) // '*' oder '?' nicht escaped
260 nP = 0; // kann ohne Strafpunkte ersetzt werden
261 else
262 nP = nRepP0;
263 if ( c == '*' && bpPatIsWild[j] )
265 nQ = 0; // Einfuegen und Loeschen ohne Strafpunkte
266 nR = 0;
268 else
270 nQ = nInsQ0; // normale Gewichtung
271 nR = nDelR0;
273 d2 = npDistance[0];
274 // Anzahl Einfuegungen um von Null-String auf Pattern zu kommen erhoehen
275 npDistance[0] = npDistance[0] + nQ;
276 nSPMin = npDistance[0];
277 int nReplacePos = -1; // tristate Flag
278 // fuer jede Patternspalte den String durchgehen
279 for ( register sal_Int32 i=1; i <= nStringLen; i++ )
281 d1 = d2; // WLD( X(i-1), Y(j-1) )
282 d2 = npDistance[i]; // WLD( X(i) , Y(j-1) )
283 if ( cString[i-1] == c )
285 nPij = 0; // p(i,j)
286 if ( nReplacePos < 0 )
288 int nBalance = 0; // gleiche Anzahl c
289 LEVDISBALANCE( j, i-1 );
290 if ( !nBalance )
291 nReplacePos = 0; // keine Ersetzung mehr
294 else
295 nPij = nP;
296 // WLD( X(i), Y(j) ) = min( WLD( X(i-1), Y(j-1) ) + p(i,j) ,
297 // WLD( X(i) , Y(j-1) ) + q ,
298 // WLD( X(i-1), Y(j) ) + r )
299 npDistance[i] = Min3( d1 + nPij, d2 + nQ, npDistance[i-1] + nR );
300 if ( npDistance[i] < nSPMin )
301 nSPMin = npDistance[i];
302 if ( bSplitCount )
304 if ( nReplacePos < 0 && nPij && npDistance[i] == d1 + nPij )
305 { // diese Stelle wird ersetzt
306 nRepS++;
307 nReplacePos = i;
308 #ifdef erTESTMAT
309 npMatrix[i][j+1] = -npDistance[i];
310 #endif
312 else if ( nReplacePos > 0 && !nPij )
313 { // Zeichen in String und Pattern gleich.
314 // wenn ab hier die gleiche Anzahl dieses Zeichens
315 // sowohl in Pattern als auch in String ist, und vor
316 // dieser Stelle das Zeichen gleich oft vorkommt, war das
317 // Replace keins. Buchstabendreher werden hier erfasst
318 // und der ReplaceS zurueckgenommen, wodurch das doppelte
319 // Limit zum Tragen kommt.
320 int nBalance = 0; // gleiche Anzahl c
321 LEVDISBALANCE( j, i-1 );
322 if ( !nBalance )
323 { // einer wurde ersetzt, der ein Insert war
324 nRepS--;
325 #ifdef erTESTMAT
326 npMatrix[nReplacePos][j+1] = npDistance[nReplacePos];
327 #endif
328 nReplacePos = 0;
333 #ifdef erTESTMAT
335 for ( sal_Int32 r=0; r<=nStringLen && r < erTESTMATMAX; r++ )
336 if ( npMatrix[r][j+1] >= 0)
337 npMatrix[r][j+1] = npDistance[r];
339 #endif
341 #ifdef erTESTSPLIT
342 printf(" nRepS: %d ", nRepS );
343 #endif
344 if ( (nSPMin <= nLimit) && (npDistance[nStringLen] <= nLimit) )
345 return(npDistance[nStringLen]);
346 else
348 if ( bSplitCount )
350 if ( nRepS && nLenDiff > 0 )
351 nRepS -= nLenDiff; // Inserts wurden mitgezaehlt
352 #ifdef erTESTSPLIT
353 printf(" nRepSdiff: %d ", nRepS );
354 #endif
355 if ( (nSPMin <= 2 * nLimit)
356 && (npDistance[nStringLen] <= 2 * nLimit)
357 && (nRepS * nRepP0 <= nLimit) )
358 return( -npDistance[nStringLen] );
359 return(LEVDISBIG);
361 return(LEVDISBIG);
367 // Berechnung von nLimit, nReplP0, nInsQ0, nDelR0, bSplitCount
368 // aus Userwerten nOtherX, nShorterY, nLongerZ, bRelaxed
369 int WLevDistance::CalcLPQR( int nX, int nY, int nZ, bool bRelaxed )
371 int nMin, nMid, nMax;
372 if ( nX < 0 ) nX = 0; // nur positive Werte
373 if ( nY < 0 ) nY = 0;
374 if ( nZ < 0 ) nZ = 0;
375 if ( 0 == (nMin = Min3( nX, nY, nZ )) ) // mindestens einer 0
377 nMax = Max3( nX, nY, nZ ); // entweder 0 bei drei 0 oder Max
378 if ( 0 == (nMid = Mid3( nX, nY, nZ )) ) // sogar zwei 0
379 nLimit = nMax; // entweder 0 oder einziger >0
380 else // einer 0
381 nLimit = KGV( nMid, nMax );
383 else // alle drei nicht 0
384 nLimit = KGV( KGV( nX, nY ), nZ );
385 nRepP0 = ( nX ? nLimit / nX : nLimit + 1 );
386 nInsQ0 = ( nY ? nLimit / nY : nLimit + 1 );
387 nDelR0 = ( nZ ? nLimit / nZ : nLimit + 1 );
388 bSplitCount = bRelaxed;
389 return( nLimit );
394 // Groesster Gemeinsamer Teiler nach Euklid (Kettendivision)
395 // Sonderfall: 0 und irgendwas geben 1
396 int WLevDistance::GGT( int a, int b )
398 if ( !a || !b )
399 return 1;
400 if ( a < 0 ) a = -a;
401 if ( b < 0 ) b = -b;
404 if ( a > b )
405 a -= int(a / b) * b;
406 else
407 b -= int(b / a) * a;
408 } while ( a && b );
409 return( a ? a : b);
414 // Kleinstes Gemeinsames Vielfaches: a * b / GGT(a,b)
415 int WLevDistance::KGV( int a, int b )
417 if ( a > b ) // Ueberlauf unwahrscheinlicher machen
418 return( (a / GGT(a,b)) * b );
419 else
420 return( (b / GGT(a,b)) * a );
424 // Minimum von drei Werten
425 inline int WLevDistance::Min3( int x, int y, int z )
427 if ( x < y )
428 return( x < z ? x : z );
429 else
430 return( y < z ? y : z );
435 // mittlerer von drei Werten
436 int WLevDistance::Mid3( int x, int y, int z )
438 int min = Min3(x,y,z);
439 if ( x == min )
440 return( y < z ? y : z);
441 else if ( y == min )
442 return( x < z ? x : z);
443 else // z == min
444 return( x < y ? x : y);
449 // Maximum von drei Werten
450 int WLevDistance::Max3( int x, int y, int z )
452 if ( x > y )
453 return( x > z ? x : z );
454 else
455 return( y > z ? y : z );
460 // Daten aus CTor initialisieren
461 void WLevDistance::InitData( const sal_Unicode* cPattern )
463 cpPattern = aPatMem.GetcPtr();
464 bpPatIsWild = aPatMem.GetbPtr();
465 npDistance = aDisMem.GetPtr();
466 nStars = 0;
467 const sal_Unicode* cp1 = cPattern;
468 sal_Unicode* cp2 = cpPattern;
469 bool* bp = bpPatIsWild;
470 // Pattern kopieren, Sternchen zaehlen, escaped Jokers
471 while ( *cp1 )
473 if ( *cp1 == '\\' ) // maybe escaped
475 if ( *(cp1+1) == '*' || *(cp1+1) == '?' ) // naechstes Joker?
477 cp1++; // skip '\\'
478 nPatternLen--;
480 *bp++ = false;
482 else if ( *cp1 == '*' || *cp1 == '?' ) // Joker
484 if ( *cp1 == '*' )
485 nStars++; // Sternchenzaehler erhoehen
486 *bp++ = true;
488 else
489 *bp++ = false;
490 *cp2++ = *cp1++;
492 *cp2 = '\0';
496 // CTor
498 #ifdef erTEST
500 WLevDistance::WLevDistance( const ::rtl::OUString& rPattern ) :
501 nPatternLen( rPattern.getLength() ),
502 aPatMem( nPatternLen + 1 ),
503 nArrayLen( nPatternLen + 1 ),
504 aDisMem( nArrayLen ),
505 nLimit( LEVDISDEFAULTLIMIT ),
506 nRepP0( LEVDISDEFAULT_P0 ),
507 nInsQ0( LEVDISDEFAULT_Q0 ),
508 nDelR0( LEVDISDEFAULT_R0 ),
509 bSplitCount( false )
511 InitData( rPattern.getStr() );
514 #endif // erTEST
517 WLevDistance::WLevDistance( const sal_Unicode* cPattern,
518 int nOtherX, int nShorterY, int nLongerZ,
519 bool bRelaxed ) :
520 nPatternLen( Impl_WLD_StringLen(cPattern) ),
521 aPatMem( nPatternLen + 1 ),
522 nArrayLen( nPatternLen + 1 ),
523 aDisMem( nArrayLen )
525 InitData( cPattern );
526 CalcLPQR( nOtherX, nShorterY, nLongerZ, bRelaxed );
530 // CopyCTor
531 WLevDistance::WLevDistance( const WLevDistance& rWLD ) :
532 nPatternLen( rWLD.nPatternLen ),
533 aPatMem( nPatternLen + 1 ),
534 nArrayLen( nPatternLen + 1 ),
535 aDisMem( nArrayLen ),
536 nLimit( rWLD.nLimit ),
537 nRepP0( rWLD.nRepP0 ),
538 nInsQ0( rWLD.nInsQ0 ),
539 nDelR0( rWLD.nDelR0 ),
540 nStars( rWLD.nStars ),
541 bSplitCount( rWLD.bSplitCount )
543 cpPattern = aPatMem.GetcPtr();
544 bpPatIsWild = aPatMem.GetbPtr();
545 npDistance = aDisMem.GetPtr();
546 sal_Int32 i;
547 for ( i=0; i<nPatternLen; i++ )
549 cpPattern[i] = rWLD.cpPattern[i];
550 bpPatIsWild[i] = rWLD.bpPatIsWild[i];
552 cpPattern[i] = '\0';
556 // DTor
557 WLevDistance::~WLevDistance()
561 /*************************************************************************
562 * Test
563 *************************************************************************/
565 #ifdef erTEST
567 #define LINESIZE 1000
568 typedef char MAXSTRING [LINESIZE+1];
570 #ifdef erTESTMAT
572 void WLevDistance::ShowMatrix( const sal_Unicode* cString )
574 sal_Int32 r, c, l = Impl_WLD_StringLen(cString);
575 printf(" | ");
576 for ( c=0; c<nPatternLen; c++ )
577 #error Error: conversion from sal_Unicode to char needed!
578 printf( " %c ", cpPattern[c] );
579 printf("\n---+---");
580 for ( c=0; c<nPatternLen; c++ )
581 printf( "---" );
582 for ( r=0; r<=l && r < erTESTMATMAX; r++ )
584 #error Error: conversion from sal_Unicode to char needed!
585 printf( "\n %c |", ( r==0 ? ' ' : cString[r-1] ) );
586 for ( c=0; c<=nPatternLen && c < erTESTMATMAX; c++ )
587 printf( "%2d ", npMatrix[r][c] );
589 printf("\n\n");
592 #endif // erTESTMAT
594 // Delimiter fuer Token, \t Tab bleibt fuer immer an der ersten Stelle
595 MAXSTRING cDelim = "\t, ;(){}[]<>&=+-/%!|.\\'\"~";
597 void WLevDistance::ShowTest()
599 printf(" \n");
600 #error Error: conversion from sal_Unicode to char needed!
601 printf(" a *cpPattern . . . . : %s\n", cpPattern);
602 printf(" b *bpPatIsWild . . . : ");
603 for ( sal_Int32 i=0; i<nPatternLen; i++ )
604 printf("%d", bpPatIsWild[i]);
605 printf("\n");
606 printf(" c nPatternLen . . . : %d\n", (int)nPatternLen);
607 printf(" d nStars . . . . . . : %d\n", nStars);
608 printf(" e nLimit . . . . . . : %d\n", nLimit);
609 printf(" f nRepP0 (Ersetzen) : %d\n", nRepP0);
610 printf(" g nInsQ0 (Einfuegen) : %d\n", nInsQ0);
611 printf(" h nDelR0 (Loeschen) : %d\n", nDelR0);
612 printf(" i bSplitCount . . . : %d\n", bSplitCount);
613 #error Error: conversion from sal_Unicode to char needed!
614 printf(" j cDelim . . . . . . : '%s'\n", cDelim);
615 printf(" ~\n");
618 inline bool IsDelim( char c )
620 char* cp = cDelim;
621 while ( *cp )
622 if ( *cp++ == c )
623 return( true );
624 return( false );
627 MAXSTRING cString, cLine, cIgString;
629 int main( int argc, char **argv )
631 int nLim, nP0, nQ0, nR0, nX, nY, nZ;
632 int args = 0;
633 bool IgnoreCase = false, Direct = false, bStrict = false;
634 WLevDistance* pTest;
635 if ( argc < 2 )
637 printf("%s Syntax:\n"
638 " ... [-i] cPattern [nOtherX, nShorterY, nLongerZ [bStrict [cDelim]]] [<stdin] [>stdout]\n"
639 " ... -d cPattern [nLimit [nRepP0 nInsQ0 nDelR0 [cDelim]]] [<stdin] [>stdout]\n"
640 , argv[0]);
641 exit(1);
643 if ( *argv[1] == '-' )
645 args++;
646 argc--;
647 switch ( *(argv[1]+1) )
649 case 'i':
651 IgnoreCase = true;
652 char* cp = argv[args+1];
653 while ( (*cp = tolower( *cp )) != 0 )
654 cp++;
655 break;
657 case 'd':
658 Direct = true;
659 break;
662 if ( Direct )
664 if ( argc > 2 )
665 nLim = atoi(argv[args+2]);
666 else
667 nLim = LEVDISDEFAULTLIMIT;
668 if ( argc > 3 )
670 nP0 = atoi(argv[args+3]);
671 nQ0 = atoi(argv[args+4]);
672 nR0 = atoi(argv[args+5]);
674 else
676 nP0 = LEVDISDEFAULT_P0;
677 nQ0 = LEVDISDEFAULT_Q0;
678 nR0 = LEVDISDEFAULT_R0;
680 if ( argc > 6 )
682 strncpy( cDelim+1, argv[args+6], LINESIZE ); // \t Tab always remains
683 cDelim[LINESIZE-1] = 0;
686 else
688 if ( argc > 2 )
690 nX = atoi(argv[args+2]);
691 nY = atoi(argv[args+3]);
692 nZ = atoi(argv[args+4]);
694 else
696 nX = LEVDISDEFAULT_XOTHER;
697 nY = LEVDISDEFAULT_YSHORTER;
698 nZ = LEVDISDEFAULT_ZLONGER;
700 if ( argc > 5 )
701 bStrict = atoi(argv[args+5]);
702 if ( argc > 6 )
704 strncpy( cDelim+1, argv[args+6], LINESIZE ); // \t Tab always remains
705 cDelim[LINESIZE-1] = 0;
708 if ( Direct )
710 #error Error: conversion from char to OUString needed!
711 pTest = new WLevDistance( argv[args+1] );
712 #ifdef erTESTDEFAULT
713 pTest->ShowTest();
714 #endif
715 pTest->SetLimit( nLim );
716 pTest->SetReplaceP0( nP0 );
717 pTest->SetInsertQ0( nQ0 );
718 pTest->SetDeleteR0( nR0 );
720 else
722 #error Error: conversion from char to sal_Unicode needed!
723 pTest = new WLevDistance( argv[args+1], nX, nY, nZ, !bStrict );
724 #ifdef erTESTCCTOR
725 WLevDistance aTmp( *pTest );
726 aTmp.ShowTest();
727 #endif
728 nLim = pTest->GetLimit();
730 pTest->ShowTest();
733 char* cp1, *cp2;
734 static long unsigned int nLine = 0;
735 cp1 = cLine;
736 cin.getline( cLine, LINESIZE ) ;
737 nLine++;
738 while ( *cp1 )
740 while ( *cp1 && IsDelim(*cp1) )
741 cp1++;
742 cp2 = cString;
743 while ( *cp1 && !IsDelim(*cp1) )
744 *cp2++ = *cp1++;
745 *cp2 = '\0';
746 while ( *cp1 && IsDelim(*cp1) )
747 cp1++;
748 if ( *cString )
750 int ret;
751 if ( IgnoreCase )
753 char* cpi1 = cString;
754 char* cpi2 = cIgString;
755 while ( *cpi1 )
756 *cpi2++ = tolower( *cpi1++ );
757 *cpi2 = '\0';
758 #error Error: conversion from char to OUString / sal_Unicode,length needed!
759 ret = pTest->WLD( cIgString );
761 else
762 #error Error: conversion from char to OUString / sal_Unicode,length needed!
763 ret = pTest->WLD( cString );
764 #ifdef erTESTMAT
765 printf("\n# %3d : %s\n", ret, cString);
766 #error Error: conversion from char to sal_Unicode needed!
767 pTest->ShowMatrix( cString );
768 #else
769 if ( ret <= nLim )
770 printf("# %3d : %s\t(line %lu)\t%s\n", ret, cString, nLine, cLine);
771 #endif
774 } while ( !cin.eof() );
775 return 0;
778 #endif // erTEST