Skip to content
Snippets Groups Projects
ICUTransService.cpp 37.7 KiB
Newer Older
PeiYong Zhang's avatar
PeiYong Zhang committed
/*
 * Copyright 1999-2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
PeiYong Zhang's avatar
PeiYong Zhang committed
 */

/*
 * $Id$
 */


// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/TranscodingException.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include "ICUTransService.hpp"
#include <string.h>
#include <unicode/uloc.h>
Tinny Ng's avatar
Tinny Ng committed
#include <unicode/uchar.h>
PeiYong Zhang's avatar
PeiYong Zhang committed
#include <unicode/ucnv.h>
#include <unicode/ucnv_err.h>
#include <unicode/ustring.h>
#include <unicode/udata.h>
#if (U_ICU_VERSION_MAJOR_NUM >= 2)
    #include <unicode/uclean.h>
#endif
PeiYong Zhang's avatar
PeiYong Zhang committed

#if !defined(XML_OS390) && !defined(XML_AS400) && !defined(XML_HPUX) && !defined(XML_PTX)
// Forward reference the symbol which points to the ICU converter data.
#if (U_ICU_VERSION_MAJOR_NUM < 2)
extern "C" const uint8_t U_IMPORT icudata_dat[];
#endif
#endif

Tinny Ng's avatar
Tinny Ng committed
XERCES_CPP_NAMESPACE_BEGIN
PeiYong Zhang's avatar
PeiYong Zhang committed

// ---------------------------------------------------------------------------
//  Local, const data
// ---------------------------------------------------------------------------
static const XMLCh gMyServiceId[] =
{
    chLatin_I, chLatin_C, chLatin_U, chNull
};

static const XMLCh gS390Id[] =
{
    chLatin_S, chDigit_3, chDigit_9, chDigit_0, chNull
};
PeiYong Zhang's avatar
PeiYong Zhang committed

static const XMLCh gs390Id[] =
{
    chLatin_s, chDigit_3, chDigit_9, chDigit_0, chNull
};
PeiYong Zhang's avatar
PeiYong Zhang committed

static const XMLCh gswaplfnlId[] =
{
    chComma, chLatin_s, chLatin_w, chLatin_a, chLatin_p,
    chLatin_l, chLatin_f, chLatin_n, chLatin_l, chNull
};
PeiYong Zhang's avatar
PeiYong Zhang committed
// ---------------------------------------------------------------------------
//  Local functions
// ---------------------------------------------------------------------------

//
//  When XMLCh and ICU's UChar are not the same size, we have to do a temp
//  conversion of all strings. These local helper methods make that easier.
//
static UChar* convertToUChar( const   XMLCh* const    toConvert
                            , const unsigned int    srcLen = 0
                            , MemoryManager* const manager = 0)
PeiYong Zhang's avatar
PeiYong Zhang committed
{
    const unsigned int actualLen = srcLen
                                   ? srcLen : XMLString::stringLen(toConvert);

    UChar* tmpBuf = (manager)
        ? (UChar*) manager->allocate((actualLen + 1) * sizeof(UChar))
		: new UChar[actualLen + 1];
PeiYong Zhang's avatar
PeiYong Zhang committed
    const XMLCh* srcPtr = toConvert;
    UChar* outPtr = tmpBuf;
    while (*srcPtr)
        *outPtr++ = UChar(*srcPtr++);
    *outPtr = 0;

    return tmpBuf;
}


static XMLCh* convertToXMLCh( const UChar* const toConvert,
                            MemoryManager* const manager = 0)
PeiYong Zhang's avatar
PeiYong Zhang committed
{
    const unsigned int srcLen = u_strlen(toConvert);
    XMLCh* retBuf = (manager)
        ? (XMLCh*) manager->allocate((srcLen+1) * sizeof(XMLCh))
        : new XMLCh[srcLen + 1];
PeiYong Zhang's avatar
PeiYong Zhang committed

    XMLCh* outPtr = retBuf;
    const UChar* srcPtr = toConvert;
    while (*srcPtr)
        *outPtr++ = XMLCh(*srcPtr++);
    *outPtr = 0;

    return retBuf;
}




// ---------------------------------------------------------------------------
//  ICUTransService: Constructors and Destructor
// ---------------------------------------------------------------------------
ICUTransService::ICUTransService()
{
#if !defined(XML_OS390) && !defined(XML_AS400) && !defined(XML_HPUX) && !defined(XML_PTX)
#if (U_ICU_VERSION_MAJOR_NUM < 2)
    // Starting with ICU 2.0, ICU itself includes a static reference to the data
    // entrypoint symbol.
    //
    // ICU 1.8 (and previous) did not include a static reference, but would
    // dynamically load the data dll when it was first needed, however this dynamic
    // loading proved unreliable in some of the odd environments that Xerces needed
    // to run in.  Hence, the static reference.

    // Pass the location of the converter data to ICU. By doing so, we are
    // forcing the load of ICU converter data DLL, after the Xerces-C DLL is
    // loaded. This implies that Xerces-C, now has to explicitly link with the
    // ICU converter dll. However, the advantage is that we no longer depend
    // on the code which does demand dynamic loading of DLL's. The demand
    // loading is highly system dependent and was a constant source of support
    // calls.
    UErrorCode uerr = U_ZERO_ERROR;
    udata_setCommonData((void *) icudata_dat, &uerr);
#endif
#endif
}

ICUTransService::~ICUTransService()
{
    /*
     * commented out the following clean up code
     * in case users use ICU outside of the parser
     * if we clean up here, users' code may crash
     *
    #if (U_ICU_VERSION_MAJOR_NUM >= 2)
        // release all lasily allocated data
        u_cleanup();
    #endif
PeiYong Zhang's avatar
PeiYong Zhang committed
}


// ---------------------------------------------------------------------------
//  ICUTransService: The virtual transcoding service API
// ---------------------------------------------------------------------------
int ICUTransService::compareIString(const   XMLCh* const    comp1
                                    , const XMLCh* const    comp2)
{
    const XMLCh* psz1 = comp1;
    const XMLCh* psz2 = comp2;

    unsigned int curCount = 0;
    while (true)
    {
        //
        //  If an inequality, then return the difference. Note that the XMLCh
        //  might be bigger physically than UChar, but it won't hold anything
        //  larger than 0xFFFF, so our cast here will work for both possible
        //  sizes of XMLCh.
        //
Tinny Ng's avatar
Tinny Ng committed
        if (u_toupper(UChar(*psz1)) != u_toupper(UChar(*psz2)))
PeiYong Zhang's avatar
PeiYong Zhang committed
            return int(*psz1) - int(*psz2);

        // If either has ended, then they both ended, so equal
        if (!*psz1 || !*psz2)
            break;

        // Move upwards for the next round
        psz1++;
        psz2++;
    }
    return 0;
}


int ICUTransService::compareNIString(const  XMLCh* const    comp1
                                    , const XMLCh* const    comp2
                                    , const unsigned int    maxChars)
{
Loading
Loading full blame...