MacOSUnicodeConverter.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:41k
源码类别:

词法分析

开发平台:

Visual C++

  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: MacOSUnicodeConverter.cpp,v 1.15 2003/05/22 14:42:32 jberry Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <xercesc/util/XercesDefs.hpp>
  63. #include <algorithm>
  64. #include <cstddef>
  65. #include <cstring>
  66. #if defined(XML_METROWERKS) || (__GNUC__ >= 3 && _GLIBCPP_USE_WCHAR_T)
  67. // Only used under metrowerks.
  68. #include <cwctype>
  69. #endif
  70. #if defined(__APPLE__)
  71.     // Framework includes from ProjectBuilder
  72.     #include <CoreServices/CoreServices.h>
  73. #else
  74.     // Classic includes otherwise
  75.     #include <MacErrors.h>
  76.     #include <Script.h>
  77.     #include <TextUtils.h>
  78.     #include <TextEncodingConverter.h>
  79.     #include <TextCommon.h>
  80.     #include <CodeFragments.h>
  81.     #include <UnicodeConverter.h>
  82.     #include <UnicodeUtilities.h>
  83.     #include <CFCharacterSet.h>
  84.     #include <CFString.h>
  85. #endif
  86. #include <xercesc/util/Transcoders/MacOSUnicodeConverter/MacOSUnicodeConverter.hpp>
  87. #include <xercesc/util/XMLUniDefs.hpp>
  88. #include <xercesc/util/XMLUni.hpp>
  89. #include <xercesc/util/XMLString.hpp>
  90. #include <xercesc/util/TranscodingException.hpp>
  91. #include <xercesc/util/PlatformUtils.hpp>
  92. #include <xercesc/util/Janitor.hpp>
  93. #include <xercesc/util/Platforms/MacOS/MacOSPlatformUtils.hpp>
  94. XERCES_CPP_NAMESPACE_BEGIN
  95. // ---------------------------------------------------------------------------
  96. // Typedefs
  97. // ---------------------------------------------------------------------------
  98. // TempUniBuf is used for cases where we need a temporary conversion due to
  99. // a mismatch between UniChar (the 16-bit type that the Unicode converter uses)
  100. // and XMLCh (the type that Xerces uses to represent a Unicode character).
  101. // In the case of Metrowerks, these are the same size. For ProjectBuilder, they
  102. // used to differ, but they are now the same since XMLCh is now always fixed
  103. // as a 16 bit character, rather than floating with wchar_t as it used to.
  104. // *** Most uses of this buffer should be removed from this code in time! ***
  105. // TempUniBuf is also used for a few cases where we want to discard the
  106. // output from the unicode converter.
  107. const std::size_t kTempUniBufCount = 256;
  108. typedef UniChar TempUniBuf[kTempUniBufCount];
  109. // ---------------------------------------------------------------------------
  110. //  Local, const data
  111. // ---------------------------------------------------------------------------
  112. static const XMLCh gMyServiceId[] =
  113. {
  114.     chLatin_M, chLatin_a, chLatin_c, chLatin_O, chLatin_S, chNull
  115. };
  116. // Detect a mismatch in unicode character size.
  117. #define UNICODE_SIZE_MISMATCH (sizeof(XMLCh) != sizeof(UniChar))
  118. // ---------------------------------------------------------------------------
  119. //  MacOSUnicodeConverter: Constructors and Destructor
  120. // ---------------------------------------------------------------------------
  121. MacOSUnicodeConverter::MacOSUnicodeConverter()
  122. {
  123. // Test for presense of unicode collation functions
  124. mHasUnicodeCollation = (UCCompareTextDefault != (void*)kUnresolvedCFragSymbolAddress);
  125. }
  126. MacOSUnicodeConverter::~MacOSUnicodeConverter()
  127. {
  128. }
  129. // ---------------------------------------------------------------------------
  130. //  MacOSUnicodeConverter: The virtual transcoding service API
  131. // ---------------------------------------------------------------------------
  132. int MacOSUnicodeConverter::compareIString(  const XMLCh* const    comp1
  133.                                           , const XMLCh* const    comp2)
  134. {
  135. // If unicode collation routines are available, use them.
  136. // This should be the case on Mac OS 8.6 and later,
  137. // with Carbon 1.0.2 or later, and under Mac OS X.
  138. //
  139. // Otherwise, but only for Metrowerks, since only Metrowerks
  140. // has a c library with a valid set of wchar routines,
  141. // fall back to the standard library.
  142. if (mHasUnicodeCollation)
  143. {
  144. // Use the Unicode Utilities to do the compare
  145. // This has gotten more painful with the need to allow
  146. // conversion between different sizes of XMLCh and UniChar.
  147. // We allocate a static buffer and do multiple passes
  148. // to allow for the case where the strings being compared
  149. // are larger than the static buffer.
  150. UCCollateOptions collateOptions =
  151. kUCCollateComposeInsensitiveMask
  152. | kUCCollateWidthInsensitiveMask
  153. | kUCCollateCaseInsensitiveMask
  154. | kUCCollatePunctuationSignificantMask
  155. ;
  156. std::size_t srcOffset = 0;
  157. std::size_t cnt1 = XMLString::stringLen(comp1);
  158. std::size_t cnt2 = XMLString::stringLen(comp2);
  159. // Do multiple passes over source, comparing each pass.
  160. // The first pass that's not equal wins.
  161. int result = 0;
  162. while (result == 0 && (cnt1 || cnt2))
  163. {
  164. TempUniBuf buf1;
  165. TempUniBuf buf2;
  166. const UniChar* src1;
  167. const UniChar* src2;
  168. std::size_t passCnt1;
  169. std::size_t passCnt2;
  170. if (UNICODE_SIZE_MISMATCH)
  171. {
  172. passCnt1 = std::min(cnt1, kTempUniBufCount);
  173. passCnt2 = std::min(cnt2, kTempUniBufCount);
  174. src1 = CopyXMLChsToUniChars(comp1 + srcOffset, buf1, passCnt1, kTempUniBufCount);
  175. src2 = CopyXMLChsToUniChars(comp2 + srcOffset, buf2, passCnt2, kTempUniBufCount);
  176. }
  177. else
  178. {
  179. passCnt1 = cnt1;
  180. passCnt2 = cnt2;
  181. src1 = reinterpret_cast<const UniChar*>(comp1);
  182. src2 = reinterpret_cast<const UniChar*>(comp2);
  183. }
  184. // Do the actual compare for this pass
  185. Boolean equivalent = false;
  186. SInt32 order = 0;
  187. OSStatus status = UCCompareTextDefault(
  188. collateOptions,
  189. src1,
  190. passCnt1,
  191. src2,
  192. passCnt2,
  193. &equivalent,
  194. &order
  195. );
  196. result = ((status != noErr) || equivalent) ? 0 : order;
  197. srcOffset += kTempUniBufCount;
  198. cnt1 -= passCnt1;
  199. cnt2 -= passCnt2;
  200. }
  201. return result;
  202. }
  203. #if defined(XML_METROWERKS)
  204. else
  205. {
  206. const XMLCh* cptr1 = comp1;
  207. const XMLCh* cptr2 = comp2;
  208. while ( (*cptr1 != 0) && (*cptr2 != 0) )
  209. {
  210. std::wint_t wch1 = std::towupper(*cptr1);
  211. std::wint_t wch2 = std::towupper(*cptr2);
  212. if (wch1 != wch2)
  213. break;
  214. cptr1++;
  215. cptr2++;
  216. }
  217. return (int) (std::towupper(*cptr1) - std::towupper(*cptr2));
  218. }
  219. #else
  220. else
  221. {
  222. // For some reason there is no platform utils available
  223. // where we expect it. Bail.
  224. XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  225. return 0;
  226. }
  227. #endif
  228. }
  229. int MacOSUnicodeConverter::compareNIString( const   XMLCh* const    comp1
  230.                                         , const XMLCh* const    comp2
  231.                                         , const unsigned int    maxChars)
  232. {
  233. // If unicode collation routines are available, use them.
  234. // This should be the case on Mac OS 8.6 and later,
  235. // with Carbon 1.0.2 or later, and under Mac OS X.
  236. //
  237. // Otherwise, but only for Metrowerks, since only Metrowerks
  238. // has a c library with a valid set of wchar routines,
  239. // fall back to the standard library.
  240. if (mHasUnicodeCollation)
  241. {
  242. // Use the Unicode Utilities to do the compare
  243. // This has gotten more painful with the need to allow
  244. // conversion between different sizes of XMLCh and UniChar.
  245. // We allocate a static buffer and do multiple passes
  246. // to allow for the case where the strings being compared
  247. // are larger than the static buffer.
  248. UCCollateOptions collateOptions =
  249. kUCCollateComposeInsensitiveMask
  250. | kUCCollateWidthInsensitiveMask
  251. | kUCCollateCaseInsensitiveMask
  252. | kUCCollatePunctuationSignificantMask
  253. ;
  254. std::size_t srcOffset = 0;
  255. std::size_t cnt1 = XMLString::stringLen(comp1);
  256. std::size_t cnt2 = XMLString::stringLen(comp2);
  257. // Restrict view of source characters to first {maxChars}
  258. if (cnt1 > maxChars)
  259. cnt1 = maxChars;
  260. if (cnt2 > maxChars)
  261. cnt2 = maxChars;
  262. // Do multiple passes over source, comparing each pass.
  263. // The first pass that's not equal wins.
  264. int result = 0;
  265. while (result == 0 && (cnt1 || cnt2))
  266. {
  267. TempUniBuf buf1;
  268. TempUniBuf buf2;
  269. const UniChar* src1;
  270. const UniChar* src2;
  271. std::size_t passCnt1;
  272. std::size_t passCnt2;
  273. if (UNICODE_SIZE_MISMATCH)
  274. {
  275. passCnt1 = std::min(cnt1, kTempUniBufCount);
  276. passCnt2 = std::min(cnt2, kTempUniBufCount);
  277. src1 = CopyXMLChsToUniChars(comp1 + srcOffset, buf1, passCnt1, kTempUniBufCount);
  278. src2 = CopyXMLChsToUniChars(comp2 + srcOffset, buf2, passCnt2, kTempUniBufCount);
  279. }
  280. else
  281. {
  282. passCnt1 = cnt1;
  283. passCnt2 = cnt2;
  284. src1 = reinterpret_cast<const UniChar*>(comp1);
  285. src2 = reinterpret_cast<const UniChar*>(comp2);
  286. }
  287. // Do the actual compare for this pass
  288. Boolean equivalent = false;
  289. SInt32 order = 0;
  290. OSStatus status = UCCompareTextDefault(
  291. collateOptions,
  292. src1,
  293. passCnt1,
  294. src2,
  295. passCnt2,
  296. &equivalent,
  297. &order
  298. );
  299. result = ((status != noErr) || equivalent) ? 0 : order;
  300. srcOffset += kTempUniBufCount;
  301. cnt1 -= passCnt1;
  302. cnt2 -= passCnt2;
  303. }
  304. return result;
  305. }
  306. #if defined(XML_METROWERKS)
  307. else
  308. {
  309. unsigned int  n = 0;
  310. const XMLCh* cptr1 = comp1;
  311. const XMLCh* cptr2 = comp2;
  312. while ( (*cptr1 != 0) && (*cptr2 != 0) && (n < maxChars) )
  313. {
  314. std::wint_t wch1 = std::towupper(*cptr1);
  315. std::wint_t wch2 = std::towupper(*cptr2);
  316. if (wch1 != wch2)
  317. break;
  318. cptr1++;
  319. cptr2++;
  320. n++;
  321. }
  322. return (int)(std::towupper(*cptr1) - std::towupper(*cptr2));
  323. }
  324. #else
  325. else
  326. {
  327. // For some reason there is no platform utils available
  328. // where we expect it. Bail.
  329. XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  330. return 0;
  331. }
  332. #endif
  333. }
  334. const XMLCh* MacOSUnicodeConverter::getId() const
  335. {
  336.     return gMyServiceId;
  337. }
  338. bool MacOSUnicodeConverter::isSpace(const XMLCh toCheck) const
  339. {
  340. #if TARGET_API_MAC_CARBON
  341.    // Return true if the specified character is in the set.
  342.    CFCharacterSetRef wsSet = CFCharacterSetGetPredefined(kCFCharacterSetWhitespaceAndNewline);
  343.    return CFCharacterSetIsCharacterMember(wsSet, toCheck);
  344. #elif defined(XML_METROWERKS) || (__GNUC__ >= 3 && _GLIBCPP_USE_WCHAR_T)
  345. // Use this if there's a reasonable c library available.
  346. // ProjectBuilder currently has no support for iswspace ;(
  347.     return (std::iswspace(toCheck) != 0);
  348. #endif
  349. }
  350. XMLLCPTranscoder* MacOSUnicodeConverter::makeNewLCPTranscoder()
  351. {
  352. XMLLCPTranscoder* result = NULL;
  353. OSStatus status = noErr;
  354. TextToUnicodeInfo textToUnicodeInfo = NULL;
  355. UnicodeToTextInfo unicodeToTextInfo = NULL;
  356. // Get TextEncoding for current Mac System Script
  357. TextEncoding systemTextEncoding;
  358. status = UpgradeScriptInfoToTextEncoding(
  359. smSystemScript, kTextLanguageDontCare, kTextRegionDontCare,
  360. NULL, &systemTextEncoding);
  361. // Try to create a Unicode converter from the system encoding to Unicode
  362. if (status == noErr)
  363. status = CreateTextToUnicodeInfoByEncoding(
  364. systemTextEncoding,
  365. &textToUnicodeInfo);
  366. // Try to create a Unicode converter from Unicode to the system encoding
  367. if (status == noErr)
  368. status = CreateUnicodeToTextInfoByEncoding(
  369. systemTextEncoding,
  370. &unicodeToTextInfo);
  371. // Clean up on error, else create our transcoder
  372. if (status != noErr)
  373. {
  374. if (textToUnicodeInfo != NULL)
  375. DisposeTextToUnicodeInfo(&textToUnicodeInfo);
  376. if (unicodeToTextInfo != NULL)
  377. DisposeUnicodeToTextInfo(&unicodeToTextInfo);
  378. }
  379. else
  380. result = new MacOSLCPTranscoder(textToUnicodeInfo, unicodeToTextInfo);
  381.     return result;
  382. }
  383. bool MacOSUnicodeConverter::supportsSrcOfs() const
  384. {
  385. // For now, we don't support source offsets
  386.     return false;
  387. }
  388. void MacOSUnicodeConverter::upperCase(XMLCh* const toUpperCase) const
  389. {
  390. #if TARGET_API_MAC_CARBON
  391.    // If we're targeting carbon, use the CFString conversion to uppercase
  392.    int len = XMLString::stringLen(toUpperCase);
  393.    CFMutableStringRef cfString = CFStringCreateMutableWithExternalCharactersNoCopy(
  394.         kCFAllocatorDefault,
  395.         (UniChar*)toUpperCase,
  396.         len, // length
  397.         len, // capacity
  398.         kCFAllocatorNull);
  399.    CFStringUppercase(cfString, NULL);
  400.    CFRelease(cfString);
  401. #elif defined(XML_METROWERKS) || (__GNUC__ >= 3 && _GLIBCPP_USE_WCHAR_T)
  402. // Use this if there's a reasonable c library available.
  403. // Metrowerks does this reasonably
  404. wchar_t c;
  405. for (XMLCh* p = (XMLCh*)toUpperCase; ((c = *p) != 0); )
  406. *p++ = std::towupper(c);
  407. #else
  408. #error Sorry, no support for upperCase
  409. #endif
  410. }
  411. void MacOSUnicodeConverter::lowerCase(XMLCh* const toLowerCase) const
  412. {
  413. #if TARGET_API_MAC_CARBON
  414.    // If we're targeting carbon, use the CFString conversion to uppercase
  415.    int len = XMLString::stringLen(toLowerCase);
  416.    CFMutableStringRef cfString = CFStringCreateMutableWithExternalCharactersNoCopy(
  417.         kCFAllocatorDefault,
  418.         (UniChar*)toLowerCase,
  419.         len, // length
  420.         len, // capacity
  421.         kCFAllocatorNull);
  422.    CFStringLowercase(cfString, NULL);
  423.    CFRelease(cfString);
  424. #elif defined(XML_METROWERKS) || (__GNUC__ >= 3 && _GLIBCPP_USE_WCHAR_T)
  425. // Use this if there's a reasonable c library available.
  426. // Metrowerks does this reasonably
  427. wchar_t c;
  428. for (XMLCh* p = (XMLCh*)toLowerCase; ((c = *p) != 0); )
  429. *p++ = std::towlower(c);
  430. #else
  431. #error Sorry, no support for lowerCase
  432. #endif
  433. }
  434. void
  435. MacOSUnicodeConverter::ConvertWideToNarrow(const XMLCh* wide, char* narrow, std::size_t maxChars)
  436. {
  437. while (maxChars-- > 0)
  438. if ((*narrow++ = *wide++) == 0)
  439. break;
  440. }
  441. // ---------------------------------------------------------------------------
  442. //  MacOSTransService: The protected virtual transcoding service API
  443. // ---------------------------------------------------------------------------
  444. XMLTranscoder*
  445. MacOSUnicodeConverter::makeNewXMLTranscoder(const   XMLCh* const encodingName
  446.                                         ,       XMLTransService::Codes& resValue
  447.                                         , const unsigned int blockSize
  448.                                         ,       MemoryManager* const    manager)
  449. {
  450. XMLTranscoder* result = NULL;
  451. resValue = XMLTransService::Ok;
  452. TextToUnicodeInfo textToUnicodeInfo = NULL;
  453. UnicodeToTextInfo unicodeToTextInfo = NULL;
  454. // Map the encoding to a Mac OS Encoding value
  455. TextEncoding textEncoding;
  456. Str255 pasEncodingName;
  457. char cEncodingName[256];
  458. // ゥ