~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/common/ustrtrns.c

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
U_INLINE static 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, FALSE);
252
 
            if(ch<=0xFFFF){
253
 
                *(pDest++)=(UChar)ch;
254
 
            }else if(ch<=0x10ffff){
255
 
                *(pDest++)=UTF16_LEAD(ch);
256
 
                if(pDest<pDestLimit){
257
 
                    *(pDest++)=UTF16_TRAIL(ch);
258
 
                }else{
259
 
                    reqLength++;
260
 
                    break;
261
 
                }
262
 
            }else{
263
 
                *pErrorCode = U_INVALID_CHAR_FOUND;
264
 
                return NULL;
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, FALSE);
275
 
            reqLength+=UTF_CHAR_LENGTH(ch);
276
 
        }
277
 
    }
278
 
 
279
 
    reqLength+=(pDest - dest);
280
 
 
281
 
    if(pDestLength){
282
 
        *pDestLength = reqLength;
283
 
    }
284
 
 
285
 
    /* Terminate the buffer */
286
 
    u_terminateUChars(dest,destCapacity,reqLength,pErrorCode);
287
 
 
288
 
    return dest;
289
 
}
290
 
 
291
 
U_INLINE static uint8_t *
292
 
_appendUTF8(uint8_t *pDest, UChar32 c) {
293
 
    /* c<=0x7f is handled by the caller, here it is 0x80<=c<=0x10ffff */
294
 
    if((c)<=0x7ff) {
295
 
        *pDest++=(uint8_t)((c>>6)|0xc0);
296
 
        *pDest++=(uint8_t)((c&0x3f)|0x80);
297
 
    } else if((uint32_t)(c)<=0xffff) {
298
 
        *pDest++=(uint8_t)((c>>12)|0xe0);
299
 
        *pDest++=(uint8_t)(((c>>6)&0x3f)|0x80);
300
 
        *pDest++=(uint8_t)(((c)&0x3f)|0x80);
301
 
    } else /* if((uint32_t)(c)<=0x10ffff) */ {
302
 
        *pDest++=(uint8_t)(((c)>>18)|0xf0);
303
 
        *pDest++=(uint8_t)((((c)>>12)&0x3f)|0x80);
304
 
        *pDest++=(uint8_t)((((c)>>6)&0x3f)|0x80);
305
 
        *pDest++=(uint8_t)(((c)&0x3f)|0x80);
306
 
    }
307
 
    return pDest;
308
 
}
309
 
 
310
 
   
311
 
U_CAPI char* U_EXPORT2 
312
 
u_strToUTF8(char *dest,           
313
 
            int32_t destCapacity,
314
 
            int32_t *pDestLength,
315
 
            const UChar *pSrc, 
316
 
            int32_t srcLength,
317
 
            UErrorCode *pErrorCode){
318
 
 
319
 
    int32_t reqLength=0;
320
 
    const UChar *pSrcLimit;
321
 
    uint32_t ch=0,ch2=0;
322
 
    uint8_t *pDest = (uint8_t *)dest;
323
 
    uint8_t *pDestLimit = pDest + destCapacity;
324
 
 
325
 
 
326
 
    /* args check */
327
 
    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)){
328
 
        return NULL;
329
 
    }
