]> git.saurik.com Git - apple/icu.git/blob - icuSources/common/ustrtrns.c
ICU-3.13.tar.gz
[apple/icu.git] / icuSources / common / ustrtrns.c
1 /*
2 ******************************************************************************
3 *
4 * Copyright (C) 2001-2003, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *
7 ******************************************************************************
8 *
9 * File ustrtrns.c
10 *
11 * Modification History:
12 *
13 * Date Name Description
14 * 9/10/2001 Ram Creation.
15 ******************************************************************************
16 */
17
18 /*******************************************************************************
19 *
20 * u_strTo* and u_strFrom* APIs
21 *
22 *******************************************************************************
23 */
24
25
26 #include "unicode/putil.h"
27 #include "unicode/ucnv.h"
28 #include "unicode/ustring.h"
29 #include "cstring.h"
30 #include "cwchar.h"
31 #include "cmemory.h"
32 #include "ustr_imp.h"
33
34
35 static U_INLINE UBool
36 u_growAnyBufferFromStatic(void *context,
37 void **pBuffer, int32_t *pCapacity, int32_t reqCapacity,
38 int32_t length, int32_t size) {
39
40 void *newBuffer=uprv_malloc(reqCapacity*size);
41 if(newBuffer!=NULL) {
42 if(length>0) {
43 uprv_memcpy(newBuffer, *pBuffer, length*size);
44 }
45 *pCapacity=reqCapacity;
46 } else {
47 *pCapacity=0;
48 }
49
50 /* release the old pBuffer if it was not statically allocated */
51 if(*pBuffer!=(void *)context) {
52 uprv_free(*pBuffer);
53 }
54
55 *pBuffer=newBuffer;
56 return (UBool)(newBuffer!=NULL);
57 }
58
59 #define _STACK_BUFFER_CAPACITY 1000
60
61 U_CAPI UChar* U_EXPORT2
62 u_strFromUTF32(UChar *dest,
63 int32_t destCapacity,
64 int32_t *pDestLength,
65 const UChar32 *src,
66 int32_t srcLength,
67 UErrorCode *pErrorCode)
68 {
69 int32_t reqLength = 0;
70 uint32_t ch =0;
71 UChar *pDestLimit =dest+destCapacity;
72 UChar *pDest = dest;
73 const uint32_t *pSrc = (const uint32_t *)src;
74
75 /* args check */
76 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)){
77 return NULL;
78 }
79
80 if((srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
81 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
82 return NULL;
83 }
84
85 /* Check if the source is null terminated */
86 if(srcLength == -1 ){
87 while(((ch=*pSrc)!=0) && (pDest < pDestLimit)){
88 ++pSrc;
89 if(ch<=0xFFFF){
90 *(pDest++)=(UChar)ch;
91 }else if(ch<=0x10ffff){
92 *(pDest++)=UTF16_LEAD(ch);
93 if(pDest<pDestLimit){
94 *(pDest++)=UTF16_TRAIL(ch);
95 }else{
96 reqLength++;
97 break;
98 }
99 }else{
100 *pErrorCode = U_INVALID_CHAR_FOUND;
101 return NULL;
102 }
103 }
104 while((ch=*pSrc++) != 0){
105 reqLength+=UTF_CHAR_LENGTH(ch);
106 }
107 }else{
108 const uint32_t* pSrcLimit = ((const uint32_t*)pSrc) + srcLength;
109 while((pSrc < pSrcLimit) && (pDest < pDestLimit)){
110 ch = *pSrc++;
111 if(ch<=0xFFFF){
112 *(pDest++)=(UChar)ch;
113 }else if(ch<=0x10FFFF){
114 *(pDest++)=UTF16_LEAD(ch);
115 if(pDest<pDestLimit){
116 *(pDest++)=UTF16_TRAIL(ch);
117 }else{
118 reqLength++;
119 break;
120 }
121 }else{
122 *pErrorCode = U_INVALID_CHAR_FOUND;
123 return NULL;
124 }
125 }
126 while(pSrc <pSrcLimit){
127 ch = *pSrc++;
128 reqLength+=UTF_CHAR_LENGTH(ch);
129 }
130 }
131
132 reqLength += pDest - dest;
133 if(pDestLength){
134 *pDestLength = reqLength;
135 }
136
137 /* Terminate the buffer */
138 u_terminateUChars(dest,destCapacity,reqLength,pErrorCode);
139
140 return dest;
141 }
142
143
144 U_CAPI UChar32* U_EXPORT2
145 u_strToUTF32(UChar32 *dest,
146 int32_t destCapacity,
147 int32_t *pDestLength,
148 const UChar *src,
149 int32_t srcLength,
150 UErrorCode *pErrorCode)
151 {
152 const UChar* pSrc = src;
153 const UChar* pSrcLimit;
154 int32_t reqLength=0;
155 uint32_t ch=0;
156 uint32_t *pDest = (uint32_t *)dest;
157 uint32_t *pDestLimit = pDest + destCapacity;
158 UChar ch2=0;
159
160 /* args check */
161 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)){
162 return NULL;
163 }
164
165
166 if((srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
167 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
168 return NULL;
169 }
170
171 if(srcLength==-1) {
172 while((ch=*pSrc)!=0 && pDest!=pDestLimit) {
173 ++pSrc;
174 /*need not check for NUL because NUL fails UTF_IS_TRAIL() anyway*/
175 if(UTF_IS_LEAD(ch) && UTF_IS_TRAIL(ch2=*pSrc)) {
176 ++pSrc;
177 ch=UTF16_GET_PAIR_VALUE(ch, ch2);
178 }
179 *(pDest++)= ch;
180 }
181 while((ch=*pSrc++)!=0) {
182 if(UTF_IS_LEAD(ch) && UTF_IS_TRAIL(ch2=*pSrc)) {
183 ++pSrc;
184 }
185 ++reqLength;
186 }
187 } else {
188 pSrcLimit = pSrc+srcLength;
189 while(pSrc<pSrcLimit && pDest<pDestLimit) {
190 ch=*pSrc++;
191 if(UTF_IS_LEAD(ch) && pSrc<pSrcLimit && UTF_IS_TRAIL(ch2=*pSrc)) {
192 ++pSrc;
193 ch=UTF16_GET_PAIR_VALUE(ch, ch2);
194 }
195 *(pDest++)= ch;
196 }
197 while(pSrc!=pSrcLimit) {
198 ch=*pSrc++;
199 if(UTF_IS_LEAD(ch) && pSrc<pSrcLimit && UTF_IS_TRAIL(ch2=*pSrc)) {
200 ++pSrc;
201 }
202 ++reqLength;
203 }
204 }
205
206 reqLength+=(pDest - (uint32_t *)dest);
207 if(pDestLength){
208 *pDestLength = reqLength;
209 }
210
211 /* Terminate the buffer */
212 u_terminateUChar32s(dest,destCapacity,reqLength,pErrorCode);
213
214 return dest;
215 }
216
217 U_CAPI UChar* U_EXPORT2
218 u_strFromUTF8(UChar *dest,
219 int32_t destCapacity,
220 int32_t *pDestLength,
221 const char* src,
222 int32_t srcLength,
223 UErrorCode *pErrorCode){
224
225 UChar *pDest = dest;
226 UChar *pDestLimit = dest+destCapacity;
227 UChar32 ch=0;
228 int32_t index = 0;
229 int32_t reqLength = 0;
230 uint8_t* pSrc = (uint8_t*) src;
231
232 /* args check */
233 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)){
234 return NULL;
235 }
236
237 if((srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
238 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
239 return NULL;
240 }
241
242 if(srcLength == -1){
243 srcLength = uprv_strlen((char*)pSrc);
244 }
245
246 while((index < srcLength)&&(pDest<pDestLimit)){
247 ch = pSrc[index++];
248 if(ch <=0x7f){
249 *pDest++=(UChar)ch;
250 }else{
251 ch=utf8_nextCharSafeBody(pSrc, &index, srcLength, ch, -1);
252 if(ch<0){
253 *pErrorCode = U_INVALID_CHAR_FOUND;
254 return NULL;
255 }else if(ch<=0xFFFF){
256 *(pDest++)=(UChar)ch;
257 }else{
258 *(pDest++)=UTF16_LEAD(ch);
259 if(pDest<pDestLimit){
260 *(pDest++)=UTF16_TRAIL(ch);
261 }else{
262 reqLength++;
263 break;
264 }
265 }
266 }
267 }
268 /* donot fill the dest buffer just count the UChars needed */
269 while(index < srcLength){
270 ch = pSrc[index++];
271 if(ch <= 0x7f){
272 reqLength++;
273 }else{
274 ch=utf8_nextCharSafeBody(pSrc, &index, srcLength, ch, -1);
275 if(ch<0){
276 *pErrorCode = U_INVALID_CHAR_FOUND;
277 return NULL;
278 }
279 reqLength+=UTF_CHAR_LENGTH(ch);
280 }
281 }
282
283 reqLength+=(pDest - dest);
284
285 if(pDestLength){
286 *pDestLength = reqLength;
287 }
288
289 /* Terminate the buffer */
290 u_terminateUChars(dest,destCapacity,reqLength,pErrorCode);
291
292 return dest;
293 }
294
295 static U_INLINE uint8_t *
296 _appendUTF8(uint8_t *pDest, UChar32 c) {
297 /* c<=0x7f is handled by the caller, here it is 0x80<=c<=0x10ffff */
298 if((c)<=0x7ff) {
299 *pDest++=(uint8_t)((c>>6)|0xc0);
300 *pDest++=(uint8_t)((c&0x3f)|0x80);
301 } else if((uint32_t)(c)<=0xffff) {
302 *pDest++=(uint8_t)((c>>12)|0xe0);
303 *pDest++=(uint8_t)(((c>>6)&0x3f)|0x80);
304 *pDest++=(uint8_t)(((c)&0x3f)|0x80);
305 } else /* if((uint32_t)(c)<=0x10ffff) */ {
306 *pDest++=(uint8_t)(((c)>>18)|0xf0);
307 *pDest++=(uint8_t)((((c)>>12)&0x3f)|0x80);
308 *pDest++=(uint8_t)((((c)>>6)&0x3f)|0x80);
309 *pDest++=(uint8_t)(((c)&0x3f)|0x80);
310 }
311 return pDest;
312 }
313
314
315 U_CAPI char* U_EXPORT2
316 u_strToUTF8(char *dest,
317 int32_t destCapacity,
318 int32_t *pDestLength,
319 const UChar *pSrc,
320 int32_t srcLength,
321 UErrorCode *pErrorCode){
322
323 int32_t reqLength=0;
324 const UChar *pSrcLimit;
325 uint32_t ch=0,ch2=0;
326 uint8_t *pDest = (uint8_t *)dest;
327 uint8_t *pDestLimit = pDest + destCapacity;
328
329
330 /* args check */
331 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)){
332 return NULL;
333 }
334
335 if((srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
336 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
337 return NULL;
338 }
339
340 if(srcLength==-1) {
341 while((ch=*pSrc)!=0 && pDest!=pDestLimit) {
342 ++pSrc;
343 if(ch <= 0x7f) {
344 *pDest++ = (char)ch;
345 ++reqLength;
346 continue;
347 }
348
349 /*need not check for NUL because NUL fails UTF_IS_TRAIL() anyway*/
350 if(UTF_IS_SURROGATE(ch)) {
351 if(UTF_IS_SURROGATE_FIRST(ch) && UTF_IS_TRAIL(ch2=*pSrc)) {
352 ++pSrc;
353 ch=UTF16_GET_PAIR_VALUE(ch, ch2);
354 } else {
355 /* Unicode 3.2 forbids surrogate code points in UTF-8 */
356 *pErrorCode = U_INVALID_CHAR_FOUND;
357 return NULL;
358 }
359 }
360 reqLength += UTF8_CHAR_LENGTH(ch);
361 /* do we have enough room in destination? */
362 if(destCapacity< reqLength){
363 break;
364 }
365 /* convert and append*/
366 pDest=_appendUTF8(pDest, ch);
367 }
368 while((ch=*pSrc++)!=0) {
369 if(ch<=0x7f) {
370 ++reqLength;
371 } else if(ch<=0x7ff) {
372 reqLength+=2;
373 } else if(!UTF_IS_SURROGATE(ch)) {
374 reqLength+=3;
375 } else if(UTF_IS_SURROGATE_FIRST(ch) && UTF_IS_TRAIL(ch2=*pSrc)) {
376 ++pSrc;
377 reqLength+=4;
378 } else {
379 /* Unicode 3.2 forbids surrogate code points in UTF-8 */
380 *pErrorCode = U_INVALID_CHAR_FOUND;
381 return NULL;
382 }
383 }
384 } else {
385 pSrcLimit = pSrc+srcLength;
386 while(pSrc<pSrcLimit && pDest<pDestLimit) {
387 ch=*pSrc++;
388 if(ch <= 0x7f) {
389 *pDest++ = (char)ch;
390 ++reqLength;
391 continue;
392 }
393
394 if(UTF_IS_SURROGATE(ch)) {
395 if(UTF_IS_SURROGATE_FIRST(ch) && pSrc<pSrcLimit && UTF_IS_TRAIL(ch2=*pSrc)) {
396 ++pSrc;
397 ch=UTF16_GET_PAIR_VALUE(ch, ch2);
398 } else {
399 /* Unicode 3.2 forbids surrogate code points in UTF-8 */
400 *pErrorCode = U_INVALID_CHAR_FOUND;
401 return NULL;
402 }
403 }
404 reqLength += UTF8_CHAR_LENGTH(ch);
405 /* do we have enough room in destination? */
406 if(destCapacity< reqLength){
407 break;
408 }
409 /* convert and append*/
410 pDest=_appendUTF8(pDest, ch);
411 }
412 while(pSrc<pSrcLimit) {
413 ch=*pSrc++;
414 if(ch<=0x7f) {
415 ++reqLength;
416 } else if(ch<=0x7ff) {
417 reqLength+=2;
418 } else if(!UTF_IS_SURROGATE(ch)) {
419 reqLength+=3;
420 } else if(UTF_IS_SURROGATE_FIRST(ch) && pSrc<pSrcLimit && UTF_IS_TRAIL(ch2=*pSrc)) {
421 ++pSrc;
422 reqLength+=4;
423 } else {
424 /* Unicode 3.2 forbids surrogate code points in UTF-8 */
425 *pErrorCode = U_INVALID_CHAR_FOUND;
426 return NULL;
427 }
428 }
429 }
430
431 if(pDestLength){
432 *pDestLength = reqLength;
433 }
434
435 /* Terminate the buffer */
436 u_terminateChars((char*)dest,destCapacity,reqLength,pErrorCode);
437
438 return (char*)dest;
439 }
440
441 #if !defined(U_WCHAR_IS_UTF16) && !defined(U_WCHAR_IS_UTF32)
442 /* helper function */
443 static wchar_t*
444 _strToWCS(wchar_t *dest,
445 int32_t destCapacity,
446 int32_t *pDestLength,
447 const UChar *src,
448 int32_t srcLength,
449 UErrorCode *pErrorCode){
450
451 char stackBuffer [_STACK_BUFFER_CAPACITY];
452 char* tempBuf = stackBuffer;
453 int32_t tempBufCapacity = _STACK_BUFFER_CAPACITY;
454 char* tempBufLimit = stackBuffer + tempBufCapacity;
455 UConverter* conv = NULL;
456 char* saveBuf = tempBuf;
457 wchar_t* intTarget=NULL;
458 int32_t intTargetCapacity=0;
459 int count=0,retVal=0;
460
461 const UChar *pSrcLimit =NULL;
462 const UChar *pSrc = src;
463
464 conv = u_getDefaultConverter(pErrorCode);
465
466 if(U_FAILURE(*pErrorCode)){
467 return NULL;
468 }
469
470 if(srcLength == -1){
471 srcLength = u_strlen(pSrc);
472 }
473
474 pSrcLimit = pSrc + srcLength;
475
476 for(;;) {
477 /* reset the error state */
478 *pErrorCode = U_ZERO_ERROR;
479
480 /* convert to chars using default converter */
481 ucnv_fromUnicode(conv,&tempBuf,tempBufLimit,&pSrc,pSrcLimit,NULL,(UBool)(pSrc==pSrcLimit),pErrorCode);
482 count =(tempBuf - saveBuf);
483
484 /* This should rarely occur */
485 if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR){
486 tempBuf = saveBuf;
487
488 /* we dont have enough room on the stack grow the buffer */
489 if(!u_growAnyBufferFromStatic(stackBuffer,(void**) &tempBuf, &tempBufCapacity,
490 (2*(pSrcLimit-pSrc)+100), count,sizeof(char))){
491 goto cleanup;
492 }
493
494 saveBuf = tempBuf;
495 tempBufLimit = tempBuf + tempBufCapacity;
496 tempBuf = tempBuf + count;
497
498 } else {
499 break;
500 }
501 }
502
503 if(U_FAILURE(*pErrorCode)){
504 goto cleanup;
505 }
506
507 /* done with conversion null terminate the char buffer */
508 if(count>=tempBufCapacity){
509 tempBuf = saveBuf;
510 /* we dont have enough room on the stack grow the buffer */
511 if(!u_growAnyBufferFromStatic(stackBuffer,(void**) &tempBuf, &tempBufCapacity,
512 tempBufCapacity-count+1, count,sizeof(char))){
513 goto cleanup;
514 }
515 saveBuf = tempBuf;
516 }
517
518 saveBuf[count]=0;
519
520
521 /* allocate more space than required
522 * here we assume that every char requires
523 * no more than 2 wchar_ts
524 */
525 intTargetCapacity = (count*2+1) /*for null termination */;
526 intTarget = (wchar_t*)uprv_malloc( intTargetCapacity * sizeof(wchar_t) );
527
528 if(intTarget){
529
530 int32_t nulLen = 0;
531 int32_t remaining = intTargetCapacity;
532 wchar_t* pIntTarget=intTarget;
533 tempBuf = saveBuf;
534
535 /* now convert the mbs to wcs */
536 for(;;){
537
538 /* we can call the system API since we are sure that
539 * there is atleast 1 null in the input
540 */
541 retVal = uprv_mbstowcs(pIntTarget,(tempBuf+nulLen),remaining);
542
543 if(retVal==-1){
544 *pErrorCode = U_INVALID_CHAR_FOUND;
545 break;
546 }else if(retVal== remaining){/* should never occur */
547 int numWritten = (pIntTarget-intTarget);
548 u_growAnyBufferFromStatic(NULL,(void**) &intTarget,
549 &intTargetCapacity,
550 intTargetCapacity*2,
551 numWritten,
552 sizeof(wchar_t));
553 pIntTarget = intTarget;
554 remaining=intTargetCapacity;
555
556 if(nulLen!=count){ /*there are embedded nulls*/
557 pIntTarget+=numWritten;
558 remaining-=numWritten;
559 }
560
561 }else{
562 /*scan for nulls */
563 /* we donot check for limit since tempBuf is null terminated */
564 while(tempBuf[nulLen++] != 0){
565 }
566 pIntTarget = pIntTarget + retVal+1;
567 remaining -=(retVal+1);
568
569 /* check if we have reached the source limit*/
570 if(nulLen>=(count)){
571 break;
572 }
573 }
574 }
575 count = (int32_t)(pIntTarget-intTarget);
576
577 if(0 < count && count <= destCapacity){
578 uprv_memcpy(dest,intTarget,count*sizeof(wchar_t));
579 }
580
581 if(pDestLength){
582 *pDestLength = count;
583 }
584
585 /* free the allocated memory */
586 uprv_free(intTarget);
587
588 }else{
589 *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
590 }
591 cleanup:
592 /* are we still using stack buffer */
593 if(stackBuffer != saveBuf){
594 uprv_free(saveBuf);
595 }
596 u_terminateWChars(dest,destCapacity,count,pErrorCode);
597
598 u_releaseDefaultConverter(conv);
599
600 return dest;
601 }
602 #endif
603
604 U_CAPI wchar_t* U_EXPORT2
605 u_strToWCS(wchar_t *dest,
606 int32_t destCapacity,
607 int32_t *pDestLength,
608 const UChar *src,
609 int32_t srcLength,
610 UErrorCode *pErrorCode){
611
612 /* args check */
613 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)){
614 return NULL;
615 }
616
617 if((srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
618 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
619 return NULL;
620 }
621
622 #ifdef U_WCHAR_IS_UTF16
623 /* wchar_t is UTF-16 just do a memcpy */
624 if(srcLength == -1){
625 srcLength = u_strlen(src);
626 }
627 if(0 < srcLength && srcLength <= destCapacity){
628 uprv_memcpy(dest,src,srcLength*U_SIZEOF_UCHAR);
629 }
630 if(pDestLength){
631 *pDestLength = srcLength;
632 }
633
634 u_terminateUChars(dest,destCapacity,srcLength,pErrorCode);
635
636 return dest;
637
638 #elif defined U_WCHAR_IS_UTF32
639
640 return (wchar_t*)u_strToUTF32((UChar32*)dest, destCapacity, pDestLength,
641 src, srcLength, pErrorCode);
642
643 #else
644
645 return _strToWCS(dest,destCapacity,pDestLength,src,srcLength, pErrorCode);
646
647 #endif
648 }
649
650 #if !defined(U_WCHAR_IS_UTF16) && !defined(U_WCHAR_IS_UTF32)
651 /* helper function */
652 static UChar*
653 _strFromWCS( UChar *dest,
654 int32_t destCapacity,
655 int32_t *pDestLength,
656 const wchar_t *src,
657 int32_t srcLength,
658 UErrorCode *pErrorCode){
659
660 int32_t retVal =0, count =0 ;
661 UConverter* conv = NULL;
662 UChar* pTarget = NULL;
663 UChar* pTargetLimit = NULL;
664 UChar* target = NULL;
665
666 UChar uStack [_STACK_BUFFER_CAPACITY];
667
668 wchar_t wStack[_STACK_BUFFER_CAPACITY];
669 wchar_t* pWStack = wStack;
670
671
672 char cStack[_STACK_BUFFER_CAPACITY];
673 int32_t cStackCap = _STACK_BUFFER_CAPACITY;
674 char* pCSrc=cStack;
675 char* pCSave=pCSrc;
676 char* pCSrcLimit=NULL;
677
678 const wchar_t* pSrc = src;
679 const wchar_t* pSrcLimit = NULL;
680
681 if(srcLength ==-1){
682 /* if the wchar_t source is null terminated we can safely
683 * assume that there are no embedded nulls, this is a fast
684 * path for null terminated strings.
685 */
686 for(;;){
687 /* convert wchars to chars */
688 retVal = uprv_wcstombs(pCSrc,src, cStackCap);
689
690 if(retVal == -1){
691 *pErrorCode = U_ILLEGAL_CHAR_FOUND;
692 goto cleanup;
693 }else if(retVal == cStackCap){
694 /* Should rarely occur */
695 u_growAnyBufferFromStatic(cStack,(void**)&pCSrc,&cStackCap,
696 cStackCap*2,0,sizeof(char));
697 pCSave = pCSrc;
698 }else{
699 /* converted every thing */
700 pCSrc = pCSrc+retVal;
701 break;
702 }
703 }
704
705 }else{
706 /* here the source is not null terminated
707 * so it may have nulls embeded and we need to
708 * do some extra processing
709 */
710 int32_t remaining =cStackCap;
711
712 pSrcLimit = src + srcLength;
713
714 for(;;){
715 register int32_t nulLen = 0;
716
717 /* find nulls in the string */
718 while(nulLen<srcLength && pSrc[nulLen++]!=0){
719 }
720
721 if((pSrc+nulLen) < pSrcLimit){
722 /* check if we have enough room in pCSrc */
723 if(remaining < (nulLen * MB_CUR_MAX)){
724 /* should rarely occur */
725 int32_t len = (pCSrc-pCSave);
726 pCSrc = pCSave;
727 /* we do not have enough room so grow the buffer*/
728 u_growAnyBufferFromStatic(cStack,(void**)&pCSrc,&cStackCap,
729 2*cStackCap+(nulLen*MB_CUR_MAX),len,sizeof(char));
730
731 pCSave = pCSrc;
732 pCSrc = pCSave+len;
733 remaining = cStackCap-(pCSrc - pCSave);
734 }
735
736 /* we have found a null so convert the
737 * chunk from begining of non-null char to null
738 */
739 retVal = uprv_wcstombs(pCSrc,pSrc,remaining);
740
741 if(retVal==-1){
742 /* an error occurred bail out */
743 *pErrorCode = U_ILLEGAL_CHAR_FOUND;
744 goto cleanup;
745 }
746
747 pCSrc += retVal+1 /* already null terminated */;
748
749 pSrc += nulLen; /* skip past the null */
750 srcLength-=nulLen; /* decrement the srcLength */
751 remaining -= (pCSrc-pCSave);
752
753
754 }else{
755 /* the source is not null terminated and we are
756 * end of source so we copy the source to a temp buffer
757 * null terminate it and convert wchar_ts to chars
758 */
759 if(nulLen > _STACK_BUFFER_CAPACITY){
760 /* Should rarely occcur */
761 /* allocate new buffer buffer */
762 pWStack =(wchar_t*) uprv_malloc(sizeof(wchar_t) * nulLen);
763 if(pWStack==NULL){
764 *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
765 goto cleanup;
766 }
767 }
768 if(nulLen>0){
769 /* copy the contents to tempStack */
770 uprv_memcpy(pWStack,pSrc,nulLen*sizeof(wchar_t));
771 }
772
773 /* null terminate the tempBuffer */
774 pWStack[nulLen] =0 ;
775
776 if(remaining < (nulLen * MB_CUR_MAX)){
777 /* Should rarely occur */
778 int32_t len = (pCSrc-pCSave);
779 pCSrc = pCSave;
780 /* we do not have enough room so grow the buffer*/
781 u_growAnyBufferFromStatic(cStack,(void**)&pCSrc,&cStackCap,
782 cStackCap+(nulLen*MB_CUR_MAX),len,sizeof(char));
783
784 pCSave = pCSrc;
785 pCSrc = pCSave+len;
786 remaining = cStackCap-(pCSrc - pCSave);
787 }
788 /* convert to chars */
789 retVal = uprv_wcstombs(pCSrc,pWStack,remaining);
790
791 pCSrc += retVal +1;
792 pSrc += nulLen;
793 srcLength-=nulLen; /* decrement the srcLength */
794 break;
795 }
796 }
797 }
798
799 /* OK..now we have converted from wchar_ts to chars now
800 * convert chars to UChars
801 */
802 pCSrcLimit = pCSrc;
803 pCSrc = pCSave;
804 pTarget = target= dest;
805 pTargetLimit = dest + destCapacity;
806
807 conv= u_getDefaultConverter(pErrorCode);
808
809 if(U_FAILURE(*pErrorCode)|| conv==NULL){
810 goto cleanup;
811 }
812
813 for(;;) {
814
815 *pErrorCode = U_ZERO_ERROR;
816
817 /* convert to stack buffer*/
818 ucnv_toUnicode(conv,&pTarget,pTargetLimit,(const char**)&pCSrc,pCSrcLimit,NULL,(UBool)(pCSrc==pCSrcLimit),pErrorCode);
819
820 /* increment count to number written to stack */
821 count+= pTarget - target;
822
823 if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR){
824 target = uStack;
825 pTarget = uStack;
826 pTargetLimit = uStack + _STACK_BUFFER_CAPACITY;
827 } else {
828 break;
829 }
830
831 }
832
833 if(pDestLength){
834 *pDestLength =count;
835 }
836
837 u_terminateUChars(dest,destCapacity,count,pErrorCode);
838
839 cleanup:
840
841 if(cStack != pCSave){
842 uprv_free(pCSave);
843 }
844
845 if(wStack != pWStack){
846 uprv_free(pWStack);
847 }
848
849 u_releaseDefaultConverter(conv);
850
851 return dest;
852 }
853 #endif
854
855 U_CAPI UChar* U_EXPORT2
856 u_strFromWCS(UChar *dest,
857 int32_t destCapacity,
858 int32_t *pDestLength,
859 const wchar_t *src,
860 int32_t srcLength,
861 UErrorCode *pErrorCode)
862 {
863
864 /* args check */
865 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)){
866 return NULL;
867 }
868
869 if((srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
870 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
871 return NULL;
872 }
873
874 #ifdef U_WCHAR_IS_UTF16
875 /* wchar_t is UTF-16 just do a memcpy */
876 if(srcLength == -1){
877 srcLength = u_strlen(src);
878 }
879 if(0 < srcLength && srcLength <= destCapacity){
880 uprv_memcpy(dest,src,srcLength*U_SIZEOF_UCHAR);
881 }
882 if(pDestLength){
883 *pDestLength = srcLength;
884 }
885
886 u_terminateUChars(dest,destCapacity,srcLength,pErrorCode);
887
888 return dest;
889
890 #elif defined U_WCHAR_IS_UTF32
891
892 return u_strFromUTF32(dest, destCapacity, pDestLength,
893 (UChar32*)src, srcLength, pErrorCode);
894
895 #else
896
897 return _strFromWCS(dest,destCapacity,pDestLength,src,srcLength,pErrorCode);
898
899 #endif
900
901 }