3 //=============================================================================
5 * @file UTF16_UCS2_Translator.cpp
7 * Defines the arrays required to convert between UCS-2, a 2 byte wide char
8 * codeset, and UCS-16, aka unicode, a 2-byte codeset. As a bit-pattern
9 * these two should be identical, with the exception that UCS-2 cannot
10 * certain characters that UTF16 can, using escape codepoints.
12 * This translator can be dynamically loaded into TAO at run-time using
13 * a service configurator file with the following contents:
15 * dynamic UTF16_UCS2_Factory Service_Object * UTF16_UCS2:_make_UTF16_UCS2_Factory ()
17 * static Resource_Factory
18 * "-ORBWCharCodesetTranslator UTF16_UCS2_Factory"
20 * This code used UTF16_BOM_Translator as a starting point.
22 * @author Iliyan Jeliazkov <jeliazkov_i@ociweb.com> Byron Harris <harrisb@ociweb.com>
24 //=============================================================================
26 #include "UTF16_UCS2_Translator.h"
27 #include "tao/debug.h"
28 #include "ace/Log_Msg.h"
29 // ****************************************************************
31 typedef ACE_CDR::UShort ACE_UTF16_T
;
32 static const size_t ACE_UTF16_CODEPOINT_SIZE
= sizeof (ACE_UTF16_T
);
34 /////////////////////////////
35 // UTF16_UCS2_Translator implementation
37 UTF16_UCS2_Translator::UTF16_UCS2_Translator (CONV_FRAME::CodeSetId tcs
)
40 if (TAO_debug_level
> 1)
41 ACE_DEBUG((LM_DEBUG
, ACE_TEXT ("TAO (%P|%t) - UTF16_UCS2_Translator: tcs=0x%x\n"),
45 UTF16_UCS2_Translator::~UTF16_UCS2_Translator ()
49 // = Documented in $ACE_ROOT/ace/CDR_Stream.h
51 UTF16_UCS2_Translator::read_wchar (ACE_InputCDR
&cdr
, ACE_CDR::WChar
&x
)
53 if (static_cast <ACE_CDR::Short
> (this->major_version(cdr
)) == 1 &&
54 static_cast <ACE_CDR::Short
> (this->minor_version(cdr
)) == 2)
57 if (! this->read_1 (cdr
, &len
))
60 ACE_ASSERT (len
== 2); // no BOM present
63 if (!this->read_array (cdr
,
64 reinterpret_cast <char *> (&sx
),1,1,2))
67 #if defined (ACE_LITTLE_ENDIAN)
69 ACE_CDR::swap_2 (reinterpret_cast <const char*> (&sx
),
70 reinterpret_cast <char *> (&ux
));
71 x
= static_cast <ACE_CDR::WChar
> (ux
);
73 x
= static_cast <ACE_CDR::WChar
> (sx
);
74 #endif // ACE_LITTLE_ENDIAN
80 if (this->read_2 (cdr
, &sx
))
82 x
= static_cast <ACE_CDR::WChar
> (sx
);
90 UTF16_UCS2_Translator::read_wstring (ACE_InputCDR
&cdr
,
94 if (!this->read_4 (cdr
, &len
))
97 // A check for the length being too great is done later in the
98 // call to read_char_array but we want to have it done before
99 // the memory is allocated.
100 if (len
> 0 && len
<= cdr
.length())
102 if (static_cast <ACE_CDR::Short
> (this->major_version(cdr
)) == 1
103 && static_cast <ACE_CDR::Short
> (this->minor_version(cdr
)) == 2)
105 len
/= ACE_UTF16_CODEPOINT_SIZE
;
107 //allocating one extra for the null character needed by applications
109 ACE_CDR::WChar
[len
+ 1],
113 if (this->read_wchar_array_i (cdr
, x
, len
, 1))
115 // Since reading the array may have adjusted the length,
116 // we simply rewrite the null terminator
124 ACE_CDR::WChar
[len
],
126 if (this->read_wchar_array (cdr
, x
, len
))
133 // Convert any null strings to empty strings since empty
134 // strings can cause crashes. (See bug 58.)
146 UTF16_UCS2_Translator::read_wchar_array_i (ACE_InputCDR
& cdr
,
148 ACE_CDR::ULong
&length
,
153 static const size_t align
= ACE_CDR::SHORT_ALIGN
;
154 if (cdr
.adjust (ACE_UTF16_CODEPOINT_SIZE
* length
, align
, buf
) == 0)
156 ACE_UTF16_T
*sb
= reinterpret_cast <ACE_UTF16_T
*> (buf
);
157 #if defined (ACE_LITTLE_ENDIAN)
159 #endif // ACE_LITTLE_ENDIAN
161 for (size_t i
= 0; i
< length
; ++i
)
162 #if defined (ACE_DISABLE_SWAP_ON_READ)
163 x
[i
] = static_cast <ACE_CDR::WChar
> (sb
[i
]);
167 x
[i
] = static_cast <ACE_CDR::WChar
> (sb
[i
]);
172 ACE_CDR::swap_2 (&buf
[i
*2], reinterpret_cast <char *> (&sx
));
173 x
[i
] = static_cast <ACE_CDR::WChar
> (sx
);
175 #endif /* ACE_DISABLE_SWAP_ON_READ */
183 UTF16_UCS2_Translator::read_wchar_array (ACE_InputCDR
& cdr
,
185 ACE_CDR::ULong length
)
190 if (static_cast <ACE_CDR::Short
> (this->major_version(cdr
)) == 1
191 && static_cast <ACE_CDR::Short
> (this->minor_version(cdr
)) == 2)
193 for (size_t i
= 0; i
< length
; ++i
)
194 if (!this->read_wchar(cdr
,x
[i
]))
200 return this->read_wchar_array_i (cdr
, x
, length
);
204 UTF16_UCS2_Translator::write_wchar (ACE_OutputCDR
&cdr
,
207 return this->write_wchar_i (cdr
, x
);
211 UTF16_UCS2_Translator::write_wchar_i (ACE_OutputCDR
&cdr
, ACE_CDR::WChar x
)
213 if (static_cast <ACE_CDR::Short
> (this->major_version(cdr
)) == 1
214 && static_cast <ACE_CDR::Short
> (this->minor_version(cdr
)) == 2)
217 ACE_CDR::UShort buffer
[2];
219 buffer
[0] = static_cast <ACE_CDR::Short
> (x
);
221 unsigned char tcsize
= static_cast <unsigned char>
222 (len
* ACE_UTF16_CODEPOINT_SIZE
);
223 if (this->write_1 (cdr
, &tcsize
))
224 return this->write_array(cdr
, &buffer
, tcsize
, 1, 1);
228 else if (static_cast <ACE_CDR::Short
> (this->minor_version(cdr
)) != 0)
230 // GIOP 1.1 simple support
231 ACE_UTF16_T sx
= static_cast <ACE_UTF16_T
> (x
);
232 return this->write_2 (cdr
, &sx
);
235 { // wchar is not allowed with GIOP 1.0.
242 UTF16_UCS2_Translator::write_wstring (ACE_OutputCDR
& cdr
,
244 const ACE_CDR::WChar
*x
)
246 // we'll accept a null pointer but only for an empty string
247 ACE_ASSERT (x
!= 0 || len
== 0);
248 if (static_cast <ACE_CDR::Short
> (this->major_version(cdr
)) == 1
249 && static_cast <ACE_CDR::Short
> (this->minor_version(cdr
)) == 2)
251 if (len
== 0) // for zero length strings, only write a length of
253 return this->write_4(cdr
, &len
);
255 ACE_CDR::ULong l
= len
* ACE_UTF16_CODEPOINT_SIZE
;
256 if (this->write_4 (cdr
, &l
) && x
!= 0)
258 if (cdr
.do_byte_swap())
260 return this->write_swapped_wchar_array_i (cdr
, x
, len
);
264 return this->write_wchar_array_i (cdr
, x
, len
);
270 // pre GIOP 1.2: include null terminator in length
271 ACE_CDR::ULong l
= len
+ 1;
273 if (this->write_4 (cdr
, &l
))
277 return this->write_wchar_array_i (cdr
, x
, len
+ 1);
282 return this->write_2 (cdr
, &s
);
291 UTF16_UCS2_Translator::write_wchar_array (ACE_OutputCDR
& cdr
,
292 const ACE_CDR::WChar
*x
,
293 ACE_CDR::ULong length
)
295 if (static_cast <ACE_CDR::Short
> (this->major_version(cdr
)) == 1
296 && static_cast <ACE_CDR::Short
> (this->minor_version(cdr
)) == 2)
298 for (size_t i
= 0; i
< length
; ++i
)
299 if (this->write_wchar_i (cdr
, x
[i
]) == 0)
305 return this->write_wchar_array_i (cdr
, x
, length
);
309 UTF16_UCS2_Translator::write_wchar_array_i (ACE_OutputCDR
& cdr
,
310 const ACE_CDR::WChar
*x
,
311 ACE_CDR::ULong length
)
316 static const size_t align
= ACE_CDR::SHORT_ALIGN
;
317 if (cdr
.adjust (ACE_UTF16_CODEPOINT_SIZE
* length
, align
, buf
)
323 ACE_UTF16_T
*sb
= reinterpret_cast <ACE_UTF16_T
*> (buf
);
325 for (size_t i
= 0; i
< length
; ++i
)
327 sb
[i
] = static_cast <ACE_UTF16_T
> (x
[i
]);
333 UTF16_UCS2_Translator::write_swapped_wchar_array_i (ACE_OutputCDR
& cdr
,
334 const ACE_CDR::WChar
*x
,
335 ACE_CDR::ULong length
)
340 static const size_t align
= ACE_CDR::SHORT_ALIGN
;
341 if (cdr
.adjust (ACE_UTF16_CODEPOINT_SIZE
* length
, align
, buf
)
347 ACE_UTF16_T
*sb
= reinterpret_cast <ACE_UTF16_T
*> (buf
);
349 for (size_t i
= 0; i
< length
; ++i
)
351 ACE_CDR::swap_2 (reinterpret_cast <const char*> (&x
[i
]),
352 reinterpret_cast <char *> (&sb
[i
]));