|
1 /* |
|
2 * Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * UTF8STR.CPP |
|
16 * This file contains the implementation of the UTF8 String ASN1 class. |
|
17 * The IA5 string can contain the following characters: |
|
18 * \<character set unknown pending arrival of ITU spec\> |
|
19 * |
|
20 */ |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 /** |
|
26 @file |
|
27 */ |
|
28 |
|
29 #include <asn1dec.h> |
|
30 |
|
31 TInt ConvertToUnicodeFromUtf8(TDes16& aUnicode, const TDesC8& aUtf8); |
|
32 |
|
33 EXPORT_C TASN1DecUTF8String::TASN1DecUTF8String(void) |
|
34 { |
|
35 } |
|
36 |
|
37 EXPORT_C HBufC* TASN1DecUTF8String::DecodeDERL(const TASN1DecGeneric& aSource) |
|
38 { |
|
39 return DecodeContentsL(aSource.GetContentDER()); |
|
40 } |
|
41 |
|
42 EXPORT_C HBufC* TASN1DecUTF8String::DecodeDERL(const TDesC8& aSource,TInt& aPos) |
|
43 |
|
44 { |
|
45 TPtrC8 Source=aSource.Mid(aPos); |
|
46 TASN1DecGeneric gen(Source); |
|
47 gen.InitL(); |
|
48 HBufC* res = DecodeContentsL(gen.GetContentDER()); |
|
49 aPos+=gen.LengthDER(); |
|
50 return res; |
|
51 } |
|
52 |
|
53 HBufC* TASN1DecUTF8String::DecodeContentsL(const TDesC8& aSource) |
|
54 { |
|
55 HBufC* res = HBufC::NewLC(aSource.Length()); |
|
56 TPtr pRes = res->Des(); |
|
57 User::LeaveIfError(ConvertToUnicodeFromUtf8(pRes, aSource)); |
|
58 CleanupStack::Pop(res); |
|
59 return res; |
|
60 } |
|
61 |
|
62 /** |
|
63 * Converts text encoded using the Unicode transformation format UTF-8 |
|
64 * into the Unicode UCS-2 character set. |
|
65 * |
|
66 * @param aUnicode On return, contains the Unicode encoded output string. |
|
67 * @param aUtf8 The UTF-8 encoded input string |
|
68 * @return The number of unconverted bytes left at the end of the |
|
69 * input descriptor, or one of the error values defined |
|
70 * in <code>TError</code>. |
|
71 */ |
|
72 TInt ConvertToUnicodeFromUtf8(TDes16& aUnicode, const TDesC8& aUtf8) |
|
73 { |
|
74 if (aUtf8.Length()==0) |
|
75 { |
|
76 aUnicode.SetLength(0); |
|
77 return 0; |
|
78 } |
|
79 if (aUnicode.MaxLength()==0) |
|
80 { |
|
81 return aUtf8.Length(); |
|
82 } |
|
83 TUint16* pointerToCurrentUnicodeCharacter=CONST_CAST(TUint16*, aUnicode.Ptr()); |
|
84 const TUint16* pointerToLastUnicodeCharacter=pointerToCurrentUnicodeCharacter+(aUnicode.MaxLength()-1); |
|
85 const TUint8* pointerToCurrentUtf8Byte=aUtf8.Ptr(); |
|
86 const TUint8* pointerToLastUtf8Byte=pointerToCurrentUtf8Byte+(aUtf8.Length()-1); |
|
87 TBool inputIsTruncated=EFalse; |
|
88 TUint16 replacementcharacter = 0xFFFD; |
|
89 FOREVER |
|
90 { |
|
91 //__ASSERT_DEBUG(pointerToCurrentUnicodeCharacter<=pointerToLastUnicodeCharacter, Panic(EPanicBadUnicodePointers8)); |
|
92 //__ASSERT_DEBUG(pointerToCurrentUtf8Byte<=pointerToLastUtf8Byte, Panic(EPanicBadUtf8Pointers3)); |
|
93 TUint currentUtf8Byte=*pointerToCurrentUtf8Byte; |
|
94 if ((currentUtf8Byte&0x80)==0x00) |
|
95 { |
|
96 *pointerToCurrentUnicodeCharacter=STATIC_CAST(TUint16, currentUtf8Byte); |
|
97 } |
|
98 else if ((currentUtf8Byte&0xe0)==0xc0) |
|
99 { |
|
100 //__ASSERT_DEBUG(pointerToCurrentUtf8Byte<=pointerToLastUtf8Byte, Panic(EPanicBadUtf8Pointers4)); |
|
101 if (pointerToCurrentUtf8Byte>=pointerToLastUtf8Byte) |
|
102 { |
|
103 --pointerToCurrentUnicodeCharacter; |
|
104 --pointerToCurrentUtf8Byte; |
|
105 inputIsTruncated=ETrue; |
|
106 break; |
|
107 } |
|
108 TUint currentUnicodeCharacter=((currentUtf8Byte&0x1f)<<6); |
|
109 ++pointerToCurrentUtf8Byte; |
|
110 currentUtf8Byte=*pointerToCurrentUtf8Byte; |
|
111 if ((currentUtf8Byte&0xc0)==0x80) |
|
112 { |
|
113 currentUnicodeCharacter|=(currentUtf8Byte&0x3f); |
|
114 *pointerToCurrentUnicodeCharacter=STATIC_CAST(TUint16, currentUnicodeCharacter); |
|
115 } |
|
116 else |
|
117 { |
|
118 *pointerToCurrentUnicodeCharacter=replacementcharacter; |
|
119 } |
|
120 } |
|
121 else if ((currentUtf8Byte&0xf0)==0xe0) |
|
122 { |
|
123 //__ASSERT_DEBUG(pointerToCurrentUtf8Byte<=pointerToLastUtf8Byte, Panic(EPanicBadUtf8Pointers5)); |
|
124 if (pointerToLastUtf8Byte-pointerToCurrentUtf8Byte<2) |
|
125 { |
|
126 --pointerToCurrentUnicodeCharacter; |
|
127 --pointerToCurrentUtf8Byte; |
|
128 inputIsTruncated=ETrue; |
|
129 break; |
|
130 } |
|
131 TUint currentUnicodeCharacter=((currentUtf8Byte&0x0f)<<12); |
|
132 ++pointerToCurrentUtf8Byte; |
|
133 currentUtf8Byte=*pointerToCurrentUtf8Byte; |
|
134 if ((currentUtf8Byte&0xc0)==0x80) |
|
135 { |
|
136 currentUnicodeCharacter|=((currentUtf8Byte&0x3f)<<6); |
|
137 ++pointerToCurrentUtf8Byte; |
|
138 currentUtf8Byte=*pointerToCurrentUtf8Byte; |
|
139 if ((currentUtf8Byte&0xc0)==0x80) |
|
140 { |
|
141 currentUnicodeCharacter|=(currentUtf8Byte&0x3f); |
|
142 *pointerToCurrentUnicodeCharacter=STATIC_CAST(TUint16, currentUnicodeCharacter); |
|
143 } |
|
144 else |
|
145 { |
|
146 *pointerToCurrentUnicodeCharacter=STATIC_CAST(TUint16, currentUnicodeCharacter); |
|
147 } |
|
148 } |
|
149 else |
|
150 { |
|
151 *pointerToCurrentUnicodeCharacter=replacementcharacter; |
|
152 } |
|
153 |
|
154 } |
|
155 else if ((currentUtf8Byte&0xf8)==0xf0) |
|
156 { |
|
157 //__ASSERT_DEBUG(pointerToCurrentUnicodeCharacter<=pointerToLastUnicodeCharacter, Panic(EPanicBadUnicodePointers9)); |
|
158 if (pointerToCurrentUnicodeCharacter>=pointerToLastUnicodeCharacter) |
|
159 { |
|
160 --pointerToCurrentUnicodeCharacter; |
|
161 --pointerToCurrentUtf8Byte; |
|
162 break; |
|
163 } |
|
164 //__ASSERT_DEBUG(pointerToCurrentUtf8Byte<=pointerToLastUtf8Byte, Panic(EPanicBadUtf8Pointers6)); |
|
165 if (pointerToLastUtf8Byte-pointerToCurrentUtf8Byte<3) |
|
166 { |
|
167 --pointerToCurrentUnicodeCharacter; |
|
168 --pointerToCurrentUtf8Byte; |
|
169 inputIsTruncated=ETrue; |
|
170 break; |
|
171 } |
|
172 TUint currentUnicodeCharacter=((currentUtf8Byte&0x07)<<8); |
|
173 ++pointerToCurrentUtf8Byte; |
|
174 currentUtf8Byte=*pointerToCurrentUtf8Byte; |
|
175 if ((currentUtf8Byte&0xc0)==0x80) |
|
176 { |
|
177 currentUnicodeCharacter|=((currentUtf8Byte&0x3f)<<2); |
|
178 if (currentUnicodeCharacter>=0x0040) |
|
179 { |
|
180 currentUnicodeCharacter-=0x0040; |
|
181 if (currentUnicodeCharacter<0x0400) |
|
182 { |
|
183 ++pointerToCurrentUtf8Byte; |
|
184 currentUtf8Byte=*pointerToCurrentUtf8Byte; |
|
185 if ((currentUtf8Byte&0xc0)==0x80) |
|
186 { |
|
187 currentUnicodeCharacter|=((currentUtf8Byte&0x30)>>4); |
|
188 *pointerToCurrentUnicodeCharacter=STATIC_CAST(TUint16, 0xd800|currentUnicodeCharacter); |
|
189 currentUnicodeCharacter=((currentUtf8Byte&0x0f)<<6); |
|
190 ++pointerToCurrentUtf8Byte; |
|
191 currentUtf8Byte=*pointerToCurrentUtf8Byte; |
|
192 if ((currentUtf8Byte&0xc0)==0x80) |
|
193 { |
|
194 currentUnicodeCharacter|=(currentUtf8Byte&0x3f); |
|
195 ++pointerToCurrentUnicodeCharacter; |
|
196 *pointerToCurrentUnicodeCharacter=STATIC_CAST(TUint16, 0xdc00|currentUnicodeCharacter); |
|
197 } |
|
198 } |
|
199 } |
|
200 } |
|
201 } |
|
202 } |
|
203 else |
|
204 { |
|
205 *pointerToCurrentUnicodeCharacter=replacementcharacter; |
|
206 } |
|
207 //__ASSERT_DEBUG(pointerToCurrentUtf8Byte<=pointerToLastUtf8Byte, Panic(EPanicBadUtf8Pointers7)); |
|
208 //__ASSERT_DEBUG(pointerToCurrentUnicodeCharacter<=pointerToLastUnicodeCharacter, Panic(EPanicBadUnicodePointers10)); |
|
209 if ((pointerToCurrentUtf8Byte>=pointerToLastUtf8Byte) || (pointerToCurrentUnicodeCharacter>=pointerToLastUnicodeCharacter)) |
|
210 { |
|
211 break; |
|
212 } |
|
213 ++pointerToCurrentUnicodeCharacter; |
|
214 ++pointerToCurrentUtf8Byte; |
|
215 } |
|
216 if ((pointerToCurrentUtf8Byte<aUtf8.Ptr()) && inputIsTruncated) |
|
217 { |
|
218 return KErrArgument; |
|
219 } |
|
220 aUnicode.SetLength((pointerToCurrentUnicodeCharacter-aUnicode.Ptr())+1); |
|
221 return pointerToLastUtf8Byte-pointerToCurrentUtf8Byte; |
|
222 } |