diff --git a/CMakeLists.txt b/CMakeLists.txt index f08772e..edf5959 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,9 @@ set (ENCFS_NAME "Encrypted Filesystem") set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") +option (BUILD_SHARED_LIBS "build shared libraries" OFF) +option (USE_INTERNAL_TINYXML "use build-in TinyXML2" ON) + # We need C++ 11 if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.0) # CMake 3.1 has built-in CXX standard checks. @@ -48,8 +51,16 @@ add_definitions (-D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26) find_package (OpenSSL REQUIRED) include_directories (${OPENSSL_INCLUDE_DIR}) -find_package (TinyXML REQUIRED) -include_directories (${TINYXML_INCLUDE_DIR}) +if (USE_INTERNAL_TINYXML) + message("-- Using local TinyXML2 copy") + add_subdirectory(tinyxml2-3.0.0) + include_directories(${CMAKE_SOURCE_DIR}/tinyxml2-3.0.0) + link_directories(${CMAKE_BINARY_DIR}/tinyxml2-3.0.0) + set(TINYXML_LIBRARIES tinyxml2) +else () + find_package (TinyXML REQUIRED) + include_directories (${TINYXML_INCLUDE_DIR}) +endif () find_package (RLog REQUIRED) add_definitions (-DRLOG_COMPONENT="encfs") @@ -129,9 +140,10 @@ set(SOURCE_FILES encfs/StreamNameIO.cpp encfs/XmlReader.cpp ) -add_library(encfs SHARED ${SOURCE_FILES}) -set_property(TARGET encfs PROPERTY VERSION ${ENCFS_VERSION}) -set_property(TARGET encfs PROPERTY SOVERSION ${ENCFS_SOVERSION}) +add_library(encfs ${SOURCE_FILES}) +set_target_properties(encfs PROPERTIES + VERSION ${ENCFS_VERSION} + SOVERSION ${ENCFS_SOVERSION}) target_link_libraries(encfs ${FUSE_LIBRARIES} ${OPENSSL_LIBRARIES} diff --git a/circle.yml b/circle.yml index df24a9e..cefc163 100644 --- a/circle.yml +++ b/circle.yml @@ -4,7 +4,7 @@ machine: dependencies: pre: - - sudo apt-get install cmake libfuse-dev librlog-dev libgettextpo-dev libtinyxml2-dev + - sudo apt-get install cmake libfuse-dev librlog-dev libgettextpo-dev - bash ./ci/install-gcc.sh test: diff --git a/drone-config/Dockerfile b/drone-config/Dockerfile index f6fc34e..baf9fcc 100644 --- a/drone-config/Dockerfile +++ b/drone-config/Dockerfile @@ -4,7 +4,7 @@ FROM ubuntu # Do system updates and install dependencies RUN apt-get update RUN apt-get -y upgrade -RUN sudo apt-get -y install git wget autopoint libfuse-dev libtinyxml2-dev +RUN sudo apt-get -y install git wget autopoint libfuse-dev RUN apt-get clean # Download Drone.io diff --git a/drone-config/worker/Dockerfile b/drone-config/worker/Dockerfile index 37592f0..6dbf9a4 100644 --- a/drone-config/worker/Dockerfile +++ b/drone-config/worker/Dockerfile @@ -35,6 +35,5 @@ RUN apt-get -y upgrade \ librlog-dev \ gettext \ libgettextpo-dev \ - libtinyxml2-dev \ && apt-get clean diff --git a/tinyxml2-3.0.0/.gitignore b/tinyxml2-3.0.0/.gitignore new file mode 100644 index 0000000..a765577 --- /dev/null +++ b/tinyxml2-3.0.0/.gitignore @@ -0,0 +1,13 @@ +# intermediate files +Win32/ +x64/ +ipch/ +resources/out/ +tinyxml2/tinyxml2-cbp/bin/ +tinyxml2/tinyxml2-cbp/obj/ +*.sdf +*.suo +*.opensdf +*.user +*.depend +*.layout \ No newline at end of file diff --git a/tinyxml2-3.0.0/CMakeLists.txt b/tinyxml2-3.0.0/CMakeLists.txt new file mode 100644 index 0000000..5b6e97c --- /dev/null +++ b/tinyxml2-3.0.0/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 2.6 FATAL_ERROR) +cmake_policy(VERSION 2.6) + +project(tinyxml2) +include(GNUInstallDirs) +#enable_testing() + +#CMAKE_BUILD_TOOL + +################################ +# set lib version here + +set(GENERIC_LIB_VERSION "3.0.0") +set(GENERIC_LIB_SOVERSION "3") + + +################################ +# Add common source + +include_directories("${CMAKE_CURRENT_SOURCE_DIR}/.") + +################################ +# Add custom target to copy all data + +set(TARGET_DATA_COPY DATA_COPY) +if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) + add_custom_target( + ${TARGET_DATA_COPY} + COMMAND ${CMAKE_COMMAND} -E echo "In source build") +else(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) + make_directory(${CMAKE_CURRENT_BINARY_DIR}/resources/) + add_custom_target( + ${TARGET_DATA_COPY} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/resources/dream.xml ${CMAKE_CURRENT_BINARY_DIR}/resources/ + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/resources/empty.xml ${CMAKE_CURRENT_BINARY_DIR}/resources/ + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/resources/utf8test.xml ${CMAKE_CURRENT_BINARY_DIR}/resources/ + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/resources/utf8testverify.xml ${CMAKE_CURRENT_BINARY_DIR}/resources/) +endif(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) + +################################ +# Add definitions + +if(MSVC) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) +endif(MSVC) + +################################ +# Add targets +option(BUILD_SHARED_LIBS "build shared or static libraries" OFF) +add_library(tinyxml2 tinyxml2.cpp tinyxml2.h) +set_target_properties(tinyxml2 PROPERTIES + COMPILE_DEFINITIONS "TINYXML2_EXPORT" + VERSION "${GENERIC_LIB_VERSION}" + SOVERSION "${GENERIC_LIB_SOVERSION}") + +add_executable(xmltest xmltest.cpp) +add_dependencies(xmltest tinyxml2) +add_dependencies(xmltest ${TARGET_DATA_COPY}) +target_link_libraries(xmltest tinyxml2) + + +install(TARGETS tinyxml2 + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +install(FILES tinyxml2.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +foreach(p LIB INCLUDE) + set(var CMAKE_INSTALL_${p}DIR) + if(NOT IS_ABSOLUTE "${${var}}") + set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") + endif() +endforeach() + +configure_file(tinyxml2.pc.in tinyxml2.pc @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/tinyxml2.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + +#add_test(xmltest ${SAMPLE_NAME} COMMAND $) diff --git a/tinyxml2-3.0.0/Makefile b/tinyxml2-3.0.0/Makefile new file mode 100644 index 0000000..aab6293 --- /dev/null +++ b/tinyxml2-3.0.0/Makefile @@ -0,0 +1,6 @@ +all: xmltest +xmltest: xmltest.cpp tinyxml2.cpp tinyxml2.h +test: clean xmltest + ./xmltest +clean: + rm -f *.o xmltest diff --git a/tinyxml2-3.0.0/contrib/html5-printer.cpp b/tinyxml2-3.0.0/contrib/html5-printer.cpp new file mode 100644 index 0000000..3205ccd --- /dev/null +++ b/tinyxml2-3.0.0/contrib/html5-printer.cpp @@ -0,0 +1,108 @@ +// g++ -Wall -O2 contrib/html5-printer.cpp -o html5-printer -ltinyxml2 + +// This program demonstrates how to use "tinyxml2" to generate conformant HTML5 +// by deriving from the "tinyxml2::XMLPrinter" class. + +// http://dev.w3.org/html5/markup/syntax.html + +// In HTML5, there are 16 so-called "void" elements. "void elements" NEVER have +// inner content (but they MAY have attributes), and are assumed to be self-closing. +// An example of a self-closig HTML5 element is "
" (line break) +// All other elements are called "non-void" and MUST never self-close. +// Examples: "
". + +// tinyxml2::XMLPrinter will emit _ALL_ XML elements with no inner content as +// self-closing. This behavior produces space-effeceint XML, but incorrect HTML5. + +// Author: Dennis Jenkins, dennis (dot) jenkins (dot) 75 (at) gmail (dot) com. +// License: Same as tinyxml2 (zlib, see below) +// This example is a small contribution to the world! Enjoy it! + +/* +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#include +#include + +#if defined (_MSC_VER) +#define strcasecmp stricmp +#endif + +using namespace tinyxml2; + +// Contrived input containing a mix of void and non-void HTML5 elements. +// When printed via XMLPrinter, some non-void elements will self-close (not valid HTML5). +static const char input[] = +"


©
"; + +// XMLPrinterHTML5 is small enough, just put the entire implementation inline. +class XMLPrinterHTML5 : public XMLPrinter +{ +public: + XMLPrinterHTML5 (FILE* file=0, bool compact = false, int depth = 0) : + XMLPrinter (file, compact, depth) + {} + +protected: + virtual void CloseElement () { + if (_elementJustOpened && !isVoidElement (_stack.PeekTop())) { + SealElement(); + } + XMLPrinter::CloseElement(); + } + + virtual bool isVoidElement (const char *name) { +// Complete list of all HTML5 "void elements", +// http://dev.w3.org/html5/markup/syntax.html + static const char *list[] = { + "area", "base", "br", "col", "command", "embed", "hr", "img", + "input", "keygen", "link", "meta", "param", "source", "track", "wbr", + NULL + }; + +// I could use 'bsearch', but I don't have MSVC to test on (it would work with gcc/libc). + for (const char **p = list; *p; ++p) { + if (!strcasecmp (name, *p)) { + return true; + } + } + + return false; + } +}; + +int main (void) { + XMLDocument doc (false); + doc.Parse (input); + + std::cout << "INPUT:\n" << input << "\n\n"; + + XMLPrinter prn (NULL, true); + doc.Print (&prn); + std::cout << "XMLPrinter (not valid HTML5):\n" << prn.CStr() << "\n\n"; + + XMLPrinterHTML5 html5 (NULL, true); + doc.Print (&html5); + std::cout << "XMLPrinterHTML5:\n" << html5.CStr() << "\n"; + + return 0; +} diff --git a/tinyxml2-3.0.0/readme.md b/tinyxml2-3.0.0/readme.md new file mode 100644 index 0000000..485e00f --- /dev/null +++ b/tinyxml2-3.0.0/readme.md @@ -0,0 +1,324 @@ +TinyXML-2 +========= +![TinyXML-2 Logo](http://www.grinninglizard.com/tinyxml2/TinyXML2_small.png) + +TinyXML-2 is a simple, small, efficient, C++ XML parser that can be +easily integrated into other programs. + +The master is hosted on github: +https://github.com/leethomason/tinyxml2 + +The online HTML version of these docs: +http://grinninglizard.com/tinyxml2docs/index.html + +Examples are in the "related pages" tab of the HTML docs. + +What it does. +------------- + +In brief, TinyXML-2 parses an XML document, and builds from that a +Document Object Model (DOM) that can be read, modified, and saved. + +XML stands for "eXtensible Markup Language." It is a general purpose +human and machine readable markup language to describe arbitrary data. +All those random file formats created to store application data can +all be replaced with XML. One parser for everything. + +http://en.wikipedia.org/wiki/XML + +There are different ways to access and interact with XML data. +TinyXML-2 uses a Document Object Model (DOM), meaning the XML data is parsed +into a C++ objects that can be browsed and manipulated, and then +written to disk or another output stream. You can also construct an XML document +from scratch with C++ objects and write this to disk or another output +stream. You can even use TinyXML-2 to stream XML programmatically from +code without creating a document first. + +TinyXML-2 is designed to be easy and fast to learn. It is one header and +one cpp file. Simply add these to your project and off you go. +There is an example file - xmltest.cpp - to get you started. + +TinyXML-2 is released under the ZLib license, +so you can use it in open source or commercial code. The details +of the license are at the top of every source file. + +TinyXML-2 attempts to be a flexible parser, but with truly correct and +compliant XML output. TinyXML-2 should compile on any reasonably C++ +compliant system. It does not rely on exceptions, RTTI, or the STL. + +What it doesn't do. +------------------- + +TinyXML-2 doesn't parse or use DTDs (Document Type Definitions) or XSLs +(eXtensible Stylesheet Language.) There are other parsers out there +that are much more fully featured. But they are also much bigger, +take longer to set up in your project, have a higher learning curve, +and often have a more restrictive license. If you are working with +browsers or have more complete XML needs, TinyXML-2 is not the parser for you. + +TinyXML-1 vs. TinyXML-2 +----------------------- + +TinyXML-2 is now the focus of all development, well tested, and your +best choice unless you have a requirement to maintain TinyXML-1 code. + +TinyXML-2 uses a similar API to TinyXML-1 and the same +rich test cases. But the implementation of the parser is completely re-written +to make it more appropriate for use in a game. It uses less memory, is faster, +and uses far fewer memory allocations. + +TinyXML-2 has no requirement for STL, but has also dropped all STL support. All +strings are query and set as 'const char*'. This allows the use of internal +allocators, and keeps the code much simpler. + +Both parsers: + +1. Simple to use with similar APIs. +2. DOM based parser. +3. UTF-8 Unicode support. http://en.wikipedia.org/wiki/UTF-8 + +Advantages of TinyXML-2 + +1. The focus of all future dev. +2. Many fewer memory allocation (1/10th to 1/100th), uses less memory + (about 40% of TinyXML-1), and faster. +3. No STL requirement. +4. More modern C++, including a proper namespace. +5. Proper and useful handling of whitespace + +Advantages of TinyXML-1 + +1. Can report the location of parsing errors. +2. Support for some C++ STL conventions: streams and strings +3. Very mature and well debugged code base. + +Features +-------- + +### Memory Model + +An XMLDocument is a C++ object like any other, that can be on the stack, or +new'd and deleted on the heap. + +However, any sub-node of the Document, XMLElement, XMLText, etc, can only +be created by calling the appropriate XMLDocument::NewElement, NewText, etc. +method. Although you have pointers to these objects, they are still owned +by the Document. When the Document is deleted, so are all the nodes it contains. + +### White Space + +#### Whitespace Preservation (default) + +Microsoft has an excellent article on white space: http://msdn.microsoft.com/en-us/library/ms256097.aspx + +By default, TinyXML-2 preserves white space in a (hopefully) sane way that is almost complient with the +spec. (TinyXML-1 used a completely different model, much more similar to 'collapse', below.) + +As a first step, all newlines / carriage-returns / line-feeds are normalized to a +line-feed character, as required by the XML spec. + +White space in text is preserved. For example: + + Hello, World + +The leading space before the "Hello" and the double space after the comma are +preserved. Line-feeds are preserved, as in this example: + + Hello again, + World + +However, white space between elements is **not** preserved. Although not strictly +compliant, tracking and reporting inter-element space is awkward, and not normally +valuable. TinyXML-2 sees these as the same XML: + + + 1 + 2 + 3 + + + 123 + +#### Whitespace Collapse + +For some applications, it is preferable to collapse whitespace. Collapsing +whitespace gives you "HTML-like" behavior, which is sometimes more suitable +for hand typed documents. + +TinyXML-2 supports this with the 'whitespace' parameter to the XMLDocument constructor. +(The default is to preserve whitespace, as described above.) + +However, you may also use COLLAPSE_WHITESPACE, which will: + +* Remove leading and trailing whitespace +* Convert newlines and line-feeds into a space character +* Collapse a run of any number of space characters into a single space character + +Note that (currently) there is a performance impact for using COLLAPSE_WHITESPACE. +It essentially causes the XML to be parsed twice. + +### Entities + +TinyXML-2 recognizes the pre-defined "character entities", meaning special +characters. Namely: + + & & + < < + > > + " " + ' ' + +These are recognized when the XML document is read, and translated to their +UTF-8 equivalents. For instance, text with the XML of: + + Far & Away + +will have the Value() of "Far & Away" when queried from the XMLText object, +and will be written back to the XML stream/file as an ampersand. + +Additionally, any character can be specified by its Unicode code point: +The syntax " " or " " are both to the non-breaking space characher. +This is called a 'numeric character reference'. Any numeric character reference +that isn't one of the special entities above, will be read, but written as a +regular code point. The output is correct, but the entity syntax isn't preserved. + +### Printing + +#### Print to file +You can directly use the convenience function: + + XMLDocument doc; + ... + doc.SaveFile( "foo.xml" ); + +Or the XMLPrinter class: + + XMLPrinter printer( fp ); + doc.Print( &printer ); + +#### Print to memory +Printing to memory is supported by the XMLPrinter. + + XMLPrinter printer; + doc.Print( &printer ); + // printer.CStr() has a const char* to the XML + +#### Print without an XMLDocument + +When loading, an XML parser is very useful. However, sometimes +when saving, it just gets in the way. The code is often set up +for streaming, and constructing the DOM is just overhead. + +The Printer supports the streaming case. The following code +prints out a trivially simple XML file without ever creating +an XML document. + + XMLPrinter printer( fp ); + printer.OpenElement( "foo" ); + printer.PushAttribute( "foo", "bar" ); + printer.CloseElement(); + +Examples +-------- + +#### Load and parse an XML file. + + /* ------ Example 1: Load and parse an XML file. ---- */ + { + XMLDocument doc; + doc.LoadFile( "dream.xml" ); + } + +#### Lookup information. + + /* ------ Example 2: Lookup information. ---- */ + { + XMLDocument doc; + doc.LoadFile( "dream.xml" ); + + // Structure of the XML file: + // - Element "PLAY" the root Element, which is the + // FirstChildElement of the Document + // - - Element "TITLE" child of the root PLAY Element + // - - - Text child of the TITLE Element + + // Navigate to the title, using the convenience function, + // with a dangerous lack of error checking. + const char* title = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" )->GetText(); + printf( "Name of play (1): %s\n", title ); + + // Text is just another Node to TinyXML-2. The more + // general way to get to the XMLText: + XMLText* textNode = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" )->FirstChild()->ToText(); + title = textNode->Value(); + printf( "Name of play (2): %s\n", title ); + } + +Using and Installing +-------------------- + +There are 2 files in TinyXML-2: +* tinyxml2.cpp +* tinyxml2.h + +And additionally a test file: +* xmltest.cpp + +Simply compile and run. There is a visual studio 2010 project included, a simple Makefile, +an XCode project, a Code::Blocks project, and a cmake CMakeLists.txt included to help you. +The top of tinyxml.h even has a simple g++ command line if you are are *nix and don't want +to use a build system. + +Versioning +---------- + +TinyXML-2 uses semantic versioning. http://semver.org/ Releases are now tagged in github. + +Note that the major version will (probably) change fairly rapidly. API changes are fairly +common. + +Documentation +------------- + +The documentation is build with Doxygen, using the 'dox' +configuration file. + +License +------- + +TinyXML-2 is released under the zlib license: + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source +distribution. + +Contributors +------------ + +Thanks very much to everyone who sends suggestions, bugs, ideas, and +encouragement. It all helps, and makes this project fun. + +The original TinyXML-1 has many contributors, who all deserve thanks +in shaping what is a very successful library. Extra thanks to Yves +Berquin and Andrew Ellerton who were key contributors. + +TinyXML-2 grew from that effort. Lee Thomason is the original author +of TinyXML-2 (and TinyXML-1) but TinyXML-2 has been and is being improved +by many contributors. + +Thanks to John Mackay at http://john.mackay.rosalilastudio.com for the TinyXML-2 logo! + + diff --git a/tinyxml2-3.0.0/resources/dream.xml b/tinyxml2-3.0.0/resources/dream.xml new file mode 100755 index 0000000..0a0b17c --- /dev/null +++ b/tinyxml2-3.0.0/resources/dream.xml @@ -0,0 +1,4546 @@ + + + + +A Midsummer Night's Dream + + +

Text placed in the public domain by Moby Lexical Tools, 1992.

+

SGML markup by Jon Bosak, 1992-1994.

+

XML version by Jon Bosak, 1996-1998.

+

This work may be freely copied and distributed worldwide.

