~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/common/normlzr.cpp

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *************************************************************************
3
 
 * COPYRIGHT: 
4
 
 * Copyright (c) 1996-2001, International Business Machines Corporation and
5
 
 * others. All Rights Reserved.
6
 
 *************************************************************************
7
 
 */
8
 
 
9
 
#include "unicode/utypes.h"
10
 
#include "unicode/unistr.h"
11
 
#include "unicode/chariter.h"
12
 
#include "unicode/schriter.h"
13
 
#include "unicode/uchriter.h"
14
 
#include "unicode/uiter.h"
15
 
#include "unicode/normlzr.h"
16
 
#include "cmemory.h"
17
 
#include "unormimp.h"
18
 
 
19
 
U_NAMESPACE_BEGIN
20
 
 
21
 
//-------------------------------------------------------------------------
22
 
// Constructors and other boilerplate
23
 
//-------------------------------------------------------------------------
24
 
 
25
 
Normalizer::Normalizer(const UnicodeString& str, UNormalizationMode mode) :
26
 
    fUMode(mode), fOptions(0),
27
 
    currentIndex(0), nextIndex(0),
28
 
    buffer(), bufferPos(0)
29
 
{
30
 
    init(new StringCharacterIterator(str));
31
 
}
32
 
 
33
 
Normalizer::Normalizer(const UChar *str, int32_t length, UNormalizationMode mode) :
34
 
    fUMode(mode), fOptions(0),
35
 
    currentIndex(0), nextIndex(0),
36
 
    buffer(), bufferPos(0)
37
 
{
38
 
    init(new UCharCharacterIterator(str, length));
39
 
}
40
 
 
41
 
Normalizer::Normalizer(const CharacterIterator& iter, UNormalizationMode mode) :
42
 
    fUMode(mode), fOptions(0),
43
 
    currentIndex(0), nextIndex(0),
44
 
    buffer(), bufferPos(0)
45
 
{
46
 
    init(iter.clone());
47
 
}
48
 
 
49
 
// deprecated constructors
50
 
 
51
 
Normalizer::Normalizer(const UnicodeString& str, 
52
 
                       EMode mode) :
53
 
    fUMode(getUMode(mode)), fOptions(0),
54
 
    currentIndex(0), nextIndex(0),
55
 
    buffer(), bufferPos(0)
56
 
{
57
 
    init(new StringCharacterIterator(str));
58
 
}
59
 
 
60
 
Normalizer::Normalizer(const UnicodeString& str, 
61
 
                       EMode mode, 
62
 
                       int32_t options) :
63
 
    fUMode(getUMode(mode)), fOptions(options),
64
 
    currentIndex(0), nextIndex(0),
65
 
    buffer(), bufferPos(0)
66
 
{
67
 
    init(new StringCharacterIterator(str));
68
 
}
69
 
 
70
 
Normalizer::Normalizer(const UChar *str, int32_t length, EMode mode) :
71
 
    fUMode(getUMode(mode)), fOptions(0),
72
 
    currentIndex(0), nextIndex(0),
73
 
    buffer(), bufferPos(0)
74
 
{
75
 
    init(new UCharCharacterIterator(str, length));
76
 
}
77
 
 
78
 
Normalizer::Normalizer(const CharacterIterator& iter, 
79
 
                       EMode mode) :
80
 
    fUMode(getUMode(mode)), fOptions(0),
81
 
    currentIndex(0), nextIndex(0),
82
 
    buffer(), bufferPos(0)
83
 
{
84
 
    init(iter.clone());
85
 
}
86
 
 
87
 
Normalizer::Normalizer(const CharacterIterator& iter, 
88
 
                       EMode mode, 
89
 
                       int32_t options) :
90
 
    fUMode(getUMode(mode)), fOptions(options),
91
 
    currentIndex(0), nextIndex(0),
92
 
    buffer(), bufferPos(0)
93
 
{
94
 
    init(iter.clone());
95
 
}
96
 
 
97
 
Normalizer::Normalizer(const Normalizer &copy) :
98
 
    fUMode(copy.fUMode), fOptions(copy.fOptions),
99
 
    currentIndex(copy.currentIndex), nextIndex(copy.nextIndex),
100
 
    buffer(copy.buffer), bufferPos(copy.bufferPos)
101
 
