2 *******************************************************************************
4 * Copyright (C) 2001-2006, 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"
28 #if defined(U_WCHAR_IS_UTF16) || defined(U_WCHAR_IS_UTF32) || !UCONFIG_NO_CONVERSION
30 #define _STACK_BUFFER_CAPACITY 1000
31 #define _BUFFER_CAPACITY_MULTIPLIER 2
33 #if !defined(U_WCHAR_IS_UTF16) && !defined(U_WCHAR_IS_UTF32)
35 u_growAnyBufferFromStatic(void *context
,
36 void **pBuffer
, int32_t *pCapacity
, int32_t reqCapacity
,
37 int32_t length
, int32_t size
) {
39 void *newBuffer
=uprv_malloc(reqCapacity
*size
);
42 uprv_memcpy(newBuffer
, *pBuffer
, length
*size
);
44 *pCapacity
=reqCapacity
;
49 /* release the old pBuffer if it was not statically allocated */
50 if(*pBuffer
!=(void *)context
) {
55 return (UBool
)(newBuffer
!=NULL
);
60 _strToWCS(wchar_t *dest
,
65 UErrorCode
*pErrorCode
){
67 char stackBuffer
[_STACK_BUFFER_CAPACITY
];
68 char* tempBuf
= stackBuffer
;
69 int32_t tempBufCapacity
= _STACK_BUFFER_CAPACITY
;
70 char* tempBufLimit
= stackBuffer
+ tempBufCapacity
;
71 UConverter
* conv
= NULL
;
72 char* saveBuf
= tempBuf
;
73 wchar_t* intTarget
=NULL
;
74 int32_t intTargetCapacity
=0;
77 const UChar
*pSrcLimit
=NULL
;
78 const UChar
*pSrc
= src
;
80 conv
= u_getDefaultConverter(pErrorCode
);
82 if(U_FAILURE(*pErrorCode
)){
87 srcLength
= u_strlen(pSrc
);
90 pSrcLimit
= pSrc
+ srcLength
;
93 /* reset the error state */
94 *pErrorCode
= U_ZERO_ERROR
;
96 /* convert to chars using default converter */
97 ucnv_fromUnicode(conv
,&tempBuf
,tempBufLimit
,&pSrc
,pSrcLimit
,NULL
,(UBool
)(pSrc
==pSrcLimit
),pErrorCode
);
98 count
=(tempBuf
- saveBuf
);
100 /* This should rarely occur */
101 if(*pErrorCode
==U_BUFFER_OVERFLOW_ERROR
){
104 /* we dont have enough room on the stack grow the buffer */
105 if(!u_growAnyBufferFromStatic(stackBuffer
,(void**) &tempBuf
, &tempBufCapacity
,
106 (_BUFFER_CAPACITY_MULTIPLIER
* (srcLength
)), count
,sizeof(char))){
111 tempBufLimit
= tempBuf
+ tempBufCapacity
;
112 tempBuf
= tempBuf
+ count
;
119 if(U_FAILURE(*pErrorCode
)){
123 /* done with conversion null terminate the char buffer */
124 if(count
>=tempBufCapacity
){
126 /* we dont have enough room on the stack grow the buffer */
127 if(!u_growAnyBufferFromStatic(stackBuffer
,(void**) &tempBuf
, &tempBufCapacity
,
128 tempBufCapacity
-count
+1, count
,sizeof(char))){
137 /* allocate more space than required
138 * here we assume that every char requires
139 * no more than 2 wchar_ts
141 intTargetCapacity
= (count
* _BUFFER_CAPACITY_MULTIPLIER
+ 1) /*for null termination */;
142 intTarget
= (wchar_t*)uprv_malloc( intTargetCapacity
* sizeof(wchar_t) );
147 int32_t remaining
= intTargetCapacity
;
148 wchar_t* pIntTarget
=intTarget
;
151 /* now convert the mbs to wcs */
154 /* we can call the system API since we are sure that
155 * there is atleast 1 null in the input
157 retVal
= uprv_mbstowcs(pIntTarget
,(tempBuf
+nulLen
),remaining
);
160 *pErrorCode
= U_INVALID_CHAR_FOUND
;
162 }else if(retVal
== remaining
){/* should never occur */
163 int numWritten
= (pIntTarget
-intTarget
);
164 u_growAnyBufferFromStatic(NULL
,(void**) &intTarget
,
166 intTargetCapacity
* _BUFFER_CAPACITY_MULTIPLIER
,
169 pIntTarget
= intTarget
;
170 remaining
=intTargetCapacity
;
172 if(nulLen
!=count
){ /*there are embedded nulls*/
173 pIntTarget
+=numWritten
;
174 remaining
-=numWritten
;
180 /* we donot check for limit since tempBuf is null terminated */
181 while(tempBuf
[nulLen
++] != 0){
183 nulVal
= (nulLen
< srcLength
) ? 1 : 0;
184 pIntTarget
= pIntTarget
+ retVal
+nulVal
;
185 remaining
-=(retVal
+nulVal
);
187 /* check if we have reached the source limit*/
193 count
= (int32_t)(pIntTarget
-intTarget
);
195 if(0 < count
&& count
<= destCapacity
){
196 uprv_memcpy(dest
,intTarget
,count
*sizeof(wchar_t));
200 *pDestLength
= count
;
203 /* free the allocated memory */
204 uprv_free(intTarget
);
207 *pErrorCode
= U_MEMORY_ALLOCATION_ERROR
;
210 /* are we still using stack buffer */
211 if(stackBuffer
!= saveBuf
){
214 u_terminateWChars(dest
,destCapacity
,count
,pErrorCode
);
216 u_releaseDefaultConverter(conv
);
222 U_CAPI
wchar_t* U_EXPORT2
223 u_strToWCS(wchar_t *dest
,
224 int32_t destCapacity
,
225 int32_t *pDestLength
,
228 UErrorCode
*pErrorCode
){
231 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)){
235 if((src
==NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
236 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
240 #ifdef U_WCHAR_IS_UTF16
241 /* wchar_t is UTF-16 just do a memcpy */
243 srcLength
= u_strlen(src
);
245 if(0 < srcLength
&& srcLength
<= destCapacity
){
246 uprv_memcpy(dest
,src
,srcLength
*U_SIZEOF_UCHAR
);
249 *pDestLength
= srcLength
;
252 u_terminateUChars(dest
,destCapacity
,srcLength
,pErrorCode
);
256 #elif defined U_WCHAR_IS_UTF32
258 return (wchar_t*)u_strToUTF32((UChar32
*)dest
, destCapacity
, pDestLength
,
259 src
, srcLength
, pErrorCode
);
263 return _strToWCS(dest
,destCapacity
,pDestLength
,src
,srcLength
, pErrorCode
);
269 #if !defined(U_WCHAR_IS_UTF16) && !defined(U_WCHAR_IS_UTF32)
270 /* helper function */
272 _strFromWCS( UChar
*dest
,
273 int32_t destCapacity
,
274 int32_t *pDestLength
,
277 UErrorCode
*pErrorCode
)
279 int32_t retVal
=0, count
=0 ;
280 UConverter
* conv
= NULL
;
281 UChar
* pTarget
= NULL
;
282 UChar
* pTargetLimit
= NULL
;
283 UChar
* target
= NULL
;
285 UChar uStack
[_STACK_BUFFER_CAPACITY
];
287 wchar_t wStack
[_STACK_BUFFER_CAPACITY
];
288 wchar_t* pWStack
= wStack
;
291 char cStack
[_STACK_BUFFER_CAPACITY
];
292 int32_t cStackCap
= _STACK_BUFFER_CAPACITY
;
295 char* pCSrcLimit
=NULL
;
297 const wchar_t* pSrc
= src
;
298 const wchar_t* pSrcLimit
= NULL
;
301 /* if the wchar_t source is null terminated we can safely
302 * assume that there are no embedded nulls, this is a fast
303 * path for null terminated strings.
306 /* convert wchars to chars */
307 retVal
= uprv_wcstombs(pCSrc
,src
, cStackCap
);
310 *pErrorCode
= U_ILLEGAL_CHAR_FOUND
;
312 }else if(retVal
>= (cStackCap
-1)){
313 /* Should rarely occur */
314 u_growAnyBufferFromStatic(cStack
,(void**)&pCSrc
,&cStackCap
,
315 cStackCap
* _BUFFER_CAPACITY_MULTIPLIER
, 0, sizeof(char));
318 /* converted every thing */
319 pCSrc
= pCSrc
+retVal
;
325 /* here the source is not null terminated
326 * so it may have nulls embeded and we need to
327 * do some extra processing
329 int32_t remaining
=cStackCap
;
331 pSrcLimit
= src
+ srcLength
;
334 register int32_t nulLen
= 0;
336 /* find nulls in the string */
337 while(nulLen
<srcLength
&& pSrc
[nulLen
++]!=0){
340 if((pSrc
+nulLen
) < pSrcLimit
){
341 /* check if we have enough room in pCSrc */
342 if(remaining
< (nulLen
* MB_CUR_MAX
)){
343 /* should rarely occur */
344 int32_t len
= (pCSrc
-pCSave
);
346 /* we do not have enough room so grow the buffer*/
347 u_growAnyBufferFromStatic(cStack
,(void**)&pCSrc
,&cStackCap
,
348 _BUFFER_CAPACITY_MULTIPLIER
*cStackCap
+(nulLen
*MB_CUR_MAX
),len
,sizeof(char));
352 remaining
= cStackCap
-(pCSrc
- pCSave
);
355 /* we have found a null so convert the
356 * chunk from begining of non-null char to null
358 retVal
= uprv_wcstombs(pCSrc
,pSrc
,remaining
);
361 /* an error occurred bail out */
362 *pErrorCode
= U_ILLEGAL_CHAR_FOUND
;
366 pCSrc
+= retVal
+1 /* already null terminated */;
368 pSrc
+= nulLen
; /* skip past the null */
369 srcLength
-=nulLen
; /* decrement the srcLength */
370 remaining
-= (pCSrc
-pCSave
);
374 /* the source is not null terminated and we are
375 * end of source so we copy the source to a temp buffer
376 * null terminate it and convert wchar_ts to chars
378 if(nulLen
>= _STACK_BUFFER_CAPACITY
){
379 /* Should rarely occcur */
380 /* allocate new buffer buffer */
381 pWStack
=(wchar_t*) uprv_malloc(sizeof(wchar_t) * (nulLen
+ 1));
383 *pErrorCode
= U_MEMORY_ALLOCATION_ERROR
;
388 /* copy the contents to tempStack */
389 uprv_memcpy(pWStack
,pSrc
,nulLen
*sizeof(wchar_t));
392 /* null terminate the tempBuffer */
395 if(remaining
< (nulLen
* MB_CUR_MAX
)){
396 /* Should rarely occur */
397 int32_t len
= (pCSrc
-pCSave
);
399 /* we do not have enough room so grow the buffer*/
400 u_growAnyBufferFromStatic(cStack
,(void**)&pCSrc
,&cStackCap
,
401 cStackCap
+(nulLen
*MB_CUR_MAX
),len
,sizeof(char));
405 remaining
= cStackCap
-(pCSrc
- pCSave
);
407 /* convert to chars */
408 retVal
= uprv_wcstombs(pCSrc
,pWStack
,remaining
);
412 srcLength
-=nulLen
; /* decrement the srcLength */
418 /* OK..now we have converted from wchar_ts to chars now
419 * convert chars to UChars
423 pTarget
= target
= dest
;
424 pTargetLimit
= dest
+ destCapacity
;
426 conv
= u_getDefaultConverter(pErrorCode
);
428 if(U_FAILURE(*pErrorCode
)|| conv
==NULL
){
434 *pErrorCode
= U_ZERO_ERROR
;
436 /* convert to stack buffer*/
437 ucnv_toUnicode(conv
,&pTarget
,pTargetLimit
,(const char**)&pCSrc
,pCSrcLimit
,NULL
,(UBool
)(pCSrc
==pCSrcLimit
),pErrorCode
);
439 /* increment count to number written to stack */
440 count
+= pTarget
- target
;
442 if(*pErrorCode
==U_BUFFER_OVERFLOW_ERROR
){
445 pTargetLimit
= uStack
+ _STACK_BUFFER_CAPACITY
;
456 u_terminateUChars(dest
,destCapacity
,count
,pErrorCode
);
460 if(cStack
!= pCSave
){
464 if(wStack
!= pWStack
){
468 u_releaseDefaultConverter(conv
);
474 U_CAPI UChar
* U_EXPORT2
475 u_strFromWCS(UChar
*dest
,
476 int32_t destCapacity
,
477 int32_t *pDestLength
,
480 UErrorCode
*pErrorCode
)
484 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)){
488 if((src
==NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
489 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
493 #ifdef U_WCHAR_IS_UTF16
494 /* wchar_t is UTF-16 just do a memcpy */
496 srcLength
= u_strlen(src
);
498 if(0 < srcLength
&& srcLength
<= destCapacity
){
499 uprv_memcpy(dest
,src
,srcLength
*U_SIZEOF_UCHAR
);
502 *pDestLength
= srcLength
;
505 u_terminateUChars(dest
,destCapacity
,srcLength
,pErrorCode
);
509 #elif defined U_WCHAR_IS_UTF32
511 return u_strFromUTF32(dest
, destCapacity
, pDestLength
,
512 (UChar32
*)src
, srcLength
, pErrorCode
);
516 return _strFromWCS(dest
,destCapacity
,pDestLength
,src
,srcLength
,pErrorCode
);
522 #endif /* #if !defined(U_WCHAR_IS_UTF16) && !defined(U_WCHAR_IS_UTF32) && !UCONFIG_NO_CONVERSION */