330
 
        
331
 
    if((srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
332
 
        *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
333
 
        return NULL;
334
 
    }
335
 
 
336
 
    if(srcLength==-1) {
337
 
        while((ch=*pSrc)!=0 && pDest!=pDestLimit) {
338
 
            ++pSrc;
339
 
            if(ch <= 0x7f) {
340
 
                *pDest++ = (char)ch;
341
 
                ++reqLength;
342
 
                continue;
343
 
            }
344
 
 
345
 
            /*need not check for NUL because NUL fails UTF_IS_TRAIL() anyway*/
346
 
            if(UTF_IS_LEAD(ch) && UTF_IS_TRAIL(ch2=*pSrc)) { 
347
 
                ++pSrc;
348
 
                ch=UTF16_GET_PAIR_VALUE(ch, ch2);
349
 
            }
350
 
            reqLength += UTF8_CHAR_LENGTH(ch);
351
 
            /* do we have enough room in destination? */
352
 
            if(destCapacity< reqLength){
353
 
                break;
354
 
            }
355
 
            /* convert and append*/
356
 
            pDest=_appendUTF8(pDest, ch);
357
 
        }
358
 
        while((ch=*pSrc++)!=0) {
359
 
            if(UTF_IS_LEAD(ch) && UTF_IS_TRAIL(ch2=*pSrc)) {
360
 
                ++pSrc;
361
 
                reqLength+=4;
362
 
            } else {
363
 
                reqLength+=UTF8_CHAR_LENGTH(ch);
364
 
            }
365
 
        }
366
 
    } else {
367
 
        pSrcLimit = pSrc+srcLength;
368
 
        while(pSrc<pSrcLimit && pDest<pDestLimit) {
369
 
            ch=*pSrc++;
370
 
            if(ch <= 0x7f) {
371
 
                *pDest++ = (char)ch;
372
 
                ++reqLength;
373
 
                continue;
374
 
            }
375
 
 
376
 
            if(UTF_IS_LEAD(ch) && pSrc<pSrcLimit && UTF_IS_TRAIL(ch2=*pSrc)) { 
377
 
                ++pSrc;
378
 
                ch=UTF16_GET_PAIR_VALUE(ch, ch2);
379
 
            }
380
 
            reqLength += UTF8_CHAR_LENGTH(ch);
381
 
            /* do we have enough room in destination? */
382
 
            if(destCapacity< reqLength){
383
 
                break;
384
 
            }
385
 
            /* convert and append*/
386
 
            pDest=_appendUTF8(pDest, ch);
387
 
        }
388
 
        while(pSrc<pSrcLimit) {
389
 
            ch=*pSrc++;
390
 
            if(UTF_IS_LEAD(ch) && pSrc<pSrcLimit && UTF_IS_TRAIL(ch2=*pSrc)) {
391
 
                ++pSrc;
392
 
                reqLength+=4;
393
 
            } else {
394
 
                reqLength+=UTF8_CHAR_LENGTH(ch);
395
 
            }
396
 
        }
397
 
    }
398
 
 
399
 
    if(pDestLength){
400
 
        *pDestLength = reqLength;
401
 
    }
402
 
 
403
 
    /* Terminate the buffer */
404
 
    u_terminateChars((char*)dest,destCapacity,reqLength,pErrorCode);
405
 
 
406
 
    return (char*)dest;
407
 
}
408
 
 
409
 
#if !defined(U_WCHAR_IS_UTF16) && !defined(U_WCHAR_IS_UTF32)
410
 
/* helper function */
411
 
static wchar_t* 
412
 
_strToWCS(wchar_t *dest, 
413
 
           int32_t destCapacity,
414
 
           int32_t *pDestLength,
415
 
           const UChar *src, 
416
 
           int32_t srcLength,
417
 
           UErrorCode *pErrorCode){
418
 
 
419
 
    char stackBuffer [_STACK_BUFFER_CAPACITY];
420
 
    char* tempBuf = stackBuffer;
421
 
    int32_t tempBufCapacity = _STACK_BUFFER_CAPACITY;
422
 
    char* tempBufLimit = stackBuffer + tempBufCapacity;
423
 
    UConverter* conv = NULL;
424
 
    char* saveBuf = tempBuf;
425
 
    wchar_t* intTarget=NULL;
426
 
    int32_t intTargetCapacity=0;
427
 
    int count=0,retVal=0;
428
 
    
429
 
    const UChar *pSrcLimit =NULL;
430
 
    const UChar *pSrc = src;
431
 
 
432
 
    conv = u_getDefaultConverter(pErrorCode);
433
 
    
434
 
    if(U_FAILURE(*pErrorCode)){
435
 
        return NULL;
436
 
    }
437
 
    
438
 
    if(srcLength == -1){
439
 
        srcLength = u_strlen(pSrc);
440
 
    }
441
 
    
442
 
    pSrcLimit = pSrc + srcLength;
443
 
 
444
 
    for(;;) {
445
 
        /* reset the error state */
446
 
        *pErrorCode = U_ZERO_ERROR;
447
 
 
448
 
        /* convert to chars using default converter */
449
 
        ucnv_fromUnicode(conv,&tempBuf,tempBufLimit,&pSrc,pSrcLimit,NULL,(UBool)(pSrc==pSrcLimit),pErrorCode);
450
 
        count =(tempBuf - saveBuf);
451
 
        
452
 
        /* This should rarely occur */
453
 
        if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR){
454
 
            tempBuf = saveBuf;
455
 
            
456
 
            /* we dont have enough room on the stack grow the buffer */
457
 
            if(!u_growAnyBufferFromStatic(stackBuffer,(void**) &tempBuf, &tempBufCapacity, 
458
 
                (2*(pSrcLimit-pSrc)+100), count,sizeof(char))){
459
 
                goto cleanup;
460
 
            }
461
 
          
462
 
           saveBuf = tempBuf;
463
 
           tempBufLimit = tempBuf + tempBufCapacity;
464
 
           tempBuf = tempBuf + count;
465
 
 
466
 
        } else {
467
 
            break;
468
 
        }
469
 
    }
