source: icXML/icXML-devel/src/xercesc/util/Transcoders/Iconv/IconvTransService.cpp @ 2722

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

Original Xerces files with import mods for icxercesc

File size: 15.6 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: IconvTransService.cpp 695885 2008-09-16 14:00:19Z borisk $
20 */
21
22
23// ---------------------------------------------------------------------------
24//  Includes
25// ---------------------------------------------------------------------------
26
27#if HAVE_CONFIG_H
28#       include <config.h>
29#endif
30
31#if HAVE_WCHAR_H
32#       include <wchar.h>
33#endif
34#if HAVE_WCTYPE_H
35#       include <wctype.h>
36#endif
37
38// Fill in for broken or missing wctype functions on some platforms
39#if !HAVE_TOWUPPER
40#       include <towupper.h>
41#endif
42#if !HAVE_TOWLOWER
43#       include <towlower.h>
44#endif
45
46#include <string.h>
47#include <stdlib.h>
48#include <stdio.h>
49
50#include "IconvTransService.hpp"
51#include <xercesc/util/XMLUniDefs.hpp>
52#include <xercesc/util/XMLUni.hpp>
53#include <xercesc/framework/MemoryManager.hpp>
54
55
56XERCES_CPP_NAMESPACE_BEGIN
57
58// ---------------------------------------------------------------------------
59//  Local, const data
60// ---------------------------------------------------------------------------
61static const int    gTempBuffArraySize = 1024;
62static const XMLCh  gMyServiceId[] =
63{
64    chLatin_I, chLatin_C, chLatin_o, chLatin_n, chLatin_v, chNull
65};
66
67// ---------------------------------------------------------------------------
68// the following is defined by 'man mbrtowc':
69// ---------------------------------------------------------------------------
70static const size_t TRANSCODING_ERROR = (size_t)(-1);
71
72// ---------------------------------------------------------------------------
73//  Local methods
74// ---------------------------------------------------------------------------
75static unsigned int getWideCharLength(const XMLCh* const src)
76{
77    if (!src)
78        return 0;
79
80    unsigned int len = 0;
81    const XMLCh* pTmp = src;
82    while (*pTmp++)
83        len++;
84    return len;
85}
86
87
88
89// ---------------------------------------------------------------------------
90//  IconvTransService: Constructors and Destructor
91// ---------------------------------------------------------------------------
92IconvTransService::IconvTransService(MemoryManager* /* manager */)
93{
94}
95
96IconvTransService::~IconvTransService()
97{
98}
99
100
101// ---------------------------------------------------------------------------
102//  IconvTransService: The virtual transcoding service API
103// ---------------------------------------------------------------------------
104int IconvTransService::compareIString(  const   XMLCh* const    comp1
105                                        , const XMLCh* const    comp2)
106{
107    const XMLCh* cptr1 = comp1;
108    const XMLCh* cptr2 = comp2;
109
110    while ( (*cptr1 != 0) && (*cptr2 != 0) )
111    {
112        wint_t wch1 = towupper(*cptr1);
113        wint_t wch2 = towupper(*cptr2);
114        if (wch1 != wch2)
115            break;
116
117        cptr1++;
118        cptr2++;
119    }
120    return (int) ( towupper(*cptr1) - towupper(*cptr2) );
121}
122
123
124int IconvTransService::compareNIString( const   XMLCh* const    comp1
125                                        , const XMLCh* const    comp2
126                                        , const XMLSize_t       maxChars)
127{
128    unsigned int  n = 0;
129    const XMLCh* cptr1 = comp1;
130    const XMLCh* cptr2 = comp2;
131
132    while (true && maxChars)
133    {
134        wint_t wch1 = towupper(*cptr1);
135        wint_t wch2 = towupper(*cptr2);
136
137        if (wch1 != wch2)
138            return (int) (wch1 - wch2);
139
140        // If either ended, then both ended, so equal
141        if (!*cptr1 || !*cptr2)
142            break;
143
144        cptr1++;
145        cptr2++;
146
147        //  Bump the count of chars done. If it equals the count then we
148        //  are equal for the requested count, so break out and return
149        //  equal.
150        n++;
151        if (n == maxChars)
152            break;
153    }
154
155    return 0;
156}
157
158
159const XMLCh* IconvTransService::getId() const
160{
161    return gMyServiceId;
162}
163
164XMLLCPTranscoder* IconvTransService::makeNewLCPTranscoder(MemoryManager* manager)
165{
166    // Just allocate a new transcoder of our type
167    return new (manager) IconvLCPTranscoder;
168}
169
170bool IconvTransService::supportsSrcOfs() const
171{
172    return true;
173}
174
175
176// ---------------------------------------------------------------------------
177//  IconvTransService: The protected virtual transcoding service API
178// ---------------------------------------------------------------------------
179XMLTranscoder*
180IconvTransService::makeNewXMLTranscoder(const   XMLCh* const
181                                        ,       XMLTransService::Codes& resValue
182                                        , const XMLSize_t
183                                        ,       MemoryManager* const)
184{
185    //
186    //  NOTE: We don't use the block size here
187    //
188    //  This is a minimalist transcoding service, that only supports a local
189    //  default transcoder. All named encodings return zero as a failure,
190    //  which means that only the intrinsic encodings supported by the parser
191    //  itself will work for XML data.
192    //
193    resValue = XMLTransService::UnsupportedEncoding;
194    return 0;
195}
196
197
198void IconvTransService::upperCase(XMLCh* const toUpperCase)
199{
200    XMLCh* outPtr = toUpperCase;
201    while (*outPtr)
202    {
203        *outPtr = towupper(*outPtr);
204        outPtr++;
205    }
206}
207
208
209void IconvTransService::lowerCase(XMLCh* const toLowerCase)
210{
211    XMLCh* outPtr = toLowerCase;
212    while (*outPtr)
213    {
214        *outPtr = towlower(*outPtr);
215        outPtr++;
216    }
217}
218
219
220// ---------------------------------------------------------------------------
221//  IconvLCPTranscoder: The virtual transcoder API
222// ---------------------------------------------------------------------------
223XMLSize_t IconvLCPTranscoder::calcRequiredSize(const char* const srcText
224                                                  , MemoryManager* const)
225{
226    if (!srcText)
227        return 0;
228
229    XMLSize_t len = 0;
230    const char *src = srcText;
231#if HAVE_MBRLEN
232    mbstate_t st;
233    memset(&st, 0, sizeof(st));
234#endif
235    for ( ; *src; ++len)
236    {
237#if HAVE_MBRLEN
238        int l=::mbrlen( src, MB_CUR_MAX, &st );
239#else
240        int l=::mblen( src, MB_CUR_MAX );
241#endif
242        if( l == TRANSCODING_ERROR )
243            return 0;
244        src += l;
245    }
246    return len;
247}
248
249
250XMLSize_t IconvLCPTranscoder::calcRequiredSize(const XMLCh* const srcText
251                                                  , MemoryManager* const manager)
252{
253    if (!srcText)
254        return 0;
255
256    XMLSize_t     wLent = getWideCharLength(srcText);
257    wchar_t       tmpWideCharArr[gTempBuffArraySize];
258    wchar_t*      allocatedArray = 0;
259    wchar_t*      wideCharBuf = 0;
260
261    if (wLent >= gTempBuffArraySize)
262        wideCharBuf = allocatedArray = (wchar_t*)
263            manager->allocate
264            (
265                (wLent + 1) * sizeof(wchar_t)
266            );//new wchar_t[wLent + 1];
267    else
268        wideCharBuf = tmpWideCharArr;
269
270    for (XMLSize_t i = 0; i < wLent; i++)
271    {
272        wideCharBuf[i] = srcText[i];
273    }
274    wideCharBuf[wLent] = 0x00;
275
276    const XMLSize_t retVal = ::wcstombs(NULL, wideCharBuf, 0);
277
278    if (allocatedArray)
279      manager->deallocate(allocatedArray);
280
281    if (retVal == ~0)
282        return 0;
283    return retVal;
284}
285
286
287bool IconvLCPTranscoder::transcode( const   XMLCh* const    toTranscode
288                                    ,       char* const     toFill
289                                    , const XMLSize_t       maxBytes
290                                    , MemoryManager* const  manager)
291{
292    // Watch for a couple of pyscho corner cases
293    if (!toTranscode || !maxBytes)
294    {
295        toFill[0] = 0;
296        return true;
297    }
298
299    if (!*toTranscode)
300    {
301        toFill[0] = 0;
302        return true;
303    }
304
305    unsigned int  wLent = getWideCharLength(toTranscode);
306    wchar_t       tmpWideCharArr[gTempBuffArraySize];
307    wchar_t*      allocatedArray = 0;
308    wchar_t*      wideCharBuf = 0;
309
310    if (wLent > maxBytes) {
311        wLent = maxBytes;
312    }
313
314    if (maxBytes >= gTempBuffArraySize) {
315        wideCharBuf = allocatedArray = (wchar_t*)
316            manager->allocate
317            (
318                (maxBytes + 1) * sizeof(wchar_t)
319            );//new wchar_t[maxBytes + 1];
320    }
321    else
322        wideCharBuf = tmpWideCharArr;
323
324    for (unsigned int i = 0; i < wLent; i++)
325    {
326        wideCharBuf[i] = toTranscode[i];
327    }
328    wideCharBuf[wLent] = 0x00;
329
330    // Ok, go ahead and try the transcoding. If it fails, then ...
331    size_t mblen = ::wcstombs(toFill, wideCharBuf, maxBytes);
332    if (mblen == (size_t)-1)
333    {
334        if (allocatedArray)
335          manager->deallocate(allocatedArray);
336        return false;
337    }
338
339    // Cap it off just in case
340    toFill[mblen] = 0;
341
342    if (allocatedArray)
343      manager->deallocate(allocatedArray);
344
345    return true;
346}
347
348
349bool IconvLCPTranscoder::transcode( const   char* const     toTranscode
350                                    ,       XMLCh* const    toFill
351                                    , const XMLSize_t       maxChars
352                                    , MemoryManager* const  manager)
353{
354    // Check for a couple of psycho corner cases
355    if (!toTranscode || !maxChars)
356    {
357        toFill[0] = 0;
358        return true;
359    }
360
361    if (!*toTranscode)
362    {
363        toFill[0] = 0;
364        return true;
365    }
366
367    XMLSize_t     len = calcRequiredSize(toTranscode);
368    wchar_t       tmpWideCharArr[gTempBuffArraySize];
369    wchar_t*      allocatedArray = 0;
370    wchar_t*      wideCharBuf = 0;
371
372    if (len > maxChars) {
373        len = maxChars;
374    }
375
376    if (maxChars >= gTempBuffArraySize)
377        wideCharBuf = allocatedArray = (wchar_t*) manager->allocate
378        (
379            (maxChars + 1) * sizeof(wchar_t)
380        );//new wchar_t[maxChars + 1];
381    else
382        wideCharBuf = tmpWideCharArr;
383
384    if (::mbstowcs(wideCharBuf, toTranscode, maxChars) == (size_t)-1)
385    {
386        if (allocatedArray)
387          manager->deallocate(allocatedArray);
388        return false;
389    }
390
391    for (XMLSize_t i = 0; i < len; i++)
392    {
393        toFill[i] = (XMLCh) wideCharBuf[i];
394    }
395    toFill[len] = 0x00;
396
397    if (allocatedArray)
398      manager->deallocate(allocatedArray);
399
400    return true;
401}
402
403
404template <typename T>
405void reallocString(T *&ref, size_t &size, MemoryManager* const manager, bool releaseOld)
406{
407    T *tmp = (T*)manager->allocate(2 * size * sizeof(T));
408    memcpy(tmp, ref, size * sizeof(T));
409    if (releaseOld) manager->deallocate(ref);
410    ref = tmp;
411    size *= 2;
412}
413
414
415char* IconvLCPTranscoder::transcode(const XMLCh* const toTranscode,
416                                    MemoryManager* const manager)
417{
418    if (!toTranscode)
419        return 0;
420    size_t srcCursor = 0, dstCursor = 0;
421    size_t resultSize = gTempBuffArraySize;
422    char localBuffer[gTempBuffArraySize];
423    char* resultString = localBuffer;
424
425#if HAVE_WCSRTOMBS
426    mbstate_t st;
427    memset(&st, 0, sizeof(st));
428    wchar_t srcBuffer[gTempBuffArraySize];
429    srcBuffer[gTempBuffArraySize - 1] = 0;
430    const wchar_t *src = 0;
431
432    while (toTranscode[srcCursor] || src)
433    {
434        if (src == 0) // copy a piece of the source string into a local
435                      // buffer, converted to wchar_t and NULL-terminated.
436                      // after that, src points to the beginning of the
437                      // local buffer and is used for the call to ::wcsrtombs
438        {
439            size_t i;
440            for (i=0; i<gTempBuffArraySize-1; ++i)
441            {
442                srcBuffer[i] = toTranscode[srcCursor];
443                if (srcBuffer[i] == '\0')
444                    break;
445                ++srcCursor;
446            }
447            src = srcBuffer;
448        }
449
450        size_t len = ::wcsrtombs(resultString + dstCursor, &src, resultSize - dstCursor, &st);
451        if (len == TRANSCODING_ERROR)
452        {
453            dstCursor = 0;
454            break;
455        }
456        dstCursor += len;
457        if (src != 0) // conversion not finished. This *always* means there
458                      // was not enough room in the destination buffer.
459        {
460            reallocString<char>(resultString, resultSize, manager, resultString != localBuffer);
461        }
462    }
463#else
464    while (toTranscode[srcCursor])
465    {
466        char mbBuf[16]; // MB_CUR_MAX is not defined as a constant on some platforms
467        int len = wctomb(mbBuf, toTranscode[srcCursor++]);
468        if (len < 0)
469        {
470            dstCursor = 0;
471            break;
472        }
473        if (dstCursor + len >= resultSize - 1)
474            reallocString<char>(resultString, resultSize, manager, resultString != localBuffer);
475        for (int j=0; j<len; ++j)
476            resultString[dstCursor++] = mbBuf[j];
477    }
478#endif
479
480    if (resultString == localBuffer)
481    {
482        resultString = (char*)manager->allocate((dstCursor + 1) * sizeof(char));
483        memcpy(resultString, localBuffer, dstCursor * sizeof(char));
484    }
485
486    resultString[dstCursor] = '\0';
487    return resultString;
488}
489
490XMLCh* IconvLCPTranscoder::transcode(const char* const toTranscode,
491                                     MemoryManager* const manager)
492{
493    if (!toTranscode)
494        return 0;
495    size_t resultSize = gTempBuffArraySize;
496    size_t srcCursor = 0, dstCursor = 0;
497
498#if HAVE_MBSRTOWCS
499    wchar_t localBuffer[gTempBuffArraySize];
500    wchar_t *tmpString = localBuffer;
501
502    mbstate_t st;
503    memset(&st, 0, sizeof(st));
504    const char *src = toTranscode;
505
506    while(true)
507    {
508        size_t len = ::mbsrtowcs(tmpString + dstCursor, &src, resultSize - dstCursor, &st);
509        if (len == TRANSCODING_ERROR)
510        {
511            dstCursor = 0;
512            break;
513        }
514        dstCursor += len;
515        if (src == 0) // conversion finished
516            break;
517        if (dstCursor >= resultSize - 1)
518            reallocString<wchar_t>(tmpString, resultSize, manager, tmpString != localBuffer);
519    }
520    // make a final copy, converting from wchar_t to XMLCh:
521    XMLCh* resultString = (XMLCh*)manager->allocate((dstCursor + 1) * sizeof(XMLCh));
522    size_t i;
523    for (i=0; i<dstCursor; ++i)
524        resultString[i] = tmpString[i];
525    if (tmpString != localBuffer) // did we allocate something?
526        manager->deallocate(tmpString);
527#else
528    XMLCh localBuffer[gTempBuffArraySize];
529    XMLCh* resultString = localBuffer;
530    size_t srcLen = strlen(toTranscode);
531
532    while(srcLen > srcCursor)
533    {
534        wchar_t wcBuf[1];
535        int len = mbtowc(wcBuf, toTranscode + srcCursor, srcLen - srcCursor);
536        if (len <= 0)
537        {
538            if (len < 0)
539                dstCursor = 0;
540            break;
541        }
542        srcCursor += len;
543        if (dstCursor + 1 >= resultSize - 1)
544            reallocString<XMLCh>(resultString, resultSize, manager, resultString != localBuffer);
545        resultString[dstCursor++] = wcBuf[0];
546    }
547
548    if (resultString == localBuffer)
549    {
550        resultString = (XMLCh*)manager->allocate((dstCursor + 1) * sizeof(XMLCh));
551        memcpy(resultString, localBuffer, dstCursor * sizeof(XMLCh));
552    }
553#endif
554
555    resultString[dstCursor] = L'\0';
556    return resultString;
557}
558
559
560// ---------------------------------------------------------------------------
561//  IconvLCPTranscoder: Constructors and Destructor
562// ---------------------------------------------------------------------------
563IconvLCPTranscoder::IconvLCPTranscoder()
564{
565}
566
567IconvLCPTranscoder::~IconvLCPTranscoder()
568{
569}
570
571XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.