1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
4 /* ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is Mozilla Communicator client code.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1998
22 * the Initial Developer. All Rights Reserved.
25 * Jungshik Shin <jshin@mailaps.org>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
42 #include "nsUCSupport.h"
43 #include "nsUnicodeToUTF32.h"
46 #define UCS4_TO_LE_STRING(u, s) \
48 s[3] = PRUint8(((u) >> 24) & 0xffL); \
49 s[2] = PRUint8(((u) >> 16) & 0xffL); \
50 s[1] = PRUint8(((u) >> 8) & 0xffL); \
51 s[0] = PRUint8((u) & 0xffL); \
54 #define UCS4_TO_LE_STRING(u, s) \
56 *((PRUint32*)(s)) = (u); \
61 #define UCS4_TO_BE_STRING(u, s) \
63 *((PRUint32*)(s)) = (u); \
66 #define UCS4_TO_BE_STRING(u, s) \
68 s[0] = PRUint8(((u) >> 24) & 0xffL); \
69 s[1] = PRUint8(((u) >> 16) & 0xffL); \
70 s[2] = PRUint8(((u) >> 8) & 0xffL); \
71 s[3] = PRUint8((u) & 0xffL); \
75 //----------------------------------------------------------------------
76 // Static functions common to nsUnicodeToUTF32LE and nsUnicodeToUTF32BE
78 static nsresult
ConvertCommon(const PRUnichar
* aSrc
,
81 PRInt32
* aDestLength
,
82 PRUnichar
* aHighSurrogate
,
85 const PRUnichar
* src
= aSrc
;
86 const PRUnichar
* srcEnd
= aSrc
+ *aSrcLength
;
88 const char * destEnd
= aDest
+ *aDestLength
;
92 // left-over high surroage code point from the prev. run.
98 return NS_OK_UENC_MOREINPUT
;
100 if (*aDestLength
< 4)
104 return NS_OK_UENC_MOREOUTPUT
;
106 if ((*src
& 0xfc00) != 0xdc00) // Not a low surrogate codepoint. Unpaird.
107 ucs4
= PRUint32(*aHighSurrogate
);
109 ucs4
= (((*aHighSurrogate
& 0x3ffL
) << 10) | (*src
& 0x3ffL
)) + 0x10000;
113 UCS4_TO_LE_STRING(ucs4
, dest
);
115 UCS4_TO_BE_STRING(ucs4
, dest
);
120 while (src
< srcEnd
) {
121 // regular codepoint or an unpaired low surrogate
122 if ((src
[0] & 0xfc00) != 0xd800)
124 if (destEnd
- dest
< 4)
125 goto error_more_output
;
126 ucs4
= PRUint32(src
[0]);
128 else // high surrogate
130 if ((src
+1) >= srcEnd
) {
131 //we need another surrogate to complete this unicode char
132 *aHighSurrogate
= src
[0];
133 *aDestLength
= dest
- aDest
;
134 return NS_OK_UENC_MOREINPUT
;
137 if (destEnd
- dest
< 4)
138 goto error_more_output
;
139 if ((src
[1] & 0xfc00) != 0xdc00) // unpaired
140 ucs4
= PRUint32(src
[0]);
142 { // convert surrogate pair to UCS4
143 ucs4
= (((src
[0] & 0x3ffL
) << 10) | (src
[1] & 0x3ffL
)) + 0x10000;
149 UCS4_TO_LE_STRING(ucs4
, dest
);
151 UCS4_TO_BE_STRING(ucs4
, dest
);
156 *aDestLength
= dest
- aDest
;
160 *aSrcLength
= src
- aSrc
;
161 *aDestLength
= dest
- aDest
;
162 return NS_OK_UENC_MOREOUTPUT
;
166 static nsresult
FinishCommon(char * aDest
,
167 PRInt32
* aDestLength
,
168 PRUnichar
* aHighSurrogate
,
173 if (*aHighSurrogate
) {
174 if (*aDestLength
< 4) {
176 return NS_OK_UENC_MOREOUTPUT
;
178 PRUint32 high
= PRUint32(*aHighSurrogate
);
180 UCS4_TO_LE_STRING(high
, dest
);
182 UCS4_TO_BE_STRING(high
, dest
);
194 //----------------------------------------------------------------------
195 // Class nsUnicodeToUTF32 [implementation]
197 NS_IMPL_ISUPPORTS1(nsUnicodeToUTF32
, nsIUnicodeEncoder
)
200 //----------------------------------------------------------------------
201 // Subclassing of nsIUnicodeEncoder class [implementation]
203 NS_IMETHODIMP
nsUnicodeToUTF32::GetMaxLength(const PRUnichar
* aSrc
,
205 PRInt32
* aDestLength
)
207 *aDestLength
= aSrcLength
* 4;
211 NS_IMETHODIMP
nsUnicodeToUTF32::FillInfo(PRUint32
*aInfo
)
213 memset(aInfo
, 0xFF, (0x10000L
>> 3));
218 //----------------------------------------------------------------------
219 // Class nsUnicodeToUTF32BE [implementation]
221 //----------------------------------------------------------------------
222 // Subclassing of nsUnicodeToUTF32 class [implementation]
225 NS_IMETHODIMP
nsUnicodeToUTF32BE::Convert(const PRUnichar
* aSrc
,
226 PRInt32
* aSrcLength
,
228 PRInt32
* aDestLength
)
230 return ConvertCommon(aSrc
, aSrcLength
, aDest
, aDestLength
,
231 &mHighSurrogate
, PR_FALSE
);
234 NS_IMETHODIMP
nsUnicodeToUTF32BE::Finish(char * aDest
,
235 PRInt32
* aDestLength
)
237 return FinishCommon(aDest
, aDestLength
, &mHighSurrogate
, PR_FALSE
);
241 //----------------------------------------------------------------------
242 // Class nsUnicodeToUTF32LE [implementation]
244 //----------------------------------------------------------------------
245 // Subclassing of nsUnicodeToUTF32 class [implementation]
248 NS_IMETHODIMP
nsUnicodeToUTF32LE::Convert(const PRUnichar
* aSrc
,
249 PRInt32
* aSrcLength
,
251 PRInt32
* aDestLength
)
253 return ConvertCommon(aSrc
, aSrcLength
, aDest
, aDestLength
,
254 &mHighSurrogate
, PR_TRUE
);
257 NS_IMETHODIMP
nsUnicodeToUTF32LE::Finish(char * aDest
,
258 PRInt32
* aDestLength
)
260 return FinishCommon(aDest
, aDestLength
, &mHighSurrogate
, PR_TRUE
);