| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| |
| /* |
| * $Id: IconvFBSDTransService.cpp 568078 2007-08-21 11:43:25Z amassari $ |
| */ |
| |
| // --------------------------------------------------------------------------- |
| // Includes |
| // --------------------------------------------------------------------------- |
| #include <ctype.h> |
| |
| #ifdef XML_USE_LIBICONV |
| # include <locale.h> |
| # include <iconv.h> |
| # include <errno.h> |
| # include <machine/endian.h> |
| |
| // --------------------------------------------------------------------------- |
| // Description of encoding schemas, supported by iconv() |
| // --------------------------------------------------------------------------- |
| typedef struct __IconvFBSDEncoding { |
| const char* fSchema; // schema name |
| size_t fUChSize; // size of the character |
| unsigned int fUBO; // byte order, relative to the host |
| } IconvFBSDEncoding; |
| |
| static const IconvFBSDEncoding gIconvFBSDEncodings[] = { |
| { "ucs-2-internal", 2, LITTLE_ENDIAN }, |
| { "ucs2-internal", 2, LITTLE_ENDIAN }, |
| { "ucs-4-internal", 4, LITTLE_ENDIAN }, |
| { "ucs4-internal", 4, LITTLE_ENDIAN }, |
| { "UNICODELITTLE", 2, LITTLE_ENDIAN }, |
| { "UNICODEBIG", 2, BIG_ENDIAN }, |
| { "iso-10646-ucs-2", 4, BIG_ENDIAN }, |
| { "iso-10646-ucs-4", 4, BIG_ENDIAN }, |
| /* { "iso-10646-utf-16", 2, BIG_ENDIAN }, */ |
| { NULL, 0, 0 } |
| }; |
| |
| //-------------------------------------------------- |
| // Macro-definitions to translate "native unicode" |
| // characters <-> XMLCh with different host byte order |
| // and encoding schemas. |
| |
| # if BYTE_ORDER == LITTLE_ENDIAN |
| # define IXMLCh2WC16(x,w) \ |
| *(w) = ((*(x)) >> 8) & 0xFF; \ |
| *((w)+1) = (*(x)) & 0xFF |
| # define IWC162XMLCh(w,x) *(x) = ((*(w)) << 8) | (*((w)+1)) |
| # define XMLCh2WC16(x,w) \ |
| *(w) = (*(x)) & 0xFF; \ |
| *((w)+1) = ((*(x)) >> 8) & 0xFF |
| # define WC162XMLCh(w,x) *(x) = ((*((w)+1)) << 8) | (*(w)) |
| |
| # define IXMLCh2WC32(x,w) \ |
| *(w) = ((*(x)) >> 24) & 0xFF; \ |
| *((w)+1) = ((*(x)) >> 16) & 0xFF; \ |
| *((w)+2) = ((*(x)) >> 8) & 0xFF; \ |
| *((w)+3) = (*(x)) & 0xFF |
| # define IWC322XMLCh(w,x) \ |
| *(x) = ((*(w)) << 24) | ((*((w)+1)) << 16) | \ |
| ((*((w)+2)) << 8) | (*((w)+3)) |
| # define XMLCh2WC32(x,w) \ |
| *((w)+3) = ((*(x)) >> 24) & 0xFF; \ |
| *((w)+2) = ((*(x)) >> 16) & 0xFF; \ |
| *((w)+1) = ((*(x)) >> 8) & 0xFF; \ |
| *(w) = (*(x)) & 0xFF |
| # define WC322XMLCh(w,x) \ |
| *(x) = ((*((w)+3)) << 24) | ((*((w)+2)) << 16) | \ |
| ((*((w)+1)) << 8) | (*(w)) |
| |
| # else /* BYTE_ORDER != LITTLE_ENDIAN */ |
| |
| # define XMLCh2WC16(x,w) \ |
| *(w) = ((*(x)) >> 8) & 0xFF; \ |
| *((w)+1) = (*(x)) & 0xFF |
| # define WC162XMLCh(w,x) *(x) = ((*(w)) << 8) | (*((w)+1)) |
| # define IXMLCh2WC16(x,w) \ |
| *(w) = (*(x)) & 0xFF; \ |
| *((w)+1) = ((*(x)) >> 8) & 0xFF |
| # define IWC162XMLCh(w,x) *(x) = ((*((w)+1)) << 8) | (*(w)) |
| |
| # define XMLCh2WC32(x,w) \ |
| *(w) = ((*(x)) >> 24) & 0xFF; \ |
| *((w)+1) = ((*(x)) >> 16) & 0xFF; \ |
| *((w)+2) = ((*(x)) >> 8) & 0xFF; \ |
| *((w)+3) = (*(x)) & 0xFF |
| # define WC322XMLCh(w,x) \ |
| *(x) = ((*(w)) << 24) | ((*((w)+1)) << 16) | \ |
| ((*((w)+2)) << 8) | (*((w)+3)) |
| # define IXMLCh2WC32(x,w) \ |
| *((w)+3) = ((*(x)) >> 24) & 0xFF; \ |
| *((w)+2) = ((*(x)) >> 16) & 0xFF; \ |
| *((w)+1) = ((*(x)) >> 8) & 0xFF; \ |
| *(w) = (*(x)) & 0xFF |
| # define IWC322XMLCh(w,x) \ |
| *(x) = ((*((w)+3)) << 24) | ((*((w)+2)) << 16) | \ |
| ((*((w)+1)) << 8) | (*(w)) |
| # endif /* BYTE_ORDER == LITTLE_ENDIAN */ |
| |
| #else /* !XML_USE_LIBICONV */ |
| |
| # if __FreeBSD_cc_version > 430000 |
| # include <wchar.h> |
| # else |
| # define wint_t XMLCh |
| # endif |
| |
| #endif /* XML_USE_LIBICONV */ |
| |
| #include <xercesc/util/XMLString.hpp> |
| #include <xercesc/util/XMLUniDefs.hpp> |
| #include <xercesc/util/XMLUni.hpp> |
| #include <xercesc/util/PlatformUtils.hpp> |
| #include <xercesc/util/TranscodingException.hpp> |
| #include "IconvFBSDTransService.hpp" |
| |
| #include <string.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| |
| #if !defined(APP_NO_THREADS) |
| #include <xercesc/util/Mutexes.hpp> |
| #endif |
| |
| XERCES_CPP_NAMESPACE_BEGIN |
| |
| // --------------------------------------------------------------------------- |
| // Local, const data |
| // --------------------------------------------------------------------------- |
| static const unsigned int gTempBuffArraySize = 4096; |
| static const XMLCh gMyServiceId[] = |
| { |
| chLatin_I, chLatin_C, chLatin_o, chLatin_n, chLatin_v, chNull |
| }; |
| |
| |
| // --------------------------------------------------------------------------- |
| // Local methods |
| // --------------------------------------------------------------------------- |
| static unsigned int getWideCharLength(const XMLCh* const src) |
| { |
| if (!src) |
| return 0; |
| |
| unsigned int len = 0; |
| const XMLCh* pTmp = src; |
| while (*pTmp++) |
| len++; |
| return len; |
| } |
| |
| #ifndef XML_USE_LIBICONV |
| |
| // --------------------------------------------------------------------------- |
| // FreeBSD got the wide-characters support since 4.0 version. But (at least |
| // up to the 4.4) this support differs from "others" in that the xxstoyys() |
| // does not handle the NULL-dest argument properly. So the custom functions |
| // are provided. |
| // --------------------------------------------------------------------------- |
| |
| #define __TMP_ARRAY_SIZE__ 4 |
| |
| static size_t fbsd_wcstombs(char *dest, const wchar_t *src, size_t n) |
| { |
| char tarr[ __TMP_ARRAY_SIZE__ + 1 ]; |
| size_t len = 0, lent = 0; |
| char* ptr; |
| size_t slen; |
| wchar_t* wptr; |
| |
| if (dest) |
| return ::wcstombs(dest, src, n); |
| if (!src) |
| return 0; |
| for (wptr = (wchar_t *) src, slen = 0; *wptr; wptr++, slen++); |
| if (slen == 0) |
| return 0; |
| wptr = (wchar_t *) src; |
| ptr = dest; |
| while ( (len = ::wcstombs(tarr, wptr, __TMP_ARRAY_SIZE__)) > 0 ) { |
| wptr += len; |
| lent += len; |
| } |
| if (len == (unsigned) -1) |
| return 0; |
| return lent; |
| } |
| |
| static size_t fbsd_mbstowcs(wchar_t *dest, const char *src, size_t n) |
| { |
| wchar_t tarr[ __TMP_ARRAY_SIZE__ + 1 ]; |
| size_t len = 0, lent = 0; |
| char* ptr; |
| |
| if (dest) |
| return ::mbstowcs(dest, src, n); |
| ptr = (char*) src; |
| if (!src || strlen(src) == 0) |
| return 0; |
| while ( (len = ::mbstowcs(tarr, ptr, __TMP_ARRAY_SIZE__)) > 0 ) { |
| ptr += len; |
| lent += len; |
| } |
| if (len == (unsigned) -1) |
| return 0; |
| return lent; |
| } |
| |
| static wint_t fbsd_towupper(wint_t ch) |
| { |
| if (ch <= 0x7F) |
| return toupper(ch); |
| unsigned char buf[16]; |
| wchar_t wc = wchar_t(ch); |
| wcstombs((char*)buf, &wc, 16); |
| return toupper(*buf); |
| } |
| |
| static wint_t fbsd_towlower(wint_t ch) |
| { |
| if (ch <= 0x7F) |
| return tolower(ch); |
| unsigned char buf[16]; |
| wchar_t wc = wchar_t(ch); |
| wcstombs((char *)buf, &wc, 16); |
| return tolower(*buf); |
| } |
| |
| #else /* XML_USE_LIBICONV */ |
| |
| #if !defined(APP_NO_THREADS) |
| // Iconv() access syncronization point |
| static XMLMutex *gIconvMutex = NULL; |
| # define ICONV_LOCK XMLMutexLock lockConverter(gIconvMutex); |
| |
| #else /* APP_NO_THREADS */ |
| |
| # define ICONV_LOCK |
| |
| #endif /* !APP_NO_THREADS */ |
| |
| //---------------------------------------------------------------------------- |
| // There is implementation of the libiconv for FreeBSD (available through the |
| // ports collection). The following is a wrapper around the iconv(). |
| //---------------------------------------------------------------------------- |
| |
| IconvFBSDCD::IconvFBSDCD () |
| : fUChSize(0), fUBO(LITTLE_ENDIAN), |
| fCDTo((iconv_t)-1), fCDFrom((iconv_t)-1) |
| { |
| } |
| |
| IconvFBSDCD::IconvFBSDCD ( iconv_t cd_from, |
| iconv_t cd_to, |
| size_t uchsize, |
| unsigned int ubo ) |
| : fUChSize(uchsize), fUBO(ubo), |
| fCDTo(cd_to), fCDFrom(cd_from) |
| { |
| if (fCDFrom == (iconv_t) -1 || fCDTo == (iconv_t) -1) { |
| XMLPlatformUtils::panic (PanicHandler::Panic_NoTransService); |
| } |
| } |
| |
| IconvFBSDCD::~IconvFBSDCD() |
| { |
| } |
| |
| // Convert "native unicode" character into XMLCh |
| void IconvFBSDCD::mbcToXMLCh (const char *mbc, XMLCh *toRet) const |
| { |
| if (fUBO == LITTLE_ENDIAN) { |
| if (fUChSize == sizeof(XMLCh)) |
| *toRet = *((XMLCh*) mbc); |
| else if (fUChSize == 2) { |
| WC162XMLCh( mbc, toRet ); |
| } else { |
| WC322XMLCh( mbc, toRet ); |
| } |
| } else { |
| if (fUChSize == 2) { |
| IWC162XMLCh( mbc, toRet ); |
| } else { |
| IWC322XMLCh( mbc, toRet ); |
| } |
| } |
| } |
| |
| // Convert XMLCh into "native unicode" character |
| void IconvFBSDCD::xmlChToMbc (XMLCh xch, char *mbc) const |
| { |
| if (fUBO == LITTLE_ENDIAN) { |
| if (fUChSize == sizeof(XMLCh)) { |
| memcpy (mbc, &xch, fUChSize); |
| return; |
| } |
| if (fUChSize == 2) { |
| XMLCh2WC16( &xch, mbc ); |
| } else { |
| XMLCh2WC32( &xch, mbc ); |
| } |
| } else { |
| if (fUChSize == 2) { |
| IXMLCh2WC16( &xch, mbc ); |
| } else { |
| IXMLCh2WC32( &xch, mbc ); |
| } |
| } |
| } |
| |
| // Return uppercase equivalent for XMLCh |
| XMLCh IconvFBSDCD::toUpper (const XMLCh ch) const |
| { |
| if (ch <= 0x7F) |
| return toupper(ch); |
| |
| char wcbuf[fUChSize * 2]; |
| xmlChToMbc (ch, wcbuf); |
| |
| char tmpArr[4]; |
| char* ptr = wcbuf; |
| size_t len = fUChSize; |
| char *pTmpArr = tmpArr; |
| size_t bLen = 2; |
| |
| ICONV_LOCK; |
| if (::iconv (fCDTo, (const char**) &ptr, &len, |
| &pTmpArr, &bLen) == (size_t) -1) |
| return 0; |
| tmpArr[1] = toupper (*((unsigned char *)tmpArr)); |
| *tmpArr = tmpArr[1]; |
| len = 1; |
| pTmpArr = wcbuf; |
| bLen = fUChSize; |
| ptr = tmpArr; |
| if (::iconv (fCDFrom, (const char **)&ptr, &len, |
| &pTmpArr, &bLen) == (size_t) -1) |
| return 0; |
| mbcToXMLCh (wcbuf, (XMLCh*) &ch); |
| return ch; |
| } |
| |
| // Return lowercase equivalent for XMLCh |
| XMLCh IconvFBSDCD::toLower (const XMLCh ch) const |
| { |
| if (ch <= 0x7F) |
| return tolower(ch); |
| |
| char wcbuf[fUChSize * 2]; |
| xmlChToMbc (ch, wcbuf); |
| |
| char tmpArr[4]; |
| char* ptr = wcbuf; |
| size_t len = fUChSize; |
| char *pTmpArr = tmpArr; |
| size_t bLen = 2; |
| |
| ICONV_LOCK; |
| if (::iconv (fCDTo, (const char**) &ptr, &len, |
| &pTmpArr, &bLen) == (size_t) -1) |
| return 0; |
| tmpArr[1] = tolower (*((unsigned char*)tmpArr)); |
| *tmpArr = tmpArr[1]; |
| len = 1; |
| pTmpArr = wcbuf; |
| bLen = fUChSize; |
| ptr = tmpArr; |
| if (::iconv (fCDFrom, (const char **)&ptr, &len, |
| &pTmpArr, &bLen) == (size_t) -1) |
| return 0; |
| mbcToXMLCh (wcbuf, (XMLCh*) &ch); |
| return ch; |
| } |
| |
| // Check if passed characters belongs to the :space: class |
| bool IconvFBSDCD::isSpace(const XMLCh toCheck) const |
| { |
| if (toCheck <= 0x7F) |
| return isspace(toCheck); |
| |
| char wcbuf[fUChSize * 2]; |
| char tmpArr[4]; |
| |
| xmlChToMbc (toCheck, wcbuf); |
| char* ptr = wcbuf; |
| size_t len = fUChSize; |
| char *pTmpArr = tmpArr; |
| size_t bLen = 2; |
| |
| { |
| ICONV_LOCK; |
| if (::iconv (fCDTo, (const char**) &ptr, &len, |
| &pTmpArr, &bLen) == (size_t) -1) |
| return 0; |
| } |
| return isspace(*tmpArr); |
| } |
| |
| // Fill array of XMLCh characters with data, supplyed in the array |
| // of "native unicode" characters. |
| XMLCh* IconvFBSDCD::mbsToXML |
| ( |
| const char* mbs_str |
| , size_t mbs_cnt |
| , XMLCh* xml_str |
| , size_t xml_cnt |
| ) const |
| { |
| if (mbs_str == NULL || mbs_cnt == 0 || xml_str == NULL || xml_cnt == 0) |
| return NULL; |
| size_t cnt = (mbs_cnt < xml_cnt) ? mbs_cnt : xml_cnt; |
| if (fUBO == LITTLE_ENDIAN) { |
| if (fUChSize == sizeof(XMLCh)) { |
| // null-transformation |
| memcpy (xml_str, mbs_str, fUChSize * cnt); |
| return xml_str; |
| } |
| if (fUChSize == 2) |
| for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize) { |
| WC162XMLCh( mbs_str, xml_str + i); |
| } |
| else |
| for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize) { |
| WC322XMLCh( mbs_str, xml_str + i ); |
| } |
| } else { |
| if (fUChSize == 2) |
| for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize) { |
| IWC162XMLCh( mbs_str, xml_str + i ); |
| } |
| else |
| for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize) { |
| IWC322XMLCh( mbs_str, xml_str + i ); |
| } |
| } |
| return xml_str; |
| } |
| |
| // Fill array of "native unicode" characters with data, supplyed |
| // in the array of XMLCh characters. |
| char* IconvFBSDCD::xmlToMbs |
| ( |
| const XMLCh* xml_str |
| , size_t xml_cnt |
| , char* mbs_str |
| , size_t mbs_cnt |
| ) const |
| { |
| if (mbs_str == NULL || mbs_cnt == 0 || xml_str == NULL || xml_cnt == 0) |
| return NULL; |
| size_t cnt = (mbs_cnt < xml_cnt) ? mbs_cnt : xml_cnt; |
| char *toReturn = mbs_str; |
| if (fUBO == LITTLE_ENDIAN) { |
| if (fUChSize == sizeof(XMLCh)) { |
| // null-transformation |
| memcpy (mbs_str, xml_str, fUChSize * cnt); |
| return toReturn; |
| } |
| if (fUChSize == 2) |
| for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize, xml_str++) { |
| XMLCh2WC16( xml_str, mbs_str ); |
| } |
| else |
| for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize, xml_str++) { |
| XMLCh2WC32( xml_str, mbs_str ); |
| } |
| } else { |
| if (fUChSize == 2) |
| for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize, xml_str++) { |
| IXMLCh2WC16( xml_str, mbs_str ); |
| } |
| else |
| for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize, xml_str++) { |
| IXMLCh2WC32( xml_str, mbs_str ); |
| } |
| } |
| return toReturn; |
| } |
| |
| size_t IconvFBSDCD::iconvFrom ( const char *fromPtr, |
| size_t *fromLen, |
| char **toPtr, |
| size_t toLen ) const |
| { |
| ICONV_LOCK; |
| return ::iconv (fCDFrom, &fromPtr, fromLen, toPtr, &toLen); |
| } |
| |
| size_t IconvFBSDCD::iconvTo ( const char *fromPtr, |
| size_t *fromLen, |
| char **toPtr, |
| size_t toLen ) const |
| { |
| ICONV_LOCK; |
| return ::iconv (fCDTo, &fromPtr, fromLen, toPtr, &toLen); |
| } |
| |
| #endif /* !XML_USE_LIBICONV */ |
| |
| |
| // --------------------------------------------------------------------------- |
| // IconvFBSDTransService: Constructors and Destructor |
| // --------------------------------------------------------------------------- |
| |
| IconvFBSDTransService::IconvFBSDTransService() |
| #ifndef XML_USE_LIBICONV |
| {} |
| #else /* XML_USE_LIBICONV */ |
| : IconvFBSDCD(), fUnicodeCP(0) |
| { |
| #if !defined(APP_NO_THREADS) |
| // Create global lock object |
| if (gIconvMutex == NULL) { |
| gIconvMutex = new XMLMutex; |
| if (gIconvMutex == NULL) |
| XMLPlatformUtils::panic (PanicHandler::Panic_NoTransService); |
| } |
| #endif |
| |
| // Try to obtain local (host) characterset from the setlocale |
| // and through the environment. Do not call setlocale(LC_*, "")! |
| // Using an empty string instead of NULL, will modify the libc |
| // behavior. |
| // |
| char* fLocalCP = setlocale (LC_CTYPE, NULL); |
| if (fLocalCP == NULL || *fLocalCP == 0 || |
| strcmp (fLocalCP, "C") == 0 || |
| strcmp (fLocalCP, "POSIX") == 0) { |
| fLocalCP = getenv ("LC_ALL"); |
| if (fLocalCP == NULL) { |
| fLocalCP = getenv ("LC_CTYPE"); |
| if (fLocalCP == NULL) |
| fLocalCP = getenv ("LANG"); |
| } |
| } |
| |
| if (fLocalCP == NULL || *fLocalCP == 0 || |
| strcmp (fLocalCP, "C") == 0 || |
| strcmp (fLocalCP, "POSIX") == 0) |
| fLocalCP = "iso-8859-1"; // fallback locale |
| else { |
| char *ptr = strchr (fLocalCP, '.'); |
| if (ptr == NULL) |
| fLocalCP = "iso-8859-1"; // fallback locale |
| else |
| fLocalCP = ptr + 1; |
| } |
| |
| // Select the native unicode characters encoding schema |
| const IconvFBSDEncoding *eptr; |
| // first - try to use the schema with character size, equil to XMLCh |
| for (eptr = gIconvFBSDEncodings; eptr->fSchema; eptr++) { |
| if (eptr->fUChSize != sizeof(XMLCh)) |
| continue; |
| ICONV_LOCK; |
| // try to create conversion descriptor |
| iconv_t cd_to = iconv_open(fLocalCP, eptr->fSchema); |
| if (cd_to == (iconv_t)-1) |
| continue; |
| iconv_t cd_from = iconv_open(eptr->fSchema, fLocalCP); |
| if (cd_to == (iconv_t)-1) { |
| iconv_close (cd_to); |
| continue; |
| } |
| // got it |
| setUChSize(eptr->fUChSize); |
| setUBO(eptr->fUBO); |
| setCDTo(cd_to); |
| setCDFrom(cd_from); |
| fUnicodeCP = eptr->fSchema; |
| break; |
| } |
| if (fUnicodeCP == NULL) |
| // try to use any known schema |
| for (eptr = gIconvFBSDEncodings; eptr->fSchema; eptr++) { |
| // try to create conversion descriptor |
| ICONV_LOCK; |
| iconv_t cd_to = iconv_open(fLocalCP, eptr->fSchema); |
| if (cd_to == (iconv_t)-1) |
| continue; |
| iconv_t cd_from = iconv_open(eptr->fSchema, fLocalCP); |
| if (cd_to == (iconv_t)-1) { |
| iconv_close (cd_to); |
| continue; |
| } |
| // got it |
| setUChSize(eptr->fUChSize); |
| setUBO(eptr->fUBO); |
| setCDTo(cd_to); |
| setCDFrom(cd_from); |
| fUnicodeCP = eptr->fSchema; |
| break; |
| } |
| |
| if (fUnicodeCP == NULL || cdTo() == (iconv_t)-1 || cdFrom() == (iconv_t)-1) |
| XMLPlatformUtils::panic (PanicHandler::Panic_NoTransService); |
| } |
| #endif /* XML_USE_LIBICONV */ |
| |
| IconvFBSDTransService::~IconvFBSDTransService() |
| { |
| #ifdef XML_USE_LIBICONV |
| if (cdTo() != (iconv_t) -1) { |
| iconv_close (cdTo()); |
| setCDTo ((iconv_t)-1); |
| } |
| if (cdFrom() != (iconv_t) -1) { |
| iconv_close (cdFrom()); |
| setCDFrom ((iconv_t)-1); |
| } |
| #endif /* XML_USE_LIBICONV */ |
| } |
| |
| // --------------------------------------------------------------------------- |
| // IconvFBSDTransService: The virtual transcoding service API |
| // --------------------------------------------------------------------------- |
| int IconvFBSDTransService::compareIString(const XMLCh* const comp1 |
| , const XMLCh* const comp2) |
| { |
| const XMLCh* cptr1 = comp1; |
| const XMLCh* cptr2 = comp2; |
| |
| #ifndef XML_USE_LIBICONV |
| |
| while ( (*cptr1 != 0) && (*cptr2 != 0) ) { |
| wint_t wch1 = fbsd_towupper(*cptr1); |
| wint_t wch2 = fbsd_towupper(*cptr2); |
| if (wch1 != wch2) |
| break; |
| cptr1++; |
| cptr2++; |
| } |
| return (int) ( fbsd_towupper(*cptr1) - fbsd_towupper(*cptr2) ); |
| |
| #else /* XML_USE_LIBICONV */ |
| |
| XMLCh c1 = toUpper(*cptr1); |
| XMLCh c2 = toUpper(*cptr2); |
| while ( (*cptr1 != 0) && (*cptr2 != 0) ) { |
| if (c1 != c2) |
| break; |
| c1 = toUpper(*(++cptr1)); |
| c2 = toUpper(*(++cptr2)); |
| |
| } |
| return (int) ( c1 - c2 ); |
| |
| #endif /* !XML_USE_LIBICONV */ |
| } |
| |
| |
| int IconvFBSDTransService::compareNIString(const XMLCh* const comp1 |
| , const XMLCh* const comp2 |
| , const unsigned int maxChars) |
| { |
| unsigned int n = 0; |
| const XMLCh* cptr1 = comp1; |
| const XMLCh* cptr2 = comp2; |
| |
| #ifndef XML_USE_LIBICONV |
| |
| while (true && maxChars) |
| { |
| wint_t wch1 = fbsd_towupper(*cptr1); |
| wint_t wch2 = fbsd_towupper(*cptr2); |
| |
| if (wch1 != wch2) |
| return (int) (wch1 - wch2); |
| |
| // If either ended, then both ended, so equal |
| if (!*cptr1 || !*cptr2) |
| break; |
| |
| cptr1++; |
| cptr2++; |
| |
| // Bump the count of chars done. If it equals the count then we |
| // are equal for the requested count, so break out and return |
| // equal. |
| n++; |
| if (n == maxChars) |
| break; |
| } |
| |
| #else /* XML_USE_LIBICONV */ |
| |
| while (true && maxChars) |
| { |
| XMLCh c1 = toUpper(*cptr1); |
| XMLCh c2 = toUpper(*cptr2); |
| |
| if (c1 != c2) |
| return (int) (c1 - c2); |
| |
| // If either ended, then both ended, so equal |
| if (!*cptr1 || !*cptr2) |
| break; |
| |
| cptr1++; |
| cptr2++; |
| |
| // Bump the count of chars done. If it equals the count then we |
| // are equal for the requested count, so break out and return |
| // equal. |
| n++; |
| if (n == maxChars) |
| break; |
| } |
| |
| #endif /* !XML_USE_LIBICONV */ |
| |
| return 0; |
| } |
| |
| |
| const XMLCh* IconvFBSDTransService::getId() const |
| { |
| return gMyServiceId; |
| } |
| |
| |
| bool IconvFBSDTransService::isSpace(const XMLCh toCheck) const |
| { |
| #ifndef XML_USE_LIBICONV |
| if (toCheck <= 0x7F) |
| return isspace(toCheck); |
| char buf[16]; |
| wchar_t wc = wchar_t(toCheck); |
| wcstombs( buf, &wc, 16 ); |
| return (isspace(*buf) != 0); |
| #else /* XML_USE_LIBICONV */ |
| return IconvFBSDCD::isSpace(toCheck); |
| #endif /* !XML_USE_LIBICONV */ |
| } |
| |
| |
| XMLLCPTranscoder* IconvFBSDTransService::makeNewLCPTranscoder() |
| { |
| // Just allocate a new transcoder of our type |
| #ifndef XML_USE_LIBICONV |
| return new IconvFBSDLCPTranscoder; |
| #else /* XML_USE_LIBICONV */ |
| return new IconvFBSDLCPTranscoder (cdFrom(), cdTo(), uChSize(), UBO()); |
| #endif /* !XML_USE_LIBICONV */ |
| } |
| |
| bool IconvFBSDTransService::supportsSrcOfs() const |
| { |
| return true; |
| } |
| |
| // --------------------------------------------------------------------------- |
| // IconvFBSDTransService: The protected virtual transcoding service API |
| // --------------------------------------------------------------------------- |
| XMLTranscoder* |
| IconvFBSDTransService::makeNewXMLTranscoder |
| ( |
| const XMLCh* const encodingName |
| , XMLTransService::Codes& resValue |
| , const unsigned int blockSize |
| , MemoryManager* const manager |
| ) |
| { |
| #ifndef XML_USE_LIBICONV |
| // |
| // NOTE: We don't use the block size here |
| // |
| // This is a minimalist transcoding service, that only supports a local |
| // default transcoder. All named encodings return zero as a failure, |
| // which means that only the intrinsic encodings supported by the parser |
| // itself will work for XML data. |
| // |
| resValue = XMLTransService::UnsupportedEncoding; |
| return 0; |
| #else /* XML_USE_LIBICONV */ |
| |
| resValue = XMLTransService::UnsupportedEncoding; |
| IconvFBSDTranscoder *newTranscoder = NULL; |
| |
| char *encLocal = XMLString::transcode(encodingName, manager); |
| iconv_t cd_from, cd_to; |
| |
| { |
| ICONV_LOCK; |
| cd_from = iconv_open (fUnicodeCP, encLocal); |
| if (cd_from == (iconv_t)-1) { |
| resValue = XMLTransService::SupportFilesNotFound; |
| if (encLocal) |
| manager->deallocate(encLocal);//delete [] encLocal; |
| return NULL; |
| } |
| cd_to = iconv_open (encLocal, fUnicodeCP); |
| if (cd_to == (iconv_t)-1) { |
| resValue = XMLTransService::SupportFilesNotFound; |
| iconv_close (cd_from); |
| if (encLocal) |
| manager->deallocate(encLocal);//delete [] encLocal; |
| return NULL; |
| } |
| newTranscoder = new (manager) IconvFBSDTranscoder (encodingName, |
| blockSize, |
| cd_from, cd_to, |
| uChSize(), UBO(), |
| manager); |
| } |
| if (newTranscoder) |
| resValue = XMLTransService::Ok; |
| if (encLocal) |
| manager->deallocate(encLocal);//delete [] encLocal; |
| return newTranscoder; |
| |
| #endif /* !XML_USE_LIBICONV */ |
| } |
| |
| void IconvFBSDTransService::upperCase(XMLCh* const toUpperCase) const |
| { |
| XMLCh* outPtr = toUpperCase; |
| while (*outPtr) |
| { |
| #ifndef XML_USE_LIBICONV |
| *outPtr = fbsd_towupper(*outPtr); |
| #else /* XML_USE_LIBICONV */ |
| *outPtr = toUpper(*outPtr); |
| #endif /* !XML_USE_LIBICONV */ |
| outPtr++; |
| } |
| } |
| |
| void IconvFBSDTransService::lowerCase(XMLCh* const toLowerCase) const |
| { |
| XMLCh* outPtr = toLowerCase; |
| while (*outPtr) |
| { |
| #ifndef XML_USE_LIBICONV |
| *outPtr = fbsd_towlower(*outPtr); |
| #else /* XML_USE_LIBICONV */ |
| *outPtr = toLower(*outPtr); |
| #endif /* !XML_USE_LIBICONV */ |
| outPtr++; |
| } |
| } |
| |
| // --------------------------------------------------------------------------- |
| // IconvFBSDLCPTranscoder: The virtual transcoder API |
| // --------------------------------------------------------------------------- |
| unsigned int |
| IconvFBSDLCPTranscoder::calcRequiredSize (const char* const srcText |
| , MemoryManager* const manager) |
| { |
| if (!srcText) |
| return 0; |
| |
| #ifndef XML_USE_LIBICONV |
| |
| unsigned int retVal = fbsd_mbstowcs(NULL, srcText, 0); |
| if (retVal == ~0) |
| return 0; |
| return retVal; |
| |
| #else /* XML_USE_LIBICONV */ |
| |
| size_t len, srcLen; |
| len = srcLen = strlen(srcText); |
| if (len == 0) |
| return 0; |
| |
| char tmpWideArr[gTempBuffArraySize]; |
| size_t totalLen = 0; |
| |
| for (;;) { |
| char *pTmpArr = tmpWideArr; |
| const char *ptr = srcText + srcLen - len; |
| size_t rc = iconvFrom(ptr, &len, &pTmpArr, gTempBuffArraySize); |
| if (rc == (size_t) -1 && errno != E2BIG) { |
| ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, manager); |
| /* return 0; */ |
| } |
| rc = pTmpArr - (char *) tmpWideArr; |
| totalLen += rc; |
| if (rc == 0 || len == 0) |
| break; |
| } |
| return totalLen / uChSize(); |
| |
| #endif /* XML_USE_LIBICONV */ |
| } |
| |
| |
| unsigned int |
| IconvFBSDLCPTranscoder::calcRequiredSize(const XMLCh* const srcText |
| , MemoryManager* const manager) |
| { |
| if (!srcText) |
| return 0; |
| unsigned int wLent = getWideCharLength(srcText); |
| if (wLent == 0) |
| return 0; |
| |
| #ifndef XML_USE_LIBICONV |
| |
| wchar_t tmpWideCharArr[gTempBuffArraySize]; |
| wchar_t* allocatedArray = 0; |
| wchar_t* wideCharBuf = 0; |
| |
| if (wLent >= gTempBuffArraySize) |
| wideCharBuf = allocatedArray = (wchar_t*) manager->allocate |
| ( |
| (wLent + 1) * sizeof(wchar_t) |
| );//new wchar_t[wLent + 1]; |
| else |
| wideCharBuf = tmpWideCharArr; |
| |
| for (unsigned int i = 0; i < wLent; i++) |
| wideCharBuf[i] = srcText[i]; |
| wideCharBuf[wLent] = 0x00; |
| |
| const unsigned int retVal = fbsd_wcstombs(NULL, wideCharBuf, 0); |
| |
| if (allocatedArray) |
| manager->deallocate(allocatedArray);//delete [] allocatedArray; |
| if (retVal == ~0) |
| return 0; |
| return retVal; |
| |
| #else /* XML_USE_LIBICONV */ |
| |
| char tmpWBuff[gTempBuffArraySize]; |
| char *wBuf = 0; |
| char *wBufPtr = 0; |
| size_t len = wLent * uChSize(); |
| if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) { |
| if (len > gTempBuffArraySize) { |
| wBufPtr = (char*) manager->allocate |
| ( |
| len * sizeof(char) |
| );//new char[len]; |
| if (wBufPtr == NULL) |
| return 0; |
| wBuf = wBufPtr; |
| } else |
| wBuf = tmpWBuff; |
| xmlToMbs (srcText, wLent, wBuf, wLent); |
| } else |
| wBuf = (char *) srcText; |
| |
| char tmpBuff[gTempBuffArraySize]; |
| size_t totalLen = 0; |
| char *srcEnd = wBuf + wLent * uChSize(); |
| |
| for (;;) { |
| char *pTmpArr = tmpBuff; |
| const char *ptr = srcEnd - len; |
| size_t rc = iconvTo(ptr, &len, &pTmpArr, gTempBuffArraySize); |
| if (rc == (size_t) -1 && errno != E2BIG) { |
| if (wBufPtr) |
| manager->deallocate(wBufPtr);//delete [] wBufPtr; |
| ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, manager); |
| /* return 0; */ |
| } |
| rc = pTmpArr - tmpBuff; |
| totalLen += rc; |
| if (rc == 0 || len == 0) |
| break; |
| } |
| if (wBufPtr) |
| manager->deallocate(wBufPtr);//delete [] wBufPtr; |
| return totalLen; |
| |
| #endif /* !XML_USE_LIBICONV */ |
| } |
| |
| |
| char* IconvFBSDLCPTranscoder::transcode(const XMLCh* const toTranscode) |
| { |
| if (!toTranscode) |
| return 0; |
| |
| char* retVal = 0; |
| if (*toTranscode) { |
| unsigned int wLent = getWideCharLength(toTranscode); |
| |
| #ifndef XML_USE_LIBICONV |
| |
| wchar_t tmpWideCharArr[gTempBuffArraySize]; |
| wchar_t* allocatedArray = 0; |
| wchar_t* wideCharBuf = 0; |
| |
| if (wLent >= gTempBuffArraySize) |
| wideCharBuf = allocatedArray = new wchar_t[wLent + 1]; |
| else |
| wideCharBuf = tmpWideCharArr; |
| |
| for (unsigned int i = 0; i < wLent; i++) |
| wideCharBuf[i] = toTranscode[i]; |
| wideCharBuf[wLent] = 0x00; |
| |
| // Calc the needed size. |
| const size_t neededLen = fbsd_wcstombs(NULL, wideCharBuf, 0); |
| if (neededLen == -1) { |
| if (allocatedArray) |
| delete [] allocatedArray; |
| return 0; |
| } |
| |
| retVal = new char[neededLen + 1]; |
| fbsd_wcstombs(retVal, wideCharBuf, neededLen); |
| if (allocatedArray) |
| delete [] allocatedArray; |
| retVal[neededLen] = 0; |
| |
| #else /* XML_USE_LIBICONV */ |
| |
| // Calc needed size. |
| const size_t neededLen = calcRequiredSize (toTranscode); |
| if (neededLen == 0) |
| return 0; |
| // allocate output buffer |
| retVal = new char[neededLen + 1]; |
| if (retVal == NULL) |
| return 0; |
| // prepare the original |
| char tmpWBuff[gTempBuffArraySize]; |
| char *wideCharBuf = 0; |
| char *wBufPtr = 0; |
| size_t len = wLent * uChSize(); |
| |
| if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) { |
| if (len > gTempBuffArraySize) { |
| wBufPtr = new char[len]; |
| if (wBufPtr == NULL) |
| return 0; |
| wideCharBuf = wBufPtr; |
| } else |
| wideCharBuf = tmpWBuff; |
| xmlToMbs (toTranscode, wLent, wideCharBuf, wLent); |
| } else |
| wideCharBuf = (char *) toTranscode; |
| |
| // perform conversion |
| wLent *= uChSize(); |
| char *ptr = retVal; |
| size_t tmpwLent = wLent; |
| size_t rc = iconvTo(wideCharBuf, &tmpwLent, &ptr, neededLen); |
| if (rc == (size_t)-1) { |
| if (wBufPtr) |
| delete [] wBufPtr; |
| return 0; |
| } |
| if (wBufPtr) |
| delete [] wBufPtr; |
| retVal[neededLen] = 0; |
| |
| #endif /* !XML_USE_LIBICONV */ |
| |
| } else { |
| retVal = new char[1]; |
| if (retVal == NULL) |
| return 0; |
| retVal[0] = 0; |
| } |
| return retVal; |
| } |
| |
| char* IconvFBSDLCPTranscoder::transcode(const XMLCh* const toTranscode, |
| MemoryManager* const manager) |
| { |
| if (!toTranscode) |
| return 0; |
| |
| char* retVal = 0; |
| if (*toTranscode) { |
| unsigned int wLent = getWideCharLength(toTranscode); |
| |
| #ifndef XML_USE_LIBICONV |
| |
| wchar_t tmpWideCharArr[gTempBuffArraySize]; |
| wchar_t* allocatedArray = 0; |
| wchar_t* wideCharBuf = 0; |
| |
| if (wLent >= gTempBuffArraySize) |
| wideCharBuf = allocatedArray = (wchar_t*) manager->allocate |
| ( |
| (wLent + 1) * sizeof(wchar_t) |
| );//new wchar_t[wLent + 1]; |
| else |
| wideCharBuf = tmpWideCharArr; |
| |
| for (unsigned int i = 0; i < wLent; i++) |
| wideCharBuf[i] = toTranscode[i]; |
| wideCharBuf[wLent] = 0x00; |
| |
| // Calc the needed size. |
| const size_t neededLen = fbsd_wcstombs(NULL, wideCharBuf, 0); |
| if (neededLen == -1) { |
| if (allocatedArray) |
| manager->deallocate(allocatedArray);//delete [] allocatedArray; |
| return 0; |
| } |
| |
| retVal = (char*) manager->allocate((neededLen + 1) * sizeof(char));//new char[neededLen + 1]; |
| fbsd_wcstombs(retVal, wideCharBuf, neededLen); |
| if (allocatedArray) |
| manager->deallocate(allocatedArray);//delete [] allocatedArray; |
| retVal[neededLen] = 0; |
| |
| #else /* XML_USE_LIBICONV */ |
| |
| // Calc needed size. |
| const size_t neededLen = calcRequiredSize (toTranscode, manager); |
| if (neededLen == 0) |
| return 0; |
| // allocate output buffer |
| retVal = (char*) manager->allocate((neededLen + 1) * sizeof(char));//new char[neededLen + 1]; |
| if (retVal == NULL) |
| return 0; |
| // prepare the original |
| char tmpWBuff[gTempBuffArraySize]; |
| char *wideCharBuf = 0; |
| char *wBufPtr = 0; |
| size_t len = wLent * uChSize(); |
| |
| if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) { |
| if (len > gTempBuffArraySize) { |
| wBufPtr = (char*) manager->allocate(len * sizeof(char));//new char[len]; |
| if (wBufPtr == NULL) { |
| manager->deallocate(retVal); |
| return 0; |
| } |
| wideCharBuf = wBufPtr; |
| } else |
| wideCharBuf = tmpWBuff; |
| xmlToMbs (toTranscode, wLent, wideCharBuf, wLent); |
| } else |
| wideCharBuf = (char *) toTranscode; |
| |
| // perform conversion |
| wLent *= uChSize(); |
| char *ptr = retVal; |
| size_t tmpwLent = wLent; |
| size_t rc = iconvTo(wideCharBuf, &tmpwLent, &ptr, neededLen); |
| if (rc == (size_t)-1) { |
| if (wBufPtr) |
| manager->deallocate(wBufPtr);//delete [] wBufPtr; |
| return 0; |
| } |
| if (wBufPtr) |
| manager->deallocate(wBufPtr);//delete [] wBufPtr; |
| retVal[neededLen] = 0; |
| |
| #endif /* !XML_USE_LIBICONV */ |
| |
| } else { |
| retVal = (char*) manager->allocate(sizeof(char));//new char[1]; |
| if (retVal == NULL) |
| return 0; |
| retVal[0] = 0; |
| } |
| return retVal; |
| } |
| |
| |
| bool IconvFBSDLCPTranscoder::transcode( const XMLCh* const toTranscode |
| , char* const toFill |
| , const unsigned int maxBytes |
| , MemoryManager* const manager) |
| { |
| // Watch for a couple of pyscho corner cases |
| if (!toTranscode || !maxBytes) { |
| toFill[0] = 0; |
| return true; |
| } |
| if (!*toTranscode) { |
| toFill[0] = 0; |
| return true; |
| } |
| |
| unsigned int wLent = getWideCharLength(toTranscode); |
| if (wLent > maxBytes) |
| wLent = maxBytes; |
| |
| #ifndef XML_USE_LIBICONV |
| |
| wchar_t tmpWideCharArr[gTempBuffArraySize]; |
| wchar_t* allocatedArray = 0; |
| wchar_t* wideCharBuf = 0; |
| |
| if (maxBytes >= gTempBuffArraySize) |
| wideCharBuf = allocatedArray = (wchar_t*) manager->allocate |
| ( |
| (maxBytes + 1) * sizeof(wchar_t) |
| );//new wchar_t[maxBytes + 1]; |
| else |
| wideCharBuf = tmpWideCharArr; |
| |
| for (unsigned int i = 0; i < wLent; i++) |
| wideCharBuf[i] = toTranscode[i]; |
| wideCharBuf[wLent] = 0x00; |
| |
| // Ok, go ahead and try the transcoding. If it fails, then ... |
| size_t mblen = fbsd_wcstombs(toFill, wideCharBuf, maxBytes); |
| if (mblen == -1) { |
| if (allocatedArray) |
| manager->deallocate(allocatedArray);//delete [] allocatedArray; |
| return false; |
| } |
| if (allocatedArray) |
| manager->deallocate(allocatedArray);//delete [] allocatedArray; |
| |
| // Cap it off just in case |
| toFill[mblen] = 0; |
| #else /* XML_USE_LIBICONV */ |
| |
| // Fill the "unicode" string |
| char tmpWBuff[gTempBuffArraySize]; |
| char *wideCharBuf = 0; |
| char *wBufPtr = 0; |
| size_t len = wLent * uChSize(); |
| |
| if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) { |
| if (len > gTempBuffArraySize) { |
| wBufPtr = (char*) manager->allocate |
| ( |
| len * sizeof(char) |
| );//new char[len]; |
| if (wBufPtr == NULL) |
| return 0; |
| wideCharBuf = wBufPtr; |
| } |
| else |
| wideCharBuf = tmpWBuff; |
| xmlToMbs (toTranscode, wLent, wideCharBuf, wLent); |
| } |
| else |
| wideCharBuf = (char *) toTranscode; |
| |
| // Ok, go ahead and try the transcoding. If it fails, then ... |
| char *ptr = toFill; |
| size_t rc = iconvTo(wideCharBuf, &len, &ptr, maxBytes); |
| if (rc == (size_t)-1) { |
| if (wBufPtr) |
| manager->deallocate(wBufPtr);//delete [] wBufPtr; |
| return false; |
| } |
| if (wBufPtr) |
| manager->deallocate(wBufPtr);//delete [] wBufPtr; |
| |
| *ptr = 0; |
| #endif /* !XML_USE_LIBICONV */ |
| |
| return true; |
| } |
| |
| |
| |
| XMLCh* IconvFBSDLCPTranscoder::transcode(const char* const toTranscode) |
| { |
| if (!toTranscode) |
| return 0; |
| |
| XMLCh* retVal = 0; |
| if (*toTranscode) { |
| const unsigned int wLent = calcRequiredSize(toTranscode); |
| if (wLent == 0) { |
| retVal = new XMLCh[1]; |
| retVal[0] = 0; |
| return retVal; |
| } |
| |
| #ifndef XML_USE_LIBICONV |
| |
| wchar_t tmpWideCharArr[gTempBuffArraySize]; |
| wchar_t* allocatedArray = 0; |
| wchar_t* wideCharBuf = 0; |
| |
| if (wLent >= gTempBuffArraySize) |
| wideCharBuf = allocatedArray = new wchar_t[wLent + 1]; |
| else |
| wideCharBuf = tmpWideCharArr; |
| |
| fbsd_mbstowcs(wideCharBuf, toTranscode, wLent); |
| retVal = new XMLCh[wLent + 1]; |
| if (retVal == NULL) { |
| if (allocatedArray) |
| delete [] allocatedArray; |
| return NULL; |
| } |
| for (unsigned int i = 0; i < wLent; i++) |
| retVal[i] = (XMLCh) wideCharBuf[i]; |
| retVal[wLent] = 0x00; |
| if (allocatedArray) |
| delete [] allocatedArray; |
| |
| #else /* XML_USE_LIBICONV */ |
| |
| char tmpWBuff[gTempBuffArraySize]; |
| char *wideCharBuf = 0; |
| char *wBufPtr = 0; |
| size_t len = wLent * uChSize(); |
| |
| retVal = new XMLCh[wLent + 1]; |
| if (retVal == NULL) |
| return NULL; |
| if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) { |
| if (len > gTempBuffArraySize) { |
| wBufPtr = new char[len]; |
| if (wBufPtr == NULL) |
| return 0; |
| wideCharBuf = wBufPtr; |
| } else |
| wideCharBuf = tmpWBuff; |
| } else |
| wideCharBuf = (char *) retVal; |
| |
| size_t flen = strlen(toTranscode); |
| char *ptr = wideCharBuf; |
| size_t rc = iconvFrom(toTranscode, &flen, &ptr, len); |
| if (rc == (size_t) -1) { |
| if (wBufPtr) |
| delete [] wBufPtr; |
| return NULL; |
| } |
| if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) |
| mbsToXML (wideCharBuf, wLent, retVal, wLent); |
| if (wBufPtr) |
| delete [] wBufPtr; |
| retVal[wLent] = 0x00; |
| |
| #endif /* !XML_USE_LIBICONV */ |
| |
| } |
| else { |
| retVal = new XMLCh[1]; |
| if (retVal == NULL ) |
| return 0; |
| retVal[0] = 0; |
| } |
| return retVal; |
| } |
| |
| XMLCh* IconvFBSDLCPTranscoder::transcode(const char* const toTranscode, |
| MemoryManager* const manager) |
| { |
| if (!toTranscode) |
| return 0; |
| |
| XMLCh* retVal = 0; |
| if (*toTranscode) { |
| const unsigned int wLent = calcRequiredSize(toTranscode, manager); |
| if (wLent == 0) { |
| retVal = (XMLCh*) manager->allocate(sizeof(XMLCh));//new XMLCh[1]; |
| retVal[0] = 0; |
| return retVal; |
| } |
| |
| #ifndef XML_USE_LIBICONV |
| |
| wchar_t tmpWideCharArr[gTempBuffArraySize]; |
| wchar_t* allocatedArray = 0; |
| wchar_t* wideCharBuf = 0; |
| |
| if (wLent >= gTempBuffArraySize) |
| wideCharBuf = allocatedArray = (wchar_t*) manager->allocate |
| ( |
| (wLent + 1) * sizeof(wchar_t) |
| );//new wchar_t[wLent + 1]; |
| else |
| wideCharBuf = tmpWideCharArr; |
| |
| fbsd_mbstowcs(wideCharBuf, toTranscode, wLent); |
| retVal = (XMLCh*) manager->allocate((wLent + 1) * sizeof(XMLCh));//new XMLCh[wLent + 1]; |
| if (retVal == NULL) { |
| if (allocatedArray) |
| manager->deallocate(allocatedArray);//delete [] allocatedArray; |
| return NULL; |
| } |
| for (unsigned int i = 0; i < wLent; i++) |
| retVal[i] = (XMLCh) wideCharBuf[i]; |
| retVal[wLent] = 0x00; |
| if (allocatedArray) |
| manager->deallocate(allocatedArray);//delete [] allocatedArray; |
| |
| #else /* XML_USE_LIBICONV */ |
| |
| char tmpWBuff[gTempBuffArraySize]; |
| char *wideCharBuf = 0; |
| char *wBufPtr = 0; |
| size_t len = wLent * uChSize(); |
| |
| retVal = (XMLCh*) manager->allocate((wLent + 1) * sizeof(XMLCh));//new XMLCh[wLent + 1]; |
| if (retVal == NULL) |
| return NULL; |
| if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) { |
| if (len > gTempBuffArraySize) { |
| wBufPtr = (char*) manager->allocate(len * sizeof(char));//new char[len]; |
| if (wBufPtr == NULL) |
| return 0; |
| wideCharBuf = wBufPtr; |
| } else |
| wideCharBuf = tmpWBuff; |
| } else |
| wideCharBuf = (char *) retVal; |
| |
| size_t flen = strlen(toTranscode); |
| char *ptr = wideCharBuf; |
| size_t rc = iconvFrom(toTranscode, &flen, &ptr, len); |
| if (rc == (size_t) -1) { |
| if (wBufPtr) |
| manager->deallocate(wBufPtr);//delete [] wBufPtr; |
| return NULL; |
| } |
| if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) |
| mbsToXML (wideCharBuf, wLent, retVal, wLent); |
| if (wBufPtr) |
| manager->deallocate(wBufPtr);//delete [] wBufPtr; |
| retVal[wLent] = 0x00; |
| |
| #endif /* !XML_USE_LIBICONV */ |
| |
| } |
| else { |
| retVal = (XMLCh*) manager->allocate(sizeof(XMLCh));//new XMLCh[1]; |
| if (retVal == NULL ) |
| return 0; |
| retVal[0] = 0; |
| } |
| return retVal; |
| } |
| |
| |
| bool IconvFBSDLCPTranscoder::transcode(const char* const toTranscode |
| , XMLCh* const toFill |
| , const unsigned int maxChars |
| , MemoryManager* const manager) |
| { |
| // Check for a couple of psycho corner cases |
| if (!toTranscode || !maxChars) |
| { |
| toFill[0] = 0; |
| return true; |
| } |
| |
| if (!*toTranscode) |
| { |
| toFill[0] = 0; |
| return true; |
| } |
| |
| size_t wLent = calcRequiredSize(toTranscode); |
| if (wLent > maxChars) |
| wLent = maxChars; |
| |
| #ifndef XML_USE_LIBICONV |
| |
| wchar_t tmpWideCharArr[gTempBuffArraySize]; |
| wchar_t* allocatedArray = 0; |
| wchar_t* wideCharBuf = 0; |
| |
| if (maxChars >= gTempBuffArraySize) |
| wideCharBuf = allocatedArray = (wchar_t*) manager->allocate |
| ( |
| (wLent + 1) * sizeof(wchar_t) |
| );//new wchar_t[wLent + 1]; |
| else |
| wideCharBuf = tmpWideCharArr; |
| |
| if (fbsd_mbstowcs(wideCharBuf, toTranscode, wLent) == -1) { |
| if (allocatedArray) |
| manager->deallocate(allocatedArray);//delete [] allocatedArray; |
| return false; |
| } |
| for (unsigned int i = 0; i < wLent; i++) |
| toFill[i] = (XMLCh) wideCharBuf[i]; |
| if (allocatedArray) |
| manager->deallocate(allocatedArray);//delete [] allocatedArray; |
| |
| #else /* XML_USE_LIBICONV */ |
| |
| char tmpWBuff[gTempBuffArraySize]; |
| char *wideCharBuf = 0; |
| char *wBufPtr = 0; |
| size_t len = wLent * uChSize(); |
| |
| if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) { |
| if (len > gTempBuffArraySize) { |
| wBufPtr = (char*) manager->allocate |
| ( |
| len * sizeof(char) |
| );//new char[len]; |
| if (wBufPtr == NULL) |
| return 0; |
| wideCharBuf = wBufPtr; |
| } else |
| wideCharBuf = tmpWBuff; |
| } else |
| wideCharBuf = (char *) toFill; |
| |
| size_t flen = strlen(toTranscode); // wLent; |
| char *ptr = wideCharBuf; |
| size_t rc = iconvFrom(toTranscode, &flen, &ptr, len); |
| if (rc == (size_t)-1) { |
| if (wBufPtr) |
| manager->deallocate(wBufPtr);//delete [] wBufPtr; |
| return false; |
| } |
| |
| if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) |
| mbsToXML (wideCharBuf, wLent, toFill, wLent); |
| if (wBufPtr) |
| manager->deallocate(wBufPtr);//delete [] wBufPtr; |
| |
| #endif /* !XML_USE_LIBICONV */ |
| |
| toFill[wLent] = 0x00; |
| return true; |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // IconvFBSDLCPTranscoder: Constructors and Destructor |
| // --------------------------------------------------------------------------- |
| |
| #ifdef XML_USE_LIBICONV |
| |
| IconvFBSDLCPTranscoder::IconvFBSDLCPTranscoder (iconv_t cd_from, |
| iconv_t cd_to, |
| size_t uchsize, |
| unsigned int ubo) |
| : IconvFBSDCD (cd_from, cd_to, uchsize, ubo) |
| { |
| } |
| |
| #endif /* XML_USE_LIBICONV */ |
| |
| |
| #ifndef XML_USE_LIBICONV |
| |
| IconvFBSDLCPTranscoder::IconvFBSDLCPTranscoder() |
| { |
| } |
| |
| #endif /* !XML_USE_LIBICONV */ |
| |
| IconvFBSDLCPTranscoder::~IconvFBSDLCPTranscoder() |
| { |
| } |
| |
| |
| #ifdef XML_USE_LIBICONV |
| |
| // --------------------------------------------------------------------------- |
| // IconvFBSDTranscoder: Constructors and Destructor |
| // --------------------------------------------------------------------------- |
| IconvFBSDTranscoder::IconvFBSDTranscoder (const XMLCh* const encodingName |
| , const unsigned int blockSize |
| , iconv_t cd_from |
| , iconv_t cd_to |
| , size_t uchsize |
| , unsigned int ubo |
| , MemoryManager* const manager |
| ) |
| : XMLTranscoder(encodingName, blockSize, manager) |
| , IconvFBSDCD (cd_from, cd_to, uchsize, ubo) |
| { |
| } |
| |
| IconvFBSDTranscoder::~IconvFBSDTranscoder() |
| { |
| ICONV_LOCK; |
| if (cdTo() != (iconv_t)-1) { |
| iconv_close (cdTo()); |
| setCDTo ((iconv_t)-1); |
| } |
| if (cdFrom() != (iconv_t)-1) { |
| iconv_close (cdFrom()); |
| setCDFrom ((iconv_t)-1); |
| } |
| } |
| |
| // --------------------------------------------------------------------------- |
| // IconvFBSDTranscoder: Implementation of the virtual transcoder API |
| // --------------------------------------------------------------------------- |
| unsigned int IconvFBSDTranscoder::transcodeFrom |
| ( |
| const XMLByte* const srcData |
| , const unsigned int srcCount |
| , XMLCh* const toFill |
| , const unsigned int maxChars |
| , unsigned int& bytesEaten |
| , unsigned char* const charSizes ) |
| { |
| // Transcode TO XMLCh |
| const char* startSrc = (const char*) srcData; |
| const char* endSrc = (const char*) srcData + srcCount; |
| |
| char tmpWBuff[gTempBuffArraySize]; |
| char *startTarget = 0; |
| char *wBufPtr = 0; |
| size_t len = maxChars * uChSize(); |
| |
| if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) { |
| if (len > gTempBuffArraySize) { |
| wBufPtr = (char*) getMemoryManager()->allocate |
| ( |
| len * sizeof(char) |
| );//new char[len]; |
| if (wBufPtr == NULL) |
| return 0; |
| startTarget = wBufPtr; |
| } else |
| startTarget = tmpWBuff; |
| } else |
| startTarget = (char *) toFill; |
| |
| // Do character-by-character transcoding |
| char *orgTarget = startTarget; |
| size_t srcLen = srcCount; |
| size_t prevSrcLen = srcLen; |
| unsigned int toReturn = 0; |
| bytesEaten = 0; |
| for (size_t cnt = 0; cnt < maxChars && srcLen; cnt++) { |
| size_t rc = iconvFrom(startSrc, &srcLen, &orgTarget, uChSize()); |
| if (rc == (size_t)-1) { |
| if (errno != E2BIG || prevSrcLen == srcLen) { |
| if (wBufPtr) |
| getMemoryManager()->deallocate(wBufPtr);//delete [] wBufPtr; |
| ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, getMemoryManager()); |
| } |
| } |
| charSizes[cnt] = prevSrcLen - srcLen; |
| prevSrcLen = srcLen; |
| bytesEaten += charSizes[cnt]; |
| startSrc = endSrc - srcLen; |
| toReturn++; |
| } |
| if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) |
| mbsToXML (startTarget, toReturn, toFill, toReturn); |
| if (wBufPtr) |
| getMemoryManager()->deallocate(wBufPtr);//delete [] wBufPtr; |
| return toReturn; |
| } |
| |
| unsigned int IconvFBSDTranscoder::transcodeTo |
| ( |
| const XMLCh* const srcData |
| , const unsigned int srcCount |
| , XMLByte* const toFill |
| , const unsigned int maxBytes |
| , unsigned int& charsEaten |
| , const UnRepOpts options ) |
| { |
| // Transcode FROM XMLCh |
| char tmpWBuff[gTempBuffArraySize]; |
| char *startSrc = tmpWBuff; |
| char *wBufPtr = 0; |
| size_t len = srcCount * uChSize(); |
| |
| if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) { |
| if (len > gTempBuffArraySize) { |
| wBufPtr = (char*) getMemoryManager()->allocate |
| ( |
| len * sizeof(char) |
| );//new char[len]; |
| if (wBufPtr == NULL) |
| return 0; |
| startSrc = wBufPtr; |
| } else |
| startSrc = tmpWBuff; |
| xmlToMbs (srcData, srcCount, startSrc, srcCount); |
| } else |
| startSrc = (char *) srcData; |
| |
| char* startTarget = (char *) toFill; |
| size_t srcLen = len; |
| size_t rc = iconvTo (startSrc, &srcLen, &startTarget, maxBytes); |
| if (rc == (size_t)-1 && errno != E2BIG) { |
| if (wBufPtr) |
| getMemoryManager()->deallocate(wBufPtr);//delete [] wBufPtr; |
| ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, getMemoryManager()); |
| } |
| charsEaten = srcCount - srcLen / uChSize(); |
| if (wBufPtr) |
| getMemoryManager()->deallocate(wBufPtr);//delete [] wBufPtr; |
| return startTarget - (char *)toFill; |
| } |
| |
| bool IconvFBSDTranscoder::canTranscodeTo |
| ( |
| const unsigned int toCheck |
| ) const |
| { |
| // |
| // If the passed value is really a surrogate embedded together, then |
| // we need to break it out into its two chars. Else just one. |
| // |
| char srcBuf[2 * uChSize()]; |
| unsigned int srcCount = 1; |
| if (toCheck & 0xFFFF0000) { |
| XMLCh ch1 = (toCheck >> 10) + 0xD800; |
| XMLCh ch2 = toCheck & 0x3FF + 0xDC00; |
| xmlToMbs(&ch1, 1, srcBuf, 1); |
| xmlToMbs(&ch2, 1, srcBuf + uChSize(), 1); |
| srcCount++; |
| } else |
| xmlToMbs((const XMLCh*) &toCheck, 1, srcBuf, 1); |
| size_t len = srcCount * uChSize(); |
| char tmpBuf[64]; |
| char* pTmpBuf = tmpBuf; |
| |
| size_t rc = iconvTo( srcBuf, &len, &pTmpBuf, 64); |
| return (rc != (size_t)-1) && (len == 0); |
| } |
| |
| #endif /* XML_USE_LIBICONV */ |
| |
| XERCES_CPP_NAMESPACE_END |