MacOSUnicodeConverter.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:37k
源码类别:

xml/soap/webservice

开发平台:

C/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.10 2001/10/19 20:03:47 jberry Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <util/Transcoders/MacOSUnicodeConverter/MacOSUnicodeConverter.hpp>
  63. #include <util/XMLUniDefs.hpp>
  64. #include <util/XMLUni.hpp>
  65. #include <util/XMLString.hpp>
  66. #include <util/TranscodingException.hpp>
  67. #include <util/PlatformUtils.hpp>
  68. #include <util/Janitor.hpp>
  69. #include <util/Platforms/MacOS/MacOSPlatformUtils.hpp>
  70. #if defined(XML_METROWERKS)
  71. // Only used under metrowerks.
  72. // In MacOS X Public Beta, the system wchar.h header is missing, which causes this to fail.
  73. #include <cwctype>
  74. #endif
  75. #include <algorithm>
  76. #include <cstddef>
  77. #include <cstring>
  78. #if defined(XML_MACOSX)
  79.     // Framework includes from ProjectBuilder
  80.     #include <CoreServices/CoreServices.h>
  81. #else
  82.     // Classic includes otherwise
  83.     #include <MacErrors.h>
  84.     #include <Script.h>
  85.     #include <TextUtils.h>
  86.     #include <TextEncodingConverter.h>
  87.     #include <TextCommon.h>
  88.     #include <CodeFragments.h>
  89.     #include <UnicodeConverter.h>
  90.     #include <UnicodeUtilities.h>
  91. #endif
  92. // ---------------------------------------------------------------------------
  93. // Typedefs
  94. // ---------------------------------------------------------------------------
  95. // TempUniBuf is used for cases where we need a temporary conversion due to
  96. // a mismatch between UniChar (the 16-bit type that the Unicode converter uses)
  97. // and wchar_t (the type the compiler uses to represent a Unicode character).
  98. // In the case of Metrowerks, these are the same size. For ProjectBuilder, they
  99. // used to differ, but they are now the same since XMLCh is now always fixed
  100. // as a 16 bit character, rather than floating with wchar_t as it used to.
  101. // *** Most uses of this buffer should be removed from this code in time! ***
  102. // TempUniBuf is also used for a few cases where we want to discard the
  103. // output from the unicode converter.
  104. const std::size_t kTempUniBufCount = 256;
  105. typedef UniChar TempUniBuf[kTempUniBufCount];
  106. // ---------------------------------------------------------------------------
  107. //  Local, const data
  108. // ---------------------------------------------------------------------------
  109. static const XMLCh gMyServiceId[] =
  110. {
  111.     chLatin_M, chLatin_a, chLatin_c, chLatin_O, chLatin_S, chNull
  112. };
  113. // Detect a mismatch in unicode character size.
  114. const bool kUniSizeMismatch = sizeof(XMLCh) != sizeof(UniChar);
  115. // ---------------------------------------------------------------------------
  116. //  MacOSUnicodeConverter: Constructors and Destructor
  117. // ---------------------------------------------------------------------------
  118. MacOSUnicodeConverter::MacOSUnicodeConverter()
  119. {
  120. // Test for presense of unicode collation functions
  121. mHasUnicodeCollation = (UCCompareTextDefault != (void*)kUnresolvedCFragSymbolAddress);
  122. }
  123. MacOSUnicodeConverter::~MacOSUnicodeConverter()
  124. {
  125. }
  126. // ---------------------------------------------------------------------------
  127. //  MacOSUnicodeConverter: The virtual transcoding service API
  128. // ---------------------------------------------------------------------------
  129. int MacOSUnicodeConverter::compareIString(  const XMLCh* const    comp1
  130.                                           , const XMLCh* const    comp2)
  131. {
  132. // If unicode collation routines are available, use them.
  133. // This should be the case on Mac OS 8.6 and later,
  134. // with Carbon 1.0.2 or later, and under Mac OS X.
  135. //
  136. // Otherwise, but only for Metrowerks, since only Metrowerks
  137. // has a c library with a valid set of wchar routines,
  138. // fall back to the standard library.
  139. if (mHasUnicodeCollation)
  140. {
  141. // Use the Unicode Utilities to do the compare
  142. // This has gotten more painful with the need to allow
  143. // conversion between different sizes of XMLCh and UniChar.
  144. // We allocate a static buffer and do multiple passes
  145. // to allow for the case where the strings being compared
  146. // are larger than the static buffer.
  147. UCCollateOptions collateOptions = 
  148. kUCCollateComposeInsensitiveMask
  149. | kUCCollateWidthInsensitiveMask
  150. | kUCCollateCaseInsensitiveMask
  151. | kUCCollatePunctuationSignificantMask
  152. ;
  153. std::size_t srcOffset = 0;
  154. std::size_t cnt1 = XMLString::stringLen(comp1);
  155. std::size_t cnt2 = XMLString::stringLen(comp2);
  156. // Do multiple passes over source, comparing each pass.
  157. // The first pass that's not equal wins.
  158. int result = 0;
  159. while (result == 0 && (cnt1 || cnt2))
  160. {
  161. TempUniBuf buf1;
  162. TempUniBuf buf2;
  163. const UniChar* src1;
  164. const UniChar* src2;
  165. std::size_t passCnt1;
  166. std::size_t passCnt2;
  167. if (kUniSizeMismatch)
  168. {
  169. passCnt1 = std::min(cnt1, kTempUniBufCount);
  170. passCnt2 = std::min(cnt2, kTempUniBufCount);
  171. src1 = CopyXMLChsToUniChars(comp1 + srcOffset, buf1, passCnt1, kTempUniBufCount);
  172. src2 = CopyXMLChsToUniChars(comp2 + srcOffset, buf2, passCnt2, kTempUniBufCount);
  173. }
  174. else
  175. {
  176. passCnt1 = cnt1;
  177. passCnt2 = cnt2;
  178. src1 = reinterpret_cast<const UniChar*>(comp1);
  179. src2 = reinterpret_cast<const UniChar*>(comp2);
  180. }
  181. // Do the actual compare for this pass
  182. Boolean equivalent = false;
  183. SInt32 order = 0;
  184. OSStatus status = UCCompareTextDefault(
  185. collateOptions,
  186. src1,
  187. passCnt1,
  188. src2,
  189. passCnt2,
  190. &equivalent,
  191. &order
  192. );
  193. result = ((status != noErr) || equivalent) ? 0 : order;
  194. srcOffset += kTempUniBufCount;
  195. cnt1 -= passCnt1;
  196. cnt2 -= passCnt2;
  197. }
  198. return result;
  199. }
  200. #if defined(XML_METROWERKS)
  201. else
  202. {
  203. const XMLCh* cptr1 = comp1;
  204. const XMLCh* cptr2 = comp2;
  205. while ( (*cptr1 != 0) && (*cptr2 != 0) )
  206. {
  207. std::wint_t wch1 = std::towupper(*cptr1);
  208. std::wint_t wch2 = std::towupper(*cptr2);
  209. if (wch1 != wch2)
  210. break;
  211. cptr1++;
  212. cptr2++;
  213. }
  214. return (int) (std::towupper(*cptr1) - std::towupper(*cptr2));
  215. }
  216. #else
  217. else
  218. {
  219. // For some reason there is no platform utils available
  220. // where we expect it. Bail.
  221. XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService);
  222. return 0;
  223. }
  224. #endif
  225. }
  226. int MacOSUnicodeConverter::compareNIString( const   XMLCh* const    comp1
  227.                                         , const XMLCh* const    comp2
  228.                                         , const unsigned int    maxChars)
  229. {
  230. // If unicode collation routines are available, use them.
  231. // This should be the case on Mac OS 8.6 and later,
  232. // with Carbon 1.0.2 or later, and under Mac OS X.
  233. //
  234. // Otherwise, but only for Metrowerks, since only Metrowerks
  235. // has a c library with a valid set of wchar routines,
  236. // fall back to the standard library.
  237. if (mHasUnicodeCollation)
  238. {
  239. // Use the Unicode Utilities to do the compare
  240. // This has gotten more painful with the need to allow
  241. // conversion between different sizes of XMLCh and UniChar.
  242. // We allocate a static buffer and do multiple passes
  243. // to allow for the case where the strings being compared
  244. // are larger than the static buffer.
  245. UCCollateOptions collateOptions = 
  246. kUCCollateComposeInsensitiveMask
  247. | kUCCollateWidthInsensitiveMask
  248. | kUCCollateCaseInsensitiveMask
  249. | kUCCollatePunctuationSignificantMask
  250. ;
  251. std::size_t srcOffset = 0;
  252. std::size_t cnt1 = XMLString::stringLen(comp1);
  253. std::size_t cnt2 = XMLString::stringLen(comp2);
  254. // Restrict view of source characters to first {maxChars}
  255. if (cnt1 > maxChars)
  256. cnt1 = maxChars;
  257. if (cnt2 > maxChars)
  258. cnt2 = maxChars;
  259. // Do multiple passes over source, comparing each pass.
  260. // The first pass that's not equal wins.
  261. int result = 0;
  262. while (result == 0 && (cnt1 || cnt2))
  263. {
  264. TempUniBuf buf1;
  265. TempUniBuf buf2;
  266. const UniChar* src1;
  267. const UniChar* src2;
  268. std::size_t passCnt1;
  269. std::size_t passCnt2;
  270. if (kUniSizeMismatch)
  271. {
  272. passCnt1 = std::min(cnt1, kTempUniBufCount);
  273. passCnt2 = std::min(cnt2, kTempUniBufCount);
  274. src1 = CopyXMLChsToUniChars(comp1 + srcOffset, buf1, passCnt1, kTempUniBufCount);
  275. src2 = CopyXMLChsToUniChars(comp2 + srcOffset, buf2, passCnt2, kTempUniBufCount);
  276. }
  277. else
  278. {
  279. passCnt1 = cnt1;
  280. passCnt2 = cnt2;
  281. src1 = reinterpret_cast<const UniChar*>(comp1);
  282. src2 = reinterpret_cast<const UniChar*>(comp2);
  283. }
  284. // Do the actual compare for this pass
  285. Boolean equivalent = false;
  286. SInt32 order = 0;
  287. OSStatus status = UCCompareTextDefault(
  288. collateOptions,
  289. src1,
  290. passCnt1,
  291. src2,
  292. passCnt2,
  293. &equivalent,
  294. &order
  295. );
  296. result = ((status != noErr) || equivalent) ? 0 : order;
  297. srcOffset += kTempUniBufCount;
  298. cnt1 -= passCnt1;
  299. cnt2 -= passCnt2;
  300. }
  301. return result;
  302. }
  303. #if defined(XML_METROWERKS)
  304. else
  305. {
  306. unsigned int  n = 0;
  307. const XMLCh* cptr1 = comp1;
  308. const XMLCh* cptr2 = comp2;
  309. while ( (*cptr1 != 0) && (*cptr2 != 0) && (n < maxChars) )
  310. {
  311. std::wint_t wch1 = std::towupper(*cptr1);
  312. std::wint_t wch2 = std::towupper(*cptr2);
  313. if (wch1 != wch2)
  314. break;
  315. cptr1++;
  316. cptr2++;
  317. n++;
  318. }
  319. return (int)(std::towupper(*cptr1) - std::towupper(*cptr2));
  320. }
  321. #else
  322. else
  323. {
  324. // For some reason there is no platform utils available
  325. // where we expect it. Bail.
  326. XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService);
  327. return 0;
  328. }
  329. #endif
  330. }
  331. const XMLCh* MacOSUnicodeConverter::getId() const
  332. {
  333.     return gMyServiceId;
  334. }
  335. bool MacOSUnicodeConverter::isSpace(const XMLCh toCheck) const
  336. {
  337. #if defined(XML_METROWERKS)
  338. // Use this if there's a reasonable c library available.
  339. // ProjectBuilder currently has no support for iswspace ;(
  340.     return (std::iswspace(toCheck) != 0);
  341. #elif defined(XML_MACOSX) || true
  342. // This looks fairly good, assuming we're on an ascii compiler.
  343. // We'll use this under ProjectBuilder for now.
  344. return (toCheck == L' ');
  345. #elif 0
  346. // This is okay but probably kind of slow for what we need
  347.     UCCharPropertyValue propValue = 0;
  348.     
  349.     OSStatus status = UCGetCharProperty(
  350.                             reinterpret_cast<const UniChar*>(&toCheck),
  351.                             1, // size of toCheck in UniChars, right? Not bytes???
  352.                             kUCCharPropTypeGenlCategory,
  353.                             &propValue);
  354.     return (status == noErr) && (propValue == kUCGenlCatSeparatorSpace);
  355. #endif
  356. }
  357. XMLLCPTranscoder* MacOSUnicodeConverter::makeNewLCPTranscoder()
  358. {
  359. XMLLCPTranscoder* result = NULL;
  360. OSStatus status = noErr;
  361. TextToUnicodeInfo textToUnicodeInfo = NULL;
  362. UnicodeToTextInfo unicodeToTextInfo = NULL;
  363. // Get TextEncoding for current Mac System Script
  364. TextEncoding systemTextEncoding;
  365. status = UpgradeScriptInfoToTextEncoding(
  366. smSystemScript, kTextLanguageDontCare, kTextRegionDontCare,
  367. NULL, &systemTextEncoding);
  368. // Try to create a Unicode converter from the system encoding to Unicode
  369. if (status == noErr)
  370. status = CreateTextToUnicodeInfoByEncoding(
  371. systemTextEncoding,
  372. &textToUnicodeInfo);
  373. // Try to create a Unicode converter from Unicode to the system encoding
  374. if (status == noErr)
  375. status = CreateUnicodeToTextInfoByEncoding(
  376. systemTextEncoding,
  377. &unicodeToTextInfo);
  378. // Clean up on error, else create our transcoder
  379. if (status != noErr)
  380. {
  381. if (textToUnicodeInfo != NULL)
  382. DisposeTextToUnicodeInfo(&textToUnicodeInfo);
  383. if (unicodeToTextInfo != NULL)
  384. DisposeUnicodeToTextInfo(&unicodeToTextInfo);
  385. }
  386. else
  387. result = new MacOSLCPTranscoder(textToUnicodeInfo, unicodeToTextInfo);
  388.     return result;
  389. }
  390. bool MacOSUnicodeConverter::supportsSrcOfs() const
  391. {
  392. // For now, we don't support source offsets
  393.     return false;
  394. }
  395. void MacOSUnicodeConverter::upperCase(XMLCh* const toUpperCase) const
  396. {
  397. // ゥ