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