~ubuntu-branches/ubuntu/quantal/icu/quantal

« back to all changes in this revision

Viewing changes to source/test/thaitest/thaitest.cpp

  • Committer: Package Import Robot
  • Author(s): Yves Arrouye
  • Date: 2002-03-03 15:31:13 UTC
  • Revision ID: package-import@ubuntu.com-20020303153113-3ssceqlq45xbmbnc
Tags: upstream-2.0-2.1pre20020303
ImportĀ upstreamĀ versionĀ 2.0-2.1pre20020303

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 ******************************************************************************
 
3
 * Copyright (C) 1998-2001, International Business Machines Corporation and   *
 
4
 * others. All Rights Reserved.                                               *
 
5
 ******************************************************************************
 
6
 */
 
7
 
 
8
#include <errno.h>
 
9
#include <stdio.h>
 
10
#include <string.h>
 
11
 
 
12
#include "unicode/utypes.h"
 
13
#include "unicode/unicode.h"
 
14
#include "unicode/uchar.h"
 
15
#include "unicode/uchriter.h"
 
16
#include "unicode/brkiter.h"
 
17
#include "unicode/locid.h"
 
18
#include "unicode/unistr.h"
 
19
 
 
20
/*
 
21
 * This program takes a Unicode text file containing Thai text with
 
22
 * spaces inserted where the word breaks are. It computes a copy of
 
23
 * the text without spaces and uses a word instance of a Thai BreakIterator
 
24
 * to compute the word breaks. The program reports any differences in the
 
25
 * breaks.
 
26
 *
 
27
 * NOTE: by it's very nature, Thai word breaking is not exact, so it is
 
28
 * exptected that this program will always report some differences.
 
29
 */
 
30
 
 
31
/*
 
32
 * This class is a break iterator that counts words and spaces.
 
33
 */
 
34
class SpaceBreakIterator
 
35
{
 
36
public:
 
37
    // The constructor:
 
38
    // text  - pointer to an array of UChars to iterate over
 
39
    // count - the number of UChars in text
 
40
    SpaceBreakIterator(const UChar *text, int32_t count);
 
41
 
 
42
    // the destructor
 
43
    ~SpaceBreakIterator();
 
44
 
 
45
    // return next break position
 
46
    int32_t next();
 
47
 
 
48
    // return current word count
 
49
    int32_t getWordCount();
 
50
 
 
51
    // return current space count
 
52
    int32_t getSpaceCount();
 
53
 
 
54
private:
 
55
    // No arg constructor: private so clients can't call it.
 
56
    SpaceBreakIterator();
 
57
 
 
58
    // The underlying BreakIterator
 
59
    BreakIterator *fBreakIter;
 
60
 
 
61
    // address of the UChar array
 
62
    const UChar *fText;
 
63
 
 
64
    // number of UChars in fText
 
65
    int32_t fTextCount;
 
66
 
 
67
    // current word count
 
68
    int32_t fWordCount;
 
69
 
 
70
    // current space count
 
71
    int32_t fSpaceCount;
 
72
 
 
73
    // true when fBreakIter has returned DONE
 
74
    UBool fDone;
 
75
};
 
76
 
 
77
/*
 
78
 * This is the main class. It compares word breaks and reports the differences.
 
79
 */
 
80
class ThaiWordbreakTest
 
