Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/intl/icu/source/common/norm2allmodes.h
Line
Count
Source (jump to first uncovered line)
1
// © 2016 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
/*
4
*******************************************************************************
5
* Copyright (C) 2014, International Business Machines
6
* Corporation and others.  All Rights Reserved.
7
*******************************************************************************
8
* norm2allmodes.h
9
*
10
* created on: 2014sep07
11
* created by: Markus W. Scherer
12
*/
13
14
#ifndef __NORM2ALLMODES_H__
15
#define __NORM2ALLMODES_H__
16
17
#include "unicode/utypes.h"
18
19
#if !UCONFIG_NO_NORMALIZATION
20
21
#include "unicode/edits.h"
22
#include "unicode/normalizer2.h"
23
#include "unicode/stringoptions.h"
24
#include "unicode/unistr.h"
25
#include "cpputils.h"
26
#include "normalizer2impl.h"
27
28
U_NAMESPACE_BEGIN
29
30
// Intermediate class:
31
// Has Normalizer2Impl and does boilerplate argument checking and setup.
32
class Normalizer2WithImpl : public Normalizer2 {
33
public:
34
12
    Normalizer2WithImpl(const Normalizer2Impl &ni) : impl(ni) {}
35
    virtual ~Normalizer2WithImpl();
36
37
    // normalize
38
    virtual UnicodeString &
39
    normalize(const UnicodeString &src,
40
              UnicodeString &dest,
41
30.4k
              UErrorCode &errorCode) const {
42
30.4k
        if(U_FAILURE(errorCode)) {
43
0
            dest.setToBogus();
44
0
            return dest;
45
0
        }
46
30.4k
        const UChar *sArray=src.getBuffer();
47
30.4k
        if(&dest==&src || sArray==NULL) {
48
0
            errorCode=U_ILLEGAL_ARGUMENT_ERROR;
49
0
            dest.setToBogus();
50
0
            return dest;
51
0
        }
52
30.4k
        dest.remove();
53
30.4k
        ReorderingBuffer buffer(impl, dest);
54
30.4k
        if(buffer.init(src.length(), errorCode)) {
55
30.4k
            normalize(sArray, sArray+src.length(), buffer, errorCode);
56
30.4k
        }
57
30.4k
        return dest;
58
30.4k
    }
59
    virtual void
60
    normalize(const UChar *src, const UChar *limit,
61
              ReorderingBuffer &buffer, UErrorCode &errorCode) const = 0;
62
63
    // normalize and append
64
    virtual UnicodeString &
65
    normalizeSecondAndAppend(UnicodeString &first,
66
                             const UnicodeString &second,
67
53.8k
                             UErrorCode &errorCode) const {
68
53.8k
        return normalizeSecondAndAppend(first, second, TRUE, errorCode);
69
53.8k
    }
70
    virtual UnicodeString &
71
    append(UnicodeString &first,
72
           const UnicodeString &second,
73
0
           UErrorCode &errorCode) const {
74
0
        return normalizeSecondAndAppend(first, second, FALSE, errorCode);
75
0
    }
76
    UnicodeString &
77
    normalizeSecondAndAppend(UnicodeString &first,
78
                             const UnicodeString &second,
79
                             UBool doNormalize,
80
53.8k
                             UErrorCode &errorCode) const {
81
53.8k
        uprv_checkCanGetBuffer(first, errorCode);
82
53.8k
        if(U_FAILURE(errorCode)) {
83
0
            return first;
84
0
        }
85
53.8k
        const UChar *secondArray=second.getBuffer();
86
53.8k
        if(&first==&second || secondArray==NULL) {
87
0
            errorCode=U_ILLEGAL_ARGUMENT_ERROR;
88
0
            return first;
89
0
        }
90
53.8k
        int32_t firstLength=first.length();
91
53.8k
        UnicodeString safeMiddle;
92
53.8k
        {
93
53.8k
            ReorderingBuffer buffer(impl, first);
94
53.8k
            if(buffer.init(firstLength+second.length(), errorCode)) {
95
53.8k
                normalizeAndAppend(secondArray, secondArray+second.length(), doNormalize,
96
53.8k
                                   safeMiddle, buffer, errorCode);
97
53.8k
            }
98
53.8k
        }  // The ReorderingBuffer destructor finalizes the first string.
99
53.8k
        if(U_FAILURE(errorCode)) {
100
0
            // Restore the modified suffix of the first string.
101
0
            first.replace(firstLength-safeMiddle.length(), 0x7fffffff, safeMiddle);
102
0
        }
103
53.8k
        return first;
104
53.8k
    }
105
    virtual void
106
    normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize,
107
                       UnicodeString &safeMiddle,
108
                       ReorderingBuffer &buffer, UErrorCode &errorCode) const = 0;