+
+ + + +Dramatis Personae + +THESEUS, Duke of Athens. +EGEUS, father to Hermia. + + +LYSANDER +DEMETRIUS +in love with Hermia. + + +PHILOSTRATE, master of the revels to Theseus. +QUINCE, a carpenter. +SNUG, a joiner. +BOTTOM, a weaver. +FLUTE, a bellows-mender. +SNOUT, a tinker. +STARVELING, a tailor. +HIPPOLYTA, queen of the Amazons, betrothed to Theseus. +HERMIA, daughter to Egeus, in love with Lysander. +HELENA, in love with Demetrius. +OBERON, king of the fairies. +TITANIA, queen of the fairies. +PUCK, or Robin Goodfellow. + + +PEASEBLOSSOM +COBWEB +MOTH +MUSTARDSEED +fairies. + + +Other fairies attending their King and Queen. +Attendants on Theseus and Hippolyta. + + +SCENE Athens, and a wood near it. + +A MIDSUMMER NIGHT'S DREAM + +ACT I + +SCENE I. Athens. The palace of THESEUS. +Enter THESEUS, HIPPOLYTA, PHILOSTRATE, and +Attendants + + +THESEUS +Now, fair Hippolyta, our nuptial hour +Draws on apace; four happy days bring in +Another moon: but, O, methinks, how slow +This old moon wanes! she lingers my desires, +Like to a step-dame or a dowager +Long withering out a young man revenue. + + + +HIPPOLYTA +Four days will quickly steep themselves in night; +Four nights will quickly dream away the time; +And then the moon, like to a silver bow +New-bent in heaven, shall behold the night +Of our solemnities. + + + +THESEUS +Go, Philostrate, +Stir up the Athenian youth to merriments; +Awake the pert and nimble spirit of mirth; +Turn melancholy forth to funerals; +The pale companion is not for our pomp. +Exit PHILOSTRATE +Hippolyta, I woo'd thee with my sword, +And won thy love, doing thee injuries; +But I will wed thee in another key, +With pomp, with triumph and with revelling. + + + +Enter EGEUS, HERMIA, LYSANDER, and DEMETRIUS + + +EGEUS +Happy be Theseus, our renowned duke! + + + +THESEUS +Thanks, good Egeus: what's the news with thee? + + + +EGEUS +Full of vexation come I, with complaint +Against my child, my daughter Hermia. +Stand forth, Demetrius. My noble lord, +This man hath my consent to marry her. +Stand forth, Lysander: and my gracious duke, +This man hath bewitch'd the bosom of my child; +Thou, thou, Lysander, thou hast given her rhymes, +And interchanged love-tokens with my child: +Thou hast by moonlight at her window sung, +With feigning voice verses of feigning love, +And stolen the impression of her fantasy +With bracelets of thy hair, rings, gawds, conceits, +Knacks, trifles, nosegays, sweetmeats, messengers +Of strong prevailment in unharden'd youth: +With cunning hast thou filch'd my daughter's heart, +Turn'd her obedience, which is due to me, +To stubborn harshness: and, my gracious duke, +Be it so she; will not here before your grace +Consent to marry with Demetrius, +I beg the ancient privilege of Athens, +As she is mine, I may dispose of her: +Which shall be either to this gentleman +Or to her death, according to our law +Immediately provided in that case. + + + +THESEUS +What say you, Hermia? be advised fair maid: +To you your father should be as a god; +One that composed your beauties, yea, and one +To whom you are but as a form in wax +By him imprinted and within his power +To leave the figure or disfigure it. +Demetrius is a worthy gentleman. + + + +HERMIA +So is Lysander. + + + +THESEUS +In himself he is; +But in this kind, wanting your father's voice, +The other must be held the worthier. + + + +HERMIA +I would my father look'd but with my eyes. + + + +THESEUS +Rather your eyes must with his judgment look. + + + +HERMIA +I do entreat your grace to pardon me. +I know not by what power I am made bold, +Nor how it may concern my modesty, +In such a presence here to plead my thoughts; +But I beseech your grace that I may know +The worst that may befall me in this case, +If I refuse to wed Demetrius. + + + +THESEUS +Either to die the death or to abjure +For ever the society of men. +Therefore, fair Hermia, question your desires; +Know of your youth, examine well your blood, +Whether, if you yield not to your father's choice, +You can endure the livery of a nun, +For aye to be in shady cloister mew'd, +To live a barren sister all your life, +Chanting faint hymns to the cold fruitless moon. +Thrice-blessed they that master so their blood, +To undergo such maiden pilgrimage; +But earthlier happy is the rose distill'd, +Than that which withering on the virgin thorn +Grows, lives and dies in single blessedness. + + + +HERMIA +So will I grow, so live, so die, my lord, +Ere I will my virgin patent up +Unto his lordship, whose unwished yoke +My soul consents not to give sovereignty. + + + +THESEUS +Take time to pause; and, by the nest new moon-- +The sealing-day betwixt my love and me, +For everlasting bond of fellowship-- +Upon that day either prepare to die +For disobedience to your father's will, +Or else to wed Demetrius, as he would; +Or on Diana's altar to protest +For aye austerity and single life. + + + +DEMETRIUS +Relent, sweet Hermia: and, Lysander, yield +Thy crazed title to my certain right. + + + +LYSANDER +You have her father's love, Demetrius; +Let me have Hermia's: do you marry him. + + + +EGEUS +Scornful Lysander! true, he hath my love, +And what is mine my love shall render him. +And she is mine, and all my right of her +I do estate unto Demetrius. + + + +LYSANDER +I am, my lord, as well derived as he, +As well possess'd; my love is more than his; +My fortunes every way as fairly rank'd, +If not with vantage, as Demetrius'; +And, which is more than all these boasts can be, +I am beloved of beauteous Hermia: +Why should not I then prosecute my right? +Demetrius, I'll avouch it to his head, +Made love to Nedar's daughter, Helena, +And won her soul; and she, sweet lady, dotes, +Devoutly dotes, dotes in idolatry, +Upon this spotted and inconstant man. + + + +THESEUS +I must confess that I have heard so much, +And with Demetrius thought to have spoke thereof; +But, being over-full of self-affairs, +My mind did lose it. But, Demetrius, come; +And come, Egeus; you shall go with me, +I have some private schooling for you both. +For you, fair Hermia, look you arm yourself +To fit your fancies to your father's will; +Or else the law of Athens yields you up-- +Which by no means we may extenuate-- +To death, or to a vow of single life. +Come, my Hippolyta: what cheer, my love? +Demetrius and Egeus, go along: +I must employ you in some business +Against our nuptial and confer with you +Of something nearly that concerns yourselves. + + + +EGEUS +With duty and desire we follow you. + + + +Exeunt all but LYSANDER and HERMIA + + +LYSANDER +How now, my love! why is your cheek so pale? +How chance the roses there do fade so fast? + + + +HERMIA +Belike for want of rain, which I could well +Beteem them from the tempest of my eyes. + + + +LYSANDER +Ay me! for aught that I could ever read, +Could ever hear by tale or history, +The course of true love never did run smooth; +But, either it was different in blood,-- + + + +HERMIA +O cross! too high to be enthrall'd to low. + + + +LYSANDER +Or else misgraffed in respect of years,-- + + + +HERMIA +O spite! too old to be engaged to young. + + + +LYSANDER +Or else it stood upon the choice of friends,-- + + + +HERMIA +O hell! to choose love by another's eyes. + + + +LYSANDER +Or, if there were a sympathy in choice, +War, death, or sickness did lay siege to it, +Making it momentany as a sound, +Swift as a shadow, short as any dream; +Brief as the lightning in the collied night, +That, in a spleen, unfolds both heaven and earth, +And ere a man hath power to say 'Behold!' +The jaws of darkness do devour it up: +So quick bright things come to confusion. + + + +HERMIA +If then true lovers have been ever cross'd, +It stands as an edict in destiny: +Then let us teach our trial patience, +Because it is a customary cross, +As due to love as thoughts and dreams and sighs, +Wishes and tears, poor fancy's followers. + + + +LYSANDER +A good persuasion: therefore, hear me, Hermia. +I have a widow aunt, a dowager +Of great revenue, and she hath no child: +From Athens is her house remote seven leagues; +And she respects me as her only son. +There, gentle Hermia, may I marry thee; +And to that place the sharp Athenian law +Cannot pursue us. If thou lovest me then, +Steal forth thy father's house to-morrow night; +And in the wood, a league without the town, +Where I did meet thee once with Helena, +To do observance to a morn of May, +There will I stay for thee. + + + +HERMIA +My good Lysander! +I swear to thee, by Cupid's strongest bow, +By his best arrow with the golden head, +By the simplicity of Venus' doves, +By that which knitteth souls and prospers loves, +And by that fire which burn'd the Carthage queen, +When the false Troyan under sail was seen, +By all the vows that ever men have broke, +In number more than ever women spoke, +In that same place thou hast appointed me, +To-morrow truly will I meet with thee. + + + +LYSANDER +Keep promise, love. Look, here comes Helena. + + + +Enter HELENA + + +HERMIA +God speed fair Helena! whither away? + + + +HELENA +Call you me fair? that fair again unsay. +Demetrius loves your fair: O happy fair! +Your eyes are lode-stars; and your tongue's sweet air +More tuneable than lark to shepherd's ear, +When wheat is green, when hawthorn buds appear. +Sickness is catching: O, were favour so, +Yours would I catch, fair Hermia, ere I go; +My ear should catch your voice, my eye your eye, +My tongue should catch your tongue's sweet melody. +Were the world mine, Demetrius being bated, +The rest I'd give to be to you translated. +O, teach me how you look, and with what art +You sway the motion of Demetrius' heart. + + + +HERMIA +I frown upon him, yet he loves me still. + + + +HELENA +O that your frowns would teach my smiles such skill! + + + +HERMIA +I give him curses, yet he gives me love. + + + +HELENA +O that my prayers could such affection move! + + + +HERMIA +The more I hate, the more he follows me. + + + +HELENA +The more I love, the more he hateth me. + + + +HERMIA +His folly, Helena, is no fault of mine. + + + +HELENA +None, but your beauty: would that fault were mine! + + + +HERMIA +Take comfort: he no more shall see my face; +Lysander and myself will fly this place. +Before the time I did Lysander see, +Seem'd Athens as a paradise to me: +O, then, what graces in my love do dwell, +That he hath turn'd a heaven unto a hell! + + + +LYSANDER +Helen, to you our minds we will unfold: +To-morrow night, when Phoebe doth behold +Her silver visage in the watery glass, +Decking with liquid pearl the bladed grass, +A time that lovers' flights doth still conceal, +Through Athens' gates have we devised to steal. + + + +HERMIA +And in the wood, where often you and I +Upon faint primrose-beds were wont to lie, +Emptying our bosoms of their counsel sweet, +There my Lysander and myself shall meet; +And thence from Athens turn away our eyes, +To seek new friends and stranger companies. +Farewell, sweet playfellow: pray thou for us; +And good luck grant thee thy Demetrius! +Keep word, Lysander: we must starve our sight +From lovers' food till morrow deep midnight. + + + +LYSANDER +I will, my Hermia. +Exit HERMIA +Helena, adieu: +As you on him, Demetrius dote on you! + + + +Exit + + +HELENA +How happy some o'er other some can be! +Through Athens I am thought as fair as she. +But what of that? Demetrius thinks not so; +He will not know what all but he do know: +And as he errs, doting on Hermia's eyes, +So I, admiring of his qualities: +Things base and vile, folding no quantity, +Love can transpose to form and dignity: +Love looks not with the eyes, but with the mind; +And therefore is wing'd Cupid painted blind: +Nor hath Love's mind of any judgement taste; +Wings and no eyes figure unheedy haste: +And therefore is Love said to be a child, +Because in choice he is so oft beguiled. +As waggish boys in game themselves forswear, +So the boy Love is perjured every where: +For ere Demetrius look'd on Hermia's eyne, +He hail'd down oaths that he was only mine; +And when this hail some heat from Hermia felt, +So he dissolved, and showers of oaths did melt. +I will go tell him of fair Hermia's flight: +Then to the wood will he to-morrow night +Pursue her; and for this intelligence +If I have thanks, it is a dear expense: +But herein mean I to enrich my pain, +To have his sight thither and back again. + + + +Exit + + +SCENE II. Athens. QUINCE'S house. +Enter QUINCE, SNUG, BOTTOM, FLUTE, SNOUT, and +STARVELING + + +QUINCE +Is all our company here? + + + +BOTTOM +You were best to call them generally, man by man, +according to the scrip. + + + +QUINCE +Here is the scroll of every man's name, which is +thought fit, through all Athens, to play in our +interlude before the duke and the duchess, on his +wedding-day at night. + + + +BOTTOM +First, good Peter Quince, say what the play treats +on, then read the names of the actors, and so grow +to a point. + + + +QUINCE +Marry, our play is, The most lamentable comedy, and +most cruel death of Pyramus and Thisby. + + + +BOTTOM +A very good piece of work, I assure you, and a +merry. Now, good Peter Quince, call forth your +actors by the scroll. Masters, spread yourselves. + + + +QUINCE +Answer as I call you. Nick Bottom, the weaver. + + + +BOTTOM +Ready. Name what part I am for, and proceed. + + + +QUINCE +You, Nick Bottom, are set down for Pyramus. + + + +BOTTOM +What is Pyramus? a lover, or a tyrant? + + + +QUINCE +A lover, that kills himself most gallant for love. + + + +BOTTOM +That will ask some tears in the true performing of +it: if I do it, let the audience look to their +eyes; I will move storms, I will condole in some +measure. To the rest: yet my chief humour is for a +tyrant: I could play Ercles rarely, or a part to +tear a cat in, to make all split. +The raging rocks +And shivering shocks +Shall break the locks +Of prison gates; +And Phibbus' car +Shall shine from far +And make and mar +The foolish Fates. +This was lofty! Now name the rest of the players. +This is Ercles' vein, a tyrant's vein; a lover is +more condoling. + + + +QUINCE +Francis Flute, the bellows-mender. + + + +FLUTE +Here, Peter Quince. + + + +QUINCE +Flute, you must take Thisby on you. + + + +FLUTE +What is Thisby? a wandering knight? + + + +QUINCE +It is the lady that Pyramus must love. + + + +FLUTE +Nay, faith, let me not play a woman; I have a beard coming. + + + +QUINCE +That's all one: you shall play it in a mask, and +you may speak as small as you will. + + + +BOTTOM +An I may hide my face, let me play Thisby too, I'll +speak in a monstrous little voice. 'Thisne, +Thisne;' 'Ah, Pyramus, lover dear! thy Thisby dear, +and lady dear!' + + + +QUINCE +No, no; you must play Pyramus: and, Flute, you Thisby. + + + +BOTTOM +Well, proceed. + + + +QUINCE +Robin Starveling, the tailor. + + + +STARVELING +Here, Peter Quince. + + + +QUINCE +Robin Starveling, you must play Thisby's mother. +Tom Snout, the tinker. + + + +SNOUT +Here, Peter Quince. + + + +QUINCE +You, Pyramus' father: myself, Thisby's father: +Snug, the joiner; you, the lion's part: and, I +hope, here is a play fitted. + + + +SNUG +Have you the lion's part written? pray you, if it +be, give it me, for I am slow of study. + + + +QUINCE +You may do it extempore, for it is nothing but roaring. + + + +BOTTOM +Let me play the lion too: I will roar, that I will +do any man's heart good to hear me; I will roar, +that I will make the duke say 'Let him roar again, +let him roar again.' + + + +QUINCE +An you should do it too terribly, you would fright +the duchess and the ladies, that they would shriek; +and that were enough to hang us all. + + + +ALL +That would hang us, every mother's son. + + + +BOTTOM +I grant you, friends, if that you should fright the +ladies out of their wits, they would have no more +discretion but to hang us: but I will aggravate my +voice so that I will roar you as gently as any +sucking dove; I will roar you an 'twere any +nightingale. + + + +QUINCE +You can play no part but Pyramus; for Pyramus is a +sweet-faced man; a proper man, as one shall see in a +summer's day; a most lovely gentleman-like man: +therefore you must needs play Pyramus. + + + +BOTTOM +Well, I will undertake it. What beard were I best +to play it in? + + + +QUINCE +Why, what you will. + + + +BOTTOM +I will discharge it in either your straw-colour +beard, your orange-tawny beard, your purple-in-grain +beard, or your French-crown-colour beard, your +perfect yellow. + + + +QUINCE +Some of your French crowns have no hair at all, and +then you will play bare-faced. But, masters, here +are your parts: and I am to entreat you, request +you and desire you, to con them by to-morrow night; +and meet me in the palace wood, a mile without the +town, by moonlight; there will we rehearse, for if +we meet in the city, we shall be dogged with +company, and our devices known. In the meantime I +will draw a bill of properties, such as our play +wants. I pray you, fail me not. + + + +BOTTOM +We will meet; and there we may rehearse most +obscenely and courageously. Take pains; be perfect: adieu. + + + +QUINCE +At the duke's oak we meet. + + + +BOTTOM +Enough; hold or cut bow-strings. + + + +Exeunt + + + + +ACT II + +SCENE I. A wood near Athens. +Enter, from opposite sides, a Fairy, and PUCK + + +PUCK +How now, spirit! whither wander you? + + + +Fairy +Over hill, over dale, +Thorough bush, thorough brier, +Over park, over pale, +Thorough flood, thorough fire, +I do wander everywhere, +Swifter than the moon's sphere; +And I serve the fairy queen, +To dew her orbs upon the green. +The cowslips tall her pensioners be: +In their gold coats spots you see; +Those be rubies, fairy favours, +In those freckles live their savours: +I must go seek some dewdrops here +And hang a pearl in every cowslip's ear. +Farewell, thou lob of spirits; I'll be gone: +Our queen and all our elves come here anon. + + + +PUCK +The king doth keep his revels here to-night: +Take heed the queen come not within his sight; +For Oberon is passing fell and wrath, +Because that she as her attendant hath +A lovely boy, stolen from an Indian king; +She never had so sweet a changeling; +And jealous Oberon would have the child +Knight of his train, to trace the forests wild; +But she perforce withholds the loved boy, +Crowns him with flowers and makes him all her joy: +And now they never meet in grove or green, +By fountain clear, or spangled starlight sheen, +But, they do square, that all their elves for fear +Creep into acorn-cups and hide them there. + + + +Fairy +Either I mistake your shape and making quite, +Or else you are that shrewd and knavish sprite +Call'd Robin Goodfellow: are not you he +That frights the maidens of the villagery; +Skim milk, and sometimes labour in the quern +And bootless make the breathless housewife churn; +And sometime make the drink to bear no barm; +Mislead night-wanderers, laughing at their harm? +Those that Hobgoblin call you and sweet Puck, +You do their work, and they shall have good luck: +Are not you he? + + + +PUCK +Thou speak'st aright; +I am that merry wanderer of the night. +I jest to Oberon and make him smile +When I a fat and bean-fed horse beguile, +Neighing in likeness of a filly foal: +And sometime lurk I in a gossip's bowl, +In very likeness of a roasted crab, +And when she drinks, against her lips I bob +And on her wither'd dewlap pour the ale. +The wisest aunt, telling the saddest tale, +Sometime for three-foot stool mistaketh me; +Then slip I from her bum, down topples she, +And 'tailor' cries, and falls into a cough; +And then the whole quire hold their hips and laugh, +And waxen in their mirth and neeze and swear +A merrier hour was never wasted there. +But, room, fairy! here comes Oberon. + + + +Fairy +And here my mistress. Would that he were gone! + + + +Enter, from one side, OBERON, with his train; +from the other, TITANIA, with hers + + +OBERON +Ill met by moonlight, proud Titania. + + + +TITANIA +What, jealous Oberon! Fairies, skip hence: +I have forsworn his bed and company. + + + +OBERON +Tarry, rash wanton: am not I thy lord? + + + +TITANIA +Then I must be thy lady: but I know +When thou hast stolen away from fairy land, +And in the shape of Corin sat all day, +Playing on pipes of corn and versing love +To amorous Phillida. Why art thou here, +Come from the farthest Steppe of India? +But that, forsooth, the bouncing Amazon, +Your buskin'd mistress and your warrior love, +To Theseus must be wedded, and you come +To give their bed joy and prosperity. + + + +OBERON +How canst thou thus for shame, Titania, +Glance at my credit with Hippolyta, +Knowing I know thy love to Theseus? +Didst thou not lead him through the glimmering night +From Perigenia, whom he ravished? +And make him with fair AEgle break his faith, +With Ariadne and Antiopa? + + + +TITANIA +These are the forgeries of jealousy: +And never, since the middle summer's spring, +Met we on hill, in dale, forest or mead, +By paved fountain or by rushy brook, +Or in the beached margent of the sea, +To dance our ringlets to the whistling wind, +But with thy brawls thou hast disturb'd our sport. +Therefore the winds, piping to us in vain, +As in revenge, have suck'd up from the sea +Contagious fogs; which falling in the land +Have every pelting river made so proud +That they have overborne their continents: +The ox hath therefore stretch'd his yoke in vain, +The ploughman lost his sweat, and the green corn +Hath rotted ere his youth attain'd a beard; +The fold stands empty in the drowned field, +And crows are fatted with the murrion flock; +The nine men's morris is fill'd up with mud, +And the quaint mazes in the wanton green +For lack of tread are undistinguishable: +The human mortals want their winter here; +No night is now with hymn or carol blest: +Therefore the moon, the governess of floods, +Pale in her anger, washes all the air, +That rheumatic diseases do abound: +And thorough this distemperature we see +The seasons alter: hoary-headed frosts +Far in the fresh lap of the crimson rose, +And on old Hiems' thin and icy crown +An odorous chaplet of sweet summer buds +Is, as in mockery, set: the spring, the summer, +The childing autumn, angry winter, change +Their wonted liveries, and the mazed world, +By their increase, now knows not which is which: +And this same progeny of evils comes +From our debate, from our dissension; +We are their parents and original. + + + +OBERON +Do you amend it then; it lies in you: +Why should Titania cross her Oberon? +I do but beg a little changeling boy, +To be my henchman. + + + +TITANIA +Set your heart at rest: +The fairy land buys not the child of me. +His mother was a votaress of my order: +And, in the spiced Indian air, by night, +Full often hath she gossip'd by my side, +And sat with me on Neptune's yellow sands, +Marking the embarked traders on the flood, +When we have laugh'd to see the sails conceive +And grow big-bellied with the wanton wind; +Which she, with pretty and with swimming gait +Following,--her womb then rich with my young squire,-- +Would imitate, and sail upon the land, +To fetch me trifles, and return again, +As from a voyage, rich with merchandise. +But she, being mortal, of that boy did die; +And for her sake do I rear up her boy, +And for her sake I will not part with him. + + + +OBERON +How long within this wood intend you stay? + + + +TITANIA +Perchance till after Theseus' wedding-day. +If you will patiently dance in our round +And see our moonlight revels, go with us; +If not, shun me, and I will spare your haunts. + + + +OBERON +Give me that boy, and I will go with thee. + + + +TITANIA +Not for thy fairy kingdom. Fairies, away! +We shall chide downright, if I longer stay. + + + +Exit TITANIA with her train + + +OBERON +Well, go thy way: thou shalt not from this grove +Till I torment thee for this injury. +My gentle Puck, come hither. Thou rememberest +Since once I sat upon a promontory, +And heard a mermaid on a dolphin's back +Uttering such dulcet and harmonious breath +That the rude sea grew civil at her song +And certain stars shot madly from their spheres, +To hear the sea-maid's music. + + + +PUCK +I remember. + + + +OBERON +That very time I saw, but thou couldst not, +Flying between the cold moon and the earth, +Cupid all arm'd: a certain aim he took +At a fair vestal throned by the west, +And loosed his love-shaft smartly from his bow, +As it should pierce a hundred thousand hearts; +But I might see young Cupid's fiery shaft +Quench'd in the chaste beams of the watery moon, +And the imperial votaress passed on, +In maiden meditation, fancy-free. +Yet mark'd I where the bolt of Cupid fell: +It fell upon a little western flower, +Before milk-white, now purple with love's wound, +And maidens call it love-in-idleness. +Fetch me that flower; the herb I shew'd thee once: +The juice of it on sleeping eye-lids laid +Will make or man or woman madly dote +Upon the next live creature that it sees. +Fetch me this herb; and be thou here again +Ere the leviathan can swim a league. + + + +PUCK +I'll put a girdle round about the earth +In forty minutes. + + + +Exit + + +OBERON +Having once this juice, +I'll watch Titania when she is asleep, +And drop the liquor of it in her eyes. +The next thing then she waking looks upon, +Be it on lion, bear, or wolf, or bull, +On meddling monkey, or on busy ape, +She shall pursue it with the soul of love: +And ere I take this charm from off her sight, +As I can take it with another herb, +I'll make her render up her page to me. +But who comes here? I am invisible; +And I will overhear their conference. + + + +Enter DEMETRIUS, HELENA, following him + + +DEMETRIUS +I love thee not, therefore pursue me not. +Where is Lysander and fair Hermia? +The one I'll slay, the other slayeth me. +Thou told'st me they were stolen unto this wood; +And here am I, and wode within this wood, +Because I cannot meet my Hermia. +Hence, get thee gone, and follow me no more. + + + +HELENA +You draw me, you hard-hearted adamant; +But yet you draw not iron, for my heart +Is true as steel: leave you your power to draw, +And I shall have no power to follow you. + + + +DEMETRIUS +Do I entice you? do I speak you fair? +Or, rather, do I not in plainest truth +Tell you, I do not, nor I cannot love you? + + + +HELENA +And even for that do I love you the more. +I am your spaniel; and, Demetrius, +The more you beat me, I will fawn on you: +Use me but as your spaniel, spurn me, strike me, +Neglect me, lose me; only give me leave, +Unworthy as I am, to follow you. +What worser place can I beg in your love,-- +And yet a place of high respect with me,-- +Than to be used as you use your dog? + + + +DEMETRIUS +Tempt not too much the hatred of my spirit; +For I am sick when I do look on thee. + + + +HELENA +And I am sick when I look not on you. + + + +DEMETRIUS +You do impeach your modesty too much, +To leave the city and commit yourself +Into the hands of one that loves you not; +To trust the opportunity of night +And the ill counsel of a desert place +With the rich worth of your virginity. + + + +HELENA +Your virtue is my privilege: for that +It is not night when I do see your face, +Therefore I think I am not in the night; +Nor doth this wood lack worlds of company, +For you in my respect are all the world: +Then how can it be said I am alone, +When all the world is here to look on me? + + + +DEMETRIUS +I'll run from thee and hide me in the brakes, +And leave thee to the mercy of wild beasts. + + + +HELENA +The wildest hath not such a heart as you. +Run when you will, the story shall be changed: +Apollo flies, and Daphne holds the chase; +The dove pursues the griffin; the mild hind +Makes speed to catch the tiger; bootless speed, +When cowardice pursues and valour flies. + + + +DEMETRIUS +I will not stay thy questions; let me go: +Or, if thou follow me, do not believe +But I shall do thee mischief in the wood. + + + +HELENA +Ay, in the temple, in the town, the field, +You do me mischief. Fie, Demetrius! +Your wrongs do set a scandal on my sex: +We cannot fight for love, as men may do; +We should be wood and were not made to woo. +Exit DEMETRIUS +I'll follow thee and make a heaven of hell, +To die upon the hand I love so well. + + + +Exit + + +OBERON +Fare thee well, nymph: ere he do leave this grove, +Thou shalt fly him and he shall seek thy love. +Re-enter PUCK +Hast thou the flower there? Welcome, wanderer. + + + +PUCK +Ay, there it is. + + + +OBERON +I pray thee, give it me. +I know a bank where the wild thyme blows, +Where oxlips and the nodding violet grows, +Quite over-canopied with luscious woodbine, +With sweet musk-roses and with eglantine: +There sleeps Titania sometime of the night, +Lull'd in these flowers with dances and delight; +And there the snake throws her enamell'd skin, +Weed wide enough to wrap a fairy in: +And with the juice of this I'll streak her eyes, +And make her full of hateful fantasies. +Take thou some of it, and seek through this grove: +A sweet Athenian lady is in love +With a disdainful youth: anoint his eyes; +But do it when the next thing he espies +May be the lady: thou shalt know the man +By the Athenian garments he hath on. +Effect it with some care, that he may prove +More fond on her than she upon her love: +And look thou meet me ere the first cock crow. + + + +PUCK +Fear not, my lord, your servant shall do so. + + + +Exeunt + + +SCENE II. Another part of the wood. +Enter TITANIA, with her train + + +TITANIA +Come, now a roundel and a fairy song; +Then, for the third part of a minute, hence; +Some to kill cankers in the musk-rose buds, +Some war with rere-mice for their leathern wings, +To make my small elves coats, and some keep back +The clamorous owl that nightly hoots and wonders +At our quaint spirits. Sing me now asleep; +Then to your offices and let me rest. +The Fairies sing +You spotted snakes with double tongue, +Thorny hedgehogs, be not seen; +Newts and blind-worms, do no wrong, +Come not near our fairy queen. +Philomel, with melody +Sing in our sweet lullaby; +Lulla, lulla, lullaby, lulla, lulla, lullaby: +Never harm, +Nor spell nor charm, +Come our lovely lady nigh; +So, good night, with lullaby. +Weaving spiders, come not here; +Hence, you long-legg'd spinners, hence! +Beetles black, approach not near; +Worm nor snail, do no offence. +Philomel, with melody, &c. + + + +Fairy +Hence, away! now all is well: +One aloof stand sentinel. + + +Exeunt Fairies. TITANIA sleeps +Enter OBERON and squeezes the flower on TITANIA's eyelids + + +OBERON +What thou seest when thou dost wake, +Do it for thy true-love take, +Love and languish for his sake: +Be it ounce, or cat, or bear, +Pard, or boar with bristled hair, +In thy eye that shall appear +When thou wakest, it is thy dear: +Wake when some vile thing is near. + + +Exit +Enter LYSANDER and HERMIA + + +LYSANDER +Fair love, you faint with wandering in the wood; +And to speak troth, I have forgot our way: +We'll rest us, Hermia, if you think it good, +And tarry for the comfort of the day. + + + +HERMIA +Be it so, Lysander: find you out a bed; +For I upon this bank will rest my head. + + + +LYSANDER +One turf shall serve as pillow for us both; +One heart, one bed, two bosoms and one troth. + + + +HERMIA +Nay, good Lysander; for my sake, my dear, +Lie further off yet, do not lie so near. + + + +LYSANDER +O, take the sense, sweet, of my innocence! +Love takes the meaning in love's conference. +I mean, that my heart unto yours is knit +So that but one heart we can make of it; +Two bosoms interchained with an oath; +So then two bosoms and a single troth. +Then by your side no bed-room me deny; +For lying so, Hermia, I do not lie. + + + +HERMIA +Lysander riddles very prettily: +Now much beshrew my manners and my pride, +If Hermia meant to say Lysander lied. +But, gentle friend, for love and courtesy +Lie further off; in human modesty, +Such separation as may well be said +Becomes a virtuous bachelor and a maid, +So far be distant; and, good night, sweet friend: +Thy love ne'er alter till thy sweet life end! + + + +LYSANDER +Amen, amen, to that fair prayer, say I; +And then end life when I end loyalty! +Here is my bed: sleep give thee all his rest! + + + +HERMIA +With half that wish the wisher's eyes be press'd! + + +They sleep +Enter PUCK + + +PUCK +Through the forest have I gone. +But Athenian found I none, +On whose eyes I might approve +This flower's force in stirring love. +Night and silence.--Who is here? +Weeds of Athens he doth wear: +This is he, my master said, +Despised the Athenian maid; +And here the maiden, sleeping sound, +On the dank and dirty ground. +Pretty soul! she durst not lie +Near this lack-love, this kill-courtesy. +Churl, upon thy eyes I throw +All the power this charm doth owe. +When thou wakest, let love forbid +Sleep his seat on thy eyelid: +So awake when I am gone; +For I must now to Oberon. + + +Exit +Enter DEMETRIUS and HELENA, running + + +HELENA +Stay, though thou kill me, sweet Demetrius. + + + +DEMETRIUS +I charge thee, hence, and do not haunt me thus. + + + +HELENA +O, wilt thou darkling leave me? do not so. + + + +DEMETRIUS +Stay, on thy peril: I alone will go. + + + +Exit + + +HELENA +O, I am out of breath in this fond chase! +The more my prayer, the lesser is my grace. +Happy is Hermia, wheresoe'er she lies; +For she hath blessed and attractive eyes. +How came her eyes so bright? Not with salt tears: +If so, my eyes are oftener wash'd than hers. +No, no, I am as ugly as a bear; +For beasts that meet me run away for fear: +Therefore no marvel though Demetrius +Do, as a monster fly my presence thus. +What wicked and dissembling glass of mine +Made me compare with Hermia's sphery eyne? +But who is here? Lysander! on the ground! +Dead? or asleep? I see no blood, no wound. +Lysander if you live, good sir, awake. + + + +LYSANDER +Awaking And run through fire I will for thy sweet sake. +Transparent Helena! Nature shows art, +That through thy bosom makes me see thy heart. +Where is Demetrius? O, how fit a word +Is that vile name to perish on my sword! + + + +HELENA +Do not say so, Lysander; say not so +What though he love your Hermia? Lord, what though? +Yet Hermia still loves you: then be content. + + + +LYSANDER +Content with Hermia! No; I do repent +The tedious minutes I with her have spent. +Not Hermia but Helena I love: +Who will not change a raven for a dove? +The will of man is by his reason sway'd; +And reason says you are the worthier maid. +Things growing are not ripe until their season +So I, being young, till now ripe not to reason; +And touching now the point of human skill, +Reason becomes the marshal to my will +And leads me to your eyes, where I o'erlook +Love's stories written in love's richest book. + + + +HELENA +Wherefore was I to this keen mockery born? +When at your hands did I deserve this scorn? +Is't not enough, is't not enough, young man, +That I did never, no, nor never can, +Deserve a sweet look from Demetrius' eye, +But you must flout my insufficiency? +Good troth, you do me wrong, good sooth, you do, +In such disdainful manner me to woo. +But fare you well: perforce I must confess +I thought you lord of more true gentleness. +O, that a lady, of one man refused. +Should of another therefore be abused! + + + +Exit + + +LYSANDER +She sees not Hermia. Hermia, sleep thou there: +And never mayst thou come Lysander near! +For as a surfeit of the sweetest things +The deepest loathing to the stomach brings, +Or as tie heresies that men do leave +Are hated most of those they did deceive, +So thou, my surfeit and my heresy, +Of all be hated, but the most of me! +And, all my powers, address your love and might +To honour Helen and to be her knight! + + + +Exit + + +HERMIA +Awaking Help me, Lysander, help me! do thy best +To pluck this crawling serpent from my breast! +Ay me, for pity! what a dream was here! +Lysander, look how I do quake with fear: +Methought a serpent eat my heart away, +And you sat smiling at his cruel pray. +Lysander! what, removed? Lysander! lord! +What, out of hearing? gone? no sound, no word? +Alack, where are you speak, an if you hear; +Speak, of all loves! I swoon almost with fear. +No? then I well perceive you all not nigh +Either death or you I'll find immediately. + + + +Exit + + + + +ACT III + +SCENE I. The wood. TITANIA lying asleep. +Enter QUINCE, SNUG, BOTTOM, FLUTE, SNOUT, and +STARVELING + + +BOTTOM +Are we all met? + + + +QUINCE +Pat, pat; and here's a marvellous convenient place +for our rehearsal. This green plot shall be our +stage, this hawthorn-brake our tiring-house; and we +will do it in action as we will do it before the duke. + + + +BOTTOM +Peter Quince,-- + + + +QUINCE +What sayest thou, bully Bottom? + + + +BOTTOM +There are things in this comedy of Pyramus and +Thisby that will never please. First, Pyramus must +draw a sword to kill himself; which the ladies +cannot abide. How answer you that? + + + +SNOUT +By'r lakin, a parlous fear. + + + +STARVELING +I believe we must leave the killing out, when all is done. + + + +BOTTOM +Not a whit: I have a device to make all well. +Write me a prologue; and let the prologue seem to +say, we will do no harm with our swords, and that +Pyramus is not killed indeed; and, for the more +better assurance, tell them that I, Pyramus, am not +Pyramus, but Bottom the weaver: this will put them +out of fear. + + + +QUINCE +Well, we will have such a prologue; and it shall be +written in eight and six. + + + +BOTTOM +No, make it two more; let it be written in eight and eight. + + + +SNOUT +Will not the ladies be afeard of the lion? + + + +STARVELING +I fear it, I promise you. + + + +BOTTOM +Masters, you ought to consider with yourselves: to +bring in--God shield us!--a lion among ladies, is a +most dreadful thing; for there is not a more fearful +wild-fowl than your lion living; and we ought to +look to 't. + + + +SNOUT +Therefore another prologue must tell he is not a lion. + + + +BOTTOM +Nay, you must name his name, and half his face must +be seen through the lion's neck: and he himself +must speak through, saying thus, or to the same +defect,--'Ladies,'--or 'Fair-ladies--I would wish +You,'--or 'I would request you,'--or 'I would +entreat you,--not to fear, not to tremble: my life +for yours. If you think I come hither as a lion, it +were pity of my life: no I am no such thing; I am a +man as other men are;' and there indeed let him name +his name, and tell them plainly he is Snug the joiner. + + + +QUINCE +Well it shall be so. But there is two hard things; +that is, to bring the moonlight into a chamber; for, +you know, Pyramus and Thisby meet by moonlight. + + + +SNOUT +Doth the moon shine that night we play our play? + + + +BOTTOM +A calendar, a calendar! look in the almanac; find +out moonshine, find out moonshine. + + + +QUINCE +Yes, it doth shine that night. + + + +BOTTOM +Why, then may you leave a casement of the great +chamber window, where we play, open, and the moon +may shine in at the casement. + + + +QUINCE +Ay; or else one must come in with a bush of thorns +and a lanthorn, and say he comes to disfigure, or to +present, the person of Moonshine. Then, there is +another thing: we must have a wall in the great +chamber; for Pyramus and Thisby says the story, did +talk through the chink of a wall. + + + +SNOUT +You can never bring in a wall. What say you, Bottom? + + + +BOTTOM +Some man or other must present Wall: and let him +have some plaster, or some loam, or some rough-cast +about him, to signify wall; and let him hold his +fingers thus, and through that cranny shall Pyramus +and Thisby whisper. + + + +QUINCE +If that may be, then all is well. Come, sit down, +every mother's son, and rehearse your parts. +Pyramus, you begin: when you have spoken your +speech, enter into that brake: and so every one +according to his cue. + + + +Enter PUCK behind + + +PUCK +What hempen home-spuns have we swaggering here, +So near the cradle of the fairy queen? +What, a play toward! I'll be an auditor; +An actor too, perhaps, if I see cause. + + + +QUINCE +Speak, Pyramus. Thisby, stand forth. + + + +BOTTOM +Thisby, the flowers of odious savours sweet,-- + + + +QUINCE +Odours, odours. + + + +BOTTOM +--odours savours sweet: +So hath thy breath, my dearest Thisby dear. +But hark, a voice! stay thou but here awhile, +And by and by I will to thee appear. + + + +Exit + + +PUCK +A stranger Pyramus than e'er played here. + + + +Exit + + +FLUTE +Must I speak now? + + + +QUINCE +Ay, marry, must you; for you must understand he goes +but to see a noise that he heard, and is to come again. + + + +FLUTE +Most radiant Pyramus, most lily-white of hue, +Of colour like the red rose on triumphant brier, +Most brisky juvenal and eke most lovely Jew, +As true as truest horse that yet would never tire, +I'll meet thee, Pyramus, at Ninny's tomb. + + + +QUINCE +'Ninus' tomb,' man: why, you must not speak that +yet; that you answer to Pyramus: you speak all your +part at once, cues and all Pyramus enter: your cue +is past; it is, 'never tire.' + + + +FLUTE +O,--As true as truest horse, that yet would +never tire. + + + +Re-enter PUCK, and BOTTOM with an ass's head + + +BOTTOM +If I were fair, Thisby, I were only thine. + + + +QUINCE +O monstrous! O strange! we are haunted. Pray, +masters! fly, masters! Help! + + + +Exeunt QUINCE, SNUG, FLUTE, SNOUT, and STARVELING + + +PUCK +I'll follow you, I'll lead you about a round, +Through bog, through bush, through brake, through brier: +Sometime a horse I'll be, sometime a hound, +A hog, a headless bear, sometime a fire; +And neigh, and bark, and grunt, and roar, and burn, +Like horse, hound, hog, bear, fire, at every turn. + + + +Exit + + +BOTTOM +Why do they run away? this is a knavery of them to +make me afeard. + + + +Re-enter SNOUT + + +SNOUT +O Bottom, thou art changed! what do I see on thee? + + + +BOTTOM +What do you see? you see an asshead of your own, do +you? + + +Exit SNOUT +Re-enter QUINCE + + +QUINCE +Bless thee, Bottom! bless thee! thou art +translated. + + + +Exit + + +BOTTOM +I see their knavery: this is to make an ass of me; +to fright me, if they could. But I will not stir +from this place, do what they can: I will walk up +and down here, and I will sing, that they shall hear +I am not afraid. +Sings +The ousel cock so black of hue, +With orange-tawny bill, +The throstle with his note so true, +The wren with little quill,-- + + + +TITANIA +Awaking What angel wakes me from my flowery bed? + + + +BOTTOM +Sings +The finch, the sparrow and the lark, +The plain-song cuckoo gray, +Whose note full many a man doth mark, +And dares not answer nay;-- +for, indeed, who would set his wit to so foolish +a bird? who would give a bird the lie, though he cry +'cuckoo' never so? + + + +TITANIA +I pray thee, gentle mortal, sing again: +Mine ear is much enamour'd of thy note; +So is mine eye enthralled to thy shape; +And thy fair virtue's force perforce doth move me +On the first view to say, to swear, I love thee. + + + +BOTTOM +Methinks, mistress, you should have little reason +for that: and yet, to say the truth, reason and +love keep little company together now-a-days; the +more the pity that some honest neighbours will not +make them friends. Nay, I can gleek upon occasion. + + + +TITANIA +Thou art as wise as thou art beautiful. + + + +BOTTOM +Not so, neither: but if I had wit enough to get out +of this wood, I have enough to serve mine own turn. + + + +TITANIA +Out of this wood do not desire to go: +Thou shalt remain here, whether thou wilt or no. +I am a spirit of no common rate; +The summer still doth tend upon my state; +And I do love thee: therefore, go with me; +I'll give thee fairies to attend on thee, +And they shall fetch thee jewels from the deep, +And sing while thou on pressed flowers dost sleep; +And I will purge thy mortal grossness so +That thou shalt like an airy spirit go. +Peaseblossom! Cobweb! Moth! and Mustardseed! + + + +Enter PEASEBLOSSOM, COBWEB, MOTH, and MUSTARDSEED + + +PEASEBLOSSOM +Ready. + + + +COBWEB +And I. + + + +MOTH +And I. + + + +MUSTARDSEED +And I. + + + +ALL +Where shall we go? + + + +TITANIA +Be kind and courteous to this gentleman; +Hop in his walks and gambol in his eyes; +Feed him with apricocks and dewberries, +With purple grapes, green figs, and mulberries; +The honey-bags steal from the humble-bees, +And for night-tapers crop their waxen thighs +And light them at the fiery glow-worm's eyes, +To have my love to bed and to arise; +And pluck the wings from Painted butterflies +To fan the moonbeams from his sleeping eyes: +Nod to him, elves, and do him courtesies. + + + +PEASEBLOSSOM +Hail, mortal! + + + +COBWEB +Hail! + + + +MOTH +Hail! + + + +MUSTARDSEED +Hail! + + + +BOTTOM +I cry your worship's mercy, heartily: I beseech your +worship's name. + + + +COBWEB +Cobweb. + + + +BOTTOM +I shall desire you of more acquaintance, good Master +Cobweb: if I cut my finger, I shall make bold with +you. Your name, honest gentleman? + + + +PEASEBLOSSOM +Peaseblossom. + + + +BOTTOM +I pray you, commend me to Mistress Squash, your +mother, and to Master Peascod, your father. Good +Master Peaseblossom, I shall desire you of more +acquaintance too. Your name, I beseech you, sir? + + + +MUSTARDSEED +Mustardseed. + + + +BOTTOM +Good Master Mustardseed, I know your patience well: +that same cowardly, giant-like ox-beef hath +devoured many a gentleman of your house: I promise +you your kindred had made my eyes water ere now. I +desire your more acquaintance, good Master +Mustardseed. + + + +TITANIA +Come, wait upon him; lead him to my bower. +The moon methinks looks with a watery eye; +And when she weeps, weeps every little flower, +Lamenting some enforced chastity. +Tie up my love's tongue bring him silently. + + + +Exeunt + + +SCENE II. Another part of the wood. +Enter OBERON + + +OBERON +I wonder if Titania be awaked; +Then, what it was that next came in her eye, +Which she must dote on in extremity. +Enter PUCK +Here comes my messenger. +How now, mad spirit! +What night-rule now about this haunted grove? + + + +PUCK +My mistress with a monster is in love. +Near to her close and consecrated bower, +While she was in her dull and sleeping hour, +A crew of patches, rude mechanicals, +That work for bread upon Athenian stalls, +Were met together to rehearse a play +Intended for great Theseus' nuptial-day. +The shallowest thick-skin of that barren sort, +Who Pyramus presented, in their sport +Forsook his scene and enter'd in a brake +When I did him at this advantage take, +An ass's nole I fixed on his head: +Anon his Thisbe must be answered, +And forth my mimic comes. When they him spy, +As wild geese that the creeping fowler eye, +Or russet-pated choughs, many in sort, +Rising and cawing at the gun's report, +Sever themselves and madly sweep the sky, +So, at his sight, away his fellows fly; +And, at our stamp, here o'er and o'er one falls; +He murder cries and help from Athens calls. +Their sense thus weak, lost with their fears +thus strong, +Made senseless things begin to do them wrong; +For briers and thorns at their apparel snatch; +Some sleeves, some hats, from yielders all +things catch. +I led them on in this distracted fear, +And left sweet Pyramus translated there: +When in that moment, so it came to pass, +Titania waked and straightway loved an ass. + + + +OBERON +This falls out better than I could devise. +But hast thou yet latch'd the Athenian's eyes +With the love-juice, as I did bid thee do? + + + +PUCK +I took him sleeping,--that is finish'd too,-- +And the Athenian woman by his side: +That, when he waked, of force she must be eyed. + + + +Enter HERMIA and DEMETRIUS + + +OBERON +Stand close: this is the same Athenian. + + + +PUCK +This is the woman, but not this the man. + + + +DEMETRIUS +O, why rebuke you him that loves you so? +Lay breath so bitter on your bitter foe. + + + +HERMIA +Now I but chide; but I should use thee worse, +For thou, I fear, hast given me cause to curse, +If thou hast slain Lysander in his sleep, +Being o'er shoes in blood, plunge in the deep, +And kill me too. +The sun was not so true unto the day +As he to me: would he have stolen away +From sleeping Hermia? I'll believe as soon +This whole earth may be bored and that the moon +May through the centre creep and so displease +Her brother's noontide with Antipodes. +It cannot be but thou hast murder'd him; +So should a murderer look, so dead, so grim. + + + +DEMETRIUS +So should the murder'd look, and so should I, +Pierced through the heart with your stern cruelty: +Yet you, the murderer, look as bright, as clear, +As yonder Venus in her glimmering sphere. + + + +HERMIA +What's this to my Lysander? where is he? +Ah, good Demetrius, wilt thou give him me? + + + +DEMETRIUS +I had rather give his carcass to my hounds. + + + +HERMIA +Out, dog! out, cur! thou drivest me past the bounds +Of maiden's patience. Hast thou slain him, then? +Henceforth be never number'd among men! +O, once tell true, tell true, even for my sake! +Durst thou have look'd upon him being awake, +And hast thou kill'd him sleeping? O brave touch! +Could not a worm, an adder, do so much? +An adder did it; for with doubler tongue +Than thine, thou serpent, never adder stung. + + + +DEMETRIUS +You spend your passion on a misprised mood: +I am not guilty of Lysander's blood; +Nor is he dead, for aught that I can tell. + + + +HERMIA +I pray thee, tell me then that he is well. + + + +DEMETRIUS +An if I could, what should I get therefore? + + + +HERMIA +A privilege never to see me more. +And from thy hated presence part I so: +See me no more, whether he be dead or no. + + + +Exit + + +DEMETRIUS +There is no following her in this fierce vein: +Here therefore for a while I will remain. +So sorrow's heaviness doth heavier grow +For debt that bankrupt sleep doth sorrow owe: +Which now in some slight measure it will pay, +If for his tender here I make some stay. + + + +Lies down and sleeps + + +OBERON +What hast thou done? thou hast mistaken quite +And laid the love-juice on some true-love's sight: +Of thy misprision must perforce ensue +Some true love turn'd and not a false turn'd true. + + + +PUCK +Then fate o'er-rules, that, one man holding troth, +A million fail, confounding oath on oath. + + + +OBERON +About the wood go swifter than the wind, +And Helena of Athens look thou find: +All fancy-sick she is and pale of cheer, +With sighs of love, that costs the fresh blood dear: +By some illusion see thou bring her here: +I'll charm his eyes against she do appear. + + + +PUCK +I go, I go; look how I go, +Swifter than arrow from the Tartar's bow. + + + +Exit + + +OBERON +Flower of this purple dye, +Hit with Cupid's archery, +Sink in apple of his eye. +When his love he doth espy, +Let her shine as gloriously +As the Venus of the sky. +When thou wakest, if she be by, +Beg of her for remedy. + + + +Re-enter PUCK + + +PUCK +Captain of our fairy band, +Helena is here at hand; +And the youth, mistook by me, +Pleading for a lover's fee. +Shall we their fond pageant see? +Lord, what fools these mortals be! + + + +OBERON +Stand aside: the noise they make +Will cause Demetrius to awake. + + + +PUCK +Then will two at once woo one; +That must needs be sport alone; +And those things do best please me +That befal preposterously. + + + +Enter LYSANDER and HELENA + + +LYSANDER +Why should you think that I should woo in scorn? +Scorn and derision never come in tears: +Look, when I vow, I weep; and vows so born, +In their nativity all truth appears. +How can these things in me seem scorn to you, +Bearing the badge of faith, to prove them true? + + + +HELENA +You do advance your cunning more and more. +When truth kills truth, O devilish-holy fray! +These vows are Hermia's: will you give her o'er? +Weigh oath with oath, and you will nothing weigh: +Your vows to her and me, put in two scales, +Will even weigh, and both as light as tales. + + + +LYSANDER +I had no judgment when to her I swore. + + + +HELENA +Nor none, in my mind, now you give her o'er. + + + +LYSANDER +Demetrius loves her, and he loves not you. + + + +DEMETRIUS +Awaking O Helena, goddess, nymph, perfect, divine! +To what, my love, shall I compare thine eyne? +Crystal is muddy. O, how ripe in show +Thy lips, those kissing cherries, tempting grow! +That pure congealed white, high Taurus snow, +Fann'd with the eastern wind, turns to a crow +When thou hold'st up thy hand: O, let me kiss +This princess of pure white, this seal of bliss! + + + +HELENA +O spite! O hell! I see you all are bent +To set against me for your merriment: +If you we re civil and knew courtesy, +You would not do me thus much injury. +Can you not hate me, as I know you do, +But you must join in souls to mock me too? +If you were men, as men you are in show, +You would not use a gentle lady so; +To vow, and swear, and superpraise my parts, +When I am sure you hate me with your hearts. +You both are rivals, and love Hermia; +And now both rivals, to mock Helena: +A trim exploit, a manly enterprise, +To conjure tears up in a poor maid's eyes +With your derision! none of noble sort +Would so offend a virgin, and extort +A poor soul's patience, all to make you sport. + + + +LYSANDER +You are unkind, Demetrius; be not so; +For you love Hermia; this you know I know: +And here, with all good will, with all my heart, +In Hermia's love I yield you up my part; +And yours of Helena to me bequeath, +Whom I do love and will do till my death. + + + +HELENA +Never did mockers waste more idle breath. + + + +DEMETRIUS +Lysander, keep thy Hermia; I will none: +If e'er I loved her, all that love is gone. +My heart to her but as guest-wise sojourn'd, +And now to Helen is it home return'd, +There to remain. + + + +LYSANDER +Helen, it is not so. + + + +DEMETRIUS +Disparage not the faith thou dost not know, +Lest, to thy peril, thou aby it dear. +Look, where thy love comes; yonder is thy dear. + + + +Re-enter HERMIA + + +HERMIA +Dark night, that from the eye his function takes, +The ear more quick of apprehension makes; +Wherein it doth impair the seeing sense, +It pays the hearing double recompense. +Thou art not by mine eye, Lysander, found; +Mine ear, I thank it, brought me to thy sound +But why unkindly didst thou leave me so? + + + +LYSANDER +Why should he stay, whom love doth press to go? + + + +HERMIA +What love could press Lysander from my side? + + + +LYSANDER +Lysander's love, that would not let him bide, +Fair Helena, who more engilds the night +Than all you fiery oes and eyes of light. +Why seek'st thou me? could not this make thee know, +The hate I bear thee made me leave thee so? + + + +HERMIA +You speak not as you think: it cannot be. + + + +HELENA +Lo, she is one of this confederacy! +Now I perceive they have conjoin'd all three +To fashion this false sport, in spite of me. +Injurious Hermia! most ungrateful maid! +Have you conspired, have you with these contrived +To bait me with this foul derision? +Is all the counsel that we two have shared, +The sisters' vows, the hours that we have spent, +When we have chid the hasty-footed time +For parting us,--O, is it all forgot? +All school-days' friendship, childhood innocence? +We, Hermia, like two artificial gods, +Have with our needles created both one flower, +Both on one sampler, sitting on one cushion, +Both warbling of one song, both in one key, +As if our hands, our sides, voices and minds, +Had been incorporate. So we grow together, +Like to a double cherry, seeming parted, +But yet an union in partition; +Two lovely berries moulded on one stem; +So, with two seeming bodies, but one heart; +Two of the first, like coats in heraldry, +Due but to one and crowned with one crest. +And will you rent our ancient love asunder, +To join with men in scorning your poor friend? +It is not friendly, 'tis not maidenly: +Our sex, as well as I, may chide you for it, +Though I alone do feel the injury. + + + +HERMIA +I am amazed at your passionate words. +I scorn you not: it seems that you scorn me. + + + +HELENA +Have you not set Lysander, as in scorn, +To follow me and praise my eyes and face? +And made your other love, Demetrius, +Who even but now did spurn me with his foot, +To call me goddess, nymph, divine and rare, +Precious, celestial? Wherefore speaks he this +To her he hates? and wherefore doth Lysander +Deny your love, so rich within his soul, +And tender me, forsooth, affection, +But by your setting on, by your consent? +What thought I be not so in grace as you, +So hung upon with love, so fortunate, +But miserable most, to love unloved? +This you should pity rather than despise. + + + +HERNIA +I understand not what you mean by this. + + + +HELENA +Ay, do, persever, counterfeit sad looks, +Make mouths upon me when I turn my back; +Wink each at other; hold the sweet jest up: +This sport, well carried, shall be chronicled. +If you have any pity, grace, or manners, +You would not make me such an argument. +But fare ye well: 'tis partly my own fault; +Which death or absence soon shall remedy. + + + +LYSANDER +Stay, gentle Helena; hear my excuse: +My love, my life my soul, fair Helena! + + + +HELENA +O excellent! + + + +HERMIA +Sweet, do not scorn her so. + + + +DEMETRIUS +If she cannot entreat, I can compel. + + + +LYSANDER +Thou canst compel no more than she entreat: +Thy threats have no more strength than her weak prayers. +Helen, I love thee; by my life, I do: +I swear by that which I will lose for thee, +To prove him false that says I love thee not. + + + +DEMETRIUS +I say I love thee more than he can do. + + + +LYSANDER +If thou say so, withdraw, and prove it too. + + + +DEMETRIUS +Quick, come! + + + +HERMIA +Lysander, whereto tends all this? + + + +LYSANDER +Away, you Ethiope! + + + +DEMETRIUS +No, no; he'll +Seem to break loose; take on as you would follow, +But yet come not: you are a tame man, go! + + + +LYSANDER +Hang off, thou cat, thou burr! vile thing, let loose, +Or I will shake thee from me like a serpent! + + + +HERMIA +Why are you grown so rude? what change is this? +Sweet love,-- + + + +LYSANDER +Thy love! out, tawny Tartar, out! +Out, loathed medicine! hated potion, hence! + + + +HERMIA +Do you not jest? + + + +HELENA +Yes, sooth; and so do you. + + + +LYSANDER +Demetrius, I will keep my word with thee. + + + +DEMETRIUS +I would I had your bond, for I perceive +A weak bond holds you: I'll not trust your word. + + + +LYSANDER +What, should I hurt her, strike her, kill her dead? +Although I hate her, I'll not harm her so. + + + +HERMIA +What, can you do me greater harm than hate? +Hate me! wherefore? O me! what news, my love! +Am not I Hermia? are not you Lysander? +I am as fair now as I was erewhile. +Since night you loved me; yet since night you left +me: +Why, then you left me--O, the gods forbid!-- +In earnest, shall I say? + + + +LYSANDER +Ay, by my life; +And never did desire to see thee more. +Therefore be out of hope, of question, of doubt; +Be certain, nothing truer; 'tis no jest +That I do hate thee and love Helena. + + + +HERMIA +O me! you juggler! you canker-blossom! +You thief of love! what, have you come by night +And stolen my love's heart from him? + + + +HELENA +Fine, i'faith! +Have you no modesty, no maiden shame, +No touch of bashfulness? What, will you tear +Impatient answers from my gentle tongue? +Fie, fie! you counterfeit, you puppet, you! + + + +HERMIA +Puppet? why so? ay, that way goes the game. +Now I perceive that she hath made compare +Between our statures; she hath urged her height; +And with her personage, her tall personage, +Her height, forsooth, she hath prevail'd with him. +And are you grown so high in his esteem; +Because I am so dwarfish and so low? +How low am I, thou painted maypole? speak; +How low am I? I am not yet so low +But that my nails can reach unto thine eyes. + + + +HELENA +I pray you, though you mock me, gentlemen, +Let her not hurt me: I was never curst; +I have no gift at all in shrewishness; +I am a right maid for my cowardice: +Let her not strike me. You perhaps may think, +Because she is something lower than myself, +That I can match her. + + + +HERMIA +Lower! hark, again. + + + +HELENA +Good Hermia, do not be so bitter with me. +I evermore did love you, Hermia, +Did ever keep your counsels, never wrong'd you; +Save that, in love unto Demetrius, +I told him of your stealth unto this wood. +He follow'd you; for love I follow'd him; +But he hath chid me hence and threaten'd me +To strike me, spurn me, nay, to kill me too: +And now, so you will let me quiet go, +To Athens will I bear my folly back +And follow you no further: let me go: +You see how simple and how fond I am. + + + +HERMIA +Why, get you gone: who is't that hinders you? + + + +HELENA +A foolish heart, that I leave here behind. + + + +HERMIA +What, with Lysander? + + + +HELENA +With Demetrius. + + + +LYSANDER +Be not afraid; she shall not harm thee, Helena. + + + +DEMETRIUS +No, sir, she shall not, though you take her part. + + + +HELENA +O, when she's angry, she is keen and shrewd! +She was a vixen when she went to school; +And though she be but little, she is fierce. + + + +HERMIA +'Little' again! nothing but 'low' and 'little'! +Why will you suffer her to flout me thus? +Let me come to her. + + + +LYSANDER +Get you gone, you dwarf; +You minimus, of hindering knot-grass made; +You bead, you acorn. + + + +DEMETRIUS +You are too officious +In her behalf that scorns your services. +Let her alone: speak not of Helena; +Take not her part; for, if thou dost intend +Never so little show of love to her, +Thou shalt aby it. + + + +LYSANDER +Now she holds me not; +Now follow, if thou darest, to try whose right, +Of thine or mine, is most in Helena. + + + +DEMETRIUS +Follow! nay, I'll go with thee, cheek by jole. + + + +Exeunt LYSANDER and DEMETRIUS + + +HERMIA +You, mistress, all this coil is 'long of you: +Nay, go not back. + + + +HELENA +I will not trust you, I, +Nor longer stay in your curst company. +Your hands than mine are quicker for a fray, +My legs are longer though, to run away. + + + +Exit + + +HERMIA +I am amazed, and know not what to say. + + + +Exit + + +OBERON +This is thy negligence: still thou mistakest, +Or else committ'st thy knaveries wilfully. + + + +PUCK +Believe me, king of shadows, I mistook. +Did not you tell me I should know the man +By the Athenian garment be had on? +And so far blameless proves my enterprise, +That I have 'nointed an Athenian's eyes; +And so far am I glad it so did sort +As this their jangling I esteem a sport. + + + +OBERON +Thou see'st these lovers seek a place to fight: +Hie therefore, Robin, overcast the night; +The starry welkin cover thou anon +With drooping fog as black as Acheron, +And lead these testy rivals so astray +As one come not within another's way. +Like to Lysander sometime frame thy tongue, +Then stir Demetrius up with bitter wrong; +And sometime rail thou like Demetrius; +And from each other look thou lead them thus, +Till o'er their brows death-counterfeiting sleep +With leaden legs and batty wings doth creep: +Then crush this herb into Lysander's eye; +Whose liquor hath this virtuous property, +To take from thence all error with his might, +And make his eyeballs roll with wonted sight. +When they next wake, all this derision +Shall seem a dream and fruitless vision, +And back to Athens shall the lovers wend, +With league whose date till death shall never end. +Whiles I in this affair do thee employ, +I'll to my queen and beg her Indian boy; +And then I will her charmed eye release +From monster's view, and all things shall be peace. + + + +PUCK +My fairy lord, this must be done with haste, +For night's swift dragons cut the clouds full fast, +And yonder shines Aurora's harbinger; +At whose approach, ghosts, wandering here and there, +Troop home to churchyards: damned spirits all, +That in crossways and floods have burial, +Already to their wormy beds are gone; +For fear lest day should look their shames upon, +They willfully themselves exile from light +And must for aye consort with black-brow'd night. + + + +OBERON +But we are spirits of another sort: +I with the morning's love have oft made sport, +And, like a forester, the groves may tread, +Even till the eastern gate, all fiery-red, +Opening on Neptune with fair blessed beams, +Turns into yellow gold his salt green streams. +But, notwithstanding, haste; make no delay: +We may effect this business yet ere day. + + + +Exit + + +PUCK +Up and down, up and down, +I will lead them up and down: +I am fear'd in field and town: +Goblin, lead them up and down. +Here comes one. + + + +Re-enter LYSANDER + + +LYSANDER +Where art thou, proud Demetrius? speak thou now. + + + +PUCK +Here, villain; drawn and ready. Where art thou? + + + +LYSANDER +I will be with thee straight. + + + +PUCK +Follow me, then, +To plainer ground. + + +Exit LYSANDER, as following the voice +Re-enter DEMETRIUS + + +DEMETRIUS +Lysander! speak again: +Thou runaway, thou coward, art thou fled? +Speak! In some bush? Where dost thou hide thy head? + + + +PUCK +Thou coward, art thou bragging to the stars, +Telling the bushes that thou look'st for wars, +And wilt not come? Come, recreant; come, thou child; +I'll whip thee with a rod: he is defiled +That draws a sword on thee. + + + +DEMETRIUS +Yea, art thou there? + + + +PUCK +Follow my voice: we'll try no manhood here. + + +Exeunt +Re-enter LYSANDER + + +LYSANDER +He goes before me and still dares me on: +When I come where he calls, then he is gone. +The villain is much lighter-heel'd than I: +I follow'd fast, but faster he did fly; +That fallen am I in dark uneven way, +And here will rest me. +Lies down +Come, thou gentle day! +For if but once thou show me thy grey light, +I'll find Demetrius and revenge this spite. + + +Sleeps +Re-enter PUCK and DEMETRIUS + + +PUCK +Ho, ho, ho! Coward, why comest thou not? + + + +DEMETRIUS +Abide me, if thou darest; for well I wot +Thou runn'st before me, shifting every place, +And darest not stand, nor look me in the face. +Where art thou now? + + + +PUCK +Come hither: I am here. + + + +DEMETRIUS +Nay, then, thou mock'st me. Thou shalt buy this dear, +If ever I thy face by daylight see: +Now, go thy way. Faintness constraineth me +To measure out my length on this cold bed. +By day's approach look to be visited. + + +Lies down and sleeps +Re-enter HELENA + + +HELENA +O weary night, O long and tedious night, +Abate thy hour! Shine comforts from the east, +That I may back to Athens by daylight, +From these that my poor company detest: +And sleep, that sometimes shuts up sorrow's eye, +Steal me awhile from mine own company. + + + +Lies down and sleeps + + +PUCK +Yet but three? Come one more; +Two of both kinds make up four. +Here she comes, curst and sad: +Cupid is a knavish lad, +Thus to make poor females mad. + + + +Re-enter HERMIA + + +HERMIA +Never so weary, never so in woe, +Bedabbled with the dew and torn with briers, +I can no further crawl, no further go; +My legs can keep no pace with my desires. +Here will I rest me till the break of day. +Heavens shield Lysander, if they mean a fray! + + + +Lies down and sleeps + + +PUCK +On the ground +Sleep sound: +I'll apply +To your eye, +Gentle lover, remedy. +Squeezing the juice on LYSANDER's eyes +When thou wakest, +Thou takest +True delight +In the sight +Of thy former lady's eye: +And the country proverb known, +That every man should take his own, +In your waking shall be shown: +Jack shall have Jill; +Nought shall go ill; +The man shall have his mare again, and all shall be well. + + + +Exit + + + + +ACT IV + +SCENE I. The same. LYSANDER, DEMETRIUS, HELENA, and HERMIA lying asleep. +Enter TITANIA and BOTTOM; PEASEBLOSSOM, COBWEB, MOTH, +MUSTARDSEED, and other Fairies attending; OBERON +behind unseen + + +TITANIA +Come, sit thee down upon this flowery bed, +While I thy amiable cheeks do coy, +And stick musk-roses in thy sleek smooth head, +And kiss thy fair large ears, my gentle joy. + + + +BOTTOM +Where's Peaseblossom? + + + +PEASEBLOSSOM +Ready. + + + +BOTTOM +Scratch my head Peaseblossom. Where's Mounsieur Cobweb? + + + +COBWEB +Ready. + + + +BOTTOM +Mounsieur Cobweb, good mounsieur, get you your +weapons in your hand, and kill me a red-hipped +humble-bee on the top of a thistle; and, good +mounsieur, bring me the honey-bag. Do not fret +yourself too much in the action, mounsieur; and, +good mounsieur, have a care the honey-bag break not; +I would be loath to have you overflown with a +honey-bag, signior. Where's Mounsieur Mustardseed? + + + +MUSTARDSEED +Ready. + + + +BOTTOM +Give me your neaf, Mounsieur Mustardseed. Pray you, +leave your courtesy, good mounsieur. + + + +MUSTARDSEED +What's your Will? + + + +BOTTOM +Nothing, good mounsieur, but to help Cavalery Cobweb +to scratch. I must to the barber's, monsieur; for +methinks I am marvellous hairy about the face; and I +am such a tender ass, if my hair do but tickle me, +I must scratch. + + + +TITANIA +What, wilt thou hear some music, +my sweet love? + + + +BOTTOM +I have a reasonable good ear in music. Let's have +the tongs and the bones. + + + +TITANIA +Or say, sweet love, what thou desirest to eat. + + + +BOTTOM +Truly, a peck of provender: I could munch your good +dry oats. Methinks I have a great desire to a bottle +of hay: good hay, sweet hay, hath no fellow. + + + +TITANIA +I have a venturous fairy that shall seek +The squirrel's hoard, and fetch thee new nuts. + + + +BOTTOM +I had rather have a handful or two of dried peas. +But, I pray you, let none of your people stir me: I +have an exposition of sleep come upon me. + + + +TITANIA +Sleep thou, and I will wind thee in my arms. +Fairies, begone, and be all ways away. +Exeunt fairies +So doth the woodbine the sweet honeysuckle +Gently entwist; the female ivy so +Enrings the barky fingers of the elm. +O, how I love thee! how I dote on thee! + + +They sleep +Enter PUCK + + +OBERON +Advancing Welcome, good Robin. +See'st thou this sweet sight? +Her dotage now I do begin to pity: +For, meeting her of late behind the wood, +Seeking sweet favours from this hateful fool, +I did upbraid her and fall out with her; +For she his hairy temples then had rounded +With a coronet of fresh and fragrant flowers; +And that same dew, which sometime on the buds +Was wont to swell like round and orient pearls, +Stood now within the pretty flowerets' eyes +Like tears that did their own disgrace bewail. +When I had at my pleasure taunted her +And she in mild terms begg'd my patience, +I then did ask of her her changeling child; +Which straight she gave me, and her fairy sent +To bear him to my bower in fairy land. +And now I have the boy, I will undo +This hateful imperfection of her eyes: +And, gentle Puck, take this transformed scalp +From off the head of this Athenian swain; +That, he awaking when the other do, +May all to Athens back again repair +And think no more of this night's accidents +But as the fierce vexation of a dream. +But first I will release the fairy queen. +Be as thou wast wont to be; +See as thou wast wont to see: +Dian's bud o'er Cupid's flower +Hath such force and blessed power. +Now, my Titania; wake you, my sweet queen. + + + +TITANIA +My Oberon! what visions have I seen! +Methought I was enamour'd of an ass. + + + +OBERON +There lies your love. + + + +TITANIA +How came these things to pass? +O, how mine eyes do loathe his visage now! + + + +OBERON +Silence awhile. Robin, take off this head. +Titania, music call; and strike more dead +Than common sleep of all these five the sense. + + + +TITANIA +Music, ho! music, such as charmeth sleep! + + + +Music, still + + +PUCK +Now, when thou wakest, with thine +own fool's eyes peep. + + + +OBERON +Sound, music! Come, my queen, take hands with me, +And rock the ground whereon these sleepers be. +Now thou and I are new in amity, +And will to-morrow midnight solemnly +Dance in Duke Theseus' house triumphantly, +And bless it to all fair prosperity: +There shall the pairs of faithful lovers be +Wedded, with Theseus, all in jollity. + + + +PUCK +Fairy king, attend, and mark: +I do hear the morning lark. + + + +OBERON +Then, my queen, in silence sad, +Trip we after the night's shade: +We the globe can compass soon, +Swifter than the wandering moon. + + + +TITANIA +Come, my lord, and in our flight +Tell me how it came this night +That I sleeping here was found +With these mortals on the ground. +Exeunt + + +Horns winded within +Enter THESEUS, HIPPOLYTA, EGEUS, and train + + +THESEUS +Go, one of you, find out the forester; +For now our observation is perform'd; +And since we have the vaward of the day, +My love shall hear the music of my hounds. +Uncouple in the western valley; let them go: +Dispatch, I say, and find the forester. +Exit an Attendant +We will, fair queen, up to the mountain's top, +And mark the musical confusion +Of hounds and echo in conjunction. + + + +HIPPOLYTA +I was with Hercules and Cadmus once, +When in a wood of Crete they bay'd the bear +With hounds of Sparta: never did I hear +Such gallant chiding: for, besides the groves, +The skies, the fountains, every region near +Seem'd all one mutual cry: I never heard +So musical a discord, such sweet thunder. + + + +THESEUS +My hounds are bred out of the Spartan kind, +So flew'd, so sanded, and their heads are hung +With ears that sweep away the morning dew; +Crook-knee'd, and dew-lapp'd like Thessalian bulls; +Slow in pursuit, but match'd in mouth like bells, +Each under each. A cry more tuneable +Was never holla'd to, nor cheer'd with horn, +In Crete, in Sparta, nor in Thessaly: +Judge when you hear. But, soft! what nymphs are these? + + + +EGEUS +My lord, this is my daughter here asleep; +And this, Lysander; this Demetrius is; +This Helena, old Nedar's Helena: +I wonder of their being here together. + + + +THESEUS +No doubt they rose up early to observe +The rite of May, and hearing our intent, +Came here in grace our solemnity. +But speak, Egeus; is not this the day +That Hermia should give answer of her choice? + + + +EGEUS +It is, my lord. + + + +THESEUS +Go, bid the huntsmen wake them with their horns. +Horns and shout within. LYSANDER, DEMETRIUS, +HELENA, and HERMIA wake and start up +Good morrow, friends. Saint Valentine is past: +Begin these wood-birds but to couple now? + + + +LYSANDER +Pardon, my lord. + + + +THESEUS +I pray you all, stand up. +I know you two are rival enemies: +How comes this gentle concord in the world, +That hatred is so far from jealousy, +To sleep by hate, and fear no enmity? + + + +LYSANDER +My lord, I shall reply amazedly, +Half sleep, half waking: but as yet, I swear, +I cannot truly say how I came here; +But, as I think,--for truly would I speak, +And now do I bethink me, so it is,-- +I came with Hermia hither: our intent +Was to be gone from Athens, where we might, +Without the peril of the Athenian law. + + + +EGEUS +Enough, enough, my lord; you have enough: +I beg the law, the law, upon his head. +They would have stolen away; they would, Demetrius, +Thereby to have defeated you and me, +You of your wife and me of my consent, +Of my consent that she should be your wife. + + + +DEMETRIUS +My lord, fair Helen told me of their stealth, +Of this their purpose hither to this wood; +And I in fury hither follow'd them, +Fair Helena in fancy following me. +But, my good lord, I wot not by what power,-- +But by some power it is,--my love to Hermia, +Melted as the snow, seems to me now +As the remembrance of an idle gaud +Which in my childhood I did dote upon; +And all the faith, the virtue of my heart, +The object and the pleasure of mine eye, +Is only Helena. To her, my lord, +Was I betroth'd ere I saw Hermia: +But, like in sickness, did I loathe this food; +But, as in health, come to my natural taste, +Now I do wish it, love it, long for it, +And will for evermore be true to it. + + + +THESEUS +Fair lovers, you are fortunately met: +Of this discourse we more will hear anon. +Egeus, I will overbear your will; +For in the temple by and by with us +These couples shall eternally be knit: +And, for the morning now is something worn, +Our purposed hunting shall be set aside. +Away with us to Athens; three and three, +We'll hold a feast in great solemnity. +Come, Hippolyta. + + + +Exeunt THESEUS, HIPPOLYTA, EGEUS, and train + + +DEMETRIUS +These things seem small and undistinguishable, + + + +HERMIA +Methinks I see these things with parted eye, +When every thing seems double. + + + +HELENA +So methinks: +And I have found Demetrius like a jewel, +Mine own, and not mine own. + + + +DEMETRIUS +Are you sure +That we are awake? It seems to me +That yet we sleep, we dream. Do not you think +The duke was here, and bid us follow him? + + + +HERMIA +Yea; and my father. + + + +HELENA +And Hippolyta. + + + +LYSANDER +And he did bid us follow to the temple. + + + +DEMETRIUS +Why, then, we are awake: let's follow him +And by the way let us recount our dreams. + + + +Exeunt + + +BOTTOM +Awaking When my cue comes, call me, and I will +answer: my next is, 'Most fair Pyramus.' Heigh-ho! +Peter Quince! Flute, the bellows-mender! Snout, +the tinker! Starveling! God's my life, stolen +hence, and left me asleep! I have had a most rare +vision. I have had a dream, past the wit of man to +say what dream it was: man is but an ass, if he go +about to expound this dream. Methought I was--there +is no man can tell what. Methought I was,--and +methought I had,--but man is but a patched fool, if +he will offer to say what methought I had. The eye +of man hath not heard, the ear of man hath not +seen, man's hand is not able to taste, his tongue +to conceive, nor his heart to report, what my dream +was. I will get Peter Quince to write a ballad of +this dream: it shall be called Bottom's Dream, +because it hath no bottom; and I will sing it in the +latter end of a play, before the duke: +peradventure, to make it the more gracious, I shall +sing it at her death. + + + +Exit + + +SCENE II. Athens. QUINCE'S house. +Enter QUINCE, FLUTE, SNOUT, and STARVELING + + +QUINCE +Have you sent to Bottom's house? is he come home yet? + + + +STARVELING +He cannot be heard of. Out of doubt he is +transported. + + + +FLUTE +If he come not, then the play is marred: it goes +not forward, doth it? + + + +QUINCE +It is not possible: you have not a man in all +Athens able to discharge Pyramus but he. + + + +FLUTE +No, he hath simply the best wit of any handicraft +man in Athens. + + + +QUINCE +Yea and the best person too; and he is a very +paramour for a sweet voice. + + + +FLUTE +You must say 'paragon:' a paramour is, God bless us, +a thing of naught. + + + +Enter SNUG + + +SNUG +Masters, the duke is coming from the temple, and +there is two or three lords and ladies more married: +if our sport had gone forward, we had all been made +men. + + + +FLUTE +O sweet bully Bottom! Thus hath he lost sixpence a +day during his life; he could not have 'scaped +sixpence a day: an the duke had not given him +sixpence a day for playing Pyramus, I'll be hanged; +he would have deserved it: sixpence a day in +Pyramus, or nothing. + + + +Enter BOTTOM + + +BOTTOM +Where are these lads? where are these hearts? + + + +QUINCE +Bottom! O most courageous day! O most happy hour! + + + +BOTTOM +Masters, I am to discourse wonders: but ask me not +what; for if I tell you, I am no true Athenian. I +will tell you every thing, right as it fell out. + + + +QUINCE +Let us hear, sweet Bottom. + + + +BOTTOM +Not a word of me. All that I will tell you is, that +the duke hath dined. Get your apparel together, +good strings to your beards, new ribbons to your +pumps; meet presently at the palace; every man look +o'er his part; for the short and the long is, our +play is preferred. In any case, let Thisby have +clean linen; and let not him that plays the lion +pair his nails, for they shall hang out for the +lion's claws. And, most dear actors, eat no onions +nor garlic, for we are to utter sweet breath; and I +do not doubt but to hear them say, it is a sweet +comedy. No more words: away! go, away! + + + +Exeunt + + + + +ACT V + +SCENE I. Athens. The palace of THESEUS. +Enter THESEUS, HIPPOLYTA, PHILOSTRATE, Lords and +Attendants + + +HIPPOLYTA +'Tis strange my Theseus, that these +lovers speak of. + + + +THESEUS +More strange than true: I never may believe +These antique fables, nor these fairy toys. +Lovers and madmen have such seething brains, +Such shaping fantasies, that apprehend +More than cool reason ever comprehends. +The lunatic, the lover and the poet +Are of imagination all compact: +One sees more devils than vast hell can hold, +That is, the madman: the lover, all as frantic, +Sees Helen's beauty in a brow of Egypt: +The poet's eye, in fine frenzy rolling, +Doth glance from heaven to earth, from earth to heaven; +And as imagination bodies forth +The forms of things unknown, the poet's pen +Turns them to shapes and gives to airy nothing +A local habitation and a name. +Such tricks hath strong imagination, +That if it would but apprehend some joy, +It comprehends some bringer of that joy; +Or in the night, imagining some fear, +How easy is a bush supposed a bear! + + + +HIPPOLYTA +But all the story of the night told over, +And all their minds transfigured so together, +More witnesseth than fancy's images +And grows to something of great constancy; +But, howsoever, strange and admirable. + + + +THESEUS +Here come the lovers, full of joy and mirth. +Enter LYSANDER, DEMETRIUS, HERMIA, and HELENA +Joy, gentle friends! joy and fresh days of love +Accompany your hearts! + + + +LYSANDER +More than to us +Wait in your royal walks, your board, your bed! + + + +THESEUS +Come now; what masques, what dances shall we have, +To wear away this long age of three hours +Between our after-supper and bed-time? +Where is our usual manager of mirth? +What revels are in hand? Is there no play, +To ease the anguish of a torturing hour? +Call Philostrate. + + + +PHILOSTRATE +Here, mighty Theseus. + + + +THESEUS +Say, what abridgement have you for this evening? +What masque? what music? How shall we beguile +The lazy time, if not with some delight? + + + +PHILOSTRATE +There is a brief how many sports are ripe: +Make choice of which your highness will see first. + + + +Giving a paper + + +THESEUS +Reads 'The battle with the Centaurs, to be sung +By an Athenian eunuch to the harp.' +We'll none of that: that have I told my love, +In glory of my kinsman Hercules. +Reads +'The riot of the tipsy Bacchanals, +Tearing the Thracian singer in their rage.' +That is an old device; and it was play'd +When I from Thebes came last a conqueror. +Reads +'The thrice three Muses mourning for the death +Of Learning, late deceased in beggary.' +That is some satire, keen and critical, +Not sorting with a nuptial ceremony. +Reads +'A tedious brief scene of young Pyramus +And his love Thisbe; very tragical mirth.' +Merry and tragical! tedious and brief! +That is, hot ice and wondrous strange snow. +How shall we find the concord of this discord? + + + +PHILOSTRATE +A play there is, my lord, some ten words long, +Which is as brief as I have known a play; +But by ten words, my lord, it is too long, +Which makes it tedious; for in all the play +There is not one word apt, one player fitted: +And tragical, my noble lord, it is; +For Pyramus therein doth kill himself. +Which, when I saw rehearsed, I must confess, +Made mine eyes water; but more merry tears +The passion of loud laughter never shed. + + + +THESEUS +What are they that do play it? + + + +PHILOSTRATE +Hard-handed men that work in Athens here, +Which never labour'd in their minds till now, +And now have toil'd their unbreathed memories +With this same play, against your nuptial. + + + +THESEUS +And we will hear it. + + + +PHILOSTRATE +No, my noble lord; +It is not for you: I have heard it over, +And it is nothing, nothing in the world; +Unless you can find sport in their intents, +Extremely stretch'd and conn'd with cruel pain, +To do you service. + + + +THESEUS +I will hear that play; +For never anything can be amiss, +When simpleness and duty tender it. +Go, bring them in: and take your places, ladies. + + + +Exit PHILOSTRATE + + +HIPPOLYTA +I love not to see wretchedness o'er charged +And duty in his service perishing. + + + +THESEUS +Why, gentle sweet, you shall see no such thing. + + + +HIPPOLYTA +He says they can do nothing in this kind. + + + +THESEUS +The kinder we, to give them thanks for nothing. +Our sport shall be to take what they mistake: +And what poor duty cannot do, noble respect +Takes it in might, not merit. +Where I have come, great clerks have purposed +To greet me with premeditated welcomes; +Where I have seen them shiver and look pale, +Make periods in the midst of sentences, +Throttle their practised accent in their fears +And in conclusion dumbly have broke off, +Not paying me a welcome. Trust me, sweet, +Out of this silence yet I pick'd a welcome; +And in the modesty of fearful duty +I read as much as from the rattling tongue +Of saucy and audacious eloquence. +Love, therefore, and tongue-tied simplicity +In least speak most, to my capacity. + + + +Re-enter PHILOSTRATE + + +PHILOSTRATE +So please your grace, the Prologue is address'd. + + + +THESEUS +Let him approach. + + +Flourish of trumpets +Enter QUINCE for the Prologue + + +Prologue +If we offend, it is with our good will. +That you should think, we come not to offend, +But with good will. To show our simple skill, +That is the true beginning of our end. +Consider then we come but in despite. +We do not come as minding to contest you, +Our true intent is. All for your delight +We are not here. That you should here repent you, +The actors are at hand and by their show +You shall know all that you are like to know. + + + +THESEUS +This fellow doth not stand upon points. + + + +LYSANDER +He hath rid his prologue like a rough colt; he knows +not the stop. A good moral, my lord: it is not +enough to speak, but to speak true. + + + +HIPPOLYTA +Indeed he hath played on his prologue like a child +on a recorder; a sound, but not in government. + + + +THESEUS +His speech, was like a tangled chain; nothing +impaired, but all disordered. Who is next? + + + +Enter Pyramus and Thisbe, Wall, Moonshine, and Lion + + +Prologue +Gentles, perchance you wonder at this show; +But wonder on, till truth make all things plain. +This man is Pyramus, if you would know; +This beauteous lady Thisby is certain. +This man, with lime and rough-cast, doth present +Wall, that vile Wall which did these lovers sunder; +And through Wall's chink, poor souls, they are content +To whisper. At the which let no man wonder. +This man, with lanthorn, dog, and bush of thorn, +Presenteth Moonshine; for, if you will know, +By moonshine did these lovers think no scorn +To meet at Ninus' tomb, there, there to woo. +This grisly beast, which Lion hight by name, +The trusty Thisby, coming first by night, +Did scare away, or rather did affright; +And, as she fled, her mantle she did fall, +Which Lion vile with bloody mouth did stain. +Anon comes Pyramus, sweet youth and tall, +And finds his trusty Thisby's mantle slain: +Whereat, with blade, with bloody blameful blade, +He bravely broach'd is boiling bloody breast; +And Thisby, tarrying in mulberry shade, +His dagger drew, and died. For all the rest, +Let Lion, Moonshine, Wall, and lovers twain +At large discourse, while here they do remain. + + + +Exeunt Prologue, Thisbe, Lion, and Moonshine + + +THESEUS +I wonder if the lion be to speak. + + + +DEMETRIUS +No wonder, my lord: one lion may, when many asses do. + + + +Wall +In this same interlude it doth befall +That I, one Snout by name, present a wall; +And such a wall, as I would have you think, +That had in it a crannied hole or chink, +Through which the lovers, Pyramus and Thisby, +Did whisper often very secretly. +This loam, this rough-cast and this stone doth show +That I am that same wall; the truth is so: +And this the cranny is, right and sinister, +Through which the fearful lovers are to whisper. + + + +THESEUS +Would you desire lime and hair to speak better? + + + +DEMETRIUS +It is the wittiest partition that ever I heard +discourse, my lord. + + + +Enter Pyramus + + +THESEUS +Pyramus draws near the wall: silence! + + + +Pyramus +O grim-look'd night! O night with hue so black! +O night, which ever art when day is not! +O night, O night! alack, alack, alack, +I fear my Thisby's promise is forgot! +And thou, O wall, O sweet, O lovely wall, +That stand'st between her father's ground and mine! +Thou wall, O wall, O sweet and lovely wall, +Show me thy chink, to blink through with mine eyne! +Wall holds up his fingers +Thanks, courteous wall: Jove shield thee well for this! +But what see I? No Thisby do I see. +O wicked wall, through whom I see no bliss! +Cursed be thy stones for thus deceiving me! + + + +THESEUS +The wall, methinks, being sensible, should curse again. + + + +Pyramus +No, in truth, sir, he should not. 'Deceiving me' +is Thisby's cue: she is to enter now, and I am to +spy her through the wall. You shall see, it will +fall pat as I told you. Yonder she comes. + + + +Enter Thisbe + + +Thisbe +O wall, full often hast thou heard my moans, +For parting my fair Pyramus and me! +My cherry lips have often kiss'd thy stones, +Thy stones with lime and hair knit up in thee. + + + +Pyramus +I see a voice: now will I to the chink, +To spy an I can hear my Thisby's face. Thisby! + + + +Thisbe +My love thou art, my love I think. + + + +Pyramus +Think what thou wilt, I am thy lover's grace; +And, like Limander, am I trusty still. + + + +Thisbe +And I like Helen, till the Fates me kill. + + + +Pyramus +Not Shafalus to Procrus was so true. + + + +Thisbe +As Shafalus to Procrus, I to you. + + + +Pyramus +O kiss me through the hole of this vile wall! + + + +Thisbe +I kiss the wall's hole, not your lips at all. + + + +Pyramus +Wilt thou at Ninny's tomb meet me straightway? + + + +Thisbe +'Tide life, 'tide death, I come without delay. + + + +Exeunt Pyramus and Thisbe + + +Wall +Thus have I, Wall, my part discharged so; +And, being done, thus Wall away doth go. + + + +Exit + + +THESEUS +Now is the mural down between the two neighbours. + + + +DEMETRIUS +No remedy, my lord, when walls are so wilful to hear +without warning. + + + +HIPPOLYTA +This is the silliest stuff that ever I heard. + + + +THESEUS +The best in this kind are but shadows; and the worst +are no worse, if imagination amend them. + + + +HIPPOLYTA +It must be your imagination then, and not theirs. + + + +THESEUS +If we imagine no worse of them than they of +themselves, they may pass for excellent men. Here +come two noble beasts in, a man and a lion. + + + +Enter Lion and Moonshine + + +Lion +You, ladies, you, whose gentle hearts do fear +The smallest monstrous mouse that creeps on floor, +May now perchance both quake and tremble here, +When lion rough in wildest rage doth roar. +Then know that I, one Snug the joiner, am +A lion-fell, nor else no lion's dam; +For, if I should as lion come in strife +Into this place, 'twere pity on my life. + + + +THESEUS +A very gentle beast, of a good conscience. + + + +DEMETRIUS +The very best at a beast, my lord, that e'er I saw. + + + +LYSANDER +This lion is a very fox for his valour. + + + +THESEUS +True; and a goose for his discretion. + + + +DEMETRIUS +Not so, my lord; for his valour cannot carry his +discretion; and the fox carries the goose. + + + +THESEUS +His discretion, I am sure, cannot carry his valour; +for the goose carries not the fox. It is well: +leave it to his discretion, and let us listen to the moon. + + + +Moonshine +This lanthorn doth the horned moon present;-- + + + +DEMETRIUS +He should have worn the horns on his head. + + + +THESEUS +He is no crescent, and his horns are +invisible within the circumference. + + + +Moonshine +This lanthorn doth the horned moon present; +Myself the man i' the moon do seem to be. + + + +THESEUS +This is the greatest error of all the rest: the man +should be put into the lanthorn. How is it else the +man i' the moon? + + + +DEMETRIUS +He dares not come there for the candle; for, you +see, it is already in snuff. + + + +HIPPOLYTA +I am aweary of this moon: would he would change! + + + +THESEUS +It appears, by his small light of discretion, that +he is in the wane; but yet, in courtesy, in all +reason, we must stay the time. + + + +LYSANDER +Proceed, Moon. + + + +Moonshine +All that I have to say, is, to tell you that the +lanthorn is the moon; I, the man in the moon; this +thorn-bush, my thorn-bush; and this dog, my dog. + + + +DEMETRIUS +Why, all these should be in the lanthorn; for all +these are in the moon. But, silence! here comes Thisbe. + + + +Enter Thisbe + + +Thisbe +This is old Ninny's tomb. Where is my love? + + + +Lion +Roaring Oh-- + + + +Thisbe runs off + + +DEMETRIUS +Well roared, Lion. + + + +THESEUS +Well run, Thisbe. + + + +HIPPOLYTA +Well shone, Moon. Truly, the moon shines with a +good grace. + + + +The Lion shakes Thisbe's mantle, and exit + + +THESEUS +Well moused, Lion. + + + +LYSANDER +And so the lion vanished. + + + +DEMETRIUS +And then came Pyramus. + + + +Enter Pyramus + + +Pyramus +Sweet Moon, I thank thee for thy sunny beams; +I thank thee, Moon, for shining now so bright; +For, by thy gracious, golden, glittering gleams, +I trust to take of truest Thisby sight. +But stay, O spite! +But mark, poor knight, +What dreadful dole is here! +Eyes, do you see? +How can it be? +O dainty duck! O dear! +Thy mantle good, +What, stain'd with blood! +Approach, ye Furies fell! +O Fates, come, come, +Cut thread and thrum; +Quail, crush, conclude, and quell! + + + +THESEUS +This passion, and the death of a dear friend, would +go near to make a man look sad. + + + +HIPPOLYTA +Beshrew my heart, but I pity the man. + + + +Pyramus +O wherefore, Nature, didst thou lions frame? +Since lion vile hath here deflower'd my dear: +Which is--no, no--which was the fairest dame +That lived, that loved, that liked, that look'd +with cheer. +Come, tears, confound; +Out, sword, and wound +The pap of Pyramus; +Ay, that left pap, +Where heart doth hop: +Stabs himself +Thus die I, thus, thus, thus. +Now am I dead, +Now am I fled; +My soul is in the sky: +Tongue, lose thy light; +Moon take thy flight: +Exit Moonshine +Now die, die, die, die, die. + + + +Dies + + +DEMETRIUS +No die, but an ace, for him; for he is but one. + + + +LYSANDER +Less than an ace, man; for he is dead; he is nothing. + + + +THESEUS +With the help of a surgeon he might yet recover, and +prove an ass. + + + +HIPPOLYTA +How chance Moonshine is gone before Thisbe comes +back and finds her lover? + + + +THESEUS +She will find him by starlight. Here she comes; and +her passion ends the play. + + + +Re-enter Thisbe + + +HIPPOLYTA +Methinks she should not use a long one for such a +Pyramus: I hope she will be brief. + + + +DEMETRIUS +A mote will turn the balance, which Pyramus, which +Thisbe, is the better; he for a man, God warrant us; +she for a woman, God bless us. + + + +LYSANDER +She hath spied him already with those sweet eyes. + + + +DEMETRIUS +And thus she means, videlicet:-- + + + +Thisbe +Asleep, my love? +What, dead, my dove? +O Pyramus, arise! +Speak, speak. Quite dumb? +Dead, dead? A tomb +Must cover thy sweet eyes. +These My lips, +This cherry nose, +These yellow cowslip cheeks, +Are gone, are gone: +Lovers, make moan: +His eyes were green as leeks. +O Sisters Three, +Come, come to me, +With hands as pale as milk; +Lay them in gore, +Since you have shore +With shears his thread of silk. +Tongue, not a word: +Come, trusty sword; +Come, blade, my breast imbrue: +Stabs herself +And, farewell, friends; +Thus Thisby ends: +Adieu, adieu, adieu. + + + +Dies + + +THESEUS +Moonshine and Lion are left to bury the dead. + + + +DEMETRIUS +Ay, and Wall too. + + + +BOTTOM +Starting up No assure you; the wall is down that +parted their fathers. Will it please you to see the +epilogue, or to hear a Bergomask dance between two +of our company? + + + +THESEUS +No epilogue, I pray you; for your play needs no +excuse. Never excuse; for when the players are all +dead, there needs none to be blamed. Marry, if he +that writ it had played Pyramus and hanged himself +in Thisbe's garter, it would have been a fine +tragedy: and so it is, truly; and very notably +discharged. But come, your Bergomask: let your +epilogue alone. +A dance +The iron tongue of midnight hath told twelve: +Lovers, to bed; 'tis almost fairy time. +I fear we shall out-sleep the coming morn +As much as we this night have overwatch'd. +This palpable-gross play hath well beguiled +The heavy gait of night. Sweet friends, to bed. +A fortnight hold we this solemnity, +In nightly revels and new jollity. + + +Exeunt +Enter PUCK + + +PUCK +Now the hungry lion roars, +And the wolf behowls the moon; +Whilst the heavy ploughman snores, +All with weary task fordone. +Now the wasted brands do glow, +Whilst the screech-owl, screeching loud, +Puts the wretch that lies in woe +In remembrance of a shroud. +Now it is the time of night +That the graves all gaping wide, +Every one lets forth his sprite, +In the church-way paths to glide: +And we fairies, that do run +By the triple Hecate's team, +From the presence of the sun, +Following darkness like a dream, +Now are frolic: not a mouse +Shall disturb this hallow'd house: +I am sent with broom before, +To sweep the dust behind the door. + + + +Enter OBERON and TITANIA with their train + + +OBERON +Through the house give gathering light, +By the dead and drowsy fire: +Every elf and fairy sprite +Hop as light as bird from brier; +And this ditty, after me, +Sing, and dance it trippingly. + + + +TITANIA +First, rehearse your song by rote +To each word a warbling note: +Hand in hand, with fairy grace, +Will we sing, and bless this place. + + + +Song and dance + + +OBERON +Now, until the break of day, +Through this house each fairy stray. +To the best bride-bed will we, +Which by us shall blessed be; +And the issue there create +Ever shall be fortunate. +So shall all the couples three +Ever true in loving be; +And the blots of Nature's hand +Shall not in their issue stand; +Never mole, hare lip, nor scar, +Nor mark prodigious, such as are +Despised in nativity, +Shall upon their children be. +With this field-dew consecrate, +Every fairy take his gait; +And each several chamber bless, +Through this palace, with sweet peace; +And the owner of it blest +Ever shall in safety rest. +Trip away; make no stay; +Meet me all by break of day. + + + +Exeunt OBERON, TITANIA, and train + + +PUCK +If we shadows have offended, +Think but this, and all is mended, +That you have but slumber'd here +While these visions did appear. +And this weak and idle theme, +No more yielding but a dream, +Gentles, do not reprehend: +if you pardon, we will mend: +And, as I am an honest Puck, +If we have unearned luck +Now to 'scape the serpent's tongue, +We will make amends ere long; +Else the Puck a liar call; +So, good night unto you all. +Give me your hands, if we be friends, +And Robin shall restore amends. + + + +
diff --git a/tinyxml2-3.0.0/resources/empty.xml b/tinyxml2-3.0.0/resources/empty.xml new file mode 100644 index 0000000..e69de29 diff --git a/tinyxml2-3.0.0/resources/utf8test.xml b/tinyxml2-3.0.0/resources/utf8test.xml new file mode 100755 index 0000000..c8e5837 --- /dev/null +++ b/tinyxml2-3.0.0/resources/utf8test.xml @@ -0,0 +1,11 @@ + + + The world has many languages + Мир имеет много языков + el mundo tiene muchos idiomas + 世界有很多语言 + <Русский название="name" ценность="value"><имеет> + <汉语 名字="name" 价值="value">世界有很多语言 + "Mëtæl!" + <ä>Umlaut Element + diff --git a/tinyxml2-3.0.0/resources/utf8testverify.xml b/tinyxml2-3.0.0/resources/utf8testverify.xml new file mode 100755 index 0000000..407f10a --- /dev/null +++ b/tinyxml2-3.0.0/resources/utf8testverify.xml @@ -0,0 +1,11 @@ + + + The world has many languages + Мир имеет много языков + el mundo tiene muchos idiomas + 世界有很多语言 + <Русский название="name" ценность="value"><имеет> + <汉语 名字="name" 价值="value">世界有很多语言 + "Mëtæl!" + <ä>Umlaut Element + diff --git a/tinyxml2-3.0.0/setversion.py b/tinyxml2-3.0.0/setversion.py new file mode 100755 index 0000000..98d58de --- /dev/null +++ b/tinyxml2-3.0.0/setversion.py @@ -0,0 +1,123 @@ +# Python program to set the version. +############################################## + +import re +import sys +import optparse + +def fileProcess( name, lineFunction ): + filestream = open( name, 'r' ) + if filestream.closed: + print( "file " + name + " not open." ) + return + + output = "" + print( "--- Processing " + name + " ---------" ) + while 1: + line = filestream.readline() + if not line: break + output += lineFunction( line ) + filestream.close() + + if not output: return # basic error checking + + print( "Writing file " + name ) + filestream = open( name, "w" ); + filestream.write( output ); + filestream.close() + +def echoInput( line ): + return line + +parser = optparse.OptionParser( "usage: %prog major minor build" ) +(options, args) = parser.parse_args() +if len(args) != 3: + parser.error( "incorrect number of arguments" ); + +major = args[0] +minor = args[1] +build = args[2] +versionStr = major + "." + minor + "." + build + +print ("Setting dox,tinyxml2.h") +print ("Version: " + major + "." + minor + "." + build) + +#### Write the tinyxml.h #### + +def engineRule( line ): + + matchMajor = "static const int TIXML2_MAJOR_VERSION" + matchMinor = "static const int TIXML2_MINOR_VERSION" + matchBuild = "static const int TIXML2_PATCH_VERSION" + + if line[0:len(matchMajor)] == matchMajor: + print( "1)tinyxml2.h Major found" ) + return matchMajor + " = " + major + ";\n" + + elif line[0:len(matchMinor)] == matchMinor: + print( "2)tinyxml2.h Minor found" ) + return matchMinor + " = " + minor + ";\n" + + elif line[0:len(matchBuild)] == matchBuild: + print( "3)tinyxml2.h Build found" ) + return matchBuild + " = " + build + ";\n" + + else: + return line; + +fileProcess( "tinyxml2.h", engineRule ) + + +#### Write the dox #### + +def doxRule( line ): + + match = "PROJECT_NUMBER" + + if line[0:len( match )] == match: + print( "dox project found" ) + return "PROJECT_NUMBER = " + major + "." + minor + "." + build + "\n" + + else: + return line; + +fileProcess( "dox", doxRule ) + + +#### Write the CMakeLists.txt #### + +def cmakeRule1( line ): + + matchVersion = "set(GENERIC_LIB_VERSION" + + if line[0:len(matchVersion)] == matchVersion: + print( "1)tinyxml2.h Major found" ) + return matchVersion + " \"" + major + "." + minor + "." + build + "\")" + "\n" + + else: + return line; + +fileProcess( "CMakeLists.txt", cmakeRule1 ) + +def cmakeRule2( line ): + + matchSoversion = "set(GENERIC_LIB_SOVERSION" + + if line[0:len(matchSoversion)] == matchSoversion: + print( "1)tinyxml2.h Major found" ) + return matchSoversion + " \"" + major + "\")" + "\n" + + else: + return line; + +fileProcess( "CMakeLists.txt", cmakeRule2 ) + +print( "Release note:" ) +print( '1. Build. g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe' ) +print( '2. Commit. git commit -am"setting the version to ' + versionStr + '"' ) +print( '3. Tag. git tag ' + versionStr ) +print( ' OR git tag -a ' + versionStr + ' -m [tag message]' ) +print( 'Remember to "git push" both code and tag. For the tag:' ) +print( 'git push origin [tagname]') + + \ No newline at end of file diff --git a/tinyxml2-3.0.0/tinyxml2.cpp b/tinyxml2-3.0.0/tinyxml2.cpp new file mode 100755 index 0000000..245c747 --- /dev/null +++ b/tinyxml2-3.0.0/tinyxml2.cpp @@ -0,0 +1,2344 @@ +/* +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "tinyxml2.h" + +#include // yes, this one new style header, is in the Android SDK. +#if defined(ANDROID_NDK) || defined(__QNXNTO__) +# include +#else +# include +#endif + +static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF +static const char LF = LINE_FEED; +static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out +static const char CR = CARRIAGE_RETURN; +static const char SINGLE_QUOTE = '\''; +static const char DOUBLE_QUOTE = '\"'; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// ef bb bf (Microsoft "lead bytes") - designates UTF-8 + +static const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +namespace tinyxml2 +{ + +struct Entity { + const char* pattern; + int length; + char value; +}; + +static const int NUM_ENTITIES = 5; +static const Entity entities[NUM_ENTITIES] = { + { "quot", 4, DOUBLE_QUOTE }, + { "amp", 3, '&' }, + { "apos", 4, SINGLE_QUOTE }, + { "lt", 2, '<' }, + { "gt", 2, '>' } +}; + + +StrPair::~StrPair() +{ + Reset(); +} + + +void StrPair::TransferTo( StrPair* other ) +{ + if ( this == other ) { + return; + } + // This in effect implements the assignment operator by "moving" + // ownership (as in auto_ptr). + + TIXMLASSERT( other->_flags == 0 ); + TIXMLASSERT( other->_start == 0 ); + TIXMLASSERT( other->_end == 0 ); + + other->Reset(); + + other->_flags = _flags; + other->_start = _start; + other->_end = _end; + + _flags = 0; + _start = 0; + _end = 0; +} + +void StrPair::Reset() +{ + if ( _flags & NEEDS_DELETE ) { + delete [] _start; + } + _flags = 0; + _start = 0; + _end = 0; +} + + +void StrPair::SetStr( const char* str, int flags ) +{ + Reset(); + size_t len = strlen( str ); + _start = new char[ len+1 ]; + memcpy( _start, str, len+1 ); + _end = _start + len; + _flags = flags | NEEDS_DELETE; +} + + +char* StrPair::ParseText( char* p, const char* endTag, int strFlags ) +{ + TIXMLASSERT( endTag && *endTag ); + + char* start = p; + char endChar = *endTag; + size_t length = strlen( endTag ); + + // Inner loop of text parsing. + while ( *p ) { + if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) { + Set( start, p, strFlags ); + return p + length; + } + ++p; + } + return 0; +} + + +char* StrPair::ParseName( char* p ) +{ + if ( !p || !(*p) ) { + return 0; + } + if ( !XMLUtil::IsNameStartChar( *p ) ) { + return 0; + } + + char* const start = p; + ++p; + while ( *p && XMLUtil::IsNameChar( *p ) ) { + ++p; + } + + Set( start, p, 0 ); + return p; +} + + +void StrPair::CollapseWhitespace() +{ + // Adjusting _start would cause undefined behavior on delete[] + TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 ); + // Trim leading space. + _start = XMLUtil::SkipWhiteSpace( _start ); + + if ( *_start ) { + char* p = _start; // the read pointer + char* q = _start; // the write pointer + + while( *p ) { + if ( XMLUtil::IsWhiteSpace( *p )) { + p = XMLUtil::SkipWhiteSpace( p ); + if ( *p == 0 ) { + break; // don't write to q; this trims the trailing space. + } + *q = ' '; + ++q; + } + *q = *p; + ++q; + ++p; + } + *q = 0; + } +} + + +const char* StrPair::GetStr() +{ + TIXMLASSERT( _start ); + TIXMLASSERT( _end ); + if ( _flags & NEEDS_FLUSH ) { + *_end = 0; + _flags ^= NEEDS_FLUSH; + + if ( _flags ) { + char* p = _start; // the read pointer + char* q = _start; // the write pointer + + while( p < _end ) { + if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) { + // CR-LF pair becomes LF + // CR alone becomes LF + // LF-CR becomes LF + if ( *(p+1) == LF ) { + p += 2; + } + else { + ++p; + } + *q++ = LF; + } + else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) { + if ( *(p+1) == CR ) { + p += 2; + } + else { + ++p; + } + *q++ = LF; + } + else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) { + // Entities handled by tinyXML2: + // - special entities in the entity table [in/out] + // - numeric character reference [in] + // 中 or 中 + + if ( *(p+1) == '#' ) { + const int buflen = 10; + char buf[buflen] = { 0 }; + int len = 0; + char* adjusted = const_cast( XMLUtil::GetCharacterRef( p, buf, &len ) ); + if ( adjusted == 0 ) { + *q = *p; + ++p; + ++q; + } + else { + TIXMLASSERT( 0 <= len && len <= buflen ); + TIXMLASSERT( q + len <= adjusted ); + p = adjusted; + memcpy( q, buf, len ); + q += len; + } + } + else { + int i=0; + for(; i(p); + // Check for BOM: + if ( *(pu+0) == TIXML_UTF_LEAD_0 + && *(pu+1) == TIXML_UTF_LEAD_1 + && *(pu+2) == TIXML_UTF_LEAD_2 ) { + *bom = true; + p += 3; + } + TIXMLASSERT( p ); + return p; +} + + +void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) { + *length = 1; + } + else if ( input < 0x800 ) { + *length = 2; + } + else if ( input < 0x10000 ) { + *length = 3; + } + else if ( input < 0x200000 ) { + *length = 4; + } + else { + *length = 0; // This code won't covert this correctly anyway. + return; + } + + output += *length; + + // Scary scary fall throughs. + switch (*length) { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + break; + default: + TIXMLASSERT( false ); + } +} + + +const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length ) +{ + // Presume an entity, and pull it out. + *length = 0; + + if ( *(p+1) == '#' && *(p+2) ) { + unsigned long ucs = 0; + TIXMLASSERT( sizeof( ucs ) >= 4 ); + ptrdiff_t delta = 0; + unsigned mult = 1; + static const char SEMICOLON = ';'; + + if ( *(p+2) == 'x' ) { + // Hexadecimal. + const char* q = p+3; + if ( !(*q) ) { + return 0; + } + + q = strchr( q, SEMICOLON ); + + if ( !q ) { + return 0; + } + TIXMLASSERT( *q == SEMICOLON ); + + delta = q-p; + --q; + + while ( *q != 'x' ) { + unsigned int digit = 0; + + if ( *q >= '0' && *q <= '9' ) { + digit = *q - '0'; + } + else if ( *q >= 'a' && *q <= 'f' ) { + digit = *q - 'a' + 10; + } + else if ( *q >= 'A' && *q <= 'F' ) { + digit = *q - 'A' + 10; + } + else { + return 0; + } + TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); + TIXMLASSERT( digit >= 0 && digit < 16); + const unsigned int digitScaled = mult * digit; + TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); + ucs += digitScaled; + TIXMLASSERT( mult <= UINT_MAX / 16 ); + mult *= 16; + --q; + } + } + else { + // Decimal. + const char* q = p+2; + if ( !(*q) ) { + return 0; + } + + q = strchr( q, SEMICOLON ); + + if ( !q ) { + return 0; + } + TIXMLASSERT( *q == SEMICOLON ); + + delta = q-p; + --q; + + while ( *q != '#' ) { + if ( *q >= '0' && *q <= '9' ) { + const unsigned int digit = *q - '0'; + TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); + const unsigned int digitScaled = mult * digit; + TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); + ucs += digitScaled; + } + else { + return 0; + } + TIXMLASSERT( mult <= UINT_MAX / 10 ); + mult *= 10; + --q; + } + } + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + return p + delta + 1; + } + return p+1; +} + + +void XMLUtil::ToStr( int v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%d", v ); +} + + +void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%u", v ); +} + + +void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 ); +} + +/* + ToStr() of a number is a very tricky topic. + https://github.com/leethomason/tinyxml2/issues/106 +*/ +void XMLUtil::ToStr( float v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v ); +} + + +void XMLUtil::ToStr( double v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v ); +} + + +bool XMLUtil::ToInt( const char* str, int* value ) +{ + if ( TIXML_SSCANF( str, "%d", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToUnsigned( const char* str, unsigned *value ) +{ + if ( TIXML_SSCANF( str, "%u", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToBool( const char* str, bool* value ) +{ + int ival = 0; + if ( ToInt( str, &ival )) { + *value = (ival==0) ? false : true; + return true; + } + if ( StringEqual( str, "true" ) ) { + *value = true; + return true; + } + else if ( StringEqual( str, "false" ) ) { + *value = false; + return true; + } + return false; +} + + +bool XMLUtil::ToFloat( const char* str, float* value ) +{ + if ( TIXML_SSCANF( str, "%f", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToDouble( const char* str, double* value ) +{ + if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) { + return true; + } + return false; +} + + +char* XMLDocument::Identify( char* p, XMLNode** node ) +{ + TIXMLASSERT( node ); + TIXMLASSERT( p ); + char* const start = p; + p = XMLUtil::SkipWhiteSpace( p ); + if( !*p ) { + *node = 0; + TIXMLASSERT( p ); + return p; + } + + // What is this thing? + // These strings define the matching patters: + static const char* xmlHeader = { "_memPool = &_commentPool; + p += xmlHeaderLen; + } + else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); + returnNode = new (_commentPool.Alloc()) XMLComment( this ); + returnNode->_memPool = &_commentPool; + p += commentHeaderLen; + } + else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); + XMLText* text = new (_textPool.Alloc()) XMLText( this ); + returnNode = text; + returnNode->_memPool = &_textPool; + p += cdataHeaderLen; + text->SetCData( true ); + } + else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); + returnNode = new (_commentPool.Alloc()) XMLUnknown( this ); + returnNode->_memPool = &_commentPool; + p += dtdHeaderLen; + } + else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); + returnNode = new (_elementPool.Alloc()) XMLElement( this ); + returnNode->_memPool = &_elementPool; + p += elementHeaderLen; + } + else { + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); + returnNode = new (_textPool.Alloc()) XMLText( this ); + returnNode->_memPool = &_textPool; + p = start; // Back it up, all the text counts. + } + + TIXMLASSERT( returnNode ); + TIXMLASSERT( p ); + *node = returnNode; + return p; +} + + +bool XMLDocument::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + if ( visitor->VisitEnter( *this ) ) { + for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) { + break; + } + } + } + return visitor->VisitExit( *this ); +} + + +// --------- XMLNode ----------- // + +XMLNode::XMLNode( XMLDocument* doc ) : + _document( doc ), + _parent( 0 ), + _firstChild( 0 ), _lastChild( 0 ), + _prev( 0 ), _next( 0 ), + _memPool( 0 ) +{ +} + + +XMLNode::~XMLNode() +{ + DeleteChildren(); + if ( _parent ) { + _parent->Unlink( this ); + } +} + +const char* XMLNode::Value() const +{ + return _value.GetStr(); +} + +void XMLNode::SetValue( const char* str, bool staticMem ) +{ + if ( staticMem ) { + _value.SetInternedStr( str ); + } + else { + _value.SetStr( str ); + } +} + + +void XMLNode::DeleteChildren() +{ + while( _firstChild ) { + TIXMLASSERT( _firstChild->_document == _document ); + XMLNode* node = _firstChild; + Unlink( node ); + + DeleteNode( node ); + } + _firstChild = _lastChild = 0; +} + + +void XMLNode::Unlink( XMLNode* child ) +{ + TIXMLASSERT( child ); + TIXMLASSERT( child->_document == _document ); + if ( child == _firstChild ) { + _firstChild = _firstChild->_next; + } + if ( child == _lastChild ) { + _lastChild = _lastChild->_prev; + } + + if ( child->_prev ) { + child->_prev->_next = child->_next; + } + if ( child->_next ) { + child->_next->_prev = child->_prev; + } + child->_parent = 0; +} + + +void XMLNode::DeleteChild( XMLNode* node ) +{ + TIXMLASSERT( node ); + TIXMLASSERT( node->_document == _document ); + TIXMLASSERT( node->_parent == this ); + DeleteNode( node ); +} + + +XMLNode* XMLNode::InsertEndChild( XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + InsertChildPreamble( addThis ); + + if ( _lastChild ) { + TIXMLASSERT( _firstChild ); + TIXMLASSERT( _lastChild->_next == 0 ); + _lastChild->_next = addThis; + addThis->_prev = _lastChild; + _lastChild = addThis; + + addThis->_next = 0; + } + else { + TIXMLASSERT( _firstChild == 0 ); + _firstChild = _lastChild = addThis; + + addThis->_prev = 0; + addThis->_next = 0; + } + addThis->_parent = this; + return addThis; +} + + +XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + InsertChildPreamble( addThis ); + + if ( _firstChild ) { + TIXMLASSERT( _lastChild ); + TIXMLASSERT( _firstChild->_prev == 0 ); + + _firstChild->_prev = addThis; + addThis->_next = _firstChild; + _firstChild = addThis; + + addThis->_prev = 0; + } + else { + TIXMLASSERT( _lastChild == 0 ); + _firstChild = _lastChild = addThis; + + addThis->_prev = 0; + addThis->_next = 0; + } + addThis->_parent = this; + return addThis; +} + + +XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + + TIXMLASSERT( afterThis ); + + if ( afterThis->_parent != this ) { + TIXMLASSERT( false ); + return 0; + } + + if ( afterThis->_next == 0 ) { + // The last node or the only node. + return InsertEndChild( addThis ); + } + InsertChildPreamble( addThis ); + addThis->_prev = afterThis; + addThis->_next = afterThis->_next; + afterThis->_next->_prev = addThis; + afterThis->_next = addThis; + addThis->_parent = this; + return addThis; +} + + + + +const XMLElement* XMLNode::FirstChildElement( const char* value ) const +{ + for( XMLNode* node=_firstChild; node; node=node->_next ) { + XMLElement* element = node->ToElement(); + if ( element ) { + if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) { + return element; + } + } + } + return 0; +} + + +const XMLElement* XMLNode::LastChildElement( const char* value ) const +{ + for( XMLNode* node=_lastChild; node; node=node->_prev ) { + XMLElement* element = node->ToElement(); + if ( element ) { + if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) { + return element; + } + } + } + return 0; +} + + +const XMLElement* XMLNode::NextSiblingElement( const char* value ) const +{ + for( XMLNode* node=this->_next; node; node = node->_next ) { + const XMLElement* element = node->ToElement(); + if ( element + && (!value || XMLUtil::StringEqual( value, node->Value() ))) { + return element; + } + } + return 0; +} + + +const XMLElement* XMLNode::PreviousSiblingElement( const char* value ) const +{ + for( XMLNode* node=_prev; node; node = node->_prev ) { + const XMLElement* element = node->ToElement(); + if ( element + && (!value || XMLUtil::StringEqual( value, node->Value() ))) { + return element; + } + } + return 0; +} + + +char* XMLNode::ParseDeep( char* p, StrPair* parentEnd ) +{ + // This is a recursive method, but thinking about it "at the current level" + // it is a pretty simple flat list: + // + // + // + // With a special case: + // + // + // + // + // Where the closing element (/foo) *must* be the next thing after the opening + // element, and the names must match. BUT the tricky bit is that the closing + // element will be read by the child. + // + // 'endTag' is the end tag for this node, it is returned by a call to a child. + // 'parentEnd' is the end tag for the parent, which is filled in and returned. + + while( p && *p ) { + XMLNode* node = 0; + + p = _document->Identify( p, &node ); + if ( node == 0 ) { + break; + } + + StrPair endTag; + p = node->ParseDeep( p, &endTag ); + if ( !p ) { + DeleteNode( node ); + if ( !_document->Error() ) { + _document->SetError( XML_ERROR_PARSING, 0, 0 ); + } + break; + } + + XMLElement* ele = node->ToElement(); + if ( ele ) { + // We read the end tag. Return it to the parent. + if ( ele->ClosingType() == XMLElement::CLOSING ) { + if ( parentEnd ) { + ele->_value.TransferTo( parentEnd ); + } + node->_memPool->SetTracked(); // created and then immediately deleted. + DeleteNode( node ); + return p; + } + + // Handle an end tag returned to this level. + // And handle a bunch of annoying errors. + bool mismatch = false; + if ( endTag.Empty() ) { + if ( ele->ClosingType() == XMLElement::OPEN ) { + mismatch = true; + } + } + else { + if ( ele->ClosingType() != XMLElement::OPEN ) { + mismatch = true; + } + else if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() ) ) { + mismatch = true; + } + } + if ( mismatch ) { + _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 ); + DeleteNode( node ); + break; + } + } + InsertEndChild( node ); + } + return 0; +} + +void XMLNode::DeleteNode( XMLNode* node ) +{ + if ( node == 0 ) { + return; + } + MemPool* pool = node->_memPool; + node->~XMLNode(); + pool->Free( node ); +} + +void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const +{ + TIXMLASSERT( insertThis ); + TIXMLASSERT( insertThis->_document == _document ); + + if ( insertThis->_parent ) + insertThis->_parent->Unlink( insertThis ); + else + insertThis->_memPool->SetTracked(); +} + +// --------- XMLText ---------- // +char* XMLText::ParseDeep( char* p, StrPair* ) +{ + const char* start = p; + if ( this->CData() ) { + p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_CDATA, start, 0 ); + } + return p; + } + else { + int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES; + if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) { + flags |= StrPair::COLLAPSE_WHITESPACE; + } + + p = _value.ParseText( p, "<", flags ); + if ( p && *p ) { + return p-1; + } + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_TEXT, start, 0 ); + } + } + return 0; +} + + +XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern? + text->SetCData( this->CData() ); + return text; +} + + +bool XMLText::ShallowEqual( const XMLNode* compare ) const +{ + const XMLText* text = compare->ToText(); + return ( text && XMLUtil::StringEqual( text->Value(), Value() ) ); +} + + +bool XMLText::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + + +// --------- XMLComment ---------- // + +XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLComment::~XMLComment() +{ +} + + +char* XMLComment::ParseDeep( char* p, StrPair* ) +{ + // Comment parses as text. + const char* start = p; + p = _value.ParseText( p, "-->", StrPair::COMMENT ); + if ( p == 0 ) { + _document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 ); + } + return p; +} + + +XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern? + return comment; +} + + +bool XMLComment::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLComment* comment = compare->ToComment(); + return ( comment && XMLUtil::StringEqual( comment->Value(), Value() )); +} + + +bool XMLComment::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + + +// --------- XMLDeclaration ---------- // + +XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLDeclaration::~XMLDeclaration() +{ + //printf( "~XMLDeclaration\n" ); +} + + +char* XMLDeclaration::ParseDeep( char* p, StrPair* ) +{ + // Declaration parses as text. + const char* start = p; + p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); + if ( p == 0 ) { + _document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 ); + } + return p; +} + + +XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern? + return dec; +} + + +bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLDeclaration* declaration = compare->ToDeclaration(); + return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() )); +} + + + +bool XMLDeclaration::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + +// --------- XMLUnknown ---------- // + +XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLUnknown::~XMLUnknown() +{ +} + + +char* XMLUnknown::ParseDeep( char* p, StrPair* ) +{ + // Unknown parses as text. + const char* start = p; + + p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION ); + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 ); + } + return p; +} + + +XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern? + return text; +} + + +bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLUnknown* unknown = compare->ToUnknown(); + return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() )); +} + + +bool XMLUnknown::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + +// --------- XMLAttribute ---------- // + +const char* XMLAttribute::Name() const +{ + return _name.GetStr(); +} + +const char* XMLAttribute::Value() const +{ + return _value.GetStr(); +} + +char* XMLAttribute::ParseDeep( char* p, bool processEntities ) +{ + // Parse using the name rules: bug fix, was using ParseText before + p = _name.ParseName( p ); + if ( !p || !*p ) { + return 0; + } + + // Skip white space before = + p = XMLUtil::SkipWhiteSpace( p ); + if ( *p != '=' ) { + return 0; + } + + ++p; // move up to opening quote + p = XMLUtil::SkipWhiteSpace( p ); + if ( *p != '\"' && *p != '\'' ) { + return 0; + } + + char endTag[2] = { *p, 0 }; + ++p; // move past opening quote + + p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES ); + return p; +} + + +void XMLAttribute::SetName( const char* n ) +{ + _name.SetStr( n ); +} + + +XMLError XMLAttribute::QueryIntValue( int* value ) const +{ + if ( XMLUtil::ToInt( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const +{ + if ( XMLUtil::ToUnsigned( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryBoolValue( bool* value ) const +{ + if ( XMLUtil::ToBool( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryFloatValue( float* value ) const +{ + if ( XMLUtil::ToFloat( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryDoubleValue( double* value ) const +{ + if ( XMLUtil::ToDouble( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +void XMLAttribute::SetAttribute( const char* v ) +{ + _value.SetStr( v ); +} + + +void XMLAttribute::SetAttribute( int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +void XMLAttribute::SetAttribute( unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +void XMLAttribute::SetAttribute( bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( float v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +// --------- XMLElement ---------- // +XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), + _closingType( 0 ), + _rootAttribute( 0 ) +{ +} + + +XMLElement::~XMLElement() +{ + while( _rootAttribute ) { + XMLAttribute* next = _rootAttribute->_next; + DeleteAttribute( _rootAttribute ); + _rootAttribute = next; + } +} + + +const XMLAttribute* XMLElement::FindAttribute( const char* name ) const +{ + for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) { + if ( XMLUtil::StringEqual( a->Name(), name ) ) { + return a; + } + } + return 0; +} + + +const char* XMLElement::Attribute( const char* name, const char* value ) const +{ + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return 0; + } + if ( !value || XMLUtil::StringEqual( a->Value(), value )) { + return a->Value(); + } + return 0; +} + + +const char* XMLElement::GetText() const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + return FirstChild()->Value(); + } + return 0; +} + + +void XMLElement::SetText( const char* inText ) +{ + if ( FirstChild() && FirstChild()->ToText() ) + FirstChild()->SetValue( inText ); + else { + XMLText* theText = GetDocument()->NewText( inText ); + InsertFirstChild( theText ); + } +} + + +void XMLElement::SetText( int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( float v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +XMLError XMLElement::QueryIntText( int* ival ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToInt( t, ival ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToUnsigned( t, uval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryBoolText( bool* bval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToBool( t, bval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryDoubleText( double* dval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToDouble( t, dval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryFloatText( float* fval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToFloat( t, fval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + + +XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) +{ + XMLAttribute* last = 0; + XMLAttribute* attrib = 0; + for( attrib = _rootAttribute; + attrib; + last = attrib, attrib = attrib->_next ) { + if ( XMLUtil::StringEqual( attrib->Name(), name ) ) { + break; + } + } + if ( !attrib ) { + TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); + attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); + attrib->_memPool = &_document->_attributePool; + if ( last ) { + last->_next = attrib; + } + else { + _rootAttribute = attrib; + } + attrib->SetName( name ); + attrib->_memPool->SetTracked(); // always created and linked. + } + return attrib; +} + + +void XMLElement::DeleteAttribute( const char* name ) +{ + XMLAttribute* prev = 0; + for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) { + if ( XMLUtil::StringEqual( name, a->Name() ) ) { + if ( prev ) { + prev->_next = a->_next; + } + else { + _rootAttribute = a->_next; + } + DeleteAttribute( a ); + break; + } + prev = a; + } +} + + +char* XMLElement::ParseAttributes( char* p ) +{ + const char* start = p; + XMLAttribute* prevAttribute = 0; + + // Read the attributes. + while( p ) { + p = XMLUtil::SkipWhiteSpace( p ); + if ( !(*p) ) { + _document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() ); + return 0; + } + + // attribute. + if (XMLUtil::IsNameStartChar( *p ) ) { + TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); + XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); + attrib->_memPool = &_document->_attributePool; + attrib->_memPool->SetTracked(); + + p = attrib->ParseDeep( p, _document->ProcessEntities() ); + if ( !p || Attribute( attrib->Name() ) ) { + DeleteAttribute( attrib ); + _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p ); + return 0; + } + // There is a minor bug here: if the attribute in the source xml + // document is duplicated, it will not be detected and the + // attribute will be doubly added. However, tracking the 'prevAttribute' + // avoids re-scanning the attribute list. Preferring performance for + // now, may reconsider in the future. + if ( prevAttribute ) { + prevAttribute->_next = attrib; + } + else { + _rootAttribute = attrib; + } + prevAttribute = attrib; + } + // end of the tag + else if ( *p == '/' && *(p+1) == '>' ) { + _closingType = CLOSED; + return p+2; // done; sealed element. + } + // end of the tag + else if ( *p == '>' ) { + ++p; + break; + } + else { + _document->SetError( XML_ERROR_PARSING_ELEMENT, start, p ); + return 0; + } + } + return p; +} + +void XMLElement::DeleteAttribute( XMLAttribute* attribute ) +{ + if ( attribute == 0 ) { + return; + } + MemPool* pool = attribute->_memPool; + attribute->~XMLAttribute(); + pool->Free( attribute ); +} + +// +// +// foobar +// +char* XMLElement::ParseDeep( char* p, StrPair* strPair ) +{ + // Read the element name. + p = XMLUtil::SkipWhiteSpace( p ); + + // The closing element is the form. It is + // parsed just like a regular element then deleted from + // the DOM. + if ( *p == '/' ) { + _closingType = CLOSING; + ++p; + } + + p = _value.ParseName( p ); + if ( _value.Empty() ) { + return 0; + } + + p = ParseAttributes( p ); + if ( !p || !*p || _closingType ) { + return p; + } + + p = XMLNode::ParseDeep( p, strPair ); + return p; +} + + + +XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern? + for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) { + element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern? + } + return element; +} + + +bool XMLElement::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLElement* other = compare->ToElement(); + if ( other && XMLUtil::StringEqual( other->Value(), Value() )) { + + const XMLAttribute* a=FirstAttribute(); + const XMLAttribute* b=other->FirstAttribute(); + + while ( a && b ) { + if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) { + return false; + } + a = a->Next(); + b = b->Next(); + } + if ( a || b ) { + // different count + return false; + } + return true; + } + return false; +} + + +bool XMLElement::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + if ( visitor->VisitEnter( *this, _rootAttribute ) ) { + for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) { + break; + } + } + } + return visitor->VisitExit( *this ); +} + + +// --------- XMLDocument ----------- // + +// Warning: List must match 'enum XMLError' +const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { + "XML_SUCCESS", + "XML_NO_ATTRIBUTE", + "XML_WRONG_ATTRIBUTE_TYPE", + "XML_ERROR_FILE_NOT_FOUND", + "XML_ERROR_FILE_COULD_NOT_BE_OPENED", + "XML_ERROR_FILE_READ_ERROR", + "XML_ERROR_ELEMENT_MISMATCH", + "XML_ERROR_PARSING_ELEMENT", + "XML_ERROR_PARSING_ATTRIBUTE", + "XML_ERROR_IDENTIFYING_TAG", + "XML_ERROR_PARSING_TEXT", + "XML_ERROR_PARSING_CDATA", + "XML_ERROR_PARSING_COMMENT", + "XML_ERROR_PARSING_DECLARATION", + "XML_ERROR_PARSING_UNKNOWN", + "XML_ERROR_EMPTY_DOCUMENT", + "XML_ERROR_MISMATCHED_ELEMENT", + "XML_ERROR_PARSING", + "XML_CAN_NOT_CONVERT_TEXT", + "XML_NO_TEXT_NODE" +}; + + +XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) : + XMLNode( 0 ), + _writeBOM( false ), + _processEntities( processEntities ), + _errorID( XML_NO_ERROR ), + _whitespace( whitespace ), + _errorStr1( 0 ), + _errorStr2( 0 ), + _charBuffer( 0 ) +{ + _document = this; // avoid warning about 'this' in initializer list +} + + +XMLDocument::~XMLDocument() +{ + Clear(); +} + + +void XMLDocument::Clear() +{ + DeleteChildren(); + +#ifdef DEBUG + const bool hadError = Error(); +#endif + _errorID = XML_NO_ERROR; + _errorStr1 = 0; + _errorStr2 = 0; + + delete [] _charBuffer; + _charBuffer = 0; + +#if 0 + _textPool.Trace( "text" ); + _elementPool.Trace( "element" ); + _commentPool.Trace( "comment" ); + _attributePool.Trace( "attribute" ); +#endif + +#ifdef DEBUG + if ( !hadError ) { + TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); + TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); + TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); + TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); + } +#endif +} + + +XMLElement* XMLDocument::NewElement( const char* name ) +{ + TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); + XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this ); + ele->_memPool = &_elementPool; + ele->SetName( name ); + return ele; +} + + +XMLComment* XMLDocument::NewComment( const char* str ) +{ + TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); + XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this ); + comment->_memPool = &_commentPool; + comment->SetValue( str ); + return comment; +} + + +XMLText* XMLDocument::NewText( const char* str ) +{ + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); + XMLText* text = new (_textPool.Alloc()) XMLText( this ); + text->_memPool = &_textPool; + text->SetValue( str ); + return text; +} + + +XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) +{ + TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() ); + XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this ); + dec->_memPool = &_commentPool; + dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); + return dec; +} + + +XMLUnknown* XMLDocument::NewUnknown( const char* str ) +{ + TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); + XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this ); + unk->_memPool = &_commentPool; + unk->SetValue( str ); + return unk; +} + +static FILE* callfopen( const char* filepath, const char* mode ) +{ + TIXMLASSERT( filepath ); + TIXMLASSERT( mode ); +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) + FILE* fp = 0; + errno_t err = fopen_s( &fp, filepath, mode ); + if ( err ) { + return 0; + } +#else + FILE* fp = fopen( filepath, mode ); +#endif + return fp; +} + +void XMLDocument::DeleteNode( XMLNode* node ) { + TIXMLASSERT( node ); + TIXMLASSERT(node->_document == this ); + if (node->_parent) { + node->_parent->DeleteChild( node ); + } + else { + // Isn't in the tree. + // Use the parent delete. + // Also, we need to mark it tracked: we 'know' + // it was never used. + node->_memPool->SetTracked(); + // Call the static XMLNode version: + XMLNode::DeleteNode(node); + } +} + + +XMLError XMLDocument::LoadFile( const char* filename ) +{ + Clear(); + FILE* fp = callfopen( filename, "rb" ); + if ( !fp ) { + SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 ); + return _errorID; + } + LoadFile( fp ); + fclose( fp ); + return _errorID; +} + + +XMLError XMLDocument::LoadFile( FILE* fp ) +{ + Clear(); + + fseek( fp, 0, SEEK_SET ); + if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + fseek( fp, 0, SEEK_END ); + const long filelength = ftell( fp ); + fseek( fp, 0, SEEK_SET ); + if ( filelength == -1L ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + const size_t size = filelength; + if ( size == 0 ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return _errorID; + } + + _charBuffer = new char[size+1]; + size_t read = fread( _charBuffer, 1, size, fp ); + if ( read != size ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + _charBuffer[size] = 0; + + Parse(); + return _errorID; +} + + +XMLError XMLDocument::SaveFile( const char* filename, bool compact ) +{ + FILE* fp = callfopen( filename, "w" ); + if ( !fp ) { + SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 ); + return _errorID; + } + SaveFile(fp, compact); + fclose( fp ); + return _errorID; +} + + +XMLError XMLDocument::SaveFile( FILE* fp, bool compact ) +{ + XMLPrinter stream( fp, compact ); + Print( &stream ); + return _errorID; +} + + +XMLError XMLDocument::Parse( const char* p, size_t len ) +{ + Clear(); + + if ( len == 0 || !p || !*p ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return _errorID; + } + if ( len == (size_t)(-1) ) { + len = strlen( p ); + } + _charBuffer = new char[ len+1 ]; + memcpy( _charBuffer, p, len ); + _charBuffer[len] = 0; + + Parse(); + if ( Error() ) { + // clean up now essentially dangling memory. + // and the parse fail can put objects in the + // pools that are dead and inaccessible. + DeleteChildren(); + _elementPool.Clear(); + _attributePool.Clear(); + _textPool.Clear(); + _commentPool.Clear(); + } + return _errorID; +} + + +void XMLDocument::Print( XMLPrinter* streamer ) const +{ + XMLPrinter stdStreamer( stdout ); + if ( !streamer ) { + streamer = &stdStreamer; + } + Accept( streamer ); +} + + +void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 ) +{ + TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT ); + _errorID = error; + _errorStr1 = str1; + _errorStr2 = str2; +} + +const char* XMLDocument::ErrorName() const +{ + TIXMLASSERT( _errorID >= 0 && _errorID < XML_ERROR_COUNT ); + return _errorNames[_errorID]; +} + +void XMLDocument::PrintError() const +{ + if ( Error() ) { + static const int LEN = 20; + char buf1[LEN] = { 0 }; + char buf2[LEN] = { 0 }; + + if ( _errorStr1 ) { + TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 ); + } + if ( _errorStr2 ) { + TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 ); + } + + printf( "XMLDocument error id=%d '%s' str1=%s str2=%s\n", + _errorID, ErrorName(), buf1, buf2 ); + } +} + +void XMLDocument::Parse() +{ + TIXMLASSERT( NoChildren() ); // Clear() must have been called previously + TIXMLASSERT( _charBuffer ); + char* p = _charBuffer; + p = XMLUtil::SkipWhiteSpace( p ); + p = const_cast( XMLUtil::ReadBOM( p, &_writeBOM ) ); + if ( !*p ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return; + } + ParseDeep(p, 0 ); +} + +XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) : + _elementJustOpened( false ), + _firstElement( true ), + _fp( file ), + _depth( depth ), + _textDepth( -1 ), + _processEntities( true ), + _compactMode( compact ) +{ + for( int i=0; i'] = true; // not required, but consistency is nice + _buffer.Push( 0 ); +} + + +void XMLPrinter::Print( const char* format, ... ) +{ + va_list va; + va_start( va, format ); + + if ( _fp ) { + vfprintf( _fp, format, va ); + } + else { +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + #if defined(WINCE) + int len = 512; + do { + len = len*2; + char* str = new char[len](); + len = _vsnprintf(str, len, format, va); + delete[] str; + }while (len < 0); + #else + int len = _vscprintf( format, va ); + #endif +#else + int len = vsnprintf( 0, 0, format, va ); +#endif + // Close out and re-start the va-args + va_end( va ); + va_start( va, format ); + TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 ); + char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator. +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + #if defined(WINCE) + _vsnprintf( p, len+1, format, va ); + #else + vsnprintf_s( p, len+1, _TRUNCATE, format, va ); + #endif +#else + vsnprintf( p, len+1, format, va ); +#endif + } + va_end( va ); +} + + +void XMLPrinter::PrintSpace( int depth ) +{ + for( int i=0; i 0 && *q < ENTITY_RANGE ) { + // Check for entities. If one is found, flush + // the stream up until the entity, write the + // entity, and keep looking. + if ( flag[(unsigned char)(*q)] ) { + while ( p < q ) { + Print( "%c", *p ); + ++p; + } + for( int i=0; i 0) ) { + Print( "%s", p ); + } +} + + +void XMLPrinter::PushHeader( bool writeBOM, bool writeDec ) +{ + if ( writeBOM ) { + static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 }; + Print( "%s", bom ); + } + if ( writeDec ) { + PushDeclaration( "xml version=\"1.0\"" ); + } +} + + +void XMLPrinter::OpenElement( const char* name, bool compactMode ) +{ + SealElementIfJustOpened(); + _stack.Push( name ); + + if ( _textDepth < 0 && !_firstElement && !compactMode ) { + Print( "\n" ); + } + if ( !compactMode ) { + PrintSpace( _depth ); + } + + Print( "<%s", name ); + _elementJustOpened = true; + _firstElement = false; + ++_depth; +} + + +void XMLPrinter::PushAttribute( const char* name, const char* value ) +{ + TIXMLASSERT( _elementJustOpened ); + Print( " %s=\"", name ); + PrintString( value, false ); + Print( "\"" ); +} + + +void XMLPrinter::PushAttribute( const char* name, int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::PushAttribute( const char* name, unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::PushAttribute( const char* name, bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::PushAttribute( const char* name, double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::CloseElement( bool compactMode ) +{ + --_depth; + const char* name = _stack.Pop(); + + if ( _elementJustOpened ) { + Print( "/>" ); + } + else { + if ( _textDepth < 0 && !compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + Print( "", name ); + } + + if ( _textDepth == _depth ) { + _textDepth = -1; + } + if ( _depth == 0 && !compactMode) { + Print( "\n" ); + } + _elementJustOpened = false; +} + + +void XMLPrinter::SealElementIfJustOpened() +{ + if ( !_elementJustOpened ) { + return; + } + _elementJustOpened = false; + Print( ">" ); +} + + +void XMLPrinter::PushText( const char* text, bool cdata ) +{ + _textDepth = _depth-1; + + SealElementIfJustOpened(); + if ( cdata ) { + Print( "" ); + } + else { + PrintString( text, true ); + } +} + +void XMLPrinter::PushText( int value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( unsigned value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( bool value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( float value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( double value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushComment( const char* comment ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + _firstElement = false; + Print( "", comment ); +} + + +void XMLPrinter::PushDeclaration( const char* value ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + _firstElement = false; + Print( "", value ); +} + + +void XMLPrinter::PushUnknown( const char* value ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + _firstElement = false; + Print( "", value ); +} + + +bool XMLPrinter::VisitEnter( const XMLDocument& doc ) +{ + _processEntities = doc.ProcessEntities(); + if ( doc.HasBOM() ) { + PushHeader( true, false ); + } + return true; +} + + +bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) +{ + const XMLElement* parentElem = element.Parent()->ToElement(); + bool compactMode = parentElem ? CompactMode(*parentElem) : _compactMode; + OpenElement( element.Name(), compactMode ); + while ( attribute ) { + PushAttribute( attribute->Name(), attribute->Value() ); + attribute = attribute->Next(); + } + return true; +} + + +bool XMLPrinter::VisitExit( const XMLElement& element ) +{ + CloseElement( CompactMode(element) ); + return true; +} + + +bool XMLPrinter::Visit( const XMLText& text ) +{ + PushText( text.Value(), text.CData() ); + return true; +} + + +bool XMLPrinter::Visit( const XMLComment& comment ) +{ + PushComment( comment.Value() ); + return true; +} + +bool XMLPrinter::Visit( const XMLDeclaration& declaration ) +{ + PushDeclaration( declaration.Value() ); + return true; +} + + +bool XMLPrinter::Visit( const XMLUnknown& unknown ) +{ + PushUnknown( unknown.Value() ); + return true; +} + +} // namespace tinyxml2 + diff --git a/tinyxml2-3.0.0/tinyxml2.h b/tinyxml2-3.0.0/tinyxml2.h new file mode 100755 index 0000000..a4769c8 --- /dev/null +++ b/tinyxml2-3.0.0/tinyxml2.h @@ -0,0 +1,2130 @@ +/* +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#ifndef TINYXML2_INCLUDED +#define TINYXML2_INCLUDED + +#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +#endif + +/* + TODO: intern strings instead of allocation. +*/ +/* + gcc: + g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe + + Formatting, Artistic Style: + AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h +*/ + +#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__) +# ifndef DEBUG +# define DEBUG +# endif +#endif + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4251) +#endif + +#ifdef _WIN32 +# ifdef TINYXML2_EXPORT +# define TINYXML2_LIB __declspec(dllexport) +# elif defined(TINYXML2_IMPORT) +# define TINYXML2_LIB __declspec(dllimport) +# else +# define TINYXML2_LIB +# endif +#else +# define TINYXML2_LIB +#endif + + +#if defined(DEBUG) +# if defined(_MSC_VER) +# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like +# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); } //if ( !(x)) WinDebugBreak() +# elif defined (ANDROID_NDK) +# include +# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } +# else +# include +# define TIXMLASSERT assert +# endif +# else +# define TIXMLASSERT( x ) {} +#endif + + +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) +// Microsoft visual studio, version 2005 and higher. +/*int _snprintf_s( + char *buffer, + size_t sizeOfBuffer, + size_t count, + const char *format [, + argument] ... +);*/ +inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) +{ + va_list va; + va_start( va, format ); + int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); + va_end( va ); + return result; +} +#define TIXML_SSCANF sscanf_s +#elif defined WINCE +#define TIXML_SNPRINTF _snprintf +#define TIXML_SSCANF sscanf +#else +// GCC version 3 and higher +//#warning( "Using sn* functions." ) +#define TIXML_SNPRINTF snprintf +#define TIXML_SSCANF sscanf +#endif + +/* Versioning, past 1.0.14: + http://semver.org/ +*/ +static const int TIXML2_MAJOR_VERSION = 3; +static const int TIXML2_MINOR_VERSION = 0; +static const int TIXML2_PATCH_VERSION = 0; + +namespace tinyxml2 +{ +class XMLDocument; +class XMLElement; +class XMLAttribute; +class XMLComment; +class XMLText; +class XMLDeclaration; +class XMLUnknown; +class XMLPrinter; + +/* + A class that wraps strings. Normally stores the start and end + pointers into the XML file itself, and will apply normalization + and entity translation if actually read. Can also store (and memory + manage) a traditional char[] +*/ +class StrPair +{ +public: + enum { + NEEDS_ENTITY_PROCESSING = 0x01, + NEEDS_NEWLINE_NORMALIZATION = 0x02, + COLLAPSE_WHITESPACE = 0x04, + + TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, + TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, + ATTRIBUTE_NAME = 0, + ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, + ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, + COMMENT = NEEDS_NEWLINE_NORMALIZATION + }; + + StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {} + ~StrPair(); + + void Set( char* start, char* end, int flags ) { + Reset(); + _start = start; + _end = end; + _flags = flags | NEEDS_FLUSH; + } + + const char* GetStr(); + + bool Empty() const { + return _start == _end; + } + + void SetInternedStr( const char* str ) { + Reset(); + _start = const_cast(str); + } + + void SetStr( const char* str, int flags=0 ); + + char* ParseText( char* in, const char* endTag, int strFlags ); + char* ParseName( char* in ); + + void TransferTo( StrPair* other ); + +private: + void Reset(); + void CollapseWhitespace(); + + enum { + NEEDS_FLUSH = 0x100, + NEEDS_DELETE = 0x200 + }; + + // After parsing, if *_end != 0, it can be set to zero. + int _flags; + char* _start; + char* _end; + + StrPair( const StrPair& other ); // not supported + void operator=( StrPair& other ); // not supported, use TransferTo() +}; + + +/* + A dynamic array of Plain Old Data. Doesn't support constructors, etc. + Has a small initial memory pool, so that low or no usage will not + cause a call to new/delete +*/ +template +class DynArray +{ +public: + DynArray() { + _mem = _pool; + _allocated = INIT; + _size = 0; + } + + ~DynArray() { + if ( _mem != _pool ) { + delete [] _mem; + } + } + + void Clear() { + _size = 0; + } + + void Push( T t ) { + TIXMLASSERT( _size < INT_MAX ); + EnsureCapacity( _size+1 ); + _mem[_size++] = t; + } + + T* PushArr( int count ) { + TIXMLASSERT( count >= 0 ); + TIXMLASSERT( _size <= INT_MAX - count ); + EnsureCapacity( _size+count ); + T* ret = &_mem[_size]; + _size += count; + return ret; + } + + T Pop() { + TIXMLASSERT( _size > 0 ); + return _mem[--_size]; + } + + void PopArr( int count ) { + TIXMLASSERT( _size >= count ); + _size -= count; + } + + bool Empty() const { + return _size == 0; + } + + T& operator[](int i) { + TIXMLASSERT( i>= 0 && i < _size ); + return _mem[i]; + } + + const T& operator[](int i) const { + TIXMLASSERT( i>= 0 && i < _size ); + return _mem[i]; + } + + const T& PeekTop() const { + TIXMLASSERT( _size > 0 ); + return _mem[ _size - 1]; + } + + int Size() const { + TIXMLASSERT( _size >= 0 ); + return _size; + } + + int Capacity() const { + return _allocated; + } + + const T* Mem() const { + return _mem; + } + + T* Mem() { + return _mem; + } + +private: + DynArray( const DynArray& ); // not supported + void operator=( const DynArray& ); // not supported + + void EnsureCapacity( int cap ) { + TIXMLASSERT( cap > 0 ); + if ( cap > _allocated ) { + TIXMLASSERT( cap <= INT_MAX / 2 ); + int newAllocated = cap * 2; + T* newMem = new T[newAllocated]; + memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs + if ( _mem != _pool ) { + delete [] _mem; + } + _mem = newMem; + _allocated = newAllocated; + } + } + + T* _mem; + T _pool[INIT]; + int _allocated; // objects allocated + int _size; // number objects in use +}; + + +/* + Parent virtual class of a pool for fast allocation + and deallocation of objects. +*/ +class MemPool +{ +public: + MemPool() {} + virtual ~MemPool() {} + + virtual int ItemSize() const = 0; + virtual void* Alloc() = 0; + virtual void Free( void* ) = 0; + virtual void SetTracked() = 0; + virtual void Clear() = 0; +}; + + +/* + Template child class to create pools of the correct type. +*/ +template< int SIZE > +class MemPoolT : public MemPool +{ +public: + MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} + ~MemPoolT() { + Clear(); + } + + void Clear() { + // Delete the blocks. + while( !_blockPtrs.Empty()) { + Block* b = _blockPtrs.Pop(); + delete b; + } + _root = 0; + _currentAllocs = 0; + _nAllocs = 0; + _maxAllocs = 0; + _nUntracked = 0; + } + + virtual int ItemSize() const { + return SIZE; + } + int CurrentAllocs() const { + return _currentAllocs; + } + + virtual void* Alloc() { + if ( !_root ) { + // Need a new block. + Block* block = new Block(); + _blockPtrs.Push( block ); + + for( int i=0; ichunk[i].next = &block->chunk[i+1]; + } + block->chunk[COUNT-1].next = 0; + _root = block->chunk; + } + void* result = _root; + _root = _root->next; + + ++_currentAllocs; + if ( _currentAllocs > _maxAllocs ) { + _maxAllocs = _currentAllocs; + } + _nAllocs++; + _nUntracked++; + return result; + } + + virtual void Free( void* mem ) { + if ( !mem ) { + return; + } + --_currentAllocs; + Chunk* chunk = static_cast( mem ); +#ifdef DEBUG + memset( chunk, 0xfe, sizeof(Chunk) ); +#endif + chunk->next = _root; + _root = chunk; + } + void Trace( const char* name ) { + printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", + name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() ); + } + + void SetTracked() { + _nUntracked--; + } + + int Untracked() const { + return _nUntracked; + } + + // This number is perf sensitive. 4k seems like a good tradeoff on my machine. + // The test file is large, 170k. + // Release: VS2010 gcc(no opt) + // 1k: 4000 + // 2k: 4000 + // 4k: 3900 21000 + // 16k: 5200 + // 32k: 4300 + // 64k: 4000 21000 + enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private + +private: + MemPoolT( const MemPoolT& ); // not supported + void operator=( const MemPoolT& ); // not supported + + union Chunk { + Chunk* next; + char mem[SIZE]; + }; + struct Block { + Chunk chunk[COUNT]; + }; + DynArray< Block*, 10 > _blockPtrs; + Chunk* _root; + + int _currentAllocs; + int _nAllocs; + int _maxAllocs; + int _nUntracked; +}; + + + +/** + Implements the interface to the "Visitor pattern" (see the Accept() method.) + If you call the Accept() method, it requires being passed a XMLVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs + are simply called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its siblings will be visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the XMLDocument, although all nodes support visiting. + + You should never change the document from a callback. + + @sa XMLNode::Accept() +*/ +class TINYXML2_LIB XMLVisitor +{ +public: + virtual ~XMLVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { + return true; + } + /// Visit a document. + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { + return true; + } + + /// Visit an element. + virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { + return true; + } + /// Visit an element. + virtual bool VisitExit( const XMLElement& /*element*/ ) { + return true; + } + + /// Visit a declaration. + virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { + return true; + } + /// Visit a text node. + virtual bool Visit( const XMLText& /*text*/ ) { + return true; + } + /// Visit a comment node. + virtual bool Visit( const XMLComment& /*comment*/ ) { + return true; + } + /// Visit an unknown node. + virtual bool Visit( const XMLUnknown& /*unknown*/ ) { + return true; + } +}; + +// WARNING: must match XMLDocument::_errorNames[] +enum XMLError { + XML_SUCCESS = 0, + XML_NO_ERROR = 0, + XML_NO_ATTRIBUTE, + XML_WRONG_ATTRIBUTE_TYPE, + XML_ERROR_FILE_NOT_FOUND, + XML_ERROR_FILE_COULD_NOT_BE_OPENED, + XML_ERROR_FILE_READ_ERROR, + XML_ERROR_ELEMENT_MISMATCH, + XML_ERROR_PARSING_ELEMENT, + XML_ERROR_PARSING_ATTRIBUTE, + XML_ERROR_IDENTIFYING_TAG, + XML_ERROR_PARSING_TEXT, + XML_ERROR_PARSING_CDATA, + XML_ERROR_PARSING_COMMENT, + XML_ERROR_PARSING_DECLARATION, + XML_ERROR_PARSING_UNKNOWN, + XML_ERROR_EMPTY_DOCUMENT, + XML_ERROR_MISMATCHED_ELEMENT, + XML_ERROR_PARSING, + XML_CAN_NOT_CONVERT_TEXT, + XML_NO_TEXT_NODE, + + XML_ERROR_COUNT +}; + + +/* + Utility functionality. +*/ +class XMLUtil +{ +public: + static const char* SkipWhiteSpace( const char* p ) { + TIXMLASSERT( p ); + while( IsWhiteSpace(*p) ) { + ++p; + } + TIXMLASSERT( p ); + return p; + } + static char* SkipWhiteSpace( char* p ) { + return const_cast( SkipWhiteSpace( const_cast(p) ) ); + } + + // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't + // correct, but simple, and usually works. + static bool IsWhiteSpace( char p ) { + return !IsUTF8Continuation(p) && isspace( static_cast(p) ); + } + + inline static bool IsNameStartChar( unsigned char ch ) { + if ( ch >= 128 ) { + // This is a heuristic guess in attempt to not implement Unicode-aware isalpha() + return true; + } + if ( isalpha( ch ) ) { + return true; + } + return ch == ':' || ch == '_'; + } + + inline static bool IsNameChar( unsigned char ch ) { + return IsNameStartChar( ch ) + || isdigit( ch ) + || ch == '.' + || ch == '-'; + } + + inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { + if ( p == q ) { + return true; + } + int n = 0; + while( *p && *q && *p == *q && n(const_cast(this)->FirstChildElement( value )); + } + + /// Get the last child node, or null if none exists. + const XMLNode* LastChild() const { + return _lastChild; + } + + XMLNode* LastChild() { + return const_cast(const_cast(this)->LastChild() ); + } + + /** Get the last child element or optionally the last child + element with the specified name. + */ + const XMLElement* LastChildElement( const char* value=0 ) const; + + XMLElement* LastChildElement( const char* value=0 ) { + return const_cast(const_cast(this)->LastChildElement(value) ); + } + + /// Get the previous (left) sibling node of this node. + const XMLNode* PreviousSibling() const { + return _prev; + } + + XMLNode* PreviousSibling() { + return _prev; + } + + /// Get the previous (left) sibling element of this node, with an optionally supplied name. + const XMLElement* PreviousSiblingElement( const char* value=0 ) const ; + + XMLElement* PreviousSiblingElement( const char* value=0 ) { + return const_cast(const_cast(this)->PreviousSiblingElement( value ) ); + } + + /// Get the next (right) sibling node of this node. + const XMLNode* NextSibling() const { + return _next; + } + + XMLNode* NextSibling() { + return _next; + } + + /// Get the next (right) sibling element of this node, with an optionally supplied name. + const XMLElement* NextSiblingElement( const char* value=0 ) const; + + XMLElement* NextSiblingElement( const char* value=0 ) { + return const_cast(const_cast(this)->NextSiblingElement( value ) ); + } + + /** + Add a child node as the last (right) child. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the node does not + belong to the same document. + */ + XMLNode* InsertEndChild( XMLNode* addThis ); + + XMLNode* LinkEndChild( XMLNode* addThis ) { + return InsertEndChild( addThis ); + } + /** + Add a child node as the first (left) child. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the node does not + belong to the same document. + */ + XMLNode* InsertFirstChild( XMLNode* addThis ); + /** + Add a node after the specified child node. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the afterThis node + is not a child of this node, or if the node does not + belong to the same document. + */ + XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); + + /** + Delete all the children of this node. + */ + void DeleteChildren(); + + /** + Delete a child of this node. + */ + void DeleteChild( XMLNode* node ); + + /** + Make a copy of this node, but not its children. + You may pass in a Document pointer that will be + the owner of the new Node. If the 'document' is + null, then the node returned will be allocated + from the current Document. (this->GetDocument()) + + Note: if called on a XMLDocument, this will return null. + */ + virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; + + /** + Test if 2 nodes are the same, but don't test children. + The 2 nodes do not need to be in the same Document. + + Note: if called on a XMLDocument, this will return false. + */ + virtual bool ShallowEqual( const XMLNode* compare ) const = 0; + + /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the XMLVisitor interface. + + This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + XMLPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( XMLVisitor* visitor ) const = 0; + + // internal + virtual char* ParseDeep( char*, StrPair* ); + +protected: + XMLNode( XMLDocument* ); + virtual ~XMLNode(); + + XMLDocument* _document; + XMLNode* _parent; + mutable StrPair _value; + + XMLNode* _firstChild; + XMLNode* _lastChild; + + XMLNode* _prev; + XMLNode* _next; + +private: + MemPool* _memPool; + void Unlink( XMLNode* child ); + static void DeleteNode( XMLNode* node ); + void InsertChildPreamble( XMLNode* insertThis ) const; + + XMLNode( const XMLNode& ); // not supported + XMLNode& operator=( const XMLNode& ); // not supported +}; + + +/** XML text. + + Note that a text node can have child element nodes, for example: + @verbatim + This is bold + @endverbatim + + A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCData() and query it with CData(). +*/ +class TINYXML2_LIB XMLText : public XMLNode +{ + friend class XMLBase; + friend class XMLDocument; +public: + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLText* ToText() { + return this; + } + virtual const XMLText* ToText() const { + return this; + } + + /// Declare whether this should be CDATA or standard text. + void SetCData( bool isCData ) { + _isCData = isCData; + } + /// Returns true if this is a CDATA text element. + bool CData() const { + return _isCData; + } + + char* ParseDeep( char*, StrPair* endTag ); + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} + virtual ~XMLText() {} + +private: + bool _isCData; + + XMLText( const XMLText& ); // not supported + XMLText& operator=( const XMLText& ); // not supported +}; + + +/** An XML Comment. */ +class TINYXML2_LIB XMLComment : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLComment* ToComment() { + return this; + } + virtual const XMLComment* ToComment() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + char* ParseDeep( char*, StrPair* endTag ); + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLComment( XMLDocument* doc ); + virtual ~XMLComment(); + +private: + XMLComment( const XMLComment& ); // not supported + XMLComment& operator=( const XMLComment& ); // not supported +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXML-2 will happily read or write files without a declaration, + however. + + The text of the declaration isn't interpreted. It is parsed + and written as a string. +*/ +class TINYXML2_LIB XMLDeclaration : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLDeclaration* ToDeclaration() { + return this; + } + virtual const XMLDeclaration* ToDeclaration() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + char* ParseDeep( char*, StrPair* endTag ); + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLDeclaration( XMLDocument* doc ); + virtual ~XMLDeclaration(); + +private: + XMLDeclaration( const XMLDeclaration& ); // not supported + XMLDeclaration& operator=( const XMLDeclaration& ); // not supported +}; + + +/** Any tag that TinyXML-2 doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into XMLUnknowns. +*/ +class TINYXML2_LIB XMLUnknown : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLUnknown* ToUnknown() { + return this; + } + virtual const XMLUnknown* ToUnknown() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + char* ParseDeep( char*, StrPair* endTag ); + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLUnknown( XMLDocument* doc ); + virtual ~XMLUnknown(); + +private: + XMLUnknown( const XMLUnknown& ); // not supported + XMLUnknown& operator=( const XMLUnknown& ); // not supported +}; + + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not XMLNodes. You may only query the + Next() attribute in a list. +*/ +class TINYXML2_LIB XMLAttribute +{ + friend class XMLElement; +public: + /// The name of the attribute. + const char* Name() const; + + /// The value of the attribute. + const char* Value() const; + + /// The next attribute in the list. + const XMLAttribute* Next() const { + return _next; + } + + /** IntValue interprets the attribute as an integer, and returns the value. + If the value isn't an integer, 0 will be returned. There is no error checking; + use QueryIntValue() if you need error checking. + */ + int IntValue() const { + int i=0; + QueryIntValue( &i ); + return i; + } + /// Query as an unsigned integer. See IntValue() + unsigned UnsignedValue() const { + unsigned i=0; + QueryUnsignedValue( &i ); + return i; + } + /// Query as a boolean. See IntValue() + bool BoolValue() const { + bool b=false; + QueryBoolValue( &b ); + return b; + } + /// Query as a double. See IntValue() + double DoubleValue() const { + double d=0; + QueryDoubleValue( &d ); + return d; + } + /// Query as a float. See IntValue() + float FloatValue() const { + float f=0; + QueryFloatValue( &f ); + return f; + } + + /** QueryIntValue interprets the attribute as an integer, and returns the value + in the provided parameter. The function will return XML_NO_ERROR on success, + and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful. + */ + XMLError QueryIntValue( int* value ) const; + /// See QueryIntValue + XMLError QueryUnsignedValue( unsigned int* value ) const; + /// See QueryIntValue + XMLError QueryBoolValue( bool* value ) const; + /// See QueryIntValue + XMLError QueryDoubleValue( double* value ) const; + /// See QueryIntValue + XMLError QueryFloatValue( float* value ) const; + + /// Set the attribute to a string value. + void SetAttribute( const char* value ); + /// Set the attribute to value. + void SetAttribute( int value ); + /// Set the attribute to value. + void SetAttribute( unsigned value ); + /// Set the attribute to value. + void SetAttribute( bool value ); + /// Set the attribute to value. + void SetAttribute( double value ); + /// Set the attribute to value. + void SetAttribute( float value ); + +private: + enum { BUF_SIZE = 200 }; + + XMLAttribute() : _next( 0 ), _memPool( 0 ) {} + virtual ~XMLAttribute() {} + + XMLAttribute( const XMLAttribute& ); // not supported + void operator=( const XMLAttribute& ); // not supported + void SetName( const char* name ); + + char* ParseDeep( char* p, bool processEntities ); + + mutable StrPair _name; + mutable StrPair _value; + XMLAttribute* _next; + MemPool* _memPool; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TINYXML2_LIB XMLElement : public XMLNode +{ + friend class XMLBase; + friend class XMLDocument; +public: + /// Get the name of an element (which is the Value() of the node.) + const char* Name() const { + return Value(); + } + /// Set the name of the element. + void SetName( const char* str, bool staticMem=false ) { + SetValue( str, staticMem ); + } + + virtual XMLElement* ToElement() { + return this; + } + virtual const XMLElement* ToElement() const { + return this; + } + virtual bool Accept( XMLVisitor* visitor ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none + exists. For example: + + @verbatim + const char* value = ele->Attribute( "foo" ); + @endverbatim + + The 'value' parameter is normally null. However, if specified, + the attribute will only be returned if the 'name' and 'value' + match. This allow you to write code: + + @verbatim + if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar(); + @endverbatim + + rather than: + @verbatim + if ( ele->Attribute( "foo" ) ) { + if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar(); + } + @endverbatim + */ + const char* Attribute( const char* name, const char* value=0 ) const; + + /** Given an attribute name, IntAttribute() returns the value + of the attribute interpreted as an integer. 0 will be + returned if there is an error. For a method with error + checking, see QueryIntAttribute() + */ + int IntAttribute( const char* name ) const { + int i=0; + QueryIntAttribute( name, &i ); + return i; + } + /// See IntAttribute() + unsigned UnsignedAttribute( const char* name ) const { + unsigned i=0; + QueryUnsignedAttribute( name, &i ); + return i; + } + /// See IntAttribute() + bool BoolAttribute( const char* name ) const { + bool b=false; + QueryBoolAttribute( name, &b ); + return b; + } + /// See IntAttribute() + double DoubleAttribute( const char* name ) const { + double d=0; + QueryDoubleAttribute( name, &d ); + return d; + } + /// See IntAttribute() + float FloatAttribute( const char* name ) const { + float f=0; + QueryFloatAttribute( name, &f ); + return f; + } + + /** Given an attribute name, QueryIntAttribute() returns + XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion + can't be performed, or XML_NO_ATTRIBUTE if the attribute + doesn't exist. If successful, the result of the conversion + will be written to 'value'. If not successful, nothing will + be written to 'value'. This allows you to provide default + value: + + @verbatim + int value = 10; + QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 + @endverbatim + */ + XMLError QueryIntAttribute( const char* name, int* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryIntValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryUnsignedValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryBoolAttribute( const char* name, bool* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryBoolValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryDoubleAttribute( const char* name, double* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryDoubleValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryFloatAttribute( const char* name, float* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryFloatValue( value ); + } + + + /** Given an attribute name, QueryAttribute() returns + XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion + can't be performed, or XML_NO_ATTRIBUTE if the attribute + doesn't exist. It is overloaded for the primitive types, + and is a generally more convenient replacement of + QueryIntAttribute() and related functions. + + If successful, the result of the conversion + will be written to 'value'. If not successful, nothing will + be written to 'value'. This allows you to provide default + value: + + @verbatim + int value = 10; + QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 + @endverbatim + */ + int QueryAttribute( const char* name, int* value ) const { + return QueryIntAttribute( name, value ); + } + + int QueryAttribute( const char* name, unsigned int* value ) const { + return QueryUnsignedAttribute( name, value ); + } + + int QueryAttribute( const char* name, bool* value ) const { + return QueryBoolAttribute( name, value ); + } + + int QueryAttribute( const char* name, double* value ) const { + return QueryDoubleAttribute( name, value ); + } + + int QueryAttribute( const char* name, float* value ) const { + return QueryFloatAttribute( name, value ); + } + + /// Sets the named attribute to value. + void SetAttribute( const char* name, const char* value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, int value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, unsigned value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, bool value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, double value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, float value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + + /** + Delete an attribute. + */ + void DeleteAttribute( const char* name ); + + /// Return the first attribute in the list. + const XMLAttribute* FirstAttribute() const { + return _rootAttribute; + } + /// Query a specific attribute in the list. + const XMLAttribute* FindAttribute( const char* name ) const; + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the XMLText child + and accessing it directly. + + If the first child of 'this' is a XMLText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + */ + const char* GetText() const; + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, SetText() is limited compared to creating an XMLText child + and mutating it directly. + + If the first child of 'this' is a XMLText, SetText() sets its value to + the given string, otherwise it will create a first child that is an XMLText. + + This is a convenient method for setting the text of simple contained text: + @verbatim + This is text + fooElement->SetText( "Hullaballoo!" ); + Hullaballoo! + @endverbatim + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then it will not change "This is text", but rather prefix it with a text element: + @verbatim + Hullaballoo!This is text + @endverbatim + + For this XML: + @verbatim + + @endverbatim + SetText() will generate + @verbatim + Hullaballoo! + @endverbatim + */ + void SetText( const char* inText ); + /// Convenience method for setting text inside and element. See SetText() for important limitations. + void SetText( int value ); + /// Convenience method for setting text inside and element. See SetText() for important limitations. + void SetText( unsigned value ); + /// Convenience method for setting text inside and element. See SetText() for important limitations. + void SetText( bool value ); + /// Convenience method for setting text inside and element. See SetText() for important limitations. + void SetText( double value ); + /// Convenience method for setting text inside and element. See SetText() for important limitations. + void SetText( float value ); + + /** + Convenience method to query the value of a child text node. This is probably best + shown by example. Given you have a document is this form: + @verbatim + + 1 + 1.4 + + @endverbatim + + The QueryIntText() and similar functions provide a safe and easier way to get to the + "value" of x and y. + + @verbatim + int x = 0; + float y = 0; // types of x and y are contrived for example + const XMLElement* xElement = pointElement->FirstChildElement( "x" ); + const XMLElement* yElement = pointElement->FirstChildElement( "y" ); + xElement->QueryIntText( &x ); + yElement->QueryFloatText( &y ); + @endverbatim + + @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted + to the requested type, and XML_NO_TEXT_NODE if there is no child text to query. + + */ + XMLError QueryIntText( int* ival ) const; + /// See QueryIntText() + XMLError QueryUnsignedText( unsigned* uval ) const; + /// See QueryIntText() + XMLError QueryBoolText( bool* bval ) const; + /// See QueryIntText() + XMLError QueryDoubleText( double* dval ) const; + /// See QueryIntText() + XMLError QueryFloatText( float* fval ) const; + + // internal: + enum { + OPEN, // + CLOSED, // + CLOSING // + }; + int ClosingType() const { + return _closingType; + } + char* ParseDeep( char* p, StrPair* endTag ); + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +private: + XMLElement( XMLDocument* doc ); + virtual ~XMLElement(); + XMLElement( const XMLElement& ); // not supported + void operator=( const XMLElement& ); // not supported + + XMLAttribute* FindAttribute( const char* name ) { + return const_cast(const_cast(this)->FindAttribute( name )); + } + XMLAttribute* FindOrCreateAttribute( const char* name ); + //void LinkAttribute( XMLAttribute* attrib ); + char* ParseAttributes( char* p ); + static void DeleteAttribute( XMLAttribute* attribute ); + + enum { BUF_SIZE = 200 }; + int _closingType; + // The attribute list is ordered; there is no 'lastAttribute' + // because the list needs to be scanned for dupes before adding + // a new attribute. + XMLAttribute* _rootAttribute; +}; + + +enum Whitespace { + PRESERVE_WHITESPACE, + COLLAPSE_WHITESPACE +}; + + +/** A Document binds together all the functionality. + It can be saved, loaded, and printed to the screen. + All Nodes are connected and allocated to a Document. + If the Document is deleted, all its Nodes are also deleted. +*/ +class TINYXML2_LIB XMLDocument : public XMLNode +{ + friend class XMLElement; +public: + /// constructor + XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE ); + ~XMLDocument(); + + virtual XMLDocument* ToDocument() { + return this; + } + virtual const XMLDocument* ToDocument() const { + return this; + } + + /** + Parse an XML file from a character string. + Returns XML_NO_ERROR (0) on success, or + an errorID. + + You may optionally pass in the 'nBytes', which is + the number of bytes which will be parsed. If not + specified, TinyXML-2 will assume 'xml' points to a + null terminated string. + */ + XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) ); + + /** + Load an XML file from disk. + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError LoadFile( const char* filename ); + + /** + Load an XML file from disk. You are responsible + for providing and closing the FILE*. + + NOTE: The file should be opened as binary ("rb") + not text in order for TinyXML-2 to correctly + do newline normalization. + + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError LoadFile( FILE* ); + + /** + Save the XML file to disk. + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError SaveFile( const char* filename, bool compact = false ); + + /** + Save the XML file to disk. You are responsible + for providing and closing the FILE*. + + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError SaveFile( FILE* fp, bool compact = false ); + + bool ProcessEntities() const { + return _processEntities; + } + Whitespace WhitespaceMode() const { + return _whitespace; + } + + /** + Returns true if this document has a leading Byte Order Mark of UTF8. + */ + bool HasBOM() const { + return _writeBOM; + } + /** Sets whether to write the BOM when writing the file. + */ + void SetBOM( bool useBOM ) { + _writeBOM = useBOM; + } + + /** Return the root element of DOM. Equivalent to FirstChildElement(). + To get the first node, use FirstChild(). + */ + XMLElement* RootElement() { + return FirstChildElement(); + } + const XMLElement* RootElement() const { + return FirstChildElement(); + } + + /** Print the Document. If the Printer is not provided, it will + print to stdout. If you provide Printer, this can print to a file: + @verbatim + XMLPrinter printer( fp ); + doc.Print( &printer ); + @endverbatim + + Or you can use a printer to print to memory: + @verbatim + XMLPrinter printer; + doc.Print( &printer ); + // printer.CStr() has a const char* to the XML + @endverbatim + */ + void Print( XMLPrinter* streamer=0 ) const; + virtual bool Accept( XMLVisitor* visitor ) const; + + /** + Create a new Element associated with + this Document. The memory for the Element + is managed by the Document. + */ + XMLElement* NewElement( const char* name ); + /** + Create a new Comment associated with + this Document. The memory for the Comment + is managed by the Document. + */ + XMLComment* NewComment( const char* comment ); + /** + Create a new Text associated with + this Document. The memory for the Text + is managed by the Document. + */ + XMLText* NewText( const char* text ); + /** + Create a new Declaration associated with + this Document. The memory for the object + is managed by the Document. + + If the 'text' param is null, the standard + declaration is used.: + @verbatim + + @endverbatim + */ + XMLDeclaration* NewDeclaration( const char* text=0 ); + /** + Create a new Unknown associated with + this Document. The memory for the object + is managed by the Document. + */ + XMLUnknown* NewUnknown( const char* text ); + + /** + Delete a node associated with this document. + It will be unlinked from the DOM. + */ + void DeleteNode( XMLNode* node ); + + void SetError( XMLError error, const char* str1, const char* str2 ); + + /// Return true if there was an error parsing the document. + bool Error() const { + return _errorID != XML_NO_ERROR; + } + /// Return the errorID. + XMLError ErrorID() const { + return _errorID; + } + const char* ErrorName() const; + + /// Return a possibly helpful diagnostic location or string. + const char* GetErrorStr1() const { + return _errorStr1; + } + /// Return a possibly helpful secondary diagnostic location or string. + const char* GetErrorStr2() const { + return _errorStr2; + } + /// If there is an error, print it to stdout. + void PrintError() const; + + /// Clear the document, resetting it to the initial state. + void Clear(); + + // internal + char* Identify( char* p, XMLNode** node ); + + virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { + return 0; + } + virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { + return false; + } + +private: + XMLDocument( const XMLDocument& ); // not supported + void operator=( const XMLDocument& ); // not supported + + bool _writeBOM; + bool _processEntities; + XMLError _errorID; + Whitespace _whitespace; + const char* _errorStr1; + const char* _errorStr2; + char* _charBuffer; + + MemPoolT< sizeof(XMLElement) > _elementPool; + MemPoolT< sizeof(XMLAttribute) > _attributePool; + MemPoolT< sizeof(XMLText) > _textPool; + MemPoolT< sizeof(XMLComment) > _commentPool; + + static const char* _errorNames[XML_ERROR_COUNT]; + + void Parse(); +}; + + +/** + A XMLHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2 + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + XMLElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + XMLElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + XMLElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + XMLElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. XMLHandle addresses the verbosity + of such code. A XMLHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + XMLHandle docHandle( &document ); + XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + XMLHandle handleCopy = handle; + @endverbatim + + See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects. +*/ +class TINYXML2_LIB XMLHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + XMLHandle( XMLNode* node ) { + _node = node; + } + /// Create a handle from a node. + XMLHandle( XMLNode& node ) { + _node = &node; + } + /// Copy constructor + XMLHandle( const XMLHandle& ref ) { + _node = ref._node; + } + /// Assignment + XMLHandle& operator=( const XMLHandle& ref ) { + _node = ref._node; + return *this; + } + + /// Get the first child of this handle. + XMLHandle FirstChild() { + return XMLHandle( _node ? _node->FirstChild() : 0 ); + } + /// Get the first child element of this handle. + XMLHandle FirstChildElement( const char* value=0 ) { + return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 ); + } + /// Get the last child of this handle. + XMLHandle LastChild() { + return XMLHandle( _node ? _node->LastChild() : 0 ); + } + /// Get the last child element of this handle. + XMLHandle LastChildElement( const char* _value=0 ) { + return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 ); + } + /// Get the previous sibling of this handle. + XMLHandle PreviousSibling() { + return XMLHandle( _node ? _node->PreviousSibling() : 0 ); + } + /// Get the previous sibling element of this handle. + XMLHandle PreviousSiblingElement( const char* _value=0 ) { + return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 ); + } + /// Get the next sibling of this handle. + XMLHandle NextSibling() { + return XMLHandle( _node ? _node->NextSibling() : 0 ); + } + /// Get the next sibling element of this handle. + XMLHandle NextSiblingElement( const char* _value=0 ) { + return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 ); + } + + /// Safe cast to XMLNode. This can return null. + XMLNode* ToNode() { + return _node; + } + /// Safe cast to XMLElement. This can return null. + XMLElement* ToElement() { + return ( ( _node == 0 ) ? 0 : _node->ToElement() ); + } + /// Safe cast to XMLText. This can return null. + XMLText* ToText() { + return ( ( _node == 0 ) ? 0 : _node->ToText() ); + } + /// Safe cast to XMLUnknown. This can return null. + XMLUnknown* ToUnknown() { + return ( ( _node == 0 ) ? 0 : _node->ToUnknown() ); + } + /// Safe cast to XMLDeclaration. This can return null. + XMLDeclaration* ToDeclaration() { + return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() ); + } + +private: + XMLNode* _node; +}; + + +/** + A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the + same in all regards, except for the 'const' qualifiers. See XMLHandle for API. +*/ +class TINYXML2_LIB XMLConstHandle +{ +public: + XMLConstHandle( const XMLNode* node ) { + _node = node; + } + XMLConstHandle( const XMLNode& node ) { + _node = &node; + } + XMLConstHandle( const XMLConstHandle& ref ) { + _node = ref._node; + } + + XMLConstHandle& operator=( const XMLConstHandle& ref ) { + _node = ref._node; + return *this; + } + + const XMLConstHandle FirstChild() const { + return XMLConstHandle( _node ? _node->FirstChild() : 0 ); + } + const XMLConstHandle FirstChildElement( const char* value=0 ) const { + return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 ); + } + const XMLConstHandle LastChild() const { + return XMLConstHandle( _node ? _node->LastChild() : 0 ); + } + const XMLConstHandle LastChildElement( const char* _value=0 ) const { + return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 ); + } + const XMLConstHandle PreviousSibling() const { + return XMLConstHandle( _node ? _node->PreviousSibling() : 0 ); + } + const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const { + return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 ); + } + const XMLConstHandle NextSibling() const { + return XMLConstHandle( _node ? _node->NextSibling() : 0 ); + } + const XMLConstHandle NextSiblingElement( const char* _value=0 ) const { + return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 ); + } + + + const XMLNode* ToNode() const { + return _node; + } + const XMLElement* ToElement() const { + return ( ( _node == 0 ) ? 0 : _node->ToElement() ); + } + const XMLText* ToText() const { + return ( ( _node == 0 ) ? 0 : _node->ToText() ); + } + const XMLUnknown* ToUnknown() const { + return ( ( _node == 0 ) ? 0 : _node->ToUnknown() ); + } + const XMLDeclaration* ToDeclaration() const { + return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() ); + } + +private: + const XMLNode* _node; +}; + + +/** + Printing functionality. The XMLPrinter gives you more + options than the XMLDocument::Print() method. + + It can: + -# Print to memory. + -# Print to a file you provide. + -# Print XML without a XMLDocument. + + Print to Memory + + @verbatim + XMLPrinter printer; + doc.Print( &printer ); + SomeFunction( printer.CStr() ); + @endverbatim + + Print to a File + + You provide the file pointer. + @verbatim + XMLPrinter printer( fp ); + doc.Print( &printer ); + @endverbatim + + Print without a XMLDocument + + When loading, an XML parser is very useful. However, sometimes + when saving, it just gets in the way. The code is often set up + for streaming, and constructing the DOM is just overhead. + + The Printer supports the streaming case. The following code + prints out a trivially simple XML file without ever creating + an XML document. + + @verbatim + XMLPrinter printer( fp ); + printer.OpenElement( "foo" ); + printer.PushAttribute( "foo", "bar" ); + printer.CloseElement(); + @endverbatim +*/ +class TINYXML2_LIB XMLPrinter : public XMLVisitor +{ +public: + /** Construct the printer. If the FILE* is specified, + this will print to the FILE. Else it will print + to memory, and the result is available in CStr(). + If 'compact' is set to true, then output is created + with only required whitespace and newlines. + */ + XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 ); + virtual ~XMLPrinter() {} + + /** If streaming, write the BOM and declaration. */ + void PushHeader( bool writeBOM, bool writeDeclaration ); + /** If streaming, start writing an element. + The element must be closed with CloseElement() + */ + void OpenElement( const char* name, bool compactMode=false ); + /// If streaming, add an attribute to an open element. + void PushAttribute( const char* name, const char* value ); + void PushAttribute( const char* name, int value ); + void PushAttribute( const char* name, unsigned value ); + void PushAttribute( const char* name, bool value ); + void PushAttribute( const char* name, double value ); + /// If streaming, close the Element. + virtual void CloseElement( bool compactMode=false ); + + /// Add a text node. + void PushText( const char* text, bool cdata=false ); + /// Add a text node from an integer. + void PushText( int value ); + /// Add a text node from an unsigned. + void PushText( unsigned value ); + /// Add a text node from a bool. + void PushText( bool value ); + /// Add a text node from a float. + void PushText( float value ); + /// Add a text node from a double. + void PushText( double value ); + + /// Add a comment + void PushComment( const char* comment ); + + void PushDeclaration( const char* value ); + void PushUnknown( const char* value ); + + virtual bool VisitEnter( const XMLDocument& /*doc*/ ); + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { + return true; + } + + virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ); + virtual bool VisitExit( const XMLElement& element ); + + virtual bool Visit( const XMLText& text ); + virtual bool Visit( const XMLComment& comment ); + virtual bool Visit( const XMLDeclaration& declaration ); + virtual bool Visit( const XMLUnknown& unknown ); + + /** + If in print to memory mode, return a pointer to + the XML file in memory. + */ + const char* CStr() const { + return _buffer.Mem(); + } + /** + If in print to memory mode, return the size + of the XML file in memory. (Note the size returned + includes the terminating null.) + */ + int CStrSize() const { + return _buffer.Size(); + } + /** + If in print to memory mode, reset the buffer to the + beginning. + */ + void ClearBuffer() { + _buffer.Clear(); + _buffer.Push(0); + } + +protected: + virtual bool CompactMode( const XMLElement& ) { return _compactMode; } + + /** Prints out the space before an element. You may override to change + the space and tabs used. A PrintSpace() override should call Print(). + */ + virtual void PrintSpace( int depth ); + void Print( const char* format, ... ); + + void SealElementIfJustOpened(); + bool _elementJustOpened; + DynArray< const char*, 10 > _stack; + +private: + void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. + + bool _firstElement; + FILE* _fp; + int _depth; + int _textDepth; + bool _processEntities; + bool _compactMode; + + enum { + ENTITY_RANGE = 64, + BUF_SIZE = 200 + }; + bool _entityFlag[ENTITY_RANGE]; + bool _restrictedEntityFlag[ENTITY_RANGE]; + + DynArray< char, 20 > _buffer; +}; + + +} // tinyxml2 + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + +#endif // TINYXML2_INCLUDED diff --git a/tinyxml2-3.0.0/tinyxml2.pc.in b/tinyxml2-3.0.0/tinyxml2.pc.in new file mode 100644 index 0000000..5a44e89 --- /dev/null +++ b/tinyxml2-3.0.0/tinyxml2.pc.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=@CMAKE_INSTALL_LIBDIR@ +includedir=@CMAKE_INSTALL_INCLUDEDIR@ + +Name: TinyXML2 +Description: simple, small, C++ XML parser +Version: @GENERIC_LIB_VERSION@ +Libs: -L${libdir} -ltinyxml2 +Cflags: -I${includedir} diff --git a/tinyxml2-3.0.0/tinyxml2/test.vcxproj b/tinyxml2-3.0.0/tinyxml2/test.vcxproj new file mode 100644 index 0000000..0f04034 --- /dev/null +++ b/tinyxml2-3.0.0/tinyxml2/test.vcxproj @@ -0,0 +1,347 @@ + + + + + Debug-Dll + Win32 + + + Debug-Dll + x64 + + + Debug-Lib + Win32 + + + Debug-Lib + x64 + + + Release-Dll + Win32 + + + Release-Dll + x64 + + + Release-Lib + Win32 + + + Release-Lib + x64 + + + + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260} + test + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + Unicode + + + Unicode + true + + + Unicode + + + Unicode + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + + + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + + + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + + + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + + + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + + + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + + + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + + + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + + + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + + Level4 + Disabled + + + true + + + + + Level4 + Disabled + + + true + + + + + Level4 + Disabled + TINYXML2_IMPORT;%(PreprocessorDefinitions) + + + true + Console + + + + + Level4 + Disabled + TINYXML2_IMPORT;%(PreprocessorDefinitions) + + + true + Console + + + + + Level4 + MaxSpeed + true + true + + + true + true + true + + + + + Level4 + MaxSpeed + true + true + + + true + true + true + + + + + Level4 + MaxSpeed + true + true + AnySuitable + Speed + true + true + true + TINYXML2_IMPORT;%(PreprocessorDefinitions) + + + false + true + true + Console + true + + + + + Level4 + MaxSpeed + true + true + AnySuitable + Speed + true + true + true + TINYXML2_IMPORT;%(PreprocessorDefinitions) + + + false + true + true + Console + true + + + + + Level4 + + + Console + + + + + Level4 + AnySuitable + true + Speed + true + true + true + + + false + Console + true + true + true + + + + + Level4 + + + Console + + + + + Level4 + AnySuitable + true + Speed + true + true + true + + + false + Console + true + true + true + + + + + + + + {d1c528b6-aa02-4d29-9d61-dc08e317a70d} + + + + + + \ No newline at end of file diff --git a/tinyxml2-3.0.0/tinyxml2/test.vcxproj.filters b/tinyxml2-3.0.0/tinyxml2/test.vcxproj.filters new file mode 100644 index 0000000..271c2cf --- /dev/null +++ b/tinyxml2-3.0.0/tinyxml2/test.vcxproj.filters @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tinyxml2-3.0.0/tinyxml2/tinyxml2-cbp/README b/tinyxml2-3.0.0/tinyxml2/tinyxml2-cbp/README new file mode 100644 index 0000000..828448e --- /dev/null +++ b/tinyxml2-3.0.0/tinyxml2/tinyxml2-cbp/README @@ -0,0 +1,3 @@ +The (default) Release configuration of this project builds a ready to use static library. +The Debug configuration of this project builds an executable console application that +executes all tests provided for tinyxml2 in the xmltest.cpp file. \ No newline at end of file diff --git a/tinyxml2-3.0.0/tinyxml2/tinyxml2-cbp/tinyxml2-cbp.cbp b/tinyxml2-3.0.0/tinyxml2/tinyxml2-cbp/tinyxml2-cbp.cbp new file mode 100644 index 0000000..915746f --- /dev/null +++ b/tinyxml2-3.0.0/tinyxml2/tinyxml2-cbp/tinyxml2-cbp.cbp @@ -0,0 +1,49 @@ + + + + + + diff --git a/tinyxml2-3.0.0/tinyxml2/tinyxml2.sln b/tinyxml2-3.0.0/tinyxml2/tinyxml2.sln new file mode 100755 index 0000000..b91b0fe --- /dev/null +++ b/tinyxml2-3.0.0/tinyxml2/tinyxml2.sln @@ -0,0 +1,56 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyxml2", "tinyxml2.vcxproj", "{D1C528B6-AA02-4D29-9D61-DC08E317A70D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcxproj", "{E8FB2712-8666-4662-A5B8-2B5B0FB1A260}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug-Dll|Win32 = Debug-Dll|Win32 + Debug-Dll|x64 = Debug-Dll|x64 + Debug-Lib|Win32 = Debug-Lib|Win32 + Debug-Lib|x64 = Debug-Lib|x64 + Release-Dll|Win32 = Release-Dll|Win32 + Release-Dll|x64 = Release-Dll|x64 + Release-Lib|Win32 = Release-Lib|Win32 + Release-Lib|x64 = Release-Lib|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Debug-Dll|Win32.ActiveCfg = Debug-Dll|Win32 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Debug-Dll|Win32.Build.0 = Debug-Dll|Win32 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Debug-Dll|x64.ActiveCfg = Debug-Dll|x64 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Debug-Dll|x64.Build.0 = Debug-Dll|x64 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Debug-Lib|Win32.ActiveCfg = Debug-Lib|Win32 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Debug-Lib|Win32.Build.0 = Debug-Lib|Win32 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Debug-Lib|x64.ActiveCfg = Debug-Lib|x64 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Debug-Lib|x64.Build.0 = Debug-Lib|x64 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Release-Dll|Win32.ActiveCfg = Release-Dll|Win32 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Release-Dll|Win32.Build.0 = Release-Dll|Win32 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Release-Dll|x64.ActiveCfg = Release-Dll|x64 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Release-Dll|x64.Build.0 = Release-Dll|x64 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Release-Lib|Win32.ActiveCfg = Release-Lib|Win32 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Release-Lib|Win32.Build.0 = Release-Lib|Win32 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Release-Lib|x64.ActiveCfg = Release-Lib|x64 + {D1C528B6-AA02-4D29-9D61-DC08E317A70D}.Release-Lib|x64.Build.0 = Release-Lib|x64 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Debug-Dll|Win32.ActiveCfg = Debug-Dll|Win32 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Debug-Dll|Win32.Build.0 = Debug-Dll|Win32 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Debug-Dll|x64.ActiveCfg = Debug-Dll|x64 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Debug-Dll|x64.Build.0 = Debug-Dll|x64 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Debug-Lib|Win32.ActiveCfg = Debug-Lib|Win32 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Debug-Lib|Win32.Build.0 = Debug-Lib|Win32 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Debug-Lib|x64.ActiveCfg = Debug-Lib|x64 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Debug-Lib|x64.Build.0 = Debug-Lib|x64 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Release-Dll|Win32.ActiveCfg = Release-Dll|Win32 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Release-Dll|Win32.Build.0 = Release-Dll|Win32 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Release-Dll|x64.ActiveCfg = Release-Dll|x64 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Release-Dll|x64.Build.0 = Release-Dll|x64 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Release-Lib|Win32.ActiveCfg = Release-Lib|Win32 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Release-Lib|Win32.Build.0 = Release-Lib|Win32 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Release-Lib|x64.ActiveCfg = Release-Lib|x64 + {E8FB2712-8666-4662-A5B8-2B5B0FB1A260}.Release-Lib|x64.Build.0 = Release-Lib|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/tinyxml2-3.0.0/tinyxml2/tinyxml2.vcxproj b/tinyxml2-3.0.0/tinyxml2/tinyxml2.vcxproj new file mode 100755 index 0000000..1257faf --- /dev/null +++ b/tinyxml2-3.0.0/tinyxml2/tinyxml2.vcxproj @@ -0,0 +1,384 @@ + + + + + Debug-Dll + Win32 + + + Debug-Dll + x64 + + + Debug-Lib + Win32 + + + Debug-Lib + x64 + + + Release-Dll + Win32 + + + Release-Dll + x64 + + + Release-Lib + Win32 + + + Release-Lib + x64 + + + + {D1C528B6-AA02-4D29-9D61-DC08E317A70D} + Win32Proj + tinyxml2 + + + + StaticLibrary + true + Unicode + + + DynamicLibrary + true + Unicode + + + StaticLibrary + true + Unicode + + + DynamicLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + DynamicLibrary + false + true + Unicode + + + StaticLibrary + false + true + Unicode + + + DynamicLibrary + false + true + Unicode + + + StaticLibrary + Unicode + + + StaticLibrary + true + Unicode + + + StaticLibrary + Unicode + + + StaticLibrary + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + true + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + true + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + true + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + false + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + false + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + false + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + false + $(SolutionDir)bin\$(Platform)-$(Configuration)\ + $(SolutionDir)temp\$(Platform)-$(Configuration)\ + + + + + + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level4 + Disabled + WIN32;TINYXML2_EXPORT;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + NotSet + true + + + + + + + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level4 + Disabled + WIN32;TINYXML2_EXPORT;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + NotSet + true + + + + + Level4 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + AnySuitable + Speed + true + true + true + false + + + Console + true + true + true + true + + + + + Level4 + + + MaxSpeed + true + true + WIN32;TINYXML2_EXPORT;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + AnySuitable + Speed + true + true + true + false + + + NotSet + true + true + true + true + + + + + Level4 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + AnySuitable + Speed + true + true + true + false + + + Console + true + true + true + true + + + + + Level4 + + + MaxSpeed + true + true + WIN32;TINYXML2_EXPORT;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + AnySuitable + Speed + true + true + true + false + + + NotSet + true + true + true + true + + + + + true + + + + + true + + + AnySuitable + + + true + + + Speed + + + true + + + true + true + false + + + + + true + + + + + true + + + AnySuitable + + + true + + + Speed + + + true + + + true + true + false + + + + + + + + + + + + \ No newline at end of file diff --git a/tinyxml2-3.0.0/tinyxml2/tinyxml2.vcxproj.filters b/tinyxml2-3.0.0/tinyxml2/tinyxml2.vcxproj.filters new file mode 100755 index 0000000..ee188b2 --- /dev/null +++ b/tinyxml2-3.0.0/tinyxml2/tinyxml2.vcxproj.filters @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/tinyxml2-3.0.0/tinyxml2/tinyxml2.xcodeproj/project.pbxproj b/tinyxml2-3.0.0/tinyxml2/tinyxml2.xcodeproj/project.pbxproj new file mode 100644 index 0000000..58c4fcc --- /dev/null +++ b/tinyxml2-3.0.0/tinyxml2/tinyxml2.xcodeproj/project.pbxproj @@ -0,0 +1,211 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 037AE8A5151E692700E0F29F /* xmltest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 037AE8A3151E692700E0F29F /* xmltest.cpp */; }; + 03F28B53152E9B1B00D4CD90 /* tinyxml2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 03F28B4A152E9B1B00D4CD90 /* tinyxml2.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 037AE86D151E685F00E0F29F /* xmltest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xmltest; sourceTree = BUILT_PRODUCTS_DIR; }; + 037AE8A3151E692700E0F29F /* xmltest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = xmltest.cpp; path = ../xmltest.cpp; sourceTree = SOURCE_ROOT; }; + 03F28B4A152E9B1B00D4CD90 /* tinyxml2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tinyxml2.cpp; sourceTree = ""; }; + 03F28B4B152E9B1B00D4CD90 /* tinyxml2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tinyxml2.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 037AE86B151E685F00E0F29F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 037AE056151CCC5200E0F29F = { + isa = PBXGroup; + children = ( + 037AE069151CCC7000E0F29F /* Classes */, + 03F28B60152E9B4C00D4CD90 /* Libraries */, + 037AE06F151CCCB900E0F29F /* Products */, + ); + sourceTree = ""; + }; + 037AE069151CCC7000E0F29F /* Classes */ = { + isa = PBXGroup; + children = ( + 037AE8A3151E692700E0F29F /* xmltest.cpp */, + ); + name = Classes; + sourceTree = ""; + }; + 037AE06F151CCCB900E0F29F /* Products */ = { + isa = PBXGroup; + children = ( + 037AE86D151E685F00E0F29F /* xmltest */, + ); + name = Products; + sourceTree = ""; + }; + 03F28AD7152E9B1B00D4CD90 /* tinyxml2 */ = { + isa = PBXGroup; + children = ( + 03F28B4A152E9B1B00D4CD90 /* tinyxml2.cpp */, + 03F28B4B152E9B1B00D4CD90 /* tinyxml2.h */, + ); + name = tinyxml2; + path = ..; + sourceTree = SOURCE_ROOT; + }; + 03F28B60152E9B4C00D4CD90 /* Libraries */ = { + isa = PBXGroup; + children = ( + 03F28AD7152E9B1B00D4CD90 /* tinyxml2 */, + ); + name = Libraries; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 037AE86C151E685F00E0F29F /* xmltest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 037AE873151E687E00E0F29F /* Build configuration list for PBXNativeTarget "xmltest" */; + buildPhases = ( + 037AE86A151E685F00E0F29F /* Sources */, + 037AE86B151E685F00E0F29F /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = xmltest; + productName = tinyxml2; + productReference = 037AE86D151E685F00E0F29F /* xmltest */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 037AE058151CCC5200E0F29F /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0610; + }; + buildConfigurationList = 037AE05B151CCC5200E0F29F /* Build configuration list for PBXProject "tinyxml2" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 037AE056151CCC5200E0F29F; + productRefGroup = 037AE06F151CCCB900E0F29F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 037AE86C151E685F00E0F29F /* xmltest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 037AE86A151E685F00E0F29F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 037AE8A5151E692700E0F29F /* xmltest.cpp in Sources */, + 03F28B53152E9B1B00D4CD90 /* tinyxml2.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 037AE059151CCC5200E0F29F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CONFIGURATION_BUILD_DIR = "$(SYMROOT)/Debug"; + COPY_PHASE_STRIP = NO; + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = DEBUG; + ONLY_ACTIVE_ARCH = YES; + SYMROOT = build; + }; + name = Debug; + }; + 037AE05A151CCC5200E0F29F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + }; + name = Release; + }; + 037AE86F151E686000E0F29F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CONFIGURATION_BUILD_DIR = ..; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + INSTALL_PATH = /usr/local/bin; + MACOSX_DEPLOYMENT_TARGET = ""; + PREBINDING = NO; + PRODUCT_NAME = xmltest; + }; + name = Debug; + }; + 037AE870151E686000E0F29F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CONFIGURATION_BUILD_DIR = ..; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + MACOSX_DEPLOYMENT_TARGET = ""; + PREBINDING = NO; + PRODUCT_NAME = tinyxml2; + ZERO_LINK = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 037AE05B151CCC5200E0F29F /* Build configuration list for PBXProject "tinyxml2" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 037AE059151CCC5200E0F29F /* Debug */, + 037AE05A151CCC5200E0F29F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 037AE873151E687E00E0F29F /* Build configuration list for PBXNativeTarget "xmltest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 037AE86F151E686000E0F29F /* Debug */, + 037AE870151E686000E0F29F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 037AE058151CCC5200E0F29F /* Project object */; +} diff --git a/tinyxml2-3.0.0/xmltest.cpp b/tinyxml2-3.0.0/xmltest.cpp new file mode 100644 index 0000000..7a14759 --- /dev/null +++ b/tinyxml2-3.0.0/xmltest.cpp @@ -0,0 +1,1489 @@ +#if defined( _MSC_VER ) + #if !defined( _CRT_SECURE_NO_WARNINGS ) + #define _CRT_SECURE_NO_WARNINGS // This test file is not intended to be secure. + #endif +#endif + +#include "tinyxml2.h" +#include +#include +#include + +#if defined( _MSC_VER ) + #include // _mkdir + #include + #define WIN32_LEAN_AND_MEAN + #include + _CrtMemState startMemState; + _CrtMemState endMemState; +#elif defined(MINGW32) || defined(__MINGW32__) + #include // mkdir +#else + #include // mkdir +#endif + +using namespace tinyxml2; +using namespace std; +int gPass = 0; +int gFail = 0; + + +bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true, bool extraNL=false ) +{ + bool pass = !strcmp( expected, found ); + if ( pass ) + printf ("[pass]"); + else + printf ("[fail]"); + + if ( !echo ) { + printf (" %s\n", testString); + } + else { + if ( extraNL ) { + printf( " %s\n", testString ); + printf( "%s\n", expected ); + printf( "%s\n", found ); + } + else { + printf (" %s [%s][%s]\n", testString, expected, found); + } + } + + if ( pass ) + ++gPass; + else + ++gFail; + return pass; +} + + +template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true ) +{ + bool pass = ( expected == found ); + if ( pass ) + printf ("[pass]"); + else + printf ("[fail]"); + + if ( !echo ) + printf (" %s\n", testString); + else + printf (" %s [%d][%d]\n", testString, static_cast(expected), static_cast(found) ); + + if ( pass ) + ++gPass; + else + ++gFail; + return pass; +} + + +void NullLineEndings( char* p ) +{ + while( p && *p ) { + if ( *p == '\n' || *p == '\r' ) { + *p = 0; + return; + } + ++p; + } +} + + +int example_1() +{ + XMLDocument doc; + doc.LoadFile( "resources/dream.xml" ); + + return doc.ErrorID(); +} +/** @page Example-1 Load an XML File + * @dontinclude ./xmltest.cpp + * Basic XML file loading. + * The basic syntax to load an XML file from + * disk and check for an error. (ErrorID() + * will return 0 for no error.) + * @skip example_1() + * @until } + */ + + +int example_2() +{ + static const char* xml = ""; + XMLDocument doc; + doc.Parse( xml ); + + return doc.ErrorID(); +} +/** @page Example-2 Parse an XML from char buffer + * @dontinclude ./xmltest.cpp + * Basic XML string parsing. + * The basic syntax to parse an XML for + * a char* and check for an error. (ErrorID() + * will return 0 for no error.) + * @skip example_2() + * @until } + */ + + +int example_3() +{ + static const char* xml = + "" + "" + "" + "A Midsummer Night's Dream" + ""; + + XMLDocument doc; + doc.Parse( xml ); + + XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" ); + const char* title = titleElement->GetText(); + printf( "Name of play (1): %s\n", title ); + + XMLText* textNode = titleElement->FirstChild()->ToText(); + title = textNode->Value(); + printf( "Name of play (2): %s\n", title ); + + return doc.ErrorID(); +} +/** @page Example-3 Get information out of XML + @dontinclude ./xmltest.cpp + In this example, we navigate a simple XML + file, and read some interesting text. Note + that this example doesn't use error + checking; working code should check for null + pointers when walking an XML tree, or use + XMLHandle. + + (The XML is an excerpt from "dream.xml"). + + @skip example_3() + @until "; + + The structure of the XML file is: + +
    +
  • (declaration)
  • +
  • (dtd stuff)
  • +
  • Element "PLAY"
  • +
      +
    • Element "TITLE"
    • +
        +
      • Text "A Midsummer Night's Dream"
      • +
      +
    +