81
{
 
82
public:
 
83
    // The main constructor:
 
84
    // spaces       - pointer to a UChar array for the text with spaces
 
85
    // spaceCount   - the number of characters in the spaces array
 
86
    // noSpaces     - pointer to a UChar array for the text without spaces
 
87
    // noSpaceCount - the number of characters in the noSpaces array
 
88
    // verbose      - report all breaks if true, otherwise just report differences
 
89
        ThaiWordbreakTest(const UChar *spaces, int32_t spaceCount, const UChar *noSpaces, int32_t noSpaceCount, UBool verbose);
 
90
        ~ThaiWordbreakTest();
 
91
 
 
92
    // returns the number of breaks that are in the spaces array
 
93
    // but aren't found in the noSpaces array
 
94
        int32_t getBreaksNotFound();
 
95
 
 
96
    // returns the number of breaks which are found in the noSpaces
 
97
    // array but aren't in the spaces array
 
98
        int32_t getInvalidBreaks();
 
99
 
 
100
    // returns the number of words found in the spaces array
 
101
        int32_t getWordCount();
 
102
 
 
103
    // reads the input Unicode text file:
 
104
    // fileName  - the path name of the file
 
105
    // charCount - set to the number of UChars read from the file
 
106
    // returns   - the address of the UChar array containing the characters
 
107
        static const UChar *readFile(char *fileName, int32_t &charCount);
 
108
 
 
109
    // removes spaces form the input UChar array:
 
110
    // spaces        - pointer to the input UChar array
 
111
    // count         - number of UChars in the spaces array
 
112
    // nonSpaceCount - the number of UChars in the result array
 
113
    // returns       - the address of the UChar array with spaces removed
 
114
        static const UChar *crunchSpaces(const UChar *spaces, int32_t count, int32_t &nonSpaceCount);
 
115
 
 
116
private:
 
117
    // The no arg constructor - private so clients can't call it
 
118
        ThaiWordbreakTest();
 
119
 
 
120
    // This does the actual comparison:
 
121
    // spaces - the address of the UChar array for the text with spaces
 
122
    // spaceCount - the number of UChars in the spaces array
 
123
    // noSpaces   - the address of the UChar array for the text without spaces
 
124
    // noSpaceCount - the number of UChars in the noSpaces array
 
125
    // returns      - true if all breaks match, false otherwise
 
126
        UBool compareWordBreaks(const UChar *spaces, int32_t spaceCount,
 
127
                            const UChar *noSpaces, int32_t noSpaceCount);
 
128
 
 
129
    // helper method to report a break in the spaces
 
130
    // array that's not found in the noSpaces array
 
131
        void breakNotFound(int32_t br);
 
132
 
 
133
    // helper method to report a break that's found in
 
134
    // the noSpaces array that's not in the spaces array
 
135
        void foundInvalidBreak(int32_t br);
 
136
 
 
137
    // count of breaks in the spaces array that
 
138
    // aren't found in the noSpaces array
 
139
        int32_t fBreaksNotFound;
 
140
 
 
141
    // count of breaks found in the noSpaces array
 
142
    // that aren't in the spaces array
 
143
        int32_t fInvalidBreaks;
 
144
 
 
145
    // number of words found in the spaces array
 
146
        int32_t fWordCount;
 
147
 
 
148
    // report all breaks if true, otherwise just report differences
 
149
        UBool fVerbose;
 
150
};
 
151
 
 
152
/*
 
153
 * The main constructor: it calls compareWordBreaks and reports any differences
 
154
 */
 
155
ThaiWordbreakTest::ThaiWordbreakTest(const UChar *spaces, int32_t spaceCount,
 
156
                                     const UChar *noSpaces, int32_t noSpaceCount, UBool verbose)
 
157
: fBreaksNotFound(0), fInvalidBreaks(0), fWordCount(0), fVerbose(verbose)
 
158
{
 
159
        compareWordBreaks(spaces, spaceCount, noSpaces, noSpaceCount);
 
160
}
 
161
 
 
162
/*
 
163
 * The no arg constructor
 
164
 */
 
165
ThaiWordbreakTest::ThaiWordbreakTest()
 
166
{
 
167
        // nothing
 
168
}
 
169
 
 
170
/*
 
171
 * The destructor
 
172
 */
 
173
ThaiWordbreakTest::~ThaiWordbreakTest()
 
174
{
 
175
        // nothing?
 
176
}
 
177
 
 
178
/*
 
179
 * returns the number of breaks in the spaces array
 
180
 * that aren't found in the noSpaces array
 
181
 */
 
182
inline int32_t ThaiWordbreakTest::getBreaksNotFound()
 
183
{
 
184
        return fBreaksNotFound;
 
185
}
 
186
 
 
187
/*
 
188
 * Returns the number of breaks found in the noSpaces
 
189
 * array that aren't in the spaces array
 
190
 */
 
191
inline int32_t ThaiWordbreakTest::getInvalidBreaks()
 
192
{
 
193
        return fInvalidBreaks;
 
194
}
 
