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

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 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.  * $Log: CygwinTransService.cpp,v $
  58.  * Revision 1.8  2003/05/17 16:32:17  knoaman
  59.  * Memory manager implementation : transcoder update.
  60.  *
  61.  * Revision 1.7  2003/05/16 14:04:46  neilg
  62.  * fix compilation error
  63.  *
  64.  * Revision 1.6  2003/05/16 06:01:57  knoaman
  65.  * Partial implementation of the configurable memory manager.
  66.  *
  67.  * Revision 1.5  2003/05/15 18:47:02  knoaman
  68.  * Partial implementation of the configurable memory manager.
  69.  *
  70.  * Revision 1.4  2003/03/09 17:02:20  peiyongz
  71.  * PanicHandler
  72.  *
  73.  * Revision 1.3  2003/03/07 18:15:57  tng
  74.  * Return a reference instead of void for operator=
  75.  *
  76.  * Revision 1.2  2002/11/04 15:14:32  tng
  77.  * C++ Namespace Support.
  78.  *
  79.  * Revision 1.1  2002/08/19 18:35:56  tng
  80.  * [Bug 6467] Installing Xerces C++ on cygwin environment.
  81.  *
  82.  */
  83. // ---------------------------------------------------------------------------
  84. //  Includes
  85. // ---------------------------------------------------------------------------
  86. #include <xercesc/util/PlatformUtils.hpp>
  87. #include <xercesc/util/TranscodingException.hpp>
  88. #include <xercesc/util/XMLException.hpp>
  89. #include <xercesc/util/XMLString.hpp>
  90. #include <xercesc/util/XMLUniDefs.hpp>
  91. #include <xercesc/util/XMLUni.hpp>
  92. #include <xercesc/util/RefHashTableOf.hpp>
  93. #include "CygwinTransService.hpp"
  94. #include <windows.h>
  95. #include <stdlib.h>
  96. XERCES_CPP_NAMESPACE_BEGIN
  97. // ---------------------------------------------------------------------------
  98. //  Local, const data
  99. // ---------------------------------------------------------------------------
  100. static const XMLCh gMyServiceId[] =
  101. {
  102.     chLatin_C, chLatin_y, chLatin_g, chLatin_w, chLatin_i, chLatin_n, chNull
  103. };
  104. // Cygwin doesn't support iswspace(), so this table is used by
  105. // CygwinTransService::isSpace() based on a union of Unicode
  106. // Table 6-1 and the ANSI definition of whitespace, arranged
  107. // in order of likely occurrence.
  108. static const XMLCh gWhitespace[] =
  109. {
  110.     0x0020,
  111.     0x00a0,
  112.     0x0009,
  113.     0x000a,
  114.     0x000d,
  115.     0x000b,
  116.     0x000c,
  117.     0x3000,
  118.     0x2000,
  119.     0x2001,
  120.     0x2002,
  121.     0x2003,
  122.     0x2004,
  123.     0x2005,
  124.     0x2006,
  125.     0x2007,
  126.     0x2008,
  127.     0x2009,
  128.     0x200a,
  129.     0x200b,
  130.     0x202f
  131. };
  132. // Used by the kernel32 function LCMapStringW to uppercasify strings
  133. // appropriate to this locale.  Cygwin doesn't support _wcsupr().
  134. static const LCID gLocaleId =
  135. #if defined(CYGWINTRANSCODER_DEFAULT_LOCALE)
  136.     MAKELCID( MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), SORT_DEFAULT);
  137. #else    // CYGWINTRANSCODER_DYNAMIC_LOCALE
  138.     GetThreadLocale();
  139. #endif
  140. // ---------------------------------------------------------------------------
  141. //  This is the simple CPMapEntry class. It just contains an encoding name
  142. //  and a code page for that encoding.
  143. // ---------------------------------------------------------------------------
  144. class CPMapEntry : public XMemory
  145. {
  146. public :
  147.     // -----------------------------------------------------------------------
  148.     //  Constructors and Destructor
  149.     // -----------------------------------------------------------------------
  150.     CPMapEntry
  151.     (
  152.         const   XMLCh* const    encodingName
  153.         , const unsigned int    cpId
  154.         , const unsigned int    ieId
  155.     );
  156.     CPMapEntry
  157.     (
  158.         const   char* const     encodingName
  159.         , const unsigned int    cpId
  160.         , const unsigned int    ieId
  161.     );
  162.     ~CPMapEntry();
  163.     // -----------------------------------------------------------------------
  164.     //  Getter methods
  165.     // -----------------------------------------------------------------------
  166.     const XMLCh* getEncodingName() const;
  167.     const XMLCh* getKey() const;
  168.     unsigned int getWinCP() const;
  169.     unsigned int getIEEncoding() const;
  170. private :
  171.     // -----------------------------------------------------------------------
  172.     //  Unimplemented constructors and operators
  173.     // -----------------------------------------------------------------------
  174.     CPMapEntry();
  175.     CPMapEntry(const CPMapEntry&);
  176.     CPMapEntry& operator=(const CPMapEntry&);
  177.     // -----------------------------------------------------------------------
  178.     //  Private data members
  179.     //
  180.     //  fEncodingName
  181.     //      This is the encoding name for the code page that this instance
  182.     //      represents.
  183.     //
  184.     //  fCPId
  185.     //      This is the Windows specific code page for the encoding that this
  186.     //      instance represents.
  187.     //
  188.     //  fIEId
  189.     //      This is the IE encoding id. Its not used at this time, but we
  190.     //      go ahead and get it and store it just in case for later.
  191.     // -----------------------------------------------------------------------
  192.     XMLCh*          fEncodingName;
  193.     unsigned int    fCPId;
  194.     unsigned int    fIEId;
  195. };
  196. // ---------------------------------------------------------------------------
  197. //  CPMapEntry: Constructors and Destructor
  198. // ---------------------------------------------------------------------------
  199. CPMapEntry::CPMapEntry( const   char* const     encodingName
  200.                         , const unsigned int    cpId
  201.                         , const unsigned int    ieId) :
  202.     fEncodingName(0)
  203.     , fCPId(cpId)
  204.     , fIEId(ieId)
  205. {
  206.     // Transcode the name to Unicode and store that copy
  207.     const unsigned int srcLen = strlen(encodingName);
  208.     const unsigned int targetLen = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, encodingName, srcLen, NULL, 0);
  209.     fEncodingName = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate
  210.     (
  211.         (targetLen + 1) * sizeof(XMLCh)
  212.     );//new XMLCh[targetLen + 1];
  213.     ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, encodingName, srcLen, (LPWSTR)fEncodingName, targetLen);
  214.     fEncodingName[targetLen] = 0;
  215.     //
  216.     //  Upper case it because we are using a hash table and need to be
  217.     //  sure that we find all case combinations.
  218.     //
  219.     ::LCMapStringW( gLocaleId, LCMAP_UPPERCASE, (LPCWSTR)fEncodingName, targetLen, (LPWSTR)fEncodingName, targetLen);
  220. }
  221. CPMapEntry::CPMapEntry( const   XMLCh* const    encodingName
  222.                         , const unsigned int    cpId
  223.                         , const unsigned int    ieId) :
  224.     fEncodingName(0)
  225.     , fCPId(cpId)
  226.     , fIEId(ieId)
  227. {
  228. fEncodingName = XMLString::replicate(encodingName, XMLPlatformUtils::fgMemoryManager);
  229.     //
  230.     //  Upper case it because we are using a hash table and need to be
  231.     //  sure that we find all case combinations.
  232.     //
  233.     unsigned int itsLen = XMLString::stringLen( fEncodingName);
  234.     ::LCMapStringW( gLocaleId, LCMAP_UPPERCASE, (LPCWSTR)fEncodingName, itsLen, (LPWSTR)fEncodingName, itsLen);
  235. }
  236. CPMapEntry::~CPMapEntry()
  237. {
  238.     XMLPlatformUtils::fgMemoryManager->deallocate(fEncodingName);//delete [] fEncodingName;
  239. }
  240. // ---------------------------------------------------------------------------
  241. //  CPMapEntry: Getter methods
  242. // ---------------------------------------------------------------------------
  243. const XMLCh* CPMapEntry::getEncodingName() const
  244. {
  245.     return fEncodingName;
  246. }
  247. unsigned int CPMapEntry::getWinCP() const
  248. {
  249.     return fCPId;
  250. }
  251. unsigned int CPMapEntry::getIEEncoding() const
  252. {
  253.     return fIEId;
  254. }
  255. //---------------------------------------------------------------------------
  256. //
  257. //  class CygwinTransService Implementation ...
  258. //
  259. //---------------------------------------------------------------------------
  260. // ---------------------------------------------------------------------------
  261. //  CygwinTransService: Constructors and Destructor
  262. // ---------------------------------------------------------------------------
  263. CygwinTransService::CygwinTransService()
  264. {
  265.     fCPMap = new RefHashTableOf<CPMapEntry>(109);
  266.     //
  267.     //  Open up the registry key that contains the info we want. Note that,
  268.     //  if this key does not exist, then we just return. It will just mean
  269.     //  that we don't have any support except for intrinsic encodings supported
  270.     //  by the parser itself (and the LCP support of course.
  271.     //
  272.     HKEY charsetKey;
  273.     if (::RegOpenKeyExA
  274.     (
  275.         HKEY_CLASSES_ROOT
  276.         , "MIME\Database\Charset"
  277.         , 0
  278.         , KEY_READ
  279.         , &charsetKey))
  280.     {
  281.         return;
  282.     }
  283.     //
  284.     //  Read in the registry keys that hold the code page ids. Skip for now
  285.     //  those entries which indicate that they are aliases for some other
  286.     //  encodings. We'll come back and do a second round for those and look
  287.     //  up the original name and get the code page id.
  288.     //
  289.     //  Note that we have to use A versions here so that this will run on
  290.     //  98, and transcode the strings to Unicode.
  291.     //
  292.     const unsigned int nameBufSz = 1024;
  293.     char nameBuf[nameBufSz + 1];
  294.     unsigned int subIndex = 0;
  295.     unsigned long theSize;
  296.     while (true)
  297.     {
  298.         // Get the name of the next key
  299.         theSize = nameBufSz;
  300.         if (::RegEnumKeyExA
  301.         (
  302.             charsetKey
  303.             , subIndex
  304.             , nameBuf
  305.             , &theSize
  306.             , 0, 0, 0, 0) == ERROR_NO_MORE_ITEMS)
  307.         {
  308.             break;
  309.         }
  310.         // Open this subkey
  311.         HKEY encodingKey;
  312.         if (::RegOpenKeyExA
  313.         (
  314.             charsetKey
  315.             , nameBuf
  316.             , 0
  317.             , KEY_READ
  318.             , &encodingKey))
  319.         {
  320.             XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  321.         }
  322.         //
  323.         //  Lts see if its an alias. If so, then ignore it in this first
  324.         //  loop. Else, we'll add a new entry for this one.
  325.         //
  326.         if (!isAlias(encodingKey))
  327.         {
  328.             //
  329.             //  Lets get the two values out of this key that we are
  330.             //  interested in. There should be a code page entry and an
  331.             //  IE entry.
  332.             //
  333.             unsigned long theType;
  334.             unsigned int CPId;
  335.             unsigned int IEId;
  336.             theSize = sizeof(unsigned int);
  337.             if (::RegQueryValueExA
  338.             (
  339.                 encodingKey
  340.                 , "Codepage"
  341.                 , 0
  342.                 , &theType
  343.                 , (unsigned char*)&CPId
  344.                 , &theSize) != ERROR_SUCCESS)
  345.             {
  346.                 XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  347.             }
  348.             //
  349.             //  If this is not a valid Id, and it might not be because its
  350.             //  not loaded on this system, then don't take it.
  351.             //
  352.             if (::IsValidCodePage(CPId))
  353.             {
  354.                 theSize = sizeof(unsigned int);
  355.                 if (::RegQueryValueExA
  356.                 (
  357.                     encodingKey
  358.                     , "InternetEncoding"
  359.                     , 0
  360.                     , &theType
  361.                     , (unsigned char*)&IEId
  362.                     , &theSize) != ERROR_SUCCESS)
  363.                 {
  364.                     XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  365.                 }
  366.                 CPMapEntry* newEntry = new CPMapEntry(nameBuf, CPId, IEId);
  367.                 fCPMap->put((void*)newEntry->getEncodingName(), newEntry);
  368.             }
  369.         }
  370.         // And now close the subkey handle and bump the subkey index
  371.         ::RegCloseKey(encodingKey);
  372.         subIndex++;
  373.     }
  374.     //
  375.     //  Now loop one more time and this time we do just the aliases. For
  376.     //  each one we find, we look up that name in the map we've already
  377.     //  built and add a new entry with this new name and the same id
  378.     //  values we stored for the original.
  379.     //
  380.     subIndex = 0;
  381.     char aliasBuf[nameBufSz + 1];
  382.     while (true)
  383.     {
  384.         // Get the name of the next key
  385.         theSize = nameBufSz;
  386.         if (::RegEnumKeyExA
  387.         (
  388.             charsetKey
  389.             , subIndex
  390.             , nameBuf
  391.             , &theSize
  392.             , 0, 0, 0, 0) == ERROR_NO_MORE_ITEMS)
  393.         {
  394.             break;
  395.         }
  396.         // Open this subkey
  397.         HKEY encodingKey;
  398.         if (::RegOpenKeyExA
  399.         (
  400.             charsetKey
  401.             , nameBuf
  402.             , 0
  403.             , KEY_READ
  404.             , &encodingKey))
  405.         {
  406.             XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  407.         }
  408.         //
  409.         //  If its an alias, look up the name in the map. If we find it,
  410.         //  then construct a new one with the new name and the aliased
  411.         //  ids.
  412.         //
  413.         if (isAlias(encodingKey, aliasBuf, nameBufSz))
  414.         {
  415.             const unsigned int srcLen = strlen(aliasBuf);
  416.             const unsigned int targetLen = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, aliasBuf, srcLen, NULL, 0);
  417.             XMLCh* uniAlias = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate
  418.             (
  419.                 (targetLen + 1) * sizeof(XMLCh)
  420.             );//new XMLCh[targetLen + 1];
  421.             ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, aliasBuf, srcLen, (LPWSTR)uniAlias, targetLen);
  422.             uniAlias[targetLen] = 0;
  423.             ::LCMapStringW( gLocaleId, LCMAP_UPPERCASE, (LPCWSTR)uniAlias, targetLen, (LPWSTR)uniAlias, targetLen);
  424.             // Look up the alias name
  425.             CPMapEntry* aliasedEntry = fCPMap->get(uniAlias);
  426.             if (aliasedEntry)
  427.             {
  428.                 //
  429.                 //  If the name is actually different, then take it.
  430.                 //  Otherwise, don't take it. They map aliases that are
  431.                 //  just different case.
  432.                 //
  433.                 if (auxCompareString(uniAlias, aliasedEntry->getEncodingName(), -1L, false))
  434.                 {
  435.                     CPMapEntry* newEntry = new CPMapEntry(uniAlias, aliasedEntry->getWinCP(), aliasedEntry->getIEEncoding());
  436.                     fCPMap->put((void*)newEntry->getEncodingName(), newEntry);
  437.                 }
  438.             }
  439.             XMLPlatformUtils::fgMemoryManager->deallocate(uniAlias);//delete [] uniAlias;
  440.         }
  441.         // And now close the subkey handle and bump the subkey index
  442.         ::RegCloseKey(encodingKey);
  443.         subIndex++;
  444.     }
  445.     // And close the main key handle
  446.     ::RegCloseKey(charsetKey);
  447. }
  448. CygwinTransService::~CygwinTransService()
  449. {
  450.     delete fCPMap;
  451. }
  452. // ---------------------------------------------------------------------------
  453. //  CygwinTransService: The virtual transcoding service API
  454. // ---------------------------------------------------------------------------
  455. int CygwinTransService::auxCompareString( const XMLCh* const comp1
  456.                                          , const XMLCh* const comp2
  457.                                          , signed long maxChars
  458.                                          , const bool ignoreCase)
  459. {
  460.     const XMLCh* args[2] = { comp1, comp2 };
  461.     XMLCh*       firstBuf = NULL;
  462.     XMLCh*       secondBuf;
  463.     unsigned int len = XMLString::stringLen( comp1);
  464.     unsigned int otherLen = XMLString::stringLen( comp2);
  465.     unsigned int countChar = 0;
  466.     int          theResult = 0;
  467.     // Determine at what string index the comparison stops.
  468.     if ( maxChars != -1L )
  469.     {
  470.         len = ( len > maxChars ) ? maxChars : len;
  471.         otherLen = ( otherLen > maxChars ) ? maxChars : otherLen;
  472.         maxChars = ( len > otherLen ) ? otherLen : len;
  473.     }
  474.     else
  475.     {
  476.         // When no Max given must compare terminating NUL to return
  477.         // difference if one string is shorter than the other.
  478.         maxChars = ( len > otherLen ) ? otherLen : len;
  479.         ++maxChars;
  480.     }
  481.     // Handle situation when one argument or the other is NULL
  482.     // by returning +/- string length of non-NULL argument (inferred
  483.     // from XMLString::CompareNString).
  484.     // Obs. Definition of stringLen(XMLCh*) implies NULL ptr and ptr
  485.     // to Empty String are equivalent.  It handles NULL args, BTW.
  486.     if ( !comp1 )
  487.     {
  488.         // Negative because null ptr (c1) less than string (c2).
  489.         return ( 0 - otherLen );
  490.     }
  491.     if ( !comp2 )
  492.     {
  493.         // Positive because string (c1) still greater than null ptr (c2).
  494.         return len;
  495.     }
  496.     // Handle case-insensitive comparison by removing case from string.
  497.     if ( ignoreCase )
  498.     {
  499.         // Copy const parameter strings (plus terminating nul) into locals.
  500.         firstBuf = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate
  501.         (
  502.             (++len) * sizeof(XMLCh)
  503.         );//new XMLCh[ ++len];
  504.         secondBuf = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate
  505.         (
  506.             (++otherLen) * sizeof(XMLCh)
  507.         );//new XMLCh[ ++otherLen];
  508.         memcpy( firstBuf, comp1, len * sizeof(XMLCh));
  509.         memcpy( secondBuf, comp2, otherLen * sizeof(XMLCh));
  510.         // Then uppercase both strings, losing their case info.
  511.         ::LCMapStringW( gLocaleId, LCMAP_UPPERCASE, (LPWSTR)firstBuf, len, (LPWSTR)firstBuf, len);
  512.         ::LCMapStringW( gLocaleId, LCMAP_UPPERCASE, (LPWSTR)secondBuf, otherLen, (LPWSTR)secondBuf, otherLen);
  513.         // Replace original params in args array with UC ones.
  514.         args[0] = (const XMLCh*)firstBuf;
  515.         args[1] = (const XMLCh*)secondBuf;
  516.         // Not necessary only because they're not used beyond this pt.
  517.         // --len;
  518.         // --otherLen;
  519.     }
  520.     // Strings are equal until proven otherwise.
  521.     while ( ( countChar < maxChars ) && ( !theResult ) )
  522.     {
  523.         theResult = (int)(args[1][countChar]) - (int)(args[0][countChar]);
  524.         ++countChar;
  525.     }
  526.     // Clean-up buffers, equivalent to if ( ignoreCase )
  527.     if ( firstBuf )
  528.     {
  529.         XMLPlatformUtils::fgMemoryManager->deallocate(firstBuf);//delete [] firstBuf;
  530.         XMLPlatformUtils::fgMemoryManager->deallocate(secondBuf);//delete [] secondBuf;
  531.     }
  532.     return theResult;
  533. }
  534. int CygwinTransService::compareIString(  const   XMLCh* const    comp1
  535.                                         , const XMLCh* const    comp2)
  536. {
  537.     return auxCompareString( comp1, comp2, -1L, true);
  538. }
  539. int CygwinTransService::compareNIString( const   XMLCh* const    comp1
  540.                                         , const XMLCh* const    comp2
  541.                                         , const unsigned int    maxChars)
  542. {
  543.     // Promote maxChars to signed long. Avoid any conceivable
  544.     // portability issue from a simple C cast with extension
  545.     // of sign bit when maxChars >= 2^16.  Making that param
  546.     // signed long was necessary for reusability/an out-of-band
  547.     // indicator in CygwinTransService::auxCompareString().
  548.     // Obs. When maxChars == 0, return 0 (strings equal).
  549.     return auxCompareString( comp1, comp2, (maxChars & 0x0000FFFFL), true);
  550. }
  551. const XMLCh* CygwinTransService::getId() const
  552. {
  553.     return gMyServiceId;
  554. }
  555. bool CygwinTransService::isSpace(const XMLCh toCheck) const
  556. {
  557.     int theCount = 0;
  558.     while ( theCount < (sizeof(gWhitespace) / sizeof(XMLCh)) )
  559.     {
  560.         if ( toCheck == gWhitespace[theCount] )
  561.             return true;
  562.         ++theCount;
  563.     }
  564.     return false;
  565. }
  566. XMLLCPTranscoder* CygwinTransService::makeNewLCPTranscoder()
  567. {
  568.     // Just allocate a new LCP transcoder of our type
  569.     return new CygwinLCPTranscoder;
  570. }
  571. bool CygwinTransService::supportsSrcOfs() const
  572. {
  573.     //
  574.     //  Since the only mechanism we have to translate XML text in this
  575.     //  transcoder basically require us to do work that allows us to support
  576.     //  source offsets, we might as well do it.
  577.     //
  578.     return true;
  579. }
  580. void CygwinTransService::upperCase(XMLCh* const toUpperCase) const
  581. {
  582.     unsigned int itsLen = XMLString::stringLen( toUpperCase);
  583.     ::LCMapStringW( gLocaleId, LCMAP_UPPERCASE, (LPWSTR)toUpperCase, itsLen, (LPWSTR)toUpperCase, itsLen);
  584. }
  585. void CygwinTransService::lowerCase(XMLCh* const toLowerCase) const
  586. {
  587.     unsigned int itsLen = XMLString::stringLen( toLowerCase);
  588.     ::LCMapStringW( gLocaleId, LCMAP_LOWERCASE, (LPWSTR)toLowerCase, itsLen, (LPWSTR)toLowerCase, itsLen);
  589. }
  590. bool CygwinTransService::isAlias(const   HKEY            encodingKey
  591.                     ,       char* const     aliasBuf
  592.                     , const unsigned int    nameBufSz )
  593. {
  594.     unsigned long theType;
  595.     unsigned long theSize = nameBufSz;
  596.     return (::RegQueryValueExA
  597.     (
  598.         encodingKey
  599.         , "AliasForCharset"
  600.         , 0
  601.         , &theType
  602.         , (unsigned char*)aliasBuf
  603.         , &theSize
  604.     ) == ERROR_SUCCESS);
  605. }
  606. XMLTranscoder*
  607. CygwinTransService::makeNewXMLTranscoder(const   XMLCh* const           encodingName
  608.                                         ,       XMLTransService::Codes& resValue
  609.                                         , const unsigned int            blockSize
  610.                                         ,       MemoryManager* const    manager)
  611. {
  612.     const unsigned int upLen = 1024;
  613.     XMLCh upEncoding[upLen + 1];
  614.     //
  615.     //  Get an upper cased copy of the encoding name, since we use a hash
  616.     //  table and we store them all in upper case.
  617.     //
  618.     int itsLen = XMLString::stringLen( encodingName) + 1;
  619.     memcpy(
  620.         upEncoding
  621.         , encodingName
  622.         , sizeof(XMLCh) * ( ( itsLen > upLen) ? upLen : itsLen)
  623.     );
  624.     upEncoding[upLen] = 0;  // necessary? terminating NUL should've copied.
  625.     upperCase(upEncoding);
  626.     // Now to try to find this guy in the CP map
  627.     CPMapEntry* theEntry = fCPMap->get(upEncoding);
  628.     // If not found, then return a null pointer
  629.     if (!theEntry)
  630.     {
  631.         resValue = XMLTransService::UnsupportedEncoding;
  632.         return 0;
  633.     }
  634.     // We found it, so return a Cygwin transcoder for this encoding
  635.     return new (manager) CygwinTranscoder
  636.     (
  637.         encodingName
  638.         , theEntry->getWinCP()
  639.         , theEntry->getIEEncoding()
  640.         , blockSize
  641.         , manager
  642.     );
  643. }
  644. //---------------------------------------------------------------------------
  645. //
  646. //  class CygwinTranscoder Implementation ...
  647. //
  648. //---------------------------------------------------------------------------
  649. // ---------------------------------------------------------------------------
  650. //  CygwinTranscoder: Constructors and Destructor
  651. // ---------------------------------------------------------------------------
  652. CygwinTranscoder::CygwinTranscoder(const  XMLCh* const    encodingName
  653.                                 , const unsigned int    winCP
  654.                                 , const unsigned int    ieCP
  655.                                 , const unsigned int    blockSize
  656.                                 , MemoryManager* const manager) :
  657.     XMLTranscoder(encodingName, blockSize, manager)
  658.     , fIECP(ieCP)
  659.     , fWinCP(winCP)
  660. {
  661. }
  662. CygwinTranscoder::~CygwinTranscoder()
  663. {
  664. }
  665. // ---------------------------------------------------------------------------
  666. //  CygwinTranscoder: The virtual transcoder API
  667. // ---------------------------------------------------------------------------
  668. unsigned int
  669. CygwinTranscoder::transcodeFrom(  const XMLByte* const      srcData
  670.                                 , const unsigned int        srcCount
  671.                                 ,       XMLCh* const        toFill
  672.                                 , const unsigned int        maxChars
  673.                                 ,       unsigned int&       bytesEaten
  674.                                 ,       unsigned char* const charSizes)
  675. {
  676.     // Get temp pointers to the in and out buffers, and the chars sizes one
  677.     XMLCh*          outPtr = toFill;
  678.     const XMLByte*  inPtr  = srcData;
  679.     unsigned char*  sizesPtr = charSizes;
  680.     // Calc end pointers for each of them
  681.     XMLCh*          outEnd = toFill + maxChars;
  682.     const XMLByte*  inEnd  = srcData + srcCount;
  683.     //
  684.     //  Now loop until we either get our max chars, or cannot get a whole
  685.     //  character from the input buffer.
  686.     //
  687.     bytesEaten = 0;
  688.     while ((outPtr < outEnd) && (inPtr < inEnd))
  689.     {
  690.         //
  691.         //  If we are looking at a leading byte of a multibyte sequence,
  692.         //  then we are going to eat 2 bytes, else 1.
  693.         //
  694.         const unsigned int toEat = ::IsDBCSLeadByteEx(fWinCP, *inPtr) ?
  695.                                     2 : 1;
  696.         // Make sure a whol char is in the source
  697.         if (inPtr + toEat > inEnd)
  698.             break;
  699.         // Try to translate this next char and check for an error
  700.         const unsigned int converted = ::MultiByteToWideChar
  701.         (
  702.             fWinCP
  703.             , MB_PRECOMPOSED | MB_ERR_INVALID_CHARS
  704.             , (const char*)inPtr
  705.             , toEat
  706.             , (LPWSTR)outPtr
  707.             , 1
  708.         );
  709.         if (converted != 1)
  710.         {
  711.             if (toEat == 1)
  712.             {
  713.                 XMLCh tmpBuf[16];
  714.                 XMLString::binToText((unsigned int)(*inPtr), tmpBuf, 16, 16);
  715.                 ThrowXML2
  716.                 (
  717.                     TranscodingException
  718.                     , XMLExcepts::Trans_BadSrcCP
  719.                     , tmpBuf
  720.                     , getEncodingName()
  721.                 );
  722.             }
  723.             else
  724.             {
  725.                 ThrowXML(TranscodingException, XMLExcepts::Trans_BadSrcSeq);
  726.             }
  727.         }
  728.         // Update the char sizes array for this round
  729.         *sizesPtr++ = toEat;
  730.         // And update the bytes eaten count
  731.         bytesEaten += toEat;
  732.         // And update our in/out ptrs
  733.         inPtr += toEat;
  734.         outPtr++;
  735.     }
  736.     // Return the chars we output
  737.     return (outPtr - toFill);
  738. }
  739. unsigned int
  740. CygwinTranscoder::transcodeTo(const  XMLCh* const   srcData
  741.                             , const unsigned int    srcCount
  742.                             ,       XMLByte* const  toFill
  743.                             , const unsigned int    maxBytes
  744.                             ,       unsigned int&   charsEaten
  745.                             , const UnRepOpts       options)
  746. {
  747.     // Get pointers to the start and end of each buffer
  748.     const XMLCh*    srcPtr = srcData;
  749.     const XMLCh*    srcEnd = srcData + srcCount;
  750.     XMLByte*        outPtr = toFill;
  751.     XMLByte*        outEnd = toFill + maxBytes;
  752.     //
  753.     //  Now loop until we either get our max chars, or cannot get a whole
  754.     //  character from the input buffer.
  755.     //
  756.     //  NOTE: We have to use a loop for this unfortunately because the
  757.     //  conversion API is too dumb to tell us how many chars it converted if
  758.     //  it couldn't do the whole source.
  759.     //
  760.     BOOL usedDef;
  761.     while ((outPtr < outEnd) && (srcPtr < srcEnd))
  762.     {
  763.         //
  764.         //  Do one char and see if it made it.
  765.         const unsigned int bytesStored = ::WideCharToMultiByte
  766.         (
  767.             fWinCP
  768.             , WC_COMPOSITECHECK | WC_SEPCHARS
  769.             , (LPCWSTR)srcPtr
  770.             , 1
  771.             , (char*)outPtr
  772.             , outEnd - outPtr
  773.             , 0
  774.             , &usedDef
  775.         );
  776.         // If we didn't transcode anything, then we are done
  777.         if (!bytesStored)
  778.             break;
  779.         //
  780.         //  If the defaault char was used and the options indicate that
  781.         //  this isn't allowed, then throw.
  782.         //
  783.         if (usedDef && (options == UnRep_Throw))
  784.         {
  785.             XMLCh tmpBuf[16];
  786.             XMLString::binToText((unsigned int)*srcPtr, tmpBuf, 16, 16);
  787.             ThrowXML2
  788.             (
  789.                 TranscodingException
  790.                 , XMLExcepts::Trans_Unrepresentable
  791.                 , tmpBuf
  792.                 , getEncodingName()
  793.             );
  794.         }
  795.         // Update our pointers
  796.         outPtr += bytesStored;
  797.         srcPtr++;
  798.     }
  799.     // Update the chars eaten
  800.     charsEaten = srcPtr - srcData;
  801.     // And return the bytes we stored
  802.     return outPtr - toFill;
  803. }
  804. bool CygwinTranscoder::canTranscodeTo(const unsigned int toCheck) const
  805. {
  806.     //
  807.     //  If the passed value is really a surrogate embedded together, then
  808.     //  we need to break it out into its two chars. Else just one.
  809.     //
  810.     XMLCh           srcBuf[2];
  811.     unsigned int    srcCount = 1;
  812.     if (toCheck & 0xFFFF0000)
  813.     {
  814.         srcBuf[0] = XMLCh((toCheck >> 10) + 0xD800);
  815.         srcBuf[1] = XMLCh(toCheck & 0x3FF) + 0xDC00;
  816.         srcCount++;
  817.     }
  818.     else
  819.     {
  820.         srcBuf[0] = XMLCh(toCheck);
  821.     }
  822.     //
  823.     //  Use a local temp buffer that would hold any sane multi-byte char
  824.     //  sequence and try to transcode this guy into it.
  825.     //
  826.     char tmpBuf[64];
  827.     BOOL usedDef;
  828.     const unsigned int bytesStored = ::WideCharToMultiByte
  829.     (
  830.         fWinCP
  831.         , WC_COMPOSITECHECK | WC_SEPCHARS
  832.         , (LPCWSTR)srcBuf
  833.         , srcCount
  834.         , tmpBuf
  835.         , 64
  836.         , 0
  837.         , &usedDef
  838.     );
  839.     if (!bytesStored || usedDef)
  840.         return false;
  841.     return true;
  842. }
  843. //---------------------------------------------------------------------------
  844. //
  845. //  class CygwinTranscoder Implementation ...
  846. //
  847. //---------------------------------------------------------------------------
  848. // ---------------------------------------------------------------------------
  849. //  CygwinLCPTranscoder: Constructors and Destructor
  850. // ---------------------------------------------------------------------------
  851. CygwinLCPTranscoder::CygwinLCPTranscoder()
  852. {
  853. }
  854. CygwinLCPTranscoder::~CygwinLCPTranscoder()
  855. {
  856. }
  857. // ---------------------------------------------------------------------------
  858. //  CygwinLCPTranscoder: Implementation of the virtual transcoder interface
  859. // ---------------------------------------------------------------------------
  860. unsigned int CygwinLCPTranscoder::calcRequiredSize(const char* const srcText)
  861. {
  862.     if (!srcText)
  863.         return 0;
  864.     const unsigned int retVal = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, srcText, -1, NULL, 0);
  865.     if (retVal == (unsigned int)-1)
  866.         return 0;
  867.     return retVal;
  868. }
  869. unsigned int CygwinLCPTranscoder::calcRequiredSize(const XMLCh* const srcText)
  870. {
  871.     if (!srcText)
  872.         return 0;
  873.     const unsigned int retVal = ::WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)srcText, -1, NULL, 0, NULL, NULL);
  874.     if (retVal == (unsigned int)-1)
  875.         return 0;
  876.     return retVal;
  877. }
  878. char* CygwinLCPTranscoder::transcode(const XMLCh* const toTranscode)
  879. {
  880.     if (!toTranscode)
  881.         return 0;
  882.     char* retVal = 0;
  883.     if (*toTranscode)
  884.     {
  885.         // Calc the needed size
  886.         const unsigned int neededLen = ::WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)toTranscode, -1, NULL, 0, NULL, NULL);
  887.         if (neededLen == (unsigned int)-1)
  888.             return 0;
  889.         // Allocate a buffer of that size plus one for the null and transcode
  890.         // Returned length of WideCharToMultiByte includes terminating NUL.
  891.         retVal = new char[neededLen+1];
  892.         ::WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)toTranscode, -1, retVal, neededLen+1, NULL, NULL);
  893.         // And cap it off anyway just to make sure
  894.         retVal[neededLen] = 0;
  895.     }
  896.     else
  897.     {
  898.         retVal = new char[1];
  899.         retVal[0] = 0;
  900.     }
  901.     return retVal;
  902. }
  903. char* CygwinLCPTranscoder::transcode(const XMLCh* const toTranscode,
  904.                                      MemoryManager* const manager)
  905. {
  906.     if (!toTranscode)
  907.         return 0;
  908.     char* retVal = 0;
  909.     if (*toTranscode)
  910.     {
  911.         // Calc the needed size
  912.         const unsigned int neededLen = ::WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)toTranscode, -1, NULL, 0, NULL, NULL);
  913.         if (neededLen == (unsigned int)-1)
  914.             return 0;
  915.         // Allocate a buffer of that size plus one for the null and transcode
  916.         // Returned length of WideCharToMultiByte includes terminating NUL.
  917.         retVal = (char*) manager->allocate((neededLen+1) * sizeof(char)); //new char[neededLen+1];
  918.         ::WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)toTranscode, -1, retVal, neededLen+1, NULL, NULL);
  919.         // And cap it off anyway just to make sure
  920.         retVal[neededLen] = 0;
  921.     }
  922.     else
  923.     {
  924.         retVal = (char*) manager->allocate(sizeof(char)); //new char[1];
  925.         retVal[0] = 0;
  926.     }
  927.     return retVal;
  928. }
  929. XMLCh* CygwinLCPTranscoder::transcode(const char* const toTranscode)
  930. {
  931.     if (!toTranscode)
  932.         return 0;
  933.     XMLCh* retVal = 0;
  934.     if (*toTranscode)
  935.     {
  936.         // Calculate the buffer size required
  937.         const unsigned int neededLen = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, toTranscode, -1, NULL, 0);
  938.         if (neededLen == (unsigned int)-1)
  939.             return 0;
  940.         // Allocate a buffer of that size plus one for the null and transcode
  941.         retVal = new XMLCh[neededLen + 1];
  942.         ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, toTranscode, -1, (LPWSTR)retVal, neededLen + 1);
  943.         // Cap it off just to make sure. We are so paranoid!
  944.         retVal[neededLen] = 0;
  945.     }
  946.     else
  947.     {
  948.         retVal = new XMLCh[1];
  949.         retVal[0] = 0;
  950.     }
  951.     return retVal;
  952. }
  953. XMLCh* CygwinLCPTranscoder::transcode(const char* const toTranscode,
  954.                                       MemoryManager* const manager)
  955. {
  956.     if (!toTranscode)
  957.         return 0;
  958.     XMLCh* retVal = 0;
  959.     if (*toTranscode)
  960.     {
  961.         // Calculate the buffer size required
  962.         const unsigned int neededLen = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, toTranscode, -1, NULL, 0);
  963.         if (neededLen == (unsigned int)-1)
  964.             return 0;
  965.         // Allocate a buffer of that size plus one for the null and transcode
  966.         retVal = (XMLCh*) manager->allocate((neededLen + 1) * sizeof(XMLCh)); //new XMLCh[neededLen + 1];
  967.         ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, toTranscode, -1, (LPWSTR)retVal, neededLen + 1);
  968.         // Cap it off just to make sure. We are so paranoid!
  969.         retVal[neededLen] = 0;
  970.     }
  971.     else
  972.     {
  973.         retVal = (XMLCh*) manager->allocate(sizeof(XMLCh)); //new XMLCh[1];
  974.         retVal[0] = 0;
  975.     }
  976.     return retVal;
  977. }
  978. bool CygwinLCPTranscoder::transcode( const   char* const    toTranscode
  979.                                     ,       XMLCh* const    toFill
  980.                                     , const unsigned int    maxChars)
  981. {
  982.     // Check for a couple of psycho corner cases
  983.     if (!toTranscode || !maxChars)
  984.     {
  985.         toFill[0] = 0;
  986.         return true;
  987.     }
  988.     if (!*toTranscode)
  989.     {
  990.         toFill[0] = 0;
  991.         return true;
  992.     }
  993.     // This one has a fixed size output, so try it and if it fails it fails
  994.     if ( size_t(-1) == ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, toTranscode, -1, (LPWSTR)toFill, maxChars + 1) )
  995.         return false;
  996.     return true;
  997. }
  998. bool CygwinLCPTranscoder::transcode( const  XMLCh* const    toTranscode
  999.                                     ,       char* const     toFill
  1000.                                     , const unsigned int    maxBytes)
  1001. {
  1002.     // Watch for a couple of pyscho corner cases
  1003.     if (!toTranscode || !maxBytes)
  1004.     {
  1005.         toFill[0] = 0;
  1006.         return true;
  1007.     }
  1008.     if (!*toTranscode)
  1009.     {
  1010.         toFill[0] = 0;
  1011.         return true;
  1012.     }
  1013.     // This one has a fixed size output, so try it and if it fails it fails
  1014.     if ( size_t(-1) == ::WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)toTranscode, -1, toFill, maxBytes + 1, NULL, NULL) )
  1015.         return false;
  1016.     // Cap it off just in case
  1017.     toFill[maxBytes] = 0;
  1018.     return true;
  1019. }
  1020. XERCES_CPP_NAMESPACE_END