Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 :
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "nsUnicodeNormalizer.h"
8 : #include "ICUUtils.h"
9 : #include "unicode/unorm2.h"
10 : #include "unicode/utext.h"
11 :
12 0 : NS_IMPL_ISUPPORTS(nsUnicodeNormalizer, nsIUnicodeNormalizer)
13 :
14 0 : nsUnicodeNormalizer::nsUnicodeNormalizer()
15 : {
16 0 : }
17 :
18 0 : nsUnicodeNormalizer::~nsUnicodeNormalizer()
19 : {
20 0 : }
21 :
22 : static nsresult
23 0 : DoNormalization(const UNormalizer2* aNorm, const nsAString& aSrc,
24 : nsAString& aDest)
25 : {
26 0 : UErrorCode errorCode = U_ZERO_ERROR;
27 0 : const int32_t length = aSrc.Length();
28 0 : const UChar* src = reinterpret_cast<const UChar*>(aSrc.BeginReading());
29 : // Initial guess for a capacity that is likely to be enough for most cases.
30 0 : int32_t capacity = length + (length >> 8) + 8;
31 : while (true) {
32 0 : aDest.SetLength(capacity);
33 0 : UChar* dest = reinterpret_cast<UChar*>(aDest.BeginWriting());
34 0 : int32_t len = unorm2_normalize(aNorm, src, aSrc.Length(), dest, capacity,
35 0 : &errorCode);
36 0 : if (U_SUCCESS(errorCode)) {
37 0 : aDest.SetLength(len);
38 0 : break;
39 : }
40 0 : if (errorCode != U_BUFFER_OVERFLOW_ERROR) {
41 : // Some other error that we don't handle
42 0 : break;
43 : }
44 : // Buffer wasn't big enough; adjust to the reported size and try again.
45 0 : capacity = len;
46 0 : errorCode = U_ZERO_ERROR;
47 0 : }
48 0 : return ICUUtils::UErrorToNsResult(errorCode);
49 : }
50 :
51 : nsresult
52 0 : nsUnicodeNormalizer::NormalizeUnicodeNFD(const nsAString& aSrc,
53 : nsAString& aDest)
54 : {
55 : // The unorm2_getNF*Instance functions return static singletons that should
56 : // not be deleted, so we just get them once on first use.
57 : static UErrorCode errorCode = U_ZERO_ERROR;
58 0 : static const UNormalizer2* norm = unorm2_getNFDInstance(&errorCode);
59 0 : if (U_SUCCESS(errorCode)) {
60 0 : return DoNormalization(norm, aSrc, aDest);
61 : }
62 0 : return ICUUtils::UErrorToNsResult(errorCode);
63 : }
64 :
65 : nsresult
66 0 : nsUnicodeNormalizer::NormalizeUnicodeNFC(const nsAString& aSrc,
67 : nsAString& aDest)
68 : {
69 : static UErrorCode errorCode = U_ZERO_ERROR;
70 0 : static const UNormalizer2* norm = unorm2_getNFCInstance(&errorCode);
71 0 : if (U_SUCCESS(errorCode)) {
72 0 : return DoNormalization(norm, aSrc, aDest);
73 : }
74 0 : return ICUUtils::UErrorToNsResult(errorCode);
75 : }
76 :
77 : nsresult
78 0 : nsUnicodeNormalizer::NormalizeUnicodeNFKD(const nsAString& aSrc,
79 : nsAString& aDest)
80 : {
81 : static UErrorCode errorCode = U_ZERO_ERROR;
82 0 : static const UNormalizer2* norm = unorm2_getNFKDInstance(&errorCode);
83 0 : if (U_SUCCESS(errorCode)) {
84 0 : return DoNormalization(norm, aSrc, aDest);
85 : }
86 0 : return ICUUtils::UErrorToNsResult(errorCode);
87 : }
88 :
89 : nsresult
90 0 : nsUnicodeNormalizer::NormalizeUnicodeNFKC(const nsAString& aSrc,
91 : nsAString& aDest)
92 : {
93 : static UErrorCode errorCode = U_ZERO_ERROR;
94 0 : static const UNormalizer2* norm = unorm2_getNFKCInstance(&errorCode);
95 0 : if (U_SUCCESS(errorCode)) {
96 0 : return DoNormalization(norm, aSrc, aDest);
97 : }
98 0 : return ICUUtils::UErrorToNsResult(errorCode);
99 : }
|