{
102
 
    init(((CharacterIterator *)(copy.text->context))->clone());
103
 
}
104
 
 
105
 
static const UChar _NUL=0;
106
 
 
107
 
void
108
 
Normalizer::init(CharacterIterator *iter) {
109
 
    UErrorCode errorCode=U_ZERO_ERROR;
110
 
 
111
 
    text=new UCharIterator;
112
 
 
113
 
    if(unorm_haveData(&errorCode)) {
114
 
        uiter_setCharacterIterator(text, iter);
115
 
    } else {
116
 
        delete iter;
117
 
        uiter_setCharacterIterator(text, new UCharCharacterIterator(&_NUL, 0));
118
 
    }
119
 
}
120
 
 
121
 
Normalizer::~Normalizer()
122
 
{
123
 
    delete (CharacterIterator *)text->context;
124
 
    delete text;
125
 
}
126
 
 
127
 
Normalizer* 
128
 
Normalizer::clone() const
129
 
{
130
 
    if(this!=0) {
131
 
        return new Normalizer(*this);
132
 
    } else {
133
 
        return 0;
134
 
    }
135
 
}
136
 
 
137
 
/**
138
 
 * Generates a hash code for this iterator.
139
 
 */
140
 
int32_t Normalizer::hashCode() const
141
 
{
142
 
    return ((CharacterIterator *)(text->context))->hashCode() + fUMode + fOptions + buffer.hashCode() + bufferPos + currentIndex + nextIndex;
143
 
}
144
 
    
145
 
UBool Normalizer::operator==(const Normalizer& that) const
146
 
{
147
 
    return
148
 
        this==&that ||
149
 
        fUMode==that.fUMode &&
150
 
        fOptions==that.fOptions &&
151
 
        *((CharacterIterator *)(text->context))==*((CharacterIterator *)(that.text->context)) &&
152
 
        buffer==that.buffer &&
153
 
        bufferPos==that.bufferPos &&
154
 
        nextIndex==that.nextIndex;
155
 
}
156
 
 
157
 
//-------------------------------------------------------------------------
158
 
// Static utility methods
159
 
//-------------------------------------------------------------------------
160
 
 
161
 
void 
162
 
Normalizer::normalize(const UnicodeString& source, 
163
 
                      UNormalizationMode mode, int32_t options,
164
 
                      UnicodeString& result, 
165
 
                      UErrorCode &status) {
166
 
    if(source.isBogus() || U_FAILURE(status)) {
167
 
        result.setToBogus();
168
 
        if(U_SUCCESS(status)) {
169
 
            status=U_ILLEGAL_ARGUMENT_ERROR;
170
 
        }
171
 
    } else {
172
 
        UChar *buffer=result.getBuffer(source.length());
173
 
        int32_t length=unorm_internalNormalize(buffer, result.getCapacity(),
174
 
                                               source.getBuffer(), source.length(),
175
 
                                               mode, (options&IGNORE_HANGUL)!=0,
176
 
                                               &status);
177
 
        result.releaseBuffer(length);
178
 
        if(status==U_BUFFER_OVERFLOW_ERROR) {
179
 
            status=U_ZERO_ERROR;
180
 
            buffer=result.getBuffer(length);
181
 
            length=unorm_internalNormalize(buffer, result.getCapacity(),
182
 
                                           source.getBuffer(), source.length(),
183
 
                                           mode, (options&IGNORE_HANGUL)!=0,
184
 
                                           &status);
185
 
            result.releaseBuffer(length);
186
 
        }
187
 
 
188
 
        if(U_FAILURE(status)) {
189
 
            result.setToBogus();
190
 
        }
191
 
    }
192
 
}
193
 
 
194
 
UNormalizationCheckResult
195
 
Normalizer::quickCheck(const UnicodeString& source,
196
 
                       UNormalizationMode mode, 
197
 
                       UErrorCode &status) {
198
 
    if(U_FAILURE(status)) {
199
 
        return UNORM_MAYBE;
200
 
    }
201
 
 
202
 
    return unorm_quickCheck(source.getBuffer(), source.length(),
203
 
                            mode, &status);
204
 
}
205
 
 
206
 
void
207
 