195
 
 
196
/*
 
197
 * Returns the number of words found in the spaces array
 
198
 */
 
199
inline int32_t ThaiWordbreakTest::getWordCount()
 
200
{
 
201
        return fWordCount;
 
202
}
 
203
 
 
204
/*
 
205
 * This method does the acutal break comparison and reports the results.
 
206
 * It uses a SpaceBreakIterator to iterate over the text with spaces,
 
207
 * and a word instance of a Thai BreakIterator to iterate over the text
 
208
 * without spaces.
 
209
 */
 
210
UBool ThaiWordbreakTest::compareWordBreaks(const UChar *spaces, int32_t spaceCount,
 
211
                                           const UChar *noSpaces, int32_t noSpaceCount)
 
212
{
 
213
    UBool result = true;
 
214
    Locale thai("th");
 
215
    UCharCharacterIterator *noSpaceIter = new UCharCharacterIterator(noSpaces, noSpaceCount);
 
216
        UErrorCode status = U_ZERO_ERROR;
 
217
    
 
218
    BreakIterator *breakIter = BreakIterator::createWordInstance(thai, status);
 
219
    breakIter->adoptText(noSpaceIter);
 
220
    
 
221
    SpaceBreakIterator spaceIter(spaces, spaceCount);
 
222
    
 
223
    int32_t nextBreak = 0;
 
224
    int32_t nextSpaceBreak = 0;
 
225
    int32_t iterCount = 0;
 
226
    
 
227
    while (true) {
 
228
        nextSpaceBreak = spaceIter.next();
 
229
        nextBreak = breakIter->next();
 
230
        
 
231
        if (nextSpaceBreak == BreakIterator::DONE || nextBreak == BreakIterator::DONE) {
 
232
            if (nextBreak != BreakIterator::DONE) {
 
233
                fprintf(stderr, "break iterator didn't end.\n");
 
234
            } else if (nextSpaceBreak != BreakIterator::DONE) {
 
235
                fprintf(stderr, "premature break iterator end.\n");
 
236
            }
 
237
            
 
238
            break;
 
239
        }
 
240
        
 
241
        while (nextSpaceBreak != nextBreak &&
 
242
               nextSpaceBreak != BreakIterator::DONE && nextBreak != BreakIterator::DONE) {
 
243
            if (nextSpaceBreak < nextBreak) {
 
244
                breakNotFound(nextSpaceBreak);
 
245
                result = false;
 
246
                nextSpaceBreak = spaceIter.next();
 
247
            } else if (nextSpaceBreak > nextBreak) {
 
248
                foundInvalidBreak(nextBreak);
 
249
                result = false;
 
250
                nextBreak = breakIter->next();
 
251
            }
 
252
        }
 
253
        
 
254
        if (fVerbose) {
 
255
            printf("%d   %d\n", nextSpaceBreak, nextBreak);
 
256
        }
 
257
    }
 
258
        
 
259
   
 
260
    fWordCount = spaceIter.getWordCount();
 
261
    
 
262
    delete breakIter;
 
263
 
 
264
    return result;
 
265
}
 
266
 
 
267
/*
 
268
 * Report a break that's in the text with spaces but
 
269
 * not found in the text without spaces.
 
270
 */
 
271
void ThaiWordbreakTest::breakNotFound(int32_t br)
 
272
{
 
273
    if (fVerbose) {
 
274
        printf("%d   ****\n", br);
 
275
    } else {
 
276
        fprintf(stderr, "break not found: %d\n", br);
 
277
    }
 
278
    
 
279
    fBreaksNotFound += 1;
 
280
}
 
281
 
 
282
/*
 
283
 * Report a break that's found in the text without spaces
 
284
 * that isn't in the text with spaces.
 
285
 */
 
286
void ThaiWordbreakTest::foundInvalidBreak(int32_t br)
 
287
{
 
288
    if (fVerbose) {
 
289
        printf("****   %d\n", br);
 
290
    } else {
 
291
        fprintf(stderr, "found invalid break: %d\n", br);
 
292
    }
 
293
    
 
294
    fInvalidBreaks += 1;
 
295
}
 
