source: icXML/icXML-devel/src/icxercesc/util/Transcoders/IconvGNU/IconvGNUTransService.cpp @ 2720

Last change on this file since 2720 was 2720, checked in by cameron, 6 years ago

Initial check-in of icXML 0.8 source files

File size: 35.4 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: IconvGNUTransService.cpp 901107 2010-01-20 08:45:02Z borisk $
20 */
21
22// ---------------------------------------------------------------------------
23//  Includes
24// ---------------------------------------------------------------------------
25#if HAVE_CONFIG_H
26  #include <config.h>
27#endif
28
29#include <ctype.h>
30
31#include <locale.h>
32#include <errno.h>
33
34#if HAVE_ENDIAN_H
35  #include <endian.h>
36#elif HAVE_MACHINE_ENDIAN_H
37  #include <machine/endian.h>
38#elif HAVE_ARPA_NAMESER_COMPAT_H
39  #include <arpa/nameser_compat.h>
40#endif
41
42#define MAX_UCHSIZE 4
43
44//--------------------------------------------------
45// Macro-definitions to translate "native unicode"
46// characters <-> XMLCh with different host byte order
47// and encoding schemas.
48
49# if BYTE_ORDER == LITTLE_ENDIAN
50#  define IXMLCh2WC16(x,w)            \
51    *(w) = ((*(x)) >> 8) & 0xFF;        \
52    *((w)+1) = (*(x)) & 0xFF
53#  define IWC162XMLCh(w,x)    *(x) = ((*(w)) << 8) | (*((w)+1))
54#  define XMLCh2WC16(x,w)            \
55    *(w) = (*(x)) & 0xFF;            \
56    *((w)+1) = ((*(x)) >> 8) & 0xFF
57#  define WC162XMLCh(w,x)    *(x) = ((*((w)+1)) << 8) | (*(w))
58
59#  define IXMLCh2WC32(x,w)            \
60    *(w) = ((*(x)) >> 24) & 0xFF;        \
61    *((w)+1) = ((*(x)) >> 16) & 0xFF;    \
62    *((w)+2) = ((*(x)) >> 8) & 0xFF;    \
63    *((w)+3) = (*(x)) & 0xFF
64#  define IWC322XMLCh(w,x)                \
65      *(x) = ((*(w)) << 24) | ((*((w)+1)) << 16) |    \
66          ((*((w)+2)) << 8) | (*((w)+3))
67#  define XMLCh2WC32(x,w)            \
68    *((w)+3) = ((*(x)) >> 24) & 0xFF;    \
69    *((w)+2) = ((*(x)) >> 16) & 0xFF;    \
70    *((w)+1) = ((*(x)) >> 8) & 0xFF;    \
71    *(w) = (*(x)) & 0xFF
72#  define WC322XMLCh(w,x)                    \
73      *(x) = ((*((w)+3)) << 24) | ((*((w)+2)) << 16) |    \
74        ((*((w)+1)) << 8) | (*(w))
75
76# else /* BYTE_ORDER != LITTLE_ENDIAN */
77
78#  define XMLCh2WC16(x,w)            \
79    *(w) = ((*(x)) >> 8) & 0xFF;        \
80    *((w)+1) = (*(x)) & 0xFF
81#  define WC162XMLCh(w,x)    *(x) = ((*(w)) << 8) | (*((w)+1))
82#  define IXMLCh2WC16(x,w)            \
83    *(w) = (*(x)) & 0xFF;            \
84    *((w)+1) = ((*(x)) >> 8) & 0xFF
85#  define IWC162XMLCh(w,x)    *(x) = ((*((w)+1)) << 8) | (*(w))
86
87#  define XMLCh2WC32(x,w)            \
88    *(w) = ((*(x)) >> 24) & 0xFF;        \
89    *((w)+1) = ((*(x)) >> 16) & 0xFF;    \
90    *((w)+2) = ((*(x)) >> 8) & 0xFF;    \
91    *((w)+3) = (*(x)) & 0xFF
92#  define WC322XMLCh(w,x)                \
93      *(x) = ((*(w)) << 24) | ((*((w)+1)) << 16) |    \
94          ((*((w)+2)) << 8) | (*((w)+3))
95#  define IXMLCh2WC32(x,w)            \
96    *((w)+3) = ((*(x)) >> 24) & 0xFF;    \
97    *((w)+2) = ((*(x)) >> 16) & 0xFF;    \
98    *((w)+1) = ((*(x)) >> 8) & 0xFF;    \
99    *(w) = (*(x)) & 0xFF
100#  define IWC322XMLCh(w,x)                    \
101      *(x) = ((*((w)+3)) << 24) | ((*((w)+2)) << 16) |    \
102        ((*((w)+1)) << 8) | (*(w))
103# endif /* BYTE_ORDER == LITTLE_ENDIAN */
104
105#include <wchar.h>
106#include <string.h>
107#include <stdlib.h>
108#include <stdio.h>
109
110#include <xercesc/util/XMLString.hpp>
111#include <xercesc/util/XMLUniDefs.hpp>
112#include <xercesc/util/XMLUni.hpp>
113#include <xercesc/util/PlatformUtils.hpp>
114#include <xercesc/util/TranscodingException.hpp>
115#include <xercesc/util/Janitor.hpp>
116#include "IconvGNUTransService.hpp"
117
118
119XERCES_CPP_NAMESPACE_BEGIN
120
121// ---------------------------------------------------------------------------
122// Description of encoding schemas, supported by iconv()
123// ---------------------------------------------------------------------------
124typedef struct __IconvGNUEncoding {
125    const char*    fSchema;    // schema name
126    size_t    fUChSize;    // size of the character
127    unsigned int fUBO;        // byte order, relative to the host
128} IconvGNUEncoding;
129
130static const IconvGNUEncoding    gIconvGNUEncodings[] = {
131    { "UTF-16LE",        2,    LITTLE_ENDIAN },
132    { "UTF-16BE",        2,    BIG_ENDIAN },
133    { "UCS-2LE",         2,    LITTLE_ENDIAN },
134    { "UCS-2BE",         2,    BIG_ENDIAN },
135    { "UCS-2-INTERNAL",  2,    BYTE_ORDER },
136    { NULL,              0,    0 }
137};
138
139// ---------------------------------------------------------------------------
140//  Local, const data
141// ---------------------------------------------------------------------------
142static const unsigned int    gTempBuffArraySize = 4096;
143static const XMLCh        gMyServiceId[] =
144{
145    chLatin_I, chLatin_C, chLatin_o, chLatin_n, chLatin_v, chNull
146};
147
148
149// ---------------------------------------------------------------------------
150//  Local methods
151// ---------------------------------------------------------------------------
152static XMLSize_t getWideCharLength(const XMLCh* const src)
153{
154    if (!src)
155        return 0;
156
157    XMLSize_t len = 0;
158    const XMLCh* pTmp = src;
159    while (*pTmp++)
160        len++;
161    return len;
162}
163
164
165//----------------------------------------------------------------------------
166// There is implementation of the libiconv for FreeBSD (available through the
167// ports collection). The following is a wrapper around the iconv().
168//----------------------------------------------------------------------------
169
170IconvGNUWrapper::IconvGNUWrapper (MemoryManager* manager)
171    : fUChSize(0), fUBO(LITTLE_ENDIAN),
172      fCDTo((iconv_t)-1), fCDFrom((iconv_t)-1), fMutex(manager)
173{
174}
175
176IconvGNUWrapper::IconvGNUWrapper ( iconv_t    cd_from,
177               iconv_t    cd_to,
178               size_t    uchsize,
179               unsigned int    ubo,
180               MemoryManager* manager)
181    : fUChSize(uchsize), fUBO(ubo),
182      fCDTo(cd_to), fCDFrom(cd_from), fMutex(manager)
183{
184    if (fCDFrom == (iconv_t) -1 || fCDTo == (iconv_t) -1) {
185        XMLPlatformUtils::panic (PanicHandler::Panic_NoTransService);
186    }
187}
188
189IconvGNUWrapper::~IconvGNUWrapper()
190{
191}
192
193// Convert "native unicode" character into XMLCh
194void    IconvGNUWrapper::mbcToXMLCh (const char *mbc, XMLCh *toRet) const
195{
196    if (fUBO == BYTE_ORDER) {
197        if (fUChSize == sizeof(XMLCh))
198            *toRet = *((XMLCh*) mbc);
199        else if (fUChSize == 2) {
200            WC162XMLCh( mbc, toRet );
201        } else {
202            WC322XMLCh( mbc, toRet );
203        }
204    } else {
205        if (fUChSize == 2) {
206            IWC162XMLCh( mbc, toRet );
207        } else {
208            IWC322XMLCh( mbc, toRet );
209        }
210    }
211}
212
213// Convert XMLCh into "native unicode" character
214void    IconvGNUWrapper::xmlChToMbc (XMLCh xch, char *mbc) const
215{
216    if (fUBO == BYTE_ORDER) {
217        if (fUChSize == sizeof(XMLCh)) {
218            memcpy (mbc, &xch, fUChSize);
219            return;
220        }
221        if (fUChSize == 2) {
222            XMLCh2WC16( &xch, mbc );
223        } else {
224            XMLCh2WC32( &xch, mbc );
225        }
226    } else {
227        if (fUChSize == 2) {
228            IXMLCh2WC16( &xch, mbc );
229        } else {
230            IXMLCh2WC32( &xch, mbc );
231        }
232    }
233}
234
235// Return uppercase equivalent for XMLCh
236XMLCh IconvGNUWrapper::toUpper (const XMLCh ch)
237{
238    if (ch <= 0x7F)
239        return toupper(ch);
240
241    char    wcbuf[MAX_UCHSIZE * 2];
242    xmlChToMbc (ch, wcbuf);
243
244    char    tmpArr[4];
245#if ICONV_USES_CONST_POINTER
246    const char* ptr = wcbuf;
247#else
248    char* ptr = wcbuf;
249#endif
250    size_t    len = fUChSize;
251    char    *pTmpArr = tmpArr;
252    size_t    bLen = 2;
253
254    if (::iconv (fCDTo, &ptr, &len, &pTmpArr, &bLen) == (size_t) -1)
255        return 0;
256    tmpArr[1] = toupper (*((unsigned char *)tmpArr));
257    *tmpArr = tmpArr[1];
258    len = 1;
259    pTmpArr = wcbuf;
260    bLen = fUChSize;
261    ptr = tmpArr;
262    if (::iconv (fCDFrom, &ptr, &len, &pTmpArr, &bLen) == (size_t) -1)
263        return 0;
264    mbcToXMLCh (wcbuf, (XMLCh*) &ch);
265    return ch;
266}
267
268// Return lowercase equivalent for XMLCh
269XMLCh IconvGNUWrapper::toLower (const XMLCh ch)
270{
271    if (ch <= 0x7F)
272        return tolower(ch);
273
274    char    wcbuf[MAX_UCHSIZE * 2];
275    xmlChToMbc (ch, wcbuf);
276
277    char    tmpArr[4];
278#if ICONV_USES_CONST_POINTER
279    const char* ptr = wcbuf;
280#else
281    char* ptr = wcbuf;
282#endif
283    size_t    len = fUChSize;
284    char    *pTmpArr = tmpArr;
285    size_t    bLen = 2;
286
287    if (::iconv (fCDTo, &ptr, &len, &pTmpArr, &bLen) == (size_t) -1)
288        return 0;
289    tmpArr[1] = tolower (*((unsigned char*)tmpArr));
290    *tmpArr = tmpArr[1];
291    len = 1;
292    pTmpArr = wcbuf;
293    bLen = fUChSize;
294    ptr = tmpArr;
295    if (::iconv (fCDFrom, &ptr, &len, &pTmpArr, &bLen) == (size_t) -1)
296        return 0;
297    mbcToXMLCh (wcbuf, (XMLCh*) &ch);
298    return ch;
299}
300
301// Fill array of XMLCh characters with data, supplyed in the array
302// of "native unicode" characters.
303XMLCh*    IconvGNUWrapper::mbsToXML
304(
305    const char*      mbs_str
306    ,      XMLCh*    xml_str
307    ,      size_t    cnt
308) const
309{
310    if (mbs_str == NULL || xml_str == NULL || cnt == 0)
311        return NULL;
312    if (fUBO == BYTE_ORDER) {
313        if (fUChSize == sizeof(XMLCh)) {
314            // null-transformation
315            memcpy (xml_str, mbs_str, fUChSize * cnt);
316            return xml_str;
317        }
318        if (fUChSize == 2)
319            for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize) {
320                WC162XMLCh( mbs_str, xml_str + i);
321            }
322        else
323            for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize) {
324                WC322XMLCh( mbs_str, xml_str + i );
325            }
326    } else {
327        if (fUChSize == 2)
328            for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize) {
329                IWC162XMLCh( mbs_str, xml_str + i );
330            }
331        else
332            for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize) {
333                IWC322XMLCh( mbs_str, xml_str + i );
334            }
335    }
336    return xml_str;
337}
338
339// Fill array of "native unicode" characters with data, supplyed
340// in the array of XMLCh characters.
341char*    IconvGNUWrapper::xmlToMbs
342(
343    const XMLCh*     xml_str
344    ,      char*     mbs_str
345    ,      size_t    cnt
346) const
347{
348    if (mbs_str == NULL || xml_str == NULL || cnt == 0)
349        return NULL;
350    char    *toReturn = mbs_str;
351    if (fUBO == BYTE_ORDER) {
352        if (fUChSize == sizeof(XMLCh)) {
353            // null-transformation
354            memcpy (mbs_str, xml_str, fUChSize * cnt);
355            return toReturn;
356        }
357        if (fUChSize == 2)
358            for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize, xml_str++) {
359                XMLCh2WC16( xml_str, mbs_str );
360            }
361        else
362            for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize, xml_str++) {
363                XMLCh2WC32( xml_str, mbs_str );
364            }
365    } else {
366        if (fUChSize == 2)
367            for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize, xml_str++) {
368                IXMLCh2WC16( xml_str, mbs_str );
369            }
370        else
371            for (size_t i = 0; i < cnt; i++, mbs_str += fUChSize, xml_str++) {
372                IXMLCh2WC32( xml_str, mbs_str );
373            }
374    }
375    return toReturn;
376}
377
378size_t    IconvGNUWrapper::iconvFrom ( const char    *fromPtr,
379                 size_t        *fromLen,
380                 char        **toPtr,
381                 size_t        toLen )
382{
383#if ICONV_USES_CONST_POINTER
384    const char ** tmpPtr = &fromPtr;
385#else
386    char ** tmpPtr = (char**)&fromPtr;
387#endif
388    return ::iconv (fCDFrom, tmpPtr, fromLen, toPtr, &toLen);
389}
390
391size_t    IconvGNUWrapper::iconvTo ( const char    *fromPtr,
392                   size_t        *fromLen,
393                   char        **toPtr,
394                   size_t        toLen )
395{
396#if ICONV_USES_CONST_POINTER
397    const char ** tmpPtr = &fromPtr;
398#else
399    char ** tmpPtr = (char**)&fromPtr;
400#endif
401    return ::iconv (fCDTo, tmpPtr, fromLen, toPtr, &toLen);
402}
403
404
405// ---------------------------------------------------------------------------
406//  IconvGNUTransService: Constructors and Destructor
407// ---------------------------------------------------------------------------
408
409IconvGNUTransService::IconvGNUTransService(MemoryManager* manager)
410    : IconvGNUWrapper(manager), fUnicodeCP(0)
411{
412    // Try to obtain local (host) characterset from the setlocale
413    // and through the environment. Do not call setlocale(LC_*, "")!
414    // Using an empty string instead of NULL, will modify the libc
415    // behavior.
416    //
417    const char* fLocalCP = setlocale (LC_CTYPE, NULL);
418    if (fLocalCP == NULL || *fLocalCP == 0 ||
419        strcmp (fLocalCP, "C") == 0 ||
420        strcmp (fLocalCP, "POSIX") == 0) {
421      fLocalCP = getenv ("LC_ALL");
422      if (fLocalCP == NULL) {
423        fLocalCP = getenv ("LC_CTYPE");
424        if (fLocalCP == NULL)
425          fLocalCP = getenv ("LANG");
426      }
427    }
428
429    if (fLocalCP == NULL || *fLocalCP == 0 ||
430        strcmp (fLocalCP, "C") == 0 ||
431        strcmp (fLocalCP, "POSIX") == 0)
432        fLocalCP = "iso-8859-1";    // fallback locale
433    else {
434        const char *ptr = strchr (fLocalCP, '.');
435        if (ptr == NULL)
436            fLocalCP = "iso-8859-1";    // fallback locale
437        else
438            fLocalCP = ptr + 1;
439    }
440
441    // Select the native unicode characters encoding schema
442    const IconvGNUEncoding    *eptr;
443    // first - try to use the schema with character size equal to XMLCh, and same endianness
444    for (eptr = gIconvGNUEncodings; eptr->fSchema; eptr++)
445    {
446        if (eptr->fUChSize != sizeof(XMLCh) || eptr->fUBO != BYTE_ORDER)
447            continue;
448
449        // try to create conversion descriptor
450        iconv_t    cd_to = iconv_open(fLocalCP, eptr->fSchema);
451        if (cd_to == (iconv_t)-1)
452            continue;
453        iconv_t    cd_from = iconv_open(eptr->fSchema, fLocalCP);
454        if (cd_from == (iconv_t)-1) {
455            iconv_close (cd_to);
456            continue;
457        }
458
459        // got it
460        setUChSize(eptr->fUChSize);
461        setUBO(eptr->fUBO);
462        setCDTo(cd_to);
463        setCDFrom(cd_from);
464        fUnicodeCP = eptr->fSchema;
465        break;
466    }
467    if (fUnicodeCP == NULL)
468        // try to use any known schema
469        for (eptr = gIconvGNUEncodings; eptr->fSchema; eptr++)
470        {
471            // try to create conversion descriptor
472            iconv_t    cd_to = iconv_open(fLocalCP, eptr->fSchema);
473            if (cd_to == (iconv_t)-1)
474                continue;
475            iconv_t    cd_from = iconv_open(eptr->fSchema, fLocalCP);
476            if (cd_from == (iconv_t)-1) {
477                iconv_close (cd_to);
478                continue;
479            }
480
481            // got it
482            setUChSize(eptr->fUChSize);
483            setUBO(eptr->fUBO);
484            setCDTo(cd_to);
485            setCDFrom(cd_from);
486            fUnicodeCP = eptr->fSchema;
487            break;
488        }
489
490    if (fUnicodeCP == NULL || cdTo() == (iconv_t)-1 || cdFrom() == (iconv_t)-1)
491        XMLPlatformUtils::panic (PanicHandler::Panic_NoTransService);
492}
493
494IconvGNUTransService::~IconvGNUTransService()
495{
496    if (cdTo() != (iconv_t) -1) {
497        iconv_close (cdTo());
498        setCDTo ((iconv_t)-1);
499    }
500    if (cdFrom() != (iconv_t) -1) {
501        iconv_close (cdFrom());
502        setCDFrom ((iconv_t)-1);
503    }
504}
505
506// ---------------------------------------------------------------------------
507//  IconvGNUTransService: The virtual transcoding service API
508// ---------------------------------------------------------------------------
509int IconvGNUTransService::compareIString(const XMLCh* const    comp1
510                                        , const XMLCh* const    comp2)
511{
512    const XMLCh* cptr1 = comp1;
513    const XMLCh* cptr2 = comp2;
514
515    XMLMutexLock lockConverter(&fMutex);
516
517    XMLCh    c1 = toUpper(*cptr1);
518    XMLCh    c2 = toUpper(*cptr2);
519    while ( (*cptr1 != 0) && (*cptr2 != 0) ) {
520        if (c1 != c2)
521            break;
522        c1 = toUpper(*(++cptr1));
523        c2 = toUpper(*(++cptr2));
524
525    }
526    return (int) ( c1 - c2 );
527}
528
529
530int IconvGNUTransService::compareNIString(const XMLCh* const     comp1
531                                         , const XMLCh* const    comp2
532                                         , const XMLSize_t       maxChars)
533{
534    unsigned int  n = 0;
535    const XMLCh* cptr1 = comp1;
536    const XMLCh* cptr2 = comp2;
537
538    XMLMutexLock lockConverter(&fMutex);
539
540    while (true && maxChars)
541    {
542        XMLCh    c1 = toUpper(*cptr1);
543        XMLCh    c2 = toUpper(*cptr2);
544
545        if (c1 != c2)
546            return (int) (c1 - c2);
547
548        // If either ended, then both ended, so equal
549        if (!*cptr1 || !*cptr2)
550            break;
551
552        cptr1++;
553        cptr2++;
554
555        //  Bump the count of chars done. If it equals the count then we
556        //  are equal for the requested count, so break out and return
557        //  equal.
558        n++;
559        if (n == maxChars)
560            break;
561    }
562
563    return 0;
564}
565
566
567const XMLCh* IconvGNUTransService::getId() const
568{
569    return gMyServiceId;
570}
571
572XMLLCPTranscoder* IconvGNUTransService::makeNewLCPTranscoder(MemoryManager* manager)
573{
574    return new (manager) IconvGNULCPTranscoder (cdFrom(), cdTo(), uChSize(), UBO(), manager);
575}
576
577bool IconvGNUTransService::supportsSrcOfs() const
578{
579    return true;
580}
581
582// ---------------------------------------------------------------------------
583//  IconvGNUTransService: The protected virtual transcoding service API
584// ---------------------------------------------------------------------------
585XMLTranscoder*
586IconvGNUTransService::makeNewXMLTranscoder
587(
588    const    XMLCh* const    encodingName
589    ,    XMLTransService::Codes&    resValue
590    , const    XMLSize_t    blockSize
591    ,        MemoryManager* const    manager
592)
593{
594    resValue = XMLTransService::UnsupportedEncoding;
595    IconvGNUTranscoder    *newTranscoder = NULL;
596
597    char    *encLocal = XMLString::transcode(encodingName, manager);
598    ArrayJanitor<char> janBuf(encLocal, manager);
599    iconv_t    cd_from, cd_to;
600
601    cd_from = iconv_open (fUnicodeCP, encLocal);
602    if (cd_from == (iconv_t)-1) {
603        resValue = XMLTransService::SupportFilesNotFound;
604        return NULL;
605    }
606    cd_to = iconv_open (encLocal, fUnicodeCP);
607    if (cd_to == (iconv_t)-1) {
608        resValue = XMLTransService::SupportFilesNotFound;
609        iconv_close (cd_from);
610        return NULL;
611    }
612    newTranscoder = new (manager) IconvGNUTranscoder (encodingName,
613                         blockSize,
614                         cd_from, cd_to,
615                         uChSize(), UBO(), manager);
616    if (newTranscoder)
617        resValue = XMLTransService::Ok;
618    return newTranscoder;
619}
620
621void IconvGNUTransService::upperCase(XMLCh* const toUpperCase)
622{
623    XMLCh* outPtr = toUpperCase;
624
625    XMLMutexLock lockConverter(&fMutex);
626
627    while (*outPtr)
628    {
629        *outPtr = toUpper(*outPtr);
630        outPtr++;
631    }
632}
633
634void IconvGNUTransService::lowerCase(XMLCh* const toLowerCase)
635{
636    XMLCh* outPtr = toLowerCase;
637
638    XMLMutexLock lockConverter(&fMutex);
639
640    while (*outPtr)
641    {
642        *outPtr = toLower(*outPtr);
643        outPtr++;
644    }
645}
646
647// ---------------------------------------------------------------------------
648//  IconvGNULCPTranscoder: The virtual transcoder API
649// ---------------------------------------------------------------------------
650XMLSize_t IconvGNULCPTranscoder::calcRequiredSize (const char* const srcText
651                                         , MemoryManager* const manager)
652{
653    if (!srcText)
654        return 0;
655
656    size_t len, srcLen;
657    len = srcLen = strlen(srcText);
658    if (len == 0)
659        return 0;
660
661    char tmpWideArr[gTempBuffArraySize];
662    size_t totalLen = 0;
663
664    XMLMutexLock lockConverter(&fMutex);
665
666    for (;;) {
667        char        *pTmpArr = tmpWideArr;
668        const char    *ptr = srcText + srcLen - len;
669        size_t    rc = iconvFrom(ptr, &len, &pTmpArr, gTempBuffArraySize);
670        if (rc == (size_t) -1 && errno != E2BIG) {
671            ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, manager);
672            /* return 0; */
673        }
674        rc = pTmpArr - (char *) tmpWideArr;
675        totalLen += rc;
676        if (rc == 0 || len == 0)
677            break;
678    }
679    return totalLen / uChSize();
680}
681
682
683XMLSize_t IconvGNULCPTranscoder::calcRequiredSize(const XMLCh* const srcText
684                                        , MemoryManager* const manager)
685{
686    if (!srcText)
687        return 0;
688    XMLSize_t  wLent = getWideCharLength(srcText);
689    if (wLent == 0)
690        return 0;
691
692    char    tmpWBuff[gTempBuffArraySize];
693    char    *wBuf = 0;
694    char    *wBufPtr = 0;
695    ArrayJanitor<char>  janBuf(wBufPtr, manager);
696    size_t      len = wLent * uChSize();
697    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
698        if (len > gTempBuffArraySize) {
699            wBufPtr = (char*) manager->allocate(len * sizeof(char));//new char[len];
700            janBuf.reset(wBufPtr, manager);
701            wBuf = wBufPtr;
702        } else
703            wBuf = tmpWBuff;
704        xmlToMbs (srcText, wBuf, wLent);
705    } else
706        wBuf = (char *) srcText;
707
708    char    tmpBuff[gTempBuffArraySize];
709    size_t    totalLen = 0;
710    char    *srcEnd = wBuf + wLent * uChSize();
711
712    XMLMutexLock lockConverter(&fMutex);
713
714    for (;;) {
715        char        *pTmpArr = tmpBuff;
716        const char    *ptr = srcEnd - len;
717        size_t    rc = iconvTo(ptr, &len, &pTmpArr, gTempBuffArraySize);
718        if (rc == (size_t) -1 && errno != E2BIG) {
719            ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, manager);
720            /* return 0; */
721        }
722        rc = pTmpArr - tmpBuff;
723        totalLen += rc;
724        if (rc == 0 || len == 0)
725            break;
726    }
727    return totalLen;
728}
729
730
731char* IconvGNULCPTranscoder::transcode(const XMLCh* const toTranscode,
732                                       MemoryManager* const manager)
733{
734    if (!toTranscode)
735        return 0;
736
737    char* retVal = 0;
738    if (!*toTranscode) {
739        retVal = (char*) manager->allocate(sizeof(char));//new char[1];
740        retVal[0] = 0;
741        return retVal;
742    }
743
744    XMLSize_t wLent = getWideCharLength(toTranscode);
745
746    // Calc needed size.
747    XMLSize_t neededLen = calcRequiredSize (toTranscode, manager);
748    if (neededLen == 0)
749        return 0;
750    // allocate output buffer
751    retVal = (char*) manager->allocate((neededLen + 1) * sizeof(char));//new char[neededLen + 1];
752    // prepare the original
753    char    tmpWBuff[gTempBuffArraySize];
754    char    *wideCharBuf = 0;
755    char    *wBufPtr = 0;
756    ArrayJanitor<char>  janBuf(wBufPtr, manager);
757    size_t  len = wLent * uChSize();
758
759    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
760        if (len > gTempBuffArraySize) {
761            wBufPtr = (char*) manager->allocate(len * sizeof(char));//new char[len];
762            janBuf.reset(wBufPtr, manager);
763            wideCharBuf = wBufPtr;
764        } else
765            wideCharBuf = tmpWBuff;
766        xmlToMbs (toTranscode, wideCharBuf, wLent);
767    } else
768        wideCharBuf = (char *) toTranscode;
769
770    // perform conversion
771    char* ptr = retVal;
772    size_t rc;
773
774    {
775      XMLMutexLock lockConverter(&fMutex);
776      rc = iconvTo(wideCharBuf, &len, &ptr, neededLen);
777    }
778
779    if (rc == (size_t)-1) {
780        return 0;
781    }
782    retVal[neededLen] = 0;
783
784    return retVal;
785}
786
787
788bool IconvGNULCPTranscoder::transcode( const   XMLCh* const    toTranscode
789                    , char* const        toFill
790                    , const XMLSize_t       maxBytes
791                    , MemoryManager* const  manager)
792{
793    // Watch for a couple of pyscho corner cases
794    if (!toTranscode || !maxBytes) {
795        toFill[0] = 0;
796        return true;
797    }
798    if (!*toTranscode) {
799        toFill[0] = 0;
800        return true;
801    }
802
803    XMLSize_t wLent = getWideCharLength(toTranscode);
804    if (wLent > maxBytes)
805        wLent = maxBytes;
806
807    // Fill the "unicode" string
808    char    tmpWBuff[gTempBuffArraySize];
809    char    *wideCharBuf = 0;
810    char    *wBufPtr = 0;
811    ArrayJanitor<char>  janBuf(wBufPtr, manager);
812    size_t  len = wLent * uChSize();
813
814    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
815        if (len > gTempBuffArraySize) {
816            wBufPtr = (char*) manager->allocate(len * sizeof(char));//new char[len];
817            janBuf.reset(wBufPtr, manager);
818            wideCharBuf = wBufPtr;
819        } else
820            wideCharBuf = tmpWBuff;
821        xmlToMbs (toTranscode, wideCharBuf, wLent);
822    } else
823        wideCharBuf = (char *) toTranscode;
824
825    // Ok, go ahead and try the transcoding. If it fails, then ...
826    char    *ptr = toFill;
827    size_t rc;
828
829    {
830      XMLMutexLock lockConverter(&fMutex);
831      rc = iconvTo(wideCharBuf, &len, &ptr, maxBytes);
832    }
833
834    if (rc == (size_t)-1) {
835        return false;
836    }
837
838    // Cap it off
839    *ptr = 0;
840    return true;
841}
842
843
844XMLCh* IconvGNULCPTranscoder::transcode(const char* const toTranscode,
845                                        MemoryManager* const manager)
846{
847    if (!toTranscode)
848        return 0;
849
850    XMLCh* retVal = 0;
851    if (!*toTranscode) {
852        retVal = (XMLCh*) manager->allocate(sizeof(XMLCh));//new XMLCh[1];
853        retVal[0] = 0;
854        return retVal;
855    }
856
857    XMLSize_t wLent = calcRequiredSize(toTranscode, manager);
858    if (wLent == 0) {
859        retVal = (XMLCh*) manager->allocate(sizeof(XMLCh));//new XMLCh[1];
860        retVal[0] = 0;
861        return retVal;
862    }
863
864    char    tmpWBuff[gTempBuffArraySize];
865    char    *wideCharBuf = 0;
866    char    *wBufPtr = 0;
867    ArrayJanitor<char>  janBuf(wBufPtr, manager);
868    size_t  len = wLent * uChSize();
869
870    retVal = (XMLCh*) manager->allocate((wLent + 1) * sizeof(XMLCh));//new XMLCh[wLent + 1];
871    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
872        if (len > gTempBuffArraySize) {
873            wBufPtr = (char*) manager->allocate(len * sizeof(char));//new char[len];
874            janBuf.reset(wBufPtr, manager);
875            wideCharBuf = wBufPtr;
876        } else
877            wideCharBuf = tmpWBuff;
878    } else
879        wideCharBuf = (char *) retVal;
880
881    size_t    flen = strlen(toTranscode);
882    char    *ptr = wideCharBuf;
883    size_t rc;
884
885    {
886      XMLMutexLock lockConverter(&fMutex);
887      rc = iconvFrom(toTranscode, &flen, &ptr, len);
888    }
889
890    if (rc == (size_t) -1) {
891        return NULL;
892    }
893    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER)
894        mbsToXML (wideCharBuf, retVal, wLent);
895    retVal[wLent] = 0x00;
896
897    return retVal;
898}
899
900
901bool IconvGNULCPTranscoder::transcode(const   char* const    toTranscode
902                       ,       XMLCh* const    toFill
903                       , const XMLSize_t       maxChars
904                       , MemoryManager* const  manager)
905{
906    // Check for a couple of psycho corner cases
907    if (!toTranscode || !maxChars)
908    {
909        toFill[0] = 0;
910        return true;
911    }
912
913    if (!*toTranscode)
914    {
915        toFill[0] = 0;
916        return true;
917    }
918
919    XMLSize_t wLent = calcRequiredSize(toTranscode);
920    if (wLent > maxChars)
921        wLent = maxChars;
922
923    char    tmpWBuff[gTempBuffArraySize];
924    char    *wideCharBuf = 0;
925    char    *wBufPtr = 0;
926    ArrayJanitor<char>  janBuf(wBufPtr, manager);
927    size_t    len = wLent * uChSize();
928
929    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
930        if (len > gTempBuffArraySize) {
931            wBufPtr = (char*) manager->allocate(len * sizeof(char));//new char[len];
932            janBuf.reset(wBufPtr, manager);
933            wideCharBuf = wBufPtr;
934        } else
935            wideCharBuf = tmpWBuff;
936    } else
937        wideCharBuf = (char *) toFill;
938
939    size_t    flen = strlen(toTranscode); // wLent;
940    char    *ptr = wideCharBuf;
941    size_t rc;
942
943    {
944      XMLMutexLock lockConverter(&fMutex);
945      rc = iconvFrom(toTranscode, &flen, &ptr, len);
946    }
947
948    if (rc == (size_t)-1) {
949        return false;
950    }
951
952    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER)
953        mbsToXML (wideCharBuf, toFill, wLent);
954
955    toFill[wLent] = 0x00;
956    return true;
957}
958
959
960// ---------------------------------------------------------------------------
961//  IconvGNULCPTranscoder: Constructors and Destructor
962// ---------------------------------------------------------------------------
963
964
965IconvGNULCPTranscoder::IconvGNULCPTranscoder (iconv_t        cd_from,
966                        iconv_t        cd_to,
967                        size_t        uchsize,
968                        unsigned int    ubo,
969                        MemoryManager* manager)
970    : IconvGNUWrapper (cd_from, cd_to, uchsize, ubo, manager)
971{
972}
973
974
975IconvGNULCPTranscoder::~IconvGNULCPTranscoder()
976{
977}
978
979
980// ---------------------------------------------------------------------------
981//  IconvGNUTranscoder: Constructors and Destructor
982// ---------------------------------------------------------------------------
983IconvGNUTranscoder::IconvGNUTranscoder (const    XMLCh* const    encodingName
984                      , const XMLSize_t    blockSize
985                      ,    iconv_t        cd_from
986                      ,    iconv_t        cd_to
987                      ,    size_t        uchsize
988                      ,    unsigned int    ubo
989                      , MemoryManager* const manager
990    )
991    : XMLTranscoder(encodingName, blockSize, manager)
992    , IconvGNUWrapper (cd_from, cd_to, uchsize, ubo, manager)
993{
994}
995
996IconvGNUTranscoder::~IconvGNUTranscoder()
997{
998    if (cdTo() != (iconv_t)-1) {
999        iconv_close (cdTo());
1000        setCDTo ((iconv_t)-1);
1001    }
1002    if (cdFrom() != (iconv_t)-1) {
1003        iconv_close (cdFrom());
1004        setCDFrom ((iconv_t)-1);
1005    }
1006}
1007
1008// ---------------------------------------------------------------------------
1009//  IconvGNUTranscoder: Implementation of the virtual transcoder API
1010// ---------------------------------------------------------------------------
1011XMLSize_t    IconvGNUTranscoder::transcodeFrom
1012(
1013    const   XMLByte* const          srcData
1014    , const XMLSize_t               srcCount
1015    ,       XMLCh* const            toFill
1016    , const XMLSize_t               maxChars
1017    ,       XMLSize_t&              bytesEaten
1018    ,       unsigned char* const    charSizes )
1019{
1020    // Transcode TO XMLCh
1021    const char*  startSrc = (const char*) srcData;
1022    const char*  endSrc = (const char*) srcData + srcCount;
1023
1024    char    tmpWBuff[gTempBuffArraySize];
1025    char    *startTarget = 0;
1026    char    *wBufPtr = 0;
1027    ArrayJanitor<char>  janBuf(wBufPtr, getMemoryManager());
1028    size_t    len = maxChars * uChSize();
1029
1030    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
1031        if (len > gTempBuffArraySize) {
1032            wBufPtr = (char*) getMemoryManager()->allocate(len * sizeof(char));//new char[len];
1033            janBuf.reset(wBufPtr, getMemoryManager());
1034            startTarget = wBufPtr;
1035        } else
1036            startTarget = tmpWBuff;
1037    } else
1038        startTarget = (char *) toFill;
1039
1040    // Do character-by-character transcoding
1041    char    *orgTarget = startTarget;
1042    size_t    srcLen = srcCount;
1043    size_t    prevSrcLen = srcLen;
1044    unsigned int toReturn = 0;
1045
1046    bytesEaten = 0;
1047
1048    XMLMutexLock lockConverter(&fMutex);
1049
1050    for (size_t cnt = 0; cnt < maxChars && srcLen; cnt++) {
1051        size_t    rc = iconvFrom(startSrc, &srcLen, &orgTarget, uChSize());
1052        if (rc == (size_t)-1) {
1053            if (errno != E2BIG || prevSrcLen == srcLen) {
1054                ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, getMemoryManager());
1055            }
1056        }
1057        charSizes[cnt] = prevSrcLen - srcLen;
1058        prevSrcLen = srcLen;
1059        bytesEaten += charSizes[cnt];
1060        startSrc = endSrc - srcLen;
1061        toReturn++;
1062    }
1063    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER)
1064        mbsToXML (startTarget, toFill, toReturn);
1065    return toReturn;
1066}
1067
1068XMLSize_t IconvGNUTranscoder::transcodeFrom
1069(
1070      const XMLByte* const          srcData
1071    , const XMLSize_t               srcCount
1072    ,       XMLBuffer &             toFill
1073)
1074{
1075    toFill.reset();
1076    toFill.ensureCapacity(srcCount * (uChSize() / sizeof(XMLCh)));
1077
1078    // Transcode TO XMLCh
1079    const char*  startSrc = (const char*) srcData;
1080    const char*  endSrc = (const char*) srcData + srcCount;
1081
1082    char    tmpWBuff[gTempBuffArraySize];
1083    char    *startTarget = 0;
1084    char    *wBufPtr = 0;
1085    ArrayJanitor<char>  janBuf(wBufPtr, getMemoryManager());
1086    size_t    len = srcCount * uChSize();
1087
1088    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER)
1089    {
1090        if (len > gTempBuffArraySize)
1091        {
1092            wBufPtr = (char*) getMemoryManager()->allocate(len * sizeof(char));
1093            janBuf.reset(wBufPtr, getMemoryManager());
1094            startTarget = wBufPtr;
1095        }
1096        else
1097        {
1098            startTarget = tmpWBuff;
1099        }
1100    }
1101    else
1102    {
1103        startTarget = (char *)toFill.getRawBuffer();
1104    }
1105
1106    // Do character-by-character transcoding
1107    char    *orgTarget = startTarget;
1108    size_t    srcLen = srcCount;
1109    size_t    prevSrcLen = srcLen;
1110    unsigned int toReturn = 0;
1111
1112    XMLMutexLock lockConverter(&fMutex);
1113
1114    for (size_t cnt = 0; cnt < srcCount && srcLen; cnt++)
1115    {
1116        size_t    rc = iconvFrom(startSrc, &srcLen, &orgTarget, uChSize());
1117        if (rc == (size_t)-1)
1118        {
1119            if (errno != E2BIG || prevSrcLen == srcLen)
1120            {
1121                ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, getMemoryManager());
1122            }
1123        }
1124
1125        prevSrcLen = srcLen;
1126        startSrc = endSrc - srcLen;
1127        toReturn++;
1128    }
1129
1130    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER)
1131        mbsToXML (startTarget, toFill.getRawBuffer(), toReturn);
1132    return toReturn;
1133}
1134
1135XMLSize_t    IconvGNUTranscoder::transcodeTo
1136(
1137    const   XMLCh* const     srcData
1138    , const XMLSize_t        srcCount
1139    ,       XMLByte* const   toFill
1140    , const XMLSize_t        maxBytes
1141    ,       XMLSize_t&       charsEaten
1142    , const UnRepOpts        /*options*/ )
1143{
1144    // Transcode FROM XMLCh
1145    char    tmpWBuff[gTempBuffArraySize];
1146    char    *startSrc = tmpWBuff;
1147    char    *wBufPtr = 0;
1148    ArrayJanitor<char>  janBuf(wBufPtr, getMemoryManager());
1149    size_t    len = srcCount * uChSize();
1150
1151    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
1152        if (len > gTempBuffArraySize) {
1153            wBufPtr = (char*) getMemoryManager()->allocate(len * sizeof(char));//new char[len];
1154            janBuf.reset(wBufPtr, getMemoryManager());
1155            startSrc = wBufPtr;
1156        } else
1157            startSrc = tmpWBuff;
1158        xmlToMbs (srcData, startSrc, srcCount);
1159    } else
1160        startSrc = (char *) srcData;
1161
1162    char* startTarget = (char *) toFill;
1163    size_t srcLen = len;
1164
1165    size_t rc;
1166
1167    {
1168      XMLMutexLock lockConverter(&fMutex);
1169      rc = iconvTo (startSrc, &srcLen, &startTarget, maxBytes);
1170    }
1171
1172    if (rc == (size_t)-1 && errno != E2BIG) {
1173        ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, getMemoryManager());
1174    }
1175    charsEaten = srcCount - srcLen / uChSize();
1176    return startTarget - (char *)toFill;
1177}
1178
1179bool IconvGNUTranscoder::canTranscodeTo
1180(
1181    const unsigned int toCheck
1182)
1183{
1184    //
1185    //  If the passed value is really a surrogate embedded together, then
1186    //  we need to break it out into its two chars. Else just one.
1187    //
1188    char        srcBuf[MAX_UCHSIZE * 2];
1189    unsigned int    srcCount = 1;
1190    if (toCheck & 0xFFFF0000) {
1191        XMLCh    ch1 = (toCheck >> 10) + 0xD800;
1192        XMLCh    ch2 = (toCheck & 0x3FF) + 0xDC00;
1193        xmlToMbs(&ch1, srcBuf, 1);
1194        xmlToMbs(&ch2, srcBuf + uChSize(), 1);
1195        srcCount++;
1196    } else
1197        xmlToMbs((const XMLCh*) &toCheck, srcBuf, 1);
1198    size_t    len = srcCount * uChSize();
1199    char    tmpBuf[64];
1200    char*    pTmpBuf = tmpBuf;
1201
1202    XMLMutexLock lockConverter(&fMutex);
1203    size_t rc = iconvTo( srcBuf, &len, &pTmpBuf, 64);
1204
1205    return (rc != (size_t)-1) && (len == 0);
1206}
1207
1208XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.