Index: branches/FEPSimulator/DataPacker.h
===================================================================
--- branches/FEPSimulator/DataPacker.h	(revision 80)
+++ branches/FEPSimulator/DataPacker.h	(revision 80)
@@ -0,0 +1,47 @@
+/* 
+ * File:   DataPacker.h
+ *
+ * DataPacker has a single static public method packData(..) that returns the
+ * packed data message that is sent to the ATMS Server in the fep_reply struct
+ * via RPC.
+ * 
+ * @author John A. Torres
+ * @version 9/8/2017
+ */
+
+#ifndef DATAPACKER_H
+#define	DATAPACKER_H
+
+// Include dependencies
+#include "network.h";
+#include <iostream>
+#include <string.h>
+
+class DataPacker {
+    
+public:
+    /**
+     * Returns packed data message to be sent to ATMS Server in fep_reply via RPC
+     * 
+     * @param station The station for which the message is to be made
+     * @return The packed data message
+     */
+    static unsigned char * packData(STATION *station);
+
+private:
+    static unsigned char *msg;
+    // Packs the static data in message sent to ATMS
+    unsigned char * staticDataPack(STATION *station);
+    // Packs dynamic data in message sent to ATMS
+    int dynamicDataPack(STATION *station, int packNo, int pos);
+    // Sets last byte of message
+    char chksum(unsigned char *dataptr, int len);
+    // Tells whether or not data is available for specified lane
+    bool DataAvail(char flag, int num);
+    // Helper function: packs vol and occ into two byte data packet
+    VOLOCC packVOLOCC(int vol, int occ);
+
+};
+
+#endif	/* DATAPACKER_H */
+
Index: branches/FEPSimulator/nbproject/private/configurations.xml
===================================================================
--- branches/fep_rpc_client/nbproject/private/configurations.xml	(revision 78)
+++ branches/FEPSimulator/nbproject/private/configurations.xml	(revision 80)
@@ -14,6 +14,4 @@
           <gdbinterceptoptions gdb_all="false" gdb_unhandled="true" gdb_unexpected="true"/>
         </gdb_interceptlist>
-        <gdb_signals>
-        </gdb_signals>
         <gdb_options>
           <DebugOptions>
Index: branches/FEPSimulator/nbproject/private/private.xml
===================================================================
--- branches/fep_rpc_client/nbproject/private/private.xml	(revision 78)
+++ branches/FEPSimulator/nbproject/private/private.xml	(revision 80)
@@ -8,9 +8,12 @@
     <open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
         <group>
-            <file>file:/home/andrew/tmcsim/branches/fep_rpc_client/NetworkReader.h</file>
-            <file>file:/home/andrew/tmcsim/branches/fep_rpc_client/FEPClient.cpp</file>
-            <file>file:/home/andrew/tmcsim/branches/fep_rpc_client/network.h</file>
-            <file>file:/home/andrew/tmcsim/branches/fep_rpc_client/fep.h</file>
-            <file>file:/home/andrew/tmcsim/branches/fep_rpc_client/NetworkReader.cpp</file>
+            <file>file:/home/andrew/tmcsimulator/branches/fep_rpc_client/NetworkReader.cpp</file>
+            <file>file:/home/andrew/tmcsimulator/branches/fep_rpc_client/NetworkReader.h</file>
+            <file>file:/home/andrew/tmcsimulator/branches/fep_rpc_client/network.h</file>
+            <file>file:/home/andrew/tmcsimulator/branches/fep_rpc_client/FEPClient.cpp</file>
+            <file>file:/home/andrew/tmcsimulator/branches/fep_rpc_client/fep.h</file>
+            <file>file:/home/andrew/tmcsimulator/branches/fep_rpc_client/DataPacker.h</file>
+            <file>file:/home/andrew/tmcsimulator/branches/fep_rpc_client/DataPacker.cpp</file>
+            <file>file:/home/andrew/tmcsimulator/branches/fep_rpc_client/FEPClient.h</file>
         </group>
     </open-files>
Index: branches/FEPSimulator/nbproject/Makefile-Release.mk
===================================================================
--- branches/fep_rpc_client/nbproject/Makefile-Release.mk	(revision 77)
+++ branches/FEPSimulator/nbproject/Makefile-Release.mk	(revision 80)
@@ -36,4 +36,5 @@
 # Object Files
 OBJECTFILES= \
+	${OBJECTDIR}/DataPacker.o \
 	${OBJECTDIR}/FEPClient.o \
 	${OBJECTDIR}/NetworkReader.o \