Normalizer::compose(const UnicodeString& source, 
208
 
                    UBool compat, int32_t options,
209
 
                    UnicodeString& result, 
210
 
                    UErrorCode &status) {
211
 
    if(source.isBogus() || U_FAILURE(status)) {
212
 
        result.setToBogus();
213
 
        if(U_SUCCESS(status)) {
214
 
            status=U_ILLEGAL_ARGUMENT_ERROR;
215
 
        }
216
 
    } else {
217
 
        UChar *buffer=result.getBuffer(source.length());
218
 
        int32_t length=unorm_compose(buffer, result.getCapacity(),
219
 
                                     source.getBuffer(), source.length(),
220
 
                                     compat, (options&IGNORE_HANGUL)!=0,
221
 
                                     &status);
222
 
        result.releaseBuffer(length);
223
 
        if(status==U_BUFFER_OVERFLOW_ERROR) {
224
 
            status=U_ZERO_ERROR;
225
 
            buffer=result.getBuffer(length);
226
 
            length=unorm_compose(buffer, result.getCapacity(),
227
 
                                 source.getBuffer(), source.length(),
228
 
                                 compat, (options&IGNORE_HANGUL)!=0,
229
 
                                 &status);
230
 
            result.releaseBuffer(length);
231
 
        }
232
 
 
233
 
        if(U_FAILURE(status)) {
234
 
            result.setToBogus();
235
 
        }
236
 
    }
237
 
}
238
 
 
239
 
void
240
 
Normalizer::decompose(const UnicodeString& source, 
241
 
                      UBool compat, int32_t options,
242
 
                      UnicodeString& result, 
243
 
                      UErrorCode &status) {
244
 
    if(source.isBogus() || U_FAILURE(status)) {
245
 
        result.setToBogus();
246
 
        if(U_SUCCESS(status)) {
247
 
            status=U_ILLEGAL_ARGUMENT_ERROR;
248
 
        }
249
 
    } else {
250
 
        UChar *buffer=result.getBuffer(source.length());
251
 
        int32_t length=unorm_decompose(buffer, result.getCapacity(),
252
 
                                     source.getBuffer(), source.length(),
253
 
                                     compat, (options&IGNORE_HANGUL)!=0,
254
 
                                     &status);
255
 
        result.releaseBuffer(length);
256
 
        if(status==U_BUFFER_OVERFLOW_ERROR) {
257
 
            status=U_ZERO_ERROR;
258
 
            buffer=result.getBuffer(length);
259
 
            length=unorm_decompose(buffer, result.getCapacity(),
260
 
                                   source.getBuffer(), source.length(),
261
 
                                   compat, (options&IGNORE_HANGUL)!=0,
262
 
                                   &status);
263
 
            result.releaseBuffer(length);
264
 
        }
265
 
 
266
 
        if(U_FAILURE(status)) {
267
 
            result.setToBogus();
268
 
        }
269
 
    }
270
 
}
271
 
 
272
 
UnicodeString &
273
 
Normalizer::concatenate(UnicodeString &left, UnicodeString &right,
274
 
                        UnicodeString &result,
275
 
                        UNormalizationMode mode, int32_t options,
276
 
                        UErrorCode &errorCode) {
277
 
    if(left.isBogus() || right.isBogus() || U_FAILURE(errorCode)) {
278
 
        result.setToBogus();
279
 
        if(U_SUCCESS(errorCode)) {
280
 
            errorCode=U_ILLEGAL_ARGUMENT_ERROR;
281
 
        }
282
 
    } else {
283
 
        UChar *buffer=result.getBuffer(left.length()+right.length());
284
 
        int32_t length=unorm_concatenate(left.getBuffer(), left.length(),
285
 
                                         right.getBuffer(), right.length(),
286
 
                                         buffer, result.getCapacity(),
287
 
                                         mode, options,
288
 
                                         &errorCode);
289
 
        result.releaseBuffer(length);
290
 
        if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
291
 
            errorCode=U_ZERO_ERROR;
292
 
            buffer=result.getBuffer(length);
293
 
            int32_t length=unorm_concatenate(left.getBuffer(), left.length(),
294
 
                                             right.getBuffer(), right.length(),
295
 
                                             buffer, result.getCapacity(),
296
 
                                             mode, options,
297
 
                                             &errorCode);
298
 
            result.releaseBuffer(length);
299
 
        }
300
 
 
301
 
        if(U_FAILURE(errorCode)) {
302
 
            result.setToBogus();
303
 
        }
304
 
    }