109
    virtual UBool
110
0
    getDecomposition(UChar32 c, UnicodeString &decomposition) const {
111
0
        UChar buffer[4];
112
0
        int32_t length;
113
0
        const UChar *d=impl.getDecomposition(c, buffer, length);
114
0
        if(d==NULL) {
115
0
            return FALSE;
116
0
        }
117
0
        if(d==buffer) {
118
0
            decomposition.setTo(buffer, length);  // copy the string (Jamos from Hangul syllable c)
119
0
        } else {
120
0
            decomposition.setTo(FALSE, d, length);  // read-only alias
121
0
        }
122
0
        return TRUE;
123
0
    }
124
    virtual UBool
125
0
    getRawDecomposition(UChar32 c, UnicodeString &decomposition) const {
126
0
        UChar buffer[30];
127
0
        int32_t length;
128
0
        const UChar *d=impl.getRawDecomposition(c, buffer, length);
129
0
        if(d==NULL) {
130
0
            return FALSE;
131
0
        }
132
0
        if(d==buffer) {
133
0
            decomposition.setTo(buffer, length);  // copy the string (algorithmic decomposition)
134
0
        } else {
135
0
            decomposition.setTo(FALSE, d, length);  // read-only alias
136
0
        }
137
0
        return TRUE;
138
0
    }
139
    virtual UChar32
140
0
    composePair(UChar32 a, UChar32 b) const {
141
0
        return impl.composePair(a, b);
142
0
    }
143
144
    virtual uint8_t
145
0
    getCombiningClass(UChar32 c) const {
146
0
        return impl.getCC(impl.getNorm16(c));
147
0
    }
148
149
    // quick checks
150
    virtual UBool
151
0
    isNormalized(const UnicodeString &s, UErrorCode &errorCode) const {
152
0
        if(U_FAILURE(errorCode)) {
153
0
            return FALSE;
154
0
        }
155
0
        const UChar *sArray=s.getBuffer();
156
0
        if(sArray==NULL) {
157
0
            errorCode=U_ILLEGAL_ARGUMENT_ERROR;
158
0
            return FALSE;
159
0
        }
160
0
        const UChar *sLimit=sArray+s.length();
161
0
        return sLimit==spanQuickCheckYes(sArray, sLimit, errorCode);
162
0
    }
163
    virtual UNormalizationCheckResult
164
0
    quickCheck(const UnicodeString &s, UErrorCode &errorCode) const {
165
0
        return Normalizer2WithImpl::isNormalized(s, errorCode) ? UNORM_YES : UNORM_NO;
166
0
    }
167
    virtual int32_t
168
0
    spanQuickCheckYes(const UnicodeString &s, UErrorCode &errorCode) const {
169
0
        if(U_FAILURE(errorCode)) {
170
0
            return 0;
171
0
        }
172
0
        const UChar *sArray=s.getBuffer();
173
0
        if(sArray==NULL) {
174
0
            errorCode=U_ILLEGAL_ARGUMENT_ERROR;
175
0
            return 0;
176
0
        }
177
0
        return (int32_t)(spanQuickCheckYes(sArray, sArray+s.length(), errorCode)-sArray);
178
0
    }
179
    virtual const UChar *
180
    spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCode) const = 0;
181
182
0
    virtual UNormalizationCheckResult getQuickCheck(UChar32) const {
183
0
        return UNORM_YES;
184
0
    }
185
186
    const Normalizer2Impl &impl;
187
};
188
189
class DecomposeNormalizer2 : public Normalizer2WithImpl {
190
public:
191
3
    DecomposeNormalizer2(const Normalizer2Impl &ni) : Normalizer2WithImpl(ni) {}
192
    virtual ~DecomposeNormalizer2();
193
194
private:
195
    virtual void
196
    normalize(const UChar *src, const UChar *limit,
197
0
              ReorderingBuffer &buffer, UErrorCode &errorCode) const {
198
0
        impl.decompose(src, limit, &buffer, errorCode);
199
0
    }
200
    using Normalizer2WithImpl::normalize;  // Avoid warning about hiding base class function.
201
    virtual void
202
    normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize,
203
                       UnicodeString &safeMiddle,
204
0
                       ReorderingBuffer &buffer, UErrorCode &errorCode) const {
205
0
        impl.decomposeAndAppend(src, limit, doNormalize, safeMiddle, buffer, errorCode);
206
0
    }