470
 
 
471
 
    if(U_FAILURE(*pErrorCode)){
472
 
        goto cleanup;
473
 
    }
474
 
 
475
 
    /* done with conversion null terminate the char buffer */
476
 
    if(count>=tempBufCapacity){
477
 
        tempBuf = saveBuf;
478
 
        /* we dont have enough room on the stack grow the buffer */
479
 
        if(!u_growAnyBufferFromStatic(stackBuffer,(void**) &tempBuf, &tempBufCapacity, 
480
 
            tempBufCapacity-count+1, count,sizeof(char))){
481
 
            goto cleanup;
482
 
        }              
483
 
       saveBuf = tempBuf;
484
 
    }
485
 
    
486
 
    saveBuf[count]=0;
487
 
      
488
 
 
489
 
    /* allocate more space than required 
490
 
     * here we assume that every char requires 
491
 
     * no more than 2 wchar_ts
492
 
     */
493
 
    intTargetCapacity =  (count*2+1) /*for null termination */;
494
 
    intTarget = (wchar_t*)uprv_malloc( intTargetCapacity * sizeof(wchar_t) );
495
 
 
496
 
    if(intTarget){
497
 
 
498
 
        int32_t nulLen = 0;
499
 
        int32_t remaining = intTargetCapacity;
500
 
        wchar_t* pIntTarget=intTarget;
501
 
        tempBuf = saveBuf;
502
 
        
503
 
        /* now convert the mbs to wcs */
504
 
        for(;;){
505
 
            
506
 
            /* we can call the system API since we are sure that
507
 
             * there is atleast 1 null in the input
508
 
             */
509
 
            retVal = uprv_mbstowcs(pIntTarget,(tempBuf+nulLen),remaining);
510
 
            
511
 
            if(retVal==-1){
512
 
                *pErrorCode = U_INVALID_CHAR_FOUND;
513
 
                break;
514
 
            }else if(retVal== remaining){/* should never occur */
515
 
                int numWritten = (pIntTarget-intTarget);
516
 
                u_growAnyBufferFromStatic(NULL,(void**) &intTarget,
517
 
                                          &intTargetCapacity,
518
 
                                          intTargetCapacity*2,
519
 
                                          numWritten,
520
 
                                          sizeof(wchar_t));
521
 
                pIntTarget = intTarget;
522
 
                remaining=intTargetCapacity;
523
 
 
524
 
                if(nulLen!=count){ /*there are embedded nulls*/
525
 
                    pIntTarget+=numWritten;
526
 
                    remaining-=numWritten;
527
 
                }
528
 
 
529
 
            }else{
530
 
                /*scan for nulls */
531
 
                /* we donot check for limit since tempBuf is null terminated */
532
 
                while(tempBuf[nulLen++] != 0){
533
 
                }
534
 
                pIntTarget = pIntTarget + retVal+1;
535
 
                remaining -=(retVal+1);
536
 
            
537
 
                /* check if we have reached the source limit*/
538
 
                if(nulLen>=(count)){
539
 
                    break;
540
 
                }
541
 
            }
542
 
        }
543
 
        count = (int32_t)(pIntTarget-intTarget);
544
 
       
545
 
        if(0 < count && count <= destCapacity){
546
 
            uprv_memcpy(dest,intTarget,count*sizeof(wchar_t));
547
 
        }  
548
 
 
549
 
        if(pDestLength){
550
 
            *pDestLength = count;
551
 
        }
552
 
 
553
 
        /* free the allocated memory */
554
 
        uprv_free(intTarget);
555
 
 
556
 
    }else{
557
 
        *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
558
 
    }
