source: icXML/icXML-devel/src/icxercesc/util/TransService.cpp

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

Changes to icxercesc files

File size: 23.8 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: TransService.cpp 933523 2010-04-13 08:53:39Z amassari $
20 */
21// ---------------------------------------------------------------------------
22//  Includes
23// ---------------------------------------------------------------------------
24#include <xercesc/util/Janitor.hpp>
25#include <icxercesc/util/TransService.hpp>
26#include <icxercesc/util/XML88591Transcoder.hpp>
27#include <icxercesc/util/XMLASCIITranscoder.hpp>
28#include <icxercesc/util/XMLChTranscoder.hpp>
29#include <xercesc/util/XMLEBCDICTranscoder.hpp>
30#include <xercesc/util/XMLIBM1047Transcoder.hpp>
31#include <xercesc/util/XMLIBM1140Transcoder.hpp>
32#include <icxercesc/util/XMLUCS4Transcoder.hpp>
33#include <icxercesc/util/XMLUTF8Transcoder.hpp>
34#include <icxercesc/util/XMLUTF16Transcoder.hpp>
35#include <xercesc/util/XMLWin1252Transcoder.hpp>
36#include <xercesc/util/XMLUniDefs.hpp>
37#include <xercesc/util/XMLUni.hpp>
38#include <xercesc/util/EncodingValidator.hpp>
39#include <icxercesc/util/PlatformUtils.hpp>
40#include <xercesc/util/TransENameMap.hpp>
41#include <xercesc/util/XMLInitializer.hpp>
42#include <xercesc/util/TranscodingException.hpp>
43
44XERCES_CPP_NAMESPACE_BEGIN
45
46// ---------------------------------------------------------------------------
47//  Local, static data
48//
49//  gStrictIANAEncoding
50//      A flag to control whether strict IANA encoding names checking should
51//      be done
52//
53// ---------------------------------------------------------------------------
54static bool gStrictIANAEncoding = false;
55RefHashTableOf<ENameMap>* XMLTransService::gMappings = 0;
56
57void XMLInitializer::initializeTransService()
58{
59        XMLTransService::gMappings = new RefHashTableOf<ENameMap>(103);
60}
61
62void XMLInitializer::terminateTransService()
63{
64        delete XMLTransService::gMappings;
65        XMLTransService::gMappings = 0;
66}
67
68// ---------------------------------------------------------------------------
69//  XMLTransService: Constructors and destructor
70// ---------------------------------------------------------------------------
71XMLTransService::XMLTransService()
72{
73}
74
75XMLTransService::~XMLTransService()
76{
77}
78
79// ---------------------------------------------------------------------------
80//    Allow user specific encodings to be added to the mappings table.
81//    Should be called after platform init
82// ---------------------------------------------------------------------------
83void XMLTransService::addEncoding(const XMLCh* const encoding,
84                                                                  ENameMap* const ownMapping)
85{
86        gMappings->put((void *) encoding, ownMapping);
87}
88
89// ---------------------------------------------------------------------------
90//  XMLTransService: Non-virtual API
91// ---------------------------------------------------------------------------
92// ---------------------------------------------------------------------------
93//  XMLTransService: Non-virtual API
94// ---------------------------------------------------------------------------
95XMLTranscoder*
96XMLTransService::makeNewTranscoderFor( const char* const             encodingName
97                                                                         ,       XMLTransService::Codes& resValue
98                                                                         , const XMLSize_t               blockSize
99                                                                         ,       MemoryManager* const    manager)
100{
101        XMLCh* tmpName = XMLString::transcode(encodingName, manager);
102        ArrayJanitor<XMLCh> janName(tmpName, manager);
103
104        return makeNewTranscoderFor(tmpName, resValue, blockSize, manager);
105}
106
107XMLTranscoder*
108XMLTransService::makeNewTranscoderFor( const XMLCh* const            encodingName
109                                                                         ,       XMLTransService::Codes& resValue
110                                                                         , const XMLSize_t               blockSize
111                                                                         ,       MemoryManager* const    manager)
112{
113        //
114        // If strict IANA encoding flag is set, validate encoding name
115        //
116        if (gStrictIANAEncoding)
117        {
118                if (!EncodingValidator::instance()->isValidEncoding(encodingName))
119                {
120                        resValue = XMLTransService::UnsupportedEncoding;
121                        return 0;
122                }
123        }
124
125        //
126        //  First try to find it in our list of mappings to intrinsically
127        //  supported encodings. We have to upper case the passed encoding
128        //  name because we use a hash table and we stored all our mappings
129        //  in all uppercase.
130        //
131        const XMLSize_t bufSize = 2048;
132        XMLCh upBuf[bufSize + 1];
133        if (!XMLString::copyNString(upBuf, encodingName, bufSize))
134        {
135                resValue = XMLTransService::InternalFailure;
136                return 0;
137        }
138        XMLString::upperCaseASCII(upBuf);
139        ENameMap* ourMapping = gMappings->get(upBuf);
140
141        // If we found it, then call the factory method for it
142        if (ourMapping)
143        {
144           XMLTranscoder* temp = ourMapping->makeNew(blockSize, manager);
145           resValue = temp ? XMLTransService::Ok : XMLTransService::InternalFailure;
146           return temp;
147        }
148
149        //
150        //  It wasn't an intrinsic and it wasn't disallowed, so pass it on
151        //  to the trans service to see if he can make anything of it.
152        //
153
154        XMLTranscoder* temp =  makeNewXMLTranscoder(encodingName, resValue, blockSize, manager);
155
156        // if successful, set resValue to OK
157        // if failed, the makeNewXMLTranscoder has already set the proper failing resValue
158        if (temp) resValue =  XMLTransService::Ok;
159
160        return temp;
161
162}
163
164
165XMLTranscoder*
166XMLTransService::makeNewTranscoderFor(  XMLRecognizer::Encodings        encodingEnum
167                                                                                ,       XMLTransService::Codes& resValue
168                                                                                , const XMLSize_t               blockSize
169                                                                                ,       MemoryManager* const    manager)
170{
171        //
172        // We can only make transcoder if the passed encodingEnum is under this range
173        //
174    if (encodingEnum < XMLRecognizer::Encodings_Min || encodingEnum > XMLRecognizer::Encodings_Max)
175    {
176                resValue = XMLTransService::InternalFailure;
177                return 0;
178        }
179
180    XMLTranscoder * transcoder;
181
182    switch (encodingEnum)
183    {
184        case XMLRecognizer::XERCES_XMLCH:
185            transcoder = new (manager) XMLChTranscoder(XMLUni::fgXMLChEncodingString, blockSize, manager);
186            break;
187        case XMLRecognizer::US_ASCII:
188            transcoder = new (manager) XMLASCIITranscoder(XMLUni::fgUSASCIIEncodingString, blockSize, manager);
189            break;
190        case XMLRecognizer::UTF_8:
191            transcoder = new (manager) XMLUTF8Transcoder(XMLUni::fgUTF8EncodingString, blockSize, manager);
192            break;
193        case XMLRecognizer::UTF_16L:
194            transcoder = new (manager) XMLUTF16Transcoder(XMLUni::fgUTF16LEncodingString, blockSize, XMLPlatformUtils::fgXMLChBigEndian, manager);
195            break;
196        case XMLRecognizer::UTF_16B:
197            transcoder = new (manager) XMLUTF16Transcoder(XMLUni::fgUTF16BEncodingString, blockSize, !XMLPlatformUtils::fgXMLChBigEndian, manager);
198            break;
199        case XMLRecognizer::UCS_4L:
200            transcoder = new (manager) XMLUCS4Transcoder(XMLUni::fgUCS4LEncodingString, blockSize, XMLPlatformUtils::fgXMLChBigEndian, manager);
201            break;
202        case XMLRecognizer::UCS_4B:
203            transcoder = new (manager) XMLUCS4Transcoder(XMLUni::fgUCS4BEncodingString, blockSize, !XMLPlatformUtils::fgXMLChBigEndian, manager);
204            break;
205        case XMLRecognizer::EBCDIC:
206            transcoder = new (manager) XMLEBCDICTranscoder(XMLUni::fgEBCDICEncodingString, blockSize, manager);
207            break;
208        default:
209            transcoder =  makeNewXMLTranscoder(XMLRecognizer::nameForEncoding(encodingEnum, manager), resValue, blockSize, manager);
210    }
211
212    if (transcoder)
213    {
214        resValue = XMLTransService::Ok;
215    }
216    else
217    {
218        resValue = XMLTransService::UnsupportedEncoding;
219    }
220
221    return transcoder;
222}
223
224// ---------------------------------------------------------------------------
225//  XMLTransTransService: Hidden Init Method
226//
227//  This is called by platform utils during startup.
228// ---------------------------------------------------------------------------
229void XMLTransService::initTransService()
230{
231        //
232        //  Add in the magical mapping for the native XMLCh transcoder. This
233        //  is used for internal entities.
234        //
235        gMappings->put((void*)XMLUni::fgXMLChEncodingString, new ENameMapFor<XMLChTranscoder>(XMLUni::fgXMLChEncodingString));
236
237        //
238        //  Add in our mappings for ASCII.
239        //
240        gMappings->put((void*)XMLUni::fgUSASCIIEncodingString, new ENameMapFor<XMLASCIITranscoder>(XMLUni::fgUSASCIIEncodingString));
241        gMappings->put((void*)XMLUni::fgUSASCIIEncodingString2, new ENameMapFor<XMLASCIITranscoder>(XMLUni::fgUSASCIIEncodingString2));
242        gMappings->put((void*)XMLUni::fgUSASCIIEncodingString3, new ENameMapFor<XMLASCIITranscoder>(XMLUni::fgUSASCIIEncodingString3));
243        gMappings->put((void*)XMLUni::fgUSASCIIEncodingString4, new ENameMapFor<XMLASCIITranscoder>(XMLUni::fgUSASCIIEncodingString4));
244
245        //
246        //  Add in our mappings for UTF-8
247        //
248        gMappings->put((void*)XMLUni::fgUTF8EncodingString, new ENameMapFor<XMLUTF8Transcoder>(XMLUni::fgUTF8EncodingString));
249        gMappings->put((void*)XMLUni::fgUTF8EncodingString2, new ENameMapFor<XMLUTF8Transcoder>(XMLUni::fgUTF8EncodingString2));
250
251        //
252        //  Add in our mappings for Latin1
253        //
254        gMappings->put((void*)XMLUni::fgISO88591EncodingString, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString));
255        gMappings->put((void*)XMLUni::fgISO88591EncodingString2, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString2));
256        gMappings->put((void*)XMLUni::fgISO88591EncodingString3, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString3));
257        gMappings->put((void*)XMLUni::fgISO88591EncodingString4, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString4));
258        gMappings->put((void*)XMLUni::fgISO88591EncodingString5, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString5));
259        gMappings->put((void*)XMLUni::fgISO88591EncodingString6, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString6));
260        gMappings->put((void*)XMLUni::fgISO88591EncodingString7, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString7));
261        gMappings->put((void*)XMLUni::fgISO88591EncodingString8, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString8));
262        gMappings->put((void*)XMLUni::fgISO88591EncodingString9, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString9));
263        gMappings->put((void*)XMLUni::fgISO88591EncodingString10, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString10));
264        gMappings->put((void*)XMLUni::fgISO88591EncodingString11, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString11));
265        gMappings->put((void*)XMLUni::fgISO88591EncodingString12, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString12));
266
267        //
268        //  Add in our mappings for UTF-16 and UCS-4, little endian
269        //
270    const bool swapped = XMLPlatformUtils::fgXMLChBigEndian;
271
272        gMappings->put
273        (
274                (void*)XMLUni::fgUTF16LEncodingString,
275                new EEndianNameMapFor<XMLUTF16Transcoder>
276                (
277                        XMLUni::fgUTF16LEncodingString
278                        , swapped
279                )
280        );
281
282        gMappings->put
283        (
284                (void*)XMLUni::fgUTF16LEncodingString2,
285                new EEndianNameMapFor<XMLUTF16Transcoder>
286                (
287                        XMLUni::fgUTF16LEncodingString2
288                        , swapped
289                )
290        );
291
292        gMappings->put
293        (
294                (void*)XMLUni::fgUCS4LEncodingString,
295                new EEndianNameMapFor<XMLUCS4Transcoder>
296                (
297                        XMLUni::fgUCS4LEncodingString
298                        , swapped
299                )
300        );
301
302        gMappings->put
303        (
304                (void*)XMLUni::fgUCS4LEncodingString2,
305                new EEndianNameMapFor<XMLUCS4Transcoder>
306                (
307                        XMLUni::fgUCS4LEncodingString2
308                        , swapped
309                )
310        );
311
312        //
313        //  Add in our mappings for UTF-16 and UCS-4, big endian
314        //
315
316        gMappings->put
317        (
318                (void*)XMLUni::fgUTF16BEncodingString,
319                new EEndianNameMapFor<XMLUTF16Transcoder>
320                (
321                        XMLUni::fgUTF16BEncodingString
322            , !swapped
323                )
324        );
325
326        gMappings->put
327        (
328                (void*)XMLUni::fgUTF16BEncodingString2,
329                new EEndianNameMapFor<XMLUTF16Transcoder>
330                (
331                        XMLUni::fgUTF16BEncodingString2
332            , !swapped
333                )
334        );
335
336        gMappings->put
337        (
338                (void*)XMLUni::fgUCS4BEncodingString,
339                new EEndianNameMapFor<XMLUCS4Transcoder>
340                (
341                        XMLUni::fgUCS4BEncodingString
342            , !swapped
343                )
344        );
345
346        gMappings->put
347        (
348                (void*)XMLUni::fgUCS4BEncodingString2,
349                new EEndianNameMapFor<XMLUCS4Transcoder>
350                (
351                        XMLUni::fgUCS4BEncodingString2
352            , !swapped
353                )
354        );
355
356        //
357        //  Add in our mappings for UTF-16 and UCS-4 which does not indicate endian
358        //  assumes the same endian encoding as the OS
359        //
360
361        gMappings->put
362        (
363                (void*)XMLUni::fgUTF16EncodingString,
364                new EEndianNameMapFor<XMLUTF16Transcoder>
365                (
366                        XMLUni::fgUTF16EncodingString
367                        , false
368                )
369        );
370        gMappings->put
371        (
372                (void*)XMLUni::fgUTF16EncodingString2,
373                new EEndianNameMapFor<XMLUTF16Transcoder>
374                (
375                        XMLUni::fgUTF16EncodingString2
376                        , false
377                )
378        );
379        gMappings->put
380        (
381                (void*)XMLUni::fgUTF16EncodingString3,
382                new EEndianNameMapFor<XMLUTF16Transcoder>
383                (
384                        XMLUni::fgUTF16EncodingString3
385                        , false
386                )
387        );
388        gMappings->put
389        (
390                (void*)XMLUni::fgUTF16EncodingString4,
391                new EEndianNameMapFor<XMLUTF16Transcoder>
392                (
393                        XMLUni::fgUTF16EncodingString4
394                        , false
395                )
396        );
397        gMappings->put
398        (
399                (void*)XMLUni::fgUTF16EncodingString5,
400                new EEndianNameMapFor<XMLUTF16Transcoder>
401                (
402                        XMLUni::fgUTF16EncodingString5
403                        , false
404                )
405        );
406        gMappings->put
407        (
408                (void*)XMLUni::fgUTF16EncodingString6,
409                new EEndianNameMapFor<XMLUTF16Transcoder>
410                (
411                        XMLUni::fgUTF16EncodingString6
412                        , false
413                )
414        );
415        gMappings->put
416        (
417                (void*)XMLUni::fgUTF16EncodingString7,
418                new EEndianNameMapFor<XMLUTF16Transcoder>
419                (
420                        XMLUni::fgUTF16EncodingString7
421                        , false
422                )
423        );
424        gMappings->put
425        (
426                (void*)XMLUni::fgUCS4EncodingString,
427                new EEndianNameMapFor<XMLUCS4Transcoder>
428                (
429                        XMLUni::fgUCS4EncodingString
430                        , false
431                )
432        );
433        gMappings->put
434        (
435                (void*)XMLUni::fgUCS4EncodingString2,
436                new EEndianNameMapFor<XMLUCS4Transcoder>
437                (
438                        XMLUni::fgUCS4EncodingString2
439                        , false
440                )
441        );
442        gMappings->put
443        (
444                (void*)XMLUni::fgUCS4EncodingString3,
445                new EEndianNameMapFor<XMLUCS4Transcoder>
446                (
447                        XMLUni::fgUCS4EncodingString3
448                        , false
449                )
450        );
451        gMappings->put
452        (
453                (void*)XMLUni::fgUCS4EncodingString4,
454                new EEndianNameMapFor<XMLUCS4Transcoder>
455                (
456                        XMLUni::fgUCS4EncodingString4
457                        , false
458                )
459        );
460        gMappings->put
461        (
462                (void*)XMLUni::fgUCS4EncodingString5,
463                new EEndianNameMapFor<XMLUCS4Transcoder>
464                (
465                        XMLUni::fgUCS4EncodingString5
466                        , false
467                )
468        );
469
470        //
471        //  Add in our mappings for IBM037, and the one alias we support for
472        //  it, which is EBCDIC-CP-US.
473        //
474
475        gMappings->put((void*)XMLUni::fgIBM037EncodingString, new ENameMapFor<XMLEBCDICTranscoder>(XMLUni::fgIBM037EncodingString));
476        gMappings->put((void*)XMLUni::fgIBM037EncodingString2, new ENameMapFor<XMLEBCDICTranscoder>(XMLUni::fgIBM037EncodingString2));
477
478
479    //
480    //  Add in our mappings for IBM1047, and the one alias we support for
481    //  it, which is EBCDIC-CP-US.
482    //
483        gMappings->put((void*)XMLUni::fgIBM1047EncodingString, new ENameMapFor<XMLIBM1047Transcoder>(XMLUni::fgIBM1047EncodingString));
484        gMappings->put((void*)XMLUni::fgIBM1047EncodingString2, new ENameMapFor<XMLIBM1047Transcoder>(XMLUni::fgIBM1047EncodingString2));
485
486        //
487        //  Add in our mappings for IBM037 with Euro update, i.e. IBM1140. It
488        //  has alias IBM01140, the one suggested by IANA
489        //
490        gMappings->put((void*)XMLUni::fgIBM1140EncodingString, new ENameMapFor<XMLIBM1140Transcoder>(XMLUni::fgIBM1140EncodingString));
491        gMappings->put((void*)XMLUni::fgIBM1140EncodingString2, new ENameMapFor<XMLIBM1140Transcoder>(XMLUni::fgIBM1140EncodingString2));
492        gMappings->put((void*)XMLUni::fgIBM1140EncodingString3, new ENameMapFor<XMLIBM1140Transcoder>(XMLUni::fgIBM1140EncodingString3));
493        gMappings->put((void*)XMLUni::fgIBM1140EncodingString4, new ENameMapFor<XMLIBM1140Transcoder>(XMLUni::fgIBM1140EncodingString4));
494
495        //
496        //  Add in our mappings for Windows-1252. We don't have any aliases for
497        //  this one, so there is just one mapping.
498        //
499        gMappings->put((void*)XMLUni::fgWin1252EncodingString, new ENameMapFor<XMLWin1252Transcoder>(XMLUni::fgWin1252EncodingString));
500
501}
502
503// ---------------------------------------------------------------------------
504//  XMLTransService: IANA encoding setting
505// ---------------------------------------------------------------------------
506void XMLTransService::strictIANAEncoding(const bool newState)
507{
508        gStrictIANAEncoding = newState;
509}
510
511bool XMLTransService::isStrictIANAEncoding()
512{
513        return gStrictIANAEncoding;
514}
515
516// ---------------------------------------------------------------------------
517//  XMLTranscoder: Is Swapped
518// ---------------------------------------------------------------------------
519bool XMLTranscoder::isSwapped() const
520{
521    return 0;
522}
523
524// ---------------------------------------------------------------------------
525//  XMLTranscoder: Public Destructor
526// ---------------------------------------------------------------------------
527XMLTranscoder::~XMLTranscoder()
528{
529
530}
531
532// ---------------------------------------------------------------------------
533//  XMLTranscoder: Hidden Constructors
534// ---------------------------------------------------------------------------
535XMLTranscoder::XMLTranscoder( const XMLCh* const    encodingName
536                                                        , const XMLSize_t       blockSize
537                                                        , MemoryManager* const  manager) :
538          fBlockSize(blockSize)
539        , fEncodingName(const_cast<XMLCh*>(encodingName))
540        , fMemoryManager(manager)
541{
542
543}
544
545// ---------------------------------------------------------------------------
546//  XMLCharacterSetAdapter: Public Destructor
547// ---------------------------------------------------------------------------
548
549XMLCharacterSetAdapter::~XMLCharacterSetAdapter()
550{
551
552}
553
554// ---------------------------------------------------------------------------
555//  XMLLCPTranscoder: Public Destructor
556// ---------------------------------------------------------------------------
557XMLLCPTranscoder::XMLLCPTranscoder()
558{
559}
560
561
562// ---------------------------------------------------------------------------
563//  XMLLCPTranscoder: Hidden Constructors
564// ---------------------------------------------------------------------------
565XMLLCPTranscoder::~XMLLCPTranscoder()
566{
567}
568
569// ---------------------------------------------------------------------------
570//  TranscodeToStr: Public constructors and destructor
571// ---------------------------------------------------------------------------
572TranscodeToStr::TranscodeToStr(const XMLCh *in, const char *encoding,
573                                                           MemoryManager *manager)
574        : fString(0),
575          fBytesWritten(0),
576          fMemoryManager(manager)
577{
578        XMLTransService::Codes failReason;
579        const XMLSize_t blockSize = 2048;
580
581        XMLTranscoder* trans = XMLPlatformUtils::fgTransService->makeNewTranscoderFor(encoding, failReason, blockSize, fMemoryManager);
582        Janitor<XMLTranscoder> janTrans(trans);
583
584        transcode(in, XMLString::stringLen(in), trans);
585}
586
587TranscodeToStr::TranscodeToStr(const XMLCh *in, XMLSize_t length, const char *encoding,
588                                                           MemoryManager *manager)
589        : fString(0),
590          fBytesWritten(0),
591          fMemoryManager(manager)
592{
593        XMLTransService::Codes failReason;
594        const XMLSize_t blockSize = 2048;
595
596        XMLTranscoder* trans = XMLPlatformUtils::fgTransService->makeNewTranscoderFor(encoding, failReason, blockSize, fMemoryManager);
597        Janitor<XMLTranscoder> janTrans(trans);
598
599        transcode(in, length, trans);
600}
601
602TranscodeToStr::TranscodeToStr(const XMLCh *in, XMLTranscoder* trans,
603                                                           MemoryManager *manager)
604        : fString(0),
605          fBytesWritten(0),
606          fMemoryManager(manager)
607{
608        transcode(in, XMLString::stringLen(in), trans);
609}
610
611TranscodeToStr::TranscodeToStr(const XMLCh *in, XMLSize_t length, XMLTranscoder* trans,
612                                                           MemoryManager *manager)
613        : fString(0),
614          fBytesWritten(0),
615          fMemoryManager(manager)
616{
617        transcode(in, length, trans);
618}
619
620TranscodeToStr::~TranscodeToStr()
621{
622        if(fString)
623                fMemoryManager->deallocate(fString);
624}
625
626// ---------------------------------------------------------------------------
627//  TranscodeToStr: Private helper methods
628// ---------------------------------------------------------------------------
629void TranscodeToStr::transcode(const XMLCh *in, XMLSize_t len, XMLTranscoder* trans)
630{
631        if(!in) return;
632
633        XMLSize_t allocSize = len * sizeof(XMLCh);
634        fString = (XMLByte*)fMemoryManager->allocate(allocSize);
635
636        XMLSize_t charsRead = 0;
637        XMLSize_t charsDone = 0;
638
639        while(true) {
640                fBytesWritten += trans->transcodeTo(in + charsDone, len - charsDone,
641                                                                                        fString + fBytesWritten, allocSize - fBytesWritten,
642                                                                                        charsRead, XMLTranscoder::UnRep_Throw);
643                if(charsRead == 0)
644                        ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, fMemoryManager);
645
646                charsDone += charsRead;
647
648                if(charsDone == len) break;
649
650                allocSize *= 2;
651                XMLByte *newBuf = (XMLByte*)fMemoryManager->allocate(allocSize);
652                memcpy(newBuf, fString, fBytesWritten);
653                fMemoryManager->deallocate(fString);
654                fString = newBuf;
655        }
656
657        // null terminate
658        if((fBytesWritten + 4) > allocSize) {
659                allocSize = fBytesWritten + 4;
660                XMLByte *newBuf = (XMLByte*)fMemoryManager->allocate(allocSize);
661                memcpy(newBuf, fString, fBytesWritten);
662                fMemoryManager->deallocate(fString);
663                fString = newBuf;
664        }
665        fString[fBytesWritten + 0] = 0;
666        fString[fBytesWritten + 1] = 0;
667        fString[fBytesWritten + 2] = 0;
668        fString[fBytesWritten + 3] = 0;
669}
670
671// ---------------------------------------------------------------------------
672//  TranscodeFromStr: Public constructors and destructor
673// ---------------------------------------------------------------------------
674TranscodeFromStr::TranscodeFromStr(const XMLByte *data, XMLSize_t length, const char *encoding,
675                                                                   MemoryManager *manager)
676        : fString(0),
677          fCharsWritten(0),
678          fMemoryManager(manager)
679{
680        XMLTransService::Codes failReason;
681        const XMLSize_t blockSize = 2048;
682
683        XMLTranscoder* trans = XMLPlatformUtils::fgTransService->makeNewTranscoderFor(encoding, failReason, blockSize, fMemoryManager);
684        Janitor<XMLTranscoder> janTrans(trans);
685
686        transcode(data, length, trans);
687}
688
689TranscodeFromStr::TranscodeFromStr(const XMLByte *data, XMLSize_t length, XMLTranscoder *trans,
690                                                                   MemoryManager *manager)
691        : fString(0),
692          fCharsWritten(0),
693          fMemoryManager(manager)
694{
695        transcode(data, length, trans);
696}
697
698TranscodeFromStr::~TranscodeFromStr()
699{
700        if(fString)
701                fMemoryManager->deallocate(fString);
702}
703
704// ---------------------------------------------------------------------------
705//  TranscodeFromStr: Private helper methods
706// ---------------------------------------------------------------------------
707void TranscodeFromStr::transcode(const XMLByte *in, XMLSize_t length, XMLTranscoder *trans)
708{
709        if(!in) return;
710
711        XMLSize_t allocSize = length + 1;
712        fString = (XMLCh*)fMemoryManager->allocate(allocSize * sizeof(XMLCh));
713
714        XMLSize_t csSize = length;
715        ArrayJanitor<unsigned char> charSizes((unsigned char*)fMemoryManager->allocate(csSize * sizeof(unsigned char)),
716                                                                                  fMemoryManager);
717
718        XMLSize_t bytesRead = 0;
719        XMLSize_t bytesDone = 0;
720
721        while(true) {
722                fCharsWritten += trans->transcodeFrom(in + bytesDone, length - bytesDone,
723                                                                                          fString + fCharsWritten, allocSize - fCharsWritten,
724                                                                                          bytesRead, charSizes.get());
725                if(bytesRead == 0)
726                        ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, fMemoryManager);
727
728                bytesDone += bytesRead;
729                if(bytesDone == length) break;
730
731                allocSize *= 2;
732                XMLCh *newBuf = (XMLCh*)fMemoryManager->allocate(allocSize * sizeof(XMLCh));
733                memcpy(newBuf, fString, fCharsWritten);
734                fMemoryManager->deallocate(fString);
735                fString = newBuf;
736
737                if((allocSize - fCharsWritten) > csSize) {
738                        csSize = allocSize - fCharsWritten;
739                        charSizes.reset((unsigned char*)fMemoryManager->allocate(csSize * sizeof(unsigned char)),
740                                                        fMemoryManager);
741                }
742        }
743
744        // null terminate
745        if(fCharsWritten == allocSize) {
746                allocSize += 1;
747                XMLCh *newBuf = (XMLCh*)fMemoryManager->allocate(allocSize * sizeof(XMLCh));
748                memcpy(newBuf, fString, fCharsWritten);
749                fMemoryManager->deallocate(fString);
750                fString = newBuf;
751        }
752        fString[fCharsWritten] = 0;
753}
754
755XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.