305
 
    return result;
306
 
}
307
 
 
308
 
//-------------------------------------------------------------------------
309
 
// Iteration API
310
 
//-------------------------------------------------------------------------
311
 
 
312
 
/**
313
 
 * Return the current character in the normalized text->
314
 
 */
315
 
UChar32 Normalizer::current() {
316
 
    if(bufferPos<buffer.length() || nextNormalize()) {
317
 
        return buffer.char32At(bufferPos);
318
 
    } else {
319
 
        return DONE;
320
 
    }
321
 
}
322
 
 
323
 
/**
324
 
 * Return the next character in the normalized text and advance
325
 
 * the iteration position by one.  If the end
326
 
 * of the text has already been reached, {@link #DONE} is returned.
327
 
 */
328
 
UChar32 Normalizer::next() {
329
 
    if(bufferPos<buffer.length() ||  nextNormalize()) {
330
 
        UChar32 c=buffer.char32At(bufferPos);
331
 
        bufferPos+=UTF_CHAR_LENGTH(c);
332
 
        return c;
333
 
    } else {
334
 
        return DONE;
335
 
    }
336
 
}
337
 
 
338
 
/**
339
 
 * Return the previous character in the normalized text and decrement
340
 
 * the iteration position by one.  If the beginning
341
 
 * of the text has already been reached, {@link #DONE} is returned.
342
 
 */
343
 
UChar32 Normalizer::previous() {
344
 
    if(bufferPos>0 || previousNormalize()) {
345
 
        UChar32 c=buffer.char32At(bufferPos-1);
346
 
        bufferPos-=UTF_CHAR_LENGTH(c);
347
 
        return c;
348
 
    } else {
349
 
        return DONE;
350
 
    }
351
 
}
352
 
 
353
 
void Normalizer::reset() {
354
 
    currentIndex=nextIndex=text->move(text, 0, UITER_START);
355
 
    clearBuffer();
356
 
}
357
 
 
358
 
void
359
 
Normalizer::setIndexOnly(int32_t index) {
360
 
    currentIndex=nextIndex=text->move(text, index, UITER_ZERO); // validates index
361
 
    clearBuffer();
362
 
}
363
 
 
364
 
/**
365
 
 * Set the iteration position in the input text that is being normalized
366
 
 * and return the first normalized character at that position.
367
 
 * <p>
368
 
 * <b>Note:</b> This method sets the position in the <em>input</em> text,
369
 
 * while {@link #next} and {@link #previous} iterate through characters
370
 
 * in the normalized <em>output</em>.  This means that there is not
371
 
 * necessarily a one-to-one correspondence between characters returned
372
 
 * by <tt>next</tt> and <tt>previous</tt> and the indices passed to and
373
 
 * returned from <tt>setIndex</tt> and {@link #getIndex}.
374
 
 * <p>
375
 
 * @param index the desired index in the input text->
376
 
 *
377
 
 * @return      the first normalized character that is the result of iterating
378
 
 *              forward starting at the given index.
379
 
 *
380
 
 * @throws IllegalArgumentException if the given index is less than
381
 
 *          {@link #getBeginIndex} or greater than {@link #getEndIndex}.
382
 
 */
383
 
UChar32 Normalizer::setIndex(int32_t index) {
384
 
    setIndexOnly(index);
385
 
    return current();
386
 
}
387
 
 
388
 
/**
389
 
 * Return the first character in the normalized text->  This resets
390
 
 * the <tt>Normalizer's</tt> position to the beginning of the text->
391
 
 */
392
 
UChar32 Normalizer::first() {
393
 
    reset();
394
 
    return next();
395
 
}
396
 
 
397
 
/**
398
 
 * Return the last character in the normalized text->  This resets
399
 
 * the <tt>Normalizer's</tt> position to be just before the
400
 
 * the input text corresponding to that normalized character.
401
 
 */
402
 
UChar32 Normalizer::last() {
403
 
    currentIndex=nextIndex=text->move(text, 0, UITER_LIMIT);
404
 
    clearBuffer();
405
 
    return previous();
406
 
}
407
 
 
408
 