559
 
cleanup:
560
 
    /* are we still using stack buffer */
561
 
    if(stackBuffer != saveBuf){
562
 
        uprv_free(saveBuf);
563
 
    }
564
 
    u_terminateWChars(dest,destCapacity,count,pErrorCode);
565
 
 
566
 
    u_releaseDefaultConverter(conv);
567
 
 
568
 
    return dest;
569
 
}
570
 
#endif
571
 
 
572
 
U_CAPI wchar_t* U_EXPORT2
573
 
u_strToWCS(wchar_t *dest, 
574
 
           int32_t destCapacity,
575
 
           int32_t *pDestLength,
576
 
           const UChar *src, 
577
 
           int32_t srcLength,
578
 
           UErrorCode *pErrorCode){
579
 
    
580
 
    /* args check */
581
 
    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)){
582
 
        return NULL;
583
 
    }
584
 
        
585
 
    if((srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
586
 
        *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
587
 
        return NULL;
588
 
    }
589
 
    
590
 
#ifdef U_WCHAR_IS_UTF16
591
 
    /* wchar_t is UTF-16 just do a memcpy */
592
 
    if(srcLength == -1){
593
 
        srcLength = u_strlen(src);
594
 
    }
595
 
    if(0 < srcLength && srcLength <= destCapacity){
596
 
        uprv_memcpy(dest,src,srcLength*U_SIZEOF_UCHAR);
597
 
    }
598
 
    if(pDestLength){
599
 
       *pDestLength = srcLength;
600
 
    }
601
 
 
602
 
    u_terminateUChars(dest,destCapacity,srcLength,pErrorCode);
603
 
 
604
 
    return dest;
605
 
 
606
 
#elif defined U_WCHAR_IS_UTF32
607
 
    
608
 
    return u_strToUTF32(dest,destCapacity,pDestLength,src,srcLength,pErrorCode);
609
 
 
610
 
#else
611
 
    
612
 
    return _strToWCS(dest,destCapacity,pDestLength,src,srcLength, pErrorCode);
613
 
    
614
 
#endif
615
 
}
616
 
 
617
 
#if !defined(U_WCHAR_IS_UTF16) && !defined(U_WCHAR_IS_UTF32)
618
 
/* helper function */
619
 
static UChar* 
620
 