@@ -65,4 +66,9 @@
 	${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
 	${LINK.cc} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/fep_rpc_client ${OBJECTFILES} ${LDLIBSOPTIONS}
+
+${OBJECTDIR}/DataPacker.o: DataPacker.cpp 
+	${MKDIR} -p ${OBJECTDIR}
+	${RM} "$@.d"
+	$(COMPILE.cc) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/DataPacker.o DataPacker.cpp
 
 ${OBJECTDIR}/FEPClient.o: FEPClient.cpp 
Index: branches/FEPSimulator/nbproject/project.xml
===================================================================
--- branches/fep_rpc_client/nbproject/project.xml	(revision 77)
+++ branches/FEPSimulator/nbproject/project.xml	(revision 80)
@@ -4,5 +4,5 @@
     <configuration>
         <data xmlns="http://www.netbeans.org/ns/make-project/1">
-            <name>fep_rpc_client</name>
+            <name>FEPSimulator</name>
             <c-extensions>c</c-extensions>
             <cpp-extensions>cpp</cpp-extensions>
Index: branches/FEPSimulator/nbproject/Makefile-Debug.mk
===================================================================
--- branches/fep_rpc_client/nbproject/Makefile-Debug.mk	(revision 77)
+++ branches/FEPSimulator/nbproject/Makefile-Debug.mk	(revision 80)
@@ -36,4 +36,5 @@
 # Object Files
 OBJECTFILES= \
+	${OBJECTDIR}/DataPacker.o \
 	${OBJECTDIR}/FEPClient.o \
 	${OBJECTDIR}/NetworkReader.o \
@@ -56,5 +57,5 @@
 
 # Link Libraries and Options
-LDLIBSOPTIONS=tinyxml/libtinyxml.a
+LDLIBSOPTIONS=tinyxml/tinyxml.a
 
 # Build Targets
@@ -62,9 +63,14 @@
 	"${MAKE}"  -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/fep_rpc_client
 
-${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/fep_rpc_client: tinyxml/libtinyxml.a
+${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/fep_rpc_client: tinyxml/tinyxml.a
 
 ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/fep_rpc_client: ${OBJECTFILES}
 	${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
 	${LINK.cc} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/fep_rpc_client ${OBJECTFILES} ${LDLIBSOPTIONS}
+
+${OBJECTDIR}/DataPacker.o: DataPacker.cpp 
+	${MKDIR} -p ${OBJECTDIR}
+	${RM} "$@.d"
+	$(COMPILE.cc) -g -Itinyxml -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/DataPacker.o DataPacker.cpp
 
 ${OBJECTDIR}/FEPClient.o: FEPClient.cpp 
Index: branches/FEPSimulator/nbproject/configurations.xml
===================================================================
--- branches/fep_rpc_client/nbproject/configurations.xml	(revision 77)
+++ branches/FEPSimulator/nbproject/configurations.xml	(revision 80)
@@ -5,4 +5,5 @@
                    displayName="Header Files"
                    projectFiles="true">
+      <itemPath>DataPacker.h</itemPath>
       <itemPath>FEPClient.h</itemPath>
       <itemPath>NetworkReader.h</itemPath>
@@ -17,4 +18,5 @@
                    displayName="Source Files"
                    projectFiles="true">
+      <itemPath>DataPacker.cpp</itemPath>
       <itemPath>FEPClient.cpp</itemPath>
       <itemPath>NetworkReader.cpp</itemPath>
@@ -50,8 +52,12 @@
         <linkerTool>
           <linkerLibItems>
-            <linkerLibFileItem>tinyxml/libtinyxml.a</linkerLibFileItem>
+            <linkerLibFileItem>tinyxml/tinyxml.a</linkerLibFileItem>
           </linkerLibItems>
         </linkerTool>
       </compileType>
+      <item path="DataPacker.cpp" ex="false" tool="1" flavor2="0">
+      </item>
+      <item path="DataPacker.h" ex="false" tool="3" flavor2="0">
+      </item>
       <item path="FEPClient.cpp" ex="false" tool="1" flavor2="0">
       </item>
@@ -91,4 +97,8 @@
         </asmTool>
       </compileType>
+      <item path="DataPacker.cpp" ex="false" tool="1" flavor2="0">
+      </item>
+      <item path="DataPacker.h" ex="false" tool="3" flavor2="0">
+      </item>
       <item path="FEPClient.cpp" ex="false" tool="1" flavor2="0">
       </item>
Index: branches/FEPSimulator/FEPClient.cpp
===================================================================
--- branches/fep_rpc_client/FEPClient.cpp	(revision 78)
+++ branches/FEPSimulator/FEPClient.cpp	(revision 80)
@@ -7,9 +7,8 @@
  * @param networkFile the xml network file
  */
-FEPClient::FEPClient(char * host, char * networkFile)
-{
-	createClient(host);
-	networkReader = new NetworkReader(networkFile);
-	updateATMS();
+FEPClient::FEPClient(char * host, char * networkFile) {
+    networkReader = new NetworkReader(networkFile);
+    createClient(host);
+    updateATMS();
 }
 
@@ -17,8 +16,7 @@
  * Destructor
  */
-FEPClient::~FEPClient()
-{
-	cout << "Destroying client..." << endl;
-	clnt_destroy(clnt);
+FEPClient::~FEPClient() {
+    cout << "Destroying client..." << endl;
+    clnt_destroy(clnt);
 }
 
@@ -27,16 +25,12 @@
  * @param response pointer to fep_reply struct
  */
-void FEPClient::handleCallResponse(void *response)
-{
-	/* If ATMS reply call fails */
-	if (response == NULL)
-	{
-		clnt_perror(clnt, "RPC call failed");
-	}
-	/* If ATMS reply is successful */
-	else
-	{
-		cout << "Successful RPC call to ATMS..." << endl;
-	}
+void FEPClient::handleCallResponse(void *response) {
+    /* If ATMS reply call fails */
+    if (response == NULL) {
+        clnt_perror(clnt, "RPC call failed");
+    }        /* If ATMS reply is successful */
+    else {
+        cout << "Successful RPC call to ATMS..." << endl;
+    }
 }
 
@@ -44,85 +38,82 @@
  * Sends an fep_reply for every line in the FEP.
  */
-void FEPClient::updateATMS()
-{
-	int i, j; // i == line_index, j == lds_index
-	void *rv;
+void FEPClient::updateATMS() {
+    int i, j; // i == line_index, j == lds_index
+    void *rv;
 
-    vector<FEP_LINE> lines = networkReader->getLines();
-    vector<LDS_LOOP> ldsMap = networkReader->getStations();
+    vector<FEP_LINE*> lines = networkReader->getLines();
+    vector<STATION*> ldsMap = networkReader->getStations();
 
-	// Send one reply for every "line" in the FEP
-	for (i = 0; i < lines.size(); i++)
-	{
-		fep_reply  fepReply;
-                cout << "Sending fepReply for line #" << lines.at(i).lineNum << endl;
-		// populate reply
-		fepReply.reply = SHORTPOLL;
-		fepReply.schedule = lines.at(i).schedule;
-		fepReply.lineinfo = lines.at(i).lineInfo;
-		fepReply.kind = (enum polltype) 0;
-		fepReply.flag = (enum replykind) 0;
+    // Send one reply for every "line" in the FEP
+    for (i = 0; i < lines.size(); i++) {
+        fep_reply fepReply;
+        cout << "Sending fepReply for line #" << lines.at(i)->lineNum << endl;
+        // populate reply
+        fepReply.reply = SHORTPOLL;
+        fepReply.schedule = lines.at(i)->schedule;
+        fepReply.lineinfo = lines.at(i)->lineInfo;
+        fepReply.kind = (enum polltype) 0;
+        fepReply.flag = (enum replykind) 0;
 
-		/***********************************
-			 This is an update to an extern, this should happen on the Java driver side??
-		lines.at(i).schedleSeq += 1;
-		lines.at(i).globalSeq += 51;
-		*/
+        /***********************************
+                 This is an update to an extern, this should happen on the Java driver side??
+        lines.at(i).schedleSeq += 1;
+        lines.at(i).globalSeq += 51;
+         */
 
-		fepReply.schedule_sequence = lines.at(i).schedleSeq;
-		fepReply.global_sequence = lines.at(i).globalSeq;
-		/************************************
-			 Need to find out what appropriate schedule time is: look at uci_unix_simulation_time src code
-		fepReply.schedule_time =
-			uci_unix_simulation_time(uci_simulation_time());	// GMT time
-		*/
-		fepReply.schedule_time = time(NULL);
+        fepReply.schedule_sequence = lines.at(i)->schedleSeq;
+        fepReply.global_sequence = lines.at(i)->globalSeq;
+        /************************************
+                 Need to find out what appropriate schedule time is: look at uci_unix_simulation_time src code
+        fepReply.schedule_time =
+                uci_unix_simulation_time(uci_simulation_time());	// GMT time
+         */
+        fepReply.schedule_time = time(NULL);
 
-		fepReply.user_info1 = lines.at(i).lineNum;
-		fepReply.user_info2 = lines.at(i).lineNum;
-		fepReply.system_key = lines.at(i).systemKey;
+        fepReply.user_info1 = lines.at(i)->lineNum;
+        fepReply.user_info2 = lines.at(i)->lineNum;
+        fepReply.system_key = lines.at(i)->systemKey;
 
-		fepReply.answers.size = 1;
-		fepReply.answers.fep_answer_list_u.shortp.count = 1;
+        fepReply.answers.size = 1;
+        fepReply.answers.fep_answer_list_u.shortp.count = 1;
 
-		/* for each LDS in the Line.... (constructs the short_answer message) */
-		for (j = 0; j < lines.at(i).lds.size(); j++)
-		{
-			fep_shortanswer fsa;
-			int index = lines.at(i).ldsIndex.at(j);
-                        cout << "LDS index: " << index << endl;
-			// msg: oa, od, ldsMap.at(index).dataPack, od, ff
-			fsa.msg.message_len = ldsMap.at(index).length + 2;
-			fsa.msg.message[0] = 0x0d;
-			fsa.msg.message[1] = 0x0a;
-			for (int k = 0; k < ldsMap.at(index).length; k++)
-				fsa.msg.message[2 + k]	= ldsMap.at(index).dataPack[k];
-			int aa = ldsMap.at(index).length;
-			fsa.msg.message[2 + aa] = 0x0d;
-			fsa.msg.message[3 + aa] = 0xff;	//????????????? warning ?????
+        /* for each LDS in the Line.... (constructs the short_answer message) */
+        for (j = 0; j < lines.at(i)->lds.size(); j++) {
+            fep_shortanswer fsa;
+            int index = lines.at(i)->ldsIndex.at(j);
+            cout << "LDS index: " << index << endl;
+            // msg: oa, od, ldsMap.at(index).dataPack, od, ff
+            fsa.msg.message_len = ldsMap.at(index)->length + 2;
+            fsa.msg.message[0] = 0x0d;
+            fsa.msg.message[1] = 0x0a;
+            for (int k = 0; k < ldsMap.at(index)->length; k++)
+                fsa.msg.message[2 + k] = ldsMap.at(index)->dataPack[k];
+            int aa = ldsMap.at(index)->length;
+            fsa.msg.message[2 + aa] = 0x0d;
+            fsa.msg.message[3 + aa] = 0xff; //????????????? warning ?????
 
-			// info
-			fsa.info.poll_error_count = 0;
-			/***************************************
-				 Need to find out polltime uci time function src code
-			fsa.info.poll_time = uci_unix_simulation_time(uci_simulation_time());
-			*/
-			fsa.info.poll_user_info1 = ldsMap.at(index).drop;	// drop number
-			fsa.info.poll_user_info2 = 1;	//always 1
-			fsa.info.retries = 0;
-			fsa.info.status = (enum replystatus) 1;
+            // info
+            fsa.info.poll_error_count = 0;
+            /***************************************
+                     Need to find out polltime uci time function src code
+            fsa.info.poll_time = uci_unix_simulation_time(uci_simulation_time());
+             */
+            fsa.info.poll_user_info1 = ldsMap.at(index)->drop; // drop number
+            fsa.info.poll_user_info2 = 1; //always 1
+            fsa.info.retries = 0;
+            fsa.info.status = (enum replystatus) 1;
 
-			//fepReply.answers.fep_answer_list_u.shortp.answers[j] = fsa;
-			fepReply.answers.fep_answer_list_u.shortp.answers[0] = fsa;
+            //fepReply.answers.fep_answer_list_u.shortp.answers[j +1] = fsa;
+            fepReply.answers.fep_answer_list_u.shortp.answers[0] = fsa;
 
-			// send out data
-			printf("Transferring line=%d, lds_drop_no=%d...\n", lines.at(i).lineNum, ldsMap.at(index).drop);
-			rv = fep_reply_xfer_32(&fepReply, clnt);
+            // send out data
+            printf("Transferring line=%d, lds_drop_no=%d...\n", lines.at(i)->lineNum, ldsMap.at(index)->drop);
+            rv = fep_reply_xfer_32(&fepReply, clnt);
 
-			/* Handle ATMS response to RPC Call */
-			printf("Handling ATMS response...\n");
-			handleCallResponse(rv);
-		}
-	}
+            /* Handle ATMS response to RPC Call */
+            printf("Handling ATMS response...\n");
+            handleCallResponse(rv);
+        }
+    }
 }
 
@@ -131,16 +122,14 @@
  * @param host rpc server ip
  */
-void FEPClient::createClient(char * host)
-{
-	/* Create RPC Client to communicate with ATMS */
-	cout << "Creating RPC Client" << endl;
-	clnt = clnt_create(host, /*100090,*/ 103121, 32, "tcp");
-        cout << "Client created" << endl;
-	/* Check if client creation failed */
-	if (clnt == (CLIENT *) NULL)
-	{
-		cerr << "Can't create client to " << host << endl;
-		exit(1);
-	}
+void FEPClient::createClient(char * host) {
+    /* Create RPC Client to communicate with ATMS */
+    cout << "Creating RPC Client" << endl;
+    clnt = clnt_create(host, /*100090,*/ 103121, 32, "tcp");
+    cout << "Client created" << endl;
+    /* Check if client creation failed */
+    if (clnt == (CLIENT *) NULL) {
+        cerr << "Can't create client to " << host << endl;
+        exit(1);
+    }
 }
 
@@ -153,20 +142,19 @@
 int main(int argc, char *argv[]) {
 
-	char *host;
-	char *networkFile;
+    char *host;
+    char *networkFile;
 
-	if (argc < 3)
-	{
-		cout << "usage:  " << argv[0] << " server_host networkFile" << endl;
-		exit(1);
-	}
+    if (argc < 3) {
+        cout << "usage:  " << argv[0] << " server_host networkFile" << endl;
+        exit(1);
+    }
 
-	/* Create RPC Client to send an fep_reply to ATMS */
-	host = argv[1];
-        networkFile = argv[2];
+    /* Create RPC Client to send an fep_reply to ATMS */
+    host = argv[1];
+    networkFile = argv[2];
 
-	FEPClient *client = new FEPClient(host, networkFile);
-        delete client;
+    FEPClient *client = new FEPClient(host, networkFile);
+    delete client;
 
-	return 0;
+    return 0;
 }
Index: branches/FEPSimulator/NetworkReader.cpp
===================================================================
--- branches/fep_rpc_client/NetworkReader.cpp	(revision 78)
+++ branches/FEPSimulator/NetworkReader.cpp	(revision 80)
@@ -10,6 +10,24 @@
 }
 
+LOOP * NetworkReader::parseLoop(TiXmlElement * loopElem) {
+        LOOP *loop = new LOOP;
+
+        TiXmlElement *subLoopElem = loopElem->FirstChildElement();
+        loop->loopID = atoi(subLoopElem->GetText());
+        cout << "LOOPID: " << subLoopElem->GetText() << endl;
+        subLoopElem = subLoopElem->NextSiblingElement();
+        loop->loop_loc = (char *) subLoopElem->GetText();
+        subLoopElem = subLoopElem->NextSiblingElement();
+        loop->vol = atoi(subLoopElem->GetText());
+        subLoopElem = subLoopElem->NextSiblingElement();
+        loop->occ = atof(subLoopElem->GetText());
+        subLoopElem = subLoopElem->NextSiblingElement();
+        loop->spd = atof(subLoopElem->GetText());
+        
+        return loop;
+}
+
 /**
- * Parses a station xml element into an "LDS_LOOP"
+ * Parses a station xml element into an "STATION"
  * 
  * @param stationElem the station xml element
@@ -17,16 +35,15 @@
  * @return the new station
  */
-LDS_LOOP NetworkReader::parseStation(TiXmlElement *stationElem, FEP_LINE *line) {
-    LDS_LOOP station;
-
+STATION * NetworkReader::parseStation(TiXmlElement *stationElem, FEP_LINE *line) {
+    STATION *station = new STATION;
+    
     TiXmlElement *stationSubElem = stationElem->FirstChildElement();
-    cout << "Station id: " << stationSubElem->GetText() << endl;
-    station.lds = atol(stationSubElem->GetText());
-    line->lds.push_back(station.lds);
+    station->lds = atol(stationSubElem->GetText());
+    line->lds.push_back(station->lds);
     line->ldsIndex.push_back(ldsIndex++);
     stationSubElem = stationSubElem->NextSiblingElement();
-    station.line_num = atoi(stationSubElem->GetText());
+    station->line_num = atoi(stationSubElem->GetText());
     stationSubElem = stationSubElem->NextSiblingElement();
-    station.drop = atoi(stationSubElem->GetText());
+    station->drop = atoi(stationSubElem->GetText());
     stationSubElem = stationSubElem->NextSiblingElement();
     stationSubElem = stationSubElem->NextSiblingElement(); // skip location
@@ -34,366 +51,101 @@
     stationSubElem = stationSubElem->NextSiblingElement(); // skip direction
     stationSubElem = stationSubElem->NextSiblingElement(); // skip freeway
-    station.MlTotVol = atoi(stationSubElem->GetText());
+    station->MlTotVol = atoi(stationSubElem->GetText());
     stationSubElem = stationSubElem->NextSiblingElement();
-    station.OppTotVol = atoi(stationSubElem->GetText());
+    station->OppTotVol = atoi(stationSubElem->GetText());
 
-    station.pos = 0;
+    station->pos = 0; // NOT SURE WHY WE NEED THIS?
+    
     // Add loops to station
-    TiXmlElement *loopsElem = stationSubElem->NextSiblingElement();
-    TiXmlElement *loopElem = loopsElem->FirstChildElement();
-    TiXmlElement *saveLoopElem = loopElem;
-    // get number of loops in station and assign to station.num
-    station.num = 0;
+    TiXmlElement *loopElem = stationSubElem->NextSiblingElement()->FirstChildElement();
     for (loopElem; loopElem; loopElem = loopElem->NextSiblingElement()) {
-        station.num += 1;
+        LOOP *loop = parseLoop(loopElem);
+        station->loops.push_back(loop);
     }
 
-    // get loopIDS and locations
-    long int loopIDS[station.num];
-    char * loopLocs[station.num];
-    int index = 0;
-    for (saveLoopElem; saveLoopElem; saveLoopElem = saveLoopElem->NextSiblingElement()) {
-        TiXmlElement *subLoopElem = saveLoopElem->FirstChildElement();
-        loopIDS[index] = atoi(subLoopElem->GetText());
-        subLoopElem = subLoopElem->NextSiblingElement();
-        loopLocs[index++] = (char *) subLoopElem->GetText();
+    // Data pack ATMS message
+    station->length = station->loops.size() * 2 + CONTROL_DATA_LEN;
+    cout << station->loops.size() << endl;
+    station->dataPack = DataPacker::packData(station);
+    
+    return station;
+}
+
+/**
+ * Parses a "Line" xml element into an FEP_LINE
+ * @param lineElem the xml element
+ * @return FEP_LINE
+ */
+FEP_LINE * NetworkReader::parseLine(TiXmlElement * lineElem) {
+    FEP_LINE *line = new FEP_LINE;
+
+    TiXmlElement *lineSubElem = lineElem->FirstChildElement();
+    line->lineNum = atoi(lineSubElem->GetText());
+    cout << "Line: " << line->lineNum << endl;
+    lineSubElem = lineSubElem->NextSiblingElement();
+    line->count = atoi(lineSubElem->GetText());
+    lineSubElem = lineSubElem->NextSiblingElement();
+    line->schedule = atoi(lineSubElem->GetText());
+    lineSubElem = lineSubElem->NextSiblingElement();
+    line->lineInfo = atoi(lineSubElem->GetText());
+    lineSubElem = lineSubElem->NextSiblingElement();
+    line->systemKey = atol(lineSubElem->GetText());
+    lineSubElem = lineSubElem->NextSiblingElement();
+    line->globalSeq = atol(lineSubElem->GetText());
+    lineSubElem = lineSubElem->NextSiblingElement();
+    line->schedleSeq = atol(lineSubElem->GetText());
+
+    TiXmlElement *stationsElem = lineSubElem->NextSiblingElement();
+    TiXmlElement *stationElem = stationsElem->FirstChildElement();
+    for (stationElem; stationElem; stationElem = stationElem->NextSiblingElement()) {
+        stations.push_back(parseStation(stationElem, line));
     }
-    station.loopID = loopIDS;
-    station.loop_loc = loopLocs;
+    return line;
+}
 
-    // Data pack ATMS message
-    station.length = station.num * 2 + CONTROL_DATA_LEN;
-    station.dataPack = staticDataPack(station);
-/*
-    // fill in dynamic data to dataPack[]
-    for (i = 0; i < g_ldsNum; i++) {
-        // Loop detector data 
-        int pos = 26;
-        pos = pp_data_packing(i, 5, pos);
-        pos = pp_data_packing(i, 6, pos);
-        pos = pp_data_packing(i, 7, pos);
-        pos = pp_data_packing(i, 8, pos);
-
-        // Update data for BYTE 9, 16, 21, 22, 23, 24
-
-        // what is the current metering rate?
-        // check each LDS, if there is demand detector, the downstream node the
-        // ldsMap[i].dataPack[22-1] = ldsMap[i].dataPack[9-1] = ;
-
-        // will need to check if queue override is enabled (Currently, no queue
-        // ldsMap[i].dataPack[16-1] = ;
-
-        // byte 23: MAINLINE total volume
-        ldsMap[i].dataPack[23 - 1] = ldsMap[i].MlTotVol;
-
-        // byte 24: opposite total volume
-        ldsMap[i].dataPack[24 - 1] = ldsMap[i].OppTotVol;
-
-        // last BYTE: checksum 
-        ldsMap[i].dataPack[ldsMap[i].length - 1] =
-                chksum(ldsMap[i].dataPack, ldsMap[i].length - 1 - 1);
-
-        // print out
-        // print out
-        for (j = 0; j < ldsMap[i].length; j++) {
-            fprintf(fi_lds, "%02X", ldsMap[i].dataPack[j]);
-        }
-        fprintf(fi_lds, "\n");
-        fflush(fi_lds);
-*/
-
-        return station;
+/**
+ * Loads FEPLines from a specified xml file
+ * @param networkFileName the input xml file
+ */
+void NetworkReader::loadLines(const char * networkFileName) {
+    // Load network xml file
+    TiXmlDocument doc(networkFileName);
+    if (!doc.LoadFile()) {
+        cerr << "TiXmlDocument did not load network file..." << endl;
+        return;
     }
 
-    /**
-     * Parses a "Line" xml element into an FEP_LINE
-     * @param lineElem the xml element
-     * @return FEP_LINE
-     */
-    FEP_LINE NetworkReader::parseLine(TiXmlElement * lineElem) {
-        FEP_LINE line;
-        TiXmlElement *lineSubElem = lineElem->FirstChildElement();
-        line.lineNum = atoi(lineSubElem->GetText());
-        cout << "Line: " << line.lineNum << endl;
-        lineSubElem = lineSubElem->NextSiblingElement();
-        line.count = atoi(lineSubElem->GetText());
-        lineSubElem = lineSubElem->NextSiblingElement();
-        line.schedule = atoi(lineSubElem->GetText());
-        lineSubElem = lineSubElem->NextSiblingElement();
-        line.lineInfo = atoi(lineSubElem->GetText());
-        lineSubElem = lineSubElem->NextSiblingElement();
-        line.systemKey = atol(lineSubElem->GetText());
-        lineSubElem = lineSubElem->NextSiblingElement();
-        line.globalSeq = atol(lineSubElem->GetText());
-        lineSubElem = lineSubElem->NextSiblingElement();
-        line.schedleSeq = atol(lineSubElem->GetText());
+    // grab <Network> element
+    TiXmlHandle hDoc(&doc);
+    TiXmlElement *networkElem = hDoc.FirstChildElement().Element();
 
-        TiXmlElement *stationsElem = lineSubElem->NextSiblingElement();
-        TiXmlElement *stationElem = stationsElem->FirstChildElement();
-        for (stationElem; stationElem; stationElem = stationElem->NextSiblingElement()) {
-            stations.push_back(parseStation(stationElem, &line));
-        }
-        return line;
+    // grab first <Line> element
+    TiXmlElement *lineElem = networkElem->FirstChildElement();
+
+    // iterate through each line element to create FEP_LINE list
+    for (lineElem; lineElem; lineElem = lineElem->NextSiblingElement()) {
+        lines.push_back(parseLine(lineElem));
     }
+}
 
-    /**
-     * Loads FEPLines from a specified xml file
-     * @param networkFileName the input xml file
-     */
-    void NetworkReader::loadLines(const char * networkFileName) {
-        // Load network xml file
-        TiXmlDocument doc(networkFileName);
-        if (!doc.LoadFile()) {
-            cerr << "TiXmlDocument did not load network file..." << endl;
-            return;
-        }
+/**
+ * Getter for lines
+ * @return List of FEP_LINES
+ */
+vector<FEP_LINE*> NetworkReader::getLines() {
 
-        // grab <Network> element
-        TiXmlHandle hDoc(&doc);
-        TiXmlElement *networkElem = hDoc.FirstChildElement().Element();
+    return lines;
+}
 
-        // grab first <Line> element
-        TiXmlElement *lineElem = networkElem->FirstChildElement();
+/**
+ * Getter for stations
+ * @return List of STATIONs
+ */
+vector<STATION*> NetworkReader::getStations() {
 
-        // iterate through each line element to create FEP_LINE list
-        for (lineElem; lineElem; lineElem = lineElem->NextSiblingElement()) {
-            lines.push_back(parseLine(lineElem));
-        }
-    }
+    return stations;
+}
 
-    // determine if a loop has data based on lane config data
+NetworkReader::~NetworkReader() {
 
-    bool NetworkReader::DataAvail(char flag, int num) {
-        int mag, fel;
-
-        // find mask value
-        if (num == 1)
-            mag = 0x01;
-        else if (num == 2)
-            mag = 0x02;
-        else if (num == 3)
-            mag = 0x04;
-        else if (num == 4)
-            mag = 0x08;
-        else if (num == 5)
-            mag = 0x10;
-        else if (num == 6)
-            mag = 0x20;
-        else if (num == 7)
-            mag = 0x40;
-        else if (num == 8)
-            mag = 0x80;
-
-        fel = flag & mag;
-        fel = fel >> (num - 1);
-
-        if (fel == 1)
-            return true;
-        else
-            return false;
-    }
-/*
-    int pp_data_packing(int index, int packNo, int pos) {
-        int i, j, k, vol, occ, lane, haveData;
-        LOOPAGG in;
-        DETECTOR *aaa;
-        VOLOCC bbb;
-        long loop;
-
-        i = index;
-
-        //used for data byte 23 and 24
-        ldsMap[i].MlTotVol = 0;
-        ldsMap[i].OppTotVol = 0;
-
-        for (j = 1; j <= 8; j++) {
-            if (DataAvail(ldsMap[i].dataPack[packNo - 1], j)) {
-                // loop at bit j has data
-                for (k = 0; k < ldsMap[i].num; k++) {
-                    // what's the corresponding loop of bit j
-                    if (packNo == 5)
-                        haveData = strcmp(ldsMap[i].loop_loc[k], dp5[j - 1]);
-                    else if (packNo == 6)
-                        haveData = strcmp(ldsMap[i].loop_loc[k], dp6[j - 1]);
-                    else if (packNo == 7)
-                        haveData = strcmp(ldsMap[i].loop_loc[k], dp7[j - 1]);
-                    else if (packNo == 8)
-                        haveData = strcmp(ldsMap[i].loop_loc[k], dp8[j - 1]);
-                    else
-                        return -1;
-
-                    if (haveData == 0) {
-                        loop = ldsMap[i].loopID[k];
-                        if (strcmp(chu[loop].paramicsName, "?") == 0) {
-                            {
-                                vol = 0;
-                                occ = 900;
-                            } else {
-                                aaa = qpg_NET_detector(chu[loop].paramicsName);
-                                Bool status = uci_loop_aggregation(qpg_DTC_index(aaa), POLLING
-                                if (status) {
-                                    if (chu[loop].paramicsLane == 0)
-                                            lane = 0;
-                                    else
-                                        lane = chu[loop].paramicsLane - 1;
-                                            vol = in.vol[lane];
-                                            occ = (int) (in.occ[lane] * 900 + 0.5);
-                                            //                   qps_GUI_printf("%d(%s), lane=%d, vol=%d(%d), occ=%.3f(%.3f,
-                                            //                      qpg_DTC_index(aaa), chu[loop].paramicsName, in.lane, in.
-                                            //                      vol, in.g_occ, in.occ[lane], occ);
-                                    } else
-                                    qps_GUI_printf("Data query error for %s\n", chu[loop].param
-                                }
-
-                            bbb = pp_vol_occ_word(vol, occ);
-                                    pos++;
-                                    ldsMap[i].dataPack[pos - 1] = bbb.high;
-                                    pos++;
-                                    ldsMap[i].dataPack[pos - 1] = bbb.low;
-
-                            if (packNo == 5) {
-                                ldsMap[i].MlTotVol += vol;
-                            } else if (packNo == 6) {
-
-                                ldsMap[i].OppTotVol += vol;
-                            }
-
-                            fprintf(fi_lds, "lds=%d, loop=%d, paramics=%s, lane=%d, vol=%d(%X
-                                    ldsMap[i].lds, loop, chu[loop].paramicsName, chu[loop].paramic
-                                    bbb.high, occ, bbb.low);
-                                    fflush(fi_lds);
-                        }
-                    }
-                }
-            }
-
-            return pos;
-        }
- */
-        // Initializes the LDS_LOOP dataPack with all necessary static data and default dynamic data
-        unsigned char * NetworkReader::staticDataPack(LDS_LOOP loop) {
-            int j;
-                    // Allocate memory for dataPack
-                    unsigned char *dataPack = (unsigned char *) calloc(1, sizeof (unsigned char) * loop.length);
-
-                    // dataPack 5-8: lane config
-                    char d5 = 0, d6 = 0, d7 = 0, d8 = 0;
-            for (j = 0; j < loop.num; j++) {
-                for (int k = 0; k < 8; k++) {
-                    if (strcmp(loop.loop_loc[j], dp5[k]) == 0)
-                            d5 += pow(2, k);
-                        if (strcmp(loop.loop_loc[j], dp6[k]) == 0)
-                                d6 += pow(2, k);
-                            if (strcmp(loop.loop_loc[j], dp7[k]) == 0)
-                                    d7 += pow(2, k);
-                                if (strcmp(loop.loop_loc[j], dp8[k]) == 0)
-                                        d8 += pow(2, k);
-                                }
-            }
-            dataPack[5 - 1] = d5;
-                    dataPack[6 - 1] = d6;
-                    dataPack[7 - 1] = d7;
-                    dataPack[8 - 1] = d8;
-
-                    // dataPack 1: Drop number, i.e. station address
-                    dataPack[1 - 1] = loop.drop;
-
-                    // dataPack2 (2 bytes per loop)
-                    dataPack[2 - 1] = loop.num * 2 + Fixed_Byte_To_Checksum;
-
-                    // dataPacket 3 (lowbyte: # of mainline loops, highbyte: # of opposite loops)
-                    int low = 0, high = 0;
-            for (j = 1; j <= 6; j++) {
-                low += DataAvail(dataPack[5 - 1], j);
-                        high += DataAvail(dataPack[6 - 1], j);
-            }
-            high = high << 4;
-                    dataPack[3 - 1] = high | low;
-
-                    // dataPack4 (Miscl. flags: samples are: 80, A0, E0, 00)
-                    dataPack[4 - 1] = 0xA0;
-
-                    // dataPack 9: initialized as 00 (meaning no metering); need to be updated every 30 sec
-                    dataPack[9 - 1] = 0;
-
-                    // datadataPack 10-13: lane malfunction? Assuming all functional
-                    dataPack[10 - 1] = 0;
-                    dataPack[11 - 1] = 0;
-                    dataPack[12 - 1] = 0;
-                    dataPack[13 - 1] = 0;
-
-                    // dataPack 14-22: ramp metering data
-                    // BYTE 16 and 22 need to be updated every 30 sec
-                    bool found = false;
-            for (j = 0; j < loop.num; j++) {
-                if (strcmp(loop.loop_loc[j], "DEMAND") == 0) {
-                    found = true;
-                    break;
-                }
-            }
-            if (found) {
-                // BYTE 14: mostly 07, some are 05, 03, 00
-                dataPack[14 - 1] = 0x07;
-                        // mostly 06(TOD table 1); some are 0B (No metering) or 05(traffic responsive)
-                        dataPack[15 - 1] = 0x06;
-                        // most 00, some are 01 (queue override) or 80(Meter ON sign)
-                        dataPack[16 - 1] = 0x00;
-                        // Field Manual Rate
-                        dataPack[17 - 1] = 0xFF;
-                        // TOC Manual Rate
-                        dataPack[18 - 1] = 0xFF;
-                        // PSO Manual Rate
-                        dataPack[19 - 1] = 0xFF;
-                        // CORM Rate
-                        dataPack[20 - 1] = 0xFF;
-                        // Local Responsive Rate. DON'T UNDERSTAND YET
-                        dataPack[21 - 1] = 0x00;
-                        // TOD Rate: need to query RAMP plugin!
-                        dataPack[22 - 1] = 0x00;
-            }                // LDS: NO Metering
-            else {
-                dataPack[14 - 1] = 0x00;
-                        dataPack[15 - 1] = 0x0B;
-                        dataPack[16 - 1] = 0x00;
-                        dataPack[17 - 1] = 0xFF;
-                        dataPack[18 - 1] = 0xFF;
-                        dataPack[19 - 1] = 0xFF;
-                        dataPack[20 - 1] = 0xFF;
-                        dataPack[21 - 1] = 0x00;
-                        dataPack[22 - 1] = 0x00;
-            }
-
-            // dataPack 23-24: sum of mainline/Oppsite traffic data; need to be updated every 30 sec
-            loop.MlTotVol = 0;
-                    loop.OppTotVol = 0;
-                    dataPack[23 - 1] = loop.MlTotVol;
-                    dataPack[24 - 1] = loop.OppTotVol;
-
-                    // dataPack 25-26: BYTE 25 is fixed, i.e. 03; BYTE 26 is either 0xA2 or 0x84
-                    dataPack[25 - 1] = 0x03;
-                    dataPack[26 - 1] = 0x84;
-
-            return dataPack;
-        }
-
-        /**
-         * Getter for lines
-         * @return List of FEP_LINES
-         */
-        vector<FEP_LINE> NetworkReader::getLines() {
-
-            return lines;
-        }
-
-        /**
-         * Getter for stations
-         * @return List of LDS_LOOPs
-         */
-        vector<LDS_LOOP> NetworkReader::getStations() {
-
-            return stations;
-        }
-
-        NetworkReader::~NetworkReader() {
-
-        }
+}
Index: branches/FEPSimulator/FEPClient.h
===================================================================
--- branches/fep_rpc_client/FEPClient.h	(revision 77)
+++ branches/FEPSimulator/FEPClient.h	(revision 80)
@@ -1,3 +1,6 @@
-/* The FEPClient is an RPC Client which transfers network data to the
+/* 
+ * File: FEPClient.h
+ * 
+ * The FEPClient is an RPC Client which transfers network data to the
  * ATMS Server.
  *
@@ -14,4 +17,5 @@
  * @version 9/8/2017
  */
+
 // Include guard
 #ifndef __FEPCLIENT_H_INCLUDED__
Index: branches/FEPSimulator/build/Debug/GNU-Linux-x86/FEPClient.o.d
===================================================================
--- branches/fep_rpc_client/build/Debug/GNU-Linux-x86/FEPClient.o.d	(revision 77)
+++ branches/FEPSimulator/build/Debug/GNU-Linux-x86/FEPClient.o.d	(revision 80)
@@ -1,4 +1,5 @@
 build/Debug/GNU-Linux-x86/FEPClient.o: FEPClient.cpp FEPClient.h fep.h \
- NetworkReader.h network.h tinyxml/tinyxml.h tinyxml/tinystr.h
+ NetworkReader.h network.h tinyxml/tinyxml.h tinyxml/tinystr.h \
+ DataPacker.h
 
 FEPClient.h:
@@ -13,2 +14,4 @@
 
 tinyxml/tinystr.h:
+
+DataPacker.h:
Index: branches/FEPSimulator/build/Debug/GNU-Linux-x86/NetworkReader.o.d
===================================================================
--- branches/fep_rpc_client/build/Debug/GNU-Linux-x86/NetworkReader.o.d	(revision 77)
+++ branches/FEPSimulator/build/Debug/GNU-Linux-x86/NetworkReader.o.d	(revision 80)
@@ -1,4 +1,5 @@
 build/Debug/GNU-Linux-x86/NetworkReader.o: NetworkReader.cpp \
- NetworkReader.h network.h tinyxml/tinyxml.h tinyxml/tinystr.h
+ NetworkReader.h network.h tinyxml/tinyxml.h tinyxml/tinystr.h \
+ DataPacker.h
 
 NetworkReader.h:
@@ -9,2 +10,4 @@
 
 tinyxml/tinystr.h:
+
+DataPacker.h:
Index: branches/FEPSimulator/build/Debug/GNU-Linux-x86/DataPacker.o.d
===================================================================
--- branches/FEPSimulator/build/Debug/GNU-Linux-x86/DataPacker.o.d	(revision 80)
+++ branches/FEPSimulator/build/Debug/GNU-Linux-x86/DataPacker.o.d	(revision 80)
@@ -0,0 +1,6 @@
+build/Debug/GNU-Linux-x86/DataPacker.o: DataPacker.cpp DataPacker.h \
+ network.h
+
+DataPacker.h:
+
+network.h:
Index: branches/FEPSimulator/NetworkReader.h
===================================================================
--- branches/fep_rpc_client/NetworkReader.h	(revision 78)
+++ branches/FEPSimulator/NetworkReader.h	(revision 80)
@@ -1,9 +1,12 @@
-/** A NetworkReader reads in data about the traffic network from a specified
+/** 
+ * File: NetworkReader.h
+ * 
+ * A NetworkReader reads in data about the traffic network from a specified
  * xml file.
  * 
  * A NetworkReader contains two public methods 'getLines' and 'getLoops',
- * which are getters for the list of FEP_LINES, and LDS_LOOPS, respectively.
+ * which are getters for the list of FEP_LINES, and STATIONS, respectively.
  * 
- * Example xml file:
+ * Example XML file:
  * <code>
  * <Network>
@@ -47,13 +50,11 @@
 #define __NETWORKREADER_H_INCLUDED__
 
-// Forward declared dependencies
-
 // Included dependencies
 #include "network.h"
 #include <vector>
-#include <string>
 #include <string.h>
 #include <iostream>
 #include "tinyxml.h"
+#include "DataPacker.h"
 
 class NetworkReader
@@ -63,18 +64,15 @@
         ~NetworkReader(); // Destructor
         
-        vector<FEP_LINE> getLines(); // Getter for FEP_LINE list
-        vector<LDS_LOOP> getStations(); // Getter for LDS_LOOP list
+        vector<FEP_LINE*> getLines(); // Getter for FEP_LINE list
+        vector<STATION*> getStations(); // Getter for STATION list
     private:
-        vector<FEP_LINE> lines;
-        vector<LDS_LOOP> stations;
+        vector<FEP_LINE*> lines;
+        vector<STATION*> stations;
         int ldsIndex;
 
         void loadLines(const char * networkFileName);
-        LDS_LOOP parseStation(TiXmlElement *stationElem, FEP_LINE *line);
-        FEP_LINE parseLine(TiXmlElement *lineElem);
-
-        bool DataAvail(char flag, int num); // Helper function for msgDataPack
-        unsigned char * staticDataPack(LDS_LOOP loop); // Packs the static data in message sent to ATMS
-        // int pp_data_packing(int index, int packNo, int pos); // Packs dynamic data in message sent to ATMS
+        LOOP * parseLoop(TiXmlElement * loopElem);
+        STATION * parseStation(TiXmlElement *stationElem, FEP_LINE *line);
+        FEP_LINE * parseLine(TiXmlElement *lineElem);
 };
 
Index: branches/FEPSimulator/tinyxml/tinystr.cpp
===================================================================
--- branches/FEPSimulator/tinyxml/tinystr.cpp	(revision 80)
+++ branches/FEPSimulator/tinyxml/tinystr.cpp	(revision 80)
@@ -0,0 +1,111 @@
+/*
+www.sourceforge.net/projects/tinyxml
+
+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 TIXML_USE_STL
+
+#include "tinystr.h"
+
+// Error value for find primitive
+const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1);
+
+
+// Null rep.
+TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } };
+
+
+void TiXmlString::reserve (size_type cap)
+{
+	if (cap > capacity())
+	{
+		TiXmlString tmp;
+		tmp.init(length(), cap);
+		memcpy(tmp.start(), data(), length());
+		swap(tmp);
+	}
+}
+
+
+TiXmlString& TiXmlString::assign(const char* str, size_type len)
+{
+	size_type cap = capacity();
+	if (len > cap || cap > 3*(len + 8))
+	{
+		TiXmlString tmp;
+		tmp.init(len);
+		memcpy(tmp.start(), str, len);
+		swap(tmp);
+	}
+	else
+	{
+		memmove(start(), str, len);
+		set_size(len);
+	}
+	return *this;
+}
+
+
+TiXmlString& TiXmlString::append(const char* str, size_type len)
+{
+	size_type newsize = length() + len;
+	if (newsize > capacity())
+	{
+		reserve (newsize + capacity());
+	}
+	memmove(finish(), str, len);
+	set_size(newsize);
+	return *this;
+}
+
+
+TiXmlString operator + (const TiXmlString & a, const TiXmlString & b)
+{
+	TiXmlString tmp;
+	tmp.reserve(a.length() + b.length());
+	tmp += a;
+	tmp += b;
+	return tmp;
+}
+
+TiXmlString operator + (const TiXmlString & a, const char* b)
+{
+	TiXmlString tmp;
+	TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) );
+	tmp.reserve(a.length() + b_len);
+	tmp += a;
+	tmp.append(b, b_len);
+	return tmp;
+}
+
+TiXmlString operator + (const char* a, const TiXmlString & b)
+{
+	TiXmlString tmp;
+	TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) );
+	tmp.reserve(a_len + b.length());
+	tmp.append(a, a_len);
+	tmp += b;
+	return tmp;
+}
+
+
+#endif	// TIXML_USE_STL
Index: branches/FEPSimulator/tinyxml/tinyxmlerror.cpp
===================================================================
--- branches/FEPSimulator/tinyxml/tinyxmlerror.cpp	(revision 80)
+++ branches/FEPSimulator/tinyxml/tinyxmlerror.cpp	(revision 80)
@@ -0,0 +1,52 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2006 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 "tinyxml.h"
+
+// The goal of the seperate error file is to make the first
+// step towards localization. tinyxml (currently) only supports
+// english error messages, but the could now be translated.
+//
+// It also cleans up the code a bit.
+//
+
+const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] =
+{
+	"No error",
+	"Error",
+	"Failed to open file",
+	"Error parsing Element.",
+	"Failed to read Element name",
+	"Error reading Element value.",
+	"Error reading Attributes.",
+	"Error: empty tag.",
+	"Error reading end tag.",
+	"Error parsing Unknown.",
+	"Error parsing Comment.",
+	"Error parsing Declaration.",
+	"Error document empty.",
+	"Error null (0) or unexpected EOF found in input stream.",
+	"Error parsing CDATA.",
+	"Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.",
+};
Index: branches/FEPSimulator/tinyxml/xmltest.cpp
===================================================================
--- branches/FEPSimulator/tinyxml/xmltest.cpp	(revision 80)
+++ branches/FEPSimulator/tinyxml/xmltest.cpp	(revision 80)
@@ -0,0 +1,1393 @@
+/*
+   Test program for TinyXML.
+*/
+
+
+#ifdef TIXML_USE_STL
+	#include <iostream>
+	#include <sstream>
+	using namespace std;
+#else
+	#include <stdio.h>
+#endif
+
+#if defined( WIN32 ) && defined( TUNE )
+	#include <crtdbg.h>
+	_CrtMemState startMemState;
+	_CrtMemState endMemState;
+#endif
+
+#include "tinyxml.h"
+
+bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho = false);
+bool XmlTest( const char* testString, int expected, int found, bool noEcho = false );
+
+static int gPass = 0;
+static int gFail = 0;
+
+
+
+bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho )
+{
+	bool pass = !strcmp( expected, found );
+	if ( pass )
+		printf ("[pass]");
+	else
+		printf ("[fail]");
+
+	if ( noEcho )
+		printf (" %s\n", testString);
+	else
+		printf (" %s [%s][%s]\n", testString, expected, found);
+
+	if ( pass )
+		++gPass;
+	else
+		++gFail;
+	return pass;
+}
+
+
+bool XmlTest( const char* testString, int expected, int found, bool noEcho )
+{
+	bool pass = ( expected == found );
+	if ( pass )
+		printf ("[pass]");
+	else
+		printf ("[fail]");
+
+	if ( noEcho )
+		printf (" %s\n", testString);
+	else
+		printf (" %s [%d][%d]\n", testString, expected, found);
+
+	if ( pass )
+		++gPass;
+	else
+		++gFail;
+	return pass;
+}
+
+
+void NullLineEndings( char* p )
+{
+	while( p && *p ) {
+		if ( *p == '\n' || *p == '\r' ) {
+			*p = 0;
+			return;
+		}
+		++p;
+	}
+}
+
+//
+// This file demonstrates some basic functionality of TinyXml.
+// Note that the example is very contrived. It presumes you know
+// what is in the XML file. But it does test the basic operations,
+// and show how to add and remove nodes.
+//
+
+int main()
+{
+
+	//
+	// We start with the 'demoStart' todo list. Process it. And
+	// should hopefully end up with the todo list as illustrated.
+	//
+	const char* demoStart =
+		"<?xml version=\"1.0\"  standalone='no' >\n"
+		"<!-- Our to do list data -->"
+		"<ToDo>\n"
+		"<!-- Do I need a secure PDA? -->\n"
+		"<Item priority=\"1\" distance='close'> Go to the <bold>Toy store!</bold></Item>"
+		"<Item priority=\"2\" distance='none'> Do bills   </Item>"
+		"<Item priority=\"2\" distance='far &amp; back'> Look for Evil Dinosaurs! </Item>"
+		"</ToDo>";
+		
+	{
+
+	#ifdef TIXML_USE_STL
+		//	What the todo list should look like after processing.
+		// In stream (no formatting) representation.
+		const char* demoEnd =
+			"<?xml version=\"1.0\" standalone=\"no\" ?>"
+			"<!-- Our to do list data -->"
+			"<ToDo>"
+			"<!-- Do I need a secure PDA? -->"
+			"<Item priority=\"2\" distance=\"close\">Go to the"
+			"<bold>Toy store!"
+			"</bold>"
+			"</Item>"
+			"<Item priority=\"1\" distance=\"far\">Talk to:"
+			"<Meeting where=\"School\">"
+			"<Attendee name=\"Marple\" position=\"teacher\" />"
+			"<Attendee name=\"Voel\" position=\"counselor\" />"
+			"</Meeting>"
+			"<Meeting where=\"Lunch\" />"
+			"</Item>"
+			"<Item priority=\"2\" distance=\"here\">Do bills"
+			"</Item>"
+			"</ToDo>";
+	#endif
+
+		// The example parses from the character string (above):
+		#if defined( WIN32 ) && defined( TUNE )
+		_CrtMemCheckpoint( &startMemState );
+		#endif	
+
+		{
+			// Write to a file and read it back, to check file I/O.
+
+			TiXmlDocument doc( "demotest.xml" );
+			doc.Parse( demoStart );
+
+			if ( doc.Error() )
+			{
+				printf( "Error in %s: %s\n", doc.Value(), doc.ErrorDesc() );
+				exit( 1 );
+			}
+			doc.SaveFile();
+		}
+
+		TiXmlDocument doc( "demotest.xml" );
+		bool loadOkay = doc.LoadFile();
+
+		if ( !loadOkay )
+		{
+			printf( "Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc() );
+			exit( 1 );
+		}
+
+		printf( "** Demo doc read from disk: ** \n\n" );
+		printf( "** Printing via doc.Print **\n" );
+		doc.Print( stdout );
+
+		{
+			printf( "** Printing via TiXmlPrinter **\n" );
+			TiXmlPrinter printer;
+			doc.Accept( &printer );
+			fprintf( stdout, "%s", printer.CStr() );
+		}
+		#ifdef TIXML_USE_STL	
+		{
+			printf( "** Printing via operator<< **\n" );
+			std::cout << doc;
+		}
+		#endif
+		TiXmlNode* node = 0;
+		TiXmlElement* todoElement = 0;
+		TiXmlElement* itemElement = 0;
+
+
+		// --------------------------------------------------------
+		// An example of changing existing attributes, and removing
+		// an element from the document.
+		// --------------------------------------------------------
+
+		// Get the "ToDo" element.
+		// It is a child of the document, and can be selected by name.
+		node = doc.FirstChild( "ToDo" );
+		assert( node );
+		todoElement = node->ToElement();
+		assert( todoElement  );
+
+		// Going to the toy store is now our second priority...
+		// So set the "priority" attribute of the first item in the list.
+		node = todoElement->FirstChildElement();	// This skips the "PDA" comment.
+		assert( node );
+		itemElement = node->ToElement();
+		assert( itemElement  );
+		itemElement->SetAttribute( "priority", 2 );
+
+		// Change the distance to "doing bills" from
+		// "none" to "here". It's the next sibling element.
+		itemElement = itemElement->NextSiblingElement();
+		assert( itemElement );
+		itemElement->SetAttribute( "distance", "here" );
+
+		// Remove the "Look for Evil Dinosaurs!" item.
+		// It is 1 more sibling away. We ask the parent to remove
+		// a particular child.
+		itemElement = itemElement->NextSiblingElement();
+		todoElement->RemoveChild( itemElement );
+
+		itemElement = 0;
+
+		// --------------------------------------------------------
+		// What follows is an example of created elements and text
+		// nodes and adding them to the document.
+		// --------------------------------------------------------
+
+		// Add some meetings.
+		TiXmlElement item( "Item" );
+		item.SetAttribute( "priority", "1" );
+		item.SetAttribute( "distance", "far" );
+
+		TiXmlText text( "Talk to:" );
+
+		TiXmlElement meeting1( "Meeting" );
+		meeting1.SetAttribute( "where", "School" );
+
+		TiXmlElement meeting2( "Meeting" );
+		meeting2.SetAttribute( "where", "Lunch" );
+
+		TiXmlElement attendee1( "Attendee" );
+		attendee1.SetAttribute( "name", "Marple" );
+		attendee1.SetAttribute( "position", "teacher" );
+
+		TiXmlElement attendee2( "Attendee" );
+		attendee2.SetAttribute( "name", "Voel" );
+		attendee2.SetAttribute( "position", "counselor" );
+
+		// Assemble the nodes we've created:
+		meeting1.InsertEndChild( attendee1 );
+		meeting1.InsertEndChild( attendee2 );
+
+		item.InsertEndChild( text );
+		item.InsertEndChild( meeting1 );
+		item.InsertEndChild( meeting2 );
+
+		// And add the node to the existing list after the first child.
+		node = todoElement->FirstChild( "Item" );
+		assert( node );
+		itemElement = node->ToElement();
+		assert( itemElement );
+
+		todoElement->InsertAfterChild( itemElement, item );
+
+		printf( "\n** Demo doc processed: ** \n\n" );
+		doc.Print( stdout );
+
+
+	#ifdef TIXML_USE_STL
+		printf( "** Demo doc processed to stream: ** \n\n" );
+		cout << doc << endl << endl;
+	#endif
+
+		// --------------------------------------------------------
+		// Different tests...do we have what we expect?
+		// --------------------------------------------------------
+
+		int count = 0;
+		TiXmlElement*	element;
+
+		//////////////////////////////////////////////////////
+
+	#ifdef TIXML_USE_STL
+		cout << "** Basic structure. **\n";
+		ostringstream outputStream( ostringstream::out );
+		outputStream << doc;
+		XmlTest( "Output stream correct.",	string( demoEnd ).c_str(),
+											outputStream.str().c_str(), true );
+	#endif
+
+		node = doc.RootElement();
+		assert( node );
+		XmlTest( "Root element exists.", true, ( node != 0 && node->ToElement() ) );
+		XmlTest ( "Root element value is 'ToDo'.", "ToDo",  node->Value());
+
+		node = node->FirstChild();
+		XmlTest( "First child exists & is a comment.", true, ( node != 0 && node->ToComment() ) );
+		node = node->NextSibling();
+		XmlTest( "Sibling element exists & is an element.", true, ( node != 0 && node->ToElement() ) );
+		XmlTest ( "Value is 'Item'.", "Item", node->Value() );
+
+		node = node->FirstChild();
+		XmlTest ( "First child exists.", true, ( node != 0 && node->ToText() ) );
+		XmlTest ( "Value is 'Go to the'.", "Go to the", node->Value() );
+
+
+		//////////////////////////////////////////////////////
+		printf ("\n** Iterators. **\n");
+
+		// Walk all the top level nodes of the document.
+		count = 0;
+		for( node = doc.FirstChild();
+			 node;
+			 node = node->NextSibling() )
+		{
+			count++;
+		}
+		XmlTest( "Top level nodes, using First / Next.", 3, count );
+
+		count = 0;
+		for( node = doc.LastChild();
+			 node;
+			 node = node->PreviousSibling() )
+		{
+			count++;
+		}
+		XmlTest( "Top level nodes, using Last / Previous.", 3, count );
+
+		// Walk all the top level nodes of the document,
+		// using a different syntax.
+		count = 0;
+		for( node = doc.IterateChildren( 0 );
+			 node;
+			 node = doc.IterateChildren( node ) )
+		{
+			count++;
+		}
+		XmlTest( "Top level nodes, using IterateChildren.", 3, count );
+
+		// Walk all the elements in a node.
+		count = 0;
+		for( element = todoElement->FirstChildElement();
+			 element;
+			 element = element->NextSiblingElement() )
+		{
+			count++;
+		}
+		XmlTest( "Children of the 'ToDo' element, using First / Next.",
+			3, count );
+
+		// Walk all the elements in a node by value.
+		count = 0;
+		for( node = todoElement->FirstChild( "Item" );
+			 node;
+			 node = node->NextSibling( "Item" ) )
+		{
+			count++;
+		}
+		XmlTest( "'Item' children of the 'ToDo' element, using First/Next.", 3, count );
+
+		count = 0;
+		for( node = todoElement->LastChild( "Item" );
+			 node;
+			 node = node->PreviousSibling( "Item" ) )
+		{
+			count++;
+		}
+		XmlTest( "'Item' children of the 'ToDo' element, using Last/Previous.", 3, count );
+
+	#ifdef TIXML_USE_STL
+		{
+			cout << "\n** Parsing. **\n";
+			istringstream parse0( "<Element0 attribute0='foo0' attribute1= noquotes attribute2 = '&gt;' />" );
+			TiXmlElement element0( "default" );
+			parse0 >> element0;
+
+			XmlTest ( "Element parsed, value is 'Element0'.", "Element0", element0.Value() );
+			XmlTest ( "Reads attribute 'attribute0=\"foo0\"'.", "foo0", element0.Attribute( "attribute0" ));
+			XmlTest ( "Reads incorrectly formatted 'attribute1=noquotes'.", "noquotes", element0.Attribute( "attribute1" ) );
+			XmlTest ( "Read attribute with entity value '>'.", ">", element0.Attribute( "attribute2" ) );
+		}
+	#endif
+
+		{
+			const char* error =	"<?xml version=\"1.0\" standalone=\"no\" ?>\n"
+								"<passages count=\"006\" formatversion=\"20020620\">\n"
+								"    <wrong error>\n"
+								"</passages>";
+
+			TiXmlDocument docTest;
+			docTest.Parse( error );
+			XmlTest( "Error row", docTest.ErrorRow(), 3 );
+			XmlTest( "Error column", docTest.ErrorCol(), 17 );
+			//printf( "error=%d id='%s' row %d col%d\n", (int) doc.Error(), doc.ErrorDesc(), doc.ErrorRow()+1, doc.ErrorCol() + 1 );
+
+		}
+
+	#ifdef TIXML_USE_STL
+		{
+			//////////////////////////////////////////////////////
+			cout << "\n** Streaming. **\n";
+
+			// Round trip check: stream in, then stream back out to verify. The stream
+			// out has already been checked, above. We use the output
+
+			istringstream inputStringStream( outputStream.str() );
+			TiXmlDocument document0;
+
+			inputStringStream >> document0;
+
+			ostringstream outputStream0( ostringstream::out );
+			outputStream0 << document0;
+
+			XmlTest( "Stream round trip correct.",	string( demoEnd ).c_str(), 
+													outputStream0.str().c_str(), true );
+
+			std::string str;
+			str << document0;
+
+			XmlTest( "String printing correct.", string( demoEnd ).c_str(), 
+												 str.c_str(), true );
+		}
+	#endif
+	}
+
+	{
+		const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
+
+		TiXmlDocument doc;
+		doc.Parse( str );
+
+		TiXmlElement* ele = doc.FirstChildElement();
+
+		int iVal, result;
+		double dVal;
+
+		result = ele->QueryDoubleAttribute( "attr0", &dVal );
+		XmlTest( "Query attribute: int as double", result, TIXML_SUCCESS );
+		XmlTest( "Query attribute: int as double", (int)dVal, 1 );
+		result = ele->QueryDoubleAttribute( "attr1", &dVal );
+		XmlTest( "Query attribute: double as double", (int)dVal, 2 );
+		result = ele->QueryIntAttribute( "attr1", &iVal );
+		XmlTest( "Query attribute: double as int", result, TIXML_SUCCESS );
+		XmlTest( "Query attribute: double as int", iVal, 2 );
+		result = ele->QueryIntAttribute( "attr2", &iVal );
+		XmlTest( "Query attribute: not a number", result, TIXML_WRONG_TYPE );
+		result = ele->QueryIntAttribute( "bar", &iVal );
+		XmlTest( "Query attribute: does not exist", result, TIXML_NO_ATTRIBUTE );
+	}
+
+	{
+		const char* str = "<doc/>";
+
+		TiXmlDocument doc;
+		doc.Parse( str );
+
+		TiXmlElement* ele = doc.FirstChildElement();
+
+		int iVal;
+		double dVal;
+
+		ele->SetAttribute( "str", "strValue" );
+		ele->SetAttribute( "int", 1 );
+		ele->SetDoubleAttribute( "double", -1.0 );
+
+		const char* cStr = ele->Attribute( "str" );
+		ele->QueryIntAttribute( "int", &iVal );
+		ele->QueryDoubleAttribute( "double", &dVal );
+
+		XmlTest( "Attribute round trip. c-string.", "strValue", cStr );
+		XmlTest( "Attribute round trip. int.", 1, iVal );
+		XmlTest( "Attribute round trip. double.", -1, (int)dVal );
+	}
+	
+	{
+		const char* str =	"\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n"
+							"</room>";
+
+		TiXmlDocument doc;
+		doc.SetTabSize( 8 );
+		doc.Parse( str );
+
+		TiXmlHandle docHandle( &doc );
+		TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" );
+
+		assert( docHandle.Node() );
+		assert( roomHandle.Element() );
+
+		TiXmlElement* room = roomHandle.Element();
+		assert( room );
+		TiXmlAttribute* doors = room->FirstAttribute();
+		assert( doors );
+
+		XmlTest( "Location tracking: Tab 8: room row", room->Row(), 1 );
+		XmlTest( "Location tracking: Tab 8: room col", room->Column(), 49 );
+		XmlTest( "Location tracking: Tab 8: doors row", doors->Row(), 1 );
+		XmlTest( "Location tracking: Tab 8: doors col", doors->Column(), 55 );
+	}
+	
+	{
+		const char* str =	"\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n"
+							"  <!-- Silly example -->\n"
+							"    <door wall='north'>A great door!</door>\n"
+							"\t<door wall='east'/>"
+							"</room>";
+
+		TiXmlDocument doc;
+		doc.Parse( str );
+
+		TiXmlHandle docHandle( &doc );
+		TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" );
+		TiXmlHandle commentHandle = docHandle.FirstChildElement( "room" ).FirstChild();
+		TiXmlHandle textHandle = docHandle.FirstChildElement( "room" ).ChildElement( "door", 0 ).FirstChild();
+		TiXmlHandle door0Handle = docHandle.FirstChildElement( "room" ).ChildElement( 0 );
+		TiXmlHandle door1Handle = docHandle.FirstChildElement( "room" ).ChildElement( 1 );
+
+		assert( docHandle.Node() );
+		assert( roomHandle.Element() );
+		assert( commentHandle.Node() );
+		assert( textHandle.Text() );
+		assert( door0Handle.Element() );
+		assert( door1Handle.Element() );
+
+		TiXmlDeclaration* declaration = doc.FirstChild()->ToDeclaration();
+		assert( declaration );
+		TiXmlElement* room = roomHandle.Element();
+		assert( room );
+		TiXmlAttribute* doors = room->FirstAttribute();
+		assert( doors );
+		TiXmlText* text = textHandle.Text();
+		TiXmlComment* comment = commentHandle.Node()->ToComment();
+		assert( comment );
+		TiXmlElement* door0 = door0Handle.Element();
+		TiXmlElement* door1 = door1Handle.Element();
+
+		XmlTest( "Location tracking: Declaration row", declaration->Row(), 1 );
+		XmlTest( "Location tracking: Declaration col", declaration->Column(), 5 );
+		XmlTest( "Location tracking: room row", room->Row(), 1 );
+		XmlTest( "Location tracking: room col", room->Column(), 45 );
+		XmlTest( "Location tracking: doors row", doors->Row(), 1 );
+		XmlTest( "Location tracking: doors col", doors->Column(), 51 );
+		XmlTest( "Location tracking: Comment row", comment->Row(), 2 );
+		XmlTest( "Location tracking: Comment col", comment->Column(), 3 );
+		XmlTest( "Location tracking: text row", text->Row(), 3 ); 
+		XmlTest( "Location tracking: text col", text->Column(), 24 );
+		XmlTest( "Location tracking: door0 row", door0->Row(), 3 );
+		XmlTest( "Location tracking: door0 col", door0->Column(), 5 );
+		XmlTest( "Location tracking: door1 row", door1->Row(), 4 );
+		XmlTest( "Location tracking: door1 col", door1->Column(), 5 );
+	}
+
+
+	// --------------------------------------------------------
+	// UTF-8 testing. It is important to test:
+	//	1. Making sure name, value, and text read correctly
+	//	2. Row, Col functionality
+	//	3. Correct output
+	// --------------------------------------------------------
+	printf ("\n** UTF-8 **\n");
+	{
+		TiXmlDocument doc( "utf8test.xml" );
+		doc.LoadFile();
+		if ( doc.Error() && doc.ErrorId() == TiXmlBase::TIXML_ERROR_OPENING_FILE ) {
+			printf( "WARNING: File 'utf8test.xml' not found.\n"
+					"(Are you running the test from the wrong directory?)\n"
+				    "Could not test UTF-8 functionality.\n" );
+		}
+		else
+		{
+			TiXmlHandle docH( &doc );
+			// Get the attribute "value" from the "Russian" element and check it.
+			TiXmlElement* element = docH.FirstChildElement( "document" ).FirstChildElement( "Russian" ).Element();
+			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" ), true );
+			XmlTest( "UTF-8: Russian value row.", 4, element->Row() );
+			XmlTest( "UTF-8: Russian value column.", 5, element->Column() );
+
+			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>";
+
+			TiXmlText* text = docH.FirstChildElement( "document" ).FirstChildElement( (const char*) russianElementName ).Child( 0 ).Text();
+			XmlTest( "UTF-8: Browsing russian element name.",
+					 russianText,
+					 text->Value(),
+					 true );
+			XmlTest( "UTF-8: Russian element name row.", 7, text->Row() );
+			XmlTest( "UTF-8: Russian element name column.", 47, text->Column() );
+
+			TiXmlDeclaration* dec = docH.Child( 0 ).Node()->ToDeclaration();
+			XmlTest( "UTF-8: Declaration column.", 1, dec->Column() );
+			XmlTest( "UTF-8: Document column.", 1, doc.Column() );
+
+			// Now try for a round trip.
+			doc.SaveFile( "utf8testout.xml" );
+
+			// Check the round trip.
+			char savedBuf[256];
+			char verifyBuf[256];
+			int okay = 1;
+
+			FILE* saved  = fopen( "utf8testout.xml", "r" );
+			FILE* verify = fopen( "utf8testverify.xml", "r" );
+
+			//bool firstLineBOM=true;
+			if ( saved && verify )
+			{
+				while ( fgets( verifyBuf, 256, verify ) )
+				{
+					fgets( savedBuf, 256, saved );
+					NullLineEndings( verifyBuf );
+					NullLineEndings( savedBuf );
+
+					if ( /*!firstLineBOM && */ strcmp( verifyBuf, savedBuf ) )
+					{
+						printf( "verify:%s<\n", verifyBuf );
+						printf( "saved :%s<\n", savedBuf );
+						okay = 0;
+						break;
+					}
+					//firstLineBOM = false;
+				}
+			}
+			if ( saved )
+				fclose( saved );
+			if ( verify )
+				fclose( verify );
+			XmlTest( "UTF-8: Verified multi-language round trip.", 1, okay );
+
+			// On most Western machines, this is an element that contains
+			// the word "resume" with the correct accents, in a latin encoding.
+			// It will be something else completely on non-wester machines,
+			// which is why TinyXml is switching to UTF-8.
+			const char latin[] = "<element>r\x82sum\x82</element>";
+
+			TiXmlDocument latinDoc;
+			latinDoc.Parse( latin, 0, TIXML_ENCODING_LEGACY );
+
+			text = latinDoc.FirstChildElement()->FirstChild()->ToText();
+			XmlTest( "Legacy encoding: Verify text element.", "r\x82sum\x82", text->Value() );
+		}
+	}		
+
+	//////////////////////
+	// Copy and assignment
+	//////////////////////
+	printf ("\n** Copy and Assignment **\n");
+	{
+		TiXmlElement element( "foo" );
+		element.Parse( "<element name='value' />", 0, TIXML_ENCODING_UNKNOWN );
+
+		TiXmlElement elementCopy( element );
+		TiXmlElement elementAssign( "foo" );
+		elementAssign.Parse( "<incorrect foo='bar'/>", 0, TIXML_ENCODING_UNKNOWN );
+		elementAssign = element;
+
+		XmlTest( "Copy/Assign: element copy #1.", "element", elementCopy.Value() );
+		XmlTest( "Copy/Assign: element copy #2.", "value", elementCopy.Attribute( "name" ) );
+		XmlTest( "Copy/Assign: element assign #1.", "element", elementAssign.Value() );
+		XmlTest( "Copy/Assign: element assign #2.", "value", elementAssign.Attribute( "name" ) );
+		XmlTest( "Copy/Assign: element assign #3.", true, ( 0 == elementAssign.Attribute( "foo" )) );
+
+		TiXmlComment comment;
+		comment.Parse( "<!--comment-->", 0, TIXML_ENCODING_UNKNOWN );
+		TiXmlComment commentCopy( comment );
+		TiXmlComment commentAssign;
+		commentAssign = commentCopy;
+		XmlTest( "Copy/Assign: comment copy.", "comment", commentCopy.Value() );
+		XmlTest( "Copy/Assign: comment assign.", "comment", commentAssign.Value() );
+
+		TiXmlUnknown unknown;
+		unknown.Parse( "<[unknown]>", 0, TIXML_ENCODING_UNKNOWN );
+		TiXmlUnknown unknownCopy( unknown );
+		TiXmlUnknown unknownAssign;
+		unknownAssign.Parse( "incorrect", 0, TIXML_ENCODING_UNKNOWN );
+		unknownAssign = unknownCopy;
+		XmlTest( "Copy/Assign: unknown copy.", "[unknown]", unknownCopy.Value() );
+		XmlTest( "Copy/Assign: unknown assign.", "[unknown]", unknownAssign.Value() );
+		
+		TiXmlText text( "TextNode" );
+		TiXmlText textCopy( text );
+		TiXmlText textAssign( "incorrect" );
+		textAssign = text;
+		XmlTest( "Copy/Assign: text copy.", "TextNode", textCopy.Value() );
+		XmlTest( "Copy/Assign: text assign.", "TextNode", textAssign.Value() );
+
+		TiXmlDeclaration dec;
+		dec.Parse( "<?xml version='1.0' encoding='UTF-8'?>", 0, TIXML_ENCODING_UNKNOWN );
+		TiXmlDeclaration decCopy( dec );
+		TiXmlDeclaration decAssign;
+		decAssign = dec;
+
+		XmlTest( "Copy/Assign: declaration copy.", "UTF-8", decCopy.Encoding() );
+		XmlTest( "Copy/Assign: text assign.", "UTF-8", decAssign.Encoding() );
+
+		TiXmlDocument doc;
+		elementCopy.InsertEndChild( textCopy );
+		doc.InsertEndChild( decAssign );
+		doc.InsertEndChild( elementCopy );
+		doc.InsertEndChild( unknownAssign );
+
+		TiXmlDocument docCopy( doc );
+		TiXmlDocument docAssign;
+		docAssign = docCopy;
+
+		#ifdef TIXML_USE_STL
+		std::string original, copy, assign;
+		original << doc;
+		copy << docCopy;
+		assign << docAssign;
+		XmlTest( "Copy/Assign: document copy.", original.c_str(), copy.c_str(), true );
+		XmlTest( "Copy/Assign: document assign.", original.c_str(), assign.c_str(), true );
+
+		#endif
+	}	
+
+	//////////////////////////////////////////////////////
+#ifdef TIXML_USE_STL
+	printf ("\n** Parsing, no Condense Whitespace **\n");
+	TiXmlBase::SetCondenseWhiteSpace( false );
+	{
+		istringstream parse1( "<start>This  is    \ntext</start>" );
+		TiXmlElement text1( "text" );
+		parse1 >> text1;
+
+		XmlTest ( "Condense white space OFF.", "This  is    \ntext",
+					text1.FirstChild()->Value(),
+					true );
+	}
+	TiXmlBase::SetCondenseWhiteSpace( true );
+#endif
+
+	//////////////////////////////////////////////////////
+	// GetText();
+	{
+		const char* str = "<foo>This is text</foo>";
+		TiXmlDocument doc;
+		doc.Parse( str );
+		const TiXmlElement* element = doc.RootElement();
+
+		XmlTest( "GetText() normal use.", "This is text", element->GetText() );
+
+		str = "<foo><b>This is text</b></foo>";
+		doc.Clear();
+		doc.Parse( str );
+		element = doc.RootElement();
+
+		XmlTest( "GetText() contained element.", element->GetText() == 0, true );
+
+		str = "<foo>This is <b>text</b></foo>";
+		doc.Clear();
+		TiXmlBase::SetCondenseWhiteSpace( false );
+		doc.Parse( str );
+		TiXmlBase::SetCondenseWhiteSpace( true );
+		element = doc.RootElement();
+
+		XmlTest( "GetText() partial.", "This is ", element->GetText() );
+	}
+
+
+	//////////////////////////////////////////////////////
+	// CDATA
+	{
+		const char* str =	"<xmlElement>"
+								"<![CDATA["
+									"I am > the rules!\n"
+									"...since I make symbolic puns"
+								"]]>"
+							"</xmlElement>";
+		TiXmlDocument doc;
+		doc.Parse( str );
+		doc.Print();
+
+		XmlTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(), 
+								 "I am > the rules!\n...since I make symbolic puns",
+								 true );
+
+		#ifdef TIXML_USE_STL
+		//cout << doc << '\n';
+
+		doc.Clear();
+
+		istringstream parse0( str );
+		parse0 >> doc;
+		//cout << doc << '\n';
+
+		XmlTest( "CDATA stream.", doc.FirstChildElement()->FirstChild()->Value(), 
+								 "I am > the rules!\n...since I make symbolic puns",
+								 true );
+		#endif
+
+		TiXmlDocument doc1 = doc;
+		//doc.Print();
+
+		XmlTest( "CDATA copy.", doc1.FirstChildElement()->FirstChild()->Value(), 
+								 "I am > the rules!\n...since I make symbolic puns",
+								 true );
+	}
+	{
+		// [ 1482728 ] Wrong wide char parsing
+		char buf[256];
+		buf[255] = 0;
+		for( int i=0; i<255; ++i ) {
+			buf[i] = (char)((i>=32) ? i : 32);
+		}
+		TIXML_STRING str( "<xmlElement><![CDATA[" );
+		str += buf;
+		str += "]]></xmlElement>";
+
+		TiXmlDocument doc;
+		doc.Parse( str.c_str() );
+
+		TiXmlPrinter printer;
+		printer.SetStreamPrinting();
+		doc.Accept( &printer );
+
+		XmlTest( "CDATA with all bytes #1.", str.c_str(), printer.CStr(), true );
+
+		#ifdef TIXML_USE_STL
+		doc.Clear();
+		istringstream iss( printer.Str() );
+		iss >> doc;
+		std::string out;
+		out << doc;
+		XmlTest( "CDATA with all bytes #2.", out.c_str(), printer.CStr(), true );
+		#endif
+	}
+	{
+		// [ 1480107 ] Bug-fix for STL-streaming of CDATA that contains tags
+		// CDATA streaming had a couple of bugs, that this tests for.
+		const char* str =	"<xmlElement>"
+								"<![CDATA["
+									"<b>I am > the rules!</b>\n"
+									"...since I make symbolic puns"
+								"]]>"
+							"</xmlElement>";
+		TiXmlDocument doc;
+		doc.Parse( str );
+		doc.Print();
+
+		XmlTest( "CDATA parse. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), 
+								 "<b>I am > the rules!</b>\n...since I make symbolic puns",
+								 true );
+
+		#ifdef TIXML_USE_STL
+
+		doc.Clear();
+
+		istringstream parse0( str );
+		parse0 >> doc;
+
+		XmlTest( "CDATA stream. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), 
+								 "<b>I am > the rules!</b>\n...since I make symbolic puns",
+								 true );
+		#endif
+
+		TiXmlDocument doc1 = doc;
+		//doc.Print();
+
+		XmlTest( "CDATA copy. [ 1480107 ]", doc1.FirstChildElement()->FirstChild()->Value(), 
+								 "<b>I am > the rules!</b>\n...since I make symbolic puns",
+								 true );
+	}
+	//////////////////////////////////////////////////////
+	// Visit()
+
+
+
+	//////////////////////////////////////////////////////
+	printf( "\n** Fuzzing... **\n" );
+
+	const int FUZZ_ITERATION = 300;
+
+	// The only goal is not to crash on bad input.
+	int len = (int) strlen( demoStart );
+	for( int i=0; i<FUZZ_ITERATION; ++i ) 
+	{
+		char* demoCopy = new char[ len+1 ];
+		strcpy( demoCopy, demoStart );
+
+		demoCopy[ i%len ] = (char)((i+1)*3);
+		demoCopy[ (i*7)%len ] = '>';
+		demoCopy[ (i*11)%len ] = '<';
+
+		TiXmlDocument xml;
+		xml.Parse( demoCopy );
+
+		delete [] demoCopy;
+	}
+	printf( "** Fuzzing Complete. **\n" );
+	
+	//////////////////////////////////////////////////////
+	printf ("\n** Bug regression tests **\n");
+
+	// InsertBeforeChild and InsertAfterChild causes crash.
+	{
+		TiXmlElement parent( "Parent" );
+		TiXmlElement childText0( "childText0" );
+		TiXmlElement childText1( "childText1" );
+		TiXmlNode* childNode0 = parent.InsertEndChild( childText0 );
+		TiXmlNode* childNode1 = parent.InsertBeforeChild( childNode0, childText1 );
+
+		XmlTest( "Test InsertBeforeChild on empty node.", ( childNode1 == parent.FirstChild() ), true );
+	}
+
+	{
+		// InsertBeforeChild and InsertAfterChild causes crash.
+		TiXmlElement parent( "Parent" );
+		TiXmlElement childText0( "childText0" );
+		TiXmlElement childText1( "childText1" );
+		TiXmlNode* childNode0 = parent.InsertEndChild( childText0 );
+		TiXmlNode* childNode1 = parent.InsertAfterChild( childNode0, childText1 );
+
+		XmlTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent.LastChild() ), true );
+	}
+
+	// Reports of missing constructors, irregular string problems.
+	{
+		// Missing constructor implementation. No test -- just compiles.
+		TiXmlText text( "Missing" );
+
+		#ifdef TIXML_USE_STL
+			// Missing implementation:
+			TiXmlDocument doc;
+			string name = "missing";
+			doc.LoadFile( name );
+
+			TiXmlText textSTL( name );
+		#else
+			// verifying some basic string functions:
+			TiXmlString a;
+			TiXmlString b( "Hello" );
+			TiXmlString c( "ooga" );
+
+			c = " World!";
+			a = b;
+			a += c;
+			a = a;
+
+			XmlTest( "Basic TiXmlString test. ", "Hello World!", a.c_str() );
+		#endif
+ 	}
+
+	// Long filenames crashing STL version
+	{
+		TiXmlDocument doc( "midsummerNightsDreamWithAVeryLongFilenameToConfuseTheStringHandlingRoutines.xml" );
+		bool loadOkay = doc.LoadFile();
+		loadOkay = true;	// get rid of compiler warning.
+		// Won't pass on non-dev systems. Just a "no crash" check.
+		//XmlTest( "Long filename. ", true, loadOkay );
+	}
+
+	{
+		// Entities not being written correctly.
+		// From Lynn Allen
+
+		const char* passages =
+			"<?xml version=\"1.0\" standalone=\"no\" ?>"
+			"<passages count=\"006\" formatversion=\"20020620\">"
+				"<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
+				" It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
+			"</passages>";
+
+		TiXmlDocument doc( "passages.xml" );
+		doc.Parse( passages );
+		TiXmlElement* 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( "textfile.txt", "w" );
+		if ( textfile )
+		{
+			psg->Print( textfile, 0 );
+			fclose( textfile );
+		}
+		textfile = fopen( "textfile.txt", "r" );
+		assert( textfile );
+		if ( textfile )
+		{
+			char buf[ 1024 ];
+			fgets( buf, 1024, textfile );
+			XmlTest( "Entity transformation: write. ",
+					 "<psg context=\'Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
+					 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.' />",
+					 buf,
+					 true );
+		}
+		fclose( textfile );
+	}
+
+    {
+		FILE* textfile = fopen( "test5.xml", "w" );
+		if ( textfile )
+		{
+            fputs("<?xml version='1.0'?><a.elem xmi.version='2.0'/>", textfile);
+            fclose(textfile);
+
+			TiXmlDocument doc;
+            doc.LoadFile( "test5.xml" );
+            XmlTest( "dot in element attributes and names", doc.Error(), 0);
+		}
+    }
+
+	{
+		FILE* textfile = fopen( "test6.xml", "w" );
+		if ( textfile )
+		{
+            fputs("<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>", textfile );
+            fclose(textfile);
+
+            TiXmlDocument doc;
+            bool result = doc.LoadFile( "test6.xml" );
+            XmlTest( "Entity with one digit.", result, true );
+
+			TiXmlText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
+			XmlTest( "Entity with one digit.",
+						text->Value(), "1.1 Start easy ignore fin thickness\n" );
+		}
+    }
+
+	{
+		// DOCTYPE not preserved (950171)
+		// 
+		const char* doctype =
+			"<?xml version=\"1.0\" ?>"
+			"<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
+			"<!ELEMENT title (#PCDATA)>"
+			"<!ELEMENT books (title,authors)>"
+			"<element />";
+
+		TiXmlDocument doc;
+		doc.Parse( doctype );
+		doc.SaveFile( "test7.xml" );
+		doc.Clear();
+		doc.LoadFile( "test7.xml" );
+		
+		TiXmlHandle docH( &doc );
+		TiXmlUnknown* unknown = docH.Child( 1 ).Unknown();
+		XmlTest( "Correct value of unknown.", "!DOCTYPE PLAY SYSTEM 'play.dtd'", unknown->Value() );
+		#ifdef TIXML_USE_STL
+		TiXmlNode* node = docH.Child( 2 ).Node();
+		std::string str;
+		str << (*node);
+		XmlTest( "Correct streaming of unknown.", "<!ELEMENT title (#PCDATA)>", str.c_str() );
+		#endif
+	}
+
+	{
+		// [ 791411 ] Formatting bug
+		// Comments do not stream out correctly.
+		const char* doctype = 
+			"<!-- Somewhat<evil> -->";
+		TiXmlDocument doc;
+		doc.Parse( doctype );
+
+		TiXmlHandle docH( &doc );
+		TiXmlComment* comment = docH.Child( 0 ).Node()->ToComment();
+
+		XmlTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
+		#ifdef TIXML_USE_STL
+		std::string str;
+		str << (*comment);
+		XmlTest( "Comment streaming.", "<!-- Somewhat<evil> -->", str.c_str() );
+		#endif
+	}
+
+	{
+		// [ 870502 ] White space issues
+		TiXmlDocument doc;
+		TiXmlText* text;
+		TiXmlHandle docH( &doc );
+	
+		const char* doctype0 = "<element> This has leading and trailing space </element>";
+		const char* doctype1 = "<element>This has  internal space</element>";
+		const char* doctype2 = "<element> This has leading, trailing, and  internal space </element>";
+
+		TiXmlBase::SetCondenseWhiteSpace( false );
+		doc.Clear();
+		doc.Parse( doctype0 );
+		text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
+		XmlTest( "White space kept.", " This has leading and trailing space ", text->Value() );
+
+		doc.Clear();
+		doc.Parse( doctype1 );
+		text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
+		XmlTest( "White space kept.", "This has  internal space", text->Value() );
+
+		doc.Clear();
+		doc.Parse( doctype2 );
+		text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
+		XmlTest( "White space kept.", " This has leading, trailing, and  internal space ", text->Value() );
+
+		TiXmlBase::SetCondenseWhiteSpace( true );
+		doc.Clear();
+		doc.Parse( doctype0 );
+		text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
+		XmlTest( "White space condensed.", "This has leading and trailing space", text->Value() );
+
+		doc.Clear();
+		doc.Parse( doctype1 );
+		text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
+		XmlTest( "White space condensed.", "This has internal space", text->Value() );
+
+		doc.Clear();
+		doc.Parse( doctype2 );
+		text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
+		XmlTest( "White space condensed.", "This has leading, trailing, and internal space", text->Value() );
+	}
+
+	{
+		// Double attributes
+		const char* doctype = "<element attr='red' attr='blue' />";
+
+		TiXmlDocument doc;
+		doc.Parse( doctype );
+		
+		XmlTest( "Parsing repeated attributes.", true, doc.Error() );	// is an  error to tinyxml (didn't use to be, but caused issues)
+		//XmlTest( "Parsing repeated attributes.", "blue", doc.FirstChildElement( "element" )->Attribute( "attr" ) );
+	}
+
+	{
+		// Embedded null in stream.
+		const char* doctype = "<element att\0r='red' attr='blue' />";
+
+		TiXmlDocument doc;
+		doc.Parse( doctype );
+		XmlTest( "Embedded null throws error.", true, doc.Error() );
+
+		#ifdef TIXML_USE_STL
+		istringstream strm( doctype );
+		doc.Clear();
+		doc.ClearError();
+		strm >> doc;
+		XmlTest( "Embedded null throws error.", true, doc.Error() );
+		#endif
+	}
+
+    {
+            // Legacy mode test. (This test may only pass on a western system)
+            const char* str =
+                        "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"
+                        "<ä>"
+                        "CöntäntßäöüÄÖÜ"
+                        "</ä>";
+
+            TiXmlDocument doc;
+            doc.Parse( str );
+
+            TiXmlHandle docHandle( &doc );
+            TiXmlHandle aHandle = docHandle.FirstChildElement( "ä" );
+            TiXmlHandle tHandle = aHandle.Child( 0 );
+            assert( aHandle.Element() );
+            assert( tHandle.Text() );
+            XmlTest( "ISO-8859-1 Parsing.", "CöntäntßäöüÄÖÜ", tHandle.Text()->Value() );
+    }
+
+	{
+		// Empty documents should return TIXML_ERROR_PARSING_EMPTY, bug 1070717
+		const char* str = "    ";
+		TiXmlDocument doc;
+		doc.Parse( str );
+		XmlTest( "Empty document error TIXML_ERROR_DOCUMENT_EMPTY", TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY, doc.ErrorId() );
+	}
+	#ifndef TIXML_USE_STL
+	{
+		// String equality. [ 1006409 ] string operator==/!= no worky in all cases
+		TiXmlString temp;
+		XmlTest( "Empty tinyxml string compare equal", ( temp == "" ), true );
+
+		TiXmlString    foo;
+		TiXmlString    bar( "" );
+		XmlTest( "Empty tinyxml string compare equal", ( foo == bar ), true );
+	}
+
+	#endif
+	{
+		// Bug [ 1195696 ] from marlonism
+		TiXmlBase::SetCondenseWhiteSpace(false); 
+		TiXmlDocument xml; 
+		xml.Parse("<text><break/>This hangs</text>"); 
+		XmlTest( "Test safe error return.", xml.Error(), false );
+	}
+
+	{
+		// Bug [ 1243992 ] - another infinite loop
+		TiXmlDocument doc;
+		doc.SetCondenseWhiteSpace(false);
+		doc.Parse("<p><pb></pb>test</p>");
+	} 
+	{
+		// Low entities
+		TiXmlDocument xml;
+		xml.Parse( "<test>&#x0e;</test>" );
+		const char result[] = { 0x0e, 0 };
+		XmlTest( "Low entities.", xml.FirstChildElement()->GetText(), result );
+		xml.Print();
+	}
+	{
+		// Bug [ 1451649 ] Attribute values with trailing quotes not handled correctly
+		TiXmlDocument xml;
+		xml.Parse( "<foo attribute=bar\" />" );
+		XmlTest( "Throw error with bad end quotes.", xml.Error(), true );
+	}
+	#ifdef TIXML_USE_STL
+	{
+		// Bug [ 1449463 ] Consider generic query
+		TiXmlDocument xml;
+		xml.Parse( "<foo bar='3' barStr='a string'/>" );
+
+		TiXmlElement* ele = xml.FirstChildElement();
+		double d;
+		int i;
+		float f;
+		bool b;
+		std::string str;
+
+		XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &d ), TIXML_SUCCESS );
+		XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &i ), TIXML_SUCCESS );
+		XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &f ), TIXML_SUCCESS );
+		XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &b ), TIXML_WRONG_TYPE );
+		XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "nobar", &b ), TIXML_NO_ATTRIBUTE );
+		XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "barStr", &str ), TIXML_SUCCESS );
+
+		XmlTest( "QueryValueAttribute", (d==3.0), true );
+		XmlTest( "QueryValueAttribute", (i==3), true );
+		XmlTest( "QueryValueAttribute", (f==3.0f), true );
+		XmlTest( "QueryValueAttribute", (str==std::string( "a string" )), true );
+	}
+	#endif
+
+	#ifdef TIXML_USE_STL
+	{
+		// [ 1505267 ] redundant malloc in TiXmlElement::Attribute
+		TiXmlDocument xml;
+		xml.Parse( "<foo bar='3' />" );
+		TiXmlElement* ele = xml.FirstChildElement();
+		double d;
+		int i;
+
+		std::string bar = "bar";
+
+		const std::string* atrrib = ele->Attribute( bar );
+		ele->Attribute( bar, &d );
+		ele->Attribute( bar, &i );
+
+		XmlTest( "Attribute", atrrib->empty(), false );
+		XmlTest( "Attribute", (d==3.0), true );
+		XmlTest( "Attribute", (i==3), true );
+	}
+	#endif
+
+	{
+		// [ 1356059 ] Allow TiXMLDocument to only be at the top level
+		TiXmlDocument xml, xml2;
+		xml.InsertEndChild( xml2 );
+		XmlTest( "Document only at top level.", xml.Error(), true );
+		XmlTest( "Document only at top level.", xml.ErrorId(), TiXmlBase::TIXML_ERROR_DOCUMENT_TOP_ONLY );
+	}
+
+	{
+		// [ 1663758 ] Failure to report error on bad XML
+		TiXmlDocument xml;
+		xml.Parse("<x>");
+		XmlTest("Missing end tag at end of input", xml.Error(), true);
+		xml.Parse("<x> ");
+		XmlTest("Missing end tag with trailing whitespace", xml.Error(), true);
+	} 
+
+	{
+		// [ 1635701 ] fail to parse files with a tag separated into two lines
+		// I'm not sure this is a bug. Marked 'pending' for feedback.
+		TiXmlDocument xml;
+		xml.Parse( "<title><p>text</p\n><title>" );
+		//xml.Print();
+		//XmlTest( "Tag split by newline", xml.Error(), false );
+	}
+
+	#ifdef TIXML_USE_STL
+	{
+		// [ 1475201 ] TinyXML parses entities in comments
+		TiXmlDocument xml;
+		istringstream parse1( "<!-- declarations for <head> & <body> -->"
+						      "<!-- far &amp; away -->" );
+		parse1 >> xml;
+
+		TiXmlNode* e0 = xml.FirstChild();
+		TiXmlNode* e1 = e0->NextSibling();
+		TiXmlComment* c0 = e0->ToComment();
+		TiXmlComment* c1 = e1->ToComment();
+
+		XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
+		XmlTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
+	}
+	#endif
+
+	{
+		// [ 1475201 ] TinyXML parses entities in comments
+		TiXmlDocument xml;
+		xml.Parse("<!-- declarations for <head> & <body> -->"
+				  "<!-- far &amp; away -->" );
+
+		TiXmlNode* e0 = xml.FirstChild();
+		TiXmlNode* e1 = e0->NextSibling();
+		TiXmlComment* c0 = e0->ToComment();
+		TiXmlComment* c1 = e1->ToComment();
+
+		XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
+		XmlTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
+	}
+
+	{
+		TiXmlDocument xml;
+		xml.Parse( "<Parent>"
+						"<child1 att=''/>"
+						"<!-- With this comment, child2 will not be parsed! -->"
+						"<child2 att=''/>"
+					"</Parent>" );
+		int count = 0;
+
+		TiXmlNode* ele = 0;
+		while ( (ele = xml.FirstChildElement( "Parent" )->IterateChildren( ele ) ) != 0 ) {
+			++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[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
+		buf[60] = 239;
+		buf[61] = 0;
+
+		TiXmlDocument doc;
+		doc.Parse( (const char*)buf);
+	} 
+
+
+	{
+		// bug 1827248 Error while parsing a little bit malformed file
+		// Actually not malformed - should work.
+		TiXmlDocument xml;
+		xml.Parse( "<attributelist> </attributelist >" );
+		XmlTest( "Handle end tag whitespace", false, xml.Error() );
+	}
+
+	{
+		// This one must not result in an infinite loop
+		TiXmlDocument xml;
+		xml.Parse( "<infinite>loop" );
+		XmlTest( "Infinite loop test.", true, true );
+	}
+
+	{
+		// 1709904 - can not repro the crash
+		{
+			TiXmlDocument xml;
+			xml.Parse( "<tag>/</tag>" );
+			XmlTest( "Odd XML parsing.", xml.FirstChild()->Value(), "tag" );
+		}
+		/* Could not repro. {
+			TiXmlDocument xml;
+			xml.LoadFile( "EQUI_Inventory.xml" );
+			//XmlTest( "Odd XML parsing.", xml.FirstChildElement()->Value(), "XML" );
+			TiXmlPrinter printer;
+			xml.Accept( &printer );
+			fprintf( stdout, "%s", printer.CStr() );
+		}*/
+	}
+
+	/*  1417717 experiment
+	{
+		TiXmlDocument xml;
+		xml.Parse("<text>Dan & Tracie</text>");
+		xml.Print(stdout);
+	}
+	{
+		TiXmlDocument xml;
+		xml.Parse("<text>Dan &foo; Tracie</text>");
+		xml.Print(stdout);
+	}
+	*/
+
+	#if defined( WIN32 ) && defined( TUNE )
+	_CrtMemCheckpoint( &endMemState );
+	//_CrtMemDumpStatistics( &endMemState );
+
+	_CrtMemState diffMemState;
+	_CrtMemDifference( &diffMemState, &startMemState, &endMemState );
+	_CrtMemDumpStatistics( &diffMemState );
+	#endif
+
+	printf ("\nPass %d, Fail %d\n", gPass, gFail);
+	return gFail;
+}
Index: branches/FEPSimulator/tinyxml/tinyxmlparser.cpp
===================================================================
--- branches/FEPSimulator/tinyxml/tinyxmlparser.cpp	(revision 80)
+++ branches/FEPSimulator/tinyxml/tinyxmlparser.cpp	(revision 80)
@@ -0,0 +1,1638 @@
+/*
+www.sourceforge.net/projects/tinyxml
+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 <ctype.h>
+#include <stddef.h>
+
+#include "tinyxml.h"
+
+//#define DEBUG_PARSER
+#if defined( DEBUG_PARSER )
+#	if defined( DEBUG ) && defined( _MSC_VER )
+#		include <windows.h>
+#		define TIXML_LOG OutputDebugString
+#	else
+#		define TIXML_LOG printf
+#	endif
+#endif
+
+// Note tha "PutString" hardcodes the same list. This
+// is less flexible than it appears. Changing the entries
+// or order will break putstring.	
+TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = 
+{
+	{ "&amp;",  5, '&' },
+	{ "&lt;",   4, '<' },
+	{ "&gt;",   4, '>' },
+	{ "&quot;", 6, '\"' },
+	{ "&apos;", 6, '\'' }
+};
+
+// Bunch of unicode info at:
+//		http://www.unicode.org/faq/utf_bom.html
+// Including the basic of this table, which determines the #bytes in the
+// sequence from the lead byte. 1 placed for invalid sequences --
+// although the result will be junk, pass it through as much as possible.
+// Beware of the non-characters in UTF-8:	
+//				ef bb bf (Microsoft "lead bytes")
+//				ef bf be
+//				ef bf bf 
+
+const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
+const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
+const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
+
+const int TiXmlBase::utf8ByteTable[256] = 
+{
+	//	0	1	2	3	4	5	6	7	8	9	a	b	c	d	e	f
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x00
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x10
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x20
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x30
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x40
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x50
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x60
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x70	End of ASCII range
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x80 0x80 to 0xc1 invalid
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x90 
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0xa0 
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0xb0 
+		1,	1,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	// 0xc0 0xc2 to 0xdf 2 byte
+		2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	// 0xd0
+		3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	// 0xe0 0xe0 to 0xef 3 byte
+		4,	4,	4,	4,	4,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1	// 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
+};
+
+
+void TiXmlBase::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; return; }	// This code won't covert this correctly anyway.
+
+	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]);
+	}
+}
+
+
+/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
+{
+	// This will only work for low-ascii, everything else is assumed to be a valid
+	// letter. I'm not sure this is the best approach, but it is quite tricky trying
+	// to figure out alhabetical vs. not across encoding. So take a very 
+	// conservative approach.
+
+//	if ( encoding == TIXML_ENCODING_UTF8 )
+//	{
+		if ( anyByte < 127 )
+			return isalpha( anyByte );
+		else
+			return 1;	// What else to do? The unicode set is huge...get the english ones right.
+//	}
+//	else
+//	{
+//		return isalpha( anyByte );
+//	}
+}
+
+
+/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
+{
+	// This will only work for low-ascii, everything else is assumed to be a valid
+	// letter. I'm not sure this is the best approach, but it is quite tricky trying
+	// to figure out alhabetical vs. not across encoding. So take a very 
+	// conservative approach.
+
+//	if ( encoding == TIXML_ENCODING_UTF8 )
+//	{
+		if ( anyByte < 127 )
+			return isalnum( anyByte );
+		else
+			return 1;	// What else to do? The unicode set is huge...get the english ones right.
+//	}
+//	else
+//	{
+//		return isalnum( anyByte );
+//	}
+}
+
+
+class TiXmlParsingData
+{
+	friend class TiXmlDocument;
+  public:
+	void Stamp( const char* now, TiXmlEncoding encoding );
+
+	const TiXmlCursor& Cursor() const	{ return cursor; }
+
+  private:
+	// Only used by the document!
+	TiXmlParsingData( const char* start, int _tabsize, int row, int col )
+	{
+		assert( start );
+		stamp = start;
+		tabsize = _tabsize;
+		cursor.row = row;
+		cursor.col = col;
+	}
+
+	TiXmlCursor		cursor;
+	const char*		stamp;
+	int				tabsize;
+};
+
+
+void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding )
+{
+	assert( now );
+
+	// Do nothing if the tabsize is 0.
+	if ( tabsize < 1 )
+	{
+		return;
+	}
+
+	// Get the current row, column.
+	int row = cursor.row;
+	int col = cursor.col;
+	const char* p = stamp;
+	assert( p );
+
+	while ( p < now )
+	{
+		// Treat p as unsigned, so we have a happy compiler.
+		const unsigned char* pU = (const unsigned char*)p;
+
+		// Code contributed by Fletcher Dunn: (modified by lee)
+		switch (*pU) {
+			case 0:
+				// We *should* never get here, but in case we do, don't
+				// advance past the terminating null character, ever
+				return;
+
+			case '\r':
+				// bump down to the next line
+				++row;
+				col = 0;				
+				// Eat the character
+				++p;
+
+				// Check for \r\n sequence, and treat this as a single character
+				if (*p == '\n') {
+					++p;
+				}
+				break;
+
+			case '\n':
+				// bump down to the next line
+				++row;
+				col = 0;
+
+				// Eat the character
+				++p;
+
+				// Check for \n\r sequence, and treat this as a single
+				// character.  (Yes, this bizarre thing does occur still
+				// on some arcane platforms...)
+				if (*p == '\r') {
+					++p;
+				}
+				break;
+
+			case '\t':
+				// Eat the character
+				++p;
+
+				// Skip to next tab stop
+				col = (col / tabsize + 1) * tabsize;
+				break;
+
+			case TIXML_UTF_LEAD_0:
+				if ( encoding == TIXML_ENCODING_UTF8 )
+				{
+					if ( *(p+1) && *(p+2) )
+					{
+						// In these cases, don't advance the column. These are
+						// 0-width spaces.
+						if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 )
+							p += 3;	
+						else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU )
+							p += 3;	
+						else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU )
+							p += 3;	
+						else
+							{ p +=3; ++col; }	// A normal character.
+					}
+				}
+				else
+				{
+					++p;
+					++col;
+				}
+				break;
+
+			default:
+				if ( encoding == TIXML_ENCODING_UTF8 )
+				{
+					// Eat the 1 to 4 byte utf8 character.
+					int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)];
+					if ( step == 0 )
+						step = 1;		// Error case from bad encoding, but handle gracefully.
+					p += step;
+
+					// Just advance one column, of course.
+					++col;
+				}
+				else
+				{
+					++p;
+					++col;
+				}
+				break;
+		}
+	}
+	cursor.row = row;
+	cursor.col = col;
+	assert( cursor.row >= -1 );
+	assert( cursor.col >= -1 );
+	stamp = p;
+	assert( stamp );
+}
+
+
+const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding )
+{
+	if ( !p || !*p )
+	{
+		return 0;
+	}
+	if ( encoding == TIXML_ENCODING_UTF8 )
+	{
+		while ( *p )
+		{
+			const unsigned char* pU = (const unsigned char*)p;
+			
+			// Skip the stupid Microsoft UTF-8 Byte order marks
+			if (	*(pU+0)==TIXML_UTF_LEAD_0
+				 && *(pU+1)==TIXML_UTF_LEAD_1 
+				 && *(pU+2)==TIXML_UTF_LEAD_2 )
+			{
+				p += 3;
+				continue;
+			}
+			else if(*(pU+0)==TIXML_UTF_LEAD_0
+				 && *(pU+1)==0xbfU
+				 && *(pU+2)==0xbeU )
+			{
+				p += 3;
+				continue;
+			}
+			else if(*(pU+0)==TIXML_UTF_LEAD_0
+				 && *(pU+1)==0xbfU
+				 && *(pU+2)==0xbfU )
+			{
+				p += 3;
+				continue;
+			}
+
+			if ( IsWhiteSpace( *p ) )		// Still using old rules for white space.
+				++p;
+			else
+				break;
+		}
+	}
+	else
+	{
+		while ( *p && IsWhiteSpace( *p ) )
+			++p;
+	}
+
+	return p;
+}
+
+#ifdef TIXML_USE_STL
+/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag )
+{
+	for( ;; )
+	{
+		if ( !in->good() ) return false;
+
+		int c = in->peek();
+		// At this scope, we can't get to a document. So fail silently.
+		if ( !IsWhiteSpace( c ) || c <= 0 )
+			return true;
+
+		*tag += (char) in->get();
+	}
+}
+
+/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag )
+{
+	//assert( character > 0 && character < 128 );	// else it won't work in utf-8
+	while ( in->good() )
+	{
+		int c = in->peek();
+		if ( c == character )
+			return true;
+		if ( c <= 0 )		// Silent failure: can't get document at this scope
+			return false;
+
+		in->get();
+		*tag += (char) c;
+	}
+	return false;
+}
+#endif
+
+// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The
+// "assign" optimization removes over 10% of the execution time.
+//
+const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding )
+{
+	// Oddly, not supported on some comilers,
+	//name->clear();
+	// So use this:
+	*name = "";
+	assert( p );
+
+	// Names start with letters or underscores.
+	// Of course, in unicode, tinyxml has no idea what a letter *is*. The
+	// algorithm is generous.
+	//
+	// After that, they can be letters, underscores, numbers,
+	// hyphens, or colons. (Colons are valid ony for namespaces,
+	// but tinyxml can't tell namespaces from names.)
+	if (    p && *p 
+		 && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) )
+	{
+		const char* start = p;
+		while(		p && *p
+				&&	(		IsAlphaNum( (unsigned char ) *p, encoding ) 
+						 || *p == '_'
+						 || *p == '-'
+						 || *p == '.'
+						 || *p == ':' ) )
+		{
+			//(*name) += *p; // expensive
+			++p;
+		}
+		if ( p-start > 0 ) {
+			name->assign( start, p-start );
+		}
+		return p;
+	}
+	return 0;
+}
+
+const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding )
+{
+	// Presume an entity, and pull it out.
+    TIXML_STRING ent;
+	int i;
+	*length = 0;
+
+	if ( *(p+1) && *(p+1) == '#' && *(p+2) )
+	{
+		unsigned long ucs = 0;
+		ptrdiff_t delta = 0;
+		unsigned mult = 1;
+
+		if ( *(p+2) == 'x' )
+		{
+			// Hexadecimal.
+			if ( !*(p+3) ) return 0;
+
+			const char* q = p+3;
+			q = strchr( q, ';' );
+
+			if ( !q || !*q ) return 0;
+
+			delta = q-p;
+			--q;
+
+			while ( *q != 'x' )
+			{
+				if ( *q >= '0' && *q <= '9' )
+					ucs += mult * (*q - '0');
+				else if ( *q >= 'a' && *q <= 'f' )
+					ucs += mult * (*q - 'a' + 10);
+				else if ( *q >= 'A' && *q <= 'F' )
+					ucs += mult * (*q - 'A' + 10 );
+				else 
+					return 0;
+				mult *= 16;
+				--q;
+			}
+		}
+		else
+		{
+			// Decimal.
+			if ( !*(p+2) ) return 0;
+
+			const char* q = p+2;
+			q = strchr( q, ';' );
+
+			if ( !q || !*q ) return 0;
+
+			delta = q-p;
+			--q;
+
+			while ( *q != '#' )
+			{
+				if ( *q >= '0' && *q <= '9' )
+					ucs += mult * (*q - '0');
+				else 
+					return 0;
+				mult *= 10;
+				--q;
+			}
+		}
+		if ( encoding == TIXML_ENCODING_UTF8 )
+		{
+			// convert the UCS to UTF-8
+			ConvertUTF32ToUTF8( ucs, value, length );
+		}
+		else
+		{
+			*value = (char)ucs;
+			*length = 1;
+		}
+		return p + delta + 1;
+	}
+
+	// Now try to match it.
+	for( i=0; i<NUM_ENTITY; ++i )
+	{
+		if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 )
+		{
+			assert( strlen( entity[i].str ) == entity[i].strLength );
+			*value = entity[i].chr;
+			*length = 1;
+			return ( p + entity[i].strLength );
+		}
+	}
+
+	// So it wasn't an entity, its unrecognized, or something like that.
+	*value = *p;	// Don't put back the last one, since we return it!
+	//*length = 1;	// Leave unrecognized entities - this doesn't really work.
+					// Just writes strange XML.
+	return p+1;
+}
+
+
+bool TiXmlBase::StringEqual( const char* p,
+							 const char* tag,
+							 bool ignoreCase,
+							 TiXmlEncoding encoding )
+{
+	assert( p );
+	assert( tag );
+	if ( !p || !*p )
+	{
+		assert( 0 );
+		return false;
+	}
+
+	const char* q = p;
+
+	if ( ignoreCase )
+	{
+		while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) )
+		{
+			++q;
+			++tag;
+		}
+
+		if ( *tag == 0 )
+			return true;
+	}
+	else
+	{
+		while ( *q && *tag && *q == *tag )
+		{
+			++q;
+			++tag;
+		}
+
+		if ( *tag == 0 )		// Have we found the end of the tag, and everything equal?
+			return true;
+	}
+	return false;
+}
+
+const char* TiXmlBase::ReadText(	const char* p, 
+									TIXML_STRING * text, 
+									bool trimWhiteSpace, 
+									const char* endTag, 
+									bool caseInsensitive,
+									TiXmlEncoding encoding )
+{
+    *text = "";
+	if (    !trimWhiteSpace			// certain tags always keep whitespace
+		 || !condenseWhiteSpace )	// if true, whitespace is always kept
+	{
+		// Keep all the white space.
+		while (	   p && *p
+				&& !StringEqual( p, endTag, caseInsensitive, encoding )
+			  )
+		{
+			int len;
+			char cArr[4] = { 0, 0, 0, 0 };
+			p = GetChar( p, cArr, &len, encoding );
+			text->append( cArr, len );
+		}
+	}
+	else
+	{
+		bool whitespace = false;
+
+		// Remove leading white space:
+		p = SkipWhiteSpace( p, encoding );
+		while (	   p && *p
+				&& !StringEqual( p, endTag, caseInsensitive, encoding ) )
+		{
+			if ( *p == '\r' || *p == '\n' )
+			{
+				whitespace = true;
+				++p;
+			}
+			else if ( IsWhiteSpace( *p ) )
+			{
+				whitespace = true;
+				++p;
+			}
+			else
+			{
+				// If we've found whitespace, add it before the
+				// new character. Any whitespace just becomes a space.
+				if ( whitespace )
+				{
+					(*text) += ' ';
+					whitespace = false;
+				}
+				int len;
+				char cArr[4] = { 0, 0, 0, 0 };
+				p = GetChar( p, cArr, &len, encoding );
+				if ( len == 1 )
+					(*text) += cArr[0];	// more efficient
+				else
+					text->append( cArr, len );
+			}
+		}
+	}
+	if ( p && *p )
+		p += strlen( endTag );
+	return ( p && *p ) ? p : 0;
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+	// The basic issue with a document is that we don't know what we're
+	// streaming. Read something presumed to be a tag (and hope), then
+	// identify it, and call the appropriate stream method on the tag.
+	//
+	// This "pre-streaming" will never read the closing ">" so the
+	// sub-tag can orient itself.
+
+	if ( !StreamTo( in, '<', tag ) ) 
+	{
+		SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return;
+	}
+
+	while ( in->good() )
+	{
+		int tagIndex = (int) tag->length();
+		while ( in->good() && in->peek() != '>' )
+		{
+			int c = in->get();
+			if ( c <= 0 )
+			{
+				SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+				break;
+			}
+			(*tag) += (char) c;
+		}
+
+		if ( in->good() )
+		{
+			// We now have something we presume to be a node of 
+			// some sort. Identify it, and call the node to
+			// continue streaming.
+			TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING );
+
+			if ( node )
+			{
+				node->StreamIn( in, tag );
+				bool isElement = node->ToElement() != 0;
+				delete node;
+				node = 0;
+
+				// If this is the root element, we're done. Parsing will be
+				// done by the >> operator.
+				if ( isElement )
+				{
+					return;
+				}
+			}
+			else
+			{
+				SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
+				return;
+			}
+		}
+	}
+	// We should have returned sooner.
+	SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
+}
+
+#endif
+
+const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding )
+{
+	ClearError();
+
+	// Parse away, at the document level. Since a document
+	// contains nothing but other tags, most of what happens
+	// here is skipping white space.
+	if ( !p || !*p )
+	{
+		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	// Note that, for a document, this needs to come
+	// before the while space skip, so that parsing
+	// starts from the pointer we are given.
+	location.Clear();
+	if ( prevData )
+	{
+		location.row = prevData->cursor.row;
+		location.col = prevData->cursor.col;
+	}
+	else
+	{
+		location.row = 0;
+		location.col = 0;
+	}
+	TiXmlParsingData data( p, TabSize(), location.row, location.col );
+	location = data.Cursor();
+
+	if ( encoding == TIXML_ENCODING_UNKNOWN )
+	{
+		// Check for the Microsoft UTF-8 lead bytes.
+		const unsigned char* pU = (const unsigned char*)p;
+		if (	*(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0
+			 && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1
+			 && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 )
+		{
+			encoding = TIXML_ENCODING_UTF8;
+			useMicrosoftBOM = true;
+		}
+	}
+
+    p = SkipWhiteSpace( p, encoding );
+	if ( !p )
+	{
+		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	while ( p && *p )
+	{
+		TiXmlNode* node = Identify( p, encoding );
+		if ( node )
+		{
+			p = node->Parse( p, &data, encoding );
+			LinkEndChild( node );
+		}
+		else
+		{
+			break;
+		}
+
+		// Did we get encoding info?
+		if (    encoding == TIXML_ENCODING_UNKNOWN
+			 && node->ToDeclaration() )
+		{
+			TiXmlDeclaration* dec = node->ToDeclaration();
+			const char* enc = dec->Encoding();
+			assert( enc );
+
+			if ( *enc == 0 )
+				encoding = TIXML_ENCODING_UTF8;
+			else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) )
+				encoding = TIXML_ENCODING_UTF8;
+			else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) )
+				encoding = TIXML_ENCODING_UTF8;	// incorrect, but be nice
+			else 
+				encoding = TIXML_ENCODING_LEGACY;
+		}
+
+		p = SkipWhiteSpace( p, encoding );
+	}
+
+	// Was this empty?
+	if ( !firstChild ) {
+		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding );
+		return 0;
+	}
+
+	// All is well.
+	return p;
+}
+
+void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding )
+{	
+	// The first error in a chain is more accurate - don't set again!
+	if ( error )
+		return;
+
+	assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
+	error   = true;
+	errorId = err;
+	errorDesc = errorString[ errorId ];
+
+	errorLocation.Clear();
+	if ( pError && data )
+	{
+		data->Stamp( pError, encoding );
+		errorLocation = data->Cursor();
+	}
+}
+
+
+TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding )
+{
+	TiXmlNode* returnNode = 0;
+
+	p = SkipWhiteSpace( p, encoding );
+	if( !p || !*p || *p != '<' )
+	{
+		return 0;
+	}
+
+	p = SkipWhiteSpace( p, encoding );
+
+	if ( !p || !*p )
+	{
+		return 0;
+	}
+
+	// What is this thing? 
+	// - Elements start with a letter or underscore, but xml is reserved.
+	// - Comments: <!--
+	// - Decleration: <?xml
+	// - Everthing else is unknown to tinyxml.
+	//
+
+	const char* xmlHeader = { "<?xml" };
+	const char* commentHeader = { "<!--" };
+	const char* dtdHeader = { "<!" };
+	const char* cdataHeader = { "<![CDATA[" };
+
+	if ( StringEqual( p, xmlHeader, true, encoding ) )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Declaration\n" );
+		#endif
+		returnNode = new TiXmlDeclaration();
+	}
+	else if ( StringEqual( p, commentHeader, false, encoding ) )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Comment\n" );
+		#endif
+		returnNode = new TiXmlComment();
+	}
+	else if ( StringEqual( p, cdataHeader, false, encoding ) )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing CDATA\n" );
+		#endif
+		TiXmlText* text = new TiXmlText( "" );
+		text->SetCDATA( true );
+		returnNode = text;
+	}
+	else if ( StringEqual( p, dtdHeader, false, encoding ) )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Unknown(1)\n" );
+		#endif
+		returnNode = new TiXmlUnknown();
+	}
+	else if (    IsAlpha( *(p+1), encoding )
+			  || *(p+1) == '_' )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Element\n" );
+		#endif
+		returnNode = new TiXmlElement( "" );
+	}
+	else
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Unknown(2)\n" );
+		#endif
+		returnNode = new TiXmlUnknown();
+	}
+
+	if ( returnNode )
+	{
+		// Set the parent, so it can report errors
+		returnNode->parent = this;
+	}
+	return returnNode;
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag)
+{
+	// We're called with some amount of pre-parsing. That is, some of "this"
+	// element is in "tag". Go ahead and stream to the closing ">"
+	while( in->good() )
+	{
+		int c = in->get();
+		if ( c <= 0 )
+		{
+			TiXmlDocument* document = GetDocument();
+			if ( document )
+				document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+			return;
+		}
+		(*tag) += (char) c ;
+		
+		if ( c == '>' )
+			break;
+	}
+
+	if ( tag->length() < 3 ) return;
+
+	// Okay...if we are a "/>" tag, then we're done. We've read a complete tag.
+	// If not, identify and stream.
+
+	if (    tag->at( tag->length() - 1 ) == '>' 
+		 && tag->at( tag->length() - 2 ) == '/' )
+	{
+		// All good!
+		return;
+	}
+	else if ( tag->at( tag->length() - 1 ) == '>' )
+	{
+		// There is more. Could be:
+		//		text
+		//		cdata text (which looks like another node)
+		//		closing tag
+		//		another node.
+		for ( ;; )
+		{
+			StreamWhiteSpace( in, tag );
+
+			// Do we have text?
+			if ( in->good() && in->peek() != '<' ) 
+			{
+				// Yep, text.
+				TiXmlText text( "" );
+				text.StreamIn( in, tag );
+
+				// What follows text is a closing tag or another node.
+				// Go around again and figure it out.
+				continue;
+			}
+
+			// We now have either a closing tag...or another node.
+			// We should be at a "<", regardless.
+			if ( !in->good() ) return;
+			assert( in->peek() == '<' );
+			int tagIndex = (int) tag->length();
+
+			bool closingTag = false;
+			bool firstCharFound = false;
+
+			for( ;; )
+			{
+				if ( !in->good() )
+					return;
+
+				int c = in->peek();
+				if ( c <= 0 )
+				{
+					TiXmlDocument* document = GetDocument();
+					if ( document )
+						document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+					return;
+				}
+				
+				if ( c == '>' )
+					break;
+
+				*tag += (char) c;
+				in->get();
+
+				// Early out if we find the CDATA id.
+				if ( c == '[' && tag->size() >= 9 )
+				{
+					size_t len = tag->size();
+					const char* start = tag->c_str() + len - 9;
+					if ( strcmp( start, "<![CDATA[" ) == 0 ) {
+						assert( !closingTag );
+						break;
+					}
+				}
+
+				if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) )
+				{
+					firstCharFound = true;
+					if ( c == '/' )
+						closingTag = true;
+				}
+			}
+			// If it was a closing tag, then read in the closing '>' to clean up the input stream.
+			// If it was not, the streaming will be done by the tag.
+			if ( closingTag )
+			{
+				if ( !in->good() )
+					return;
+
+				int c = in->get();
+				if ( c <= 0 )
+				{
+					TiXmlDocument* document = GetDocument();
+					if ( document )
+						document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+					return;
+				}
+				assert( c == '>' );
+				*tag += (char) c;
+
+				// We are done, once we've found our closing tag.
+				return;
+			}
+			else
+			{
+				// If not a closing tag, id it, and stream.
+				const char* tagloc = tag->c_str() + tagIndex;
+				TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING );
+				if ( !node )
+					return;
+				node->StreamIn( in, tag );
+				delete node;
+				node = 0;
+
+				// No return: go around from the beginning: text, closing tag, or node.
+			}
+		}
+	}
+}
+#endif
+
+const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	p = SkipWhiteSpace( p, encoding );
+	TiXmlDocument* document = GetDocument();
+
+	if ( !p || !*p )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding );
+		return 0;
+	}
+
+	if ( data )
+	{
+		data->Stamp( p, encoding );
+		location = data->Cursor();
+	}
+
+	if ( *p != '<' )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding );
+		return 0;
+	}
+
+	p = SkipWhiteSpace( p+1, encoding );
+
+	// Read the name.
+	const char* pErr = p;
+
+    p = ReadName( p, &value, encoding );
+	if ( !p || !*p )
+	{
+		if ( document )	document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding );
+		return 0;
+	}
+
+    TIXML_STRING endTag ("</");
+	endTag += value;
+
+	// Check for and read attributes. Also look for an empty
+	// tag or an end tag.
+	while ( p && *p )
+	{
+		pErr = p;
+		p = SkipWhiteSpace( p, encoding );
+		if ( !p || !*p )
+		{
+			if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
+			return 0;
+		}
+		if ( *p == '/' )
+		{
+			++p;
+			// Empty tag.
+			if ( *p  != '>' )
+			{
+				if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding );		
+				return 0;
+			}
+			return (p+1);
+		}
+		else if ( *p == '>' )
+		{
+			// Done with attributes (if there were any.)
+			// Read the value -- which can include other
+			// elements -- read the end tag, and return.
+			++p;
+			p = ReadValue( p, data, encoding );		// Note this is an Element method, and will set the error if one happens.
+			if ( !p || !*p ) {
+				// We were looking for the end tag, but found nothing.
+				// Fix for [ 1663758 ] Failure to report error on bad XML
+				if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
+				return 0;
+			}
+
+			// We should find the end tag now
+			// note that:
+			// </foo > and
+			// </foo> 
+			// are both valid end tags.
+			if ( StringEqual( p, endTag.c_str(), false, encoding ) )
+			{
+				p += endTag.length();
+				p = SkipWhiteSpace( p, encoding );
+				if ( p && *p && *p == '>' ) {
+					++p;
+					return p;
+				}
+				if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
+				return 0;
+			}
+			else
+			{
+				if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
+				return 0;
+			}
+		}
+		else
+		{
+			// Try to read an attribute:
+			TiXmlAttribute* attrib = new TiXmlAttribute();
+			if ( !attrib )
+			{
+				return 0;
+			}
+
+			attrib->SetDocument( document );
+			pErr = p;
+			p = attrib->Parse( p, data, encoding );
+
+			if ( !p || !*p )
+			{
+				if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
+				delete attrib;
+				return 0;
+			}
+
+			// Handle the strange case of double attributes:
+			#ifdef TIXML_USE_STL
+			TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() );
+			#else
+			TiXmlAttribute* node = attributeSet.Find( attrib->Name() );
+			#endif
+			if ( node )
+			{
+				if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
+				delete attrib;
+				return 0;
+			}
+
+			attributeSet.Add( attrib );
+		}
+	}
+	return p;
+}
+
+
+const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	TiXmlDocument* document = GetDocument();
+
+	// Read in text and elements in any order.
+	const char* pWithWhiteSpace = p;
+	p = SkipWhiteSpace( p, encoding );
+
+	while ( p && *p )
+	{
+		if ( *p != '<' )
+		{
+			// Take what we have, make a text element.
+			TiXmlText* textNode = new TiXmlText( "" );
+
+			if ( !textNode )
+			{
+			    return 0;
+			}
+
+			if ( TiXmlBase::IsWhiteSpaceCondensed() )
+			{
+				p = textNode->Parse( p, data, encoding );
+			}
+			else
+			{
+				// Special case: we want to keep the white space
+				// so that leading spaces aren't removed.
+				p = textNode->Parse( pWithWhiteSpace, data, encoding );
+			}
+
+			if ( !textNode->Blank() )
+				LinkEndChild( textNode );
+			else
+				delete textNode;
+		} 
+		else 
+		{
+			// We hit a '<'
+			// Have we hit a new element or an end tag? This could also be
+			// a TiXmlText in the "CDATA" style.
+			if ( StringEqual( p, "</", false, encoding ) )
+			{
+				return p;
+			}
+			else
+			{
+				TiXmlNode* node = Identify( p, encoding );
+				if ( node )
+				{
+					p = node->Parse( p, data, encoding );
+					LinkEndChild( node );
+				}				
+				else
+				{
+					return 0;
+				}
+			}
+		}
+		pWithWhiteSpace = p;
+		p = SkipWhiteSpace( p, encoding );
+	}
+
+	if ( !p )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding );
+	}	
+	return p;
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlUnknown::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->get();	
+		if ( c <= 0 )
+		{
+			TiXmlDocument* document = GetDocument();
+			if ( document )
+				document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+			return;
+		}
+		(*tag) += (char) c;
+
+		if ( c == '>' )
+		{
+			// All is well.
+			return;		
+		}
+	}
+}
+#endif
+
+
+const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	TiXmlDocument* document = GetDocument();
+	p = SkipWhiteSpace( p, encoding );
+
+	if ( data )
+	{
+		data->Stamp( p, encoding );
+		location = data->Cursor();
+	}
+	if ( !p || !*p || *p != '<' )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding );
+		return 0;
+	}
+	++p;
+    value = "";
+
+	while ( p && *p && *p != '>' )
+	{
+		value += *p;
+		++p;
+	}
+
+	if ( !p )
+	{
+		if ( document )	
+			document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
+	}
+	if ( p && *p == '>' )
+		return p+1;
+	return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->get();	
+		if ( c <= 0 )
+		{
+			TiXmlDocument* document = GetDocument();
+			if ( document )
+				document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+			return;
+		}
+
+		(*tag) += (char) c;
+
+		if ( c == '>' 
+			 && tag->at( tag->length() - 2 ) == '-'
+			 && tag->at( tag->length() - 3 ) == '-' )
+		{
+			// All is well.
+			return;		
+		}
+	}
+}
+#endif
+
+
+const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	TiXmlDocument* document = GetDocument();
+	value = "";
+
+	p = SkipWhiteSpace( p, encoding );
+
+	if ( data )
+	{
+		data->Stamp( p, encoding );
+		location = data->Cursor();
+	}
+	const char* startTag = "<!--";
+	const char* endTag   = "-->";
+
+	if ( !StringEqual( p, startTag, false, encoding ) )
+	{
+		if ( document )
+			document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding );
+		return 0;
+	}
+	p += strlen( startTag );
+
+	// [ 1475201 ] TinyXML parses entities in comments
+	// Oops - ReadText doesn't work, because we don't want to parse the entities.
+	// p = ReadText( p, &value, false, endTag, false, encoding );
+	//
+	// from the XML spec:
+	/*
+	 [Definition: Comments may appear anywhere in a document outside other markup; in addition, 
+	              they may appear within the document type declaration at places allowed by the grammar. 
+				  They are not part of the document's character data; an XML processor MAY, but need not, 
+				  make it possible for an application to retrieve the text of comments. For compatibility, 
+				  the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity 
+				  references MUST NOT be recognized within comments.
+
+				  An example of a comment:
+
+				  <!-- declarations for <head> & <body> -->
+	*/
+
+    value = "";
+	// Keep all the white space.
+	while (	p && *p && !StringEqual( p, endTag, false, encoding ) )
+	{
+		value.append( p, 1 );
+		++p;
+	}
+	if ( p && *p ) 
+		p += strlen( endTag );
+
+	return p;
+}
+
+
+const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	p = SkipWhiteSpace( p, encoding );
+	if ( !p || !*p ) return 0;
+
+	if ( data )
+	{
+		data->Stamp( p, encoding );
+		location = data->Cursor();
+	}
+	// Read the name, the '=' and the value.
+	const char* pErr = p;
+	p = ReadName( p, &name, encoding );
+	if ( !p || !*p )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
+		return 0;
+	}
+	p = SkipWhiteSpace( p, encoding );
+	if ( !p || !*p || *p != '=' )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+		return 0;
+	}
+
+	++p;	// skip '='
+	p = SkipWhiteSpace( p, encoding );
+	if ( !p || !*p )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+		return 0;
+	}
+	
+	const char* end;
+	const char SINGLE_QUOTE = '\'';
+	const char DOUBLE_QUOTE = '\"';
+
+	if ( *p == SINGLE_QUOTE )
+	{
+		++p;
+		end = "\'";		// single quote in string
+		p = ReadText( p, &value, false, end, false, encoding );
+	}
+	else if ( *p == DOUBLE_QUOTE )
+	{
+		++p;
+		end = "\"";		// double quote in string
+		p = ReadText( p, &value, false, end, false, encoding );
+	}
+	else
+	{
+		// All attribute values should be in single or double quotes.
+		// But this is such a common error that the parser will try
+		// its best, even without them.
+		value = "";
+		while (    p && *p											// existence
+				&& !IsWhiteSpace( *p )								// whitespace
+				&& *p != '/' && *p != '>' )							// tag end
+		{
+			if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) {
+				// [ 1451649 ] Attribute values with trailing quotes not handled correctly
+				// We did not have an opening quote but seem to have a 
+				// closing one. Give up and throw an error.
+				if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+				return 0;
+			}
+			value += *p;
+			++p;
+		}
+	}
+	return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->peek();	
+		if ( !cdata && (c == '<' ) ) 
+		{
+			return;
+		}
+		if ( c <= 0 )
+		{
+			TiXmlDocument* document = GetDocument();
+			if ( document )
+				document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+			return;
+		}
+
+		(*tag) += (char) c;
+		in->get();	// "commits" the peek made above
+
+		if ( cdata && c == '>' && tag->size() >= 3 ) {
+			size_t len = tag->size();
+			if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) {
+				// terminator of cdata.
+				return;
+			}
+		}    
+	}
+}
+#endif
+
+const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	value = "";
+	TiXmlDocument* document = GetDocument();
+
+	if ( data )
+	{
+		data->Stamp( p, encoding );
+		location = data->Cursor();
+	}
+
+	const char* const startTag = "<![CDATA[";
+	const char* const endTag   = "]]>";
+
+	if ( cdata || StringEqual( p, startTag, false, encoding ) )
+	{
+		cdata = true;
+
+		if ( !StringEqual( p, startTag, false, encoding ) )
+		{
+			if ( document )
+				document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding );
+			return 0;
+		}
+		p += strlen( startTag );
+
+		// Keep all the white space, ignore the encoding, etc.
+		while (	   p && *p
+				&& !StringEqual( p, endTag, false, encoding )
+			  )
+		{
+			value += *p;
+			++p;
+		}
+
+		TIXML_STRING dummy; 
+		p = ReadText( p, &dummy, false, endTag, false, encoding );
+		return p;
+	}
+	else
+	{
+		bool ignoreWhite = true;
+
+		const char* end = "<";
+		p = ReadText( p, &value, ignoreWhite, end, false, encoding );
+		if ( p && *p )
+			return p-1;	// don't truncate the '<'
+		return 0;
+	}
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->get();
+		if ( c <= 0 )
+		{
+			TiXmlDocument* document = GetDocument();
+			if ( document )
+				document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+			return;
+		}
+		(*tag) += (char) c;
+
+		if ( c == '>' )
+		{
+			// All is well.
+			return;
+		}
+	}
+}
+#endif
+
+const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding )
+{
+	p = SkipWhiteSpace( p, _encoding );
+	// Find the beginning, find the end, and look for
+	// the stuff in-between.
+	TiXmlDocument* document = GetDocument();
+	if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding );
+		return 0;
+	}
+	if ( data )
+	{
+		data->Stamp( p, _encoding );
+		location = data->Cursor();
+	}
+	p += 5;
+
+	version = "";
+	encoding = "";
+	standalone = "";
+
+	while ( p && *p )
+	{
+		if ( *p == '>' )
+		{
+			++p;
+			return p;
+		}
+
+		p = SkipWhiteSpace( p, _encoding );
+		if ( StringEqual( p, "version", true, _encoding ) )
+		{
+			TiXmlAttribute attrib;
+			p = attrib.Parse( p, data, _encoding );		
+			version = attrib.Value();
+		}
+		else if ( StringEqual( p, "encoding", true, _encoding ) )
+		{
+			TiXmlAttribute attrib;
+			p = attrib.Parse( p, data, _encoding );		
+			encoding = attrib.Value();
+		}
+		else if ( StringEqual( p, "standalone", true, _encoding ) )
+		{
+			TiXmlAttribute attrib;
+			p = attrib.Parse( p, data, _encoding );		
+			standalone = attrib.Value();
+		}
+		else
+		{
+			// Read over whatever it is.
+			while( p && *p && *p != '>' && !IsWhiteSpace( *p ) )
+				++p;
+		}
+	}
+	return 0;
+}
+
+bool TiXmlText::Blank() const
+{
+	for ( unsigned i=0; i<value.length(); i++ )
+		if ( !IsWhiteSpace( value[i] ) )
+			return false;
+	return true;
+}
+
Index: branches/FEPSimulator/tinyxml/tinyxml.cpp
===================================================================
--- branches/FEPSimulator/tinyxml/tinyxml.cpp	(revision 80)
+++ branches/FEPSimulator/tinyxml/tinyxml.cpp	(revision 80)
@@ -0,0 +1,1886 @@
+/*
+www.sourceforge.net/projects/tinyxml
+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 <ctype.h>
+
+#ifdef TIXML_USE_STL
+#include <sstream>
+#include <iostream>
+#endif
+
+#include "tinyxml.h"
+
+FILE* TiXmlFOpen( const char* filename, const char* mode );
+
+bool TiXmlBase::condenseWhiteSpace = true;
+
+// Microsoft compiler security
+FILE* TiXmlFOpen( const char* filename, const char* mode )
+{
+	#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+		FILE* fp = 0;
+		errno_t err = fopen_s( &fp, filename, mode );
+		if ( !err && fp )
+			return fp;
+		return 0;
+	#else
+		return fopen( filename, mode );
+	#endif
+}
+
+void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
+{
+	int i=0;
+
+	while( i<(int)str.length() )
+	{
+		unsigned char c = (unsigned char) str[i];
+
+		if (    c == '&' 
+		     && i < ( (int)str.length() - 2 )
+			 && str[i+1] == '#'
+			 && str[i+2] == 'x' )
+		{
+			// Hexadecimal character reference.
+			// Pass through unchanged.
+			// &#xA9;	-- copyright symbol, for example.
+			//
+			// The -1 is a bug fix from Rob Laveaux. It keeps
+			// an overflow from happening if there is no ';'.
+			// There are actually 2 ways to exit this loop -
+			// while fails (error case) and break (semicolon found).
+			// However, there is no mechanism (currently) for
+			// this function to return an error.
+			while ( i<(int)str.length()-1 )
+			{
+				outString->append( str.c_str() + i, 1 );
+				++i;
+				if ( str[i] == ';' )
+					break;
+			}
+		}
+		else if ( c == '&' )
+		{
+			outString->append( entity[0].str, entity[0].strLength );
+			++i;
+		}
+		else if ( c == '<' )
+		{
+			outString->append( entity[1].str, entity[1].strLength );
+			++i;
+		}
+		else if ( c == '>' )
+		{
+			outString->append( entity[2].str, entity[2].strLength );
+			++i;
+		}
+		else if ( c == '\"' )
+		{
+			outString->append( entity[3].str, entity[3].strLength );
+			++i;
+		}
+		else if ( c == '\'' )
+		{
+			outString->append( entity[4].str, entity[4].strLength );
+			++i;
+		}
+		else if ( c < 32 )
+		{
+			// Easy pass at non-alpha/numeric/symbol
+			// Below 32 is symbolic.
+			char buf[ 32 ];
+			
+			#if defined(TIXML_SNPRINTF)		
+				TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
+			#else
+				sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
+			#endif		
+
+			//*ME:	warning C4267: convert 'size_t' to 'int'
+			//*ME:	Int-Cast to make compiler happy ...
+			outString->append( buf, (int)strlen( buf ) );
+			++i;
+		}
+		else
+		{
+			//char realc = (char) c;
+			//outString->append( &realc, 1 );
+			*outString += (char) c;	// somewhat more efficient function call.
+			++i;
+		}
+	}
+}
+
+
+TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
+{
+	parent = 0;
+	type = _type;
+	firstChild = 0;
+	lastChild = 0;
+	prev = 0;
+	next = 0;
+}
+
+
+TiXmlNode::~TiXmlNode()
+{
+	TiXmlNode* node = firstChild;
+	TiXmlNode* temp = 0;
+
+	while ( node )
+	{
+		temp = node;
+		node = node->next;
+		delete temp;
+	}	
+}
+
+
+void TiXmlNode::CopyTo( TiXmlNode* target ) const
+{
+	target->SetValue (value.c_str() );
+	target->userData = userData; 
+	target->location = location;
+}
+
+
+void TiXmlNode::Clear()
+{
+	TiXmlNode* node = firstChild;
+	TiXmlNode* temp = 0;
+
+	while ( node )
+	{
+		temp = node;
+		node = node->next;
+		delete temp;
+	}	
+
+	firstChild = 0;
+	lastChild = 0;
+}
+
+
+TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
+{
+	assert( node->parent == 0 || node->parent == this );
+	assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
+
+	if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT )
+	{
+		delete node;
+		if ( GetDocument() ) 
+			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	node->parent = this;
+
+	node->prev = lastChild;
+	node->next = 0;
+
+	if ( lastChild )
+		lastChild->next = node;
+	else
+		firstChild = node;			// it was an empty list.
+
+	lastChild = node;
+	return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
+{
+	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
+	{
+		if ( GetDocument() ) 
+			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+	TiXmlNode* node = addThis.Clone();
+	if ( !node )
+		return 0;
+
+	return LinkEndChild( node );
+}
+
+
+TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
+{	
+	if ( !beforeThis || beforeThis->parent != this ) {
+		return 0;
+	}
+	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
+	{
+		if ( GetDocument() ) 
+			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	TiXmlNode* node = addThis.Clone();
+	if ( !node )
+		return 0;
+	node->parent = this;
+
+	node->next = beforeThis;
+	node->prev = beforeThis->prev;
+	if ( beforeThis->prev )
+	{
+		beforeThis->prev->next = node;
+	}
+	else
+	{
+		assert( firstChild == beforeThis );
+		firstChild = node;
+	}
+	beforeThis->prev = node;
+	return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
+{
+	if ( !afterThis || afterThis->parent != this ) {
+		return 0;
+	}
+	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
+	{
+		if ( GetDocument() ) 
+			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	TiXmlNode* node = addThis.Clone();
+	if ( !node )
+		return 0;
+	node->parent = this;
+
+	node->prev = afterThis;
+	node->next = afterThis->next;
+	if ( afterThis->next )
+	{
+		afterThis->next->prev = node;
+	}
+	else
+	{
+		assert( lastChild == afterThis );
+		lastChild = node;
+	}
+	afterThis->next = node;
+	return node;
+}
+
+
+TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
+{
+	if ( !replaceThis )
+		return 0;
+
+	if ( replaceThis->parent != this )
+		return 0;
+
+	if ( withThis.ToDocument() ) {
+		// A document can never be a child.	Thanks to Noam.
+		TiXmlDocument* document = GetDocument();
+		if ( document ) 
+			document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	TiXmlNode* node = withThis.Clone();
+	if ( !node )
+		return 0;
+
+	node->next = replaceThis->next;
+	node->prev = replaceThis->prev;
+
+	if ( replaceThis->next )
+		replaceThis->next->prev = node;
+	else
+		lastChild = node;
+
+	if ( replaceThis->prev )
+		replaceThis->prev->next = node;
+	else
+		firstChild = node;
+
+	delete replaceThis;
+	node->parent = this;
+	return node;
+}
+
+
+bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
+{
+	if ( !removeThis ) {
+		return false;
+	}
+
+	if ( removeThis->parent != this )
+	{	
+		assert( 0 );
+		return false;
+	}
+
+	if ( removeThis->next )
+		removeThis->next->prev = removeThis->prev;
+	else
+		lastChild = removeThis->prev;
+
+	if ( removeThis->prev )
+		removeThis->prev->next = removeThis->next;
+	else
+		firstChild = removeThis->next;
+
+	delete removeThis;
+	return true;
+}
+
+const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
+{
+	const TiXmlNode* node;
+	for ( node = firstChild; node; node = node->next )
+	{
+		if ( strcmp( node->Value(), _value ) == 0 )
+			return node;
+	}
+	return 0;
+}
+
+
+const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
+{
+	const TiXmlNode* node;
+	for ( node = lastChild; node; node = node->prev )
+	{
+		if ( strcmp( node->Value(), _value ) == 0 )
+			return node;
+	}
+	return 0;
+}
+
+
+const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
+{
+	if ( !previous )
+	{
+		return FirstChild();
+	}
+	else
+	{
+		assert( previous->parent == this );
+		return previous->NextSibling();
+	}
+}
+
+
+const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
+{
+	if ( !previous )
+	{
+		return FirstChild( val );
+	}
+	else
+	{
+		assert( previous->parent == this );
+		return previous->NextSibling( val );
+	}
+}
+
+
+const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const 
+{
+	const TiXmlNode* node;
+	for ( node = next; node; node = node->next )
+	{
+		if ( strcmp( node->Value(), _value ) == 0 )
+			return node;
+	}
+	return 0;
+}
+
+
+const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
+{
+	const TiXmlNode* node;
+	for ( node = prev; node; node = node->prev )
+	{
+		if ( strcmp( node->Value(), _value ) == 0 )
+			return node;
+	}
+	return 0;
+}
+
+
+void TiXmlElement::RemoveAttribute( const char * name )
+{
+    #ifdef TIXML_USE_STL
+	TIXML_STRING str( name );
+	TiXmlAttribute* node = attributeSet.Find( str );
+	#else
+	TiXmlAttribute* node = attributeSet.Find( name );
+	#endif
+	if ( node )
+	{
+		attributeSet.Remove( node );
+		delete node;
+	}
+}
+
+const TiXmlElement* TiXmlNode::FirstChildElement() const
+{
+	const TiXmlNode* node;
+
+	for (	node = FirstChild();
+			node;
+			node = node->NextSibling() )
+	{
+		if ( node->ToElement() )
+			return node->ToElement();
+	}
+	return 0;
+}
+
+
+const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
+{
+	const TiXmlNode* node;
+
+	for (	node = FirstChild( _value );
+			node;
+			node = node->NextSibling( _value ) )
+	{
+		if ( node->ToElement() )
+			return node->ToElement();
+	}
+	return 0;
+}
+
+
+const TiXmlElement* TiXmlNode::NextSiblingElement() const
+{
+	const TiXmlNode* node;
+
+	for (	node = NextSibling();
+			node;
+			node = node->NextSibling() )
+	{
+		if ( node->ToElement() )
+			return node->ToElement();
+	}
+	return 0;
+}
+
+
+const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
+{
+	const TiXmlNode* node;
+
+	for (	node = NextSibling( _value );
+			node;
+			node = node->NextSibling( _value ) )
+	{
+		if ( node->ToElement() )
+			return node->ToElement();
+	}
+	return 0;
+}
+
+
+const TiXmlDocument* TiXmlNode::GetDocument() const
+{
+	const TiXmlNode* node;
+
+	for( node = this; node; node = node->parent )
+	{
+		if ( node->ToDocument() )
+			return node->ToDocument();
+	}
+	return 0;
+}
+
+
+TiXmlElement::TiXmlElement (const char * _value)
+	: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
+{
+	firstChild = lastChild = 0;
+	value = _value;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlElement::TiXmlElement( const std::string& _value ) 
+	: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
+{
+	firstChild = lastChild = 0;
+	value = _value;
+}
+#endif
+
+
+TiXmlElement::TiXmlElement( const TiXmlElement& copy)
+	: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
+{
+	firstChild = lastChild = 0;
+	copy.CopyTo( this );	
+}
+
+
+TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base )
+{
+	ClearThis();
+	base.CopyTo( this );
+	return *this;
+}
+
+
+TiXmlElement::~TiXmlElement()
+{
+	ClearThis();
+}
+
+
+void TiXmlElement::ClearThis()
+{
+	Clear();
+	while( attributeSet.First() )
+	{
+		TiXmlAttribute* node = attributeSet.First();
+		attributeSet.Remove( node );
+		delete node;
+	}
+}
+
+
+const char* TiXmlElement::Attribute( const char* name ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( node )
+		return node->Value();
+	return 0;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	if ( attrib )
+		return &attrib->ValueStr();
+	return 0;
+}
+#endif
+
+
+const char* TiXmlElement::Attribute( const char* name, int* i ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	const char* result = 0;
+
+	if ( attrib ) {
+		result = attrib->Value();
+		if ( i ) {
+			attrib->QueryIntValue( i );
+		}
+	}
+	return result;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	const std::string* result = 0;
+
+	if ( attrib ) {
+		result = &attrib->ValueStr();
+		if ( i ) {
+			attrib->QueryIntValue( i );
+		}
+	}
+	return result;
+}
+#endif
+
+
+const char* TiXmlElement::Attribute( const char* name, double* d ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	const char* result = 0;
+
+	if ( attrib ) {
+		result = attrib->Value();
+		if ( d ) {
+			attrib->QueryDoubleValue( d );
+		}
+	}
+	return result;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	const std::string* result = 0;
+
+	if ( attrib ) {
+		result = &attrib->ValueStr();
+		if ( d ) {
+			attrib->QueryDoubleValue( d );
+		}
+	}
+	return result;
+}
+#endif
+
+
+int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	if ( !attrib )
+		return TIXML_NO_ATTRIBUTE;
+	return attrib->QueryIntValue( ival );
+}
+
+
+int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( !node )
+		return TIXML_NO_ATTRIBUTE;
+
+	int ival = 0;
+	int result = node->QueryIntValue( &ival );
+	*value = (unsigned)ival;
+	return result;
+}
+
+
+int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( !node )
+		return TIXML_NO_ATTRIBUTE;
+	
+	int result = TIXML_WRONG_TYPE;
+	if (    StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN ) 
+		 || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN ) 
+		 || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) ) 
+	{
+		*bval = true;
+		result = TIXML_SUCCESS;
+	}
+	else if (    StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN ) 
+			  || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN ) 
+			  || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) ) 
+	{
+		*bval = false;
+		result = TIXML_SUCCESS;
+	}
+	return result;
+}
+
+
+
+#ifdef TIXML_USE_STL
+int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	if ( !attrib )
+		return TIXML_NO_ATTRIBUTE;
+	return attrib->QueryIntValue( ival );
+}
+#endif
+
+
+int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	if ( !attrib )
+		return TIXML_NO_ATTRIBUTE;
+	return attrib->QueryDoubleValue( dval );
+}
+
+
+#ifdef TIXML_USE_STL
+int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
+{
+	const TiXmlAttribute* attrib = attributeSet.Find( name );
+	if ( !attrib )
+		return TIXML_NO_ATTRIBUTE;
+	return attrib->QueryDoubleValue( dval );
+}
+#endif
+
+
+void TiXmlElement::SetAttribute( const char * name, int val )
+{	
+	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
+	if ( attrib ) {
+		attrib->SetIntValue( val );
+	}
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& name, int val )
+{	
+	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
+	if ( attrib ) {
+		attrib->SetIntValue( val );
+	}
+}
+#endif
+
+
+void TiXmlElement::SetDoubleAttribute( const char * name, double val )
+{	
+	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
+	if ( attrib ) {
+		attrib->SetDoubleValue( val );
+	}
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetDoubleAttribute( const std::string& name, double val )
+{	
+	TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
+	if ( attrib ) {
+		attrib->SetDoubleValue( val );
+	}
+}
+#endif 
+
+
+void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
+{
+	TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname );
+	if ( attrib ) {
+		attrib->SetValue( cvalue );
+	}
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value )
+{
+	TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name );
+	if ( attrib ) {
+		attrib->SetValue( _value );
+	}
+}
+#endif
+
+
+void TiXmlElement::Print( FILE* cfile, int depth ) const
+{
+	int i;
+	assert( cfile );
+	for ( i=0; i<depth; i++ ) {
+		fprintf( cfile, "    " );
+	}
+
+	fprintf( cfile, "<%s", value.c_str() );
+
+	const TiXmlAttribute* attrib;
+	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
+	{
+		fprintf( cfile, " " );
+		attrib->Print( cfile, depth );
+	}
+
+	// There are 3 different formatting approaches:
+	// 1) An element without children is printed as a <foo /> node
+	// 2) An element with only a text child is printed as <foo> text </foo>
+	// 3) An element with children is printed on multiple lines.
+	TiXmlNode* node;
+	if ( !firstChild )
+	{
+		fprintf( cfile, " />" );
+	}
+	else if ( firstChild == lastChild && firstChild->ToText() )
+	{
+		fprintf( cfile, ">" );
+		firstChild->Print( cfile, depth + 1 );
+		fprintf( cfile, "</%s>", value.c_str() );
+	}
+	else
+	{
+		fprintf( cfile, ">" );
+
+		for ( node = firstChild; node; node=node->NextSibling() )
+		{
+			if ( !node->ToText() )
+			{
+				fprintf( cfile, "\n" );
+			}
+			node->Print( cfile, depth+1 );
+		}
+		fprintf( cfile, "\n" );
+		for( i=0; i<depth; ++i ) {
+			fprintf( cfile, "    " );
+		}
+		fprintf( cfile, "</%s>", value.c_str() );
+	}
+}
+
+
+void TiXmlElement::CopyTo( TiXmlElement* target ) const
+{
+	// superclass:
+	TiXmlNode::CopyTo( target );
+
+	// Element class: 
+	// Clone the attributes, then clone the children.
+	const TiXmlAttribute* attribute = 0;
+	for(	attribute = attributeSet.First();
+	attribute;
+	attribute = attribute->Next() )
+	{
+		target->SetAttribute( attribute->Name(), attribute->Value() );
+	}
+
+	TiXmlNode* node = 0;
+	for ( node = firstChild; node; node = node->NextSibling() )
+	{
+		target->LinkEndChild( node->Clone() );
+	}
+}
+
+bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
+{
+	if ( visitor->VisitEnter( *this, attributeSet.First() ) ) 
+	{
+		for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+		{
+			if ( !node->Accept( visitor ) )
+				break;
+		}
+	}
+	return visitor->VisitExit( *this );
+}
+
+
+TiXmlNode* TiXmlElement::Clone() const
+{
+	TiXmlElement* clone = new TiXmlElement( Value() );
+	if ( !clone )
+		return 0;
+
+	CopyTo( clone );
+	return clone;
+}
+
+
+const char* TiXmlElement::GetText() const
+{
+	const TiXmlNode* child = this->FirstChild();
+	if ( child ) {
+		const TiXmlText* childText = child->ToText();
+		if ( childText ) {
+			return childText->Value();
+		}
+	}
+	return 0;
+}
+
+
+TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
+{
+	tabsize = 4;
+	useMicrosoftBOM = false;
+	ClearError();
+}
+
+TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
+{
+	tabsize = 4;
+	useMicrosoftBOM = false;
+	value = documentName;
+	ClearError();
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
+{
+	tabsize = 4;
+	useMicrosoftBOM = false;
+    value = documentName;
+	ClearError();
+}
+#endif
+
+
+TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
+{
+	copy.CopyTo( this );
+}
+
+
+TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy )
+{
+	Clear();
+	copy.CopyTo( this );
+	return *this;
+}
+
+
+bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
+{
+	return LoadFile( Value(), encoding );
+}
+
+
+bool TiXmlDocument::SaveFile() const
+{
+	return SaveFile( Value() );
+}
+
+bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
+{
+	TIXML_STRING filename( _filename );
+	value = filename;
+
+	// reading in binary mode so that tinyxml can normalize the EOL
+	FILE* file = TiXmlFOpen( value.c_str (), "rb" );	
+
+	if ( file )
+	{
+		bool result = LoadFile( file, encoding );
+		fclose( file );
+		return result;
+	}
+	else
+	{
+		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return false;
+	}
+}
+
+bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
+{
+	if ( !file ) 
+	{
+		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return false;
+	}
+
+	// Delete the existing data:
+	Clear();
+	location.Clear();
+
+	// Get the file size, so we can pre-allocate the string. HUGE speed impact.
+	long length = 0;
+	fseek( file, 0, SEEK_END );
+	length = ftell( file );
+	fseek( file, 0, SEEK_SET );
+
+	// Strange case, but good to handle up front.
+	if ( length <= 0 )
+	{
+		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return false;
+	}
+
+	// Subtle bug here. TinyXml did use fgets. But from the XML spec:
+	// 2.11 End-of-Line Handling
+	// <snip>
+	// <quote>
+	// ...the XML processor MUST behave as if it normalized all line breaks in external 
+	// parsed entities (including the document entity) on input, before parsing, by translating 
+	// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to 
+	// a single #xA character.
+	// </quote>
+	//
+	// It is not clear fgets does that, and certainly isn't clear it works cross platform. 
+	// Generally, you expect fgets to translate from the convention of the OS to the c/unix
+	// convention, and not work generally.
+
+	/*
+	while( fgets( buf, sizeof(buf), file ) )
+	{
+		data += buf;
+	}
+	*/
+
+	char* buf = new char[ length+1 ];
+	buf[0] = 0;
+
+	if ( fread( buf, length, 1, file ) != 1 ) {
+		delete [] buf;
+		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return false;
+	}
+
+	// Process the buffer in place to normalize new lines. (See comment above.)
+	// Copies from the 'p' to 'q' pointer, where p can advance faster if
+	// a newline-carriage return is hit.
+	//
+	// Wikipedia:
+	// Systems based on ASCII or a compatible character set use either LF  (Line feed, '\n', 0x0A, 10 in decimal) or 
+	// CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)...
+	//		* LF:    Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others
+    //		* CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS
+    //		* CR:    Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9
+
+	const char* p = buf;	// the read head
+	char* q = buf;			// the write head
+	const char CR = 0x0d;
+	const char LF = 0x0a;
+
+	buf[length] = 0;
+	while( *p ) {
+		assert( p < (buf+length) );
+		assert( q <= (buf+length) );
+		assert( q <= p );
+
+		if ( *p == CR ) {
+			*q++ = LF;
+			p++;
+			if ( *p == LF ) {		// check for CR+LF (and skip LF)
+				p++;
+			}
+		}
+		else {
+			*q++ = *p++;
+		}
+	}
+	assert( q <= (buf+length) );
+	*q = 0;
+
+	Parse( buf, 0, encoding );
+
+	delete [] buf;
+	return !Error();
+}
+
+
+bool TiXmlDocument::SaveFile( const char * filename ) const
+{
+	// The old c stuff lives on...
+	FILE* fp = TiXmlFOpen( filename, "w" );
+	if ( fp )
+	{
+		bool result = SaveFile( fp );
+		fclose( fp );
+		return result;
+	}
+	return false;
+}
+
+
+bool TiXmlDocument::SaveFile( FILE* fp ) const
+{
+	if ( useMicrosoftBOM ) 
+	{
+		const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
+		const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
+		const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
+
+		fputc( TIXML_UTF_LEAD_0, fp );
+		fputc( TIXML_UTF_LEAD_1, fp );
+		fputc( TIXML_UTF_LEAD_2, fp );
+	}
+	Print( fp, 0 );
+	return (ferror(fp) == 0);
+}
+
+
+void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
+{
+	TiXmlNode::CopyTo( target );
+
+	target->error = error;
+	target->errorId = errorId;
+	target->errorDesc = errorDesc;
+	target->tabsize = tabsize;
+	target->errorLocation = errorLocation;
+	target->useMicrosoftBOM = useMicrosoftBOM;
+
+	TiXmlNode* node = 0;
+	for ( node = firstChild; node; node = node->NextSibling() )
+	{
+		target->LinkEndChild( node->Clone() );
+	}	
+}
+
+
+TiXmlNode* TiXmlDocument::Clone() const
+{
+	TiXmlDocument* clone = new TiXmlDocument();
+	if ( !clone )
+		return 0;
+
+	CopyTo( clone );
+	return clone;
+}
+
+
+void TiXmlDocument::Print( FILE* cfile, int depth ) const
+{
+	assert( cfile );
+	for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+	{
+		node->Print( cfile, depth );
+		fprintf( cfile, "\n" );
+	}
+}
+
+
+bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
+{
+	if ( visitor->VisitEnter( *this ) )
+	{
+		for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+		{
+			if ( !node->Accept( visitor ) )
+				break;
+		}
+	}
+	return visitor->VisitExit( *this );
+}
+
+
+const TiXmlAttribute* TiXmlAttribute::Next() const
+{
+	// We are using knowledge of the sentinel. The sentinel
+	// have a value or name.
+	if ( next->value.empty() && next->name.empty() )
+		return 0;
+	return next;
+}
+
+/*
+TiXmlAttribute* TiXmlAttribute::Next()
+{
+	// We are using knowledge of the sentinel. The sentinel
+	// have a value or name.
+	if ( next->value.empty() && next->name.empty() )
+		return 0;
+	return next;
+}
+*/
+
+const TiXmlAttribute* TiXmlAttribute::Previous() const
+{
+	// We are using knowledge of the sentinel. The sentinel
+	// have a value or name.
+	if ( prev->value.empty() && prev->name.empty() )
+		return 0;
+	return prev;
+}
+
+/*
+TiXmlAttribute* TiXmlAttribute::Previous()
+{
+	// We are using knowledge of the sentinel. The sentinel
+	// have a value or name.
+	if ( prev->value.empty() && prev->name.empty() )
+		return 0;
+	return prev;
+}
+*/
+
+void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
+{
+	TIXML_STRING n, v;
+
+	EncodeString( name, &n );
+	EncodeString( value, &v );
+
+	if (value.find ('\"') == TIXML_STRING::npos) {
+		if ( cfile ) {
+			fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
+		}
+		if ( str ) {
+			(*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
+		}
+	}
+	else {
+		if ( cfile ) {
+			fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
+		}
+		if ( str ) {
+			(*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
+		}
+	}
+}
+
+
+int TiXmlAttribute::QueryIntValue( int* ival ) const
+{
+	if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
+		return TIXML_SUCCESS;
+	return TIXML_WRONG_TYPE;
+}
+
+int TiXmlAttribute::QueryDoubleValue( double* dval ) const
+{
+	if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
+		return TIXML_SUCCESS;
+	return TIXML_WRONG_TYPE;
+}
+
+void TiXmlAttribute::SetIntValue( int _value )
+{
+	char buf [64];
+	#if defined(TIXML_SNPRINTF)		
+		TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
+	#else
+		sprintf (buf, "%d", _value);
+	#endif
+	SetValue (buf);
+}
+
+void TiXmlAttribute::SetDoubleValue( double _value )
+{
+	char buf [256];
+	#if defined(TIXML_SNPRINTF)		
+		TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value);
+	#else
+		sprintf (buf, "%g", _value);
+	#endif
+	SetValue (buf);
+}
+
+int TiXmlAttribute::IntValue() const
+{
+	return atoi (value.c_str ());
+}
+
+double  TiXmlAttribute::DoubleValue() const
+{
+	return atof (value.c_str ());
+}
+
+
+TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT )
+{
+	copy.CopyTo( this );
+}
+
+
+TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base )
+{
+	Clear();
+	base.CopyTo( this );
+	return *this;
+}
+
+
+void TiXmlComment::Print( FILE* cfile, int depth ) const
+{
+	assert( cfile );
+	for ( int i=0; i<depth; i++ )
+	{
+		fprintf( cfile,  "    " );
+	}
+	fprintf( cfile, "<!--%s-->", value.c_str() );
+}
+
+
+void TiXmlComment::CopyTo( TiXmlComment* target ) const
+{
+	TiXmlNode::CopyTo( target );
+}
+
+
+bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
+{
+	return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlComment::Clone() const
+{
+	TiXmlComment* clone = new TiXmlComment();
+
+	if ( !clone )
+		return 0;
+
+	CopyTo( clone );
+	return clone;
+}
+
+
+void TiXmlText::Print( FILE* cfile, int depth ) const
+{
+	assert( cfile );
+	if ( cdata )
+	{
+		int i;
+		fprintf( cfile, "\n" );
+		for ( i=0; i<depth; i++ ) {
+			fprintf( cfile, "    " );
+		}
+		fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() );	// unformatted output
+	}
+	else
+	{
+		TIXML_STRING buffer;
+		EncodeString( value, &buffer );
+		fprintf( cfile, "%s", buffer.c_str() );
+	}
+}
+
+
+void TiXmlText::CopyTo( TiXmlText* target ) const
+{
+	TiXmlNode::CopyTo( target );
+	target->cdata = cdata;
+}
+
+
+bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
+{
+	return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlText::Clone() const
+{	
+	TiXmlText* clone = 0;
+	clone = new TiXmlText( "" );
+
+	if ( !clone )
+		return 0;
+
+	CopyTo( clone );
+	return clone;
+}
+
+
+TiXmlDeclaration::TiXmlDeclaration( const char * _version,
+									const char * _encoding,
+									const char * _standalone )
+	: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
+{
+	version = _version;
+	encoding = _encoding;
+	standalone = _standalone;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlDeclaration::TiXmlDeclaration(	const std::string& _version,
+									const std::string& _encoding,
+									const std::string& _standalone )
+	: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
+{
+	version = _version;
+	encoding = _encoding;
+	standalone = _standalone;
+}
+#endif
+
+
+TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
+	: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
+{
+	copy.CopyTo( this );	
+}
+
+
+TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
+{
+	Clear();
+	copy.CopyTo( this );
+	return *this;
+}
+
+
+void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
+{
+	if ( cfile ) fprintf( cfile, "<?xml " );
+	if ( str )	 (*str) += "<?xml ";
+
+	if ( !version.empty() ) {
+		if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
+		if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
+	}
+	if ( !encoding.empty() ) {
+		if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
+		if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
+	}
+	if ( !standalone.empty() ) {
+		if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
+		if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
+	}
+	if ( cfile ) fprintf( cfile, "?>" );
+	if ( str )	 (*str) += "?>";
+}
+
+
+void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
+{
+	TiXmlNode::CopyTo( target );
+
+	target->version = version;
+	target->encoding = encoding;
+	target->standalone = standalone;
+}
+
+
+bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
+{
+	return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlDeclaration::Clone() const
+{	
+	TiXmlDeclaration* clone = new TiXmlDeclaration();
+
+	if ( !clone )
+		return 0;
+
+	CopyTo( clone );
+	return clone;
+}
+
+
+void TiXmlUnknown::Print( FILE* cfile, int depth ) const
+{
+	for ( int i=0; i<depth; i++ )
+		fprintf( cfile, "    " );
+	fprintf( cfile, "<%s>", value.c_str() );
+}
+
+
+void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
+{
+	TiXmlNode::CopyTo( target );
+}
+
+
+bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
+{
+	return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlUnknown::Clone() const
+{
+	TiXmlUnknown* clone = new TiXmlUnknown();
+
+	if ( !clone )
+		return 0;
+
+	CopyTo( clone );
+	return clone;
+}
+
+
+TiXmlAttributeSet::TiXmlAttributeSet()
+{
+	sentinel.next = &sentinel;
+	sentinel.prev = &sentinel;
+}
+
+
+TiXmlAttributeSet::~TiXmlAttributeSet()
+{
+	assert( sentinel.next == &sentinel );
+	assert( sentinel.prev == &sentinel );
+}
+
+
+void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
+{
+    #ifdef TIXML_USE_STL
+	assert( !Find( TIXML_STRING( addMe->Name() ) ) );	// Shouldn't be multiply adding to the set.
+	#else
+	assert( !Find( addMe->Name() ) );	// Shouldn't be multiply adding to the set.
+	#endif
+
+	addMe->next = &sentinel;
+	addMe->prev = sentinel.prev;
+
+	sentinel.prev->next = addMe;
+	sentinel.prev      = addMe;
+}
+
+void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
+{
+	TiXmlAttribute* node;
+
+	for( node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( node == removeMe )
+		{
+			node->prev->next = node->next;
+			node->next->prev = node->prev;
+			node->next = 0;
+			node->prev = 0;
+			return;
+		}
+	}
+	assert( 0 );		// we tried to remove a non-linked attribute.
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
+{
+	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( node->name == name )
+			return node;
+	}
+	return 0;
+}
+
+TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name )
+{
+	TiXmlAttribute* attrib = Find( _name );
+	if ( !attrib ) {
+		attrib = new TiXmlAttribute();
+		Add( attrib );
+		attrib->SetName( _name );
+	}
+	return attrib;
+}
+#endif
+
+
+TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
+{
+	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( strcmp( node->name.c_str(), name ) == 0 )
+			return node;
+	}
+	return 0;
+}
+
+
+TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name )
+{
+	TiXmlAttribute* attrib = Find( _name );
+	if ( !attrib ) {
+		attrib = new TiXmlAttribute();
+		Add( attrib );
+		attrib->SetName( _name );
+	}
+	return attrib;
+}
+
+
+#ifdef TIXML_USE_STL	
+std::istream& operator>> (std::istream & in, TiXmlNode & base)
+{
+	TIXML_STRING tag;
+	tag.reserve( 8 * 1000 );
+	base.StreamIn( &in, &tag );
+
+	base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
+	return in;
+}
+#endif
+
+
+#ifdef TIXML_USE_STL	
+std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
+{
+	TiXmlPrinter printer;
+	printer.SetStreamPrinting();
+	base.Accept( &printer );
+	out << printer.Str();
+
+	return out;
+}
+
+
+std::string& operator<< (std::string& out, const TiXmlNode& base )
+{
+	TiXmlPrinter printer;
+	printer.SetStreamPrinting();
+	base.Accept( &printer );
+	out.append( printer.Str() );
+
+	return out;
+}
+#endif
+
+
+TiXmlHandle TiXmlHandle::FirstChild() const
+{
+	if ( node )
+	{
+		TiXmlNode* child = node->FirstChild();
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
+{
+	if ( node )
+	{
+		TiXmlNode* child = node->FirstChild( value );
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChildElement() const
+{
+	if ( node )
+	{
+		TiXmlElement* child = node->FirstChildElement();
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
+{
+	if ( node )
+	{
+		TiXmlElement* child = node->FirstChildElement( value );
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::Child( int count ) const
+{
+	if ( node )
+	{
+		int i;
+		TiXmlNode* child = node->FirstChild();
+		for (	i=0;
+				child && i<count;
+				child = child->NextSibling(), ++i )
+		{
+			// nothing
+		}
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
+{
+	if ( node )
+	{
+		int i;
+		TiXmlNode* child = node->FirstChild( value );
+		for (	i=0;
+				child && i<count;
+				child = child->NextSibling( value ), ++i )
+		{
+			// nothing
+		}
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::ChildElement( int count ) const
+{
+	if ( node )
+	{
+		int i;
+		TiXmlElement* child = node->FirstChildElement();
+		for (	i=0;
+				child && i<count;
+				child = child->NextSiblingElement(), ++i )
+		{
+			// nothing
+		}
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
+{
+	if ( node )
+	{
+		int i;
+		TiXmlElement* child = node->FirstChildElement( value );
+		for (	i=0;
+				child && i<count;
+				child = child->NextSiblingElement( value ), ++i )
+		{
+			// nothing
+		}
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
+{
+	return true;
+}
+
+bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
+{
+	return true;
+}
+
+bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
+{
+	DoIndent();
+	buffer += "<";
+	buffer += element.Value();
+
+	for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
+	{
+		buffer += " ";
+		attrib->Print( 0, 0, &buffer );
+	}
+
+	if ( !element.FirstChild() ) 
+	{
+		buffer += " />";
+		DoLineBreak();
+	}
+	else 
+	{
+		buffer += ">";
+		if (    element.FirstChild()->ToText()
+			  && element.LastChild() == element.FirstChild()
+			  && element.FirstChild()->ToText()->CDATA() == false )
+		{
+			simpleTextPrint = true;
+			// no DoLineBreak()!
+		}
+		else
+		{
+			DoLineBreak();
+		}
+	}
+	++depth;	
+	return true;
+}
+
+
+bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
+{
+	--depth;
+	if ( !element.FirstChild() ) 
+	{
+		// nothing.
+	}
+	else 
+	{
+		if ( simpleTextPrint )
+		{
+			simpleTextPrint = false;
+		}
+		else
+		{
+			DoIndent();
+		}
+		buffer += "</";
+		buffer += element.Value();
+		buffer += ">";
+		DoLineBreak();
+	}
+	return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlText& text )
+{
+	if ( text.CDATA() )
+	{
+		DoIndent();
+		buffer += "<![CDATA[";
+		buffer += text.Value();
+		buffer += "]]>";
+		DoLineBreak();
+	}
+	else if ( simpleTextPrint )
+	{
+		TIXML_STRING str;
+		TiXmlBase::EncodeString( text.ValueTStr(), &str );
+		buffer += str;
+	}
+	else
+	{
+		DoIndent();
+		TIXML_STRING str;
+		TiXmlBase::EncodeString( text.ValueTStr(), &str );
+		buffer += str;
+		DoLineBreak();
+	}
+	return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
+{
+	DoIndent();
+	declaration.Print( 0, 0, &buffer );
+	DoLineBreak();
+	return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlComment& comment )
+{
+	DoIndent();
+	buffer += "<!--";
+	buffer += comment.Value();
+	buffer += "-->";
+	DoLineBreak();
+	return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
+{
+	DoIndent();
+	buffer += "<";
+	buffer += unknown.Value();
+	buffer += ">";
+	DoLineBreak();
+	return true;
+}
+
Index: branches/FEPSimulator/network.h
===================================================================
--- branches/fep_rpc_client/network.h	(revision 77)
+++ branches/FEPSimulator/network.h	(revision 80)
@@ -11,4 +11,5 @@
 const int Fixed_Byte_To_Checksum = 25; // the first byte is not considered in the calculation of "BYTE 2"
 const int CONTROL_DATA_LEN = 27;
+
 char * const dp5[8] = { "ML_1", "ML_2", "ML_3", "ML_4", "ML_5",
                                                 "ML_6", "HOV_Lane", "FYW_Conn"};
@@ -20,32 +21,15 @@
                                                 "SD_6", "Pass_Vol_Count", "X"};
 
-/*** NETWORK STRUCTS ***/
-typedef struct loopagg LOOPAGG;
-struct loopagg
-{
-	int		index;
-	char	lane;			// how namy lanes at the detector station
-	long	time;
-	int		interval;
-	int 	g_vol;
-	float	g_occ;
-	double	g_spd;
-	int		*vol;
-	float	*occ;
-	double	*spd;
-};
-
 // FEP line: has several lds
 typedef struct fep_line FEP_LINE;
 struct  fep_line
 {
-	int		lineNum;
-	vector<long> lds;
-	vector<long> ldsIndex;	// location in ldsMap
-	short	ldsNum;			// actual number of lds on the line
+	int             lineNum;
+	vector<long>    lds;
+	vector<long>    ldsIndex;	// location in ldsMap
 
-	short	count;	// actual count from caltrans
-	int		schedule;
-	int		lineInfo;
+	short   count;	// actual count from caltrans
+	int	schedule;
+	int	lineInfo;
 	long	systemKey;
 	long	globalSeq;
@@ -53,7 +37,19 @@
 };
 
+// Loop detector
+typedef struct loop LOOP;
+struct loop
+{
+    long loopID;
+    char *loop_loc;
+    
+    int vol;
+    float occ;
+    double spd;
+};
+
 // Loop detector station: has several loops
-typedef struct Lds_loop LDS_LOOP;
-struct  Lds_loop
+typedef struct Station STATION;
+struct  Station
 {
 	// Each lds has its own line_num and drop (Caltrans use)
@@ -61,8 +57,6 @@
 	short	line_num;
 	short	drop;
-
-	int		num;	// number of loops
-	long	*loopID;
-	char	**loop_loc;
+        
+        vector<LOOP*> loops;
 
 	// LDS data
@@ -74,3 +68,11 @@
 };
 
+typedef struct volOcc VOLOCC;
+struct  volOcc
+{
+   char high;
+   char low;
+};
+
+
 #endif
Index: branches/FEPSimulator/DataPacker.cpp
===================================================================
--- branches/FEPSimulator/DataPacker.cpp	(revision 80)
+++ branches/FEPSimulator/DataPacker.cpp	(revision 80)
@@ -0,0 +1,266 @@
+#include "DataPacker.h";
+
+unsigned char * DataPacker::msg;
+
+unsigned char * DataPacker::packData(STATION *station) {
+    int pos = 26;
+    DataPacker packer;
+    msg = packer.staticDataPack(station);
+    pos = packer.dynamicDataPack(station, 5, pos);    
+    pos = packer.dynamicDataPack(station, 6, pos);
+    pos = packer.dynamicDataPack(station, 7, pos);
+    pos = packer.dynamicDataPack(station, 8, pos);
+    // Update data for BYTE 9, 16, 21, 22, 23, 24
+
+    // what is the current metering rate?
+    // check each LDS, if there is demand detector, the downstream node the
+    // ldsMap[i].dataPack[22-1] = ldsMap[i].dataPack[9-1] = ;
+
+    // will need to check if queue override is enabled (Currently, no queue
+    // ldsMap[i].dataPack[16-1] = ;
+
+    // byte 23: MAINLINE total volume
+    msg[23 - 1] = station->MlTotVol;
+
+    // byte 24: opposite total volume
+    msg[24 - 1] = station->OppTotVol;
+
+    // last BYTE: checksum 
+    msg[station->length - 1] =
+            packer.chksum(msg, station->length - 1 - 1);
+    
+    /*
+    for (int j = 0; j < station->length; j++) {
+        printf("%02X", msg[j]);
+    }
+    printf("\n");
+    */
+}
+
+int DataPacker::dynamicDataPack(STATION *station, int packNo, int pos) {
+    int i, j, vol, occ, haveData;
+    //used for data byte 23 and 24
+    station->MlTotVol = 0;
+    station->OppTotVol = 0;
+
+    for (j = 1; j <= 8; j++) {
+        
+        if (DataAvail(msg[packNo - 1], j)) {
+            // loop at bit j has data
+            for (int lane = 0; lane < station->loops.size(); lane++) {
+                // what's the corresponding loop of bit j
+                char * currLoopLoc = station->loops.at(lane)->loop_loc;
+                if (packNo == 5)
+                    haveData = strcmp(currLoopLoc, dp5[j - 1]);
+                else if (packNo == 6)
+                    haveData = strcmp(currLoopLoc, dp6[j - 1]);
+                else if (packNo == 7)
+                    haveData = strcmp(currLoopLoc, dp7[j - 1]);
+                else if (packNo == 8)
+                    haveData = strcmp(currLoopLoc, dp8[j - 1]);
+                else
+                    return -1;
+
+                if (haveData == 0) {
+                    LOOP *currLoop = station->loops.at(lane);
+                    vol = currLoop->vol;
+                    occ = (int) (currLoop->occ * 900 + 0.5);
+
+                    VOLOCC packedVOLOCC = packVOLOCC(vol, occ);
+                    pos++;
+                    msg[pos - 1] = packedVOLOCC.high;
+                    pos++;
+                    msg[pos - 1] = packedVOLOCC.low;
+
+                    if (packNo == 5) {
+                        station->MlTotVol += vol;
+                    } else if (packNo == 6) {
+                        station->OppTotVol += vol;
+                    }
+                }
+            }
+        }
+    }
+    return pos;
+}
+
+unsigned char * DataPacker::staticDataPack(STATION *station) {
+    int j;
+    // Allocate memory for dataPack
+    unsigned char *dataPack = (unsigned char *) calloc(sizeof(unsigned char), station->length);
+
+    // dataPack 5-8: lane config
+    char d5 = 0, d6 = 0, d7 = 0, d8 = 0;
+    for (j = 0; j < station->loops.size(); j++) {
+        for (int k = 0; k < 8; k++) {
+            char * currLoopLoc = station->loops.at(j)->loop_loc;
+            if (strcmp(currLoopLoc, dp5[k]) == 0)
+                d5 += pow(2, k);
+            if (strcmp(currLoopLoc, dp6[k]) == 0)
+                d6 += pow(2, k);
+            if (strcmp(currLoopLoc, dp7[k]) == 0)
+                d7 += pow(2, k);
+            if (strcmp(currLoopLoc, dp8[k]) == 0)
+                d8 += pow(2, k);
+        }
+    }
+    dataPack[5 - 1] = d5;
+    dataPack[6 - 1] = d6;
+    dataPack[7 - 1] = d7;
+    dataPack[8 - 1] = d8;
+
+    // dataPack 1: Drop number, i.e. station address
+    dataPack[1 - 1] = station->drop;
+    // dataPack2 (2 bytes per loop)
+    dataPack[2 - 1] = station->loops.size() * 2 + Fixed_Byte_To_Checksum;
+
+    // dataPacket 3 (lowbyte: # of mainline loops, highbyte: # of opposite loops)
+    int low = 0, high = 0;
+    for (j = 1; j <= 6; j++) {
+        low += DataAvail(dataPack[5 - 1], j);
+        high += DataAvail(dataPack[6 - 1], j);
+    }
+    high = high << 4;
+    dataPack[3 - 1] = high | low;
+
+    // dataPack4 (Miscl. flags: samples are: 80, A0, E0, 00)
+    dataPack[4 - 1] = 0xA0;
+
+    // dataPack 9: initialized as 00 (meaning no metering); need to be updated every 30 sec
+    dataPack[9 - 1] = 0;
+
+    // datadataPack 10-13: lane malfunction? Assuming all functional
+    dataPack[10 - 1] = 0;
+    dataPack[11 - 1] = 0;
+    dataPack[12 - 1] = 0;
+    dataPack[13 - 1] = 0;
+
+    // dataPack 14-22: ramp metering data
+    // BYTE 16 and 22 need to be updated every 30 sec
+    bool found = false;
+    for (j = 0; j < station->loops.size(); j++) {
+        if (strcmp(station->loops.at(j)->loop_loc, "DEMAND") == 0) {
+            found = true;
+            break;
+        }
+    }
+    if (found) {
+        // BYTE 14: mostly 07, some are 05, 03, 00
+        dataPack[14 - 1] = 0x07;
+        // mostly 06(TOD table 1); some are 0B (No metering) or 05(traffic responsive)
+        dataPack[15 - 1] = 0x06;
+        // most 00, some are 01 (queue override) or 80(Meter ON sign)
+        dataPack[16 - 1] = 0x00;
+        // Field Manual Rate
+        dataPack[17 - 1] = 0xFF;
+        // TOC Manual Rate
+        dataPack[18 - 1] = 0xFF;
+        // PSO Manual Rate
+        dataPack[19 - 1] = 0xFF;
+        // CORM Rate
+        dataPack[20 - 1] = 0xFF;
+        // Local Responsive Rate. DON'T UNDERSTAND YET
+        dataPack[21 - 1] = 0x00;
+        // TOD Rate: need to query RAMP plugin!
+        dataPack[22 - 1] = 0x00;
+    }// LDS: NO Metering
+    else {
+        dataPack[14 - 1] = 0x00;
+        dataPack[15 - 1] = 0x0B;
+        dataPack[16 - 1] = 0x00;
+        dataPack[17 - 1] = 0xFF;
+        dataPack[18 - 1] = 0xFF;
+        dataPack[19 - 1] = 0xFF;
+        dataPack[20 - 1] = 0xFF;
+        dataPack[21 - 1] = 0x00;
+        dataPack[22 - 1] = 0x00;
+    }
+
+    // dataPack 23-24: sum of mainline/Opp traffic data; need to be updated every 30 sec
+    station->MlTotVol = 0;
+    station->OppTotVol = 0;
+    dataPack[23 - 1] = station->MlTotVol;
+    dataPack[24 - 1] = station->OppTotVol;
+
+    // dataPack 25-26: BYTE 25 is fixed, i.e. 03; BYTE 26 is either 0xA2 or 0x84
+    dataPack[25 - 1] = 0x03;
+    dataPack[26 - 1] = 0x84;
+
+    return dataPack;
+}
+
+bool DataPacker::DataAvail(char flag, int num) {
+    int mag, fel;
+
+    // find mask value
+    if (num == 1)
+        mag = 0x01;
+    else if (num == 2)
+        mag = 0x02;
+    else if (num == 3)
+        mag = 0x04;
+    else if (num == 4)
+        mag = 0x08;
+    else if (num == 5)
+        mag = 0x10;
+    else if (num == 6)
+        mag = 0x20;
+    else if (num == 7)
+        mag = 0x40;
+    else if (num == 8)
+        mag = 0x80;
+
+    fel = flag & mag;
+    fel = fel >> (num - 1);
+
+    if (fel == 1)
+        return true;
+    else
+        return false;
+}
+
+// checksum based on data from byte 1 (after 0DOA) to the second last byte (the 
+char DataPacker::chksum(unsigned char *dataptr, int len) {
+    int i;
+    unsigned char checksum = 0;
+
+    for (i = 0; i < len; i++)
+        checksum += dataptr[i];
+
+    return checksum;
+}
+
+// convert vol and occ data to a two-byte data packet
+VOLOCC DataPacker::packVOLOCC(int vol, int occ)
+{
+   int bit, i;
+   int   high, low; 
+   int high_high = 0, high_low = 0;
+   VOLOCC com;
+   
+   // occ data: 10 bits
+   low = 0;
+   for (i=9; i>=0; i--) 
+   {
+      if (i >= 8)
+      {
+         bit = ((occ >> i) & 1);
+         high_low += pow(2, (i - 8)) * bit; 
+      }
+      // lower byte
+      else
+      {
+         bit = ((occ >> i) & 1);
+         low += pow(2, i) * bit;
+      }
+   }
+
+   // vol: 6 bits (1. vol, shift to the left for two times; 2. combine data)
+   high_high = vol << 2;
+   high = high_high | high_low;
+
+   com.high = high;
+   com.low = low;
+
+   return com;
+}