207
    virtual const UChar *
208
0
    spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCode) const {
209
0
        return impl.decompose(src, limit, NULL, errorCode);
210
0
    }
211
    using Normalizer2WithImpl::spanQuickCheckYes;  // Avoid warning about hiding base class function.
212
0
    virtual UNormalizationCheckResult getQuickCheck(UChar32 c) const {
213
0
        return impl.isDecompYes(impl.getNorm16(c)) ? UNORM_YES : UNORM_NO;
214
0
    }
215
0
    virtual UBool hasBoundaryBefore(UChar32 c) const { return impl.hasDecompBoundaryBefore(c); }
216
0
    virtual UBool hasBoundaryAfter(UChar32 c) const { return impl.hasDecompBoundaryAfter(c); }
217
0
    virtual UBool isInert(UChar32 c) const { return impl.isDecompInert(c); }
218
};
219
220
class ComposeNormalizer2 : public Normalizer2WithImpl {
221
public:
222
    ComposeNormalizer2(const Normalizer2Impl &ni, UBool fcc) :
223
6
        Normalizer2WithImpl(ni), onlyContiguous(fcc) {}
224
    virtual ~ComposeNormalizer2();
225
226
private:
227
    virtual void
228
    normalize(const UChar *src, const UChar *limit,
229
30.4k
              ReorderingBuffer &buffer, UErrorCode &errorCode) const U_OVERRIDE {
230
30.4k
        impl.compose(src, limit, onlyContiguous, TRUE, buffer, errorCode);
231
30.4k
    }
232
    using Normalizer2WithImpl::normalize;  // Avoid warning about hiding base class function.
233
234
    void
235
    normalizeUTF8(uint32_t options, StringPiece src, ByteSink &sink,
236
0
                  Edits *edits, UErrorCode &errorCode) const U_OVERRIDE {
237
0
        if (U_FAILURE(errorCode)) {
238
0
            return;
239
0
        }
240
0
        if (edits != nullptr && (options & U_EDITS_NO_RESET) == 0) {
241
0
            edits->reset();
242
0
        }
243
0
        const uint8_t *s = reinterpret_cast<const uint8_t *>(src.data());
244
0
        impl.composeUTF8(options, onlyContiguous, s, s + src.length(),
245
0
                         &sink, edits, errorCode);
246
0
        sink.Flush();
247
0
    }
248
249
    virtual void
250
    normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize,
251
                       UnicodeString &safeMiddle,
252
53.8k
                       ReorderingBuffer &buffer, UErrorCode &errorCode) const U_OVERRIDE {
253
53.8k
        impl.composeAndAppend(src, limit, doNormalize, onlyContiguous, safeMiddle, buffer, errorCode);
254
53.8k
    }
255
256
    virtual UBool
257
7.12k
    isNormalized(const UnicodeString &s, UErrorCode &errorCode) const U_OVERRIDE {
258
7.12k
        if(U_FAILURE(errorCode)) {
259
0
            return FALSE;
260
0
        }
261
7.12k
        const UChar *sArray=s.getBuffer();
262
7.12k
        if(sArray==NULL) {
263
0
            errorCode=U_ILLEGAL_ARGUMENT_ERROR;
264
0
            return FALSE;
265
0
        }
266
7.12k
        UnicodeString temp;
267
7.12k
        ReorderingBuffer buffer(impl, temp);
268
7.12k
        if(!buffer.init(5, errorCode)) {  // small destCapacity for substring normalization
269
0
            return FALSE;
270
0
        }
271
7.12k
        return impl.compose(sArray, sArray+s.length(), onlyContiguous, FALSE, buffer, errorCode);
272
7.12k
    }
273
    virtual UBool
274
0
    isNormalizedUTF8(StringPiece sp, UErrorCode &errorCode) const U_OVERRIDE {
275
0
        if(U_FAILURE(errorCode)) {
276
0
            return FALSE;
277
0
        }
278
0
        const uint8_t *s = reinterpret_cast<const uint8_t *>(sp.data());
279
0
        return impl.composeUTF8(0, onlyContiguous, s, s + sp.length(), nullptr, nullptr, errorCode);
280
0
    }
281
    virtual UNormalizationCheckResult