+ + For this example, we want to print out the + title of the play. The text of the title (what + we want) is child of the "TITLE" element which + is a child of the "PLAY" element. + + We want to skip the declaration and dtd, so the + method FirstChildElement() is a good choice. The + FirstChildElement() of the Document is the "PLAY" + Element, the FirstChildElement() of the "PLAY" Element + is the "TITLE" Element. + + @until ( "TITLE" ); + + We can then use the convenience function GetText() + to get the title of the play. + + @until title ); + + Text is just another Node in the XML DOM. And in + fact you should be a little cautious with it, as + text nodes can contain elements. + + @verbatim + Consider: A Midsummer Night's Dream + @endverbatim + + It is more correct to actually query the Text Node + if in doubt: + + @until title ); + + Noting that here we use FirstChild() since we are + looking for XMLText, not an element, and ToText() + is a cast from a Node to a XMLText. +*/ + + +bool example_4() +{ + static const char* xml = + "" + " " + " " + " 2" + " " + ""; + + XMLDocument doc; + doc.Parse( xml ); + + int v0 = 0; + int v1 = 0; + + XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" ); + attributeApproachElement->QueryIntAttribute( "v", &v0 ); + + XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" ); + textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 ); + + printf( "Both values are the same: %d and %d\n", v0, v1 ); + + return !doc.Error() && ( v0 == v1 ); +} +/** @page Example-4 Read attributes and text information. + @dontinclude ./xmltest.cpp + + There are fundamentally 2 ways of writing a key-value + pair into an XML file. (Something that's always annoyed + me about XML.) Either by using attributes, or by writing + the key name into an element and the value into + the text node wrapped by the element. Both approaches + are illustrated in this example, which shows two ways + to encode the value "2" into the key "v": + + @skip example_4() + @until ""; + + TinyXML-2 has accessors for both approaches. + + When using an attribute, you navigate to the XMLElement + with that attribute and use the QueryIntAttribute() + group of methods. (Also QueryFloatAttribute(), etc.) + + @skip XMLElement* attributeApproachElement + @until &v0 ); + + When using the text approach, you need to navigate + down one more step to the XMLElement that contains + the text. Note the extra FirstChildElement( "v" ) + in the code below. The value of the text can then + be safely queried with the QueryIntText() group + of methods. (Also QueryFloatText(), etc.) + + @skip XMLElement* textApproachElement + @until &v1 ); +*/ + + +int main( int argc, const char ** argv ) +{ + #if defined( _MSC_VER ) && defined( DEBUG ) + _CrtMemCheckpoint( &startMemState ); + // Enable MS Visual C++ debug heap memory leaks dump on exit + _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); + #endif + + #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__) + #if defined __MINGW64_VERSION_MAJOR && defined __MINGW64_VERSION_MINOR + //MINGW64: both 32 and 64-bit + mkdir( "resources/out/" ); + #else + _mkdir( "resources/out/" ); + #endif + #else + mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + #endif + + { + TIXMLASSERT( true ); + } + + if ( argc > 1 ) { + XMLDocument* doc = new XMLDocument(); + clock_t startTime = clock(); + doc->LoadFile( argv[1] ); + clock_t loadTime = clock(); + int errorID = doc->ErrorID(); + delete doc; doc = 0; + clock_t deleteTime = clock(); + + printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID ); + if ( !errorID ) { + printf( "Load time=%u\n", (unsigned)(loadTime - startTime) ); + printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) ); + printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) ); + } + exit(0); + } + + FILE* fp = fopen( "resources/dream.xml", "r" ); + if ( !fp ) { + printf( "Error opening test file 'dream.xml'.\n" + "Is your working directory the same as where \n" + "the xmltest.cpp and dream.xml file are?\n\n" + #if defined( _MSC_VER ) + "In windows Visual Studio you may need to set\n" + "Properties->Debugging->Working Directory to '..'\n" + #endif + ); + exit( 1 ); + } + fclose( fp ); + + XMLTest( "Example-1", 0, example_1() ); + XMLTest( "Example-2", 0, example_2() ); + XMLTest( "Example-3", 0, example_3() ); + XMLTest( "Example-4", true, example_4() ); + + /* ------ Example 2: Lookup information. ---- */ + + { + static const char* test[] = { "", + "", + "", + "", + "", + "", + " \n \n ", + "", + "", + "Text inside element.", + "", + "Text inside and bolded in the element.", + "Text inside and bolded in the element.", + "This & That.", + "", + 0 + }; + for( int i=0; test[i]; ++i ) { + XMLDocument doc; + doc.Parse( test[i] ); + doc.Print(); + printf( "----------------------------------------------\n" ); + } + } +#if 1 + { + static const char* test = ""; + + XMLDocument doc; + doc.Parse( test ); + doc.Print(); + } + + { + static const char* test = "Text before."; + XMLDocument doc; + doc.Parse( test ); + XMLElement* root = doc.FirstChildElement(); + XMLElement* newElement = doc.NewElement( "Subelement" ); + root->InsertEndChild( newElement ); + doc.Print(); + } + { + XMLDocument* doc = new XMLDocument(); + static const char* test = ""; + doc->Parse( test ); + delete doc; + } + { + // Test: Programmatic DOM + // Build: + // + // + // + // + // & Text! + // + + XMLDocument* doc = new XMLDocument(); + XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) ); + + XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) }; + for( int i=0; i<3; ++i ) { + sub[i]->SetAttribute( "attrib", i ); + } + element->InsertEndChild( sub[2] ); + XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) ); + element->InsertAfterChild( comment, sub[0] ); + element->InsertAfterChild( sub[0], sub[1] ); + sub[2]->InsertFirstChild( doc->NewText( "& Text!" )); + doc->Print(); + XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() ); + XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) ); + XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) ); + XMLTest( "Programmatic DOM", "& Text!", + doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() ); + + // And now deletion: + element->DeleteChild( sub[2] ); + doc->DeleteNode( comment ); + + element->FirstChildElement()->SetAttribute( "attrib", true ); + element->LastChildElement()->DeleteAttribute( "attrib" ); + + XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) ); + int value = 10; + int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value ); + XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE ); + XMLTest( "Programmatic DOM", value, 10 ); + + doc->Print(); + + { + XMLPrinter streamer; + doc->Print( &streamer ); + printf( "%s", streamer.CStr() ); + } + { + XMLPrinter streamer( 0, true ); + doc->Print( &streamer ); + XMLTest( "Compact mode", "", streamer.CStr(), false ); + } + doc->SaveFile( "./resources/out/pretty.xml" ); + doc->SaveFile( "./resources/out/compact.xml", true ); + delete doc; + } + { + // Test: Dream + // XML1 : 1,187,569 bytes in 31,209 allocations + // XML2 : 469,073 bytes in 323 allocations + //int newStart = gNew; + XMLDocument doc; + doc.LoadFile( "resources/dream.xml" ); + + doc.SaveFile( "resources/out/dreamout.xml" ); + doc.PrintError(); + + XMLTest( "Dream", "xml version=\"1.0\"", + doc.FirstChild()->ToDeclaration()->Value() ); + XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false ); + XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"", + doc.FirstChild()->NextSibling()->ToUnknown()->Value() ); + XMLTest( "Dream", "And Robin shall restore amends.", + doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() ); + XMLTest( "Dream", "And Robin shall restore amends.", + doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() ); + + XMLDocument doc2; + doc2.LoadFile( "resources/out/dreamout.xml" ); + XMLTest( "Dream-out", "xml version=\"1.0\"", + doc2.FirstChild()->ToDeclaration()->Value() ); + XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false ); + XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"", + doc2.FirstChild()->NextSibling()->ToUnknown()->Value() ); + XMLTest( "Dream-out", "And Robin shall restore amends.", + doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() ); + + //gNewTotal = gNew - newStart; + } + + + { + const char* error = "\n" + "\n" + " \n" + ""; + + XMLDocument doc; + doc.Parse( error ); + XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE ); + } + + { + const char* str = ""; + + XMLDocument doc; + doc.Parse( str ); + + XMLElement* ele = doc.FirstChildElement(); + + int iVal, result; + double dVal; + + result = ele->QueryDoubleAttribute( "attr0", &dVal ); + XMLTest( "Query attribute: int as double", result, (int)XML_NO_ERROR ); + XMLTest( "Query attribute: int as double", (int)dVal, 1 ); + result = ele->QueryDoubleAttribute( "attr1", &dVal ); + XMLTest( "Query attribute: double as double", result, (int)XML_NO_ERROR ); + XMLTest( "Query attribute: double as double", (int)dVal, 2 ); + result = ele->QueryIntAttribute( "attr1", &iVal ); + XMLTest( "Query attribute: double as int", result, (int)XML_NO_ERROR ); + XMLTest( "Query attribute: double as int", iVal, 2 ); + result = ele->QueryIntAttribute( "attr2", &iVal ); + XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE ); + result = ele->QueryIntAttribute( "bar", &iVal ); + XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE ); + } + + { + const char* str = ""; + + XMLDocument doc; + doc.Parse( str ); + + XMLElement* ele = doc.FirstChildElement(); + + int iVal, iVal2; + double dVal, dVal2; + + ele->SetAttribute( "str", "strValue" ); + ele->SetAttribute( "int", 1 ); + ele->SetAttribute( "double", -1.0 ); + + const char* cStr = ele->Attribute( "str" ); + ele->QueryIntAttribute( "int", &iVal ); + ele->QueryDoubleAttribute( "double", &dVal ); + + ele->QueryAttribute( "int", &iVal2 ); + ele->QueryAttribute( "double", &dVal2 ); + + XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" ); + XMLTest( "Attribute round trip. c-string.", "strValue", cStr ); + XMLTest( "Attribute round trip. int.", 1, iVal ); + XMLTest( "Attribute round trip. double.", -1, (int)dVal ); + XMLTest( "Alternate query", true, iVal == iVal2 ); + XMLTest( "Alternate query", true, dVal == dVal2 ); + } + + { + XMLDocument doc; + doc.LoadFile( "resources/utf8test.xml" ); + + // Get the attribute "value" from the "Russian" element and check it. + XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" ); + const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU, + 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 }; + + XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) ); + + const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U, + 0xd1U, 0x81U, 0xd1U, 0x81U, + 0xd0U, 0xbaU, 0xd0U, 0xb8U, + 0xd0U, 0xb9U, 0 }; + const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>"; + + XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText(); + XMLTest( "UTF-8: Browsing russian element name.", + russianText, + text->Value() ); + + // Now try for a round trip. + doc.SaveFile( "resources/out/utf8testout.xml" ); + + // Check the round trip. + int okay = 0; + + FILE* saved = fopen( "resources/out/utf8testout.xml", "r" ); + FILE* verify = fopen( "resources/utf8testverify.xml", "r" ); + + if ( saved && verify ) + { + okay = 1; + char verifyBuf[256]; + while ( fgets( verifyBuf, 256, verify ) ) + { + char savedBuf[256]; + fgets( savedBuf, 256, saved ); + NullLineEndings( verifyBuf ); + NullLineEndings( savedBuf ); + + if ( strcmp( verifyBuf, savedBuf ) ) + { + printf( "verify:%s<\n", verifyBuf ); + printf( "saved :%s<\n", savedBuf ); + okay = 0; + break; + } + } + } + if ( saved ) + fclose( saved ); + if ( verify ) + fclose( verify ); + XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay ); + } + + // --------GetText()----------- + { + const char* str = "This is text"; + XMLDocument doc; + doc.Parse( str ); + const XMLElement* element = doc.RootElement(); + + XMLTest( "GetText() normal use.", "This is text", element->GetText() ); + + str = "This is text"; + doc.Parse( str ); + element = doc.RootElement(); + + XMLTest( "GetText() contained element.", element->GetText() == 0, true ); + } + + + // --------SetText()----------- + { + const char* str = ""; + XMLDocument doc; + doc.Parse( str ); + XMLElement* element = doc.RootElement(); + + element->SetText("darkness."); + XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() ); + + element->SetText("blue flame."); + XMLTest( "SetText() replace.", "blue flame.", element->GetText() ); + + str = ""; + doc.Parse( str ); + element = doc.RootElement(); + + element->SetText("The driver"); + XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() ); + + element->SetText("horses"); + XMLTest( "SetText() replace with tag-like text.", "horses", element->GetText() ); + //doc.Print(); + + str = "Text in nested element"; + doc.Parse( str ); + element = doc.RootElement(); + + element->SetText("wolves"); + XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() ); + + str = ""; + doc.Parse( str ); + element = doc.RootElement(); + + element->SetText( "str" ); + XMLTest( "SetText types", "str", element->GetText() ); + + element->SetText( 1 ); + XMLTest( "SetText types", "1", element->GetText() ); + + element->SetText( 1U ); + XMLTest( "SetText types", "1", element->GetText() ); + + element->SetText( true ); + XMLTest( "SetText types", "1", element->GetText() ); // TODO: should be 'true'? + + element->SetText( 1.5f ); + XMLTest( "SetText types", "1.5", element->GetText() ); + + element->SetText( 1.5 ); + XMLTest( "SetText types", "1.5", element->GetText() ); + } + + + // ---------- CDATA --------------- + { + const char* str = "" + " the rules!\n" + "...since I make symbolic puns" + "]]>" + ""; + XMLDocument doc; + doc.Parse( str ); + doc.Print(); + + XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + false ); + } + + // ----------- CDATA ------------- + { + const char* str = "" + "I am > the rules!\n" + "...since I make symbolic puns" + "]]>" + ""; + XMLDocument doc; + doc.Parse( str ); + doc.Print(); + + XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + false ); + } + + // InsertAfterChild causes crash. + { + // InsertBeforeChild and InsertAfterChild causes crash. + XMLDocument doc; + XMLElement* parent = doc.NewElement( "Parent" ); + doc.InsertFirstChild( parent ); + + XMLElement* childText0 = doc.NewElement( "childText0" ); + XMLElement* childText1 = doc.NewElement( "childText1" ); + + XMLNode* childNode0 = parent->InsertEndChild( childText0 ); + XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 ); + + XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true ); + } + + { + // Entities not being written correctly. + // From Lynn Allen + + const char* passages = + "" + "" + " " + ""; + + XMLDocument doc; + doc.Parse( passages ); + XMLElement* psg = doc.RootElement()->FirstChildElement(); + const char* context = psg->Attribute( "context" ); + const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9."; + + XMLTest( "Entity transformation: read. ", expected, context, true ); + + FILE* textfile = fopen( "resources/out/textfile.txt", "w" ); + if ( textfile ) + { + XMLPrinter streamer( textfile ); + psg->Accept( &streamer ); + fclose( textfile ); + } + + textfile = fopen( "resources/out/textfile.txt", "r" ); + TIXMLASSERT( textfile ); + if ( textfile ) + { + char buf[ 1024 ]; + fgets( buf, 1024, textfile ); + XMLTest( "Entity transformation: write. ", + "\n", + buf, false ); + fclose( textfile ); + } + } + + { + // Suppress entities. + const char* passages = + "" + "" + "Crazy &ttk;" + ""; + + XMLDocument doc( false ); + doc.Parse( passages ); + + XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ), + "Line 5 has "quotation marks" and 'apostrophe marks'." ); + XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(), + "Crazy &ttk;" ); + doc.Print(); + } + + { + const char* test = ""; + + XMLDocument doc; + doc.Parse( test ); + XMLTest( "dot in names", doc.Error(), false ); + XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" ); + XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" ); + } + + { + const char* test = "1.1 Start easy ignore fin thickness "; + + XMLDocument doc; + doc.Parse( test ); + + XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText(); + XMLTest( "Entity with one digit.", + text->Value(), "1.1 Start easy ignore fin thickness\n", + false ); + } + + { + // DOCTYPE not preserved (950171) + // + const char* doctype = + "" + "" + "" + "" + ""; + + XMLDocument doc; + doc.Parse( doctype ); + doc.SaveFile( "resources/out/test7.xml" ); + doc.DeleteChild( doc.RootElement() ); + doc.LoadFile( "resources/out/test7.xml" ); + doc.Print(); + + const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown(); + XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() ); + + } + + { + // Comments do not stream out correctly. + const char* doctype = + ""; + XMLDocument doc; + doc.Parse( doctype ); + + XMLComment* comment = doc.FirstChild()->ToComment(); + + XMLTest( "Comment formatting.", " Somewhat ", comment->Value() ); + } + { + // Double attributes + const char* doctype = ""; + + XMLDocument doc; + doc.Parse( doctype ); + + XMLTest( "Parsing repeated attributes.", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() ); // is an error to tinyxml (didn't use to be, but caused issues) + doc.PrintError(); + } + + { + // Embedded null in stream. + const char* doctype = ""; + + XMLDocument doc; + doc.Parse( doctype ); + XMLTest( "Embedded null throws error.", true, doc.Error() ); + } + + { + // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717 + const char* str = ""; + XMLDocument doc; + doc.Parse( str ); + XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() ); + } + + { + // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717 + const char* str = " "; + XMLDocument doc; + doc.Parse( str ); + XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() ); + } + + { + // Low entities + XMLDocument doc; + doc.Parse( "" ); + const char result[] = { 0x0e, 0 }; + XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result ); + doc.Print(); + } + + { + // Attribute values with trailing quotes not handled correctly + XMLDocument doc; + doc.Parse( "" ); + XMLTest( "Throw error with bad end quotes.", doc.Error(), true ); + } + + { + // [ 1663758 ] Failure to report error on bad XML + XMLDocument xml; + xml.Parse(""); + XMLTest("Missing end tag at end of input", xml.Error(), true); + xml.Parse(" "); + XMLTest("Missing end tag with trailing whitespace", xml.Error(), true); + xml.Parse(""); + XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT); + } + + + { + // [ 1475201 ] TinyXML parses entities in comments + XMLDocument xml; + xml.Parse("" + "" ); + + XMLNode* e0 = xml.FirstChild(); + XMLNode* e1 = e0->NextSibling(); + XMLComment* c0 = e0->ToComment(); + XMLComment* c1 = e1->ToComment(); + + XMLTest( "Comments ignore entities.", " declarations for & ", c0->Value(), true ); + XMLTest( "Comments ignore entities.", " far & away ", c1->Value(), true ); + } + + { + XMLDocument xml; + xml.Parse( "" + "" + "" + "" + "" ); + xml.Print(); + + int count = 0; + + for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild(); + ele; + ele = ele->NextSibling() ) + { + ++count; + } + + XMLTest( "Comments iterate correctly.", 3, count ); + } + + { + // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well. + unsigned char buf[] = " " ); + XMLTest( "Handle end tag whitespace", false, xml.Error() ); + } + + { + // This one must not result in an infinite loop + XMLDocument xml; + xml.Parse( "loop" ); + XMLTest( "Infinite loop test.", true, true ); + } +#endif + { + const char* pub = " "; + XMLDocument doc; + doc.Parse( pub ); + + XMLDocument clone; + for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) { + XMLNode* copy = node->ShallowClone( &clone ); + clone.InsertEndChild( copy ); + } + + clone.Print(); + + int count=0; + const XMLNode* a=clone.FirstChild(); + const XMLNode* b=doc.FirstChild(); + for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) { + ++count; + XMLTest( "Clone and Equal", true, a->ShallowEqual( b )); + } + XMLTest( "Clone and Equal", 4, count ); + } + + { + // This shouldn't crash. + XMLDocument doc; + if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" )) + { + doc.PrintError(); + } + XMLTest( "Error in snprinf handling.", true, doc.Error() ); + } + + { + // Attribute ordering. + static const char* xml = ""; + XMLDocument doc; + doc.Parse( xml ); + XMLElement* ele = doc.FirstChildElement(); + + const XMLAttribute* a = ele->FirstAttribute(); + XMLTest( "Attribute order", "1", a->Value() ); + a = a->Next(); + XMLTest( "Attribute order", "2", a->Value() ); + a = a->Next(); + XMLTest( "Attribute order", "3", a->Value() ); + XMLTest( "Attribute order", "attrib3", a->Name() ); + + ele->DeleteAttribute( "attrib2" ); + a = ele->FirstAttribute(); + XMLTest( "Attribute order", "1", a->Value() ); + a = a->Next(); + XMLTest( "Attribute order", "3", a->Value() ); + + ele->DeleteAttribute( "attrib1" ); + ele->DeleteAttribute( "attrib3" ); + XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false ); + } + + { + // Make sure an attribute with a space in it succeeds. + static const char* xml0 = ""; + static const char* xml1 = ""; + static const char* xml2 = ""; + XMLDocument doc0; + doc0.Parse( xml0 ); + XMLDocument doc1; + doc1.Parse( xml1 ); + XMLDocument doc2; + doc2.Parse( xml2 ); + + XMLElement* ele = 0; + ele = doc0.FirstChildElement(); + XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) ); + ele = doc1.FirstChildElement(); + XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) ); + ele = doc2.FirstChildElement(); + XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) ); + } + + { + // Make sure we don't go into an infinite loop. + static const char* xml = ""; + XMLDocument doc; + doc.Parse( xml ); + XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement(); + XMLElement* ele1 = ele0->NextSiblingElement(); + bool equal = ele0->ShallowEqual( ele1 ); + + XMLTest( "Infinite loop in shallow equal.", true, equal ); + } + + // -------- Handles ------------ + { + static const char* xml = "Text"; + XMLDocument doc; + doc.Parse( xml ); + + XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement(); + XMLTest( "Handle, success, mutable", ele->Value(), "sub" ); + + XMLHandle docH( doc ); + ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement(); + XMLTest( "Handle, dne, mutable", false, ele != 0 ); + } + + { + static const char* xml = "Text"; + XMLDocument doc; + doc.Parse( xml ); + XMLConstHandle docH( doc ); + + const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement(); + XMLTest( "Handle, success, const", ele->Value(), "sub" ); + + ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement(); + XMLTest( "Handle, dne, const", false, ele != 0 ); + } + { + // Default Declaration & BOM + XMLDocument doc; + doc.InsertEndChild( doc.NewDeclaration() ); + doc.SetBOM( true ); + + XMLPrinter printer; + doc.Print( &printer ); + + static const char* result = "\xef\xbb\xbf"; + XMLTest( "BOM and default declaration", printer.CStr(), result, false ); + XMLTest( "CStrSize", printer.CStrSize(), 42, false ); + } + { + const char* xml = " This \nis ' text ' " + " This is ' text ' \n" + "This is ' \n\n text '" + ""; + XMLDocument doc( true, COLLAPSE_WHITESPACE ); + doc.Parse( xml ); + + const XMLElement* element = doc.FirstChildElement(); + for( const XMLElement* parent = element->FirstChildElement(); + parent; + parent = parent->NextSiblingElement() ) + { + XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() ); + } + } + +#if 0 + { + // Passes if assert doesn't fire. + XMLDocument xmlDoc; + + xmlDoc.NewDeclaration(); + xmlDoc.NewComment("Configuration file"); + + XMLElement *root = xmlDoc.NewElement("settings"); + root->SetAttribute("version", 2); + } +#endif + + { + const char* xml = " "; + XMLDocument doc( true, COLLAPSE_WHITESPACE ); + doc.Parse( xml ); + XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() ); + } + + { + // An assert should not fire. + const char* xml = ""; + XMLDocument doc; + doc.Parse( xml ); + XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope. + XMLTest( "Tracking unused elements", true, ele != 0, false ); + } + + + { + const char* xml = "abc"; + XMLDocument doc; + doc.Parse( xml ); + XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child"); + + XMLPrinter printer; + ele->Accept( &printer ); + XMLTest( "Printing of sub-element", "abc\n", printer.CStr(), false ); + } + + + { + XMLDocument doc; + XMLError error = doc.LoadFile( "resources/empty.xml" ); + XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error ); + XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() ); + doc.PrintError(); + } + + { + // BOM preservation + static const char* xml_bom_preservation = "\xef\xbb\xbf\n"; + { + XMLDocument doc; + XMLTest( "BOM preservation (parse)", XML_NO_ERROR, doc.Parse( xml_bom_preservation ), false ); + XMLPrinter printer; + doc.Print( &printer ); + + XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true ); + doc.SaveFile( "resources/bomtest.xml" ); + } + { + XMLDocument doc; + doc.LoadFile( "resources/bomtest.xml" ); + XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false ); + + XMLPrinter printer; + doc.Print( &printer ); + XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true ); + } + } + + { + // Insertion with Removal + const char* xml = "" + "" + "" + "" + "element 1text" + "" + "" + "" + ""; + const char* xmlInsideTwo = "" + "" + "" + "" + "" + "element 1text" + "" + "" + ""; + const char* xmlAfterOne = "" + "" + "" + "" + "element 1text" + "" + "" + ""; + const char* xmlAfterTwo = "" + "" + "" + "" + "" + "element 1text" + "" + ""; + + XMLDocument doc; + doc.Parse(xml); + XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree"); + XMLElement* two = doc.RootElement()->FirstChildElement("two"); + two->InsertFirstChild(subtree); + XMLPrinter printer1(0, true); + doc.Accept(&printer1); + XMLTest("Move node from within to ", xmlInsideTwo, printer1.CStr()); + + doc.Parse(xml); + subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree"); + two = doc.RootElement()->FirstChildElement("two"); + doc.RootElement()->InsertAfterChild(two, subtree); + XMLPrinter printer2(0, true); + doc.Accept(&printer2); + XMLTest("Move node from within after ", xmlAfterTwo, printer2.CStr(), false); + + doc.Parse(xml); + XMLNode* one = doc.RootElement()->FirstChildElement("one"); + subtree = one->FirstChildElement("subtree"); + doc.RootElement()->InsertAfterChild(one, subtree); + XMLPrinter printer3(0, true); + doc.Accept(&printer3); + XMLTest("Move node from within after ", xmlAfterOne, printer3.CStr(), false); + + doc.Parse(xml); + subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree"); + two = doc.RootElement()->FirstChildElement("two"); + doc.RootElement()->InsertEndChild(subtree); + XMLPrinter printer4(0, true); + doc.Accept(&printer4); + XMLTest("Move node from within after ", xmlAfterTwo, printer4.CStr(), false); + } + + { + const char* xml = "" + " " + ""; + XMLDocument doc; + doc.Parse(xml); + doc.Print(); + } + + { + // Test that it doesn't crash. + const char* xml = "<12"; + XMLDocument doc; + doc.Parse(xml); + doc.PrintError(); + } + +#if 1 + // the question being explored is what kind of print to use: + // https://github.com/leethomason/tinyxml2/issues/63 + { + //const char* xml = ""; + const char* xml = ""; + XMLDocument doc; + doc.Parse( xml ); + doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 ); + doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 ); + doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 ); + doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 ); + doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 ); + doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 ); + + doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f ); + doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f ); + doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f ); + doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f ); + doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f ); + doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f ); + + doc.Print(); + + /* The result of this test is platform, compiler, and library version dependent. :(" + XMLPrinter printer; + doc.Print( &printer ); + XMLTest( "Float and double formatting.", + "\n", + printer.CStr(), + true ); + */ + } +#endif + + { + // Issue #184 + // If it doesn't assert, it passes. Caused by objects + // getting created during parsing which are then + // inaccessible in the memory pools. + { + XMLDocument doc; + doc.Parse(""); + } + { + XMLDocument doc; + doc.Parse(""); + doc.Clear(); + } + } + + { + // If this doesn't assert in DEBUG, all is well. + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement *pRoot = doc.NewElement("Root"); + doc.DeleteNode(pRoot); + } + + { + // Should not assert in DEBUG + XMLPrinter printer; + } + + { + // Issue 291. Should not crash + const char* xml = "�"; + XMLDocument doc; + doc.Parse( xml ); + + XMLPrinter printer; + doc.Print( &printer ); + } + + // ----------- Performance tracking -------------- + { +#if defined( _MSC_VER ) + __int64 start, end, freq; + QueryPerformanceFrequency( (LARGE_INTEGER*) &freq ); +#endif + + FILE* fp = fopen( "resources/dream.xml", "r" ); + fseek( fp, 0, SEEK_END ); + long size = ftell( fp ); + fseek( fp, 0, SEEK_SET ); + + char* mem = new char[size+1]; + fread( mem, size, 1, fp ); + fclose( fp ); + mem[size] = 0; + +#if defined( _MSC_VER ) + QueryPerformanceCounter( (LARGE_INTEGER*) &start ); +#else + clock_t cstart = clock(); +#endif + static const int COUNT = 10; + for( int i=0; i