Skip to content
Snippets Groups Projects
ICUTransService.cpp 38.2 KiB
Newer Older
        targetCap = ucnv_fromUChars
        (
            fConverter
            , retBuf
            , targetLen + 1
            , actualSrc
            , -1
            , &err
        );
    }

    // If targetLen is not enough then buffer overflow might occur
    if (err == U_BUFFER_OVERFLOW_ERROR)
    {
        //
        //  Reset the error, delete the old buffer, allocate a new one,
        //  and try again.
        //
        err = U_ZERO_ERROR;
        manager->deallocate(retBuf);//delete [] retBuf;
        retBuf = (char*) manager->allocate((targetCap + 1) * sizeof(char));//new char[targetCap + 1];

        // Lock again before we retry
        XMLMutexLock lockConverter(&fMutex);
        targetCap = ucnv_fromUChars
        (
            fConverter
            , retBuf
            , targetCap
            , actualSrc
            , -1
            , &err
        );
    }

    if (U_FAILURE(err))
    {
        manager->deallocate(retBuf);//delete [] retBuf;
        return 0;
    }

    // Cap it off and return
    retBuf[targetCap] = 0;
    return retBuf;
}

PeiYong Zhang's avatar
PeiYong Zhang committed
XMLCh* ICULCPTranscoder::transcode(const char* const toTranscode)
{
    // Watch for a few pyscho corner cases
    if (!toTranscode)
        return 0;

    if (!*toTranscode)
    {
        XMLCh* retVal = new XMLCh[1];
        retVal[0] = 0;
        return retVal;
    }

    //
    //  Get the length of the string to transcode. The Unicode string will
    //  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 = new UChar[targetCap + 1];
        ucnv_toUChars
        (
            fConverter
            , targetBuf
            , targetCap
            , toTranscode
            , srcLen
            , &err
        );
    }

    if (U_FAILURE(err))
    {
        // Clean up if we got anything allocated
        delete [] targetBuf;
        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);
        delete [] targetBuf;
    }
    return actualRet;
}

XMLCh* ICULCPTranscoder::transcode(const char* const toTranscode,
                                   MemoryManager* const manager)
{
    // Watch for a few pyscho corner cases
    if (!toTranscode)
        return 0;

    if (!*toTranscode)
    {
        XMLCh* retVal = (XMLCh*) manager->allocate(sizeof(XMLCh));//new XMLCh[1];
        retVal[0] = 0;
        return retVal;
    }

    //
    //  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
            , targetCap
            , 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 unsigned int    maxChars)
{
    // 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 unsigned int srcLen = strlen(toTranscode);

    //
    //  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*) XMLPlatformUtils::fgMemoryManager->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
            , maxChars + 1
            , toTranscode
            , srcLen
            , &err
        );
    }

    if (U_FAILURE(err))
    {
        if (targetBuf != (UChar*)toFill)
            XMLPlatformUtils::fgMemoryManager->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
        XMLPlatformUtils::fgMemoryManager->deallocate(targetBuf);//delete [] targetBuf;
PeiYong Zhang's avatar
PeiYong Zhang committed
    }

    return true;
}


bool ICULCPTranscoder::transcode(   const   XMLCh* const    toTranscode
                                    ,       char* const     toFill
                                    , const unsigned int    maxChars)
{
    // 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, XMLPlatformUtils::fgMemoryManager);
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, XMLPlatformUtils::fgMemoryManager);
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
            , maxChars
            , 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