282
0
    quickCheck(const UnicodeString &s, UErrorCode &errorCode) const U_OVERRIDE {
283
0
        if(U_FAILURE(errorCode)) {
284
0
            return UNORM_MAYBE;
285
0
        }
286
0
        const UChar *sArray=s.getBuffer();
287
0
        if(sArray==NULL) {
288
0
            errorCode=U_ILLEGAL_ARGUMENT_ERROR;
289
0
            return UNORM_MAYBE;
290
0
        }
291
0
        UNormalizationCheckResult qcResult=UNORM_YES;
292
0
        impl.composeQuickCheck(sArray, sArray+s.length(), onlyContiguous, &qcResult);
293
0
        return qcResult;
294
0
    }
295
    virtual const UChar *
296
0
    spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &) const U_OVERRIDE {
297
0
        return impl.composeQuickCheck(src, limit, onlyContiguous, NULL);
298
0
    }
299
    using Normalizer2WithImpl::spanQuickCheckYes;  // Avoid warning about hiding base class function.
300
0
    virtual UNormalizationCheckResult getQuickCheck(UChar32 c) const U_OVERRIDE {
301
0
        return impl.getCompQuickCheck(impl.getNorm16(c));
302
0
    }
303
0
    virtual UBool hasBoundaryBefore(UChar32 c) const U_OVERRIDE {
304
0
        return impl.hasCompBoundaryBefore(c);
305
0
    }
306
0
    virtual UBool hasBoundaryAfter(UChar32 c) const U_OVERRIDE {
307
0
        return impl.hasCompBoundaryAfter(c, onlyContiguous);
308
0
    }
309
0
    virtual UBool isInert(UChar32 c) const U_OVERRIDE {
310
0
        return impl.isCompInert(c, onlyContiguous);
311
0
    }
312
313
    const UBool onlyContiguous;
314
};
315
316
class FCDNormalizer2 : public Normalizer2WithImpl {
317
public:
318
3
    FCDNormalizer2(const Normalizer2Impl &ni) : Normalizer2WithImpl(ni) {}
319
    virtual ~FCDNormalizer2();
320
321
private:
322
    virtual void
323
    normalize(const UChar *src, const UChar *limit,
324
0
              ReorderingBuffer &buffer, UErrorCode &errorCode) const {
325
0
        impl.makeFCD(src, limit, &buffer, errorCode);
326
0
    }
327
    using Normalizer2WithImpl::normalize;  // Avoid warning about hiding base class function.
328
    virtual void
329
    normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize,
330
                       UnicodeString &safeMiddle,
331
0
                       ReorderingBuffer &buffer, UErrorCode &errorCode) const {
332
0
        impl.makeFCDAndAppend(src, limit, doNormalize, safeMiddle, buffer, errorCode);
333
0
    }
334
    virtual const UChar *
335
0
    spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCode) const {
336
0
        return impl.makeFCD(src, limit, NULL, errorCode);
337
0
    }
338
    using Normalizer2WithImpl::spanQuickCheckYes;  // Avoid warning about hiding base class function.
339
0
    virtual UBool hasBoundaryBefore(UChar32 c) const { return impl.hasFCDBoundaryBefore(c); }
340
0
    virtual UBool hasBoundaryAfter(UChar32 c) const { return impl.hasFCDBoundaryAfter(c); }
341
0
    virtual UBool isInert(UChar32 c) const { return impl.isFCDInert(c); }
342
};
343
344
struct Norm2AllModes : public UMemory {
345
    Norm2AllModes(Normalizer2Impl *i)
346
3
            : impl(i), comp(*i, FALSE), decomp(*i), fcd(*i), fcc(*i, TRUE) {}
347
    ~Norm2AllModes();
348
349
    static Norm2AllModes *createInstance(Normalizer2Impl *impl, UErrorCode &errorCode);
350
    static Norm2AllModes *createNFCInstance(UErrorCode &errorCode);
351
    static Norm2AllModes *createInstance(const char *packageName,
352
                                         const char *name,
353
                                         UErrorCode &errorCode);
354
355
    static const Norm2AllModes *getNFCInstance(UErrorCode &errorCode);
356
    static const Norm2AllModes *getNFKCInstance(UErrorCode &errorCode);
357
    static const Norm2AllModes *getNFKC_CFInstance(UErrorCode &errorCode);
358
359
    Normalizer2Impl *impl;
360
    ComposeNormalizer2 comp;
361
    DecomposeNormalizer2 decomp;
362
    FCDNormalizer2 fcd;
363
    ComposeNormalizer2 fcc;
364
};
365
366
U_NAMESPACE_END
367
368
#endif  // !UCONFIG_NO_NORMALIZATION
369
#endif  // __NORM2ALLMODES_H__