GME  13
TransService.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: TransService.cpp 933523 2010-04-13 08:53:39Z amassari $
00020  */
00021 // ---------------------------------------------------------------------------
00022 //  Includes
00023 // ---------------------------------------------------------------------------
00024 #include <xercesc/util/Janitor.hpp>
00025 #include <xercesc/util/TransService.hpp>
00026 #include <xercesc/util/XML88591Transcoder.hpp>
00027 #include <xercesc/util/XMLASCIITranscoder.hpp>
00028 #include <xercesc/util/XMLChTranscoder.hpp>
00029 #include <xercesc/util/XMLEBCDICTranscoder.hpp>
00030 #include <xercesc/util/XMLIBM1047Transcoder.hpp>
00031 #include <xercesc/util/XMLIBM1140Transcoder.hpp>
00032 #include <xercesc/util/XMLUCS4Transcoder.hpp>
00033 #include <xercesc/util/XMLUTF8Transcoder.hpp>
00034 #include <xercesc/util/XMLUTF16Transcoder.hpp>
00035 #include <xercesc/util/XMLWin1252Transcoder.hpp>
00036 #include <xercesc/util/XMLUniDefs.hpp>
00037 #include <xercesc/util/XMLUni.hpp>
00038 #include <xercesc/util/EncodingValidator.hpp>
00039 #include <xercesc/util/PlatformUtils.hpp>
00040 #include <xercesc/util/TransENameMap.hpp>
00041 #include <xercesc/util/XMLInitializer.hpp>
00042 #include <xercesc/util/TranscodingException.hpp>
00043 
00044 XERCES_CPP_NAMESPACE_BEGIN
00045 
00046 // ---------------------------------------------------------------------------
00047 //  Local, static data
00048 //
00049 //  gStrictIANAEncoding
00050 //      A flag to control whether strict IANA encoding names checking should
00051 //      be done
00052 //
00053 // ---------------------------------------------------------------------------
00054 static bool gStrictIANAEncoding = false;
00055 RefHashTableOf<ENameMap>* XMLTransService::gMappings = 0;
00056 RefVectorOf<ENameMap> * XMLTransService::gMappingsRecognizer = 0;
00057 
00058 void XMLInitializer::initializeTransService()
00059 {
00060     XMLTransService::gMappings = new RefHashTableOf<ENameMap>(103);
00061     XMLTransService::gMappingsRecognizer = new RefVectorOf<ENameMap>(
00062       (XMLSize_t)XMLRecognizer::Encodings_Count);
00063 }
00064 
00065 void XMLInitializer::terminateTransService()
00066 {
00067     delete XMLTransService::gMappingsRecognizer;
00068     XMLTransService::gMappingsRecognizer = 0;
00069 
00070     delete XMLTransService::gMappings;
00071     XMLTransService::gMappings = 0;
00072 }
00073 
00074 // ---------------------------------------------------------------------------
00075 //  XMLTransService: Constructors and destructor
00076 // ---------------------------------------------------------------------------
00077 XMLTransService::XMLTransService()
00078 {
00079 }
00080 
00081 XMLTransService::~XMLTransService()
00082 {
00083 }
00084 
00085 // ---------------------------------------------------------------------------
00086 //    Allow user specific encodings to be added to the mappings table.
00087 //    Should be called after platform init
00088 // ---------------------------------------------------------------------------
00089 void XMLTransService::addEncoding(const XMLCh* const encoding,
00090                                   ENameMap* const ownMapping)
00091 {
00092     gMappings->put((void *) encoding, ownMapping);
00093 }
00094 
00095 // ---------------------------------------------------------------------------
00096 //  XMLTransService: Non-virtual API
00097 // ---------------------------------------------------------------------------
00098 XMLTranscoder*
00099 XMLTransService::makeNewTranscoderFor(  const   char* const             encodingName
00100                                         ,       XMLTransService::Codes& resValue
00101                                         , const XMLSize_t               blockSize
00102                                         ,       MemoryManager* const    manager)
00103 {
00104     XMLCh* tmpName = XMLString::transcode(encodingName, manager);
00105     ArrayJanitor<XMLCh> janName(tmpName, manager);
00106 
00107     return makeNewTranscoderFor(tmpName, resValue, blockSize, manager);
00108 }
00109 
00110 XMLTranscoder*
00111 XMLTransService::makeNewTranscoderFor(  const   XMLCh* const            encodingName
00112                                         ,       XMLTransService::Codes& resValue
00113                                         , const XMLSize_t               blockSize
00114                                         ,       MemoryManager* const    manager)
00115 {
00116     //
00117     // If strict IANA encoding flag is set, validate encoding name
00118     //
00119     if (gStrictIANAEncoding)
00120     {
00121         if (!EncodingValidator::instance()->isValidEncoding(encodingName))
00122         {
00123             resValue = XMLTransService::UnsupportedEncoding;
00124             return 0;
00125         }
00126     }
00127 
00128     //
00129     //  First try to find it in our list of mappings to intrinsically
00130     //  supported encodings. We have to upper case the passed encoding
00131     //  name because we use a hash table and we stored all our mappings
00132     //  in all uppercase.
00133     //
00134     const XMLSize_t bufSize = 2048;
00135     XMLCh upBuf[bufSize + 1];
00136     if (!XMLString::copyNString(upBuf, encodingName, bufSize))
00137     {
00138         resValue = XMLTransService::InternalFailure;
00139         return 0;
00140     }
00141     XMLString::upperCaseASCII(upBuf);
00142     ENameMap* ourMapping = gMappings->get(upBuf);
00143 
00144     // If we found it, then call the factory method for it
00145     if (ourMapping)
00146     {
00147        XMLTranscoder* temp = ourMapping->makeNew(blockSize, manager);
00148        resValue = temp ? XMLTransService::Ok : XMLTransService::InternalFailure;
00149        return temp;
00150     }
00151 
00152     //
00153     //  It wasn't an intrinsic and it wasn't disallowed, so pass it on
00154     //  to the trans service to see if he can make anything of it.
00155     //
00156 
00157     XMLTranscoder* temp =  makeNewXMLTranscoder(encodingName, resValue, blockSize, manager);
00158 
00159     // if successful, set resValue to OK
00160     // if failed, the makeNewXMLTranscoder has already set the proper failing resValue
00161     if (temp) resValue =  XMLTransService::Ok;
00162 
00163     return temp;
00164 
00165 }
00166 
00167 
00168 XMLTranscoder*
00169 XMLTransService::makeNewTranscoderFor(  XMLRecognizer::Encodings        encodingEnum
00170                                         ,       XMLTransService::Codes& resValue
00171                                         , const XMLSize_t               blockSize
00172                                         ,       MemoryManager* const    manager)
00173 {
00174     //
00175     // We can only make transcoder if the passed encodingEnum is under this range
00176     //
00177     if (encodingEnum < XMLRecognizer::Encodings_Min || encodingEnum > XMLRecognizer::Encodings_Max) {
00178         resValue = XMLTransService::InternalFailure;
00179         return 0;
00180     }
00181 
00182     ENameMap* ourMapping = gMappingsRecognizer->elementAt(encodingEnum);
00183 
00184     // If we found it, then call the factory method for it
00185     if (ourMapping)    {
00186        XMLTranscoder* temp = ourMapping->makeNew(blockSize, manager);
00187        resValue = temp ? XMLTransService::Ok : XMLTransService::InternalFailure;
00188        return temp;
00189     }
00190     else {
00191         XMLTranscoder* temp =  makeNewXMLTranscoder(XMLRecognizer::nameForEncoding(encodingEnum, manager), resValue, blockSize, manager);
00192 
00193         // if successful, set resValue to OK
00194         // if failed, the makeNewXMLTranscoder has already set the proper failing resValue
00195         if (temp) resValue =  XMLTransService::Ok;
00196 
00197         return temp;
00198     }
00199 
00200 }
00201 
00202 
00203 // ---------------------------------------------------------------------------
00204 //  XMLTransTransService: Hidden Init Method
00205 //
00206 //  This is called by platform utils during startup.
00207 // ---------------------------------------------------------------------------
00208 void XMLTransService::initTransService()
00209 {
00210     //
00211     //  A stupid way to increment the fCurCount inside the RefVectorOf
00212     //
00213     for (XMLSize_t i = 0; i < (XMLSize_t)XMLRecognizer::Encodings_Count; i++)
00214         gMappingsRecognizer->addElement(0);
00215 
00216     //
00217     //  Add in the magical mapping for the native XMLCh transcoder. This
00218     //  is used for internal entities.
00219     //
00220     gMappingsRecognizer->setElementAt(new ENameMapFor<XMLChTranscoder>(XMLUni::fgXMLChEncodingString), XMLRecognizer::XERCES_XMLCH);
00221     gMappings->put((void*)XMLUni::fgXMLChEncodingString, new ENameMapFor<XMLChTranscoder>(XMLUni::fgXMLChEncodingString));
00222 
00223     //
00224     //  Add in our mappings for ASCII.
00225     //
00226     gMappingsRecognizer->setElementAt(new ENameMapFor<XMLASCIITranscoder>(XMLUni::fgUSASCIIEncodingString), XMLRecognizer::US_ASCII);
00227     gMappings->put((void*)XMLUni::fgUSASCIIEncodingString, new ENameMapFor<XMLASCIITranscoder>(XMLUni::fgUSASCIIEncodingString));
00228     gMappings->put((void*)XMLUni::fgUSASCIIEncodingString2, new ENameMapFor<XMLASCIITranscoder>(XMLUni::fgUSASCIIEncodingString2));
00229     gMappings->put((void*)XMLUni::fgUSASCIIEncodingString3, new ENameMapFor<XMLASCIITranscoder>(XMLUni::fgUSASCIIEncodingString3));
00230     gMappings->put((void*)XMLUni::fgUSASCIIEncodingString4, new ENameMapFor<XMLASCIITranscoder>(XMLUni::fgUSASCIIEncodingString4));
00231 
00232 
00233     //
00234     //  Add in our mappings for UTF-8
00235     //
00236     gMappingsRecognizer->setElementAt(new ENameMapFor<XMLUTF8Transcoder>(XMLUni::fgUTF8EncodingString), XMLRecognizer::UTF_8);
00237     gMappings->put((void*)XMLUni::fgUTF8EncodingString, new ENameMapFor<XMLUTF8Transcoder>(XMLUni::fgUTF8EncodingString));
00238     gMappings->put((void*)XMLUni::fgUTF8EncodingString2, new ENameMapFor<XMLUTF8Transcoder>(XMLUni::fgUTF8EncodingString2));
00239 
00240     //
00241     //  Add in our mappings for Latin1
00242     //
00243     gMappings->put((void*)XMLUni::fgISO88591EncodingString, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString));
00244     gMappings->put((void*)XMLUni::fgISO88591EncodingString2, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString2));
00245     gMappings->put((void*)XMLUni::fgISO88591EncodingString3, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString3));
00246     gMappings->put((void*)XMLUni::fgISO88591EncodingString4, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString4));
00247     gMappings->put((void*)XMLUni::fgISO88591EncodingString5, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString5));
00248     gMappings->put((void*)XMLUni::fgISO88591EncodingString6, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString6));
00249     gMappings->put((void*)XMLUni::fgISO88591EncodingString7, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString7));
00250     gMappings->put((void*)XMLUni::fgISO88591EncodingString8, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString8));
00251     gMappings->put((void*)XMLUni::fgISO88591EncodingString9, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString9));
00252     gMappings->put((void*)XMLUni::fgISO88591EncodingString10, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString10));
00253     gMappings->put((void*)XMLUni::fgISO88591EncodingString11, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString11));
00254     gMappings->put((void*)XMLUni::fgISO88591EncodingString12, new ENameMapFor<XML88591Transcoder>(XMLUni::fgISO88591EncodingString12));
00255 
00256     //
00257     //  Add in our mappings for UTF-16 and UCS-4, little endian
00258     //
00259     bool swapped = XMLPlatformUtils::fgXMLChBigEndian;
00260 
00261     gMappingsRecognizer->setElementAt(new EEndianNameMapFor<XMLUTF16Transcoder>(XMLUni::fgUTF16LEncodingString, swapped), XMLRecognizer::UTF_16L);
00262     gMappings->put
00263     (
00264         (void*)XMLUni::fgUTF16LEncodingString,
00265         new EEndianNameMapFor<XMLUTF16Transcoder>
00266         (
00267             XMLUni::fgUTF16LEncodingString
00268             , swapped
00269         )
00270     );
00271 
00272     gMappings->put
00273     (
00274         (void*)XMLUni::fgUTF16LEncodingString2,
00275         new EEndianNameMapFor<XMLUTF16Transcoder>
00276         (
00277             XMLUni::fgUTF16LEncodingString2
00278             , swapped
00279         )
00280     );
00281 
00282     gMappingsRecognizer->setElementAt(new EEndianNameMapFor<XMLUCS4Transcoder>(XMLUni::fgUCS4LEncodingString, swapped), XMLRecognizer::UCS_4L);
00283     gMappings->put
00284     (
00285         (void*)XMLUni::fgUCS4LEncodingString,
00286         new EEndianNameMapFor<XMLUCS4Transcoder>
00287         (
00288             XMLUni::fgUCS4LEncodingString
00289             , swapped
00290         )
00291     );
00292 
00293     gMappings->put
00294     (
00295         (void*)XMLUni::fgUCS4LEncodingString2,
00296         new EEndianNameMapFor<XMLUCS4Transcoder>
00297         (
00298             XMLUni::fgUCS4LEncodingString2
00299             , swapped
00300         )
00301     );
00302 
00303     //
00304     //  Add in our mappings for UTF-16 and UCS-4, big endian
00305     //
00306     swapped = !XMLPlatformUtils::fgXMLChBigEndian;
00307 
00308     gMappingsRecognizer->setElementAt(new EEndianNameMapFor<XMLUTF16Transcoder>(XMLUni::fgUTF16BEncodingString, swapped), XMLRecognizer::UTF_16B);
00309     gMappings->put
00310     (
00311         (void*)XMLUni::fgUTF16BEncodingString,
00312         new EEndianNameMapFor<XMLUTF16Transcoder>
00313         (
00314             XMLUni::fgUTF16BEncodingString
00315             , swapped
00316         )
00317     );
00318 
00319     gMappings->put
00320     (
00321         (void*)XMLUni::fgUTF16BEncodingString2,
00322         new EEndianNameMapFor<XMLUTF16Transcoder>
00323         (
00324             XMLUni::fgUTF16BEncodingString2
00325             , swapped
00326         )
00327     );
00328 
00329     gMappingsRecognizer->setElementAt(new EEndianNameMapFor<XMLUCS4Transcoder>(XMLUni::fgUCS4BEncodingString, swapped), XMLRecognizer::UCS_4B);
00330     gMappings->put
00331     (
00332         (void*)XMLUni::fgUCS4BEncodingString,
00333         new EEndianNameMapFor<XMLUCS4Transcoder>
00334         (
00335             XMLUni::fgUCS4BEncodingString
00336             , swapped
00337         )
00338     );
00339 
00340     gMappings->put
00341     (
00342         (void*)XMLUni::fgUCS4BEncodingString2,
00343         new EEndianNameMapFor<XMLUCS4Transcoder>
00344         (
00345             XMLUni::fgUCS4BEncodingString2
00346             , swapped
00347         )
00348     );
00349 
00350     //
00351     //  Add in our mappings for UTF-16 and UCS-4 which does not indicate endian
00352     //  assumes the same endian encoding as the OS
00353     //
00354 
00355     gMappings->put
00356     (
00357         (void*)XMLUni::fgUTF16EncodingString,
00358         new EEndianNameMapFor<XMLUTF16Transcoder>
00359         (
00360             XMLUni::fgUTF16EncodingString
00361             , false
00362         )
00363     );
00364     gMappings->put
00365     (
00366         (void*)XMLUni::fgUTF16EncodingString2,
00367         new EEndianNameMapFor<XMLUTF16Transcoder>
00368         (
00369             XMLUni::fgUTF16EncodingString2
00370             , false
00371         )
00372     );
00373     gMappings->put
00374     (
00375         (void*)XMLUni::fgUTF16EncodingString3,
00376         new EEndianNameMapFor<XMLUTF16Transcoder>
00377         (
00378             XMLUni::fgUTF16EncodingString3
00379             , false
00380         )
00381     );
00382     gMappings->put
00383     (
00384         (void*)XMLUni::fgUTF16EncodingString4,
00385         new EEndianNameMapFor<XMLUTF16Transcoder>
00386         (
00387             XMLUni::fgUTF16EncodingString4
00388             , false
00389         )
00390     );
00391     gMappings->put
00392     (
00393         (void*)XMLUni::fgUTF16EncodingString5,
00394         new EEndianNameMapFor<XMLUTF16Transcoder>
00395         (
00396             XMLUni::fgUTF16EncodingString5
00397             , false
00398         )
00399     );
00400     gMappings->put
00401     (
00402         (void*)XMLUni::fgUTF16EncodingString6,
00403         new EEndianNameMapFor<XMLUTF16Transcoder>
00404         (
00405             XMLUni::fgUTF16EncodingString6
00406             , false
00407         )
00408     );
00409     gMappings->put
00410     (
00411         (void*)XMLUni::fgUTF16EncodingString7,
00412         new EEndianNameMapFor<XMLUTF16Transcoder>
00413         (
00414             XMLUni::fgUTF16EncodingString7
00415             , false
00416         )
00417     );
00418     gMappings->put
00419     (
00420         (void*)XMLUni::fgUCS4EncodingString,
00421         new EEndianNameMapFor<XMLUCS4Transcoder>
00422         (
00423             XMLUni::fgUCS4EncodingString
00424             , false
00425         )
00426     );
00427     gMappings->put
00428     (
00429         (void*)XMLUni::fgUCS4EncodingString2,
00430         new EEndianNameMapFor<XMLUCS4Transcoder>
00431         (
00432             XMLUni::fgUCS4EncodingString2
00433             , false
00434         )
00435     );
00436     gMappings->put
00437     (
00438         (void*)XMLUni::fgUCS4EncodingString3,
00439         new EEndianNameMapFor<XMLUCS4Transcoder>
00440         (
00441             XMLUni::fgUCS4EncodingString3
00442             , false
00443         )
00444     );
00445     gMappings->put
00446     (
00447         (void*)XMLUni::fgUCS4EncodingString4,
00448         new EEndianNameMapFor<XMLUCS4Transcoder>
00449         (
00450             XMLUni::fgUCS4EncodingString4
00451             , false
00452         )
00453     );
00454     gMappings->put
00455     (
00456         (void*)XMLUni::fgUCS4EncodingString5,
00457         new EEndianNameMapFor<XMLUCS4Transcoder>
00458         (
00459             XMLUni::fgUCS4EncodingString5
00460             , false
00461         )
00462     );
00463 
00464     //
00465     //  Add in our mappings for IBM037, and the one alias we support for
00466     //  it, which is EBCDIC-CP-US.
00467     //
00468     gMappingsRecognizer->setElementAt(new ENameMapFor<XMLEBCDICTranscoder>(XMLUni::fgEBCDICEncodingString), XMLRecognizer::EBCDIC);
00469     gMappings->put((void*)XMLUni::fgIBM037EncodingString, new ENameMapFor<XMLEBCDICTranscoder>(XMLUni::fgIBM037EncodingString));
00470     gMappings->put((void*)XMLUni::fgIBM037EncodingString2, new ENameMapFor<XMLEBCDICTranscoder>(XMLUni::fgIBM037EncodingString2));
00471 
00472 
00473     //hhe
00474     gMappings->put((void*)XMLUni::fgIBM1047EncodingString, new ENameMapFor<XMLIBM1047Transcoder>(XMLUni::fgIBM1047EncodingString));
00475     gMappings->put((void*)XMLUni::fgIBM1047EncodingString2, new ENameMapFor<XMLIBM1047Transcoder>(XMLUni::fgIBM1047EncodingString2));
00476 
00477     //
00478     //  Add in our mappings for IBM037 with Euro update, i.e. IBM1140. It
00479     //  has alias IBM01140, the one suggested by IANA
00480     //
00481     gMappings->put((void*)XMLUni::fgIBM1140EncodingString, new ENameMapFor<XMLIBM1140Transcoder>(XMLUni::fgIBM1140EncodingString));
00482     gMappings->put((void*)XMLUni::fgIBM1140EncodingString2, new ENameMapFor<XMLIBM1140Transcoder>(XMLUni::fgIBM1140EncodingString2));
00483     gMappings->put((void*)XMLUni::fgIBM1140EncodingString3, new ENameMapFor<XMLIBM1140Transcoder>(XMLUni::fgIBM1140EncodingString3));
00484     gMappings->put((void*)XMLUni::fgIBM1140EncodingString4, new ENameMapFor<XMLIBM1140Transcoder>(XMLUni::fgIBM1140EncodingString4));
00485 
00486     //
00487     //  Add in our mappings for Windows-1252. We don't have any aliases for
00488     //  this one, so there is just one mapping.
00489     //
00490     gMappings->put((void*)XMLUni::fgWin1252EncodingString, new ENameMapFor<XMLWin1252Transcoder>(XMLUni::fgWin1252EncodingString));
00491 
00492 }
00493 
00494 // ---------------------------------------------------------------------------
00495 //  XMLTransService: IANA encoding setting
00496 // ---------------------------------------------------------------------------
00497 void XMLTransService::strictIANAEncoding(const bool newState)
00498 {
00499     gStrictIANAEncoding = newState;
00500 }
00501 
00502 bool XMLTransService::isStrictIANAEncoding()
00503 {
00504     return gStrictIANAEncoding;
00505 }
00506 
00507 // ---------------------------------------------------------------------------
00508 //  XMLTranscoder: Public Destructor
00509 // ---------------------------------------------------------------------------
00510 XMLTranscoder::~XMLTranscoder()
00511 {
00512     fMemoryManager->deallocate(fEncodingName);//delete [] fEncodingName;
00513 }
00514 
00515 
00516 // ---------------------------------------------------------------------------
00517 //  XMLTranscoder: Hidden Constructors
00518 // ---------------------------------------------------------------------------
00519 XMLTranscoder::XMLTranscoder(const  XMLCh* const    encodingName
00520                             , const XMLSize_t       blockSize
00521                             , MemoryManager* const  manager) :
00522       fBlockSize(blockSize)
00523     , fEncodingName(0)
00524     , fMemoryManager(manager)
00525 {
00526     fEncodingName = XMLString::replicate(encodingName, fMemoryManager);
00527 }
00528 
00529 
00530 // ---------------------------------------------------------------------------
00531 //  XMLTranscoder: Protected helpers
00532 // ---------------------------------------------------------------------------
00533 
00534 
00535 // ---------------------------------------------------------------------------
00536 //  XMLLCPTranscoder: Public Destructor
00537 // ---------------------------------------------------------------------------
00538 XMLLCPTranscoder::XMLLCPTranscoder()
00539 {
00540 }
00541 
00542 
00543 // ---------------------------------------------------------------------------
00544 //  XMLLCPTranscoder: Hidden Constructors
00545 // ---------------------------------------------------------------------------
00546 XMLLCPTranscoder::~XMLLCPTranscoder()
00547 {
00548 }
00549 
00550 // ---------------------------------------------------------------------------
00551 //  TranscodeToStr: Public constructors and destructor
00552 // ---------------------------------------------------------------------------
00553 TranscodeToStr::TranscodeToStr(const XMLCh *in, const char *encoding,
00554                                MemoryManager *manager)
00555     : fString(0),
00556       fBytesWritten(0),
00557       fMemoryManager(manager)
00558 {
00559     XMLTransService::Codes failReason;
00560     const XMLSize_t blockSize = 2048;
00561 
00562     XMLTranscoder* trans = XMLPlatformUtils::fgTransService->makeNewTranscoderFor(encoding, failReason, blockSize, fMemoryManager);
00563     Janitor<XMLTranscoder> janTrans(trans);
00564 
00565     transcode(in, XMLString::stringLen(in), trans);
00566 }
00567 
00568 TranscodeToStr::TranscodeToStr(const XMLCh *in, XMLSize_t length, const char *encoding,
00569                                MemoryManager *manager)
00570     : fString(0),
00571       fBytesWritten(0),
00572       fMemoryManager(manager)
00573 {
00574     XMLTransService::Codes failReason;
00575     const XMLSize_t blockSize = 2048;
00576 
00577     XMLTranscoder* trans = XMLPlatformUtils::fgTransService->makeNewTranscoderFor(encoding, failReason, blockSize, fMemoryManager);
00578     Janitor<XMLTranscoder> janTrans(trans);
00579 
00580     transcode(in, length, trans);
00581 }
00582 
00583 TranscodeToStr::TranscodeToStr(const XMLCh *in, XMLTranscoder* trans,
00584                                MemoryManager *manager)
00585     : fString(0),
00586       fBytesWritten(0),
00587       fMemoryManager(manager)
00588 {
00589     transcode(in, XMLString::stringLen(in), trans);
00590 }
00591 
00592 TranscodeToStr::TranscodeToStr(const XMLCh *in, XMLSize_t length, XMLTranscoder* trans,
00593                                MemoryManager *manager)
00594     : fString(0),
00595       fBytesWritten(0),
00596       fMemoryManager(manager)
00597 {
00598     transcode(in, length, trans);
00599 }
00600 
00601 TranscodeToStr::~TranscodeToStr()
00602 {
00603     if(fString)
00604         fMemoryManager->deallocate(fString);
00605 }
00606 
00607 // ---------------------------------------------------------------------------
00608 //  TranscodeToStr: Private helper methods
00609 // ---------------------------------------------------------------------------
00610 void TranscodeToStr::transcode(const XMLCh *in, XMLSize_t len, XMLTranscoder* trans)
00611 {
00612     if(!in) return;
00613 
00614     XMLSize_t allocSize = len * sizeof(XMLCh);
00615     fString = (XMLByte*)fMemoryManager->allocate(allocSize);
00616 
00617     XMLSize_t charsRead = 0;
00618     XMLSize_t charsDone = 0;
00619 
00620     while(true) {
00621         fBytesWritten += trans->transcodeTo(in + charsDone, len - charsDone,
00622                                             fString + fBytesWritten, allocSize - fBytesWritten,
00623                                             charsRead, XMLTranscoder::UnRep_Throw);
00624         if(charsRead == 0)
00625             ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, fMemoryManager);
00626 
00627         charsDone += charsRead;
00628 
00629         if(charsDone == len) break;
00630 
00631         allocSize *= 2;
00632         XMLByte *newBuf = (XMLByte*)fMemoryManager->allocate(allocSize);
00633         memcpy(newBuf, fString, fBytesWritten);
00634         fMemoryManager->deallocate(fString);
00635         fString = newBuf;
00636     }
00637 
00638     // null terminate
00639     if((fBytesWritten + 4) > allocSize) {
00640         allocSize = fBytesWritten + 4;
00641         XMLByte *newBuf = (XMLByte*)fMemoryManager->allocate(allocSize);
00642         memcpy(newBuf, fString, fBytesWritten);
00643         fMemoryManager->deallocate(fString);
00644         fString = newBuf;
00645     }
00646     fString[fBytesWritten + 0] = 0;
00647     fString[fBytesWritten + 1] = 0;
00648     fString[fBytesWritten + 2] = 0;
00649     fString[fBytesWritten + 3] = 0;
00650 }
00651 
00652 // ---------------------------------------------------------------------------
00653 //  TranscodeFromStr: Public constructors and destructor
00654 // ---------------------------------------------------------------------------
00655 TranscodeFromStr::TranscodeFromStr(const XMLByte *data, XMLSize_t length, const char *encoding,
00656                                    MemoryManager *manager)
00657     : fString(0),
00658       fCharsWritten(0),
00659       fMemoryManager(manager)
00660 {
00661     XMLTransService::Codes failReason;
00662     const XMLSize_t blockSize = 2048;
00663 
00664     XMLTranscoder* trans = XMLPlatformUtils::fgTransService->makeNewTranscoderFor(encoding, failReason, blockSize, fMemoryManager);
00665     Janitor<XMLTranscoder> janTrans(trans);
00666 
00667     transcode(data, length, trans);
00668 }
00669 
00670 TranscodeFromStr::TranscodeFromStr(const XMLByte *data, XMLSize_t length, XMLTranscoder *trans,
00671                                    MemoryManager *manager)
00672     : fString(0),
00673       fCharsWritten(0),
00674       fMemoryManager(manager)
00675 {
00676     transcode(data, length, trans);
00677 }
00678 
00679 TranscodeFromStr::~TranscodeFromStr()
00680 {
00681     if(fString)
00682         fMemoryManager->deallocate(fString);
00683 }
00684 
00685 // ---------------------------------------------------------------------------
00686 //  TranscodeFromStr: Private helper methods
00687 // ---------------------------------------------------------------------------
00688 void TranscodeFromStr::transcode(const XMLByte *in, XMLSize_t length, XMLTranscoder *trans)
00689 {
00690     if(!in) return;
00691 
00692     XMLSize_t allocSize = length + 1;
00693     fString = (XMLCh*)fMemoryManager->allocate(allocSize * sizeof(XMLCh));
00694 
00695     XMLSize_t csSize = length;
00696     ArrayJanitor<unsigned char> charSizes((unsigned char*)fMemoryManager->allocate(csSize * sizeof(unsigned char)),
00697                                           fMemoryManager);
00698 
00699     XMLSize_t bytesRead = 0;
00700     XMLSize_t bytesDone = 0;
00701 
00702     while(true) {
00703         fCharsWritten += trans->transcodeFrom(in + bytesDone, length - bytesDone,
00704                                               fString + fCharsWritten, allocSize - fCharsWritten,
00705                                               bytesRead, charSizes.get());
00706         if(bytesRead == 0)
00707             ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, fMemoryManager);
00708 
00709         bytesDone += bytesRead;
00710         if(bytesDone == length) break;
00711 
00712         allocSize *= 2;
00713         XMLCh *newBuf = (XMLCh*)fMemoryManager->allocate(allocSize * sizeof(XMLCh));
00714         memcpy(newBuf, fString, fCharsWritten);
00715         fMemoryManager->deallocate(fString);
00716         fString = newBuf;
00717 
00718         if((allocSize - fCharsWritten) > csSize) {
00719             csSize = allocSize - fCharsWritten;
00720             charSizes.reset((unsigned char*)fMemoryManager->allocate(csSize * sizeof(unsigned char)),
00721                             fMemoryManager);
00722         }
00723     }
00724 
00725     // null terminate
00726     if(fCharsWritten == allocSize) {
00727         allocSize += 1;
00728         XMLCh *newBuf = (XMLCh*)fMemoryManager->allocate(allocSize * sizeof(XMLCh));
00729         memcpy(newBuf, fString, fCharsWritten);
00730         fMemoryManager->deallocate(fString);
00731         fString = newBuf;
00732     }
00733     fString[fCharsWritten] = 0;
00734 }
00735 
00736 XERCES_CPP_NAMESPACE_END