1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
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/. */
8 #include "nsUTF8Utils.h"
15 void AddBOMs(nsACString
& aDest
, const nsACString
& aSource
) {
16 uint32_t destlength
= 0;
18 // First compute how much room we will need.
19 for (uint32_t srci
= 0; srci
< aSource
.Length();) {
20 int bytes
= UTF8traits::bytes(aSource
[srci
]);
22 // Non-BMP character, will add a BOM after it.
25 // Skip whole character encoding.
30 uint32_t desti
= 0; // Index within aDest.
32 // Add BOMs after non-BMP characters.
33 aDest
.SetLength(destlength
);
34 for (uint32_t srci
= 0; srci
< aSource
.Length();) {
35 uint32_t bytes
= UTF8traits::bytes(aSource
[srci
]);
37 MOZ_ASSERT(bytes
<= aSource
.Length() - srci
,
38 "We should have the whole sequence");
40 // Copy whole sequence.
41 aDest
.Replace(desti
, bytes
, Substring(aSource
, srci
, bytes
));
46 // More than 4 bytes in UTF-8 encoding exactly means more than 16 encoded
47 // bits. This is thus a non-BMP character which needed a surrogate
48 // pair to get encoded in UTF-16, add a BOM after it.
50 // And add a BOM after it.
51 aDest
.Replace(desti
, 3, "\xEF\xBB\xBF");
55 MOZ_ASSERT(desti
== destlength
,
56 "Incoherency between computed length"
57 "and actually translated length");
60 void ATKStringConverterHelper::AdjustOffsets(gint
* aStartOffset
,
61 gint
* aEndOffset
, gint count
) {
62 MOZ_ASSERT(!mAdjusted
,
63 "DOMtoATK::ATKStringConverterHelper::AdjustOffsets needs to be "
66 if (*aStartOffset
> 0) {
71 if (*aEndOffset
>= 0 && *aEndOffset
< count
) {
81 gchar
* ATKStringConverterHelper::FinishUTF16toUTF8(nsCString
& aStr
) {
85 // AdjustOffsets added a leading character.
87 MOZ_ASSERT(aStr
.Length() > 0, "There should be a leading character");
89 static_cast<int>(aStr
.Length()) >= UTF8traits::bytes(aStr
.CharAt(0)),
90 "The leading character should be complete");
92 // drop first character
93 skip
= UTF8traits::bytes(aStr
.CharAt(0));
97 // AdjustOffsets added a trailing character.
99 MOZ_ASSERT(aStr
.Length() > 0, "There should be a trailing character");
102 // Find beginning of last character.
103 for (trail
= aStr
.Length() - 1; trail
>= 0; trail
--) {
104 if (!UTF8traits::isInSeq(aStr
.CharAt(trail
))) {
108 MOZ_ASSERT(trail
>= 0,
109 "There should be at least a whole trailing character");
110 MOZ_ASSERT(trail
+ UTF8traits::bytes(aStr
.CharAt(trail
)) ==
111 static_cast<int>(aStr
.Length()),
112 "The trailing character should be complete");
114 // Drop the last character.
115 aStr
.Truncate(trail
);
118 // copy and return, libspi will free it
119 return g_strdup(aStr
.get() + skip
);
122 gchar
* ATKStringConverterHelper::ConvertAdjusted(const nsAString
& aStr
) {
123 MOZ_ASSERT(mAdjusted
,
124 "DOMtoATK::ATKStringConverterHelper::AdjustOffsets needs to be "
125 "called before ATKStringConverterHelper::ConvertAdjusted");
127 NS_ConvertUTF16toUTF8
cautoStr(aStr
);
128 if (!cautoStr
.get()) {
132 nsAutoCString cautoStrBOMs
;
133 AddBOMs(cautoStrBOMs
, cautoStr
);
134 return FinishUTF16toUTF8(cautoStrBOMs
);
137 gchar
* Convert(const nsAString
& aStr
) {
138 NS_ConvertUTF16toUTF8
cautoStr(aStr
);
139 if (!cautoStr
.get()) {
143 nsAutoCString cautoStrBOMs
;
144 AddBOMs(cautoStrBOMs
, cautoStr
);
145 return g_strdup(cautoStrBOMs
.get());
148 } // namespace DOMtoATK
151 } // namespace mozilla