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

词法分析

开发平台:

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. //
  58. //  This test program is used, in conjunction with a set of test data files,
  59. //  to verify support for different character encodings in XML.
  60. //
  61. //---------------------------------------------------------------------
  62. // ---------------------------------------------------------------------------
  63. //  Includes
  64. // ---------------------------------------------------------------------------
  65. #include <xercesc/framework/XMLBuffer.hpp>
  66. #include <xercesc/util/PlatformUtils.hpp>
  67. #include <xercesc/util/XMLString.hpp>
  68. #include <xercesc/util/XMLException.hpp>
  69. #include <xercesc/sax/SAXException.hpp>
  70. #include <xercesc/sax/ErrorHandler.hpp>
  71. #include <xercesc/sax/SAXParseException.hpp>
  72. #include <xercesc/parsers/XercesDOMParser.hpp>
  73. #include <xercesc/dom/DOM.hpp>
  74. #include <stdio.h>
  75. XERCES_CPP_NAMESPACE_USE
  76. static int gTestsFailed = 0;
  77. static int gTestsRun    = 0;
  78. static XercesDOMParser* parser = 0;
  79. //-----------------------------------------------------------------------
  80. //
  81. //  ErrorHandler.   The DOM Parser will report any parsing errors by means
  82. //                  of call-backs to the methods of this class.
  83. //                  This is just necessary boilerplate, as far as this
  84. //                  program is concerned.
  85. //
  86. //-----------------------------------------------------------------------
  87. class  ParseErrorHandler: public ErrorHandler
  88. {
  89. public:
  90.     void warning(const SAXParseException& e);
  91.     void error(const SAXParseException& e);
  92.     void fatalError(const SAXParseException& e);
  93.     void resetErrors() {};
  94. };
  95. void ParseErrorHandler::error(const SAXParseException& e)
  96. {
  97.     char* systemId = XMLString::transcode(e.getSystemId());
  98.     char* message = XMLString::transcode(e.getMessage());
  99.     fprintf(stderr, "nError at file "%s", line %d, char %d:  %sn",
  100.         systemId, e.getLineNumber(),
  101.         e.getColumnNumber(), message);
  102.     XMLString::release(&systemId);
  103.     XMLString::release(&message);
  104.     throw e;
  105. };
  106. void ParseErrorHandler::fatalError(const SAXParseException& e)
  107. {
  108.     char* systemId = XMLString::transcode(e.getSystemId());
  109.     char* message = XMLString::transcode(e.getMessage());
  110.     fprintf(stderr, "nFatal Error at file "%s", line %d, char %d:  %sn",
  111.         systemId, e.getLineNumber(),
  112.         e.getColumnNumber(), message);
  113.     XMLString::release(&systemId);
  114.     XMLString::release(&message);
  115.     throw e;
  116. };
  117. void ParseErrorHandler::warning(const SAXParseException& e)
  118. {
  119.     char* systemId = XMLString::transcode(e.getSystemId());
  120.     char* message = XMLString::transcode(e.getMessage());
  121.     fprintf(stderr, "nWarning at file "%s", line %d, char %d:  %sn",
  122.         systemId, e.getLineNumber(),
  123.         e.getColumnNumber(), message);
  124.     XMLString::release(&systemId);
  125.     XMLString::release(&message);
  126.     throw e;
  127. };
  128. //------------------------------------------------------------------------
  129. //
  130. //   parseFile  - a simpler to use function for just parsing an XML file
  131. //                and getting the DOM Document back.
  132. //
  133. //------------------------------------------------------------------------
  134. static DOMDocument* parseFile(char *fileName)
  135. {
  136.     ParseErrorHandler eh;
  137.     if (!parser)
  138.         parser = new XercesDOMParser;
  139.     parser->setDoValidation(false);
  140.     parser->setErrorHandler(&eh);
  141.     try
  142.     {
  143.         parser->parse(fileName);
  144.     }
  145.     catch (const XMLException& e )
  146.     {
  147. fprintf(stderr, "Exception Occurred "%s".  n",
  148. XMLString::transcode(e.getMessage()));
  149. fprintf(stderr, "File being parsed is "%s".n", fileName);
  150.         return 0;  // A null document.
  151.     }
  152. catch (...)
  153. {
  154. fprintf(stderr, "Unexpected Exception thrown during parse of file "%s".n",
  155.                  fileName);
  156. return 0;
  157. }
  158.     return parser->getDocument();
  159. }
  160. //------------------------------------------------------------------------
  161. //
  162. //  writeUData - Write out a udata xml element for a XMLCh* contents.
  163. //
  164. //------------------------------------------------------------------------
  165. static void writeUData(const XMLCh* s)
  166. {
  167.     unsigned int i;
  168.     printf("<udata>n");
  169.     size_t len = XMLString::stringLen(s);
  170.     for (i=0; i<len; i++)
  171.     {
  172.         if (i % 16 == 0)
  173.             printf("n");
  174.         XMLCh c = s[i];
  175.         printf("%4x ", c);
  176.     }
  177.     printf("n</udata>n");
  178. };
  179. //------------------------------------------------------------------------
  180. //
  181. //  eatWhiteSpace -  XMLCh*s are kind of short on utility functions :-(
  182. //
  183. //------------------------------------------------------------------------
  184. static void eatWhiteSpace(XMLCh* s, unsigned int &i)
  185. {
  186.     while (i < XMLString::stringLen(s))
  187.     {
  188.     XMLCh c = s[i];
  189.     if (!(c == 0x20 ||           // These are the official XML space characters,
  190.         c == 0x09 ||             //   expressed as Unicode constants.
  191.         c == 0x0A))
  192.         break;
  193.     i++;
  194.     }
  195. }
  196. //------------------------------------------------------------------------
  197. //
  198. //   convertHexValue     if the XMLCh* contains a hex number at position i,
  199. //                       convert it and return it, and update i to index the
  200. //                       first char not in the string.
  201. //                       return 0 if string[i] didn't have a hex digit.
  202. //                       0 return is ambiguous, but it doesn't matter for XML,
  203. //                       where 0 is not a valid character.
  204. //
  205. //------------------------------------------------------------------------
  206. static int convertHexValue(XMLCh* s, unsigned int &i)
  207. {
  208.     int value = 0;
  209.                                    // For reference, the digits  0-9 are Unicode 0x30-39
  210.                                    //                the letters A-F are Unicode 0x41-0x46
  211.                                    //                the letters a-f are Unicode 0x61-66
  212.                                    // We can't use character literals - we might be
  213.                                    //  building on an EBCDIC machine.
  214.     while (i < XMLString::stringLen(s))
  215.     {
  216.         XMLCh c = s[i];
  217.         if (c >= 0x61 && c <= 0x66)     // Uppercase a-f to A-F.
  218.             c -= 0x20;
  219.         if (c < 0x30 || c >0x46)        // Stop if not a hex digit
  220.             break;
  221.         if (c > 0x39 && c <0x41)
  222.             break;
  223.         value = value << 4;             // Append this digit to accumulating value
  224.         if (c <= 0x39)
  225.             value += c-0x30;
  226.         else
  227.             value += 0xA + c - 0x41;
  228.         i++;
  229.     }
  230.     return value;
  231. }
  232. //------------------------------------------------------------------------
  233. //
  234. //  processTestFile   Given the file name of an encoding test xml file,
  235. //                    run it.
  236. //
  237. //------------------------------------------------------------------------
  238. static bool  processTestFile(const XMLCh* fileName)
  239. {
  240.     //
  241.     //  Send the input file through the parse, create a DOM document for it.
  242.     //
  243.     char cFileName[4000];
  244.     XMLString::transcode(fileName, cFileName, 3999);
  245.     DOMDocument* testDoc = parseFile(cFileName);
  246.     if (testDoc == 0)
  247.         return false;    // parse errors in the source xml.
  248.     //
  249.     //  Pull the "data" element out of the document.
  250.     //
  251.     XMLCh tempStr[4000];
  252.     XMLString::transcode("data", tempStr, 3999);
  253.     DOMNodeList* nl = testDoc->getElementsByTagName(tempStr);
  254.     if (nl->getLength() != 1) {
  255.         fprintf(stderr, "Test file "%s" must have exactly one "data" element.n", cFileName);
  256.         return false;
  257.     };
  258.     DOMNode* tmpNode = nl->item(0);
  259.     DOMElement* data = (DOMElement*) tmpNode;
  260.     //
  261.     //  Build up a string containing the character data contents of the data element.
  262.     //
  263.     DOMNode* child;
  264.     XMLBuffer elData;
  265.     for (child=data->getFirstChild(); child != 0; child= child->getNextSibling())
  266.     {
  267. if (child->getNodeType() == DOMNode::COMMENT_NODE)
  268. continue;
  269.         if (! (child->getNodeType() == DOMNode::TEXT_NODE ||
  270.                child->getNodeType() == DOMNode::CDATA_SECTION_NODE ||
  271.                child->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE))
  272.         {
  273.                fprintf(stderr, "Test file "%s": data element contains unexpected children.",
  274.                     cFileName);
  275.                return false;
  276.         }
  277.         elData.append(((DOMCharacterData *)child)->getData());
  278.     };
  279.     //
  280.     //  Pull the "udata" element out of the document
  281.     //
  282.     XMLString::transcode("udata", tempStr, 3999);
  283.     nl = testDoc->getElementsByTagName(tempStr);
  284.     if (nl->getLength() != 1) {
  285.         fprintf(stderr, "Test file "%s" must have exactly one "udata" element.n", cFileName);
  286.         return false;
  287.     };
  288.     DOMNode* tmpNode1 = nl->item(0);
  289.     DOMElement* udata = (DOMElement*) tmpNode1;
  290.     //
  291.     //  Build up a string containing the character data contents of the udata element.
  292.     //  This will consist of a whole bunch hex numbers, still in string from
  293.     //
  294.     XMLBuffer rawUData;
  295.     for (child=udata->getFirstChild(); child != 0; child= child->getNextSibling())
  296.     {
  297.         if (child->getNodeType() == DOMNode::COMMENT_NODE)
  298.             continue;
  299.         if (! (child->getNodeType() == DOMNode::TEXT_NODE ||
  300.             child->getNodeType() == DOMNode::CDATA_SECTION_NODE ||
  301.             child->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE))
  302.         {
  303.             fprintf(stderr, "Test file "%s": udata element contains unexpected children.",
  304.                 cFileName);
  305.             return false;
  306.         }
  307.         rawUData.append(((DOMCharacterData *)child)->getData());
  308.     };
  309.     //
  310.     // Convert the raw (hex numbers)  form of the udata to the corresponding string.
  311.     //
  312.     XMLBuffer uData;
  313.     unsigned int rawIndex = 0;
  314.     while (rawIndex < rawUData.getLen())
  315.     {
  316.         eatWhiteSpace(rawUData.getRawBuffer(), rawIndex);
  317.         XMLCh c = convertHexValue(rawUData.getRawBuffer(), rawIndex);
  318.         if (c > 0)
  319.             uData.append(c);
  320.         else
  321.             if (rawIndex < rawUData.getLen())
  322.             {
  323.                 fprintf(stderr, "Test file "%s": Bad hex number in udata element.  "
  324.                     "Data character number %dn", cFileName, uData.getLen());
  325.                 return false;
  326.             }
  327.     }
  328.     //
  329.     // Compare the two strings.
  330.     //
  331.     unsigned int i;
  332.     for (i=0; i< elData.getLen(); i++)
  333.     {
  334.         XMLCh* elDataRaw = elData.getRawBuffer();
  335.         XMLCh* uDataRaw = uData.getRawBuffer();
  336.         if (i >= uData.getLen())
  337.         {
  338.             fprintf(stderr, "Test file "%s": udata element shorter than data at char number %dn",
  339.                 cFileName, i);
  340.             writeUData(elDataRaw);
  341.             return false;
  342.         }
  343.         if (uDataRaw[i] != elDataRaw[i])
  344.         {
  345.             fprintf(stderr, "Test file "%s": comparison failure at character number %dn",
  346.                 cFileName, i);
  347.             writeUData(elDataRaw);
  348.             return false;
  349.         };
  350.     }
  351.     if (elData.getLen() != uData.getLen())
  352.     {
  353.         fprintf(stderr, "Test file "%s": udata element longer than data at char number %dn",
  354.             cFileName, i);
  355.         writeUData(elData.getRawBuffer());
  356.         return false;
  357.     }
  358.     return true;
  359. }
  360. int main(int argc, char ** argv) {
  361.    //
  362.     // Initialize the Xerces-c environment
  363.     //
  364. try
  365.     {
  366.         XMLPlatformUtils::Initialize();
  367.     }
  368.     catch (const XMLException& toCatch)
  369.     {
  370.         fprintf(stderr, "Error during initialization of xerces-c: %sn",
  371.             XMLString::transcode(toCatch.getMessage()));
  372.          return 1;
  373.     }
  374.     //
  375.     // Parse the command line, which should specify exactly one file, which is an
  376.     //   xml file containing the list of test files to be processed.
  377.     //
  378.     if (argc != 2) {
  379.         printf("usage: %s file_name n"
  380.                "   where file name is the xml file specifying the list of test files.", argv[0]);
  381.         return 1;
  382.     }
  383.     DOMDocument* fileListDoc = parseFile(argv[1]);
  384.     if (fileListDoc == 0) return 1;
  385.     //
  386.     // Iterate over the list of files, running each as a test.
  387.     //
  388.     XMLCh tempStr[4000];
  389.     XMLString::transcode("testFile", tempStr, 3999);
  390.     DOMNodeList* list = fileListDoc->getElementsByTagName(tempStr);
  391.     int i;
  392.     int numFiles = list->getLength();
  393.     for (i=0; i<numFiles; i++)
  394.     {
  395.         ++gTestsRun;
  396.         DOMNode* tmpNode3 = list->item(i);
  397.         XMLString::transcode("name", tempStr, 3999);
  398.         const XMLCh* fileName = ((DOMElement*) tmpNode3)->getAttribute(tempStr);
  399.         if (processTestFile(fileName) == false)
  400.             ++gTestsFailed;
  401.     };
  402.     //
  403.     // We are done.  Print out a summary of the results
  404.     //
  405.     printf("Encoding Tests Results Summary: n"
  406.            "   %d encoding tests run.n"
  407.            "   %d tests passed,n"
  408.            "   %d tests failedn", gTestsRun, gTestsRun-gTestsFailed, gTestsFailed);
  409.     delete parser;
  410.     parser = 0;
  411.    return 0;
  412. };