2 *******************************************************************************
4 * Copyright (C) 2001-2004, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * file name: ustr_wcs.c
10 * tab size: 8 (not used)
13 * created on: 2004sep07
14 * created by: Markus W. Scherer
16 * u_strToWCS() and u_strFromWCS() functions
17 * moved here from ustrtrns.c for better modularization.
20 #include "unicode/utypes.h"
21 #include "unicode/ustring.h"
29 u_growAnyBufferFromStatic(void *context
,
30 void **pBuffer
, int32_t *pCapacity
, int32_t reqCapacity
,
31 int32_t length
, int32_t size
) {
33 void *newBuffer
=uprv_malloc(reqCapacity
*size
);
36 uprv_memcpy(newBuffer
, *pBuffer
, length
*size
);
38 *pCapacity
=reqCapacity
;
43 /* release the old pBuffer if it was not statically allocated */
44 if(*pBuffer
!=(void *)context
) {
49 return (UBool
)(newBuffer
!=NULL
);
52 #define _STACK_BUFFER_CAPACITY 1000
53 #define _BUFFER_CAPACITY_MULTIPLIER 2
55 #if !defined(U_WCHAR_IS_UTF16) && !defined(U_WCHAR_IS_UTF32)
58 _strToWCS(wchar_t *dest
,
63 UErrorCode
*pErrorCode
){
65 char stackBuffer
[_STACK_BUFFER_CAPACITY
];
66 char* tempBuf
= stackBuffer
;
67 int32_t tempBufCapacity
= _STACK_BUFFER_CAPACITY
;
68 char* tempBufLimit
= stackBuffer
+ tempBufCapacity
;
69 UConverter
* conv
= NULL
;
70 char* saveBuf
= tempBuf
;
71 wchar_t* intTarget
=NULL
;
72 int32_t intTargetCapacity
=0;
75 const UChar
*pSrcLimit
=NULL
;
76 const UChar
*pSrc
= src
;
78 conv
= u_getDefaultConverter(pErrorCode
);
80 if(U_FAILURE(*pErrorCode
)){
85 srcLength
= u_strlen(pSrc
);
88 pSrcLimit
= pSrc
+ srcLength
;
91 /* reset the error state */
92 *pErrorCode
= U_ZERO_ERROR
;
94 /* convert to chars using default converter */
95 ucnv_fromUnicode(conv
,&tempBuf
,tempBufLimit
,&pSrc
,pSrcLimit
,NULL
,(UBool
)(pSrc
==pSrcLimit
),pErrorCode
);
96 count
=(tempBuf
- saveBuf
);
98 /* This should rarely occur */
99 if(*pErrorCode
==U_BUFFER_OVERFLOW_ERROR
){
102 /* we dont have enough room on the stack grow the buffer */
103 if(!u_growAnyBufferFromStatic(stackBuffer
,(void**) &tempBuf
, &tempBufCapacity
,
104 (_BUFFER_CAPACITY_MULTIPLIER
* (srcLength
)), count
,sizeof(char))){
109 tempBufLimit
= tempBuf
+ tempBufCapacity
;
110 tempBuf
= tempBuf
+ count
;
117 if(U_FAILURE(*pErrorCode
)){
121 /* done with conversion null terminate the char buffer */
122 if(count
>=tempBufCapacity
){
124 /* we dont have enough room on the stack grow the buffer */
125 if(!u_growAnyBufferFromStatic(stackBuffer
,(void**) &tempBuf
, &tempBufCapacity
,
126 tempBufCapacity
-count
+1, count
,sizeof(char))){
135 /* allocate more space than required
136 * here we assume that every char requires
137 * no more than 2 wchar_ts
139 intTargetCapacity
= (count
* _BUFFER_CAPACITY_MULTIPLIER
+ 1) /*for null termination */;
140 intTarget
= (wchar_t*)uprv_malloc( intTargetCapacity
* sizeof(wchar_t) );
145 int32_t remaining
= intTargetCapacity
;
146 wchar_t* pIntTarget
=intTarget
;
149 /* now convert the mbs to wcs */
152 /* we can call the system API since we are sure that
153 * there is atleast 1 null in the input
155 retVal
= uprv_mbstowcs(pIntTarget
,(tempBuf
+nulLen
),remaining
);
158 *pErrorCode
= U_INVALID_CHAR_FOUND
;
160 }else if(retVal
== remaining
){/* should never occur */
161 int numWritten
= (pIntTarget
-intTarget
);
162 u_growAnyBufferFromStatic(NULL
,(void**) &intTarget
,
164 intTargetCapacity
* _BUFFER_CAPACITY_MULTIPLIER
,
167 pIntTarget
= intTarget
;
168 remaining
=intTargetCapacity
;
170 if(nulLen
!=count
){ /*there are embedded nulls*/
171 pIntTarget
+=numWritten
;
172 remaining
-=numWritten
;
178 /* we donot check for limit since tempBuf is null terminated */
179 while(tempBuf
[nulLen
++] != 0){
181 nulVal
= (nulLen
< srcLength
) ? 1 : 0;
182 pIntTarget
= pIntTarget
+ retVal
+nulVal
;
183 remaining
-=(retVal
+nulVal
);
185 /* check if we have reached the source limit*/
191 count
= (int32_t)(pIntTarget
-intTarget
);
193 if(0 < count
&& count
<= destCapacity
){
194 uprv_memcpy(dest
,intTarget
,count
*sizeof(wchar_t));
198 *pDestLength
= count
;
201 /* free the allocated memory */
202 uprv_free(intTarget
);
205 *pErrorCode
= U_MEMORY_ALLOCATION_ERROR
;
208 /* are we still using stack buffer */
209 if(stackBuffer
!= saveBuf
){
212 u_terminateWChars(dest
,destCapacity
,count
,pErrorCode
);
214 u_releaseDefaultConverter(conv
);
220 U_CAPI
wchar_t* U_EXPORT2
221 u_strToWCS(wchar_t *dest
,
222 int32_t destCapacity
,
223 int32_t *pDestLength
,
226 UErrorCode
*pErrorCode
){
229 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)){
233 if((src
==NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
234 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
238 #ifdef U_WCHAR_IS_UTF16
239 /* wchar_t is UTF-16 just do a memcpy */
241 srcLength
= u_strlen(src
);
243 if(0 < srcLength
&& srcLength
<= destCapacity
){
244 uprv_memcpy(dest
,src
,srcLength
*U_SIZEOF_UCHAR
);
247 *pDestLength
= srcLength
;
250 u_terminateUChars(dest
,destCapacity
,srcLength
,pErrorCode
);
254 #elif defined U_WCHAR_IS_UTF32
256 return (wchar_t*)u_strToUTF32((UChar32
*)dest
, destCapacity
, pDestLength
,
257 src
, srcLength
, pErrorCode
);
261 return _strToWCS(dest
,destCapacity
,pDestLength
,src
,srcLength
, pErrorCode
);
267 #if !defined(U_WCHAR_IS_UTF16) && !defined(U_WCHAR_IS_UTF32)
268 /* helper function */
270 _strFromWCS( UChar
*dest
,
271 int32_t destCapacity
,
272 int32_t *pDestLength
,
275 UErrorCode
*pErrorCode
){
277 int32_t retVal
=0, count
=0 ;
278 UConverter
* conv
= NULL
;
279 UChar
* pTarget
= NULL
;
280 UChar
* pTargetLimit
= NULL
;
281 UChar
* target
= NULL
;
283 UChar uStack
[_STACK_BUFFER_CAPACITY
];
285 wchar_t wStack
[_STACK_BUFFER_CAPACITY
];
286 wchar_t* pWStack
= wStack
;
289 char cStack
[_STACK_BUFFER_CAPACITY
];
290 int32_t cStackCap
= _STACK_BUFFER_CAPACITY
;
293 char* pCSrcLimit
=NULL
;
295 const wchar_t* pSrc
= src
;
296 const wchar_t* pSrcLimit
= NULL
;
299 /* if the wchar_t source is null terminated we can safely
300 * assume that there are no embedded nulls, this is a fast
301 * path for null terminated strings.
304 /* convert wchars to chars */
305 retVal
= uprv_wcstombs(pCSrc
,src
, cStackCap
);
308 *pErrorCode
= U_ILLEGAL_CHAR_FOUND
;
310 }else if(retVal
== cStackCap
){
311 /* Should rarely occur */
312 u_growAnyBufferFromStatic(cStack
,(void**)&pCSrc
,&cStackCap
,
313 cStackCap
* _BUFFER_CAPACITY_MULTIPLIER
, 0, sizeof(char));
316 /* converted every thing */
317 pCSrc
= pCSrc
+retVal
;
323 /* here the source is not null terminated
324 * so it may have nulls embeded and we need to
325 * do some extra processing
327 int32_t remaining
=cStackCap
;
329 pSrcLimit
= src
+ srcLength
;
332 register int32_t nulLen
= 0;
334 /* find nulls in the string */
335 while(nulLen
<srcLength
&& pSrc
[nulLen
++]!=0){
338 if((pSrc
+nulLen
) < pSrcLimit
){
339 /* check if we have enough room in pCSrc */
340 if(remaining
< (nulLen
* MB_CUR_MAX
)){
341 /* should rarely occur */
342 int32_t len
= (pCSrc
-pCSave
);
344 /* we do not have enough room so grow the buffer*/
345 u_growAnyBufferFromStatic(cStack
,(void**)&pCSrc
,&cStackCap
,
346 _BUFFER_CAPACITY_MULTIPLIER
*cStackCap
+(nulLen
*MB_CUR_MAX
),len
,sizeof(char));
350 remaining
= cStackCap
-(pCSrc
- pCSave
);
353 /* we have found a null so convert the
354 * chunk from begining of non-null char to null
356 retVal
= uprv_wcstombs(pCSrc
,pSrc
,remaining
);
359 /* an error occurred bail out */
360 *pErrorCode
= U_ILLEGAL_CHAR_FOUND
;
364 pCSrc
+= retVal
+1 /* already null terminated */;
366 pSrc
+= nulLen
; /* skip past the null */
367 srcLength
-=nulLen
; /* decrement the srcLength */
368 remaining
-= (pCSrc
-pCSave
);
372 /* the source is not null terminated and we are
373 * end of source so we copy the source to a temp buffer
374 * null terminate it and convert wchar_ts to chars
376 if(nulLen
>= _STACK_BUFFER_CAPACITY
){
377 /* Should rarely occcur */
378 /* allocate new buffer buffer */
379 pWStack
=(wchar_t*) uprv_malloc(sizeof(wchar_t) * (nulLen
+ 1));
381 *pErrorCode
= U_MEMORY_ALLOCATION_ERROR
;
386 /* copy the contents to tempStack */
387 uprv_memcpy(pWStack
,pSrc
,nulLen
*sizeof(wchar_t));
390 /* null terminate the tempBuffer */
393 if(remaining
< (nulLen
* MB_CUR_MAX
)){
394 /* Should rarely occur */
395 int32_t len
= (pCSrc
-pCSave
);
397 /* we do not have enough room so grow the buffer*/
398 u_growAnyBufferFromStatic(cStack
,(void**)&pCSrc
,&cStackCap
,
399 cStackCap
+(nulLen
*MB_CUR_MAX
),len
,sizeof(char));
403 remaining
= cStackCap
-(pCSrc
- pCSave
);
405 /* convert to chars */
406 retVal
= uprv_wcstombs(pCSrc
,pWStack
,remaining
);
410 srcLength
-=nulLen
; /* decrement the srcLength */
416 /* OK..now we have converted from wchar_ts to chars now
417 * convert chars to UChars
421 pTarget
= target
= dest
;
422 pTargetLimit
= dest
+ destCapacity
;
424 conv
= u_getDefaultConverter(pErrorCode
);
426 if(U_FAILURE(*pErrorCode
)|| conv
==NULL
){
432 *pErrorCode
= U_ZERO_ERROR
;
434 /* convert to stack buffer*/
435 ucnv_toUnicode(conv
,&pTarget
,pTargetLimit
,(const char**)&pCSrc
,pCSrcLimit
,NULL
,(UBool
)(pCSrc
==pCSrcLimit
),pErrorCode
);
437 /* increment count to number written to stack */
438 count
+= pTarget
- target
;
440 if(*pErrorCode
==U_BUFFER_OVERFLOW_ERROR
){
443 pTargetLimit
= uStack
+ _STACK_BUFFER_CAPACITY
;
454 u_terminateUChars(dest
,destCapacity
,count
,pErrorCode
);
458 if(cStack
!= pCSave
){
462 if(wStack
!= pWStack
){
466 u_releaseDefaultConverter(conv
);
472 U_CAPI UChar
* U_EXPORT2
473 u_strFromWCS(UChar
*dest
,
474 int32_t destCapacity
,
475 int32_t *pDestLength
,
478 UErrorCode
*pErrorCode
)
482 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)){
486 if((src
==NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
487 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
491 #ifdef U_WCHAR_IS_UTF16
492 /* wchar_t is UTF-16 just do a memcpy */
494 srcLength
= u_strlen(src
);
496 if(0 < srcLength
&& srcLength
<= destCapacity
){
497 uprv_memcpy(dest
,src
,srcLength
*U_SIZEOF_UCHAR
);
500 *pDestLength
= srcLength
;
503 u_terminateUChars(dest
,destCapacity
,srcLength
,pErrorCode
);
507 #elif defined U_WCHAR_IS_UTF32
509 return u_strFromUTF32(dest
, destCapacity
, pDestLength
,
510 (UChar32
*)src
, srcLength
, pErrorCode
);
514 return _strFromWCS(dest
,destCapacity
,pDestLength
,src
,srcLength
,pErrorCode
);