296
 
 
297
/*
 
298
 * Read the text from a file. The text must start with a Unicode Byte
 
299
 * Order Mark (BOM) so that we know what order to read the bytes in.
 
300
 */
 
301
const UChar *ThaiWordbreakTest::readFile(char *fileName, int32_t &charCount)
 
302
{
 
303
    FILE *f;
 
304
    int32_t fileSize;
 
305
    
 
306
    UChar *buffer;
 
307
    char *bufferChars;
 
308
    
 
309
    f = fopen(fileName, "rb");
 
310
    
 
311
    if( f == NULL ) {
 
312
        fprintf(stderr,"Couldn't open %s reason: %s \n", fileName, strerror(errno));
 
313
        return 0;
 
314
    }
 
315
    
 
316
    fseek(f, 0, SEEK_END);
 
317
    fileSize = ftell(f);
 
318
    
 
319
    fseek(f, 0, SEEK_SET);
 
320
    bufferChars = new char[fileSize];
 
321
    
 
322
    if(bufferChars == 0) {
 
323
        fprintf(stderr,"Couldn't get memory for reading %s reason: %s \n", fileName, strerror(errno));
 
324
        fclose(f);
 
325
        return 0;
 
326
    }
 
327
    
 
328
    fread(bufferChars, sizeof(char), fileSize, f);
 
329
    if( ferror(f) ) {
 
330
        fprintf(stderr,"Couldn't read %s reason: %s \n", fileName, strerror(errno));
 
331
        fclose(f);
 
332
        delete[] bufferChars;
 
333
        return 0;
 
334
    }
 
335
    fclose(f);
 
336
    
 
337
    UnicodeString myText(bufferChars, fileSize, "UTF-8");
 
338
 
 
339
    delete[] bufferChars;
 
340
    
 
341
    charCount = myText.length();
 
342
    buffer = new UChar[charCount];
 
343
    if(buffer == 0) {
 
344
        fprintf(stderr,"Couldn't get memory for reading %s reason: %s \n", fileName, strerror(errno));
 
345
        return 0;
 
346
    }
 
347
    
 
348
    myText.extract(1, myText.length(), buffer);
 
349
    charCount--;  // skip the BOM
 
350
    buffer[charCount] = 0;    // NULL terminate for easier reading in the debugger
 
351
    
 
352
    return buffer;
 
353
}
 
354
 
 
355
/*
 
356
 * Remove spaces from the input UChar array.
 
357
 *
 
358
 * We check explicitly for a Unicode code value of 0x0020
 
359
 * because Unicode::isSpaceChar returns true for CR, LF, etc.
 
360
 *
 
361
 */
 
362
const UChar *ThaiWordbreakTest::crunchSpaces(const UChar *spaces, int32_t count, int32_t &nonSpaceCount)
 
363
{
 
364
    int32_t i, out, spaceCount;
 
365
 
 
366
    spaceCount = 0;
 
367
    for (i = 0; i < count; i += 1) {
 
368
        if (spaces[i] == 0x0020 /*Unicode::isSpaceChar(spaces[i])*/) {
 
369
            spaceCount += 1;
 
370
        }
 
371
    }
 
372
 
 
373
        nonSpaceCount = count - spaceCount;
 
374
    UChar *noSpaces = new UChar[nonSpaceCount];
 
375
 
 
376
        if (noSpaces == 0) {
 
377
                fprintf(stderr, "Couldn't allocate memory for the space stripped text.\n");
 
378
                return 0;
 
379
        }
 
380
 
 
381
    for (out = 0, i = 0; i < count; i += 1) {
 
382
        if (spaces[i] != 0x0020 /*! Unicode::isSpaceChar(spaces[i])*/) {
 
383
            noSpaces[out++] = spaces[i];
 
384
        }
 
385
    }
 
386
 
 
387
        return noSpaces;
 
388
}
 
389
 
 
390
/*
 
391
 * The main routine. Read the command line arguments, read the text file,
 
392
 * remove the spaces, do the comparison and report the final results
 
393
 */
 
394
int main(int argc, char **argv)
 
