114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project/*
214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*******************************************************************************
314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*
4103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius*   Copyright (C) 2001-2012, International Business Machines
514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*   Corporation and others.  All Rights Reserved.
614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*
714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*******************************************************************************
8103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius*   file name:  ustr_wcs.cpp
914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*   encoding:   US-ASCII
1014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*   tab size:   8 (not used)
1114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*   indentation:4
1214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*
1314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*   created on: 2004sep07
1414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*   created by: Markus W. Scherer
1514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*
1614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*   u_strToWCS() and u_strFromWCS() functions
1714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*   moved here from ustrtrns.c for better modularization.
1814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project*/
1914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
2014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#include "unicode/utypes.h"
2114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#include "unicode/ustring.h"
2214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#include "cstring.h"
2314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#include "cwchar.h"
2414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#include "cmemory.h"
2514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#include "ustr_imp.h"
2614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#include "ustr_cnv.h"
2714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
2814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#if defined(U_WCHAR_IS_UTF16) || defined(U_WCHAR_IS_UTF32) || !UCONFIG_NO_CONVERSION
2914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
3014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#define _STACK_BUFFER_CAPACITY 1000
3114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#define _BUFFER_CAPACITY_MULTIPLIER 2
3214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
3314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#if !defined(U_WCHAR_IS_UTF16) && !defined(U_WCHAR_IS_UTF32)
34103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// TODO: We should use CharString for char buffers and UnicodeString for UChar buffers.
35103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Then we could change this to work only with wchar_t buffers.
36103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic inline UBool
3714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Projectu_growAnyBufferFromStatic(void *context,
3814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                       void **pBuffer, int32_t *pCapacity, int32_t reqCapacity,
3914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                       int32_t length, int32_t size) {
40103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // Use char* not void* to avoid the compiler's strict-aliasing assumptions
41103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // and related warnings.
42103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    char *newBuffer=(char *)uprv_malloc(reqCapacity*size);
4314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(newBuffer!=NULL) {
4414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        if(length>0) {
4514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            uprv_memcpy(newBuffer, *pBuffer, length*size);
4614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        }
4714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        *pCapacity=reqCapacity;
4814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    } else {
4914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        *pCapacity=0;
5014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
5114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
5214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    /* release the old pBuffer if it was not statically allocated */
53103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if(*pBuffer!=(char *)context) {
5414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        uprv_free(*pBuffer);
5514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
5614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
5714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    *pBuffer=newBuffer;
5814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    return (UBool)(newBuffer!=NULL);
5914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project}
6014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
6114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project/* helper function */
6214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Projectstatic wchar_t*
6314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project_strToWCS(wchar_t *dest,
6414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project           int32_t destCapacity,
6514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project           int32_t *pDestLength,
6614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project           const UChar *src,
6714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project           int32_t srcLength,
6814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project           UErrorCode *pErrorCode){
6914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
7014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    char stackBuffer [_STACK_BUFFER_CAPACITY];
7114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    char* tempBuf = stackBuffer;
7214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    int32_t tempBufCapacity = _STACK_BUFFER_CAPACITY;
7314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    char* tempBufLimit = stackBuffer + tempBufCapacity;
7414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    UConverter* conv = NULL;
7514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    char* saveBuf = tempBuf;
7614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    wchar_t* intTarget=NULL;
7714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    int32_t intTargetCapacity=0;
7814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    int count=0,retVal=0;
7914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
8014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    const UChar *pSrcLimit =NULL;
8114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    const UChar *pSrc = src;
8214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
8314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    conv = u_getDefaultConverter(pErrorCode);
8414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
8514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(U_FAILURE(*pErrorCode)){
8614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        return NULL;
8714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
8814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
8914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(srcLength == -1){
9014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        srcLength = u_strlen(pSrc);
9114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
9214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
9314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    pSrcLimit = pSrc + srcLength;
9414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
9514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    for(;;) {
9614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        /* reset the error state */
9714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        *pErrorCode = U_ZERO_ERROR;
9814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
9914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        /* convert to chars using default converter */
10014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        ucnv_fromUnicode(conv,&tempBuf,tempBufLimit,&pSrc,pSrcLimit,NULL,(UBool)(pSrc==pSrcLimit),pErrorCode);
10114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        count =(tempBuf - saveBuf);
10214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
10314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        /* This should rarely occur */
10414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR){
10514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            tempBuf = saveBuf;
10614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
10714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            /* we dont have enough room on the stack grow the buffer */
108103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            int32_t newCapacity = 2 * srcLength;
109103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            if(newCapacity <= tempBufCapacity) {
110103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                newCapacity = _BUFFER_CAPACITY_MULTIPLIER * tempBufCapacity;
111103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            }
112103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            if(!u_growAnyBufferFromStatic(stackBuffer,(void**) &tempBuf, &tempBufCapacity,
113103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    newCapacity, count, 1)) {
11414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                goto cleanup;
11514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            }
11614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
11714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project           saveBuf = tempBuf;
11814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project           tempBufLimit = tempBuf + tempBufCapacity;
11914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project           tempBuf = tempBuf + count;
12014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
12114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        } else {
12214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            break;
12314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        }
12414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
12514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
12614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(U_FAILURE(*pErrorCode)){
12714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        goto cleanup;
12814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
12914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
13014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    /* done with conversion null terminate the char buffer */
13114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(count>=tempBufCapacity){
13214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        tempBuf = saveBuf;
13314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        /* we dont have enough room on the stack grow the buffer */
13414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        if(!u_growAnyBufferFromStatic(stackBuffer,(void**) &tempBuf, &tempBufCapacity,
135103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                count+1, count, 1)) {
13614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            goto cleanup;
13714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        }
13814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project       saveBuf = tempBuf;
13914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
14014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
14114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    saveBuf[count]=0;
14214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
14314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
14414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    /* allocate more space than required
14514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project     * here we assume that every char requires
14614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project     * no more than 2 wchar_ts
14714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project     */
14814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    intTargetCapacity =  (count * _BUFFER_CAPACITY_MULTIPLIER + 1) /*for null termination */;
14914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    intTarget = (wchar_t*)uprv_malloc( intTargetCapacity * sizeof(wchar_t) );
15014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
15114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(intTarget){
15214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
15314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        int32_t nulLen = 0;
15414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        int32_t remaining = intTargetCapacity;
15514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        wchar_t* pIntTarget=intTarget;
15614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        tempBuf = saveBuf;
15714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
15814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        /* now convert the mbs to wcs */
15914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        for(;;){
16014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
16114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            /* we can call the system API since we are sure that
16214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project             * there is atleast 1 null in the input
16314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project             */
16414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            retVal = uprv_mbstowcs(pIntTarget,(tempBuf+nulLen),remaining);
16514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
16614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            if(retVal==-1){
16714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                *pErrorCode = U_INVALID_CHAR_FOUND;
16814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                break;
16914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            }else if(retVal== remaining){/* should never occur */
17014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                int numWritten = (pIntTarget-intTarget);
17114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                u_growAnyBufferFromStatic(NULL,(void**) &intTarget,
17214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                                          &intTargetCapacity,
17314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                                          intTargetCapacity * _BUFFER_CAPACITY_MULTIPLIER,
17414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                                          numWritten,
17514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                                          sizeof(wchar_t));
17614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                pIntTarget = intTarget;
17714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                remaining=intTargetCapacity;
17814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
17914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                if(nulLen!=count){ /*there are embedded nulls*/
18014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    pIntTarget+=numWritten;
18114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    remaining-=numWritten;
18214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                }
18314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
18414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            }else{
18514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                int32_t nulVal;
18614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                /*scan for nulls */
18714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                /* we donot check for limit since tempBuf is null terminated */
18814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                while(tempBuf[nulLen++] != 0){
18914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                }
19014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                nulVal = (nulLen < srcLength) ? 1 : 0;
19114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                pIntTarget = pIntTarget + retVal+nulVal;
19214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                remaining -=(retVal+nulVal);
19314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
19414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                /* check if we have reached the source limit*/
19514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                if(nulLen>=(count)){
19614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    break;
19714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                }
19814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            }
19914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        }
20014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        count = (int32_t)(pIntTarget-intTarget);
20114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
20214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        if(0 < count && count <= destCapacity){
20314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            uprv_memcpy(dest,intTarget,count*sizeof(wchar_t));
20414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        }
20514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
20614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        if(pDestLength){
20714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            *pDestLength = count;
20814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        }
20914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
21014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        /* free the allocated memory */
21114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        uprv_free(intTarget);
21214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
21314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }else{
21414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
21514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
21614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Projectcleanup:
21714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    /* are we still using stack buffer */
21814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(stackBuffer != saveBuf){
21914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        uprv_free(saveBuf);
22014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
22114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    u_terminateWChars(dest,destCapacity,count,pErrorCode);
22214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
22314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    u_releaseDefaultConverter(conv);
22414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
22514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    return dest;
22614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project}
22714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#endif
22814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
22914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source ProjectU_CAPI wchar_t* U_EXPORT2
23014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Projectu_strToWCS(wchar_t *dest,
23114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project           int32_t destCapacity,
23214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project           int32_t *pDestLength,
23314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project           const UChar *src,
23414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project           int32_t srcLength,
23514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project           UErrorCode *pErrorCode){
23614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
23714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    /* args check */
23814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)){
23914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        return NULL;
24014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
24114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
24250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if( (src==NULL && srcLength!=0) || srcLength < -1 ||
24350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        (destCapacity<0) || (dest == NULL && destCapacity > 0)
24450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ) {
24514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
24614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        return NULL;
24714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
24814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
24914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#ifdef U_WCHAR_IS_UTF16
25014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    /* wchar_t is UTF-16 just do a memcpy */
25114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(srcLength == -1){
25214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        srcLength = u_strlen(src);
25314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
25414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(0 < srcLength && srcLength <= destCapacity){
25514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        uprv_memcpy(dest,src,srcLength*U_SIZEOF_UCHAR);
25614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
25714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(pDestLength){
25814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project       *pDestLength = srcLength;
25914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
26014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
26114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    u_terminateUChars(dest,destCapacity,srcLength,pErrorCode);
26214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
26314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    return dest;
26414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
26514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#elif defined U_WCHAR_IS_UTF32
26614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
26714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    return (wchar_t*)u_strToUTF32((UChar32*)dest, destCapacity, pDestLength,
26814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                                  src, srcLength, pErrorCode);
26914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
27014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#else
27114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
27214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    return _strToWCS(dest,destCapacity,pDestLength,src,srcLength, pErrorCode);
27314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
27414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#endif
27514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
27614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project}
27714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
27814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#if !defined(U_WCHAR_IS_UTF16) && !defined(U_WCHAR_IS_UTF32)
27914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project/* helper function */
28014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Projectstatic UChar*
28114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project_strFromWCS( UChar   *dest,
28214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project             int32_t destCapacity,
28314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project             int32_t *pDestLength,
28414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project             const wchar_t *src,
28514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project             int32_t srcLength,
28614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project             UErrorCode *pErrorCode)
28714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project{
28814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    int32_t retVal =0, count =0 ;
28914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    UConverter* conv = NULL;
29014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    UChar* pTarget = NULL;
29114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    UChar* pTargetLimit = NULL;
29214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    UChar* target = NULL;
29314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
29414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    UChar uStack [_STACK_BUFFER_CAPACITY];
29514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
29614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    wchar_t wStack[_STACK_BUFFER_CAPACITY];
29714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    wchar_t* pWStack = wStack;
29814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
29914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
30014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    char cStack[_STACK_BUFFER_CAPACITY];
30114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    int32_t cStackCap = _STACK_BUFFER_CAPACITY;
30214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    char* pCSrc=cStack;
30314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    char* pCSave=pCSrc;
30414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    char* pCSrcLimit=NULL;
30514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
30614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    const wchar_t* pSrc = src;
30714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    const wchar_t* pSrcLimit = NULL;
30814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
30914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(srcLength ==-1){
31014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        /* if the wchar_t source is null terminated we can safely
31114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project         * assume that there are no embedded nulls, this is a fast
31214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project         * path for null terminated strings.
31314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project         */
31414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        for(;;){
31514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            /* convert wchars  to chars */
31614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            retVal = uprv_wcstombs(pCSrc,src, cStackCap);
31714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
31814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            if(retVal == -1){
31914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                *pErrorCode = U_ILLEGAL_CHAR_FOUND;
32014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                goto cleanup;
32114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            }else if(retVal >= (cStackCap-1)){
32214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                /* Should rarely occur */
32314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                u_growAnyBufferFromStatic(cStack,(void**)&pCSrc,&cStackCap,
32414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    cStackCap * _BUFFER_CAPACITY_MULTIPLIER, 0, sizeof(char));
32514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                pCSave = pCSrc;
32614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            }else{
32714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                /* converted every thing */
32814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                pCSrc = pCSrc+retVal;
32914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                break;
33014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            }
33114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        }
33214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
33314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }else{
33414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        /* here the source is not null terminated
33514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project         * so it may have nulls embeded and we need to
33614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project         * do some extra processing
33714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project         */
33814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        int32_t remaining =cStackCap;
33914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
34014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        pSrcLimit = src + srcLength;
34114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
34214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        for(;;){
34314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            register int32_t nulLen = 0;
34414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
34514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            /* find nulls in the string */
34614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            while(nulLen<srcLength && pSrc[nulLen++]!=0){
34714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            }
34814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
34914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            if((pSrc+nulLen) < pSrcLimit){
35014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                /* check if we have enough room in pCSrc */
35114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                if(remaining < (nulLen * MB_CUR_MAX)){
35214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    /* should rarely occur */
35314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    int32_t len = (pCSrc-pCSave);
35414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    pCSrc = pCSave;
35514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    /* we do not have enough room so grow the buffer*/
35614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    u_growAnyBufferFromStatic(cStack,(void**)&pCSrc,&cStackCap,
35714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                           _BUFFER_CAPACITY_MULTIPLIER*cStackCap+(nulLen*MB_CUR_MAX),len,sizeof(char));
35814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
35914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    pCSave = pCSrc;
36014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    pCSrc = pCSave+len;
36114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    remaining = cStackCap-(pCSrc - pCSave);
36214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                }
36314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
36414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                /* we have found a null  so convert the
36514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                 * chunk from begining of non-null char to null
36614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                 */
36714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                retVal = uprv_wcstombs(pCSrc,pSrc,remaining);
36814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
36914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                if(retVal==-1){
37014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    /* an error occurred bail out */
37114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    *pErrorCode = U_ILLEGAL_CHAR_FOUND;
37214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    goto cleanup;
37314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                }
37414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
37514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                pCSrc += retVal+1 /* already null terminated */;
37614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
37714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                pSrc += nulLen; /* skip past the null */
37814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                srcLength-=nulLen; /* decrement the srcLength */
37914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                remaining -= (pCSrc-pCSave);
38014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
38114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
38214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            }else{
38314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                /* the source is not null terminated and we are
38414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                 * end of source so we copy the source to a temp buffer
38514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                 * null terminate it and convert wchar_ts to chars
38614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                 */
38714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                if(nulLen >= _STACK_BUFFER_CAPACITY){
38814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    /* Should rarely occcur */
38914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    /* allocate new buffer buffer */
39014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    pWStack =(wchar_t*) uprv_malloc(sizeof(wchar_t) * (nulLen + 1));
39114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    if(pWStack==NULL){
39214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                        *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
39314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                        goto cleanup;
39414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    }
39514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                }
39614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                if(nulLen>0){
39714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    /* copy the contents to tempStack */
39814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    uprv_memcpy(pWStack,pSrc,nulLen*sizeof(wchar_t));
39914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                }
40014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
40114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                /* null terminate the tempBuffer */
40214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                pWStack[nulLen] =0 ;
40314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
40414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                if(remaining < (nulLen * MB_CUR_MAX)){
40514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    /* Should rarely occur */
40614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    int32_t len = (pCSrc-pCSave);
40714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    pCSrc = pCSave;
40814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    /* we do not have enough room so grow the buffer*/
40914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    u_growAnyBufferFromStatic(cStack,(void**)&pCSrc,&cStackCap,
41014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                           cStackCap+(nulLen*MB_CUR_MAX),len,sizeof(char));
41114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
41214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    pCSave = pCSrc;
41314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    pCSrc = pCSave+len;
41414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                    remaining = cStackCap-(pCSrc - pCSave);
41514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                }
41614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                /* convert to chars */
41714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                retVal = uprv_wcstombs(pCSrc,pWStack,remaining);
41814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
41914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                pCSrc += retVal;
42014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                pSrc  += nulLen;
42114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                srcLength-=nulLen; /* decrement the srcLength */
42214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                break;
42314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            }
42414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        }
42514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
42614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
42714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    /* OK..now we have converted from wchar_ts to chars now
42814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project     * convert chars to UChars
42914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project     */
43014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    pCSrcLimit = pCSrc;
43114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    pCSrc = pCSave;
43214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    pTarget = target= dest;
43314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    pTargetLimit = dest + destCapacity;
43414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
43514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    conv= u_getDefaultConverter(pErrorCode);
43614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
43714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(U_FAILURE(*pErrorCode)|| conv==NULL){
43814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        goto cleanup;
43914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
44014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
44114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    for(;;) {
44214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
44314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        *pErrorCode = U_ZERO_ERROR;
44414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
44514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        /* convert to stack buffer*/
44614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        ucnv_toUnicode(conv,&pTarget,pTargetLimit,(const char**)&pCSrc,pCSrcLimit,NULL,(UBool)(pCSrc==pCSrcLimit),pErrorCode);
44714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
44814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        /* increment count to number written to stack */
44914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        count+= pTarget - target;
45014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
45114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR){
45214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            target = uStack;
45314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            pTarget = uStack;
45414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            pTargetLimit = uStack + _STACK_BUFFER_CAPACITY;
45514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        } else {
45614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project            break;
45714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        }
45814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
45914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
46014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
46114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(pDestLength){
46214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        *pDestLength =count;
46314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
46414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
46514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    u_terminateUChars(dest,destCapacity,count,pErrorCode);
46614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
46714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Projectcleanup:
46814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
46914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(cStack != pCSave){
47014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        uprv_free(pCSave);
47114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
47214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
47314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(wStack != pWStack){
47414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        uprv_free(pWStack);
47514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
47614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
47714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    u_releaseDefaultConverter(conv);
47814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
47914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    return dest;
48014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project}
48114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#endif
48214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
48314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source ProjectU_CAPI UChar* U_EXPORT2
48414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Projectu_strFromWCS(UChar   *dest,
48514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project             int32_t destCapacity,
48614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project             int32_t *pDestLength,
48714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project             const wchar_t *src,
48814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project             int32_t srcLength,
48914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project             UErrorCode *pErrorCode)
49014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project{
49114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
49214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    /* args check */
49314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)){
49414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        return NULL;
49514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
49650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
49750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if( (src==NULL && srcLength!=0) || srcLength < -1 ||
49850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        (destCapacity<0) || (dest == NULL && destCapacity > 0)
49950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ) {
50014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
50114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        return NULL;
50214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
50314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
50414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#ifdef U_WCHAR_IS_UTF16
50514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    /* wchar_t is UTF-16 just do a memcpy */
50614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(srcLength == -1){
50714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        srcLength = u_strlen(src);
50814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
50914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(0 < srcLength && srcLength <= destCapacity){
51014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project        uprv_memcpy(dest,src,srcLength*U_SIZEOF_UCHAR);
51114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
51214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    if(pDestLength){
51314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project       *pDestLength = srcLength;
51414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    }
51514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
51614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    u_terminateUChars(dest,destCapacity,srcLength,pErrorCode);
51714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
51814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    return dest;
51914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
52014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#elif defined U_WCHAR_IS_UTF32
52114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
52214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    return u_strFromUTF32(dest, destCapacity, pDestLength,
52314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project                          (UChar32*)src, srcLength, pErrorCode);
52414a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
52514a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#else
52614a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
52714a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project    return _strFromWCS(dest,destCapacity,pDestLength,src,srcLength,pErrorCode);
52814a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
52914a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#endif
53014a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
53114a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project}
53214a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project
53314a752ecbd4e9bccfc5fa0a6a5e9ace7747a4cbcThe Android Open Source Project#endif /* #if !defined(U_WCHAR_IS_UTF16) && !defined(U_WCHAR_IS_UTF32) && !UCONFIG_NO_CONVERSION */
534