PageRenderTime 56ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/ATF2/control-software/epics-3.14.8/extensions/src/ChannelArchiver/ThirdParty/xerces-c-src2_4_0/src/xercesc/util/Transcoders/Win32/Win32TransService.cpp

http://atf2flightsim.googlecode.com/
C++ | 1069 lines | 633 code | 167 blank | 269 comment | 78 complexity | ac7a8089ee2c70e5e72310ef2a997199 MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-2.0, IPL-1.0, BSD-3-Clause
  1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 1999-2000 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution,
  20. * if any, must include the following acknowledgment:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowledgment may appear in the software itself,
  24. * if and wherever such third-party acknowledgments normally appear.
  25. *
  26. * 4. The names "Xerces" and "Apache Software Foundation" must
  27. * not be used to endorse or promote products derived from this
  28. * software without prior written permission. For written
  29. * permission, please contact apache\@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache",
  32. * nor may "Apache" appear in their name, without prior written
  33. * permission of the Apache Software Foundation.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation, and was
  51. * originally based on software copyright (c) 1999, International
  52. * Business Machines, Inc., http://www.ibm.com . For more information
  53. * on the Apache Software Foundation, please see
  54. * <http://www.apache.org/>.
  55. */
  56. /*
  57. * $Id: Win32TransService.cpp,v 1.1.1.1 2009/03/14 06:42:36 whitegr Exp $
  58. */
  59. // ---------------------------------------------------------------------------
  60. // Includes
  61. // ---------------------------------------------------------------------------
  62. #include <xercesc/util/PlatformUtils.hpp>
  63. #include <xercesc/util/TranscodingException.hpp>
  64. #include <xercesc/util/XMLException.hpp>
  65. #include <xercesc/util/XMLString.hpp>
  66. #include <xercesc/util/XMLUniDefs.hpp>
  67. #include <xercesc/util/XMLUni.hpp>
  68. #include <xercesc/util/RefHashTableOf.hpp>
  69. #include "Win32TransService.hpp"
  70. #include <windows.h>
  71. XERCES_CPP_NAMESPACE_BEGIN
  72. // ---------------------------------------------------------------------------
  73. // Local, const data
  74. // ---------------------------------------------------------------------------
  75. static const XMLCh gMyServiceId[] =
  76. {
  77. chLatin_W, chLatin_i, chLatin_n, chDigit_3, chDigit_2, chNull
  78. };
  79. // ---------------------------------------------------------------------------
  80. // This is the simple CPMapEntry class. It just contains an encoding name
  81. // and a code page for that encoding.
  82. // ---------------------------------------------------------------------------
  83. class CPMapEntry : public XMemory
  84. {
  85. public :
  86. // -----------------------------------------------------------------------
  87. // Constructors and Destructor
  88. // -----------------------------------------------------------------------
  89. CPMapEntry
  90. (
  91. const XMLCh* const encodingName
  92. , const unsigned int cpId
  93. , const unsigned int ieId
  94. );
  95. CPMapEntry
  96. (
  97. const char* const encodingName
  98. , const unsigned int cpId
  99. , const unsigned int ieId
  100. );
  101. ~CPMapEntry();
  102. // -----------------------------------------------------------------------
  103. // Getter methods
  104. // -----------------------------------------------------------------------
  105. const XMLCh* getEncodingName() const;
  106. const XMLCh* getKey() const;
  107. unsigned int getWinCP() const;
  108. unsigned int getIEEncoding() const;
  109. private :
  110. // -----------------------------------------------------------------------
  111. // Unimplemented constructors and operators
  112. // -----------------------------------------------------------------------
  113. CPMapEntry();
  114. CPMapEntry(const CPMapEntry&);
  115. CPMapEntry& operator=(const CPMapEntry&);
  116. // -----------------------------------------------------------------------
  117. // Private data members
  118. //
  119. // fEncodingName
  120. // This is the encoding name for the code page that this instance
  121. // represents.
  122. //
  123. // fCPId
  124. // This is the Windows specific code page for the encoding that this
  125. // instance represents.
  126. //
  127. // fIEId
  128. // This is the IE encoding id. Its not used at this time, but we
  129. // go ahead and get it and store it just in case for later.
  130. // -----------------------------------------------------------------------
  131. XMLCh* fEncodingName;
  132. unsigned int fCPId;
  133. unsigned int fIEId;
  134. };
  135. // ---------------------------------------------------------------------------
  136. // CPMapEntry: Constructors and Destructor
  137. // ---------------------------------------------------------------------------
  138. CPMapEntry::CPMapEntry( const char* const encodingName
  139. , const unsigned int cpId
  140. , const unsigned int ieId) :
  141. fEncodingName(0)
  142. , fCPId(cpId)
  143. , fIEId(ieId)
  144. {
  145. // Transcode the name to Unicode and store that copy
  146. const unsigned int srcLen = strlen(encodingName);
  147. const unsigned charLen = ::mblen(encodingName, MB_CUR_MAX);
  148. if (charLen != -1) {
  149. const unsigned int targetLen = srcLen/charLen;
  150. fEncodingName = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate
  151. (
  152. (targetLen + 1) * sizeof(XMLCh)
  153. );//new XMLCh[targetLen + 1];
  154. ::mbstowcs(fEncodingName, encodingName, srcLen);
  155. fEncodingName[targetLen] = 0;
  156. //
  157. // Upper case it because we are using a hash table and need to be
  158. // sure that we find all case combinations.
  159. //
  160. _wcsupr(fEncodingName);
  161. }
  162. }
  163. CPMapEntry::CPMapEntry( const XMLCh* const encodingName
  164. , const unsigned int cpId
  165. , const unsigned int ieId) :
  166. fEncodingName(0)
  167. , fCPId(cpId)
  168. , fIEId(ieId)
  169. {
  170. fEncodingName = XMLString::replicate(encodingName, XMLPlatformUtils::fgMemoryManager);
  171. //
  172. // Upper case it because we are using a hash table and need to be
  173. // sure that we find all case combinations.
  174. //
  175. _wcsupr(fEncodingName);
  176. }
  177. CPMapEntry::~CPMapEntry()
  178. {
  179. XMLPlatformUtils::fgMemoryManager->deallocate(fEncodingName);//delete [] fEncodingName;
  180. }
  181. // ---------------------------------------------------------------------------
  182. // CPMapEntry: Getter methods
  183. // ---------------------------------------------------------------------------
  184. const XMLCh* CPMapEntry::getEncodingName() const
  185. {
  186. return fEncodingName;
  187. }
  188. unsigned int CPMapEntry::getWinCP() const
  189. {
  190. return fCPId;
  191. }
  192. unsigned int CPMapEntry::getIEEncoding() const
  193. {
  194. return fIEId;
  195. }
  196. //---------------------------------------------------------------------------
  197. //
  198. // class Win32TransService Implementation ...
  199. //
  200. //---------------------------------------------------------------------------
  201. // ---------------------------------------------------------------------------
  202. // Win32TransService: Constructors and Destructor
  203. // ---------------------------------------------------------------------------
  204. Win32TransService::Win32TransService()
  205. {
  206. fCPMap = new RefHashTableOf<CPMapEntry>(109);
  207. //
  208. // Open up the registry key that contains the info we want. Note that,
  209. // if this key does not exist, then we just return. It will just mean
  210. // that we don't have any support except for intrinsic encodings supported
  211. // by the parser itself (and the LCP support of course.
  212. //
  213. HKEY charsetKey;
  214. if (::RegOpenKeyExA
  215. (
  216. HKEY_CLASSES_ROOT
  217. , "MIME\\Database\\Charset"
  218. , 0
  219. , KEY_READ
  220. , &charsetKey))
  221. {
  222. return;
  223. }
  224. //
  225. // Read in the registry keys that hold the code page ids. Skip for now
  226. // those entries which indicate that they are aliases for some other
  227. // encodings. We'll come back and do a second round for those and look
  228. // up the original name and get the code page id.
  229. //
  230. // Note that we have to use A versions here so that this will run on
  231. // 98, and transcode the strings to Unicode.
  232. //
  233. const unsigned int nameBufSz = 1024;
  234. char nameBuf[nameBufSz + 1];
  235. unsigned int subIndex = 0;
  236. unsigned long theSize;
  237. while (true)
  238. {
  239. // Get the name of the next key
  240. theSize = nameBufSz;
  241. if (::RegEnumKeyExA
  242. (
  243. charsetKey
  244. , subIndex
  245. , nameBuf
  246. , &theSize
  247. , 0, 0, 0, 0) == ERROR_NO_MORE_ITEMS)
  248. {
  249. break;
  250. }
  251. // Open this subkey
  252. HKEY encodingKey;
  253. if (::RegOpenKeyExA
  254. (
  255. charsetKey
  256. , nameBuf
  257. , 0
  258. , KEY_READ
  259. , &encodingKey))
  260. {
  261. XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  262. }
  263. //
  264. // Lts see if its an alias. If so, then ignore it in this first
  265. // loop. Else, we'll add a new entry for this one.
  266. //
  267. if (!isAlias(encodingKey))
  268. {
  269. //
  270. // Lets get the two values out of this key that we are
  271. // interested in. There should be a code page entry and an
  272. // IE entry.
  273. //
  274. unsigned long theType;
  275. unsigned int CPId;
  276. unsigned int IEId;
  277. theSize = sizeof(unsigned int);
  278. if (::RegQueryValueExA
  279. (
  280. encodingKey
  281. , "Codepage"
  282. , 0
  283. , &theType
  284. , (unsigned char*)&CPId
  285. , &theSize) != ERROR_SUCCESS)
  286. {
  287. XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  288. }
  289. //
  290. // If this is not a valid Id, and it might not be because its
  291. // not loaded on this system, then don't take it.
  292. //
  293. if (::IsValidCodePage(CPId))
  294. {
  295. theSize = sizeof(unsigned int);
  296. if (::RegQueryValueExA
  297. (
  298. encodingKey
  299. , "InternetEncoding"
  300. , 0
  301. , &theType
  302. , (unsigned char*)&IEId
  303. , &theSize) != ERROR_SUCCESS)
  304. {
  305. XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  306. }
  307. CPMapEntry* newEntry = new CPMapEntry(nameBuf, CPId, IEId);
  308. fCPMap->put((void*)newEntry->getEncodingName(), newEntry);
  309. }
  310. }
  311. // And now close the subkey handle and bump the subkey index
  312. ::RegCloseKey(encodingKey);
  313. subIndex++;
  314. }
  315. //
  316. // Now loop one more time and this time we do just the aliases. For
  317. // each one we find, we look up that name in the map we've already
  318. // built and add a new entry with this new name and the same id
  319. // values we stored for the original.
  320. //
  321. subIndex = 0;
  322. char aliasBuf[nameBufSz + 1];
  323. while (true)
  324. {
  325. // Get the name of the next key
  326. theSize = nameBufSz;
  327. if (::RegEnumKeyExA
  328. (
  329. charsetKey
  330. , subIndex
  331. , nameBuf
  332. , &theSize
  333. , 0, 0, 0, 0) == ERROR_NO_MORE_ITEMS)
  334. {
  335. break;
  336. }
  337. // Open this subkey
  338. HKEY encodingKey;
  339. if (::RegOpenKeyExA
  340. (
  341. charsetKey
  342. , nameBuf
  343. , 0
  344. , KEY_READ
  345. , &encodingKey))
  346. {
  347. XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  348. }
  349. //
  350. // If its an alias, look up the name in the map. If we find it,
  351. // then construct a new one with the new name and the aliased
  352. // ids.
  353. //
  354. if (isAlias(encodingKey, aliasBuf, nameBufSz))
  355. {
  356. const unsigned int srcLen = strlen(aliasBuf);
  357. const unsigned charLen = ::mblen(aliasBuf, MB_CUR_MAX);
  358. if (charLen != -1) {
  359. const unsigned int targetLen = srcLen/charLen;
  360. XMLCh* uniAlias = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate
  361. (
  362. (targetLen + 1) * sizeof(XMLCh)
  363. );//new XMLCh[targetLen + 1];
  364. ::mbstowcs(uniAlias, aliasBuf, srcLen);
  365. uniAlias[targetLen] = 0;
  366. _wcsupr(uniAlias);
  367. // Look up the alias name
  368. CPMapEntry* aliasedEntry = fCPMap->get(uniAlias);
  369. if (aliasedEntry)
  370. {
  371. const unsigned int srcLen = strlen(nameBuf);
  372. const unsigned charLen = ::mblen(nameBuf, MB_CUR_MAX);
  373. const unsigned int targetLen = srcLen/charLen;
  374. XMLCh* uniName = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate
  375. (
  376. (targetLen + 1) * sizeof(XMLCh)
  377. );//new XMLCh[targetLen + 1];
  378. ::mbstowcs(uniName, nameBuf, srcLen);
  379. uniName[targetLen] = 0;
  380. _wcsupr(uniName);
  381. //
  382. // If the name is actually different, then take it.
  383. // Otherwise, don't take it. They map aliases that are
  384. // just different case.
  385. //
  386. if (::wcscmp(uniName, aliasedEntry->getEncodingName()))
  387. {
  388. CPMapEntry* newEntry = new CPMapEntry(uniName, aliasedEntry->getWinCP(), aliasedEntry->getIEEncoding());
  389. fCPMap->put((void*)newEntry->getEncodingName(), newEntry);
  390. }
  391. XMLPlatformUtils::fgMemoryManager->deallocate(uniName);//delete [] uniName;
  392. }
  393. XMLPlatformUtils::fgMemoryManager->deallocate(uniAlias);//delete [] uniAlias;
  394. }
  395. }
  396. // And now close the subkey handle and bump the subkey index
  397. ::RegCloseKey(encodingKey);
  398. subIndex++;
  399. }
  400. // And close the main key handle
  401. ::RegCloseKey(charsetKey);
  402. }
  403. Win32TransService::~Win32TransService()
  404. {
  405. delete fCPMap;
  406. }
  407. // ---------------------------------------------------------------------------
  408. // Win32TransService: The virtual transcoding service API
  409. // ---------------------------------------------------------------------------
  410. int Win32TransService::compareIString( const XMLCh* const comp1
  411. , const XMLCh* const comp2)
  412. {
  413. return _wcsicmp(comp1, comp2);
  414. }
  415. int Win32TransService::compareNIString( const XMLCh* const comp1
  416. , const XMLCh* const comp2
  417. , const unsigned int maxChars)
  418. {
  419. return _wcsnicmp(comp1, comp2, maxChars);
  420. }
  421. const XMLCh* Win32TransService::getId() const
  422. {
  423. return gMyServiceId;
  424. }
  425. bool Win32TransService::isSpace(const XMLCh toCheck) const
  426. {
  427. return (iswspace(toCheck) != 0);
  428. }
  429. XMLLCPTranscoder* Win32TransService::makeNewLCPTranscoder()
  430. {
  431. // Just allocate a new LCP transcoder of our type
  432. return new Win32LCPTranscoder;
  433. }
  434. bool Win32TransService::supportsSrcOfs() const
  435. {
  436. //
  437. // Since the only mechanism we have to translate XML text in this
  438. // transcoder basically require us to do work that allows us to support
  439. // source offsets, we might as well do it.
  440. //
  441. return true;
  442. }
  443. void Win32TransService::upperCase(XMLCh* const toUpperCase) const
  444. {
  445. _wcsupr(toUpperCase);
  446. }
  447. void Win32TransService::lowerCase(XMLCh* const toLowerCase) const
  448. {
  449. _wcslwr(toLowerCase);
  450. }
  451. bool Win32TransService::isAlias(const HKEY encodingKey
  452. , char* const aliasBuf
  453. , const unsigned int nameBufSz )
  454. {
  455. unsigned long theType;
  456. unsigned long theSize = nameBufSz;
  457. return (::RegQueryValueExA
  458. (
  459. encodingKey
  460. , "AliasForCharset"
  461. , 0
  462. , &theType
  463. , (unsigned char*)aliasBuf
  464. , &theSize
  465. ) == ERROR_SUCCESS);
  466. }
  467. XMLTranscoder*
  468. Win32TransService::makeNewXMLTranscoder(const XMLCh* const encodingName
  469. , XMLTransService::Codes& resValue
  470. , const unsigned int blockSize
  471. , MemoryManager* const manager)
  472. {
  473. const unsigned int upLen = 1024;
  474. XMLCh upEncoding[upLen + 1];
  475. //
  476. // Get an upper cased copy of the encoding name, since we use a hash
  477. // table and we store them all in upper case.
  478. //
  479. ::wcsncpy(upEncoding, encodingName, upLen);
  480. upEncoding[upLen] = 0;
  481. _wcsupr(upEncoding);
  482. // Now to try to find this guy in the CP map
  483. CPMapEntry* theEntry = fCPMap->get(upEncoding);
  484. // If not found, then return a null pointer
  485. if (!theEntry)
  486. {
  487. resValue = XMLTransService::UnsupportedEncoding;
  488. return 0;
  489. }
  490. // We found it, so return a Win32 transcoder for this encoding
  491. return new (manager) Win32Transcoder
  492. (
  493. encodingName
  494. , theEntry->getWinCP()
  495. , theEntry->getIEEncoding()
  496. , blockSize
  497. , manager
  498. );
  499. }
  500. //---------------------------------------------------------------------------
  501. //
  502. // class Win32Transcoder Implementation ...
  503. //
  504. //---------------------------------------------------------------------------
  505. // ---------------------------------------------------------------------------
  506. // Win32Transcoder: Constructors and Destructor
  507. // ---------------------------------------------------------------------------
  508. Win32Transcoder::Win32Transcoder(const XMLCh* const encodingName
  509. , const unsigned int winCP
  510. , const unsigned int ieCP
  511. , const unsigned int blockSize
  512. , MemoryManager* const manager) :
  513. XMLTranscoder(encodingName, blockSize, manager)
  514. , fIECP(ieCP)
  515. , fWinCP(winCP)
  516. {
  517. }
  518. Win32Transcoder::~Win32Transcoder()
  519. {
  520. }
  521. // ---------------------------------------------------------------------------
  522. // Win32Transcoder: The virtual transcoder API
  523. // ---------------------------------------------------------------------------
  524. unsigned int
  525. Win32Transcoder::transcodeFrom( const XMLByte* const srcData
  526. , const unsigned int srcCount
  527. , XMLCh* const toFill
  528. , const unsigned int maxChars
  529. , unsigned int& bytesEaten
  530. , unsigned char* const charSizes)
  531. {
  532. // Get temp pointers to the in and out buffers, and the chars sizes one
  533. XMLCh* outPtr = toFill;
  534. const XMLByte* inPtr = srcData;
  535. unsigned char* sizesPtr = charSizes;
  536. // Calc end pointers for each of them
  537. XMLCh* outEnd = toFill + maxChars;
  538. const XMLByte* inEnd = srcData + srcCount;
  539. //
  540. // Now loop until we either get our max chars, or cannot get a whole
  541. // character from the input buffer.
  542. //
  543. bytesEaten = 0;
  544. while ((outPtr < outEnd) && (inPtr < inEnd))
  545. {
  546. //
  547. // If we are looking at a leading byte of a multibyte sequence,
  548. // then we are going to eat 2 bytes, else 1.
  549. //
  550. const unsigned int toEat = ::IsDBCSLeadByteEx(fWinCP, *inPtr) ?
  551. 2 : 1;
  552. // Make sure a whol char is in the source
  553. if (inPtr + toEat > inEnd)
  554. break;
  555. // Try to translate this next char and check for an error
  556. const unsigned int converted = ::MultiByteToWideChar
  557. (
  558. fWinCP
  559. , MB_PRECOMPOSED | MB_ERR_INVALID_CHARS
  560. , (const char*)inPtr
  561. , toEat
  562. , outPtr
  563. , 1
  564. );
  565. if (converted != 1)
  566. {
  567. if (toEat == 1)
  568. {
  569. XMLCh tmpBuf[16];
  570. XMLString::binToText((unsigned int)(*inPtr), tmpBuf, 16, 16);
  571. ThrowXML2
  572. (
  573. TranscodingException
  574. , XMLExcepts::Trans_BadSrcCP
  575. , tmpBuf
  576. , getEncodingName()
  577. );
  578. }
  579. else
  580. {
  581. ThrowXML(TranscodingException, XMLExcepts::Trans_BadSrcSeq);
  582. }
  583. }
  584. // Update the char sizes array for this round
  585. *sizesPtr++ = toEat;
  586. // And update the bytes eaten count
  587. bytesEaten += toEat;
  588. // And update our in/out ptrs
  589. inPtr += toEat;
  590. outPtr++;
  591. }
  592. // Return the chars we output
  593. return (outPtr - toFill);
  594. }
  595. unsigned int
  596. Win32Transcoder::transcodeTo(const XMLCh* const srcData
  597. , const unsigned int srcCount
  598. , XMLByte* const toFill
  599. , const unsigned int maxBytes
  600. , unsigned int& charsEaten
  601. , const UnRepOpts options)
  602. {
  603. // Get pointers to the start and end of each buffer
  604. const XMLCh* srcPtr = srcData;
  605. const XMLCh* srcEnd = srcData + srcCount;
  606. XMLByte* outPtr = toFill;
  607. XMLByte* outEnd = toFill + maxBytes;
  608. //
  609. // Now loop until we either get our max chars, or cannot get a whole
  610. // character from the input buffer.
  611. //
  612. // NOTE: We have to use a loop for this unfortunately because the
  613. // conversion API is too dumb to tell us how many chars it converted if
  614. // it couldn't do the whole source.
  615. //
  616. BOOL usedDef;
  617. while ((outPtr < outEnd) && (srcPtr < srcEnd))
  618. {
  619. //
  620. // Do one char and see if it made it.
  621. const unsigned int bytesStored = ::WideCharToMultiByte
  622. (
  623. fWinCP
  624. , WC_COMPOSITECHECK | WC_SEPCHARS
  625. , srcPtr
  626. , 1
  627. , (char*)outPtr
  628. , outEnd - outPtr
  629. , 0
  630. , &usedDef
  631. );
  632. // If we didn't transcode anything, then we are done
  633. if (!bytesStored)
  634. break;
  635. //
  636. // If the defaault char was used and the options indicate that
  637. // this isn't allowed, then throw.
  638. //
  639. if (usedDef && (options == UnRep_Throw))
  640. {
  641. XMLCh tmpBuf[16];
  642. XMLString::binToText((unsigned int)*srcPtr, tmpBuf, 16, 16);
  643. ThrowXML2
  644. (
  645. TranscodingException
  646. , XMLExcepts::Trans_Unrepresentable
  647. , tmpBuf
  648. , getEncodingName()
  649. );
  650. }
  651. // Update our pointers
  652. outPtr += bytesStored;
  653. srcPtr++;
  654. }
  655. // Update the chars eaten
  656. charsEaten = srcPtr - srcData;
  657. // And return the bytes we stored
  658. return outPtr - toFill;
  659. }
  660. bool Win32Transcoder::canTranscodeTo(const unsigned int toCheck) const
  661. {
  662. //
  663. // If the passed value is really a surrogate embedded together, then
  664. // we need to break it out into its two chars. Else just one.
  665. //
  666. XMLCh srcBuf[2];
  667. unsigned int srcCount = 1;
  668. if (toCheck & 0xFFFF0000)
  669. {
  670. srcBuf[0] = XMLCh((toCheck >> 10) + 0xD800);
  671. srcBuf[1] = XMLCh(toCheck & 0x3FF) + 0xDC00;
  672. srcCount++;
  673. }
  674. else
  675. {
  676. srcBuf[0] = XMLCh(toCheck);
  677. }
  678. //
  679. // Use a local temp buffer that would hold any sane multi-byte char
  680. // sequence and try to transcode this guy into it.
  681. //
  682. char tmpBuf[64];
  683. BOOL usedDef;
  684. const unsigned int bytesStored = ::WideCharToMultiByte
  685. (
  686. fWinCP
  687. , WC_COMPOSITECHECK | WC_SEPCHARS
  688. , srcBuf
  689. , srcCount
  690. , tmpBuf
  691. , 64
  692. , 0
  693. , &usedDef
  694. );
  695. if (!bytesStored || usedDef)
  696. return false;
  697. return true;
  698. }
  699. //---------------------------------------------------------------------------
  700. //
  701. // class Win32Transcoder Implementation ...
  702. //
  703. //---------------------------------------------------------------------------
  704. // ---------------------------------------------------------------------------
  705. // Win32LCPTranscoder: Constructors and Destructor
  706. // ---------------------------------------------------------------------------
  707. Win32LCPTranscoder::Win32LCPTranscoder()
  708. {
  709. }
  710. Win32LCPTranscoder::~Win32LCPTranscoder()
  711. {
  712. }
  713. // ---------------------------------------------------------------------------
  714. // Win32LCPTranscoder: Implementation of the virtual transcoder interface
  715. // ---------------------------------------------------------------------------
  716. unsigned int Win32LCPTranscoder::calcRequiredSize(const char* const srcText)
  717. {
  718. if (!srcText)
  719. return 0;
  720. unsigned charLen = ::mblen(srcText, MB_CUR_MAX);
  721. if (charLen == -1)
  722. return 0;
  723. else if (charLen != 0)
  724. charLen = strlen(srcText)/charLen;
  725. if (charLen == -1)
  726. return 0;
  727. return charLen;
  728. }
  729. unsigned int Win32LCPTranscoder::calcRequiredSize(const XMLCh* const srcText)
  730. {
  731. if (!srcText)
  732. return 0;
  733. unsigned int retVal = -1;
  734. #if defined(XML_METROWERKS)
  735. const unsigned int srcLen = ::wcslen(srcText);
  736. retVal = ::wcsmbslen(srcText, srcLen);
  737. #else
  738. retVal = ::wcstombs(0, srcText, 0);
  739. #endif
  740. if (retVal == (unsigned int)-1)
  741. return 0;
  742. return retVal;
  743. }
  744. // Return value using global operator new
  745. // Revisit: deprecate ?
  746. char* Win32LCPTranscoder::transcode(const XMLCh* const toTranscode)
  747. {
  748. if (!toTranscode)
  749. return 0;
  750. char* retVal = 0;
  751. if (*toTranscode)
  752. {
  753. // Calc the needed size
  754. unsigned int neededLen;
  755. #if defined(XML_METROWERKS)
  756. const unsigned int srcLen = ::wcslen(toTranscode);
  757. neededLen = ::wcsmbslen(toTranscode, srcLen);
  758. #else
  759. neededLen = ::wcstombs(0, toTranscode, 0);
  760. #endif
  761. if (neededLen == (unsigned int)-1)
  762. return 0;
  763. // Allocate a buffer of that size plus one for the null and transcode
  764. retVal = new char[neededLen + 1];
  765. ::wcstombs(retVal, toTranscode, neededLen + 1);
  766. // And cap it off anyway just to make sure
  767. retVal[neededLen] = 0;
  768. }
  769. else
  770. {
  771. retVal = new char[1];
  772. retVal[0] = 0;
  773. }
  774. return retVal;
  775. }
  776. char* Win32LCPTranscoder::transcode(const XMLCh* const toTranscode,
  777. MemoryManager* const manager)
  778. {
  779. if (!toTranscode)
  780. return 0;
  781. char* retVal = 0;
  782. if (*toTranscode)
  783. {
  784. // Calc the needed size
  785. const unsigned int neededLen = ::wcstombs(0, toTranscode, 0);
  786. if (neededLen == (unsigned int)-1)
  787. return 0;
  788. // Allocate a buffer of that size plus one for the null and transcode
  789. retVal = (char*) manager->allocate((neededLen + 1) * sizeof(char)); //new char[neededLen + 1];
  790. ::wcstombs(retVal, toTranscode, neededLen + 1);
  791. // And cap it off anyway just to make sure
  792. retVal[neededLen] = 0;
  793. }
  794. else
  795. {
  796. retVal = (char*) manager->allocate(sizeof(char)); //new char[1];
  797. retVal[0] = 0;
  798. }
  799. return retVal;
  800. }
  801. // Return value using global operator new
  802. // Revisit: deprecate ?
  803. XMLCh* Win32LCPTranscoder::transcode(const char* const toTranscode)
  804. {
  805. if (!toTranscode)
  806. return 0;
  807. XMLCh* retVal = 0;
  808. if (*toTranscode)
  809. {
  810. // Calculate the buffer size required
  811. const unsigned int neededLen = calcRequiredSize(toTranscode);
  812. if (neededLen == 0)
  813. {
  814. retVal = new XMLCh[1];
  815. retVal[0] = 0;
  816. return retVal;
  817. }
  818. // Allocate a buffer of that size plus one for the null and transcode
  819. retVal = new XMLCh[neededLen + 1];
  820. ::mbstowcs(retVal, toTranscode, neededLen + 1);
  821. // Cap it off just to make sure. We are so paranoid!
  822. retVal[neededLen] = 0;
  823. }
  824. else
  825. {
  826. retVal = new XMLCh[1];
  827. retVal[0] = 0;
  828. }
  829. return retVal;
  830. }
  831. XMLCh* Win32LCPTranscoder::transcode(const char* const toTranscode,
  832. MemoryManager* const manager)
  833. {
  834. if (!toTranscode)
  835. return 0;
  836. XMLCh* retVal = 0;
  837. if (*toTranscode)
  838. {
  839. // Calculate the buffer size required
  840. const unsigned int neededLen = calcRequiredSize(toTranscode);
  841. if (neededLen == 0)
  842. {
  843. retVal = (XMLCh*) manager->allocate(sizeof(XMLCh)); //new XMLCh[1];
  844. retVal[0] = 0;
  845. return retVal;
  846. }
  847. // Allocate a buffer of that size plus one for the null and transcode
  848. retVal = (XMLCh*) manager->allocate((neededLen + 1) * sizeof(XMLCh)); //new XMLCh[neededLen + 1];
  849. ::mbstowcs(retVal, toTranscode, neededLen + 1);
  850. // Cap it off just to make sure. We are so paranoid!
  851. retVal[neededLen] = 0;
  852. }
  853. else
  854. {
  855. retVal = (XMLCh*) manager->allocate(sizeof(XMLCh*)); //new XMLCh[1];
  856. retVal[0] = 0;
  857. }
  858. return retVal;
  859. }
  860. bool Win32LCPTranscoder::transcode( const char* const toTranscode
  861. , XMLCh* const toFill
  862. , const unsigned int maxChars)
  863. {
  864. // Check for a couple of psycho corner cases
  865. if (!toTranscode || !maxChars)
  866. {
  867. toFill[0] = 0;
  868. return true;
  869. }
  870. if (!*toTranscode)
  871. {
  872. toFill[0] = 0;
  873. return true;
  874. }
  875. // This one has a fixed size output, so try it and if it fails it fails
  876. if (::mbstowcs(toFill, toTranscode, maxChars + 1) == size_t(-1))
  877. return false;
  878. return true;
  879. }
  880. bool Win32LCPTranscoder::transcode( const XMLCh* const toTranscode
  881. , char* const toFill
  882. , const unsigned int maxBytes)
  883. {
  884. // Watch for a couple of pyscho corner cases
  885. if (!toTranscode || !maxBytes)
  886. {
  887. toFill[0] = 0;
  888. return true;
  889. }
  890. if (!*toTranscode)
  891. {
  892. toFill[0] = 0;
  893. return true;
  894. }
  895. // This one has a fixed size output, so try it and if it fails it fails
  896. if (::wcstombs(toFill, toTranscode, maxBytes + 1) == size_t(-1))
  897. return false;
  898. // Cap it off just in case
  899. toFill[maxBytes] = 0;
  900. return true;
  901. }
  902. XERCES_CPP_NAMESPACE_END