PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

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

http://atf2flightsim.googlecode.com/
C++ | 1074 lines | 692 code | 154 blank | 228 comment | 93 complexity | 522b341e8268eb1c485ad4818a88f0bc 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-2002 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. * @01A D998714.1 V5R2M0 100301 Swan :Fix error return flags
  58. * @02A V5R2M0 200419 jrhansen : support lowercase function
  59. * $Id: Iconv400TransService.cpp,v 1.1.1.1 2009/03/14 06:42:37 whitegr Exp $
  60. */
  61. // ---------------------------------------------------------------------------
  62. // Includes
  63. // ---------------------------------------------------------------------------
  64. #include <xercesc/util/TranscodingException.hpp>
  65. #include "Iconv400TransService.hpp"
  66. #include <string.h>
  67. #include <qlgcase.h>
  68. #include "iconv_cnv.hpp"
  69. #include "iconv_util.hpp"
  70. #include <qusec.h>
  71. #include <xercesc/util/XMLUniDefs.hpp>
  72. #include <xercesc/util/XMLString.hpp>
  73. #include <xercesc/util/Janitor.hpp>
  74. XERCES_CPP_NAMESPACE_BEGIN
  75. // ---------------------------------------------------------------------------
  76. // Local functions
  77. // ---------------------------------------------------------------------------
  78. //
  79. // When XMLCh and ICU's UChar are not the same size, we have to do a temp
  80. // conversion of all strings. These local helper methods make that easier.
  81. //
  82. static UChar* convertToUChar( const XMLCh* const toConvert
  83. , const unsigned int srcLen = 0)
  84. {
  85. const unsigned int actualLen = srcLen
  86. ? srcLen : XMLString::stringLen(toConvert);
  87. UChar* tmpBuf = (UChar*) XMLPlatformUtils::fgMemoryManager->allocate
  88. (
  89. (srcLen + 1) * sizeof(UChar)
  90. );//new UChar[srcLen + 1];
  91. const XMLCh* srcPtr = toConvert;
  92. UChar* outPtr = tmpBuf;
  93. while (*srcPtr)
  94. *outPtr++ = UChar(*srcPtr++);
  95. *outPtr = 0;
  96. return tmpBuf;
  97. }
  98. // ---------------------------------------------------------------------------
  99. // Local, const data
  100. // ---------------------------------------------------------------------------
  101. static const XMLCh gMyServiceId[] =
  102. {
  103. chLatin_I, chLatin_C, chLatin_O, chLatin_V, chDigit_4, chDigit_0, chDigit_0, chNull
  104. };
  105. // ---------------------------------------------------------------------------
  106. // IconvTransService: Constructors and Destructor
  107. // ---------------------------------------------------------------------------
  108. Iconv400TransService::Iconv400TransService()
  109. {
  110. memset((char*)&convertCtlblkUpper,'\0',sizeof(convertCtlblkUpper));
  111. convertCtlblkUpper.Type_of_Request = 1;
  112. convertCtlblkUpper.Case_Request = 0; // upper case
  113. convertCtlblkUpper.CCSID_of_Input_Data = 13488;
  114. memset((char*)&convertCtlblkLower,'\0',sizeof(convertCtlblkLower));
  115. convertCtlblkLower.Type_of_Request = 1;
  116. convertCtlblkLower.Case_Request = 1;
  117. convertCtlblkLower.CCSID_of_Input_Data = 13488;
  118. }
  119. Iconv400TransService::~Iconv400TransService()
  120. {
  121. }
  122. // ---------------------------------------------------------------------------
  123. // Iconv400TransService: The virtual transcoding service API
  124. // ---------------------------------------------------------------------------
  125. int Iconv400TransService::compareIString(const XMLCh* const comp1
  126. , const XMLCh* const comp2)
  127. {
  128. const XMLCh* psz1 = comp1;
  129. const XMLCh* psz2 = comp2;
  130. while (true)
  131. {
  132. if (toUnicodeUpper(*psz1) != toUnicodeUpper(*psz2))
  133. return int(*psz1) - int(*psz2);
  134. // If either has ended, then they both ended, so equal
  135. if (!*psz1 || !*psz2)
  136. break;
  137. // Move upwards for the next round
  138. psz1++;
  139. psz2++;
  140. }
  141. return 0;
  142. }
  143. int Iconv400TransService::compareNIString(const XMLCh* const comp1
  144. , const XMLCh* const comp2
  145. , const unsigned int maxChars)
  146. {
  147. const XMLCh* psz1 = comp1;
  148. const XMLCh* psz2 = comp2;
  149. unsigned int curCount = 0;
  150. while (true)
  151. {
  152. // If an inequality, then return the difference
  153. // If an inequality, then return difference
  154. if (toUnicodeUpper(*psz1) != toUnicodeUpper(*psz2))
  155. return int(*psz1) - int(*psz2);
  156. // If either ended, then both ended, so equal
  157. if (!*psz1 || !*psz2)
  158. break;
  159. // Move upwards to next chars
  160. psz1++;
  161. psz2++;
  162. //
  163. // Bump the count of chars done. If it equals the count then we
  164. // are equal for the requested count, so break out and return
  165. // equal.
  166. //
  167. curCount++;
  168. if (maxChars == curCount)
  169. break;
  170. }
  171. return 0;
  172. }
  173. const XMLCh* Iconv400TransService::getId() const
  174. {
  175. return gMyServiceId;
  176. }
  177. bool Iconv400TransService::isSpace(const XMLCh toCheck) const
  178. {
  179. // The following are Unicode Space characters
  180. //
  181. if ((toCheck == 0x09)
  182. || (toCheck == 0x0A)
  183. || (toCheck == 0x0D)
  184. || (toCheck == 0x20)
  185. || (toCheck == 0xA0)
  186. || ((toCheck >= 0x2000) && (toCheck <= 0x200B))
  187. || (toCheck == 0x3000)
  188. || (toCheck == 0xFEFF))
  189. {
  190. return true;
  191. }
  192. else return false;
  193. }
  194. XMLLCPTranscoder* Iconv400TransService::makeNewLCPTranscoder()
  195. {
  196. //
  197. // Try to create a default converter. If it fails, return a null pointer
  198. // which will basically cause the system to give up because we really can't
  199. // do anything without one.
  200. //
  201. UErrorCode uerr = U_ZERO_ERROR;
  202. UConverter* converter = ucnv_open(NULL, &uerr);
  203. if (!converter)
  204. return 0;
  205. // That went ok, so create an Iconv LCP transcoder wrapper and return it
  206. return new Iconv400LCPTranscoder(converter);
  207. }
  208. bool Iconv400TransService::supportsSrcOfs() const
  209. {
  210. // This implementation supports source offset information
  211. return true;
  212. }
  213. void Iconv400TransService::upperCase(XMLCh* const toUpperCase) const
  214. {
  215. XMLCh* outPtr = toUpperCase;
  216. while (*outPtr)
  217. {
  218. *outPtr = toUnicodeUpper(*outPtr);
  219. outPtr++;
  220. }
  221. }
  222. void Iconv400TransService::lowerCase(XMLCh* const toLowerCase) const
  223. {
  224. XMLCh* outPtr = toLowerCase;
  225. while (*outPtr)
  226. {
  227. *outPtr = toUnicodeLower(*outPtr);
  228. outPtr++;
  229. }
  230. }
  231. // ---------------------------------------------------------------------------
  232. // Iconv400TransService: The virtual transcoding service API
  233. // ---------------------------------------------------------------------------
  234. XMLCh Iconv400TransService::toUnicodeUpper(XMLCh comp1) const
  235. {
  236. XMLCh chRet;
  237. struct {
  238. int bytes_available;
  239. int bytes_used;
  240. char exception_id[7];
  241. char reserved;
  242. char exception_data[15];
  243. } error_code;
  244. error_code.bytes_available = sizeof(error_code);
  245. long charlen =2;
  246. QlgConvertCase((char*)&convertCtlblkUpper,
  247. (char*)&comp1,
  248. (char*)&chRet,
  249. (long*)&charlen,
  250. (char*)&error_code);
  251. return chRet;
  252. }
  253. XMLCh Iconv400TransService::toUnicodeLower(XMLCh comp1) const
  254. {
  255. XMLCh chRet;
  256. struct {
  257. int bytes_available;
  258. int bytes_used;
  259. char exception_id[7];
  260. char reserved;
  261. char exception_data[15];
  262. } error_code;
  263. error_code.bytes_available = sizeof(error_code);
  264. long charlen =2;
  265. QlgConvertCase((char*)&convertCtlblkLower,
  266. (char*)&comp1,
  267. (char*)&chRet,
  268. (long*)&charlen,
  269. (char*)&error_code);
  270. return chRet;
  271. }
  272. // ---------------------------------------------------------------------------
  273. // Iconv400TransService: The protected virtual transcoding service API
  274. // ---------------------------------------------------------------------------
  275. XMLTranscoder*
  276. Iconv400TransService::makeNewXMLTranscoder( const XMLCh* const encodingName
  277. , XMLTransService::Codes& resValue
  278. , const unsigned int blockSize
  279. , MemoryManager* const manager)
  280. {
  281. UErrorCode uerr = U_ZERO_ERROR;
  282. UConverter* converter = ucnv_openU(encodingName, &uerr);
  283. if (!converter)
  284. {
  285. resValue = XMLTransService::UnsupportedEncoding;
  286. return 0;
  287. }
  288. return new (manager) Iconv400Transcoder(encodingName, converter, blockSize, manager);
  289. }
  290. // ---------------------------------------------------------------------------
  291. // IconvTranscoder: Constructors and Destructor
  292. // ---------------------------------------------------------------------------
  293. Iconv400Transcoder::Iconv400Transcoder( const XMLCh* const encodingName
  294. , UConverter* const toAdopt
  295. , const unsigned int blockSize
  296. , MemoryManager* const manager) :
  297. XMLTranscoder(encodingName, blockSize, manager)
  298. , fConverter(toAdopt)
  299. , fFixed(false)
  300. , fSrcOffsets(0)
  301. {
  302. // If there is a block size, then allocate our source offset array
  303. if (blockSize)
  304. fSrcOffsets = (long*) manager->allocate(blockSize * sizeof(long));//new long[blockSize];
  305. // Remember if its a fixed size encoding
  306. fFixed = (ucnv_getMaxCharSize(fConverter) == ucnv_getMinCharSize(fConverter));
  307. }
  308. Iconv400Transcoder::~Iconv400Transcoder()
  309. {
  310. getMemoryManager()->deallocate(fSrcOffsets);//delete [] fSrcOffsets;
  311. // If there is a converter, ask Iconv400 to clean it up
  312. if (fConverter)
  313. {
  314. // <TBD> Does this actually delete the structure???
  315. ucnv_close(fConverter);
  316. fConverter = 0;
  317. }
  318. }
  319. // ---------------------------------------------------------------------------
  320. // Iconv400Transcoder: The virtual transcoder API
  321. // ---------------------------------------------------------------------------
  322. unsigned int
  323. Iconv400Transcoder::transcodeFrom(const XMLByte* const srcData
  324. , const unsigned int srcCount
  325. , XMLCh* const toFill
  326. , const unsigned int maxChars
  327. , unsigned int& bytesEaten
  328. , unsigned char* const charSizes)
  329. {
  330. // If debugging, insure the block size is legal
  331. // Set up pointers to the start and end of the source buffer
  332. const XMLByte* startSrc = srcData;
  333. const XMLByte* endSrc = srcData + srcCount;
  334. //
  335. // And now do the target buffer. This works differently according to
  336. // whether XMLCh and UChar are the same size or not.
  337. //
  338. UChar* startTarget;
  339. if (sizeof(XMLCh) == sizeof(UChar))
  340. startTarget = (UChar*)toFill;
  341. else
  342. startTarget = (UChar*) getMemoryManager()->allocate
  343. (
  344. maxChars * sizeof(UChar)
  345. );//new UChar[maxChars];
  346. UChar* orgTarget = startTarget;
  347. //
  348. // Transoode the buffer. Buffer overflow errors are normal, occuring
  349. // when the raw input buffer holds more characters than will fit in
  350. // the Unicode output buffer.
  351. //
  352. UErrorCode err = U_ZERO_ERROR;
  353. ucnv_toUnicode
  354. (
  355. fConverter
  356. , &startTarget
  357. , startTarget + maxChars
  358. , (const char**)&startSrc
  359. , (const char*)endSrc
  360. , (fFixed ? 0 : (int32_t*)fSrcOffsets)
  361. , false
  362. , &err
  363. );
  364. if ((err != U_ZERO_ERROR) && (err != U_INDEX_OUTOFBOUNDS_ERROR))
  365. {
  366. if (orgTarget != (UChar*)toFill)
  367. getMemoryManager()->deallocate(orgTarget);//delete [] orgTarget;
  368. if (fFixed)
  369. {
  370. XMLCh tmpBuf[16];
  371. XMLString::binToText((unsigned int)(*startTarget), tmpBuf, 16, 16);
  372. ThrowXML2
  373. (
  374. TranscodingException
  375. , XMLExcepts::Trans_BadSrcCP
  376. , tmpBuf
  377. , getEncodingName()
  378. );
  379. }
  380. else
  381. {
  382. ThrowXML(TranscodingException, XMLExcepts::Trans_BadSrcSeq);
  383. }
  384. }
  385. // Calculate the bytes eaten and store in caller's param
  386. bytesEaten = startSrc - srcData;
  387. // And the characters decoded
  388. const unsigned int charsDecoded = startTarget - orgTarget;
  389. //
  390. // Translate the array of char offsets into an array of character
  391. // sizes, which is what the transcoder interface semantics requires.
  392. // If its fixed, then we can optimize it.
  393. //
  394. if (fFixed)
  395. {
  396. const unsigned char fillSize = (unsigned char)ucnv_getMaxCharSize(fConverter);;
  397. memset(charSizes, fillSize, maxChars);
  398. }
  399. else
  400. {
  401. //
  402. // We have to convert the series of offsets into a series of
  403. // sizes. If just one char was decoded, then its the total bytes
  404. // eaten. Otherwise, do a loop and subtract out each element from
  405. // its previous element.
  406. //
  407. if (charsDecoded == 1)
  408. {
  409. charSizes[0] = (unsigned char)bytesEaten;
  410. }
  411. else
  412. {
  413. // ICU does not return an extra element to allow us to figure
  414. // out the last char size, so we have to compute it from the
  415. // total bytes used.
  416. unsigned int index;
  417. for (index = 0; index < charsDecoded - 1; index++)
  418. {
  419. charSizes[index] = (unsigned char)(fSrcOffsets[index + 1]
  420. - fSrcOffsets[index]);
  421. }
  422. if( charsDecoded > 0 ) {
  423. charSizes[charsDecoded - 1] = (unsigned char)(bytesEaten
  424. - fSrcOffsets[charsDecoded - 1]);
  425. }
  426. }
  427. }
  428. //
  429. // If XMLCh and UChar are not the same size, then we need to copy over
  430. // the temp buffer to the new one.
  431. //
  432. if (sizeof(UChar) != sizeof(XMLCh))
  433. {
  434. XMLCh* outPtr = toFill;
  435. startTarget = orgTarget;
  436. for (unsigned int index = 0; index < charsDecoded; index++)
  437. *outPtr++ = XMLCh(*startTarget++);
  438. // And delete the temp buffer
  439. getMemoryManager()->deallocate(orgTarget);//delete [] orgTarget;
  440. }
  441. // Return the chars we put into the target buffer
  442. return charsDecoded;
  443. }
  444. unsigned int
  445. Iconv400Transcoder::transcodeTo( const XMLCh* const srcData
  446. , const unsigned int srcCount
  447. , XMLByte* const toFill
  448. , const unsigned int maxBytes
  449. , unsigned int& charsEaten
  450. , const UnRepOpts options)
  451. {
  452. //
  453. // Get a pointer to the buffer to transcode. If UChar and XMLCh are
  454. // the same size here, then use the original. Else, create a temp
  455. // one and put a janitor on it.
  456. //
  457. const UChar* srcPtr;
  458. UChar* tmpBufPtr = 0;
  459. if (sizeof(XMLCh) == sizeof(UChar))
  460. {
  461. srcPtr = (const UChar*)srcData;
  462. }
  463. else
  464. {
  465. tmpBufPtr = convertToUChar(srcData, srcCount);
  466. srcPtr = tmpBufPtr;
  467. }
  468. ArrayJanitor<UChar> janTmpBuf(tmpBufPtr, XMLPlatformUtils::fgMemoryManager);
  469. //
  470. // Set the appropriate callback so that it will either fail or use
  471. // the rep char. Remember the old one so we can put it back.
  472. //
  473. UErrorCode err = U_ZERO_ERROR;
  474. //
  475. // Ok, lets transcode as many chars as we we can in one shot. The
  476. // ICU API gives enough info not to have to do this one char by char.
  477. //
  478. XMLByte* startTarget = toFill;
  479. const UChar* startSrc = srcPtr;
  480. err = U_ZERO_ERROR;
  481. ucnv_fromUnicode
  482. (
  483. fConverter
  484. , (char**)&startTarget
  485. , (char*)(startTarget + maxBytes)
  486. , &startSrc
  487. , srcPtr + srcCount
  488. , 0
  489. , false
  490. , &err
  491. );
  492. if (err) /*@01A*/
  493. {
  494. XMLCh tmpBuf[16];
  495. XMLString::binToText((unsigned int)*startSrc, tmpBuf, 16, 16);
  496. ThrowXML2
  497. (
  498. TranscodingException
  499. , XMLExcepts::Trans_Unrepresentable
  500. , tmpBuf
  501. , getEncodingName()
  502. );
  503. }
  504. // Fill in the chars we ate from the input
  505. charsEaten = startSrc - srcPtr;
  506. // Return the chars we stored
  507. return startTarget - toFill;
  508. }
  509. bool Iconv400Transcoder::canTranscodeTo(const unsigned int toCheck) const
  510. {
  511. //
  512. // If the passed value is really a surrogate embedded together, then
  513. // we need to break it out into its two chars. Else just one. While
  514. // we are ate it, convert them to UChar format if required.
  515. //
  516. UChar srcBuf[2];
  517. unsigned int srcCount = 1;
  518. if (toCheck & 0xFFFF0000)
  519. {
  520. srcBuf[0] = UChar((toCheck >> 10) + 0xD800);
  521. srcBuf[1] = UChar(toCheck & 0x3FF) + 0xDC00;
  522. srcCount++;
  523. }
  524. else
  525. {
  526. srcBuf[0] = UChar(toCheck);
  527. }
  528. // Set upa temp buffer to format into. Make it more than big enough
  529. char tmpBuf[64];
  530. char* startTarget = tmpBuf;
  531. const UChar* startSrc = srcBuf;
  532. UErrorCode err = U_ZERO_ERROR;
  533. ucnv_fromUnicode
  534. (
  535. fConverter
  536. , &startTarget
  537. , startTarget + 64
  538. , &startSrc
  539. , srcBuf + srcCount
  540. , 0
  541. , false
  542. , &err
  543. );
  544. return (err==U_ZERO_ERROR); /*@01A*/
  545. }
  546. // ---------------------------------------------------------------------------
  547. // IconvLCPTranscoder: Constructors and Destructor
  548. // ---------------------------------------------------------------------------
  549. Iconv400LCPTranscoder::Iconv400LCPTranscoder(UConverter* const toAdopt) :
  550. fConverter(toAdopt)
  551. {
  552. }
  553. Iconv400LCPTranscoder::~Iconv400LCPTranscoder()
  554. {
  555. // If there is a converter, ask Iconv to clean it up
  556. if (fConverter)
  557. {
  558. // <TBD> Does this actually delete the structure???
  559. ucnv_close(fConverter);
  560. fConverter = 0;
  561. }
  562. }
  563. // ---------------------------------------------------------------------------
  564. // Iconv400LCPTranscoder: Constructors and Destructor
  565. // ---------------------------------------------------------------------------
  566. unsigned int Iconv400LCPTranscoder::calcRequiredSize(const XMLCh* const srcText)
  567. {
  568. if (!srcText)
  569. return 0;
  570. // Lock and attempt the calculation
  571. UErrorCode err = U_ZERO_ERROR;
  572. int32_t targetCap;
  573. {
  574. XMLMutexLock lockConverter(&fMutex);
  575. targetCap = ucnv_fromUChars
  576. (
  577. fConverter
  578. , 0
  579. , 0
  580. , srcText
  581. , &err
  582. );
  583. }
  584. if (err != U_BUFFER_OVERFLOW_ERROR)
  585. return 0;
  586. return (unsigned int)targetCap;
  587. }
  588. unsigned int Iconv400LCPTranscoder::calcRequiredSize(const char* const srcText)
  589. {
  590. if (!srcText)
  591. return 0;
  592. int32_t targetCap;
  593. UErrorCode err = U_ZERO_ERROR;
  594. {
  595. XMLMutexLock lockConverter(&fMutex);
  596. targetCap = ucnv_toUChars
  597. (
  598. fConverter
  599. , 0
  600. , 0
  601. , srcText
  602. , strlen(srcText)
  603. , &err
  604. );
  605. }
  606. if (err != U_BUFFER_OVERFLOW_ERROR)
  607. return 0;
  608. // Subtract one since it includes the terminator space
  609. return (unsigned int)(targetCap - 1);
  610. }
  611. char* Iconv400LCPTranscoder::transcode(const XMLCh* const toTranscode)
  612. {
  613. char* retBuf = 0;
  614. // Check for a couple of special cases
  615. if (!toTranscode)
  616. return 0;
  617. if (!*toTranscode)
  618. {
  619. retBuf = new char[1];
  620. retBuf[0] = 0;
  621. return retBuf;
  622. }
  623. // Caculate a return buffer size not too big, but less likely to overflow
  624. int32_t targetLen = (int32_t)(u_strlen(toTranscode) * 1.25);
  625. // Allocate the return buffer
  626. retBuf = new char[targetLen + 1];
  627. // Lock now while we call the converter.
  628. UErrorCode err = U_ZERO_ERROR;
  629. int32_t targetCap;
  630. {
  631. XMLMutexLock lockConverter(&fMutex);
  632. //Convert the Unicode string to char*
  633. targetCap = ucnv_fromUChars
  634. (
  635. fConverter
  636. , retBuf
  637. , targetLen + 1
  638. , toTranscode
  639. , &err
  640. );
  641. }
  642. // If targetLen is not enough then buffer overflow might occur
  643. if (err == U_BUFFER_OVERFLOW_ERROR)
  644. {
  645. // Reset the error, delete the old buffer, allocate a new one, and try again
  646. err = U_ZERO_ERROR;
  647. delete [] retBuf;
  648. retBuf = new char[targetCap];
  649. // Lock again before we retry
  650. XMLMutexLock lockConverter(&fMutex);
  651. targetCap = ucnv_fromUChars
  652. (
  653. fConverter
  654. , retBuf
  655. , targetCap
  656. , toTranscode
  657. , &err
  658. );
  659. }
  660. if (U_FAILURE(err))
  661. {
  662. delete [] retBuf;
  663. return 0;
  664. }
  665. // Cap it off and return
  666. retBuf[targetCap] = 0;
  667. return retBuf;
  668. }
  669. char* Iconv400LCPTranscoder::transcode(const XMLCh* const toTranscode,
  670. MemoryManager* const manager)
  671. {
  672. char* retBuf = 0;
  673. // Check for a couple of special cases
  674. if (!toTranscode)
  675. return 0;
  676. if (!*toTranscode)
  677. {
  678. retBuf = (char*) manager->allocate(sizeof(char));//new char[1];
  679. retBuf[0] = 0;
  680. return retBuf;
  681. }
  682. // Caculate a return buffer size not too big, but less likely to overflow
  683. int32_t targetLen = (int32_t)(u_strlen(toTranscode) * 1.25);
  684. // Allocate the return buffer
  685. retBuf = (char*) manager->allocate((targetLen + 1) * sizeof(char));//new char[targetLen + 1];
  686. // Lock now while we call the converter.
  687. UErrorCode err = U_ZERO_ERROR;
  688. int32_t targetCap;
  689. {
  690. XMLMutexLock lockConverter(&fMutex);
  691. //Convert the Unicode string to char*
  692. targetCap = ucnv_fromUChars
  693. (
  694. fConverter
  695. , retBuf
  696. , targetLen + 1
  697. , toTranscode
  698. , &err
  699. );
  700. }
  701. // If targetLen is not enough then buffer overflow might occur
  702. if (err == U_BUFFER_OVERFLOW_ERROR)
  703. {
  704. // Reset the error, delete the old buffer, allocate a new one, and try again
  705. err = U_ZERO_ERROR;
  706. manager->deallocate(retBuf);//delete [] retBuf;
  707. retBuf = (char*) manager->allocate(targetCap * sizeof(char));//new char[targetCap];
  708. // Lock again before we retry
  709. XMLMutexLock lockConverter(&fMutex);
  710. targetCap = ucnv_fromUChars
  711. (
  712. fConverter
  713. , retBuf
  714. , targetCap
  715. , toTranscode
  716. , &err
  717. );
  718. }
  719. if (U_FAILURE(err))
  720. {
  721. manager->deallocate(retBuf);//delete [] retBuf;
  722. return 0;
  723. }
  724. // Cap it off and return
  725. retBuf[targetCap] = 0;
  726. return retBuf;
  727. }
  728. XMLCh* Iconv400LCPTranscoder::transcode(const char* const toTranscode)
  729. {
  730. // Watch for a few pyscho corner cases
  731. if (!toTranscode)
  732. return 0;
  733. XMLCh* retVal = 0;
  734. if (!*toTranscode)
  735. {
  736. retVal = new XMLCh[1];
  737. retVal[0] = 0;
  738. return retVal;
  739. }
  740. //
  741. // Get the length of the string to transcode. The Unicode string will
  742. // almost always be no more chars than were in the source, so this is
  743. // the best guess as to the storage needed.
  744. //
  745. const int32_t srcLen = (int32_t)strlen(toTranscode);
  746. // Allocate unicode string of equivalent length in unicode bytes
  747. retVal = new XMLCh[srcLen+1];
  748. // Now lock while we do these calculations
  749. UErrorCode err = U_ZERO_ERROR;
  750. {
  751. XMLMutexLock lockConverter(&fMutex);
  752. //
  753. // Here we don't know what the target length will be so use 0 and
  754. // expect an U_BUFFER_OVERFLOW_ERROR in which case it'd get resolved
  755. // by the correct capacity value.
  756. //
  757. int32_t targetCap;
  758. targetCap = ucnv_toUChars
  759. (
  760. fConverter
  761. , retVal
  762. , srcLen+1
  763. , toTranscode
  764. , srcLen
  765. , &err
  766. );
  767. if (err != U_BUFFER_OVERFLOW_ERROR)
  768. {
  769. err = U_ZERO_ERROR;
  770. retVal = new XMLCh[targetCap];
  771. ucnv_toUChars
  772. (
  773. fConverter
  774. , retVal
  775. , targetCap
  776. , toTranscode
  777. , srcLen
  778. , &err
  779. );
  780. }
  781. }
  782. if (U_FAILURE(err))
  783. {
  784. // Clean up if we got anything allocated
  785. delete [] retVal;
  786. return 0;
  787. }
  788. return retVal;
  789. }
  790. XMLCh* Iconv400LCPTranscoder::transcode(const char* const toTranscode,
  791. MemoryManager* const manager)
  792. {
  793. // Watch for a few pyscho corner cases
  794. if (!toTranscode)
  795. return 0;
  796. XMLCh* retVal = 0;
  797. if (!*toTranscode)
  798. {
  799. retVal = (XMLCh*) manager->allocate(sizeof(XMLCh));//new XMLCh[1];
  800. retVal[0] = 0;
  801. return retVal;
  802. }
  803. //
  804. // Get the length of the string to transcode. The Unicode string will
  805. // almost always be no more chars than were in the source, so this is
  806. // the best guess as to the storage needed.
  807. //
  808. const int32_t srcLen = (int32_t)strlen(toTranscode);
  809. // Allocate unicode string of equivalent length in unicode bytes
  810. retVal = (XMLCh*) manager->allocate((srcLen + 1) * sizeof(XMLCh));//new XMLCh[srcLen+1];
  811. // Now lock while we do these calculations
  812. UErrorCode err = U_ZERO_ERROR;
  813. {
  814. XMLMutexLock lockConverter(&fMutex);
  815. //
  816. // Here we don't know what the target length will be so use 0 and
  817. // expect an U_BUFFER_OVERFLOW_ERROR in which case it'd get resolved
  818. // by the correct capacity value.
  819. //
  820. int32_t targetCap;
  821. targetCap = ucnv_toUChars
  822. (
  823. fConverter
  824. , retVal
  825. , srcLen+1
  826. , toTranscode
  827. , srcLen
  828. , &err
  829. );
  830. if (err != U_BUFFER_OVERFLOW_ERROR)
  831. {
  832. err = U_ZERO_ERROR;
  833. retVal = (XMLCh*) manager->allocate(targetCap * sizeof(XMLCh));//new XMLCh[targetCap];
  834. ucnv_toUChars
  835. (
  836. fConverter
  837. , retVal
  838. , targetCap
  839. , toTranscode
  840. , srcLen
  841. , &err
  842. );
  843. }
  844. }
  845. if (U_FAILURE(err))
  846. {
  847. // Clean up if we got anything allocated
  848. manager->deallocate(retVal);//delete [] retVal;
  849. return 0;
  850. }
  851. return retVal;
  852. }
  853. bool Iconv400LCPTranscoder::transcode(const char* const toTranscode
  854. , XMLCh* const toFill
  855. , const unsigned int maxChars)
  856. {
  857. // Check for a couple of psycho corner cases
  858. if (!toTranscode || !maxChars)
  859. {
  860. toFill[0] = 0;
  861. return true;
  862. }
  863. if (!*toTranscode)
  864. {
  865. toFill[0] = 0;
  866. return true;
  867. }
  868. // Lock and do the transcode operation
  869. UErrorCode err = U_ZERO_ERROR;
  870. const int32_t srcLen = (int32_t)strlen(toTranscode);
  871. {
  872. XMLMutexLock lockConverter(&fMutex);
  873. ucnv_toUChars
  874. (
  875. fConverter
  876. , toFill
  877. , maxChars + 1
  878. , toTranscode
  879. , srcLen
  880. , &err
  881. );
  882. }
  883. if (U_FAILURE(err))
  884. return false;
  885. return true;
  886. }
  887. bool Iconv400LCPTranscoder::transcode( const XMLCh* const toTranscode
  888. , char* const toFill
  889. , const unsigned int maxChars)
  890. {
  891. // Watch for a few psycho corner cases
  892. if (!toTranscode || !maxChars)
  893. {
  894. toFill[0] = 0;
  895. return true;
  896. }
  897. if (!*toTranscode)
  898. {
  899. toFill[0] = 0;
  900. return true;
  901. }
  902. UErrorCode err = U_ZERO_ERROR;
  903. int32_t targetCap;
  904. {
  905. XMLMutexLock lockConverter(&fMutex);
  906. targetCap = ucnv_fromUChars
  907. (
  908. fConverter
  909. , toFill
  910. , maxChars + 1
  911. , toTranscode
  912. , &err
  913. );
  914. }
  915. if (U_FAILURE(err))
  916. return false;
  917. toFill[targetCap] = 0;
  918. return true;
  919. }
  920. XERCES_CPP_NAMESPACE_END