_strFromWCS( UChar   *dest,
621
 
             int32_t destCapacity, 
622
 
             int32_t *pDestLength,
623
 
             const wchar_t *src,
624
 
             int32_t srcLength,
625
 
             UErrorCode *pErrorCode){
626
 
 
627
 
    int32_t retVal =0, count =0 ;
628
 
    UConverter* conv = NULL;
629
 
    UChar* pTarget = NULL;
630
 
    UChar* pTargetLimit = NULL;
631
 
    UChar* target = NULL;
632
 
    
633
 
    UChar uStack [_STACK_BUFFER_CAPACITY];
634
 
 
635
 
    wchar_t wStack[_STACK_BUFFER_CAPACITY];
636
 
    wchar_t* pWStack = wStack;
637
 
 
638
 
 
639
 
    char cStack[_STACK_BUFFER_CAPACITY];
640
 
    int32_t cStackCap = _STACK_BUFFER_CAPACITY;
641
 
    char* pCSrc=cStack;
642
 
    char* pCSave=pCSrc;
643
 
    char* pCSrcLimit=NULL;
644
 
 
645
 
    const wchar_t* pSrc = src;
646
 
    const wchar_t* pSrcLimit = NULL;
647
 
 
648
 
    if(srcLength ==-1){
649
 
        /* if the wchar_t source is null terminated we can safely
650
 
         * assume that there are no embedded nulls, this is a fast
651
 
         * path for null terminated strings.
652
 
         */
653
 
        for(;;){
654
 
            /* convert wchars  to chars */
655
 
            retVal = uprv_wcstombs(pCSrc,src, cStackCap);
656
 
    
657
 
            if(retVal == -1){
658
 
                *pErrorCode = U_ILLEGAL_CHAR_FOUND;
659
 
                goto cleanup;
660
 
            }else if(retVal == cStackCap){
661
 
                /* Should rarely occur */
662
 
                u_growAnyBufferFromStatic(cStack,(void**)&pCSrc,&cStackCap,
663
 
                    cStackCap*2,0,sizeof(char));
664
 
                pCSave = pCSrc;
665
 
            }else{
666
 
                /* converted every thing */
667
 
                pCSrc = pCSrc+retVal;
668
 
                break;
669
 
            }
670
 
        }
671
 
        
672
 
    }else{
673
 
        /* here the source is not null terminated 
674
 
         * so it may have nulls embeded and we need to
675
 
         * do some extra processing 
676
 
         */
677
 
        int32_t remaining =cStackCap;
678
 
        
679
 
        pSrcLimit = src + srcLength;
680
 
 
681
 
        for(;;){
682
 
            register int32_t nulLen = 0;
683
 
 
684
 
            /* find nulls in the string */
685
 
            while(nulLen<srcLength && pSrc[nulLen++]!=0){
686
 
            }
687
 
 
688
 
            if((pSrc+nulLen) < pSrcLimit){
689
 
                /* check if we have enough room in pCSrc */
690
 
                if(remaining < (nulLen * MB_CUR_MAX)){
691
 
                    /* should rarely occur */
692
 
                    int32_t len = (pCSrc-pCSave);
693
 
                    pCSrc = pCSave;
694
 
                    /* we do not have enough room so grow the buffer*/
695
 
                    u_growAnyBufferFromStatic(cStack,(void**)&pCSrc,&cStackCap,
696
 
                           2*cStackCap+(nulLen*MB_CUR_MAX),len,sizeof(char));
697
 
 
698
 
                    pCSave = pCSrc;
699
 
                    pCSrc = pCSave+len;
700
 
                    remaining = cStackCap-(pCSrc - pCSave);
701
 
                }
702
 
 
703
 
                /* we have found a null  so convert the 
704
 
                 * chunk from begining of non-null char to null
705
 
                 */
706
 
                retVal = uprv_wcstombs(pCSrc,pSrc,remaining);
707
 
 
708
 
                if(retVal==-1){
709
 
                    /* an error occurred bail out */
710
 
                    *pErrorCode = U_ILLEGAL_CHAR_FOUND;
711
 
                    goto cleanup;
712
 
                }
713
 
 
714
 
                pCSrc += retVal+1 /* already null terminated */;
715
 
 
716
 
                pSrc += nulLen; /* skip past the null */
717
 
                srcLength-=nulLen; /* decrement the srcLength */
718
 
                remaining -= (pCSrc-pCSave);
719
 
 
720
 
 
721
 
            }else{
722
 
                /* the source is not null terminated and we are 
723
 
                 * end of source so we copy the source to a temp buffer
724
 
                 * null terminate it and convert wchar_ts to chars
725
 
                 */
726
 
                if(nulLen > _STACK_BUFFER_CAPACITY){
727
 
                    /* Should rarely occcur */
728
 
                    /* allocate new buffer buffer */
729
 
                    pWStack =(wchar_t*) uprv_malloc(sizeof(wchar_t) * nulLen);
730
 
                    if(pWStack==NULL){
731
 
                        *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
732
 
                        goto cleanup;
733
 
                    }
734
 
                }
735
 
                if(nulLen>0){
736
 
                    /* copy the contents to tempStack */
737
 
                    uprv_memcpy(pWStack,pSrc,nulLen*sizeof(wchar_t));
738
 
                }
739
 
            
740
 
                /* null terminate the tempBuffer */
741
 
                pWStack[nulLen] =0 ;
742
 
            
743
 
                if(remaining < (nulLen * MB_CUR_MAX)){
744
 
                    /* Should rarely occur */
745
 
                    int32_t len = (pCSrc-pCSave);
746
 
                    pCSrc = pCSave;
747
 
                    /* we do not have enough room so grow the buffer*/
748
 
                    u_growAnyBufferFromStatic(cStack,(void**)&pCSrc,&cStackCap,
749
 
                           cStackCap+(nulLen*MB_CUR_MAX),len,sizeof(char));
750
 
 
751
 
                    pCSave = pCSrc;
752
 
                    pCSrc = pCSave+len;
753
 
                    remaining = cStackCap-(pCSrc - pCSave);
754
 
                }
755
 
                /* convert to chars */
756
 
                retVal = uprv_wcstombs(pCSrc,pWStack,remaining);
757
 
            
758
 
                pCSrc += retVal +1;
759
 
                pSrc  += nulLen;
760
 
                srcLength-=nulLen; /* decrement the srcLength */
761
 
                break;
762
 
            }
763
 
        }
764
 
    }
765
 
 
766
 
    /* OK..now we have converted from wchar_ts to chars now 
767
 
     * convert chars to UChars 
768
 
     */
769
 
    pCSrcLimit = pCSrc;
770
 
    pCSrc = pCSave;
771
 
    pTarget = target= dest;
772
 
    pTargetLimit = dest + destCapacity;    
773
 
    
774
 
    conv= u_getDefaultConverter(pErrorCode);
775
 
    
776
 
    if(U_FAILURE(*pErrorCode)|| conv==NULL){
777
 
        goto cleanup;
778
 
    }
779
 
    
780
 
    for(;;) {
781
 
        
782
 
        *pErrorCode = U_ZERO_ERROR;
783
 
        
784
 
        /* convert to stack buffer*/
785
 
        ucnv_toUnicode(conv,&pTarget,pTargetLimit,(const char**)&pCSrc,pCSrcLimit,NULL,(UBool)(pCSrc==pCSrcLimit),pErrorCode);
786
 
        
787
 
        /* increment count to number written to stack */
788
 
        count+= pTarget - target;
789
 
        
790
 
        if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR){
791
 
            target = uStack;
792
 
            pTarget = uStack;
793
 
            pTargetLimit = uStack + _STACK_BUFFER_CAPACITY;
794
 
        } else {
795
 
            break;
796
 
        }
797
 
        
798
 
    }