/**
409
 
 * Retrieve the current iteration position in the input text that is
410
 
 * being normalized.  This method is useful in applications such as
411
 
 * searching, where you need to be able to determine the position in
412
 
 * the input text that corresponds to a given normalized output character.
413
 
 * <p>
414
 
 * <b>Note:</b> This method sets the position in the <em>input</em>, while
415
 
 * {@link #next} and {@link #previous} iterate through characters in the
416
 
 * <em>output</em>.  This means that there is not necessarily a one-to-one
417
 
 * correspondence between characters returned by <tt>next</tt> and
418
 
 * <tt>previous</tt> and the indices passed to and returned from
419
 
 * <tt>setIndex</tt> and {@link #getIndex}.
420
 
 *
421
 
 */
422
 
int32_t Normalizer::getIndex() const {
423
 
    if(bufferPos<buffer.length()) {
424
 
        return currentIndex;
425
 
    } else {
426
 
        return nextIndex;
427
 
    }
428
 
}
429
 
 
430
 
/**
431
 
 * Retrieve the index of the start of the input text->  This is the begin index
432
 
 * of the <tt>CharacterIterator</tt> or the start (i.e. 0) of the <tt>String</tt>
433
 
 * over which this <tt>Normalizer</tt> is iterating
434
 
 */
435
 
int32_t Normalizer::startIndex() const {
436
 
    return text->getIndex(text, UITER_START);
437
 
}
438
 
 
439
 
/**
440
 
 * Retrieve the index of the end of the input text->  This is the end index
441
 
 * of the <tt>CharacterIterator</tt> or the length of the <tt>String</tt>
442
 
 * over which this <tt>Normalizer</tt> is iterating
443
 
 */
444
 
int32_t Normalizer::endIndex() const {
445
 
    return text->getIndex(text, UITER_LIMIT);
446
 
}
447
 
 
448
 
//-------------------------------------------------------------------------
449
 
// Property access methods
450
 
//-------------------------------------------------------------------------
451
 
 
452
 
void
453
 
Normalizer::setMode(UNormalizationMode newMode) 
454
 
{
455
 
    fUMode = newMode;
456
 
}
457
 
 
458
 
UNormalizationMode
459
 
Normalizer::getUMode() const
460
 
{
461
 
    return fUMode;
462
 
}
463
 
 
464
 
void
465
 
Normalizer::setOption(int32_t option, 
466
 
                      UBool value) 
467
 
{
468
 
    if (value) {
469
 
        fOptions |= option;
470
 
    } else {
471
 
        fOptions &= (~option);
472
 
    }
473
 
}
474
 
 
475
 
UBool
476
 
Normalizer::getOption(int32_t option) const
477
 
{
478
 
    return (fOptions & option) != 0;
479
 
}
480
 
 
481
 
/**
482
 
 * Set the input text over which this <tt>Normalizer</tt> will iterate.
483
 
 * The iteration position is set to the beginning of the input text->
484
 
 */
485
 
void
486
 
Normalizer::setText(const UnicodeString& newText, 
487
 
                    UErrorCode &status)
488
 
{
489
 
    if (U_FAILURE(status)) {
490
 
        return;
491
 
    }
492
 
    CharacterIterator *newIter = new StringCharacterIterator(newText);
493
 
    if (newIter == NULL) {
494
 
        status = U_MEMORY_ALLOCATION_ERROR;
495
 
        return;
496
 
    }
497
 
    delete (CharacterIterator *)(text->context);
498
 
    text->context = newIter;
499
 
    reset();
500
 
}
501
 
 
502
 
/**
503
 
 * Set the input text over which this <tt>Normalizer</tt> will iterate.
504
 
 * The iteration position is set to the beginning of the string.
505
 
 */
506
 
void
507
 
Normalizer::setText(const CharacterIterator& newText, 
508
 
                    UErrorCode &status) 
509
 
{
510
 
    if (U_FAILURE(status)) {
511
 
        return;
512
 
    }
513
 
    CharacterIterator *newIter = newText.clone();
514
 
    if (newIter == NULL) {
515
 
        status = U_MEMORY_ALLOCATION_ERROR;
516
 
        return;
517
 
    }
518
 
    delete (CharacterIterator *)(text->context);
519
 
    text->context = newIter;
520
 
    reset();
521
 
}
522
 
 
523
 
void
524
 