395
{
 
396
    char *fileName = "space.txt";
 
397
    int arg = 1;
 
398
    UBool verbose = false;
 
399
 
 
400
    if (argc >= 2 && strcmp(argv[1], "-verbose") == 0) {
 
401
        verbose = true;
 
402
        arg += 1;
 
403
    }
 
404
 
 
405
    if (arg == argc - 1) {
 
406
        fileName = argv[arg++];
 
407
    }
 
408
 
 
409
    if (arg != argc) {
 
410
        fprintf(stderr, "Usage: %s [-verbose] [<file>]\n", argv[0]);
 
411
        return 1;
 
412
    }
 
413
 
 
414
        int32_t spaceCount, nonSpaceCount;
 
415
    const UChar *spaces, *noSpaces;
 
416
 
 
417
    spaces = ThaiWordbreakTest::readFile(fileName, spaceCount);
 
418
 
 
419
    if (spaces == 0) {
 
420
        return 1;
 
421
    }
 
422
 
 
423
    noSpaces = ThaiWordbreakTest::crunchSpaces(spaces, spaceCount, nonSpaceCount);
 
424
 
 
425
        if (noSpaces == 0) {
 
426
                return 1;
 
427
        }
 
428
 
 
429
    ThaiWordbreakTest test(spaces, spaceCount, noSpaces, nonSpaceCount, verbose);
 
430
 
 
431
        printf("word count: %d\n", test.getWordCount());
 
432
        printf("breaks not found: %d\n", test.getBreaksNotFound());
 
433
        printf("invalid breaks found: %d\n", test.getInvalidBreaks());
 
434
 
 
435
    return 0;
 
436
}
 
437
 
 
438
/*
 
439
 * The main constructor. Clear all the counts and construct a default
 
440
 * word instance of a BreakIterator.
 
441
 */
 
442
SpaceBreakIterator::SpaceBreakIterator(const UChar *text, int32_t count)
 
443
  : fBreakIter(0), fText(text), fTextCount(count), fWordCount(0), fSpaceCount(0), fDone(false)
 
444
{
 
445
    UCharCharacterIterator *iter = new UCharCharacterIterator(text, count);
 
446
    UErrorCode status = U_ZERO_ERROR;
 
447
    Locale us("us");
 
448
 
 
449
    fBreakIter = BreakIterator::createWordInstance(us, status);
 
450
    fBreakIter->adoptText(iter);
 
451
}
 
452
 
 
453
SpaceBreakIterator::SpaceBreakIterator()
 
454
{
 
455
    // nothing
 
456
}
 
457
 
 
458
/*
 
459
 * The destructor. delete the underlying BreakIterator
 
460
 */
 
461
SpaceBreakIterator::~SpaceBreakIterator()
 
462
{
 
463
    delete fBreakIter;
 
464
}
 
465
 
 
466
/*
 
467
 * Return the next break, counting words and spaces.
 
468
 */
 
469
int32_t SpaceBreakIterator::next()
 
470
{
 
471
    if (fDone) {
 
472
        return BreakIterator::DONE;
 
473
    }
 
474
    
 
475
    int32_t nextBreak = fBreakIter->next();
 
476
    
 
477
    if (nextBreak == BreakIterator::DONE) {
 
478
        fDone = true;
 
479
        return BreakIterator::DONE;
 
480
    }
 
481
    
 
482
   int32_t result = nextBreak - fSpaceCount;
 
483
    
 
484
    if (nextBreak < fTextCount) {
 
485
        if (fText[nextBreak] == 0x0020 /*Unicode::isSpaceChar(fText[nextBreak])*/) {
 
486
            fSpaceCount += fBreakIter->next() - nextBreak;
 
487
        }
 
488
    }
 
489
    
 
490
    fWordCount += 1;
 
491
 
 
492
    return result;
 
493
}
 
494
 
 
495
/*
 
496
 * Returns the current space count
 
497
 */
 
498
int32_t SpaceBreakIterator::getSpaceCount()
 
499
{
 
500
    return fSpaceCount;
 
501
}
 
502
 
 
503
/*
 
504
 * Returns the current word count
 
505
 */
 
506
int32_t SpaceBreakIterator::getWordCount()
 
507
{
 
508
    return fWordCount;
 
509
}
 
510
 
 
511