799
 
    
800
 
    if(pDestLength){
801
 
        *pDestLength =count;
802
 
    }
803
 
 
804
 
    u_terminateUChars(dest,destCapacity,count,pErrorCode);
805
 
    
806
 
cleanup:
807
 
 
808
 
    if(cStack != pCSave){
809
 
        uprv_free(pCSave);
810
 
    }
811
 
 
812
 
    if(wStack != pWStack){
813
 
        uprv_free(pWStack);
814
 
    }
815
 
    
816
 
    u_releaseDefaultConverter(conv);
817
 
 
818
 
    return dest;
819
 
}
820
 
#endif
821
 
 
822
 
U_CAPI UChar* U_EXPORT2
823
 
u_strFromWCS(UChar   *dest,
824
 
             int32_t destCapacity, 
825
 
             int32_t *pDestLength,
826
 
             const wchar_t *src,
827
 
             int32_t srcLength,
828
 
             UErrorCode *pErrorCode)
829
 
{
830
 
 
831
 
    /* args check */
832
 
    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)){
833
 
        return NULL;
834
 
    }
835
 
        
836
 
    if((srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
837
 
        *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
838
 
        return NULL;
839
 
    }
840
 
 
841
 
#ifdef U_WCHAR_IS_UTF16
842
 
    /* wchar_t is UTF-16 just do a memcpy */
843
 
    if(srcLength == -1){
844
 
        srcLength = u_strlen(src);
845
 
    }
846
 
    if(0 < srcLength && srcLength <= destCapacity){
847
 
        uprv_memcpy(dest,src,srcLength*U_SIZEOF_UCHAR);
848
 
    }
849
 
    if(pDestLength){
850
 
       *pDestLength = srcLength;
851
 
    }
852
 
 
853
 
    u_terminateUChars(dest,destCapacity,srcLength,pErrorCode);
854
 
 
855
 
    return dest;
856
 
 
857
 
#elif defined U_WCHAR_IS_UTF32
858
 
    
859
 
    return u_strFromUTF32(dest,destCapacity,pDestLength,src,srcLength,pErrorCode);
860
 
 
861
 
#else
862
 
 
863
 
    return _strFromWCS(dest,destCapacity,pDestLength,src,srcLength,pErrorCode);  
864
 
 
865
 
#endif
866
 
 
867
 
}