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_search.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
Impl_WLD_StringLen(const sal_Unicode * pStr)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
WLD(const sal_Unicode * cString,sal_Int32 nStringLen)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
CalcLPQR(int nX,int nY,int nZ,bool 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
GGT(int a,int b)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)
KGV(int a,int 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
Min3(int x,int y,int z)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
Mid3(int x,int y,int z)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
Max3(int x,int y,int z)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
InitData(const sal_Unicode * cPattern)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
WLevDistance(const::rtl::OUString & rPattern)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
WLevDistance(const sal_Unicode * cPattern,int nOtherX,int nShorterY,int nLongerZ,bool bRelaxed)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
WLevDistance(const WLevDistance & rWLD)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
~WLevDistance()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
ShowMatrix(const sal_Unicode * cString)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
ShowTest()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
IsDelim(char c)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
main(int argc,char ** argv)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