Skip to content
Snippets Groups Projects
ICUTransService.cpp 34.8 KiB
Newer Older
    }

    //
    //  Get the length of the string to transcode. The Unicode string will
PeiYong Zhang's avatar
PeiYong Zhang committed
    //  almost always be no more chars than were in the source, so this is
    //  the best guess as to the storage needed.
    //
    const int32_t srcLen = (int32_t)strlen(toTranscode);

    // We need a target buffer of UChars to fill in
    UChar* targetBuf = 0;

    // Now lock while we do these calculations
    UErrorCode err = U_ZERO_ERROR;
    int32_t targetCap;
    {
        XMLMutexLock lockConverter(&fMutex);

        //
        //  Here we don't know what the target length will be so use 0 and
        //  expect an U_BUFFER_OVERFLOW_ERROR in which case it'd get resolved
        //  by the correct capacity value.
        //
        targetCap = ucnv_toUChars
        (
            fConverter
            , 0
            , 0
            , toTranscode
            , srcLen
            , &err
        );

        if (err != U_BUFFER_OVERFLOW_ERROR)
            return 0;

        err = U_ZERO_ERROR;
        targetBuf = (UChar*) manager->allocate((targetCap+1) * sizeof(UChar));//new UChar[targetCap + 1];
PeiYong Zhang's avatar
PeiYong Zhang committed
        ucnv_toUChars
        (
            fConverter
            , targetBuf
PeiYong Zhang's avatar
PeiYong Zhang committed
            , toTranscode
            , srcLen
            , &err
        );
    }

    if (U_FAILURE(err))
    {
        // Clean up if we got anything allocated
        manager->deallocate(targetBuf);//delete [] targetBuf;
PeiYong Zhang's avatar
PeiYong Zhang committed
        return 0;
    }

    // Cap it off to make sure
    targetBuf[targetCap] = 0;

    //
    //  If XMLCh and UChar are the same size, then we can return retVal
    //  as is. Else, we have to allocate another buffer and copy the data
    //  over to it.
    //
    XMLCh* actualRet;
    if (sizeof(XMLCh) == sizeof(UChar))
    {
        actualRet = (XMLCh*)targetBuf;
    }
     else
    {
        actualRet = convertToXMLCh(targetBuf, manager);
        manager->deallocate(targetBuf);//delete [] targetBuf;
PeiYong Zhang's avatar
PeiYong Zhang committed
    }
    return actualRet;
}


bool ICULCPTranscoder::transcode(const  char* const     toTranscode
                                ,       XMLCh* const    toFill
                                , const XMLSize_t       maxChars
PeiYong Zhang's avatar
PeiYong Zhang committed
{
    // Check for a couple of psycho corner cases
    if (!toTranscode || !maxChars)
    {
        toFill[0] = 0;
        return true;
    }

    if (!*toTranscode)
    {
        toFill[0] = 0;
        return true;
    }

    // We'll need this in a couple of places below
    const XMLSize_t srcLen = strlen(toTranscode);
PeiYong Zhang's avatar
PeiYong Zhang committed

    //
    //  Set up the target buffer. If XMLCh and UChar are not the same size
    //  then we have to use a temp buffer and convert over.
    //
    UChar* targetBuf;
    if (sizeof(XMLCh) == sizeof(UChar))
        targetBuf = (UChar*)toFill;
    else
        targetBuf = (UChar*) manager->allocate
        (
            (maxChars + 1) * sizeof(UChar)
        );//new UChar[maxChars + 1];
PeiYong Zhang's avatar
PeiYong Zhang committed

    //
    //  Use a faux block to enforce a lock on the converter, which will
    //  unlock immediately after its completed.
    //
    UErrorCode err = U_ZERO_ERROR;
    {
        XMLMutexLock lockConverter(&fMutex);
        ucnv_toUChars
        (
            fConverter
            , targetBuf
            , (int32_t)maxChars + 1
PeiYong Zhang's avatar
PeiYong Zhang committed
            , toTranscode
            , (int32_t)srcLen
PeiYong Zhang's avatar
PeiYong Zhang committed
            , &err
        );
    }

    if (U_FAILURE(err))
    {
        if (targetBuf != (UChar*)toFill)
            manager->deallocate(targetBuf);//delete [] targetBuf;
PeiYong Zhang's avatar
PeiYong Zhang committed
        return false;
    }

    // If the sizes are not the same, then copy the data over
    if (sizeof(XMLCh) != sizeof(UChar))
    {
        UChar* srcPtr = targetBuf;
        XMLCh* outPtr = toFill;
        while (*srcPtr)
            *outPtr++ = XMLCh(*srcPtr++);
        *outPtr = 0;

        // And delete the temp buffer
        manager->deallocate(targetBuf);//delete [] targetBuf;
PeiYong Zhang's avatar
PeiYong Zhang committed
    }

    return true;
}


bool ICULCPTranscoder::transcode(   const   XMLCh* const    toTranscode
                                    ,       char* const     toFill
                                    , const XMLSize_t       maxChars
PeiYong Zhang's avatar
PeiYong Zhang committed
{
    // Watch for a few psycho corner cases
    if (!toTranscode || !maxChars)
    {
        toFill[0] = 0;
        return true;
    }

    if (!*toTranscode)
    {
        toFill[0] = 0;
        return true;
    }

    //
    //  If XMLCh and UChar are not the same size, then we have to make a
    //  temp copy of the text to pass to ICU.
    //
    const UChar* actualSrc;
    UChar* ncActual = 0;
    if (sizeof(XMLCh) == sizeof(UChar))
    {
        actualSrc = (const UChar*)toTranscode;
    }
     else
    {
        // Allocate a non-const temp buf, but store it also in the actual
        ncActual = convertToUChar(toTranscode, 0, manager);
PeiYong Zhang's avatar
PeiYong Zhang committed
        actualSrc = ncActual;
    }

    // Insure that the temp buffer, if any, gets cleaned up via the nc pointer
    ArrayJanitor<UChar> janTmp(ncActual, manager);
PeiYong Zhang's avatar
PeiYong Zhang committed

    //
    //  Use a faux block to enforce a lock on the converter while we do this.
    //  It will be released immediately after its done.
    //
    UErrorCode err = U_ZERO_ERROR;
    int32_t targetCap;
    {
        XMLMutexLock lockConverter(&fMutex);
        targetCap = ucnv_fromUChars
        (
            fConverter
            , toFill
            , (int32_t)maxChars
PeiYong Zhang's avatar
PeiYong Zhang committed
            , actualSrc
            , -1
            , &err
        );
    }

    if (U_FAILURE(err))
        return false;

    toFill[targetCap] = 0;
    return true;
}
Tinny Ng's avatar
Tinny Ng committed

XERCES_CPP_NAMESPACE_END