Normalizer::setText(const UChar* newText,
525
 
                    int32_t length,
526
 
                    UErrorCode &status)
527
 
{
528
 
    if (U_FAILURE(status)) {
529
 
        return;
530
 
    }
531
 
    CharacterIterator *newIter = new UCharCharacterIterator(newText, length);
532
 
    if (newIter == NULL) {
533
 
        status = U_MEMORY_ALLOCATION_ERROR;
534
 
        return;
535
 
    }
536
 
    delete (CharacterIterator *)(text->context);
537
 
    text->context = newIter;
538
 
    reset();
539
 
}
540
 
 
541
 
/**
542
 
 * Copies the text under iteration into the UnicodeString referred to by "result".
543
 
 * @param result Receives a copy of the text under iteration.
544
 
 */
545
 
void
546
 
Normalizer::getText(UnicodeString&  result) 
547
 
{
548
 
    ((CharacterIterator *)(text->context))->getText(result);
549
 
}
550
 
 
551
 
//-------------------------------------------------------------------------
552
 
// Private utility methods
553
 
//-------------------------------------------------------------------------
554
 
 
555
 
void Normalizer::clearBuffer() {
556
 
    buffer.remove();
557
 
    bufferPos=0;
558
 
}
559
 
 
560
 
UBool
561
 
Normalizer::nextNormalize() {
562
 
    UChar *p;
563
 
    int32_t length;
564
 
    UErrorCode errorCode;
565
 
 
566
 
    clearBuffer();
567
 
    currentIndex=nextIndex;
568
 
    text->move(text, nextIndex, UITER_ZERO);
569
 
    if(!text->hasNext(text)) {
570
 
        return FALSE;
571
 
    }
572
 
 
573
 
    errorCode=U_ZERO_ERROR;
574
 
    p=buffer.getBuffer(-1);
575
 
    length=unorm_next(text, p, buffer.getCapacity(),
576
 
                      fUMode, fOptions!=0,
577
 
                      TRUE, 0,
578
 
                      &errorCode);
579
 
    buffer.releaseBuffer(length);
580
 
    if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
581
 
        errorCode=U_ZERO_ERROR;
582
 
        text->move(text, nextIndex, UITER_ZERO);
583
 
        p=buffer.getBuffer(length);
584
 
        length=unorm_next(text, p, buffer.getCapacity(),
585
 
                          fUMode, fOptions!=0,
586
 
                          TRUE, 0,
587
 
                          &errorCode);
588
 
        buffer.releaseBuffer(length);
589
 
    }
590
 
 
591
 
    nextIndex=text->getIndex(text, UITER_CURRENT);
592
 
    return U_SUCCESS(errorCode) && !buffer.isEmpty();
593
 
}
594
 
 
595
 
UBool
596
 
Normalizer::previousNormalize() {
597
 
    UChar *p;
598
 
    int32_t length;
599
 
    UErrorCode errorCode;
600
 
 
601
 
    clearBuffer();
602
 
    nextIndex=currentIndex;
603
 
    text->move(text, currentIndex, UITER_ZERO);
604
 
    if(!text->hasPrevious(text)) {
605
 
        return FALSE;
606
 
    }
607
 
 
608
 
    errorCode=U_ZERO_ERROR;
609
 
    p=buffer.getBuffer(-1);
610
 
    length=unorm_previous(text, p, buffer.getCapacity(),
611
 
                          fUMode, fOptions,
612
 
                          TRUE, 0,
613
 
                          &errorCode);
614
 
    buffer.releaseBuffer(length);
615
 
    if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
616
 
        errorCode=U_ZERO_ERROR;
617
 
        text->move(text, currentIndex, UITER_ZERO);
618
 
        p=buffer.getBuffer(length);
619
 
        length=unorm_previous(text, p, buffer.getCapacity(),
620
 
                              fUMode, fOptions,
621
 
                              TRUE, 0,
622
 
                              &errorCode);
623
 
        buffer.releaseBuffer(length);
624
 
    }
625
 
 
626
 
    bufferPos=buffer.length();
627
 
    currentIndex=text->getIndex(text, UITER_CURRENT);
628
 
    return U_SUCCESS(errorCode) && !buffer.isEmpty();
629
 
}
630
 
 
631
 
U_NAMESPACE_END