Index: vtcross/branches/wrodgers/src/cognitive_engines/cbr.c
===================================================================
--- vtcross/branches/wrodgers/src/cognitive_engines/cbr.c	(revision 230)
+++ vtcross/branches/wrodgers/src/cognitive_engines/cbr.c	(revision 230)
@@ -0,0 +1,311 @@
+//
+// Case-based reasoner
+//
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "vtcross/cbr.h"
+#include "vtcross/common.h"
+
+
+struct cbr_s {
+    char filename[64];
+    char tablename[64];
+    char command[2048];
+    sqlite3 *db; 
+    unsigned int num_columns;
+};
+
+
+// open a database or create a database if it does not exist
+int OpenDatabase(cbr _cbr){
+    int rc;
+    //sqlite3 **db;
+
+    //printf("database name: %s\n", _cbr->filename);
+    //rc = sqlite3_open(_cbr->filename, db);
+    rc = sqlite3_open(_cbr->filename, &(_cbr->db));
+    if (rc) {
+        //fprintf(stderr, "can't open database: %s\n", sqlite3_errmsg(*db));
+        fprintf(stderr, "can't open database: %s\n", sqlite3_errmsg(_cbr->db));
+        sqlite3_close(_cbr->db);
+        exit(1);
+    } else{
+        //printf("database opened.\n");
+    }
+    //_cbr->db = *db;
+    return rc;
+}
+
+
+// simple callback function, display result
+int callback(void *notUsed, int argc, char **argv, char **azColName){
+    int i;
+    for(i=0; i<argc; i++){
+        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
+    }
+    printf("\n");
+    return 0;
+}
+
+
+// execute command
+int ExecuteCommand(cbr _cbr){
+    int rc;
+    char *zErrMsg = 0;
+
+    //printf("command: %s\n", _cbr->command);
+    rc = sqlite3_exec(_cbr->db, _cbr->command, callback, 0, &zErrMsg);
+    if( rc!=SQLITE_OK){
+        fprintf(stderr, "SQL error: %s: %s\n", zErrMsg,_cbr->command);
+        sqlite3_free(zErrMsg);
+    } else{
+        //printf("command executed.\n");
+    }
+    return rc;
+}
+
+
+// execute search command
+int ExecuteSearchCommand(cbr _cbr, float *_retvals){
+    int rc;
+    unsigned int i;
+
+    sqlite3_stmt * pStatement;
+    rc = sqlite3_prepare_v2(_cbr->db, _cbr->command, -1, &pStatement, NULL);
+    if (rc == SQLITE_OK){ 
+        if (sqlite3_step(pStatement) == SQLITE_ROW){
+            for (i=0; i<_cbr->num_columns; ++i)
+                _retvals[i] = sqlite3_column_double(pStatement, i);
+        } else {
+		    printf("CBR:: No matched results returning default.\n");
+			rc=31337;
+		}
+    } else {
+		printf("CBR:: Error executing SQL statement. rc = %i\n%s\n",rc,_cbr->command);
+    }
+
+    sqlite3_finalize(pStatement);
+   
+    return rc;
+}
+
+
+// create database
+cbr cbr_create(char * _filename, char * _tablename, char * _cols[], unsigned int _len)
+{
+    // cbr is a pointer to struct cbr_s
+    cbr _cbr = (cbr) malloc(sizeof(struct cbr_s));
+
+    // create database
+
+    // copy filename
+    unsigned int i=0;
+    strcpy(_cbr->filename, _filename);
+
+    // execute create database command
+    // database handle
+    //_cbr->db = NULL;
+    OpenDatabase(_cbr);
+
+    // create table
+
+    // copy tablename
+    strcpy(_cbr->tablename, _tablename);
+
+    // number of columns in the table
+    _cbr->num_columns = _len;
+
+    // generate command
+    strcpy(_cbr->command, "CREATE TABLE ");
+    strcat(_cbr->command, _cbr->tablename);
+    strcat(_cbr->command, "(");
+    for (i=0; i<_cbr->num_columns; i++) {
+        strcat(_cbr->command, _cols[i]);
+        strcat(_cbr->command, " FLOAT");
+        if (i != _cbr->num_columns-1) // not last entry
+            strcat(_cbr->command, ", ");
+    }
+    strcat(_cbr->command, ");");
+
+    // execute create table command
+    ExecuteCommand(_cbr);
+
+    return _cbr;
+}
+
+
+// free space
+void cbr_free(cbr _cbr)
+{  
+    // generate command, remove a table with its content
+    strcpy(_cbr->command, "drop table ");
+    strcat(_cbr->command, _cbr->tablename);
+
+    // execute delete command
+    ExecuteCommand(_cbr);
+
+    // clean the database
+    strcpy(_cbr->command, "vacuum");
+    ExecuteCommand(_cbr);
+
+    free(_cbr);
+}
+
+
+// print 
+void cbr_print(cbr _cbr)
+{
+    // generate commandi
+    strcpy(_cbr->command, "select ");
+    strcat(_cbr->command, _cbr->tablename);
+    strcat(_cbr->command, ".* from ");
+    strcat(_cbr->command, _cbr->tablename);
+    strcat(_cbr->command, ";");
+
+    // execute print (select all)  command
+    ExecuteCommand(_cbr);
+    printf("database %s, table %s:\n", _cbr->filename, _cbr->tablename);
+}
+
+
+/*//static
+int cbr_callback(void *notUsed, int argc, char **argv, char **azColName)
+{
+    return 0;
+}*/
+
+
+const char * ops_str[] = {
+    "==", "!=", ">", ">=", "<", "<="};
+
+
+// cbr search
+int cbr_search(
+    cbr _cbr,
+    char *_names[],
+    int * _ops,
+    float *_vals,
+    unsigned int _n,
+    float *_retvals)
+{   
+    int rc;
+    // generate command
+    strcpy(_cbr->command, "select ");
+    strcat(_cbr->command, _cbr->tablename);
+    strcat(_cbr->command, ".* from ");
+    strcat(_cbr->command, _cbr->tablename);
+    strcat(_cbr->command, " where ");
+
+    unsigned int i;
+    char str_buffer[64];
+    //printf("number of ops %d:\n", _n);
+    for (i=0; i<_n; i++) {
+        // ensure valid ops value
+        if (_ops[i] < 0 || _ops[i] > 5) {
+            printf("error: cbr_search(), invalid ops id : %d\n", _ops[i]);
+            exit(1);
+        }
+
+        strcat(_cbr->command, _names[i]);
+        strcat(_cbr->command, ops_str[_ops[i]]);
+        sprintf(str_buffer, "%E", _vals[i]);
+        strcat(_cbr->command, str_buffer);
+
+
+        if (i<_n-1)
+            strcat(_cbr->command, " AND ");
+        else
+            strcat(_cbr->command, " order by utility desc;");
+    }
+
+    //printf("search command: %s\n", _cbr->command);
+
+    //ExecuteCommand(_cbr);
+    rc = ExecuteSearchCommand(_cbr, _retvals);
+    
+    /*printf("search result: ");
+    for (i=0; i<_cbr->num_columns; i++)
+        printf("%f, ",_retvals[i]);
+    printf("\n");*/
+
+    return rc;
+}
+
+
+// update a row 
+int cbr_update(cbr _cbr, char *_where[], char*_set[], float *_wherevals, float *_setvals, 
+		unsigned int _wherelen, unsigned int _setlen)
+{
+    unsigned int i;
+    
+    // generate command
+    //printf("%s\n", _cbr->command);
+    strcpy(_cbr->command, "UPDATE ");
+    strcat(_cbr->command, _cbr->tablename);
+    
+    strcat(_cbr->command, " SET ");
+    for (i=0; i<_setlen; i++) {
+        strcat(_cbr->command, _set[i]);
+        strcat(_cbr->command, " = ");
+        sprintf(_cbr->command, "%s%f", _cbr->command, _setvals[i]);
+        strcat(_cbr->command, "  ");
+        if (i != _setlen-1) // not last entry
+            strcat(_cbr->command, ", ");
+    }
+    strcat(_cbr->command, " WHERE ");
+
+    for (i=0; i<_wherelen; i++) {
+        strcat(_cbr->command, _where[i]);
+        strcat(_cbr->command, " = ");
+        sprintf(_cbr->command, "%s%f", _cbr->command, _wherevals[i]);
+        strcat(_cbr->command, "  ");
+        if (i != _wherelen-1) // not last entry
+            strcat(_cbr->command, "AND ");
+    }
+    strcat(_cbr->command, ";");
+    
+    //printf("search command: %s\n", _cbr->command);
+    // execute add command
+    ExecuteCommand(_cbr);
+
+    return 0;
+}
+
+// cbr add a row
+int cbr_add_row(cbr _cbr, char *_cols[], float *_vals, unsigned int _len)
+{
+    unsigned int i;
+    
+    // generate command
+    //printf("%s\n", _cbr->command);
+    strcpy(_cbr->command, "insert into ");
+    strcat(_cbr->command, _cbr->tablename);
+    
+    strcat(_cbr->command, " (");
+    for (i=0; i<_len; i++) {
+        strcat(_cbr->command, _cols[i]);
+        if (i != _cbr->num_columns-1) // not last entry
+            strcat(_cbr->command, ", ");
+    }
+    strcat(_cbr->command, ") ");
+
+    strcat(_cbr->command, " values(");
+    for (i=0; i<_len; i++) {
+        // ???? how to fill the values if _cbr->num_columns != _len
+        // assume = in the following
+        sprintf(_cbr->command, "%s%f", _cbr->command, _vals[i]);
+        if (i != _cbr->num_columns-1) // not last entry
+            strcat(_cbr->command, ", ");
+    }
+    strcat(_cbr->command, ");");
+    
+    //printf("search command: %s\n", _cbr->command);
+    // execute add command
+    ExecuteCommand(_cbr);
+
+    return 0;
+}
+
Index: vtcross/branches/wrodgers/src/cognitive_engines/Makefile.am
===================================================================
--- vtcross/branches/wrodgers/src/cognitive_engines/Makefile.am	(revision 218)
+++ vtcross/branches/wrodgers/src/cognitive_engines/Makefile.am	(revision 218)
@@ -0,0 +1,9 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+AM_CXXFLAGS = -Wall -g
+
+bin_PROGRAMS = cbr_demo
+
+cbr_demo_SOURCES = CognitiveEngine.cpp cbr_demo.cpp
+cbr_demo_LDADD = -lsqlite3 ../lib/socketcomm/libsocketcomm.a
+
Index: vtcross/branches/wrodgers/src/cognitive_engines/cbr_demo.c
===================================================================
--- vtcross/branches/wrodgers/src/cognitive_engines/cbr_demo.c	(revision 218)
+++ vtcross/branches/wrodgers/src/cognitive_engines/cbr_demo.c	(revision 218)
@@ -0,0 +1,593 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+//#include <iostream>
+#include <stdlib.h>
+#include <string.h>
+#include <sqlite3.h>
+#include <sqlite3ext.h>
+
+#include "vtcross/cbr.h"
+#include "vtcross/common.h"
+
+//using namespace std;
+
+struct CE_Info {
+    int numUtilities;
+    int numParameters;
+    int numObservables;
+};
+
+struct Utility {
+    char name[50];
+    char units[50];
+    char goal[50];
+   /* string name;
+    string units;
+    string goal;*/
+    float target;
+    float value;
+};
+
+struct Affect {
+    struct Utility u; 
+    //string relation;
+    char relation[50];
+};      
+
+struct Parameter {
+    /*string name;
+    string units;*/
+    char name[50];
+    char units[50];
+    float min;
+    int numAffects; 
+    struct Affect affection_list[10];
+    float max;
+    float step;
+    float value;
+};      
+        
+struct Observable {
+    //string name;
+    char name[50];
+    struct Affect affection_list[10];
+    int numAffects;
+    float value;
+};
+
+// error handling
+void error(char *msg)
+{
+    perror(msg);
+    exit(0);
+}
+
+void ReadMessage(int socket,char * buffer) {
+    int i,n;
+
+    n = recv(socket,buffer,256,MSG_PEEK);
+    for(i=0;i<256;i++){
+	    if(strcmp(&buffer[i],"\0") == 0) break;
+    }
+    n = recv(socket,buffer,i+1,0);
+    if (n < 0) 
+         error("ERROR reading from socket");
+    //printf("ReadMessage:%s %d\n",buffer,n);
+}
+
+
+int GetUtility(int sockfd, struct Utility uList[], struct CE_Info *ce_info)
+{
+    char buffer[256];
+    int i;
+
+    // read unitilities
+    // numUtilities
+    bzero(buffer,256);
+    ReadMessage(sockfd,buffer);
+    ce_info->numUtilities = atoi(buffer);
+    //printf("number of utilities: %d\n", ce_info->numUtilities);
+        
+    for (i = 0; i < ce_info->numUtilities; i++){
+        bzero(buffer,256);
+	    ReadMessage(sockfd,buffer);
+	    //printf("Name: %s\n", buffer);
+        strcpy(uList[i].name, buffer);
+                 
+        bzero(buffer,256);
+	    ReadMessage(sockfd,buffer);
+	    //printf("Units: %s\n", buffer);
+        strcpy(uList[i].units, buffer);
+
+        bzero(buffer,256);
+	    ReadMessage(sockfd,buffer);
+        //printf("Goal: %s\n", buffer);
+        strcpy(uList[i].goal, buffer);
+        
+	    bzero(buffer,256);
+	    ReadMessage(sockfd,buffer);
+        //printf("Target: %s\n", buffer);
+        uList[i].target = atof(buffer);
+    }
+    return 1;
+}
+
+
+int GetParameter(int sockfd, struct Parameter pList[], struct CE_Info *ce_info)
+{
+    char buffer[256];
+    int i, j;
+
+    // numParameters
+    bzero(buffer,256);
+    ReadMessage(sockfd,buffer);
+    ce_info->numParameters = atoi(buffer);
+    //printf("number of parameters: %d\n", ce_info->numParameters);
+        
+    for (i = 0; i < ce_info->numParameters; i++){
+        bzero(buffer,256);
+	    ReadMessage(sockfd,buffer);
+	    //printf("Name: %s\n", buffer);
+        strcpy(pList[i].name, buffer);
+                 
+        bzero(buffer,256);
+	    ReadMessage(sockfd,buffer);
+	    //printf("Units: %s\n", buffer);
+        strcpy(pList[i].units, buffer);
+
+        bzero(buffer,256);
+	    ReadMessage(sockfd,buffer);
+        //printf("Min: %s\n", buffer);
+        pList[i].min = atof(buffer);
+        
+        bzero(buffer,256);
+	    ReadMessage(sockfd,buffer);
+        //printf("Max: %s\n", buffer);
+        pList[i].max = atof(buffer);
+        
+	    bzero(buffer,256);
+	    ReadMessage(sockfd,buffer);
+        //printf("Step: %s\n", buffer);
+        pList[i].step = atof(buffer);
+    
+        // numAffects
+        bzero(buffer,256);
+        ReadMessage(sockfd,buffer);
+        pList[i].numAffects = atoi(buffer);
+        //printf("number of affects: %d\n", pList[i].numAffects);
+        
+        for (j = 0; j < pList[i].numAffects; j++){
+            bzero(buffer,256);
+	        ReadMessage(sockfd,buffer);
+	        //printf("Utility name: %s\n", buffer);
+            strcpy(pList[i].affection_list[j].u.name, buffer);
+                 
+            bzero(buffer,256);
+	        ReadMessage(sockfd,buffer);
+	        //printf("Relation: %s\n", buffer);
+            strcpy(pList[i].affection_list[j].relation, buffer);
+        }
+    }
+    return 1;
+}
+
+
+int GetObservable(int sockfd, struct Observable oList[], struct CE_Info *ce_info)
+{
+    char buffer[256];
+    int i,j;
+
+    // numParameters
+    bzero(buffer,256);
+    ReadMessage(sockfd,buffer);
+    ce_info->numObservables = atoi(buffer);
+    //printf("number of observables: %d\n", ce_info->numObservables);
+        
+    for (i = 0; i < ce_info->numObservables; i++){
+        bzero(buffer,256);
+	    ReadMessage(sockfd,buffer);
+	    //printf("Name: %s\n", buffer);
+        strcpy(oList[i].name, buffer);
+                 
+        // numAffects
+        bzero(buffer,256);
+        ReadMessage(sockfd,buffer);
+        oList[i].numAffects = atoi(buffer);
+        //printf("number of affects: %d\n", oList[i].numAffects);
+        
+        for (j = 0; j < oList[i].numAffects; j++){
+            bzero(buffer,256);
+	        ReadMessage(sockfd,buffer);
+	        //printf("Utility name: %s\n", buffer);
+            strcpy(oList[i].affection_list[j].u.name, buffer);
+                 
+            bzero(buffer,256);
+	        ReadMessage(sockfd,buffer);
+	        //printf("Relation: %s\n", buffer);
+            strcpy(oList[i].affection_list[j].relation, buffer);
+        }
+    }
+    return 1;
+}
+
+
+// setup client socket connection
+int ClientSocket(int argc, char** argv)
+{
+    int sockfd;
+    int portno;
+    struct sockaddr_in serv_addr;
+    struct hostent *server;
+    
+    // setup client socket connection
+    if (argc < 3) {
+       fprintf(stderr,"usage: %s hostname port\n", argv[0]);
+       exit(0);
+    }
+    // server name
+    server = gethostbyname(argv[1]);
+    if (server == NULL) {
+        fprintf(stderr,"ERROR, no such host\n");
+        exit(0);
+    }
+    // port no.
+    portno = atoi(argv[2]);
+    // socket file descriptor
+    sockfd = socket(AF_INET, SOCK_STREAM, 0);
+    if (sockfd < 0) 
+        error("ERROR opening socket");
+    // initiate struct socketaddr_in
+    bzero((char *) &serv_addr, sizeof(serv_addr));
+    serv_addr.sin_family = AF_INET;
+    serv_addr.sin_port = htons(portno);
+    bcopy((char *)server->h_addr, 
+         (char *)&serv_addr.sin_addr.s_addr,
+         server->h_length);
+    // cast sockaddr_in to sockaddr
+    if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) 
+        error("ERROR connecting");
+
+    return sockfd;
+}
+
+    
+int SendMessage(int socketfd, char *message) 
+{
+    int n;
+     
+    strcat(message, "\0000");
+    // Write message back to client
+    //n = write(socketfd,message,(strlen(message)+1));
+    n = send(socketfd,message,(strlen(message)+1),0);
+    if (n<0)
+        error("Error sending to server\n");
+    else if(n == 0)
+        printf("Server closed the socket.\n");
+    
+    return n;
+}
+
+
+int GetXMLFromServer(int sockfd, struct Utility uList[], struct Parameter pList[], 
+        struct Observable oList[], struct CE_Info *ce_info)
+{
+    // get utilities
+    GetUtility(sockfd, uList, ce_info);
+    
+    // get parameters
+    GetParameter(sockfd, pList, ce_info);
+
+    // read obervables
+    GetObservable(sockfd, oList, ce_info);
+
+    // send ack back to server
+    char buffer[256];
+    strcpy(buffer, "xml received");
+    SendMessage(sockfd, buffer);
+    //printf("xml reception done\n");
+    
+    return 1;
+}
+
+
+int GetExperienceSize(int sockfd, int *num_rows, int *num_cols)
+{
+    char buffer[256];
+    
+    // number of rows
+    bzero(buffer,256);
+    ReadMessage(sockfd,buffer);
+    *num_rows = atoi(buffer);
+    // number of columns
+    bzero(buffer,256);
+    ReadMessage(sockfd,buffer);
+    *num_cols = atoi(buffer);
+    return 1;
+}
+
+int GetRequest(int sockfd)
+{
+    char buffer[256];
+
+	bzero(buffer,256);
+	ReadMessage(sockfd,buffer);
+
+    return 1;
+}
+
+int GetExperience(int sockfd, int num_rows, int num_cols, 
+        //float **past_exp)
+        float past_exp[num_rows][num_cols])
+{
+    char buffer[256];
+    int i, j;
+
+    // read experience
+    for (i = 0; i < num_rows; i++){
+        for (j = 0; j < num_cols; j++){
+	    bzero(buffer,256);
+	    ReadMessage(sockfd,buffer);
+    //    printf("experience: %s\n", buffer);
+        past_exp[i][j] = atof(buffer);
+        }
+    }
+
+    return 1;
+}
+
+
+void print_current_config(struct Utility uList[], 
+        struct Parameter pList[], 
+        struct Observable oList[], 
+        struct CE_Info * ce_info) 
+{    
+    int i = 0;
+    int j = 0;
+
+    // utilities
+    for(i = 0; i < ce_info->numUtilities ; i++) {
+        printf("Utility: %s\n", uList[i].name);
+        printf("    Units: %s\n", uList[i].units);
+        printf("    Goal: %s\n", uList[i].goal);
+        printf("    Target: %f\n", uList[i].target);
+        /*cout << "Utility:  " << uList[i].name << endl;
+        cout << "     Units:  " << uList[i].units << endl;
+        cout << "     Goal:   " << uList[i].goal << endl;
+        cout << "     Target: " << uList[i].target << endl;*/
+    }
+                       
+    // parameters                        
+    for(i = 0; i < ce_info->numParameters; i++) {
+        printf("Paramter: %s\n", pList[i].name);
+        printf("    Units: %s\n", pList[i].units);
+        printf("    Min: %f\n", pList[i].min);
+        printf("    Max: %f\n", pList[i].max);
+        printf("    Step: %f\n", pList[i].step);
+        /*cout << "Parameter:  " << pList[i].name << endl;
+        cout << "       Units:   " << pList[i].units << endl;
+        cout << "       Min:     " << pList[i].min << endl;
+        cout << "       Max:     " << pList[i].max << endl;
+        cout << "       Step:    " << pList[i].step << endl;*/
+        for(j = 0; j < pList[i].numAffects; j++) {
+            printf("        Affect: %s -> %s\n", pList[i].affection_list[j].u.name, pList[i].affection_list[j].relation);
+            //cout << "       Affect: " << pList[i].affection_list[j].u.name << " -> " << pList[i].affection_list[j].relation << endl;
+        }
+    }
+
+    // observables
+    for(i = 0; i < ce_info->numObservables; i++) {
+        printf("Observable: %s\n", oList[i].name);
+        //cout << "Observable:  " << oList[i].name << endl;
+        for(j = 0; j < oList[i].numAffects; j++) {
+            printf("        Affect: %s -> %s\n", oList[i].affection_list[j].u.name, oList[i].affection_list[j].relation);
+            //cout << "       Affect: " << oList[i].affection_list[j].u.name << " -> " << oList[i].affection_list[j].relation << endl;
+        }
+    }
+}
+
+int RunCBREngine(struct Utility uList[], struct Parameter pList[],
+        struct Observable oList[], struct CE_Info *ce_info, 
+        //int num_cols, int num_rows, float ** past_exp)
+        int num_cols, int num_rows, float past_exp[num_rows][num_cols])
+{
+    
+    int i, j;
+
+    // get column names
+    /*char *cols[50] = {"throughput", "spectral_efficiency", 
+    "log10_ber", "mod_scheme", "tx_power", "SNR", "utility"};*/
+    //char cols[num_cols][50];
+   
+
+    char **cols;
+    cols = (char **)malloc(sizeof(char)*num_cols);
+    j = 0;
+    for (i = 0; i < ce_info->numUtilities; i++){
+        cols[j] = malloc(strlen(uList[i].name)+1);
+        cols[j] = uList[i].name;
+    //    strcpy(cols[j], uList[i].name);
+        j++;
+    }
+    for (i = 0; i < ce_info->numParameters; i++){
+        cols[j] = malloc(strlen(pList[i].name)+1);
+        cols[j] = pList[i].name;
+    //    strcpy(cols[j], pList[i].name);
+        j++;
+    }
+    for (i = 0; i < ce_info->numObservables; i++){
+        cols[j] = malloc(strlen(oList[i].name)+1);
+        cols[j] = oList[i].name;
+    //    strcpy(cols[j], oList[i].name);
+        j++;
+    }
+    cols[j] = malloc(strlen("utility")+1);
+    cols[j] = "utility";
+    
+    //printf("column names:");
+    //for (i = 0; i<num_cols; i++){
+    //    printf(" %s",cols[i]);
+    //}
+    //printf("\n");
+
+    int rc;
+
+    // create cbr database/table
+    //printf("create cbr database\n");
+    char filename[] = {"ex1"}, tablename[] = {"data"};
+    cbr mycbr = cbr_create(filename, tablename, cols, num_cols);
+    //cbr mycbr = cbr_create("ex1", "data", cols, num_cols);
+
+    // add row here
+    float vals[num_cols];
+    /*// sample table entry
+    vals[0] = 1e3f;    // throughput
+    vals[1] = 1;        // spectral_efficiency
+    vals[2] = -3.50;    // log10_ber
+    vals[3] = 1;        // mod_scheme
+    vals[4] = -3.5f;    // tx_power
+    vals[5] = 10.0f;   // SNR
+    vals[6] = 0.762;    // utility*/
+    for (i = 0; i < num_rows; i++){
+        for (j = 0; j < num_cols; j++){
+            vals[j] = past_exp[i][j];
+        }
+        rc = cbr_add_row(mycbr, cols, vals, num_cols);
+    }
+    
+    // print
+    printf("cbr table\n");
+    cbr_print(mycbr);
+    
+    // simple search: find entry where...
+    //   log10_ber < 1e-2 and SNR > 5
+    //char * search_names[] = {"log10_ber", "SNR"};
+    char ** search_names;
+    search_names
+        = (char **)malloc(sizeof(char)*(ce_info->numUtilities));
+    for (i = 0; i < ce_info->numUtilities; i++){
+        search_names[i] 
+            = malloc(sizeof(char)*(strlen(uList[i].name)+1));
+        search_names[i] = uList[i].name;
+    }
+    int search_ops[] = {GT, GT, LT};
+    //float search_vals[] = {1e-2f, 5.f};
+    float *search_vals;
+    search_vals = malloc(sizeof(float)*(ce_info->numUtilities));
+    for (i = 0; i < ce_info->numUtilities; i++){
+        search_vals[i] = uList[i].target;
+    }
+    float retvals[num_cols];
+    rc = cbr_search(mycbr, search_names, search_ops, 
+            search_vals, ce_info->numUtilities, retvals);
+
+    j = 0;
+    for (i = 0; i < ce_info->numUtilities; i++){
+        uList[i].value = retvals[j];
+        j++;
+    }
+    for (i = 0; i < ce_info->numParameters; i++){
+        pList[i].value = retvals[j];
+        j++;
+    }
+    for (i = 0; i < ce_info->numObservables; i++){
+        oList[i].value = retvals[j];
+        j++;
+    }
+
+    // clean up database
+    //printf("clean cbr database\n");
+    cbr_free(mycbr);
+    
+    return 1;
+}
+
+
+int SendCEResults(int sockfd, struct Utility uList[], struct Parameter pList[], 
+        struct Observable oList[], struct CE_Info *ce_info)
+{
+    // send results back to server
+    char var[50];
+    int i;
+ 
+    /*// utility
+    for (i = 0; i < ce_info->numUtilities; i++){
+        sprintf(var, "%f", uList[i].value);
+        SendMessage(sockfd, var);
+    }*/
+    
+    // parameter
+    for (i = 0; i < ce_info->numParameters; i++){
+        sprintf(var, "%f", pList[i].value);
+        SendMessage(sockfd, var);
+    }
+    
+    /*// observable
+    for (i = 0; i < ce_info->numObservables; i++){
+        sprintf(var, "%f", oList[i].value);
+        SendMessage(sockfd, var);
+    }*/
+
+    return 1;
+}
+
+int RegisterCE(int sockfd, struct Utility uList[], struct Parameter pList[], 
+        struct Observable oList[], struct CE_Info *ce_info)
+{
+    // Send register message to cognitive radio
+    SendMessage(sockfd, "register_engine_cognitive");
+    return 1;
+}
+
+// main client socket
+int main(int argc, char *argv[])
+{
+    struct Utility uList[10];
+    struct Parameter pList[10];
+    struct Observable oList[10];
+    struct CE_Info ce_info;
+    char buffer[256];
+
+    // setup client socket connection
+    int sockfd;
+    sockfd = ClientSocket(argc, argv);
+
+    RegisterCE(sockfd,uList,pList,oList,&ce_info);
+    // get xml info from server
+    GetXMLFromServer(sockfd, uList, pList, oList, &ce_info);
+    printf("Received Radio Operation Profile from Server Successfully.\n\n");
+    //print_current_config(uList, pList, oList, &ce_info); 
+    
+    // get experience size from server
+    int num_rows, num_cols;
+    GetExperienceSize(sockfd, &num_rows, &num_cols);
+
+    // get experience
+    int i, j;
+    float past_exp[num_rows][num_cols];
+    GetExperience(sockfd, num_rows, num_cols, past_exp);
+    printf("Received Previous Radio Experience from Server Successfully.\n\n");
+    // cbr operation
+    //unsigned int num_cols;
+    // get number of columns
+    num_cols = ce_info.numUtilities + ce_info.numParameters;
+    num_cols = num_cols + ce_info.numObservables;
+    num_cols = num_cols + 1;    // overall utility
+    //while(1) {
+        
+        // Wait until request is received from server to perform optimization 
+        //printf("Waiting for Request for optimization from Server\n\n");
+        //GetRequest(sockfd);
+        //printf("Received optimization request from server\n\n");
+        RunCBREngine(uList, pList, oList, &ce_info, num_cols, num_rows, past_exp);    
+   
+        printf("Sending optimization results to server.\n\n");
+        // send results back to server
+        SendCEResults(sockfd, uList, pList, oList, &ce_info);
+        
+    //}
+    
+    return 0;
+}
Index: vtcross/branches/wrodgers/src/cognitive_engines/cbr_demo.cpp
===================================================================
--- vtcross/branches/wrodgers/src/cognitive_engines/cbr_demo.cpp	(revision 222)
+++ vtcross/branches/wrodgers/src/cognitive_engines/cbr_demo.cpp	(revision 222)
@@ -0,0 +1,42 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * TODO LICENSE INFORMATION GOES HERE
+ */
+
+/* TODO DESCRIPTION OF FILE.
+ *
+ * This file is a temporary demo of a policy engine using some of our socket
+ * communication functions. This is *not* an actual implementation of our
+ * defined PolicyEngine class.
+ */
+
+
+#include <cstdlib>
+#include <cstring>
+#include <stdint.h>
+
+#include "vtcross/common.h"
+#include "vtcross/components.h"
+#include "vtcross/containers.h"
+#include "vtcross/debug.h"
+#include "vtcross/error.h"
+#include "vtcross/socketcomm.h"
+
+
+int32_t 
+main(int32_t argc, char *argv[])
+{
+    if(argc < 3)
+       ERROR(1, "Usage: %s hostname port\n", argv[0]);
+    
+    CognitiveEngine cognitiveEngine(argv[1], argv[2], false);
+
+    LOG("Waiting for signal...\n");
+    while(1) {
+        cognitiveEngine.WaitForSignal();
+    }
+
+    return 0;
+}
+
Index: vtcross/branches/wrodgers/src/cognitive_engines/CognitiveEngine.cpp
===================================================================
--- vtcross/branches/wrodgers/src/cognitive_engines/CognitiveEngine.cpp	(revision 275)
+++ vtcross/branches/wrodgers/src/cognitive_engines/CognitiveEngine.cpp	(revision 275)
@@ -0,0 +1,710 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * LICENSE INFORMATION GOES HERE
+ */
+
+/* DESCRIPTION OF FILE.
+ */
+
+
+#include <cstdlib>
+#include <cstring>
+#include <stdint.h>
+#include <math.h>
+
+#include "vtcross/common.h"
+#include "vtcross/components.h"
+#include "vtcross/containers.h"
+#include "vtcross/debug.h"
+#include "vtcross/error.h"
+#include "vtcross/socketcomm.h"
+#include "vtcross/cbr.h"
+
+// TODO this is really bad; need to move to a proper cbr.h
+#include "cbr.c"
+
+#include "sqlite3.h"
+#include "sqlite3ext.h"
+
+
+static cbr myCBR;
+
+
+CognitiveEngine::CognitiveEngine()
+{
+    LOG("Creating Cognitive Engine.\n");
+    SML_present = false;
+    commandSocketFD = -1;
+}
+
+
+CognitiveEngine::~CognitiveEngine()
+{
+    cbr_free(myCBR);
+    delete [] pList;
+    delete [] oList;
+    delete [] uList;
+    delete [] radioInfo;
+}
+
+
+CognitiveEngine::CognitiveEngine(const char *serverName, const char *serverPort, \
+        const bool SML)
+{
+    LOG("Creating Cognitive Engine.\n");
+
+    pList = new Parameter[10];
+    oList = new Observable[10];
+    uList = new Utility[10];
+    radioInfo = new Radio_Info;
+
+    ConnectToRemoteComponent(serverName, serverPort, SML);
+}
+
+
+void
+CognitiveEngine::SendComponentType()
+{
+    SendMessage(commandSocketFD, "response_engine_cognitive");
+    LOG("Cognitive Engine responded to GetRemoteComponentType query.\n");
+}
+
+
+void
+CognitiveEngine::ConnectToRemoteComponent(const char *serverName, \
+        const char *serverPort, const bool SML)
+{
+    commandSocketFD = ClientSocket(serverName, serverPort);
+
+    SML_present = SML;
+
+    if(SML) {
+        RegisterServices();
+        RegisterComponent();
+        LOG("Cognitive Engine connected to SML at %s.\n", serverName);
+        ReceiveRadioConfiguration();
+        ReceiveExperience();
+    }
+    else {
+        RegisterComponent();
+        LOG("Cognitive Engine connected to shell at %s.\n", serverName);
+        ReceiveRadioConfiguration();
+        ReceiveExperience();
+    }
+}
+
+void 
+CognitiveEngine::ReceiveFeedback(Observable *observables, Parameter *parameters)
+{ 
+   LOG("Cognitive Engine:: Receiving feedback.\n");
+    
+    uint32_t numberColumns = 
+        radioInfo->numParameters +
+        radioInfo->numUtilities;
+
+    uint32_t obsColumns = radioInfo->numObservables + 1;
+
+    float valList[numberColumns];
+    float obsVals[numberColumns];
+    char *nameList[numberColumns];
+    char *obsList[obsColumns];
+
+    size_t columnObsIndex = 0;
+    for (size_t i = 0; i < radioInfo->numObservables; i++){
+        obsList[columnObsIndex] = (char*)observables[i].name.c_str();
+        columnObsIndex++;
+    }  
+    obsList[columnObsIndex] = "utility";
+
+    size_t columnIndex = 0;
+    for (size_t i = 0; i < radioInfo->numParameters; i++){
+        nameList[columnIndex] = (char*)parameters[i].name.c_str();
+        columnIndex++;
+    }   
+    for (size_t i = 0; i < radioInfo->numUtilities; i++){
+        nameList[columnIndex] = (char*)uList[i].name.c_str();
+        columnIndex++;
+    }   
+
+    size_t obsValueIndex = 0;
+    for(size_t i = 0; i < radioInfo->numObservables; i++) {
+        obsVals[obsValueIndex] = observables[i].value;
+        obsValueIndex++;
+    }
+
+    /* Calculate Utility */
+    float newUtilityValue = 0;
+
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        newUtilityValue = newUtilityValue + (uList[i].target - observables[i].value);
+    }
+    obsVals[obsValueIndex] = newUtilityValue;
+
+    size_t returnValueIndex = 0;
+    for(size_t i = 0; i < radioInfo->numParameters; i++) {
+        valList[returnValueIndex] = parameters[i].value;
+        returnValueIndex++;
+    }
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        valList[returnValueIndex] = uList[i].target;
+        returnValueIndex++;
+    }
+
+    cbr_update(myCBR, nameList, obsList, valList, obsVals, 
+            numberColumns, obsColumns);
+}
+
+
+void 
+CognitiveEngine::WaitForSignal()
+{
+    char buffer[256];
+
+    while(true) {
+        memset(buffer, 0, 256);
+       
+        ReadMessage(commandSocketFD, buffer);
+
+        // TODO this is ugly... is there a better way? Doesn't strcmp compare the
+        // whole string?  We only need to compare until we find a single different
+        // byte...
+        //
+        // If we send integer op codes rather than strings, this process will be
+        // MUCH faster since instead of donig string compares we can simply
+        // switch on the integer value...
+        if(strcmp(buffer, "update_performance") == 0) {
+            
+            /* Receive Set of current Parameters */
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD, buffer);
+            uint32_t numParameters = atoi(buffer);
+   
+            Parameter *p = new Parameter[numParameters];
+ 
+            for(size_t i = 0; i < numParameters; i++) {
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                p[i].name = std::string(buffer);
+    
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                p[i].value = atof(buffer);
+            } 
+
+            /* Receive Set of Observables */
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD, buffer);
+            uint32_t numObservables = atoi(buffer);
+   
+            Observable *o = new Observable[numObservables];
+ 
+            for(size_t i = 0; i < numObservables; i++) {
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                o[i].name = std::string(buffer);
+    
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                o[i].value = atof(buffer);
+            }  
+
+            ReceiveFeedback(o,p);
+
+            delete [] o;
+            delete [] p;
+        } 
+        else if(strcmp(buffer, "request_optimization") == 0) {
+            
+            /* Receive Set of Observables */
+            LOG("\nCognitive Engine:: Receiving Observable Parameters\n");
+
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD,buffer);
+            uint32_t numObservables = atoi(buffer);
+   
+            Observable *o = new Observable[numObservables];
+ 
+            for(size_t i = 0; i < numObservables; i++) {
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                o[i].name = std::string(buffer);
+    
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                o[i].value = atof(buffer);
+            }  
+
+            /* Receive Set of current Parameters */
+            LOG("Cognitive Engine:: Receiving Current Transmission Parameters\n");
+
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD, buffer);
+            uint32_t numCurrentParameters = atoi(buffer);
+   
+            Parameter *cp = new Parameter[numCurrentParameters];
+ 
+            for(size_t i = 0; i < numCurrentParameters; i++) {
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                cp[i].name = std::string(buffer);
+    
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                cp[i].value = atof(buffer);
+            }  
+            LOG("Cognitive Engine:: Processing parameters....\n");
+
+            Parameter *solutionSet;
+            
+            solutionSet = GetSolution(o,cp);
+
+            // TODO need to actually do something with the observables here
+           
+            LOG("Cognitive Engine:: Sending Optimal Parameters to Application.\n");
+            char numParametersChar[10];
+            char solutionValue[50];
+            sprintf(numParametersChar, "%i", radioInfo->numParameters);
+            SendMessage(commandSocketFD, numParametersChar);
+            for(size_t i = 0; i < radioInfo->numParameters; i++) {
+                SendMessage(commandSocketFD, solutionSet[i].name.c_str());
+                memset(solutionValue, 0, 50);
+                sprintf(solutionValue, "%f", solutionSet[i].value);
+                SendMessage(commandSocketFD, solutionValue);
+            }
+
+            delete [] o;
+            delete [] cp;
+        }
+        else if(strcmp(buffer, "query_component_type") == 0) {
+            SendComponentType();
+        }
+        else if(strcmp(buffer, "connect_sml") == 0) {
+            /* This command implies that we are disconnecting from the shell and
+             * connecting to a SML component. */
+            char serverName[256];
+            char serverPort[256];
+            // TODO is this going to end up being too slow?
+            memset(serverName, 0, 256);
+            memset(serverPort, 0, 256);
+
+            ReadMessage(commandSocketFD, serverName);
+            ReadMessage(commandSocketFD, serverPort);
+
+            /* Only continue if we are currently connected to a shell. */
+            if(!SML_present) {
+                DeregisterComponent();
+
+                shutdown(commandSocketFD, 2);
+                close(commandSocketFD);
+
+                ConnectToRemoteComponent(serverName, serverPort, true);
+            }
+        }
+        else if(strcmp(buffer, "disconnect_sml") == 0) {
+            /* This command implies that we are disconnecting from the SML and
+             * connecting to a shell component. */
+            char serverName[256];
+            char serverPort[256];
+            // TODO is this going to end up being too slow?
+            memset(serverName, 0, 256);
+            memset(serverPort, 0, 256);
+
+            ReadMessage(commandSocketFD, serverName);
+            ReadMessage(commandSocketFD, serverPort);
+
+            /* We only want to do this if we are actually connected to an SML
+             * currently. */
+            if(SML_present) {
+                DeregisterServices();
+
+                shutdown(commandSocketFD, 2);
+                close(commandSocketFD);
+
+                ConnectToRemoteComponent(serverName, serverPort, false);
+            }
+        }
+        else if(strcmp(buffer, "reset_engine_cognitive") == 0) {
+            Reset();
+        }
+        else if(strcmp(buffer, "shutdown_engine_cognitive") == 0) {
+            Shutdown();
+        }
+    }
+}
+
+
+void 
+CognitiveEngine::Shutdown()
+{
+    if(SML_present) {
+        //DeregisterServices();
+        DeregisterComponent();
+    } 
+    else {
+        DeregisterComponent();
+    }
+    // TODO should something else be happening here?
+}
+
+
+void
+CognitiveEngine::Reset()
+{
+    LOG("Resetting Cognitive Engine.\n");
+
+    if(SML_present) {
+        DeregisterServices();
+        DeregisterComponent();
+    } 
+    else {
+        DeregisterComponent();
+    }
+}
+
+        RegisterServices();
+
+void
+CognitiveEngine::RegisterComponent()
+{
+    SendMessage(commandSocketFD, "register_engine_cognitive");
+    LOG("Cognitive Engine:: Registration message sent to shell.\n");
+}
+
+void 
+CognitiveEngine::DeregisterComponent()
+{
+    SendMessage(commandSocketFD, "deregister_engine_cognitive");
+    LOG("Cognitive Engine:: Deregistration message sent.\n");
+
+    shutdown(commandSocketFD, 2);
+    close(commandSocketFD);
+    commandSocketFD = -1;
+    LOG("Cognitive Engine:: Shell socket closed.\n");
+}
+
+
+void 
+CognitiveEngine::RegisterServices()
+{
+    LOG("Cognitive Engine:: Registering services.\n");
+
+    SendMessage(commandSocketFD, "register_service");
+    SendMessage(commandSocketFD, "jam_wifi");
+
+    SendMessage(commandSocketFD, "register_service");
+    SendMessage(commandSocketFD, "signal_detection");
+
+    SendMessage(commandSocketFD, "register_service");
+    SendMessage(commandSocketFD, "max_throughput");
+
+    SendMessage(commandSocketFD, "register_service");
+    SendMessage(commandSocketFD, "jam_bluetooth");
+}
+
+//Combined with deregister component since those two things must happen togeather
+/*void 
+CognitiveEngine::DeregisterServices()
+{
+    LOG("Cognitive Engine:: Deregistering services.\n");
+
+    SendMessage(commandSocketFD, "deregister_service");
+    SendMessage(commandSocketFD, "jam_wifi");
+
+    SendMessage(commandSocketFD, "deregister_service");
+    SendMessage(commandSocketFD, "signal_detection");
+
+    SendMessage(commandSocketFD, "deregister_service");
+    SendMessage(commandSocketFD, "max_throughput");
+
+    SendMessage(commandSocketFD, "deregister_service");
+    SendMessage(commandSocketFD, "jam_bluetooth");
+
+}*/
+
+void 
+CognitiveEngine::ReceiveRadioConfiguration()
+{
+    LOG("Cognitive Engine:: Receiving Radio Configuration.\n");
+    
+    char buffer[256];
+ 
+    /* Receive Set of Utilities */
+    memset(buffer, 0, 256);
+    ReadMessage(commandSocketFD, buffer);
+    radioInfo->numUtilities = atoi(buffer);
+    
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        uList[i].name = std::string(buffer);
+   
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        uList[i].units = std::string(buffer);
+
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        uList[i].goal = std::string(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        uList[i].target = atof(buffer);
+    }
+
+    /* Receive Set of Parameters */
+    memset(buffer, 0, 256);
+    ReadMessage(commandSocketFD, buffer);
+    radioInfo->numParameters = atoi(buffer);
+    
+    for(size_t i = 0; i < radioInfo->numParameters; i++) {
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        pList[i].name = std::string(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        pList[i].units = std::string(buffer);
+
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        pList[i].min = atof(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        pList[i].max = atof(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        pList[i].step = atof(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD,buffer);
+        pList[i].numAffects = atoi(buffer);
+    
+        for(size_t j = 0; j < pList[i].numAffects; j++) {
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD,buffer);
+            // TODO for + if{break} = while?
+            for(size_t k = 0; k < radioInfo->numUtilities; k++) {
+                if(uList[k].name == std::string(buffer)) {    
+                    pList[i].affection_list[j].u = &uList[k];   
+                    break;
+                }
+            }
+
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD, buffer);
+            pList[i].affection_list[j].relation = std::string(buffer);   
+        }
+    }   
+
+    /* Receive Set of Observables */
+    memset(buffer, 0, 256);
+    ReadMessage(commandSocketFD, buffer);
+    radioInfo->numObservables = atoi(buffer);
+    
+    for(size_t i = 0; i < radioInfo->numObservables; i++) {
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        oList[i].name = std::string(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        oList[i].numAffects = atoi(buffer);
+    
+        for(size_t j = 0; j < oList[i].numAffects; j++) {
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD, buffer);
+            // TODO for + if{break} = while?
+            for(size_t k = 0; k < radioInfo->numUtilities; k++) {
+                if(uList[k].name == std::string(buffer)){    
+                    oList[i].affection_list[j].u = &uList[k];   
+                    break;
+                }
+            }
+ 
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD, buffer);
+            oList[i].affection_list[j].relation = std::string(buffer);   
+        }
+    }
+
+    SendMessage(commandSocketFD, "receive_config_ack");
+
+    BuildCognitiveEngine();
+}
+
+void 
+CognitiveEngine::ReceiveExperience()
+{
+    LOG("Cognitive Engine:: Receiving Experience Report.\n");
+    char buffer[256];
+    uint32_t numberExp;
+    
+    /* Receive number of experience entries */
+    memset(buffer, 0, 256);
+    ReadMessage(commandSocketFD, buffer);
+    numberExp = atoi(buffer);
+
+    LOG("Cognitive Engine:: Waiting for %i number of entries.\n", numberExp);
+ 
+    SendMessage(commandSocketFD, "receive_exp_ack");
+}
+
+Parameter* 
+CognitiveEngine::GetSolution(Observable *observables, Parameter *currentParameters)
+{
+    LOG("Cognitive Engine:: Generating solution.\n");
+
+    char *searchNames[radioInfo->numUtilities];
+
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        searchNames[i] = (char*)observables[i].name.c_str();
+    }
+
+    float searchVals[radioInfo->numUtilities];
+
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        searchVals[i] = uList[i].target;
+    }
+
+    uint32_t numberColumns = 
+        radioInfo->numUtilities +
+        radioInfo->numParameters +
+        radioInfo->numObservables + 1;
+    
+    float returnValues[numberColumns];
+    
+    int searchOps[radioInfo->numUtilities];
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+
+        /* If the goal is to maximum, set the search operation to
+         * return values greater than the target.
+         *
+         * If the goal is to minimize, set the search operation to
+         * return values less than the target.
+         */
+        if(strcmp(uList[i].goal.c_str(), "max") == 0) {
+            searchOps[i] = GT;
+        } else if(strcmp(uList[i].goal.c_str(), "min") == 0) {
+            searchOps[i] = LT;
+        }
+    }
+
+    /* CBR specific call */
+    uint32_t rc = cbr_search(myCBR, searchNames, searchOps, searchVals,
+            radioInfo->numUtilities, returnValues);
+
+    if(rc == 0){
+        /* Adapt the returned parameters to meet the objective */
+        WARNING("Cognitive Engine:: Found\n");
+
+        /* Should do a random adaptation.. */
+        if(returnValues[numberColumns-1] < 0) {
+            returnValues[2] = returnValues[2] - 15;
+            returnValues[3] = returnValues[3] - 2;
+        } else {
+            returnValues[2] = returnValues[2] + 15;
+            returnValues[3] = returnValues[3] + 2;
+        }
+    } else if(rc == 31337) {
+        WARNING("Cognitive Engine:: Not Found.\n");
+        /* No rows in the CBR, pick default parameters */
+        /* Currently this is hard coded and implementation specific! */
+        returnValues[2] = currentParameters[0].value + 5;
+        returnValues[3] = currentParameters[1].value + 10;
+        
+    } else {
+        WARNING("Cognitive Engine:: Search return an invalid value.\n");
+    }
+
+    size_t returnValueIndex = 0;
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        uList[i].value = returnValues[returnValueIndex];
+        returnValueIndex++;
+    }
+    for(size_t i = 0; i < radioInfo->numParameters; i++) {
+        pList[i].value = returnValues[returnValueIndex];
+        returnValueIndex++;
+    }
+    for(size_t i = 0; i < radioInfo->numObservables; i++) {
+        oList[i].value = returnValues[returnValueIndex];
+        returnValueIndex++;
+    }
+    returnValues[returnValueIndex] = 0;
+
+    char *allNames[numberColumns];
+    size_t allNameIndex = 0;
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        allNames[allNameIndex] = (char*)uList[i].name.c_str();
+        returnValues[allNameIndex] = uList[i].target;
+        allNameIndex++;
+    }
+    for(size_t i = 0; i < radioInfo->numParameters; i++) {
+        allNames[allNameIndex] = (char*)pList[i].name.c_str();
+        allNameIndex++;
+    }
+    for(size_t i = 0; i < radioInfo->numObservables; i++) {
+        allNames[allNameIndex] = (char*)oList[i].name.c_str();
+        returnValues[allNameIndex] = 0;
+        allNameIndex++;
+    }
+    allNames[allNameIndex] = "utility";
+
+    // Add row to CBR. 
+    cbr_add_row(myCBR, allNames, returnValues, returnValueIndex+1);
+
+    return pList;
+}
+
+
+Parameter* 
+CognitiveEngine::GetSolution(Observable *observables, \
+        Parameter *currentParameters, std::string service)
+{
+    LOG("Cognitive Engine:: Generating solution for %s service.\n", service.c_str());
+
+    return pList;
+}
+
+
+void 
+CognitiveEngine::ReceiveFeedback(Observable *observables, Parameter *parameters, \
+    std::string service)
+{
+    LOG("Cognitive Engine:: Receiving feedback.\n");
+}
+
+
+void
+CognitiveEngine::BuildCognitiveEngine()
+{
+    char filename[] = {"ex1"};
+    char tablename[] = {"data"};
+
+    uint32_t numberColumns = 
+        radioInfo->numUtilities +
+        radioInfo->numParameters +
+        radioInfo->numObservables + 1;
+
+    char *cols[numberColumns];
+
+    size_t columnIndex = 0;
+    for (size_t i = 0; i < radioInfo->numUtilities; i++){
+        cols[columnIndex] = (char*)uList[i].name.c_str();
+        columnIndex++;
+    }   
+    for (size_t i = 0; i < radioInfo->numParameters; i++){
+        cols[columnIndex] = (char*)pList[i].name.c_str();
+        columnIndex++;
+    }   
+    for (size_t i = 0; i < radioInfo->numObservables; i++){
+        cols[columnIndex] = (char*)oList[i].name.c_str();
+        columnIndex++;
+    }   
+    cols[columnIndex] = "utility";
+
+    myCBR = cbr_create(filename, tablename, cols, numberColumns);
+}
+
Index: vtcross/branches/wrodgers/src/include/vtcross/error.h
===================================================================
--- vtcross/branches/wrodgers/src/include/vtcross/error.h	(revision 161)
+++ vtcross/branches/wrodgers/src/include/vtcross/error.h	(revision 161)
@@ -0,0 +1,21 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * LICENSE INFORMATION GOES HERE
+ */
+
+/* DESCRIPTION OF FILE.
+ */
+
+#ifndef ERROR_H
+#define ERROR_H
+
+#include <cstdio>
+
+#define ERROR(exit_code, ...) { \
+    fprintf(stderr, __VA_ARGS__); \
+    exit(exit_code); }
+
+#define WARNING(...) fprintf(stderr, __VA_ARGS__)
+
+#endif
Index: vtcross/branches/wrodgers/src/include/vtcross/libvtcross.h
===================================================================
--- vtcross/branches/wrodgers/src/include/vtcross/libvtcross.h	(revision 230)
+++ vtcross/branches/wrodgers/src/include/vtcross/libvtcross.h	(revision 230)
@@ -0,0 +1,112 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * LICENSE INFORMATION GOES HERE
+ */
+
+/* VTCROSS Cognitive Radio API
+ *
+ * This header exports all public functions that comprise the VTCROSS function
+ * library.  
+ *
+ * PUT MORE STUFF HERE
+ */
+
+#ifndef LIBVTCROSS_H
+#define LIBVTCROSS_H
+
+#include <stdint.h>
+
+#include "components.h"
+#include "containers.h"
+
+
+/* Parses VTCROSS XML configuration file and uses it to configure the radio. 
+ *
+ * This function *must* be called when the radio first starts up, and may be
+ * called at any point after that to reconfigure the radio.
+ */
+bool ParseRadioConfiguration();
+
+
+/* Lists current radio configuration options loaded from the configuration XML
+ * file. 
+ *
+ * TODO How are we listing these?  Are we simply returning them to stdout?
+ * Logging them? Returning strings?  Need to figure this out...
+ */
+void ListCurrentRadioConfiguration();
+
+
+/* View data from the current status of the radio. 
+ *
+ * This function allows client code to capture radio properties at any certain
+ * instant.  Note, however, that these properties could be changing at very
+ * rapid rates. There is no guarantee that the return results from these
+ * functions will still be valid by the time the client code receives them.
+ */
+Observable* GetRadioObservables();
+Parameter* GetRadioParameters();
+Utility* GetRadioUtilities();
+
+
+/* View components currently connected to the radio by id. 
+ *
+ * TODO Should there be another way to list components? If you have 10 cognitive
+ * engines, how are you going to know which is which just by id?
+ */
+uint32_t* GetConnectedCognitiveEngines();
+uint32_t* GetConnectedPolicyEngines();
+uint32_t* GetConnectedManagementServiceLayers();
+uint32_t* GetConnectedComponents();
+
+
+/* Look up component information by id. 
+ *
+ * Note that the return type is of abstract base class component, which can then
+ * be used to reference whatever sub-component type was referenced by the id.
+ */
+Component* GetComponentInformation(uint32_t id);
+
+
+/* Given a certain set of observables, ask the radio to find the optimum radio
+ * parameters and return them. 
+ *
+ * TODO I'm a little confused about this function... why would anyone need to
+ * use this?  Shouldn't this be internal to the radio operation? 
+ */
+Parameter* GetOptimalParameters(Observable *radioObservables, uint32_t numObservables, 
+		Parameter *currentParameters, uint32_t numCurrentParameters);
+
+
+/* Update the radio regarding its performance for a certain set of transmission
+ * parameters, observables, and utilities.
+ *
+ * TODO Where in the function parameters are we accurately representing the
+ * radio's performance?
+ */
+bool UpdateParameterPerformance(Parameter *p, uint32_t numParameters, Observable *o, \
+        uint32_t numObservables);
+
+/* Deactivate/Activate/Disconnect a component by id.
+ */
+bool ActivateComponent(uint32_t id);
+bool DeactivateComponent(uint32_t id);
+bool DisconnectComponent(uint32_t id);
+
+
+/* Shut down the radio.
+ *
+ * This function will deactivate and disconnect all radio components before
+ * finally shutting down the shell and stopping radio operations.
+ */
+bool Shutdown();
+
+/* Return total number of currently recognized transmission parameters.
+ */
+uint32_t GetNumParameters();
+uint32_t GetNumObservables();
+uint32_t GetNumUtilities();
+
+
+#endif
Index: vtcross/branches/wrodgers/src/include/vtcross/Makefile.am
===================================================================
--- vtcross/branches/wrodgers/src/include/vtcross/Makefile.am	(revision 199)
+++ vtcross/branches/wrodgers/src/include/vtcross/Makefile.am	(revision 199)
@@ -0,0 +1,3 @@
+include_HEADERS = error.h debug.h socketcomm.h cbr.h components.h \
+				  containers.h libvtcross.h common.h config.h
+
Index: vtcross/branches/wrodgers/src/include/vtcross/socketcomm.h
===================================================================
--- vtcross/branches/wrodgers/src/include/vtcross/socketcomm.h	(revision 275)
+++ vtcross/branches/wrodgers/src/include/vtcross/socketcomm.h	(revision 275)
@@ -0,0 +1,53 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * TODO LICENSE INFORMATION GOES HERE
+ */
+
+/* TODO DESCRIPTION OF FILE.
+ */
+
+#ifndef SOCKET_COMM_H
+#define SOCKET_COMM_H
+
+#include <stdint.h>
+
+#include "containers.h"
+
+
+/* TODO
+ */
+void ReadMessage(int32_t socketFD, char *msgBuffer);
+
+/* TODO
+ */
+int32_t SendMessage(int32_t socketFD, const char *message) ;
+
+/* TODO
+ */
+int32_t GetParameter(int32_t socketFD, struct Parameter pList[], \
+        struct Radio_Info *radio_info);
+
+/* TODO
+ */
+int32_t GetRequest(int32_t socketFD, struct Parameter pList[], \
+        struct Radio_Info *radio_info);
+
+/* This is the original function that does what the above function is supposed
+ * to do.
+ */
+int32_t ClientSocket(const char  *serverName, const char *portNumber);
+
+/* TODO
+ */
+int32_t  AcceptTCPConnection(int32_t servSock);
+
+/* TODO
+ */
+int32_t CreateTCPServerSocket(uint16_t port);
+
+/* TODO
+ */
+int32_t InitializeTCPServerPort(int32_t servSock);
+
+#endif
Index: vtcross/branches/wrodgers/src/include/vtcross/components.h
===================================================================
--- vtcross/branches/wrodgers/src/include/vtcross/components.h	(revision 275)
+++ vtcross/branches/wrodgers/src/include/vtcross/components.h	(revision 275)
@@ -0,0 +1,402 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * LICENSE INFORMATION GOES HERE
+ */
+
+/* This header exports the declarations for all VT-CROSS radio components.  It
+ * contains two pure abstract base classes, Component and Engine; Engine derives
+ * from Component.  All functions contained within the abstract base classes are
+ * dynamically linked and pure, and all child non-abstract classes derive using 
+ * private inheritence.  Class functions of the abstract base classes are public
+ * for two reasons: (1) To allow for public/protected inheritence in other 
+ * implementations, (2) So that symbolic debuggers can navigate the call tree 
+ * for typecasted objects of derivative classes.
+ */
+
+#ifndef COMPONENTS_H
+#define COMPONENTS_H
+
+
+#include <cstring>
+#include <stdint.h>
+#include <string>
+
+#include "containers.h"
+#include "socketcomm.h"
+
+
+/* Component abstract base class that all component classes should inherit from,
+ * including cognitive and policy engines, and the service management layer.
+ * Defines only functions required by all component types.
+ */
+class Component
+{
+    public:
+        /* Asks the component at the passed socket FD for its component type
+         * string.  Note that this implementation is global for all component
+         * types, so is implemented here.  Should a component need to override
+         * it, that is possible via dynamic binding or overloading.
+         */
+        virtual std::string GetRemoteComponentType(int32_t componentSocketFD)
+        {
+            SendMessage(componentSocketFD, "request_component_type");
+
+            char buffer[256];
+            memset(buffer, 0, 256);
+            ReadMessage(componentSocketFD, buffer);
+
+            return std::string(buffer);
+        }
+
+        /* Send an indentfying string for this object's component type in
+         * response to a GetRemoteComponentType query.
+         */
+        virtual void SendComponentType() = 0;
+
+        /* Wait for a command signal containing task instructions.
+         */
+        //virtual void WaitForSignal() = 0;
+
+        /* Completely shutdown the radio and all operations.
+         */
+        virtual void Shutdown() = 0;
+
+        /* Reset the radio and reload all configuration files.
+         *
+         * TODO are we remembering experiences in CEs?
+         */
+        virtual void Reset() = 0;
+
+        /* Register or deregister a component with the primary radio shell.
+         */
+        virtual void RegisterComponent() = 0;
+        virtual void DeregisterComponent() = 0;
+};
+
+
+/* Engine abstract base class from which all engine component types should
+ * inherit (e.g. cognitive and policy engines). Inherits all functions from the
+ * ABC Component publically.
+ */
+class Engine : public Component
+{
+    public:
+        /* Connect to the remote control component, which will always be either
+         * the VTCROSS shell or SML.  Based on the status of the SML_present
+         * bool, this function will also register the component or services.
+         *
+         * TODO I feel like the name of this function could be changed to be a
+         * little more descriptive?
+         */
+        virtual void ConnectToRemoteComponent(const char* serverName, \
+                const char* serverPort, const bool SML) = 0;
+
+        /* Register or deregister services that this engine provides with the
+         * service management layer.
+         */
+        virtual void RegisterServices() = 0;
+        //virtual void DeregisterServices() = 0;
+};
+
+
+/* Service Management Layer (SML) class declaration.  The functions listed here
+ * are required by the VTCROSS API for service-oriented VTCROSS radio
+ * architectures.
+ */
+class ServiceManagementLayer : public Component
+{
+    public:
+        ServiceManagementLayer();
+        ~ServiceManagementLayer();
+
+        /* Overloaded constructor that creates an SML and connects it to the
+         * shell with the passed hostname and port.
+         */
+        ServiceManagementLayer(const char* SML_Config, const char* serverName, const char* serverPort);
+
+        /* Connect and register with the shell component at the passed hostname
+         * and port.
+         */
+        void ConnectToShell(const char* serverName, \
+                const char* serverPort);
+        void SendComponentType();
+        void MessageHandler(int32_t ID);
+        void Shutdown();
+        void Reset();
+        void RegisterComponent();
+        void DeregisterComponent();
+
+	/* Starts the SML Server and watches it for incoming messages
+	 */
+	void StartSMLServer();
+
+    private: 
+        /* Receive the radio configuration settings from the shell and pass them
+         * on to another component.
+         */
+        void TransferRadioConfiguration(int32_t ID);
+
+        /* Receive information regarding a completed 'experience' and pass it on
+         * to the appropriate cognitive engine.
+         */
+        void TransferExperience(int32_t ID);
+        
+        /* Listen for other components registering their available services with
+         * the SML. 
+         */
+        void ReceiveServices(int32_t ID);
+ 	void DeregisterServices(int32_t ID);
+
+        /* Change the active mission of the radio to a new one and adjust radio
+         * behavoir appropriately.
+         */
+        void SetActiveMission();
+
+	void RegisterCognitiveEngine(int32_t ID);
+	void DeregisterCognitiveEngine(int32_t ID);
+
+        /* List all services provided to the radio by registered components.
+         */
+        void ListServices();
+
+        /* Load/Relead the XML configuration file. 
+         */
+        void ReloadConfiguration();
+        void LoadConfiguration(const char *SML_Config, Mission* &mList);
+
+	/* Create and initialize the DB to hold the services
+	 */
+	void CreateServicesDB();
+	void CreateDataDB();
+
+	void PerformActiveMission();
+	void TransactData(int32_t sourceID);
+
+
+        /* The socket file descriptor information for the shell which this SML
+         * is connected to.
+         */
+        int32_t shellSocketFD;
+	CE_Reg *CE_List;
+    	int32_t cogEngSrv;
+	int16_t CEPort;
+	uint16_t numberOfCognitiveEngines;
+	uint32_t Current_ID; 
+        Mission *miss;
+	bool CE_Present;
+        int32_t activeMission;
+};
+
+
+/* Policy Engine class declaration.  All public functions are inherited from
+ * parent classes.
+ */
+class PolicyEngine : public Engine
+{
+    public:
+        PolicyEngine();
+        ~PolicyEngine();
+
+        /* Overloaded constructor that creates a policy engine object and
+         * connects it to either the shell or an SML, depening on the SML bool.
+         */
+        PolicyEngine(const char* serverName, const char* serverPort, \
+                const bool SML);
+
+        void SendComponentType();
+        void ConnectToRemoteComponent(const char* serverName, \
+                const char* serverPort, const bool SML);
+        void WaitForSignal();
+        void Shutdown();
+        void Reset();
+        void RegisterComponent();
+        void DeregisterComponent();
+
+        void RegisterServices();
+        void DeregisterServices();
+
+    private:
+        /* Parse and load/reload policies into the policy engine.
+         */
+        void LoadPolicies();
+        void ReloadPolicies();
+
+        /* Return a decision made by the policy engine regarding a certain set
+         * of transmission parameters.
+         */
+        void SendPEDecision(struct Parameter pList[], struct Radio_Info *radio_info, \
+                int32_t decision_array[]);
+
+        /* Validate a set of transmission parameters received from the radio.
+         */
+        void ValidateParameters();
+
+        /* The SML_present bool reflects whether or not the remote component
+         * this object is connected to is an SML.  If it isn't, then it must be
+         * a shell.  The socketFD stores the socket file descriptor for this
+         * connection.
+         */
+        bool SML_present;
+        int32_t commandSocketFD;
+};
+
+
+/* Cognitive Engine class declaration.  All public functions are inherited from
+ * parent classes.
+ */
+class CognitiveEngine : public Engine
+{
+    public:
+        CognitiveEngine();
+        ~CognitiveEngine();
+
+        /* Overloaded constructor that creates a cognitive engine object and
+         * connects it to either the shell or an SML, depening on the SML bool.
+         */
+        CognitiveEngine(const char* serverName, const char* serverPort, \
+                const bool SML);
+        
+        void SendComponentType();
+        void ConnectToRemoteComponent(const char* serverName, \
+                const char* serverPort, const bool SML);
+        void WaitForSignal();
+        void Shutdown();
+        void Reset();
+        void RegisterComponent();
+        void DeregisterComponent();
+
+        void RegisterServices();
+        //void DeregisterServices();
+
+    private:
+        /* Receive the transmitted radio configuration from the radio itself
+         * (the CE will not always be local to the radio).
+         */
+        void ReceiveRadioConfiguration();
+
+        /* Receive an 'experience' report from the radio.
+         */
+        void ReceiveExperience();
+
+        /* Find the most optimal set of transmission parameters given certain
+         * observables and possibly a service if the SML component is present
+         * and active.
+         */
+        Parameter *GetSolution(Observable *observables, Parameter *currentParameters);
+        Parameter *GetSolution(Observable *observables, Parameter *currentParameters, std::string service);
+
+        /* Receive a feedback from the radio regarding the performance of a
+         * certain set of parameters, possibly associated with a service.
+         *
+         * Feedback is a single set of performance statistics that is achieved
+         * corresponding to a specific set of transmission parameters.  Feedback
+         * helps a Cognitive Engine make better future decisions based upon 
+         * more accurate performance statistics. 
+         */
+        void ReceiveFeedback(Observable *observables,\
+                Parameter *parameters);
+        void ReceiveFeedback(Observable *observables, \
+                Parameter *parameters, std::string service);
+
+
+		/* BuildCognitiveEngine performs the CE implementation specific work
+		 * that defines the internals of a CE.  For example, a CBR CE engine
+		 * would build the case-base reasoner or create the database, a neural
+		 * network based CE may perform the initial training, a GA based CE
+		 * may build the chromosome structure.
+		 */
+		void BuildCognitiveEngine();
+
+        /* The SML_present bool reflects whether or not the remote component
+         * this object is connected to is an SML.  If it isn't, then it must be
+         * a shell.  The socketFD stores the socket file descriptor for this
+         * connection.
+         */
+        bool SML_present;
+        int32_t commandSocketFD;
+        
+        // TODO Need a description for these fields.  Are these radio utilites,
+        // parameters, and observables global to the whole system?
+        Utility *uList;
+        Parameter *pList;
+        Observable *oList;
+        struct Radio_Info *radioInfo;
+};
+
+/* Cognitive Radio Shell class declaration. 
+ */
+class CognitiveRadioShell 
+{
+    public:
+        CognitiveRadioShell();
+        ~CognitiveRadioShell();
+
+        /* Overloaded constructor that creates a CR Shell object and loads the
+         * passed radio configuration XML file.
+         */
+        CognitiveRadioShell(const char* radioConfig, int16_t primaryPort, \
+            int16_t policyPort, int16_t commandPort);
+
+        /* Ask for the component type of a remote component via sockets, or
+         * respond to such a query sent to the shell itself.
+         */
+        std::string GetRemoteComponentType(int32_t socketFD);
+        void SendComponentType(int32_t socketFD);
+
+        void Shutdown();
+        void Reset();
+        
+        /* Start all the socket servers */
+        void StartShellServer(); 
+
+        int32_t LoadRadioConfiguration(const char* radioConfig, Parameter* &pList, \
+            Utility* &uList, Observable* &oList, Radio_Info* radioInfo);
+    private:
+        /* Parse and load/reload policies into the policy engine.
+         */
+        void LoadPolicies();
+        void ReloadPolicies();
+
+        /* Register and Deregister the different components.
+         */
+        void RegisterCognitiveEngine(int32_t socketFD);
+        void DeregisterCognitiveEngine(int32_t socketFD);
+        void RegisterPolicyEngine(int32_t socketFD);
+        void DeregisterPolicyEngine(int32_t socketFD);
+        void RegisterSML(int32_t socketFD);
+        void DeregisterSML(int32_t socketFD);
+
+        /* Handle a message that is received from a component.
+         */
+        void HandleMessage(int32_t socketFD);
+       
+        /* Send optimization request to primary port FD.
+         */
+        void GetOptimalParameters(int32_t socketFD);
+
+        bool SendRadioConfiguration(int32_t socketFD);
+        bool SendRadioExperience(int32_t socketFD);
+
+		bool UpdateParameterPerformance(int32_t socketFD);
+
+        bool SML_present;
+        bool PE_present;
+        bool CE_present;
+       
+        int32_t numberOfCognitiveEngines; 
+        int16_t primaryPort;
+        int16_t policyPort;
+        int16_t commandPort;
+
+        int32_t ceSocketFD;
+        int32_t commandSocketFD;
+        int32_t policySocketFD;
+
+        Utility *utils;
+        Parameter *params;
+        Observable *observables;
+        struct Radio_Info *radio_info;
+};
+
+#endif
Index: vtcross/branches/wrodgers/src/include/vtcross/containers.h
===================================================================
--- vtcross/branches/wrodgers/src/include/vtcross/containers.h	(revision 275)
+++ vtcross/branches/wrodgers/src/include/vtcross/containers.h	(revision 275)
@@ -0,0 +1,115 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * LICENSE INFORMATION GOES HERE
+ */
+
+/* This header contains commonly used data container structs in VT-CROSS
+ * systems.
+ */
+
+#ifndef CONTAINERS_H
+#define CONTAINERS_H
+
+
+#include <netdb.h>
+#include <stdint.h>
+#include <string>
+
+
+/* TODO
+ *
+ */
+struct Radio_Info {
+    uint32_t numUtilities;
+    uint32_t numParameters;
+    uint32_t numObservables;
+    uint32_t policy_engine;
+    uint32_t policy_socket;
+    uint32_t ce_socket;
+};
+
+
+/* TODO
+ *
+ */
+struct Utility {
+    std::string name;
+    std::string units;
+    std::string goal;
+    float target;
+    float value;
+};
+
+
+/* TODO
+ *
+ */
+struct Affect {
+    Utility *u;
+    std::string relation;
+};
+
+
+/* TODO
+ *
+ */
+struct Parameter {
+    std::string name;
+    std::string units;
+    float min;
+    uint32_t numAffects;
+    Affect affection_list[10];
+    float max;
+    float step;
+    float value;
+};
+
+
+/* TODO
+ *
+ */
+struct Observable {
+    std::string name;
+    Affect affection_list[10];
+    uint32_t numAffects;
+    float value;
+};
+
+
+/* TODO
+ *
+ */
+struct Service {
+    std::string name;
+    int32_t socketFD;
+    int32_t componentID;
+    uint16_t num_conds;
+    bool cond_flag;
+    std::string input[3];
+    std::string output[3];
+}; 
+
+
+/* TODO
+ *
+ */
+struct Mission {
+    std::string name;
+    uint32_t missionID;
+    uint32_t numServices;
+    Service *services;
+    std::string input[3];
+    std::string output[3];
+};
+
+/* Registration data for Cognitive Engines for use in communication 
+ */
+struct CE_Reg {
+    int32_t ID_num;
+    //sockaddr_in *sock_ptr;
+    //socklen_t sock_len;
+    int32_t FD;
+};
+
+#endif
Index: vtcross/branches/wrodgers/src/include/vtcross/cbr.h
===================================================================
--- vtcross/branches/wrodgers/src/include/vtcross/cbr.h	(revision 170)
+++ vtcross/branches/wrodgers/src/include/vtcross/cbr.h	(revision 170)
@@ -0,0 +1,36 @@
+//
+// Case-based reasoner
+//
+//
+// TODO REDO THIS FILE
+
+#ifndef CBR_H
+#define CBR_H
+
+#include "sqlite3.h"
+//#define CBR_LEN_FILENAME 64
+
+#define DATABASENAME "cactus_cbr"
+
+typedef struct cbr_s * cbr;
+
+// create the CBR
+cbr cbr_create(char * _filename, char * _tablename, char * _cols[], unsigned int _len);
+
+// free the CBR
+void cbr_free(cbr _cbr);
+
+// print databse/table
+void cbr_print(cbr _cbr);
+
+#define EQ 0    // equals
+#define NE 1    // not equals
+#define GT 2    // greater than
+#define GE 3    // greater than or equal to
+#define LT 4    // less than
+#define LE 5    // less than or equal to
+int cbr_search(cbr _cbr, char *_names[], int * _ops, float *_vals, unsigned int _n, float *_retvals);
+
+int cbr_add_row(cbr _cbr, char *_cols[], float *_vals, unsigned int _len);
+
+#endif
Index: vtcross/branches/wrodgers/src/include/vtcross/debug.h
===================================================================
--- vtcross/branches/wrodgers/src/include/vtcross/debug.h	(revision 161)
+++ vtcross/branches/wrodgers/src/include/vtcross/debug.h	(revision 161)
@@ -0,0 +1,24 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * LICENSE INFORMATION GOES HERE
+ */
+
+/* DESCRIPTION OF FILE.
+ */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#include <cstdio>
+
+extern bool VTCROSS_DEBUG;
+
+#define DEBUG(...) \
+    if(VTCROSS_DEBUG) {\
+        fprintf(stderr, __VA_ARGS__);\
+    }
+
+#define LOG(...) fprintf(stdout, __VA_ARGS__)
+
+#endif
Index: vtcross/branches/wrodgers/src/include/vtcross/common.h
===================================================================
--- vtcross/branches/wrodgers/src/include/vtcross/common.h	(revision 161)
+++ vtcross/branches/wrodgers/src/include/vtcross/common.h	(revision 161)
@@ -0,0 +1,18 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * LICENSE INFORMATION GOES HERE
+ */
+
+/* This file is included in every source file of the VTCROSS system.  It
+ * declares global flags and includes.
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#ifdef HAVE_CONFIG_H
+    #include "config.h"
+#endif
+
+#endif
Index: vtcross/branches/wrodgers/src/include/tinyxml/tinystr.h
===================================================================
--- vtcross/branches/wrodgers/src/include/tinyxml/tinystr.h	(revision 161)
+++ vtcross/branches/wrodgers/src/include/tinyxml/tinystr.h	(revision 161)
@@ -0,0 +1,319 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original file by Yves Berquin.
+
+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.
+*/
+
+/*
+ * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005.
+ *
+ * - completely rewritten. compact, clean, and fast implementation.
+ * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems)
+ * - fixed reserve() to work as per specification.
+ * - fixed buggy compares operator==(), operator<(), and operator>()
+ * - fixed operator+=() to take a const ref argument, following spec.
+ * - added "copy" constructor with length, and most compare operators.
+ * - added swap(), clear(), size(), capacity(), operator+().
+ */
+
+#ifndef TIXML_USE_STL
+
+#ifndef TIXML_STRING_INCLUDED
+#define TIXML_STRING_INCLUDED
+
+#include <assert.h>
+#include <string.h>
+
+/*	The support for explicit isn't that universal, and it isn't really
+	required - it is used to check that the TiXmlString class isn't incorrectly
+	used. Be nice to old compilers and macro it here:
+*/
+#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
+	// Microsoft visual studio, version 6 and higher.
+	#define TIXML_EXPLICIT explicit
+#elif defined(__GNUC__) && (__GNUC__ >= 3 )
+	// GCC version 3 and higher.s
+	#define TIXML_EXPLICIT explicit
+#else
+	#define TIXML_EXPLICIT
+#endif
+
+
+/*
+   TiXmlString is an emulation of a subset of the std::string template.
+   Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
+   Only the member functions relevant to the TinyXML project have been implemented.
+   The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
+   a string and there's no more room, we allocate a buffer twice as big as we need.
+*/
+class TiXmlString
+{
+  public :
+	// The size type used
+  	typedef size_t size_type;
+
+	// Error value for find primitive
+	static const size_type npos; // = -1;
+
+
+	// TiXmlString empty constructor
+	TiXmlString () : rep_(&nullrep_)
+	{
+	}
+
+	// TiXmlString copy constructor
+	TiXmlString ( const TiXmlString & copy) : rep_(0)
+	{
+		init(copy.length());
+		memcpy(start(), copy.data(), length());
+	}
+
+	// TiXmlString constructor, based on a string
+	TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0)
+	{
+		init( static_cast<size_type>( strlen(copy) ));
+		memcpy(start(), copy, length());
+	}
+
+	// TiXmlString constructor, based on a string
+	TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0)
+	{
+		init(len);
+		memcpy(start(), str, len);
+	}
+
+	// TiXmlString destructor
+	~TiXmlString ()
+	{
+		quit();
+	}
+
+	// = operator
+	TiXmlString& operator = (const char * copy)
+	{
+		return assign( copy, (size_type)strlen(copy));
+	}
+
+	// = operator
+	TiXmlString& operator = (const TiXmlString & copy)
+	{
+		return assign(copy.start(), copy.length());
+	}
+
+
+	// += operator. Maps to append
+	TiXmlString& operator += (const char * suffix)
+	{
+		return append(suffix, static_cast<size_type>( strlen(suffix) ));
+	}
+
+	// += operator. Maps to append
+	TiXmlString& operator += (char single)
+	{
+		return append(&single, 1);
+	}
+
+	// += operator. Maps to append
+	TiXmlString& operator += (const TiXmlString & suffix)
+	{
+		return append(suffix.data(), suffix.length());
+	}
+
+
+	// Convert a TiXmlString into a null-terminated char *
+	const char * c_str () const { return rep_->str; }
+
+	// Convert a TiXmlString into a char * (need not be null terminated).
+	const char * data () const { return rep_->str; }
+
+	// Return the length of a TiXmlString
+	size_type length () const { return rep_->size; }
+
+	// Alias for length()
+	size_type size () const { return rep_->size; }
+
+	// Checks if a TiXmlString is empty
+	bool empty () const { return rep_->size == 0; }
+
+	// Return capacity of string
+	size_type capacity () const { return rep_->capacity; }
+
+
+	// single char extraction
+	const char& at (size_type index) const
+	{
+		assert( index < length() );
+		return rep_->str[ index ];
+	}
+
+	// [] operator
+	char& operator [] (size_type index) const
+	{
+		assert( index < length() );
+		return rep_->str[ index ];
+	}
+
+	// find a char in a string. Return TiXmlString::npos if not found
+	size_type find (char lookup) const
+	{
+		return find(lookup, 0);
+	}
+
+	// find a char in a string from an offset. Return TiXmlString::npos if not found
+	size_type find (char tofind, size_type offset) const
+	{
+		if (offset >= length()) return npos;
+
+		for (const char* p = c_str() + offset; *p != '\0'; ++p)
+		{
+		   if (*p == tofind) return static_cast< size_type >( p - c_str() );
+		}
+		return npos;
+	}
+
+	void clear ()
+	{
+		//Lee:
+		//The original was just too strange, though correct:
+		//	TiXmlString().swap(*this);
+		//Instead use the quit & re-init:
+		quit();
+		init(0,0);
+	}
+
+	/*	Function to reserve a big amount of data when we know we'll need it. Be aware that this
+		function DOES NOT clear the content of the TiXmlString if any exists.
+	*/
+	void reserve (size_type cap);
+
+	TiXmlString& assign (const char* str, size_type len);
+
+	TiXmlString& append (const char* str, size_type len);
+
+	void swap (TiXmlString& other)
+	{
+		Rep* r = rep_;
+		rep_ = other.rep_;
+		other.rep_ = r;
+	}
+
+  private:
+
+	void init(size_type sz) { init(sz, sz); }
+	void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
+	char* start() const { return rep_->str; }
+	char* finish() const { return rep_->str + rep_->size; }
+
+	struct Rep
+	{
+		size_type size, capacity;
+		char str[1];
+	};
+
+	void init(size_type sz, size_type cap)
+	{
+		if (cap)
+		{
+			// Lee: the original form:
+			//	rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
+			// doesn't work in some cases of new being overloaded. Switching
+			// to the normal allocation, although use an 'int' for systems
+			// that are overly picky about structure alignment.
+			const size_type bytesNeeded = sizeof(Rep) + cap;
+			const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); 
+			rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
+
+			rep_->str[ rep_->size = sz ] = '\0';
+			rep_->capacity = cap;
+		}
+		else
+		{
+			rep_ = &nullrep_;
+		}
+	}
+
+	void quit()
+	{
+		if (rep_ != &nullrep_)
+		{
+			// The rep_ is really an array of ints. (see the allocator, above).
+			// Cast it back before delete, so the compiler won't incorrectly call destructors.
+			delete [] ( reinterpret_cast<int*>( rep_ ) );
+		}
+	}
+
+	Rep * rep_;
+	static Rep nullrep_;
+
+} ;
+
+
+inline bool operator == (const TiXmlString & a, const TiXmlString & b)
+{
+	return    ( a.length() == b.length() )				// optimization on some platforms
+	       && ( strcmp(a.c_str(), b.c_str()) == 0 );	// actual compare
+}
+inline bool operator < (const TiXmlString & a, const TiXmlString & b)
+{
+	return strcmp(a.c_str(), b.c_str()) < 0;
+}
+
+inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
+inline bool operator >  (const TiXmlString & a, const TiXmlString & b) { return b < a; }
+inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
+inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
+
+inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
+inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
+inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
+inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
+
+TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
+TiXmlString operator + (const TiXmlString & a, const char* b);
+TiXmlString operator + (const char* a, const TiXmlString & b);
+
+
+/*
+   TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
+   Only the operators that we need for TinyXML have been developped.
+*/
+class TiXmlOutStream : public TiXmlString
+{
+public :
+
+	// TiXmlOutStream << operator.
+	TiXmlOutStream & operator << (const TiXmlString & in)
+	{
+		*this += in;
+		return *this;
+	}
+
+	// TiXmlOutStream << operator.
+	TiXmlOutStream & operator << (const char * in)
+	{
+		*this += in;
+		return *this;
+	}
+
+} ;
+
+#endif	// TIXML_STRING_INCLUDED
+#endif	// TIXML_USE_STL
Index: vtcross/branches/wrodgers/src/include/tinyxml/Makefile.am
===================================================================
--- vtcross/branches/wrodgers/src/include/tinyxml/Makefile.am	(revision 161)
+++ vtcross/branches/wrodgers/src/include/tinyxml/Makefile.am	(revision 161)
@@ -0,0 +1,1 @@
+include_HEADERS = tinystr.h tinyxml.h
Index: vtcross/branches/wrodgers/src/include/tinyxml/tinyxml.h
===================================================================
--- vtcross/branches/wrodgers/src/include/tinyxml/tinyxml.h	(revision 161)
+++ vtcross/branches/wrodgers/src/include/tinyxml/tinyxml.h	(revision 161)
@@ -0,0 +1,1802 @@
+/*
+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.
+*/
+
+
+#ifndef TINYXML_INCLUDED
+#define TINYXML_INCLUDED
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4530 )
+#pragma warning( disable : 4786 )
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+// Help out windows:
+#if defined( _DEBUG ) && !defined( DEBUG )
+#define DEBUG
+#endif
+
+#ifdef TIXML_USE_STL
+	#include <string>
+ 	#include <iostream>
+	#include <sstream>
+	#define TIXML_STRING		std::string
+#else
+	#include "tinystr.h"
+	#define TIXML_STRING		TiXmlString
+#endif
+
+// Deprecated library function hell. Compilers want to use the
+// new safe versions. This probably doesn't fully address the problem,
+// but it gets closer. There are too many compilers for me to fully
+// test. If you get compilation troubles, undefine TIXML_SAFE
+#define TIXML_SAFE
+
+#ifdef TIXML_SAFE
+	#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+		// Microsoft visual studio, version 2005 and higher.
+		#define TIXML_SNPRINTF _snprintf_s
+		#define TIXML_SNSCANF  _snscanf_s
+		#define TIXML_SSCANF   sscanf_s
+	#elif defined(_MSC_VER) && (_MSC_VER >= 1200 )
+		// Microsoft visual studio, version 6 and higher.
+		//#pragma message( "Using _sn* functions." )
+		#define TIXML_SNPRINTF _snprintf
+		#define TIXML_SNSCANF  _snscanf
+		#define TIXML_SSCANF   sscanf
+	#elif defined(__GNUC__) && (__GNUC__ >= 3 )
+		// GCC version 3 and higher.s
+		//#warning( "Using sn* functions." )
+		#define TIXML_SNPRINTF snprintf
+		#define TIXML_SNSCANF  snscanf
+		#define TIXML_SSCANF   sscanf
+	#else
+		#define TIXML_SSCANF   sscanf
+	#endif
+#endif	
+
+class TiXmlDocument;
+class TiXmlElement;
+class TiXmlComment;
+class TiXmlUnknown;
+class TiXmlAttribute;
+class TiXmlText;
+class TiXmlDeclaration;
+class TiXmlParsingData;
+
+const int TIXML_MAJOR_VERSION = 2;
+const int TIXML_MINOR_VERSION = 5;
+const int TIXML_PATCH_VERSION = 3;
+
+/*	Internal structure for tracking location of items 
+	in the XML file.
+*/
+struct TiXmlCursor
+{
+	TiXmlCursor()		{ Clear(); }
+	void Clear()		{ row = col = -1; }
+
+	int row;	// 0 based.
+	int col;	// 0 based.
+};
+
+
+/**
+	If you call the Accept() method, it requires being passed a TiXmlVisitor
+	class to handle callbacks. For nodes that contain other nodes (Document, Element)
+	you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
+	are simple called with Visit().
+
+	If you return 'true' from a Visit method, recursive parsing will continue. If you return
+	false, <b>no children of this node or its sibilings</b> will be Visited.
+
+	All flavors of Visit methods have a default implementation that returns 'true' (continue 
+	visiting). You need to only override methods that are interesting to you.
+
+	Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
+
+	You should never change the document from a callback.
+
+	@sa TiXmlNode::Accept()
+*/
+class TiXmlVisitor
+{
+public:
+	virtual ~TiXmlVisitor() {}
+
+	/// Visit a document.
+	virtual bool VisitEnter( const TiXmlDocument& /*doc*/ )			{ return true; }
+	/// Visit a document.
+	virtual bool VisitExit( const TiXmlDocument& /*doc*/ )			{ return true; }
+
+	/// Visit an element.
+	virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ )	{ return true; }
+	/// Visit an element.
+	virtual bool VisitExit( const TiXmlElement& /*element*/ )		{ return true; }
+
+	/// Visit a declaration
+	virtual bool Visit( const TiXmlDeclaration& /*declaration*/ )	{ return true; }
+	/// Visit a text node
+	virtual bool Visit( const TiXmlText& /*text*/ )					{ return true; }
+	/// Visit a comment node
+	virtual bool Visit( const TiXmlComment& /*comment*/ )			{ return true; }
+	/// Visit an unknow node
+	virtual bool Visit( const TiXmlUnknown& /*unknown*/ )			{ return true; }
+};
+
+// Only used by Attribute::Query functions
+enum 
+{ 
+	TIXML_SUCCESS,
+	TIXML_NO_ATTRIBUTE,
+	TIXML_WRONG_TYPE
+};
+
+
+// Used by the parsing routines.
+enum TiXmlEncoding
+{
+	TIXML_ENCODING_UNKNOWN,
+	TIXML_ENCODING_UTF8,
+	TIXML_ENCODING_LEGACY
+};
+
+const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN;
+
+/** TiXmlBase is a base class for every class in TinyXml.
+	It does little except to establish that TinyXml classes
+	can be printed and provide some utility functions.
+
+	In XML, the document and elements can contain
+	other elements and other types of nodes.
+
+	@verbatim
+	A Document can contain:	Element	(container or leaf)
+							Comment (leaf)
+							Unknown (leaf)
+							Declaration( leaf )
+
+	An Element can contain:	Element (container or leaf)
+							Text	(leaf)
+							Attributes (not on tree)
+							Comment (leaf)
+							Unknown (leaf)
+
+	A Decleration contains: Attributes (not on tree)
+	@endverbatim
+*/
+class TiXmlBase
+{
+	friend class TiXmlNode;
+	friend class TiXmlElement;
+	friend class TiXmlDocument;
+
+public:
+	TiXmlBase()	:	userData(0)		{}
+	virtual ~TiXmlBase()			{}
+
+	/**	All TinyXml classes can print themselves to a filestream
+		or the string class (TiXmlString in non-STL mode, std::string
+		in STL mode.) Either or both cfile and str can be null.
+		
+		This is a formatted print, and will insert 
+		tabs and newlines.
+		
+		(For an unformatted stream, use the << operator.)
+	*/
+	virtual void Print( FILE* cfile, int depth ) const = 0;
+
+	/**	The world does not agree on whether white space should be kept or
+		not. In order to make everyone happy, these global, static functions
+		are provided to set whether or not TinyXml will condense all white space
+		into a single space or not. The default is to condense. Note changing this
+		value is not thread safe.
+	*/
+	static void SetCondenseWhiteSpace( bool condense )		{ condenseWhiteSpace = condense; }
+
+	/// Return the current white space setting.
+	static bool IsWhiteSpaceCondensed()						{ return condenseWhiteSpace; }
+
+	/** Return the position, in the original source file, of this node or attribute.
+		The row and column are 1-based. (That is the first row and first column is
+		1,1). If the returns values are 0 or less, then the parser does not have
+		a row and column value.
+
+		Generally, the row and column value will be set when the TiXmlDocument::Load(),
+		TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set
+		when the DOM was created from operator>>.
+
+		The values reflect the initial load. Once the DOM is modified programmatically
+		(by adding or changing nodes and attributes) the new values will NOT update to
+		reflect changes in the document.
+
+		There is a minor performance cost to computing the row and column. Computation
+		can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value.
+
+		@sa TiXmlDocument::SetTabSize()
+	*/
+	int Row() const			{ return location.row + 1; }
+	int Column() const		{ return location.col + 1; }	///< See Row()
+
+	void  SetUserData( void* user )			{ userData = user; }	///< Set a pointer to arbitrary user data.
+	void* GetUserData()						{ return userData; }	///< Get a pointer to arbitrary user data.
+	const void* GetUserData() const 		{ return userData; }	///< Get a pointer to arbitrary user data.
+
+	// Table that returs, for a given lead byte, the total number of bytes
+	// in the UTF-8 sequence.
+	static const int utf8ByteTable[256];
+
+	virtual const char* Parse(	const char* p, 
+								TiXmlParsingData* data, 
+								TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0;
+
+	/** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, 
+		or they will be transformed into entities!
+	*/
+	static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out );
+
+	enum
+	{
+		TIXML_NO_ERROR = 0,
+		TIXML_ERROR,
+		TIXML_ERROR_OPENING_FILE,
+		TIXML_ERROR_OUT_OF_MEMORY,
+		TIXML_ERROR_PARSING_ELEMENT,
+		TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
+		TIXML_ERROR_READING_ELEMENT_VALUE,
+		TIXML_ERROR_READING_ATTRIBUTES,
+		TIXML_ERROR_PARSING_EMPTY,
+		TIXML_ERROR_READING_END_TAG,
+		TIXML_ERROR_PARSING_UNKNOWN,
+		TIXML_ERROR_PARSING_COMMENT,
+		TIXML_ERROR_PARSING_DECLARATION,
+		TIXML_ERROR_DOCUMENT_EMPTY,
+		TIXML_ERROR_EMBEDDED_NULL,
+		TIXML_ERROR_PARSING_CDATA,
+		TIXML_ERROR_DOCUMENT_TOP_ONLY,
+
+		TIXML_ERROR_STRING_COUNT
+	};
+
+protected:
+
+	static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding );
+	inline static bool IsWhiteSpace( char c )		
+	{ 
+		return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); 
+	}
+	inline static bool IsWhiteSpace( int c )
+	{
+		if ( c < 256 )
+			return IsWhiteSpace( (char) c );
+		return false;	// Again, only truly correct for English/Latin...but usually works.
+	}
+
+	#ifdef TIXML_USE_STL
+	static bool	StreamWhiteSpace( std::istream * in, TIXML_STRING * tag );
+	static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag );
+	#endif
+
+	/*	Reads an XML name into the string provided. Returns
+		a pointer just past the last character of the name,
+		or 0 if the function has an error.
+	*/
+	static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding );
+
+	/*	Reads text. Returns a pointer past the given end tag.
+		Wickedly complex options, but it keeps the (sensitive) code in one place.
+	*/
+	static const char* ReadText(	const char* in,				// where to start
+									TIXML_STRING* text,			// the string read
+									bool ignoreWhiteSpace,		// whether to keep the white space
+									const char* endTag,			// what ends this text
+									bool ignoreCase,			// whether to ignore case in the end tag
+									TiXmlEncoding encoding );	// the current encoding
+
+	// If an entity has been found, transform it into a character.
+	static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding );
+
+	// Get a character, while interpreting entities.
+	// The length can be from 0 to 4 bytes.
+	inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding )
+	{
+		assert( p );
+		if ( encoding == TIXML_ENCODING_UTF8 )
+		{
+			*length = utf8ByteTable[ *((const unsigned char*)p) ];
+			assert( *length >= 0 && *length < 5 );
+		}
+		else
+		{
+			*length = 1;
+		}
+
+		if ( *length == 1 )
+		{
+			if ( *p == '&' )
+				return GetEntity( p, _value, length, encoding );
+			*_value = *p;
+			return p+1;
+		}
+		else if ( *length )
+		{
+			//strncpy( _value, p, *length );	// lots of compilers don't like this function (unsafe),
+												// and the null terminator isn't needed
+			for( int i=0; p[i] && i<*length; ++i ) {
+				_value[i] = p[i];
+			}
+			return p + (*length);
+		}
+		else
+		{
+			// Not valid text.
+			return 0;
+		}
+	}
+
+	// Return true if the next characters in the stream are any of the endTag sequences.
+	// Ignore case only works for english, and should only be relied on when comparing
+	// to English words: StringEqual( p, "version", true ) is fine.
+	static bool StringEqual(	const char* p,
+								const char* endTag,
+								bool ignoreCase,
+								TiXmlEncoding encoding );
+
+	static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
+
+	TiXmlCursor location;
+
+    /// Field containing a generic user pointer
+	void*			userData;
+	
+	// None of these methods are reliable for any language except English.
+	// Good for approximation, not great for accuracy.
+	static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding );
+	static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding );
+	inline static int ToLower( int v, TiXmlEncoding encoding )
+	{
+		if ( encoding == TIXML_ENCODING_UTF8 )
+		{
+			if ( v < 128 ) return tolower( v );
+			return v;
+		}
+		else
+		{
+			return tolower( v );
+		}
+	}
+	static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
+
+private:
+	TiXmlBase( const TiXmlBase& );				// not implemented.
+	void operator=( const TiXmlBase& base );	// not allowed.
+
+	struct Entity
+	{
+		const char*     str;
+		unsigned int	strLength;
+		char		    chr;
+	};
+	enum
+	{
+		NUM_ENTITY = 5,
+		MAX_ENTITY_LENGTH = 6
+
+	};
+	static Entity entity[ NUM_ENTITY ];
+	static bool condenseWhiteSpace;
+};
+
+
+/** The parent class for everything in the Document Object Model.
+	(Except for attributes).
+	Nodes have siblings, a parent, and children. A node can be
+	in a document, or stand on its own. The type of a TiXmlNode
+	can be queried, and it can be cast to its more defined type.
+*/
+class TiXmlNode : public TiXmlBase
+{
+	friend class TiXmlDocument;
+	friend class TiXmlElement;
+
+public:
+	#ifdef TIXML_USE_STL	
+
+	    /** An input stream operator, for every class. Tolerant of newlines and
+		    formatting, but doesn't expect them.
+	    */
+	    friend std::istream& operator >> (std::istream& in, TiXmlNode& base);
+
+	    /** An output stream operator, for every class. Note that this outputs
+		    without any newlines or formatting, as opposed to Print(), which
+		    includes tabs and new lines.
+
+		    The operator<< and operator>> are not completely symmetric. Writing
+		    a node to a stream is very well defined. You'll get a nice stream
+		    of output, without any extra whitespace or newlines.
+		    
+		    But reading is not as well defined. (As it always is.) If you create
+		    a TiXmlElement (for example) and read that from an input stream,
+		    the text needs to define an element or junk will result. This is
+		    true of all input streams, but it's worth keeping in mind.
+
+		    A TiXmlDocument will read nodes until it reads a root element, and
+			all the children of that root element.
+	    */	
+	    friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base);
+
+		/// Appends the XML node or attribute to a std::string.
+		friend std::string& operator<< (std::string& out, const TiXmlNode& base );
+
+	#endif
+
+	/** The types of XML nodes supported by TinyXml. (All the
+			unsupported types are picked up by UNKNOWN.)
+	*/
+	enum NodeType
+	{
+		DOCUMENT,
+		ELEMENT,
+		COMMENT,
+		UNKNOWN,
+		TEXT,
+		DECLARATION,
+		TYPECOUNT
+	};
+
+	virtual ~TiXmlNode();
+
+	/** The meaning of 'value' changes for the specific type of
+		TiXmlNode.
+		@verbatim
+		Document:	filename of the xml file
+		Element:	name of the element
+		Comment:	the comment text
+		Unknown:	the tag contents
+		Text:		the text string
+		@endverbatim
+
+		The subclasses will wrap this function.
+	*/
+	const char *Value() const { return value.c_str (); }
+
+    #ifdef TIXML_USE_STL
+	/** Return Value() as a std::string. If you only use STL,
+	    this is more efficient than calling Value().
+		Only available in STL mode.
+	*/
+	const std::string& ValueStr() const { return value; }
+	#endif
+
+	const TIXML_STRING& ValueTStr() const { return value; }
+
+	/** Changes the value of the node. Defined as:
+		@verbatim
+		Document:	filename of the xml file
+		Element:	name of the element
+		Comment:	the comment text
+		Unknown:	the tag contents
+		Text:		the text string
+		@endverbatim
+	*/
+	void SetValue(const char * _value) { value = _value;}
+
+    #ifdef TIXML_USE_STL
+	/// STL std::string form.
+	void SetValue( const std::string& _value )	{ value = _value; }
+	#endif
+
+	/// Delete all the children of this node. Does not affect 'this'.
+	void Clear();
+
+	/// One step up the DOM.
+	TiXmlNode* Parent()							{ return parent; }
+	const TiXmlNode* Parent() const				{ return parent; }
+
+	const TiXmlNode* FirstChild()	const		{ return firstChild; }	///< The first child of this node. Will be null if there are no children.
+	TiXmlNode* FirstChild()						{ return firstChild; }
+	const TiXmlNode* FirstChild( const char * value ) const;			///< The first child of this node with the matching 'value'. Will be null if none found.
+	/// The first child of this node with the matching 'value'. Will be null if none found.
+	TiXmlNode* FirstChild( const char * _value ) {
+		// Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe)
+		// call the method, cast the return back to non-const.
+		return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value ));
+	}
+	const TiXmlNode* LastChild() const	{ return lastChild; }		/// The last child of this node. Will be null if there are no children.
+	TiXmlNode* LastChild()	{ return lastChild; }
+	
+	const TiXmlNode* LastChild( const char * value ) const;			/// The last child of this node matching 'value'. Will be null if there are no children.
+	TiXmlNode* LastChild( const char * _value ) {
+		return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value ));
+	}
+
+    #ifdef TIXML_USE_STL
+	const TiXmlNode* FirstChild( const std::string& _value ) const	{	return FirstChild (_value.c_str ());	}	///< STL std::string form.
+	TiXmlNode* FirstChild( const std::string& _value )				{	return FirstChild (_value.c_str ());	}	///< STL std::string form.
+	const TiXmlNode* LastChild( const std::string& _value ) const	{	return LastChild (_value.c_str ());	}	///< STL std::string form.
+	TiXmlNode* LastChild( const std::string& _value )				{	return LastChild (_value.c_str ());	}	///< STL std::string form.
+	#endif
+
+	/** An alternate way to walk the children of a node.
+		One way to iterate over nodes is:
+		@verbatim
+			for( child = parent->FirstChild(); child; child = child->NextSibling() )
+		@endverbatim
+
+		IterateChildren does the same thing with the syntax:
+		@verbatim
+			child = 0;
+			while( child = parent->IterateChildren( child ) )
+		@endverbatim
+
+		IterateChildren takes the previous child as input and finds
+		the next one. If the previous child is null, it returns the
+		first. IterateChildren will return null when done.
+	*/
+	const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const;
+	TiXmlNode* IterateChildren( const TiXmlNode* previous ) {
+		return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) );
+	}
+
+	/// This flavor of IterateChildren searches for children with a particular 'value'
+	const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const;
+	TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) {
+		return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) );
+	}
+
+    #ifdef TIXML_USE_STL
+	const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const	{	return IterateChildren (_value.c_str (), previous);	}	///< STL std::string form.
+	TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) {	return IterateChildren (_value.c_str (), previous);	}	///< STL std::string form.
+	#endif
+
+	/** Add a new node related to this. Adds a child past the LastChild.
+		Returns a pointer to the new object or NULL if an error occured.
+	*/
+	TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
+
+
+	/** Add a new node related to this. Adds a child past the LastChild.
+
+		NOTE: the node to be added is passed by pointer, and will be
+		henceforth owned (and deleted) by tinyXml. This method is efficient
+		and avoids an extra copy, but should be used with care as it
+		uses a different memory model than the other insert functions.
+
+		@sa InsertEndChild
+	*/
+	TiXmlNode* LinkEndChild( TiXmlNode* addThis );
+
+	/** Add a new node related to this. Adds a child before the specified child.
+		Returns a pointer to the new object or NULL if an error occured.
+	*/
+	TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
+
+	/** Add a new node related to this. Adds a child after the specified child.
+		Returns a pointer to the new object or NULL if an error occured.
+	*/
+	TiXmlNode* InsertAfterChild(  TiXmlNode* afterThis, const TiXmlNode& addThis );
+
+	/** Replace a child of this node.
+		Returns a pointer to the new object or NULL if an error occured.
+	*/
+	TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
+
+	/// Delete a child of this node.
+	bool RemoveChild( TiXmlNode* removeThis );
+
+	/// Navigate to a sibling node.
+	const TiXmlNode* PreviousSibling() const			{ return prev; }
+	TiXmlNode* PreviousSibling()						{ return prev; }
+
+	/// Navigate to a sibling node.
+	const TiXmlNode* PreviousSibling( const char * ) const;
+	TiXmlNode* PreviousSibling( const char *_prev ) {
+		return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) );
+	}
+
+    #ifdef TIXML_USE_STL
+	const TiXmlNode* PreviousSibling( const std::string& _value ) const	{	return PreviousSibling (_value.c_str ());	}	///< STL std::string form.
+	TiXmlNode* PreviousSibling( const std::string& _value ) 			{	return PreviousSibling (_value.c_str ());	}	///< STL std::string form.
+	const TiXmlNode* NextSibling( const std::string& _value) const		{	return NextSibling (_value.c_str ());	}	///< STL std::string form.
+	TiXmlNode* NextSibling( const std::string& _value) 					{	return NextSibling (_value.c_str ());	}	///< STL std::string form.
+	#endif
+
+	/// Navigate to a sibling node.
+	const TiXmlNode* NextSibling() const				{ return next; }
+	TiXmlNode* NextSibling()							{ return next; }
+
+	/// Navigate to a sibling node with the given 'value'.
+	const TiXmlNode* NextSibling( const char * ) const;
+	TiXmlNode* NextSibling( const char* _next ) {
+		return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) );
+	}
+
+	/** Convenience function to get through elements.
+		Calls NextSibling and ToElement. Will skip all non-Element
+		nodes. Returns 0 if there is not another element.
+	*/
+	const TiXmlElement* NextSiblingElement() const;
+	TiXmlElement* NextSiblingElement() {
+		return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() );
+	}
+
+	/** Convenience function to get through elements.
+		Calls NextSibling and ToElement. Will skip all non-Element
+		nodes. Returns 0 if there is not another element.
+	*/
+	const TiXmlElement* NextSiblingElement( const char * ) const;
+	TiXmlElement* NextSiblingElement( const char *_next ) {
+		return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) );
+	}
+
+    #ifdef TIXML_USE_STL
+	const TiXmlElement* NextSiblingElement( const std::string& _value) const	{	return NextSiblingElement (_value.c_str ());	}	///< STL std::string form.
+	TiXmlElement* NextSiblingElement( const std::string& _value)				{	return NextSiblingElement (_value.c_str ());	}	///< STL std::string form.
+	#endif
+
+	/// Convenience function to get through elements.
+	const TiXmlElement* FirstChildElement()	const;
+	TiXmlElement* FirstChildElement() {
+		return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() );
+	}
+
+	/// Convenience function to get through elements.
+	const TiXmlElement* FirstChildElement( const char * _value ) const;
+	TiXmlElement* FirstChildElement( const char * _value ) {
+		return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) );
+	}
+
+    #ifdef TIXML_USE_STL
+	const TiXmlElement* FirstChildElement( const std::string& _value ) const	{	return FirstChildElement (_value.c_str ());	}	///< STL std::string form.
+	TiXmlElement* FirstChildElement( const std::string& _value )				{	return FirstChildElement (_value.c_str ());	}	///< STL std::string form.
+	#endif
+
+	/** Query the type (as an enumerated value, above) of this node.
+		The possible types are: DOCUMENT, ELEMENT, COMMENT,
+								UNKNOWN, TEXT, and DECLARATION.
+	*/
+	int Type() const	{ return type; }
+
+	/** Return a pointer to the Document this node lives in.
+		Returns null if not in a document.
+	*/
+	const TiXmlDocument* GetDocument() const;
+	TiXmlDocument* GetDocument() {
+		return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() );
+	}
+
+	/// Returns true if this node has no children.
+	bool NoChildren() const						{ return !firstChild; }
+
+	virtual const TiXmlDocument*    ToDocument()    const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual const TiXmlElement*     ToElement()     const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual const TiXmlComment*     ToComment()     const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual const TiXmlUnknown*     ToUnknown()     const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual const TiXmlText*        ToText()        const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+
+	virtual TiXmlDocument*          ToDocument()    { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual TiXmlElement*           ToElement()	    { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual TiXmlComment*           ToComment()     { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual TiXmlUnknown*           ToUnknown()	    { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual TiXmlText*	            ToText()        { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual TiXmlDeclaration*       ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+
+	/** Create an exact duplicate of this node and return it. The memory must be deleted
+		by the caller. 
+	*/
+	virtual TiXmlNode* Clone() const = 0;
+
+	/** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the 
+		XML tree will be conditionally visited and the host will be called back
+		via the TiXmlVisitor interface.
+
+		This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
+		the XML for the callbacks, so the performance of TinyXML is unchanged by using this
+		interface versus any other.)
+
+		The interface has been based on ideas from:
+
+		- http://www.saxproject.org/
+		- http://c2.com/cgi/wiki?HierarchicalVisitorPattern 
+
+		Which are both good references for "visiting".
+
+		An example of using Accept():
+		@verbatim
+		TiXmlPrinter printer;
+		tinyxmlDoc.Accept( &printer );
+		const char* xmlcstr = printer.CStr();
+		@endverbatim
+	*/
+	virtual bool Accept( TiXmlVisitor* visitor ) const = 0;
+
+protected:
+	TiXmlNode( NodeType _type );
+
+	// Copy to the allocated object. Shared functionality between Clone, Copy constructor,
+	// and the assignment operator.
+	void CopyTo( TiXmlNode* target ) const;
+
+	#ifdef TIXML_USE_STL
+	    // The real work of the input operator.
+	virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0;
+	#endif
+
+	// Figure out what is at *p, and parse it. Returns null if it is not an xml node.
+	TiXmlNode* Identify( const char* start, TiXmlEncoding encoding );
+
+	TiXmlNode*		parent;
+	NodeType		type;
+
+	TiXmlNode*		firstChild;
+	TiXmlNode*		lastChild;
+
+	TIXML_STRING	value;
+
+	TiXmlNode*		prev;
+	TiXmlNode*		next;
+
+private:
+	TiXmlNode( const TiXmlNode& );				// not implemented.
+	void operator=( const TiXmlNode& base );	// not allowed.
+};
+
+
+/** An attribute is a name-value pair. Elements have an arbitrary
+	number of attributes, each with a unique name.
+
+	@note The attributes are not TiXmlNodes, since they are not
+		  part of the tinyXML document object model. There are other
+		  suggested ways to look at this problem.
+*/
+class TiXmlAttribute : public TiXmlBase
+{
+	friend class TiXmlAttributeSet;
+
+public:
+	/// Construct an empty attribute.
+	TiXmlAttribute() : TiXmlBase()
+	{
+		document = 0;
+		prev = next = 0;
+	}
+
+	#ifdef TIXML_USE_STL
+	/// std::string constructor.
+	TiXmlAttribute( const std::string& _name, const std::string& _value )
+	{
+		name = _name;
+		value = _value;
+		document = 0;
+		prev = next = 0;
+	}
+	#endif
+
+	/// Construct an attribute with a name and value.
+	TiXmlAttribute( const char * _name, const char * _value )
+	{
+		name = _name;
+		value = _value;
+		document = 0;
+		prev = next = 0;
+	}
+
+	const char*		Name()  const		{ return name.c_str(); }		///< Return the name of this attribute.
+	const char*		Value() const		{ return value.c_str(); }		///< Return the value of this attribute.
+	#ifdef TIXML_USE_STL
+	const std::string& ValueStr() const	{ return value; }				///< Return the value of this attribute.
+	#endif
+	int				IntValue() const;									///< Return the value of this attribute, converted to an integer.
+	double			DoubleValue() const;								///< Return the value of this attribute, converted to a double.
+
+	// Get the tinyxml string representation
+	const TIXML_STRING& NameTStr() const { return name; }
+
+	/** QueryIntValue examines the value string. It is an alternative to the
+		IntValue() method with richer error checking.
+		If the value is an integer, it is stored in 'value' and 
+		the call returns TIXML_SUCCESS. If it is not
+		an integer, it returns TIXML_WRONG_TYPE.
+
+		A specialized but useful call. Note that for success it returns 0,
+		which is the opposite of almost all other TinyXml calls.
+	*/
+	int QueryIntValue( int* _value ) const;
+	/// QueryDoubleValue examines the value string. See QueryIntValue().
+	int QueryDoubleValue( double* _value ) const;
+
+	void SetName( const char* _name )	{ name = _name; }				///< Set the name of this attribute.
+	void SetValue( const char* _value )	{ value = _value; }				///< Set the value.
+
+	void SetIntValue( int _value );										///< Set the value from an integer.
+	void SetDoubleValue( double _value );								///< Set the value from a double.
+
+    #ifdef TIXML_USE_STL
+	/// STL std::string form.
+	void SetName( const std::string& _name )	{ name = _name; }	
+	/// STL std::string form.	
+	void SetValue( const std::string& _value )	{ value = _value; }
+	#endif
+
+	/// Get the next sibling attribute in the DOM. Returns null at end.
+	const TiXmlAttribute* Next() const;
+	TiXmlAttribute* Next() {
+		return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); 
+	}
+
+	/// Get the previous sibling attribute in the DOM. Returns null at beginning.
+	const TiXmlAttribute* Previous() const;
+	TiXmlAttribute* Previous() {
+		return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); 
+	}
+
+	bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
+	bool operator<( const TiXmlAttribute& rhs )	 const { return name < rhs.name; }
+	bool operator>( const TiXmlAttribute& rhs )  const { return name > rhs.name; }
+
+	/*	Attribute parsing starts: first letter of the name
+						 returns: the next char after the value end quote
+	*/
+	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+	// Prints this Attribute to a FILE stream.
+	virtual void Print( FILE* cfile, int depth ) const {
+		Print( cfile, depth, 0 );
+	}
+	void Print( FILE* cfile, int depth, TIXML_STRING* str ) const;
+
+	// [internal use]
+	// Set the document pointer so the attribute can report errors.
+	void SetDocument( TiXmlDocument* doc )	{ document = doc; }
+
+private:
+	TiXmlAttribute( const TiXmlAttribute& );				// not implemented.
+	void operator=( const TiXmlAttribute& base );	// not allowed.
+
+	TiXmlDocument*	document;	// A pointer back to a document, for error reporting.
+	TIXML_STRING name;
+	TIXML_STRING value;
+	TiXmlAttribute*	prev;
+	TiXmlAttribute*	next;
+};
+
+
+/*	A class used to manage a group of attributes.
+	It is only used internally, both by the ELEMENT and the DECLARATION.
+	
+	The set can be changed transparent to the Element and Declaration
+	classes that use it, but NOT transparent to the Attribute
+	which has to implement a next() and previous() method. Which makes
+	it a bit problematic and prevents the use of STL.
+
+	This version is implemented with circular lists because:
+		- I like circular lists
+		- it demonstrates some independence from the (typical) doubly linked list.
+*/
+class TiXmlAttributeSet
+{
+public:
+	TiXmlAttributeSet();
+	~TiXmlAttributeSet();
+
+	void Add( TiXmlAttribute* attribute );
+	void Remove( TiXmlAttribute* attribute );
+
+	const TiXmlAttribute* First()	const	{ return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
+	TiXmlAttribute* First()					{ return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
+	const TiXmlAttribute* Last() const		{ return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
+	TiXmlAttribute* Last()					{ return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
+
+	const TiXmlAttribute*	Find( const char* _name ) const;
+	TiXmlAttribute*	Find( const char* _name ) {
+		return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) );
+	}
+	#ifdef TIXML_USE_STL
+	const TiXmlAttribute*	Find( const std::string& _name ) const;
+	TiXmlAttribute*	Find( const std::string& _name ) {
+		return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) );
+	}
+
+	#endif
+
+private:
+	//*ME:	Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element),
+	//*ME:	this class must be also use a hidden/disabled copy-constructor !!!
+	TiXmlAttributeSet( const TiXmlAttributeSet& );	// not allowed
+	void operator=( const TiXmlAttributeSet& );	// not allowed (as TiXmlAttribute)
+
+	TiXmlAttribute sentinel;
+};
+
+
+/** The element is a container class. It has a value, the element name,
+	and can contain other elements, text, comments, and unknowns.
+	Elements also contain an arbitrary number of attributes.
+*/
+class TiXmlElement : public TiXmlNode
+{
+public:
+	/// Construct an element.
+	TiXmlElement (const char * in_value);
+
+	#ifdef TIXML_USE_STL
+	/// std::string constructor.
+	TiXmlElement( const std::string& _value );
+	#endif
+
+	TiXmlElement( const TiXmlElement& );
+
+	void operator=( const TiXmlElement& base );
+
+	virtual ~TiXmlElement();
+
+	/** Given an attribute name, Attribute() returns the value
+		for the attribute of that name, or null if none exists.
+	*/
+	const char* Attribute( const char* name ) const;
+
+	/** Given an attribute name, Attribute() returns the value
+		for the attribute of that name, or null if none exists.
+		If the attribute exists and can be converted to an integer,
+		the integer value will be put in the return 'i', if 'i'
+		is non-null.
+	*/
+	const char* Attribute( const char* name, int* i ) const;
+
+	/** Given an attribute name, Attribute() returns the value
+		for the attribute of that name, or null if none exists.
+		If the attribute exists and can be converted to an double,
+		the double value will be put in the return 'd', if 'd'
+		is non-null.
+	*/
+	const char* Attribute( const char* name, double* d ) const;
+
+	/** QueryIntAttribute examines the attribute - it is an alternative to the
+		Attribute() method with richer error checking.
+		If the attribute is an integer, it is stored in 'value' and 
+		the call returns TIXML_SUCCESS. If it is not
+		an integer, it returns TIXML_WRONG_TYPE. If the attribute
+		does not exist, then TIXML_NO_ATTRIBUTE is returned.
+	*/	
+	int QueryIntAttribute( const char* name, int* _value ) const;
+	/// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
+	int QueryDoubleAttribute( const char* name, double* _value ) const;
+	/// QueryFloatAttribute examines the attribute - see QueryIntAttribute().
+	int QueryFloatAttribute( const char* name, float* _value ) const {
+		double d;
+		int result = QueryDoubleAttribute( name, &d );
+		if ( result == TIXML_SUCCESS ) {
+			*_value = (float)d;
+		}
+		return result;
+	}
+
+    #ifdef TIXML_USE_STL
+	/** Template form of the attribute query which will try to read the
+		attribute into the specified type. Very easy, very powerful, but
+		be careful to make sure to call this with the correct type.
+		
+		NOTE: This method doesn't work correctly for 'string' types.
+
+		@return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE
+	*/
+	template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const
+	{
+		const TiXmlAttribute* node = attributeSet.Find( name );
+		if ( !node )
+			return TIXML_NO_ATTRIBUTE;
+
+		std::stringstream sstream( node->ValueStr() );
+		sstream >> *outValue;
+		if ( !sstream.fail() )
+			return TIXML_SUCCESS;
+		return TIXML_WRONG_TYPE;
+	}
+	/*
+	 This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string"
+	 but template specialization is hard to get working cross-compiler. Leaving the bug for now.
+	 
+	// The above will fail for std::string because the space character is used as a seperator.
+	// Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string
+	template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const
+	{
+		const TiXmlAttribute* node = attributeSet.Find( name );
+		if ( !node )
+			return TIXML_NO_ATTRIBUTE;
+		*outValue = node->ValueStr();
+		return TIXML_SUCCESS;
+	}
+	*/
+	#endif
+
+	/** Sets an attribute of name to a given value. The attribute
+		will be created if it does not exist, or changed if it does.
+	*/
+	void SetAttribute( const char* name, const char * _value );
+
+    #ifdef TIXML_USE_STL
+	const std::string* Attribute( const std::string& name ) const;
+	const std::string* Attribute( const std::string& name, int* i ) const;
+	const std::string* Attribute( const std::string& name, double* d ) const;
+	int QueryIntAttribute( const std::string& name, int* _value ) const;
+	int QueryDoubleAttribute( const std::string& name, double* _value ) const;
+
+	/// STL std::string form.
+	void SetAttribute( const std::string& name, const std::string& _value );
+	///< STL std::string form.
+	void SetAttribute( const std::string& name, int _value );
+	#endif
+
+	/** Sets an attribute of name to a given value. The attribute
+		will be created if it does not exist, or changed if it does.
+	*/
+	void SetAttribute( const char * name, int value );
+
+	/** Sets an attribute of name to a given value. The attribute
+		will be created if it does not exist, or changed if it does.
+	*/
+	void SetDoubleAttribute( const char * name, double value );
+
+	/** Deletes an attribute with the given name.
+	*/
+	void RemoveAttribute( const char * name );
+    #ifdef TIXML_USE_STL
+	void RemoveAttribute( const std::string& name )	{	RemoveAttribute (name.c_str ());	}	///< STL std::string form.
+	#endif
+
+	const TiXmlAttribute* FirstAttribute() const	{ return attributeSet.First(); }		///< Access the first attribute in this element.
+	TiXmlAttribute* FirstAttribute() 				{ return attributeSet.First(); }
+	const TiXmlAttribute* LastAttribute()	const 	{ return attributeSet.Last(); }		///< Access the last attribute in this element.
+	TiXmlAttribute* LastAttribute()					{ return attributeSet.Last(); }
+
+	/** Convenience function for easy access to the text inside an element. Although easy
+		and concise, GetText() is limited compared to getting the TiXmlText child
+		and accessing it directly.
+	
+		If the first child of 'this' is a TiXmlText, the GetText()
+		returns the character string of the Text node, else null is returned.
+
+		This is a convenient method for getting the text of simple contained text:
+		@verbatim
+		<foo>This is text</foo>
+		const char* str = fooElement->GetText();
+		@endverbatim
+
+		'str' will be a pointer to "This is text". 
+		
+		Note that this function can be misleading. If the element foo was created from
+		this XML:
+		@verbatim
+		<foo><b>This is text</b></foo> 
+		@endverbatim
+
+		then the value of str would be null. The first child node isn't a text node, it is
+		another element. From this XML:
+		@verbatim
+		<foo>This is <b>text</b></foo> 
+		@endverbatim
+		GetText() will return "This is ".
+
+		WARNING: GetText() accesses a child node - don't become confused with the 
+				 similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are 
+				 safe type casts on the referenced node.
+	*/
+	const char* GetText() const;
+
+	/// Creates a new Element and returns it - the returned element is a copy.
+	virtual TiXmlNode* Clone() const;
+	// Print the Element to a FILE stream.
+	virtual void Print( FILE* cfile, int depth ) const;
+
+	/*	Attribtue parsing starts: next char past '<'
+						 returns: next char past '>'
+	*/
+	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+	virtual const TiXmlElement*     ToElement()     const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+	virtual TiXmlElement*           ToElement()	          { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	/** Walk the XML tree visiting this node and all of its children. 
+	*/
+	virtual bool Accept( TiXmlVisitor* visitor ) const;
+
+protected:
+
+	void CopyTo( TiXmlElement* target ) const;
+	void ClearThis();	// like clear, but initializes 'this' object as well
+
+	// Used to be public [internal use]
+	#ifdef TIXML_USE_STL
+	virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+	#endif
+	/*	[internal use]
+		Reads the "value" of the element -- another element, or text.
+		This should terminate with the current end tag.
+	*/
+	const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding );
+
+private:
+
+	TiXmlAttributeSet attributeSet;
+};
+
+
+/**	An XML comment.
+*/
+class TiXmlComment : public TiXmlNode
+{
+public:
+	/// Constructs an empty comment.
+	TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
+	/// Construct a comment from text.
+	TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) {
+		SetValue( _value );
+	}
+	TiXmlComment( const TiXmlComment& );
+	void operator=( const TiXmlComment& base );
+
+	virtual ~TiXmlComment()	{}
+
+	/// Returns a copy of this Comment.
+	virtual TiXmlNode* Clone() const;
+	// Write this Comment to a FILE stream.
+	virtual void Print( FILE* cfile, int depth ) const;
+
+	/*	Attribtue parsing starts: at the ! of the !--
+						 returns: next char past '>'
+	*/
+	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+	virtual const TiXmlComment*  ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+	virtual TiXmlComment*  ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	/** Walk the XML tree visiting this node and all of its children. 
+	*/
+	virtual bool Accept( TiXmlVisitor* visitor ) const;
+
+protected:
+	void CopyTo( TiXmlComment* target ) const;
+
+	// used to be public
+	#ifdef TIXML_USE_STL
+	virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+	#endif
+//	virtual void StreamOut( TIXML_OSTREAM * out ) const;
+
+private:
+
+};
+
+
+/** XML text. A text node can have 2 ways to output the next. "normal" output 
+	and CDATA. It will default to the mode it was parsed from the XML file and
+	you generally want to leave it alone, but you can change the output mode with 
+	SetCDATA() and query it with CDATA().
+*/
+class TiXmlText : public TiXmlNode
+{
+	friend class TiXmlElement;
+public:
+	/** Constructor for text element. By default, it is treated as 
+		normal, encoded text. If you want it be output as a CDATA text
+		element, set the parameter _cdata to 'true'
+	*/
+	TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT)
+	{
+		SetValue( initValue );
+		cdata = false;
+	}
+	virtual ~TiXmlText() {}
+
+	#ifdef TIXML_USE_STL
+	/// Constructor.
+	TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
+	{
+		SetValue( initValue );
+		cdata = false;
+	}
+	#endif
+
+	TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT )	{ copy.CopyTo( this ); }
+	void operator=( const TiXmlText& base )							 	{ base.CopyTo( this ); }
+
+	// Write this text object to a FILE stream.
+	virtual void Print( FILE* cfile, int depth ) const;
+
+	/// Queries whether this represents text using a CDATA section.
+	bool CDATA() const				{ return cdata; }
+	/// Turns on or off a CDATA representation of text.
+	void SetCDATA( bool _cdata )	{ cdata = _cdata; }
+
+	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+	virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+	virtual TiXmlText*       ToText()       { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	/** Walk the XML tree visiting this node and all of its children. 
+	*/
+	virtual bool Accept( TiXmlVisitor* content ) const;
+
+protected :
+	///  [internal use] Creates a new Element and returns it.
+	virtual TiXmlNode* Clone() const;
+	void CopyTo( TiXmlText* target ) const;
+
+	bool Blank() const;	// returns true if all white space and new lines
+	// [internal use]
+	#ifdef TIXML_USE_STL
+	virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+	#endif
+
+private:
+	bool cdata;			// true if this should be input and output as a CDATA style text element
+};
+
+
+/** In correct XML the declaration is the first entry in the file.
+	@verbatim
+		<?xml version="1.0" standalone="yes"?>
+	@endverbatim
+
+	TinyXml will happily read or write files without a declaration,
+	however. There are 3 possible attributes to the declaration:
+	version, encoding, and standalone.
+
+	Note: In this version of the code, the attributes are
+	handled as special cases, not generic attributes, simply
+	because there can only be at most 3 and they are always the same.
+*/
+class TiXmlDeclaration : public TiXmlNode
+{
+public:
+	/// Construct an empty declaration.
+	TiXmlDeclaration()   : TiXmlNode( TiXmlNode::DECLARATION ) {}
+
+#ifdef TIXML_USE_STL
+	/// Constructor.
+	TiXmlDeclaration(	const std::string& _version,
+						const std::string& _encoding,
+						const std::string& _standalone );
+#endif
+
+	/// Construct.
+	TiXmlDeclaration(	const char* _version,
+						const char* _encoding,
+						const char* _standalone );
+
+	TiXmlDeclaration( const TiXmlDeclaration& copy );
+	void operator=( const TiXmlDeclaration& copy );
+
+	virtual ~TiXmlDeclaration()	{}
+
+	/// Version. Will return an empty string if none was found.
+	const char *Version() const			{ return version.c_str (); }
+	/// Encoding. Will return an empty string if none was found.
+	const char *Encoding() const		{ return encoding.c_str (); }
+	/// Is this a standalone document?
+	const char *Standalone() const		{ return standalone.c_str (); }
+
+	/// Creates a copy of this Declaration and returns it.
+	virtual TiXmlNode* Clone() const;
+	// Print this declaration to a FILE stream.
+	virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const;
+	virtual void Print( FILE* cfile, int depth ) const {
+		Print( cfile, depth, 0 );
+	}
+
+	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+	virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+	virtual TiXmlDeclaration*       ToDeclaration()       { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	/** Walk the XML tree visiting this node and all of its children. 
+	*/
+	virtual bool Accept( TiXmlVisitor* visitor ) const;
+
+protected:
+	void CopyTo( TiXmlDeclaration* target ) const;
+	// used to be public
+	#ifdef TIXML_USE_STL
+	virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+	#endif
+
+private:
+
+	TIXML_STRING version;
+	TIXML_STRING encoding;
+	TIXML_STRING standalone;
+};
+
+
+/** Any tag that tinyXml doesn't recognize is saved as an
+	unknown. It is a tag of text, but should not be modified.
+	It will be written back to the XML, unchanged, when the file
+	is saved.
+
+	DTD tags get thrown into TiXmlUnknowns.
+*/
+class TiXmlUnknown : public TiXmlNode
+{
+public:
+	TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN )	{}
+	virtual ~TiXmlUnknown() {}
+
+	TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN )		{ copy.CopyTo( this ); }
+	void operator=( const TiXmlUnknown& copy )										{ copy.CopyTo( this ); }
+
+	/// Creates a copy of this Unknown and returns it.
+	virtual TiXmlNode* Clone() const;
+	// Print this Unknown to a FILE stream.
+	virtual void Print( FILE* cfile, int depth ) const;
+
+	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+	virtual const TiXmlUnknown*     ToUnknown()     const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+	virtual TiXmlUnknown*           ToUnknown()	    { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	/** Walk the XML tree visiting this node and all of its children. 
+	*/
+	virtual bool Accept( TiXmlVisitor* content ) const;
+
+protected:
+	void CopyTo( TiXmlUnknown* target ) const;
+
+	#ifdef TIXML_USE_STL
+	virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+	#endif
+
+private:
+
+};
+
+
+/** Always the top level node. A document binds together all the
+	XML pieces. It can be saved, loaded, and printed to the screen.
+	The 'value' of a document node is the xml file name.
+*/
+class TiXmlDocument : public TiXmlNode
+{
+public:
+	/// Create an empty document, that has no name.
+	TiXmlDocument();
+	/// Create a document with a name. The name of the document is also the filename of the xml.
+	TiXmlDocument( const char * documentName );
+
+	#ifdef TIXML_USE_STL
+	/// Constructor.
+	TiXmlDocument( const std::string& documentName );
+	#endif
+
+	TiXmlDocument( const TiXmlDocument& copy );
+	void operator=( const TiXmlDocument& copy );
+
+	virtual ~TiXmlDocument() {}
+
+	/** Load a file using the current document value.
+		Returns true if successful. Will delete any existing
+		document data before loading.
+	*/
+	bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+	/// Save a file using the current document value. Returns true if successful.
+	bool SaveFile() const;
+	/// Load a file using the given filename. Returns true if successful.
+	bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+	/// Save a file using the given filename. Returns true if successful.
+	bool SaveFile( const char * filename ) const;
+	/** Load a file using the given FILE*. Returns true if successful. Note that this method
+		doesn't stream - the entire object pointed at by the FILE*
+		will be interpreted as an XML file. TinyXML doesn't stream in XML from the current
+		file location. Streaming may be added in the future.
+	*/
+	bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+	/// Save a file using the given FILE*. Returns true if successful.
+	bool SaveFile( FILE* ) const;
+
+	#ifdef TIXML_USE_STL
+	bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING )			///< STL std::string version.
+	{
+//		StringToBuffer f( filename );
+//		return ( f.buffer && LoadFile( f.buffer, encoding ));
+		return LoadFile( filename.c_str(), encoding );
+	}
+	bool SaveFile( const std::string& filename ) const		///< STL std::string version.
+	{
+//		StringToBuffer f( filename );
+//		return ( f.buffer && SaveFile( f.buffer ));
+		return SaveFile( filename.c_str() );
+	}
+	#endif
+
+	/** Parse the given null terminated block of xml data. Passing in an encoding to this
+		method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml
+		to use that encoding, regardless of what TinyXml might otherwise try to detect.
+	*/
+	virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+
+	/** Get the root element -- the only top level element -- of the document.
+		In well formed XML, there should only be one. TinyXml is tolerant of
+		multiple elements at the document level.
+	*/
+	const TiXmlElement* RootElement() const		{ return FirstChildElement(); }
+	TiXmlElement* RootElement()					{ return FirstChildElement(); }
+
+	/** If an error occurs, Error will be set to true. Also,
+		- The ErrorId() will contain the integer identifier of the error (not generally useful)
+		- The ErrorDesc() method will return the name of the error. (very useful)
+		- The ErrorRow() and ErrorCol() will return the location of the error (if known)
+	*/	
+	bool Error() const						{ return error; }
+
+	/// Contains a textual (english) description of the error if one occurs.
+	const char * ErrorDesc() const	{ return errorDesc.c_str (); }
+
+	/** Generally, you probably want the error string ( ErrorDesc() ). But if you
+		prefer the ErrorId, this function will fetch it.
+	*/
+	int ErrorId()	const				{ return errorId; }
+
+	/** Returns the location (if known) of the error. The first column is column 1, 
+		and the first row is row 1. A value of 0 means the row and column wasn't applicable
+		(memory errors, for example, have no row/column) or the parser lost the error. (An
+		error in the error reporting, in that case.)
+
+		@sa SetTabSize, Row, Column
+	*/
+	int ErrorRow() const	{ return errorLocation.row+1; }
+	int ErrorCol() const	{ return errorLocation.col+1; }	///< The column where the error occured. See ErrorRow()
+
+	/** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol())
+		to report the correct values for row and column. It does not change the output
+		or input in any way.
+		
+		By calling this method, with a tab size
+		greater than 0, the row and column of each node and attribute is stored
+		when the file is loaded. Very useful for tracking the DOM back in to
+		the source file.
+
+		The tab size is required for calculating the location of nodes. If not
+		set, the default of 4 is used. The tabsize is set per document. Setting
+		the tabsize to 0 disables row/column tracking.
+
+		Note that row and column tracking is not supported when using operator>>.
+
+		The tab size needs to be enabled before the parse or load. Correct usage:
+		@verbatim
+		TiXmlDocument doc;
+		doc.SetTabSize( 8 );
+		doc.Load( "myfile.xml" );
+		@endverbatim
+
+		@sa Row, Column
+	*/
+	void SetTabSize( int _tabsize )		{ tabsize = _tabsize; }
+
+	int TabSize() const	{ return tabsize; }
+
+	/** If you have handled the error, it can be reset with this call. The error
+		state is automatically cleared if you Parse a new XML block.
+	*/
+	void ClearError()						{	error = false; 
+												errorId = 0; 
+												errorDesc = ""; 
+												errorLocation.row = errorLocation.col = 0; 
+												//errorLocation.last = 0; 
+											}
+
+	/** Write the document to standard out using formatted printing ("pretty print"). */
+	void Print() const						{ Print( stdout, 0 ); }
+
+	/* Write the document to a string using formatted printing ("pretty print"). This
+		will allocate a character array (new char[]) and return it as a pointer. The
+		calling code pust call delete[] on the return char* to avoid a memory leak.
+	*/
+	//char* PrintToMemory() const; 
+
+	/// Print this Document to a FILE stream.
+	virtual void Print( FILE* cfile, int depth = 0 ) const;
+	// [internal use]
+	void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding );
+
+	virtual const TiXmlDocument*    ToDocument()    const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+	virtual TiXmlDocument*          ToDocument()          { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	/** Walk the XML tree visiting this node and all of its children. 
+	*/
+	virtual bool Accept( TiXmlVisitor* content ) const;
+
+protected :
+	// [internal use]
+	virtual TiXmlNode* Clone() const;
+	#ifdef TIXML_USE_STL
+	virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+	#endif
+
+private:
+	void CopyTo( TiXmlDocument* target ) const;
+
+	bool error;
+	int  errorId;
+	TIXML_STRING errorDesc;
+	int tabsize;
+	TiXmlCursor errorLocation;
+	bool useMicrosoftBOM;		// the UTF-8 BOM were found when read. Note this, and try to write.
+};
+
+
+/**
+	A TiXmlHandle is a class that wraps a node pointer with null checks; this is
+	an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml
+	DOM structure. It is a separate utility class.
+
+	Take an example:
+	@verbatim
+	<Document>
+		<Element attributeA = "valueA">
+			<Child attributeB = "value1" />
+			<Child attributeB = "value2" />
+		</Element>
+	<Document>
+	@endverbatim
+
+	Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very 
+	easy to write a *lot* of code that looks like:
+
+	@verbatim
+	TiXmlElement* root = document.FirstChildElement( "Document" );
+	if ( root )
+	{
+		TiXmlElement* element = root->FirstChildElement( "Element" );
+		if ( element )
+		{
+			TiXmlElement* child = element->FirstChildElement( "Child" );
+			if ( child )
+			{
+				TiXmlElement* child2 = child->NextSiblingElement( "Child" );
+				if ( child2 )
+				{
+					// Finally do something useful.
+	@endverbatim
+
+	And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity
+	of such code. A TiXmlHandle checks for null	pointers so it is perfectly safe 
+	and correct to use:
+
+	@verbatim
+	TiXmlHandle docHandle( &document );
+	TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement();
+	if ( child2 )
+	{
+		// do something useful
+	@endverbatim
+
+	Which is MUCH more concise and useful.
+
+	It is also safe to copy handles - internally they are nothing more than node pointers.
+	@verbatim
+	TiXmlHandle handleCopy = handle;
+	@endverbatim
+
+	What they should not be used for is iteration:
+
+	@verbatim
+	int i=0; 
+	while ( true )
+	{
+		TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement();
+		if ( !child )
+			break;
+		// do something
+		++i;
+	}
+	@endverbatim
+
+	It seems reasonable, but it is in fact two embedded while loops. The Child method is 
+	a linear walk to find the element, so this code would iterate much more than it needs 
+	to. Instead, prefer:
+
+	@verbatim
+	TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement();
+
+	for( child; child; child=child->NextSiblingElement() )
+	{
+		// do something
+	}
+	@endverbatim
+*/
+class TiXmlHandle
+{
+public:
+	/// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
+	TiXmlHandle( TiXmlNode* _node )					{ this->node = _node; }
+	/// Copy constructor
+	TiXmlHandle( const TiXmlHandle& ref )			{ this->node = ref.node; }
+	TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; }
+
+	/// Return a handle to the first child node.
+	TiXmlHandle FirstChild() const;
+	/// Return a handle to the first child node with the given name.
+	TiXmlHandle FirstChild( const char * value ) const;
+	/// Return a handle to the first child element.
+	TiXmlHandle FirstChildElement() const;
+	/// Return a handle to the first child element with the given name.
+	TiXmlHandle FirstChildElement( const char * value ) const;
+
+	/** Return a handle to the "index" child with the given name. 
+		The first child is 0, the second 1, etc.
+	*/
+	TiXmlHandle Child( const char* value, int index ) const;
+	/** Return a handle to the "index" child. 
+		The first child is 0, the second 1, etc.
+	*/
+	TiXmlHandle Child( int index ) const;
+	/** Return a handle to the "index" child element with the given name. 
+		The first child element is 0, the second 1, etc. Note that only TiXmlElements
+		are indexed: other types are not counted.
+	*/
+	TiXmlHandle ChildElement( const char* value, int index ) const;
+	/** Return a handle to the "index" child element. 
+		The first child element is 0, the second 1, etc. Note that only TiXmlElements
+		are indexed: other types are not counted.
+	*/
+	TiXmlHandle ChildElement( int index ) const;
+
+	#ifdef TIXML_USE_STL
+	TiXmlHandle FirstChild( const std::string& _value ) const				{ return FirstChild( _value.c_str() ); }
+	TiXmlHandle FirstChildElement( const std::string& _value ) const		{ return FirstChildElement( _value.c_str() ); }
+
+	TiXmlHandle Child( const std::string& _value, int index ) const			{ return Child( _value.c_str(), index ); }
+	TiXmlHandle ChildElement( const std::string& _value, int index ) const	{ return ChildElement( _value.c_str(), index ); }
+	#endif
+
+	/** Return the handle as a TiXmlNode. This may return null.
+	*/
+	TiXmlNode* ToNode() const			{ return node; } 
+	/** Return the handle as a TiXmlElement. This may return null.
+	*/
+	TiXmlElement* ToElement() const		{ return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
+	/**	Return the handle as a TiXmlText. This may return null.
+	*/
+	TiXmlText* ToText() const			{ return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
+	/** Return the handle as a TiXmlUnknown. This may return null.
+	*/
+	TiXmlUnknown* ToUnknown() const		{ return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
+
+	/** @deprecated use ToNode. 
+		Return the handle as a TiXmlNode. This may return null.
+	*/
+	TiXmlNode* Node() const			{ return ToNode(); } 
+	/** @deprecated use ToElement. 
+		Return the handle as a TiXmlElement. This may return null.
+	*/
+	TiXmlElement* Element() const	{ return ToElement(); }
+	/**	@deprecated use ToText()
+		Return the handle as a TiXmlText. This may return null.
+	*/
+	TiXmlText* Text() const			{ return ToText(); }
+	/** @deprecated use ToUnknown()
+		Return the handle as a TiXmlUnknown. This may return null.
+	*/
+	TiXmlUnknown* Unknown() const	{ return ToUnknown(); }
+
+private:
+	TiXmlNode* node;
+};
+
+
+/** Print to memory functionality. The TiXmlPrinter is useful when you need to:
+
+	-# Print to memory (especially in non-STL mode)
+	-# Control formatting (line endings, etc.)
+
+	When constructed, the TiXmlPrinter is in its default "pretty printing" mode.
+	Before calling Accept() you can call methods to control the printing
+	of the XML document. After TiXmlNode::Accept() is called, the printed document can
+	be accessed via the CStr(), Str(), and Size() methods.
+
+	TiXmlPrinter uses the Visitor API.
+	@verbatim
+	TiXmlPrinter printer;
+	printer.SetIndent( "\t" );
+
+	doc.Accept( &printer );
+	fprintf( stdout, "%s", printer.CStr() );
+	@endverbatim
+*/
+class TiXmlPrinter : public TiXmlVisitor
+{
+public:
+	TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ),
+					 buffer(), indent( "    " ), lineBreak( "\n" ) {}
+
+	virtual bool VisitEnter( const TiXmlDocument& doc );
+	virtual bool VisitExit( const TiXmlDocument& doc );
+
+	virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute );
+	virtual bool VisitExit( const TiXmlElement& element );
+
+	virtual bool Visit( const TiXmlDeclaration& declaration );
+	virtual bool Visit( const TiXmlText& text );
+	virtual bool Visit( const TiXmlComment& comment );
+	virtual bool Visit( const TiXmlUnknown& unknown );
+
+	/** Set the indent characters for printing. By default 4 spaces
+		but tab (\t) is also useful, or null/empty string for no indentation.
+	*/
+	void SetIndent( const char* _indent )			{ indent = _indent ? _indent : "" ; }
+	/// Query the indention string.
+	const char* Indent()							{ return indent.c_str(); }
+	/** Set the line breaking string. By default set to newline (\n). 
+		Some operating systems prefer other characters, or can be
+		set to the null/empty string for no indenation.
+	*/
+	void SetLineBreak( const char* _lineBreak )		{ lineBreak = _lineBreak ? _lineBreak : ""; }
+	/// Query the current line breaking string.
+	const char* LineBreak()							{ return lineBreak.c_str(); }
+
+	/** Switch over to "stream printing" which is the most dense formatting without 
+		linebreaks. Common when the XML is needed for network transmission.
+	*/
+	void SetStreamPrinting()						{ indent = "";
+													  lineBreak = "";
+													}	
+	/// Return the result.
+	const char* CStr()								{ return buffer.c_str(); }
+	/// Return the length of the result string.
+	size_t Size()									{ return buffer.size(); }
+
+	#ifdef TIXML_USE_STL
+	/// Return the result.
+	const std::string& Str()						{ return buffer; }
+	#endif
+
+private:
+	void DoIndent()	{
+		for( int i=0; i<depth; ++i )
+			buffer += indent;
+	}
+	void DoLineBreak() {
+		buffer += lineBreak;
+	}
+
+	int depth;
+	bool simpleTextPrint;
+	TIXML_STRING buffer;
+	TIXML_STRING indent;
+	TIXML_STRING lineBreak;
+};
+
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+#endif
+
Index: vtcross/branches/wrodgers/src/include/Makefile.am
===================================================================
--- vtcross/branches/wrodgers/src/include/Makefile.am	(revision 161)
+++ vtcross/branches/wrodgers/src/include/Makefile.am	(revision 161)
@@ -0,0 +1,1 @@
+SUBDIRS = vtcross tinyxml
Index: vtcross/branches/wrodgers/src/lib/socketcomm/socketcomm.cpp
===================================================================
--- vtcross/branches/wrodgers/src/lib/socketcomm/socketcomm.cpp	(revision 232)
+++ vtcross/branches/wrodgers/src/lib/socketcomm/socketcomm.cpp	(revision 232)
@@ -0,0 +1,274 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * TODO LICENSE INFORMATION GOES HERE
+ */
+
+/* TODO DESCRIPTION OF FILE.
+ */
+
+
+#include <arpa/inet.h>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdint.h>
+#include <string>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "vtcross/common.h"
+#include "vtcross/containers.h"
+#include "vtcross/debug.h"
+#include "vtcross/error.h"
+#include "vtcross/socketcomm.h"
+
+
+// TODO can someone write a description of how this function is operating? I'm
+// not sure I understand why it is making two separate blocking calls to recv
+//
+// TODO also, it appears that this function can, at maximum, receive 256 bytes
+// without causing a buffer overflow. can someone confirm/deny?
+void
+ReadMessage(int32_t socketFD, char* msgBuffer)
+{
+
+    // Peek at the buffer to get real message length.
+    // Messages are termination with a "\0" to denote EOM.
+    ssize_t msgLength = recv(socketFD, msgBuffer, 256, MSG_PEEK);
+    if(msgLength < 0)
+        ERROR(1, "Error reading from socket.\n");
+    if(msgLength == 0)
+        ERROR(1, "Remote component closed connection. 1\n");
+
+    size_t i;
+    for(i = 0; i < 256; i++) {
+        if(strcmp(&msgBuffer[i], "\0") == 0)
+            break;
+    }
+
+    // Read the message into msgBuffer
+    msgLength = recv(socketFD, msgBuffer, i + 1, 0);
+    if(msgLength < 0)
+        ERROR(1, "Error reading from socket.\n");
+    if(msgLength == 0)
+        ERROR(1, "Remote component closed connection. 2\n");
+}
+
+
+int32_t 
+ClientSocket(const char* serverName, const char* serverPort)
+{
+    int32_t socketFD;
+    int32_t portNumber;
+
+    struct sockaddr_in serv_addr;
+    struct hostent *server;
+    
+    server = gethostbyname(serverName);
+    if(server == NULL)
+        ERROR(1, "No server found by that hostname.\n");
+
+    portNumber = atoi(serverPort);
+
+    socketFD = socket(AF_INET, SOCK_STREAM, 0);
+    if(socketFD < 0) 
+        ERROR(1, "Error opening socket\n");
+
+    memset((void *) &serv_addr, 0, sizeof(serv_addr));
+    serv_addr.sin_family = AF_INET;
+    serv_addr.sin_port = htons(portNumber);
+    memcpy((char *) &serv_addr.sin_addr.s_addr, (char *) server->h_addr, \
+            server->h_length);
+
+    if(connect(socketFD, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
+        ERROR(1, "Error connecting to remote socket.\n");
+
+    return socketFD;
+}
+
+    
+/* TODO I'm fairly certain this function is unnecessary, see function below for more details...
+int32_t
+SendMessage(int32_t socketFD, char* message) 
+{
+     
+    // TODO explain this. What, exactly, does the below line do and how does it
+    // affect the rest of the function?
+    strcat(message, "\0000");
+
+    ssize_t numSentBytes = send(socketFD, message, (strlen(message) + 1), 0);
+    if(numSentBytes < 0) {
+        ERROR(1, "Error sending to server.");
+    }
+    else if(numSentBytes == 0) {
+        LOG("socket_comm::SendMessage - Server closed the socket.\n");
+    }
+   
+    return numSentBytes;
+}
+*/
+
+// TODO this function is here to handle calls to send const char* messages. Note
+// that the std::string.c_str() function auto-appends a null character at the
+// end of the cstring, so the strcat function call in the previous function
+// isn't necessary here... I think... although I still don't really understand
+// what exactly that call is for.
+int32_t
+SendMessage(int32_t socketFD, const char* message) 
+{
+    ssize_t numSentBytes = send(socketFD, message, (strlen(message) + 1), 0);
+    if(numSentBytes < 0) {
+        ERROR(1, "Error sending to server %i (%i): %s\n",socketFD, numSentBytes, message);
+    }
+    else if(numSentBytes == 0) {
+        LOG("socket_comm::SendMessage - Server closed the socket.\n");
+    }
+   
+    return numSentBytes;
+}
+
+
+// TODO This function is currently returning 1... always... is this necessary?
+// If we want a fail/success return type, then why aren't we ever returning a
+// failure?
+int32_t 
+GetParameter(int32_t socketFD, struct Parameter pList[], \
+        struct Radio_Info *radio_info)
+{
+    char buffer[256];
+    memset(buffer, 0, 256);
+
+    ReadMessage(socketFD, buffer);
+    radio_info->numParameters = atoi(buffer);
+    LOG("socket_comm::GetParameter - Number of parameters: %d\n", \
+            radio_info->numParameters);
+    
+    for(size_t i = 0; i < radio_info->numParameters; i++) {
+        memset(buffer, 0, 256);
+        ReadMessage(socketFD, buffer);
+        LOG("socket_comm::GetParameter - Name: %s\n", buffer);
+        pList[i].name = std::string(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(socketFD, buffer);
+        LOG("socket_comm::GetParameter - Units: %s\n", buffer);
+        pList[i].units = std::string(buffer);
+
+        memset(buffer, 0, 256);
+        ReadMessage(socketFD, buffer);
+        LOG("socket_comm::GetParameter - Min: %s\n", buffer);
+        pList[i].min = atof(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(socketFD, buffer);
+        LOG("socket_comm::GetParameter - Max: %s\n", buffer);
+        pList[i].max = atof(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(socketFD, buffer);
+        LOG("socket_comm::GetParameter - Step: %s\n", buffer);
+        pList[i].step = atof(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(socketFD, buffer);
+        LOG("socket_comm::GetParameter - Value: %s\n", buffer);
+        pList[i].value = atof(buffer);
+    }
+
+    return 1;
+}
+
+
+// TODO if we are just returing fail/success here, then why not return a bool
+// instead of an entire 32 bit integer?  Seems wasteful.
+int32_t 
+GetRequest(int32_t socketFD, struct Parameter pList[], struct Radio_Info *radio_info)
+{
+    char buffer[256];
+    memset(buffer, 0, 256);
+   
+    ReadMessage(socketFD, buffer);
+
+    if(strcmp(buffer, "val") != 0) {
+        LOG("socket_comm::GetRequest - Unexpected control data received.\n\n");
+        return 0;
+    }
+
+    LOG("socket_comm::GetRequest - Getting parameters.\n\n");
+    GetParameter(socketFD, pList, radio_info);
+
+    return 1;
+}
+
+
+int32_t 
+AcceptTCPConnection(int32_t serverSock)
+{
+    struct sockaddr_in echoClientAddr;
+
+    uint32_t clientLength = sizeof(echoClientAddr);
+
+    int32_t clientSocket = accept(serverSock, NULL, NULL);
+    if(clientSocket < 0) { 
+        //WARNING("ALERT: Could not establish connection with client socket.\n");
+        return -1;
+    }
+    //LOG("Handling client %s\n", inet_ntoa(echoClientAddr.sin_addr));
+
+    return clientSocket;
+}
+
+
+int32_t 
+CreateTCPServerSocket(uint16_t port)
+{
+    struct sockaddr_in echoServerAddr;
+
+    int32_t localSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (localSocket < 0)
+        ERROR(1, "socket() failed\n");
+      
+    /* Construct the local address structure */
+    memset(&echoServerAddr, 0, sizeof(echoServerAddr));
+    echoServerAddr.sin_family = AF_INET;
+    echoServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+    echoServerAddr.sin_port = htons(port);
+
+    /* Bind to the local address */
+    if(bind(localSocket, (struct sockaddr *) &echoServerAddr, \
+            sizeof(echoServerAddr)) < 0)
+        ERROR(1, "bind() failed\n");
+
+    /* Mark the socket so it will listen for incoming connections */
+    if(listen(localSocket, 5) < 0)
+        ERROR(1, "listen() failed\n");
+
+    return localSocket;
+}
+
+int32_t
+InitializeTCPServerPort(int32_t servSock)
+{
+    int32_t rc, on = 1;
+
+    rc = setsockopt(servSock, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));
+    if(rc < 0) {
+        shutdown(servSock, 2);
+        close(servSock);
+        ERROR(1,"setsockopt() failed\n");
+    }
+
+    rc = ioctl(servSock, FIONBIO, (char*)&on);
+    if(rc < 0) {
+        shutdown(servSock, 2);
+        close(servSock);
+        ERROR(1,"ioctl() failed\n");
+    }
+
+    return 1;
+}
Index: vtcross/branches/wrodgers/src/lib/socketcomm/Makefile.am
===================================================================
--- vtcross/branches/wrodgers/src/lib/socketcomm/Makefile.am	(revision 161)
+++ vtcross/branches/wrodgers/src/lib/socketcomm/Makefile.am	(revision 161)
@@ -0,0 +1,4 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+noinst_LIBRARIES = libsocketcomm.a
+libsocketcomm_a_SOURCES = socketcomm.cpp
Index: vtcross/branches/wrodgers/src/lib/tinyxml/tinyxmlerror.cpp
===================================================================
--- vtcross/branches/wrodgers/src/lib/tinyxml/tinyxmlerror.cpp	(revision 161)
+++ vtcross/branches/wrodgers/src/lib/tinyxml/tinyxmlerror.cpp	(revision 161)
@@ -0,0 +1,53 @@
+/*
+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[ TIXML_ERROR_STRING_COUNT ] =
+{
+	"No error",
+	"Error",
+	"Failed to open file",
+	"Memory allocation failed.",
+	"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: vtcross/branches/wrodgers/src/lib/tinyxml/tinyxmlparser.cpp
===================================================================
--- vtcross/branches/wrodgers/src/lib/tinyxml/tinyxmlparser.cpp	(revision 161)
+++ vtcross/branches/wrodgers/src/lib/tinyxml/tinyxmlparser.cpp	(revision 161)
@@ -0,0 +1,1638 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 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[ 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()	{ 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 ) || *p == '\n' || *p =='\r' )		// Still using old rules for white space.
+				++p;
+			else
+				break;
+		}
+	}
+	else
+	{
+		while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' )
+			++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 += strlen( endTag );
+	return p;
+}
+
+#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;
+	}
+
+	TiXmlDocument* doc = GetDocument();
+	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;
+	}
+	else
+	{
+		if ( doc )
+			doc->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+	}
+	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;
+	endTag += ">";
+
+	// 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
+			if ( StringEqual( p, endTag.c_str(), false, encoding ) )
+			{
+				p += endTag.length();
+				return p;
+			}
+			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 )
+			{
+				if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding );
+				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 )
+			{
+				node->SetValue( attrib->Value() );
+				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 )
+			{
+				if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding );
+				    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 == '>' )
+		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 ) )
+	{
+		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 += strlen( endTag );
+
+	return p;
+}
+
+
+const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	p = SkipWhiteSpace( p, encoding );
+	if ( !p || !*p ) return 0;
+
+//	int tabsize = 4;
+//	if ( document )
+//		tabsize = document->TabSize();
+
+	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 ) && *p != '\n' && *p != '\r'	// 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 ) )
+		{
+			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 )
+			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: vtcross/branches/wrodgers/src/lib/tinyxml/tinyxml.cpp
===================================================================
--- vtcross/branches/wrodgers/src/lib/tinyxml/tinyxml.cpp	(revision 161)
+++ vtcross/branches/wrodgers/src/lib/tinyxml/tinyxml.cpp	(revision 161)
@@ -0,0 +1,1888 @@
+/*
+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 <ctype.h>
+
+#ifdef TIXML_USE_STL
+#include <sstream>
+#include <iostream>
+#endif
+
+#include "tinyxml.h"
+
+
+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; 
+}
+
+
+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::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::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::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::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->parent != this )
+		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->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::ELEMENT )
+{
+	firstChild = lastChild = 0;
+	value = _value;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlElement::TiXmlElement( const std::string& _value ) 
+	: TiXmlNode( TiXmlNode::ELEMENT )
+{
+	firstChild = lastChild = 0;
+	value = _value;
+}
+#endif
+
+
+TiXmlElement::TiXmlElement( const TiXmlElement& copy)
+	: TiXmlNode( TiXmlNode::ELEMENT )
+{
+	firstChild = lastChild = 0;
+	copy.CopyTo( this );	
+}
+
+
+void TiXmlElement::operator=( const TiXmlElement& base )
+{
+	ClearThis();
+	base.CopyTo( 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* node = attributeSet.Find( name );
+	if ( node )
+		return &node->ValueStr();
+	return 0;
+}
+#endif
+
+
+const char* TiXmlElement::Attribute( const char* name, int* i ) const
+{
+	const char* s = Attribute( name );
+	if ( i )
+	{
+		if ( s ) {
+			*i = atoi( s );
+		}
+		else {
+			*i = 0;
+		}
+	}
+	return s;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
+{
+	const std::string* s = Attribute( name );
+	if ( i )
+	{
+		if ( s ) {
+			*i = atoi( s->c_str() );
+		}
+		else {
+			*i = 0;
+		}
+	}
+	return s;
+}
+#endif
+
+
+const char* TiXmlElement::Attribute( const char* name, double* d ) const
+{
+	const char* s = Attribute( name );
+	if ( d )
+	{
+		if ( s ) {
+			*d = atof( s );
+		}
+		else {
+			*d = 0;
+		}
+	}
+	return s;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
+{
+	const std::string* s = Attribute( name );
+	if ( d )
+	{
+		if ( s ) {
+			*d = atof( s->c_str() );
+		}
+		else {
+			*d = 0;
+		}
+	}
+	return s;
+}
+#endif
+
+
+int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( !node )
+		return TIXML_NO_ATTRIBUTE;
+	return node->QueryIntValue( ival );
+}
+
+
+#ifdef TIXML_USE_STL
+int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( !node )
+		return TIXML_NO_ATTRIBUTE;
+	return node->QueryIntValue( ival );
+}
+#endif
+
+
+int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( !node )
+		return TIXML_NO_ATTRIBUTE;
+	return node->QueryDoubleValue( dval );
+}
+
+
+#ifdef TIXML_USE_STL
+int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( !node )
+		return TIXML_NO_ATTRIBUTE;
+	return node->QueryDoubleValue( dval );
+}
+#endif
+
+
+void TiXmlElement::SetAttribute( const char * name, int val )
+{	
+	char buf[64];
+	#if defined(TIXML_SNPRINTF)		
+		TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
+	#else
+		sprintf( buf, "%d", val );
+	#endif
+	SetAttribute( name, buf );
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& name, int val )
+{	
+   std::ostringstream oss;
+   oss << val;
+   SetAttribute( name, oss.str() );
+}
+#endif
+
+
+void TiXmlElement::SetDoubleAttribute( const char * name, double val )
+{	
+	char buf[256];
+	#if defined(TIXML_SNPRINTF)		
+		TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
+	#else
+		sprintf( buf, "%f", val );
+	#endif
+	SetAttribute( name, buf );
+}
+
+
+void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
+{
+    #ifdef TIXML_USE_STL
+	TIXML_STRING _name( cname );
+	TIXML_STRING _value( cvalue );
+	#else
+	const char* _name = cname;
+	const char* _value = cvalue;
+	#endif
+
+	TiXmlAttribute* node = attributeSet.Find( _name );
+	if ( node )
+	{
+		node->SetValue( _value );
+		return;
+	}
+
+	TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
+	if ( attrib )
+	{
+		attributeSet.Add( attrib );
+	}
+	else
+	{
+		TiXmlDocument* document = GetDocument();
+		if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+	}
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
+{
+	TiXmlAttribute* node = attributeSet.Find( name );
+	if ( node )
+	{
+		node->SetValue( _value );
+		return;
+	}
+
+	TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
+	if ( attrib )
+	{
+		attributeSet.Add( attrib );
+	}
+	else
+	{
+		TiXmlDocument* document = GetDocument();
+		if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+	}
+}
+#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::DOCUMENT )
+{
+	tabsize = 4;
+	useMicrosoftBOM = false;
+	ClearError();
+}
+
+TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+	tabsize = 4;
+	useMicrosoftBOM = false;
+	value = documentName;
+	ClearError();
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+	tabsize = 4;
+	useMicrosoftBOM = false;
+    value = documentName;
+	ClearError();
+}
+#endif
+
+
+TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+	copy.CopyTo( this );
+}
+
+
+void TiXmlDocument::operator=( const TiXmlDocument& copy )
+{
+	Clear();
+	copy.CopyTo( this );
+}
+
+
+bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
+{
+	// See STL_STRING_BUG below.
+	//StringToBuffer buf( value );
+
+	return LoadFile( Value(), encoding );
+}
+
+
+bool TiXmlDocument::SaveFile() const
+{
+	// See STL_STRING_BUG below.
+//	StringToBuffer buf( value );
+//
+//	if ( buf.buffer && SaveFile( buf.buffer ) )
+//		return true;
+//
+//	return false;
+	return SaveFile( Value() );
+}
+
+bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
+{
+	// There was a really terrifying little bug here. The code:
+	//		value = filename
+	// in the STL case, cause the assignment method of the std::string to
+	// be called. What is strange, is that the std::string had the same
+	// address as it's c_str() method, and so bad things happen. Looks
+	// like a bug in the Microsoft STL implementation.
+	// Add an extra string to avoid the crash.
+	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;
+	}
+
+	// If we have a file, assume it is all one big XML file, and read it in.
+	// The document parser may decide the document ends sooner than the entire file, however.
+	TIXML_STRING data;
+	data.reserve( length );
+
+	// 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;
+	}
+
+	const char* lastPos = buf;
+	const char* p = buf;
+
+	buf[length] = 0;
+	while( *p ) {
+		assert( p < (buf+length) );
+		if ( *p == 0xa ) {
+			// Newline character. No special rules for this. Append all the characters
+			// since the last string, and include the newline.
+			data.append( lastPos, (p-lastPos+1) );	// append, include the newline
+			++p;									// move past the newline
+			lastPos = p;							// and point to the new buffer (may be 0)
+			assert( p <= (buf+length) );
+		}
+		else if ( *p == 0xd ) {
+			// Carriage return. Append what we have so far, then
+			// handle moving forward in the buffer.
+			if ( (p-lastPos) > 0 ) {
+				data.append( lastPos, p-lastPos );	// do not add the CR
+			}
+			data += (char)0xa;						// a proper newline
+
+			if ( *(p+1) == 0xa ) {
+				// Carriage return - new line sequence
+				p += 2;
+				lastPos = p;
+				assert( p <= (buf+length) );
+			}
+			else {
+				// it was followed by something else...that is presumably characters again.
+				++p;
+				lastPos = p;
+				assert( p <= (buf+length) );
+			}
+		}
+		else {
+			++p;
+		}
+	}
+	// Handle any left over characters.
+	if ( p-lastPos ) {
+		data.append( lastPos, p-lastPos );
+	}		
+	delete [] buf;
+	buf = 0;
+
+	Parse( data.c_str(), 0, encoding );
+
+	if (  Error() )
+        return false;
+    else
+		return true;
+}
+
+
+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), "%lf", _value);
+	#else
+		sprintf (buf, "%lf", _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::COMMENT )
+{
+	copy.CopyTo( this );
+}
+
+
+void TiXmlComment::operator=( const TiXmlComment& base )
+{
+	Clear();
+	base.CopyTo( 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::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::DECLARATION )
+{
+	version = _version;
+	encoding = _encoding;
+	standalone = _standalone;
+}
+#endif
+
+
+TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
+	: TiXmlNode( TiXmlNode::DECLARATION )
+{
+	copy.CopyTo( this );	
+}
+
+
+void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
+{
+	Clear();
+	copy.CopyTo( 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
+const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
+{
+	for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( node->name == name )
+			return node;
+	}
+	return 0;
+}
+
+/*
+TiXmlAttribute*	TiXmlAttributeSet::Find( const std::string& name )
+{
+	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( node->name == name )
+			return node;
+	}
+	return 0;
+}
+*/
+#endif
+
+
+const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
+{
+	for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( strcmp( node->name.c_str(), name ) == 0 )
+			return node;
+	}
+	return 0;
+}
+
+/*
+TiXmlAttribute*	TiXmlAttributeSet::Find( const char* name )
+{
+	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( strcmp( node->name.c_str(), name ) == 0 )
+			return node;
+	}
+	return 0;
+}
+*/
+
+#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: vtcross/branches/wrodgers/src/lib/tinyxml/Makefile.am
===================================================================
--- vtcross/branches/wrodgers/src/lib/tinyxml/Makefile.am	(revision 161)
+++ vtcross/branches/wrodgers/src/lib/tinyxml/Makefile.am	(revision 161)
@@ -0,0 +1,4 @@
+INCLUDES = -I$(top_srcdir)/src/include/tinyxml
+
+noinst_LIBRARIES = libtinyxml.a
+libtinyxml_a_SOURCES = tinystr.cpp tinyxml.cpp tinyxmlerror.cpp tinyxmlparser.cpp
Index: vtcross/branches/wrodgers/src/lib/tinyxml/tinystr.cpp
===================================================================
--- vtcross/branches/wrodgers/src/lib/tinyxml/tinystr.cpp	(revision 161)
+++ vtcross/branches/wrodgers/src/lib/tinyxml/tinystr.cpp	(revision 161)
@@ -0,0 +1,116 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original file by Yves Berquin.
+
+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.
+*/
+
+/*
+ * THIS FILE WAS ALTERED BY Tyge Løvset, 7. April 2005.
+ */
+
+
+#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: vtcross/branches/wrodgers/src/lib/Makefile.am
===================================================================
--- vtcross/branches/wrodgers/src/lib/Makefile.am	(revision 161)
+++ vtcross/branches/wrodgers/src/lib/Makefile.am	(revision 161)
@@ -0,0 +1,1 @@
+SUBDIRS = socketcomm tinyxml
Index: vtcross/branches/wrodgers/src/policy_engines/policy_demo.cpp
===================================================================
--- vtcross/branches/wrodgers/src/policy_engines/policy_demo.cpp	(revision 187)
+++ vtcross/branches/wrodgers/src/policy_engines/policy_demo.cpp	(revision 187)
@@ -0,0 +1,42 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * TODO LICENSE INFORMATION GOES HERE
+ */
+
+/* TODO DESCRIPTION OF FILE.
+ *
+ * This file is a temporary demo of a policy engine using some of our socket
+ * communication functions. This is *not* an actual implementation of our
+ * defined PolicyEngine class.
+ */
+
+
+#include <cstdlib>
+#include <cstring>
+#include <stdint.h>
+
+#include "vtcross/common.h"
+#include "vtcross/components.h"
+#include "vtcross/containers.h"
+#include "vtcross/debug.h"
+#include "vtcross/error.h"
+#include "vtcross/socketcomm.h"
+
+
+int32_t 
+main(int32_t argc, char *argv[])
+{
+    if(argc < 3)
+       ERROR(1, "Usage: %s hostname port\n", argv[0]);
+    
+    PolicyEngine policyEngine(argv[1], argv[2], false);
+
+    LOG("Waiting for signal...\n");
+    while(1) {
+//        policyEngine.WaitForSignal();
+    }
+
+    return 0;
+}
+
Index: vtcross/branches/wrodgers/src/policy_engines/PolicyEngine.cpp
===================================================================
--- vtcross/branches/wrodgers/src/policy_engines/PolicyEngine.cpp	(revision 205)
+++ vtcross/branches/wrodgers/src/policy_engines/PolicyEngine.cpp	(revision 205)
@@ -0,0 +1,294 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * LICENSE INFORMATION GOES HERE
+ */
+
+/* DESCRIPTION OF FILE.
+ */
+
+
+#include <cstdlib>
+#include <cstring>
+#include <stdint.h>
+
+#include "vtcross/common.h"
+#include "vtcross/components.h"
+#include "vtcross/containers.h"
+#include "vtcross/debug.h"
+#include "vtcross/error.h"
+#include "vtcross/socketcomm.h"
+
+
+PolicyEngine::PolicyEngine()
+{
+    LOG("Creating Policy Engine.\n");
+    SML_present = false;
+    commandSocketFD = -1;
+    LoadPolicies();
+}
+
+
+PolicyEngine::~PolicyEngine()
+{
+}
+
+
+PolicyEngine::PolicyEngine(const char* serverName, const char* serverPort, \
+        const bool SML)
+{
+    LOG("Creating Policy Engine.\n");
+
+    ConnectToRemoteComponent(serverName, serverPort, SML);
+
+    LoadPolicies();
+}
+
+
+void
+PolicyEngine::SendComponentType()
+{
+    SendMessage(commandSocketFD, "response_engine_policy");
+    LOG("Policy Engine responded to GetRemoteComponentType query.\n");
+}
+
+
+void
+PolicyEngine::ConnectToRemoteComponent(const char* serverName, \
+        const char* serverPort, const bool SML)
+{
+    commandSocketFD = ClientSocket(serverName, serverPort);
+
+    SML_present = SML;
+
+    if(SML) {
+        RegisterServices();
+        LOG("Policy Engine connected to SML at %s.\n", serverName);
+    }
+    else {
+        RegisterComponent();
+        LOG("Policy Engine connected to shell at %s.\n", serverName);
+    }
+}
+
+
+void 
+PolicyEngine::WaitForSignal()
+{
+    char buffer[256];
+
+    while(true) {
+        memset(buffer, 0, 256);
+       
+        ReadMessage(commandSocketFD, buffer);
+
+        // TODO this is ugly... is there a better way? Doesn't strcmp compare the
+        // whole string?  We only need to compare until we find a single different
+        // byte...
+        //
+        // If we send integer op codes rather than strings, this process will be
+        // MUCH faster since instead of donig string compares we can simply
+        // switch on the integer value...
+        if(strcmp(buffer, "validate_parameters") == 0) {
+            ValidateParameters();
+        }
+        else if(strcmp(buffer, "query_component_type") == 0) {
+            SendComponentType();
+        }
+        else if(strcmp(buffer, "connect_sml") == 0) {
+            /* This command implies that we are disconnecting from the shell and
+             * connecting to a SML component. */
+            char serverName[256];
+            char serverPort[256];
+            // TODO is this going to end up being too slow?
+            memset(serverName, 0, 256);
+            memset(serverPort, 0, 256);
+
+            ReadMessage(commandSocketFD, serverName);
+            ReadMessage(commandSocketFD, serverPort);
+
+            /* Only continue if we are currently connected to a shell. */
+            if(!SML_present) {
+                DeregisterComponent();
+
+                shutdown(commandSocketFD, 2);
+                close(commandSocketFD);
+
+                ConnectToRemoteComponent(serverName, serverPort, true);
+            }
+        }
+        else if(strcmp(buffer, "disconnect_sml") == 0) {
+            /* This command implies that we are disconnecting from the SML and
+             * connecting to a shell component. */
+            char serverName[256];
+            char serverPort[256];
+            // TODO is this going to end up being too slow?
+            memset(serverName, 0, 256);
+            memset(serverPort, 0, 256);
+
+            ReadMessage(commandSocketFD, serverName);
+            ReadMessage(commandSocketFD, serverPort);
+
+            /* We only want to do this if we are actually connected to an SML
+             * currently. */
+            if(SML_present) {
+                DeregisterServices();
+
+                shutdown(commandSocketFD, 2);
+                close(commandSocketFD);
+
+                ConnectToRemoteComponent(serverName, serverPort, false);
+            }
+        }
+        else if(strcmp(buffer, "reload_engine_configs") == 0) {
+            ReloadPolicies();
+        }
+        else if(strcmp(buffer, "reset_engine_policy") == 0) {
+            Reset();
+        }
+        else if(strcmp(buffer, "shutdown_engine_policy") == 0) {
+            Shutdown();
+        }
+    }
+}
+
+
+void 
+PolicyEngine::Shutdown()
+{
+    if(SML_present)
+        DeregisterServices();
+    else
+        DeregisterComponent();
+
+    // TODO should something else be happening here?
+}
+
+
+void
+PolicyEngine::Reset()
+{
+    LOG("Resetting Policy Engine.\n");
+
+    if(SML_present)
+        DeregisterServices();
+    else
+        DeregisterComponent();
+}
+
+
+void
+PolicyEngine::RegisterComponent()
+{
+    SendMessage(commandSocketFD, "register_engine_policy");
+    LOG("Policy Engine:: Registration message sent to shell.\n");
+}
+
+
+void 
+PolicyEngine::DeregisterComponent()
+{
+    SendMessage(commandSocketFD, "deregister_engine_policy");
+    LOG("Policy Engine:: Deregistration message sent to shell.\n");
+
+    shutdown(commandSocketFD, 2);
+    close(commandSocketFD);
+    commandSocketFD = -1;
+    LOG("Policy Engine:: Shell socket closed.\n");
+}
+
+
+void 
+PolicyEngine::RegisterServices()
+{
+    LOG("Policy Engine:: Registering services.\n");
+
+    SendMessage(commandSocketFD, "register_service");
+    SendMessage(commandSocketFD, "policy_geo");
+
+    SendMessage(commandSocketFD, "register_service");
+    SendMessage(commandSocketFD, "policy_time");
+
+    SendMessage(commandSocketFD, "register_service");
+    SendMessage(commandSocketFD, "policy_spectrum");
+
+    SendMessage(commandSocketFD, "register_service");
+    SendMessage(commandSocketFD, "policy_spacial");
+}
+
+
+void 
+PolicyEngine::DeregisterServices()
+{
+    LOG("Policy Engine:: Deregistering services.\n");
+
+    SendMessage(commandSocketFD, "deregister_service");
+    SendMessage(commandSocketFD, "policy_geo");
+
+    SendMessage(commandSocketFD, "deregister_service");
+    SendMessage(commandSocketFD, "policy_time");
+
+    SendMessage(commandSocketFD, "deregister_service");
+    SendMessage(commandSocketFD, "policy_spectrum");
+
+    SendMessage(commandSocketFD, "deregister_service");
+    SendMessage(commandSocketFD, "policy_spacial");
+
+    shutdown(commandSocketFD, 2);
+    close(commandSocketFD);
+    commandSocketFD = -1;
+    LOG("Policy Engine:: SML socket closed.\n");
+}
+
+
+void 
+PolicyEngine::LoadPolicies()
+{
+    LOG("PolicyEngine:: Loading policies.\n");
+}
+
+
+void 
+PolicyEngine::ReloadPolicies()
+{
+    LOG("PolicyEngine:: Reloading policies.\n");
+}
+
+
+void 
+PolicyEngine::SendPEDecision(struct Parameter pList[], \
+        struct Radio_Info *radio_info, int32_t decision_array[])
+{
+    char var[50];
+ 
+    for (size_t i = 0; i < radio_info->numParameters; i++) {
+        sprintf(var, "%i", decision_array[i]);
+        SendMessage(commandSocketFD, var);
+    }
+}
+
+
+void 
+PolicyEngine::ValidateParameters()
+{
+    LOG("Policy Engine:: Preparing to receive parameters for validation....\n");
+
+    int32_t decision_array[10];
+    struct Parameter pList[10];
+    struct Radio_Info radio_info;
+
+    if(GetRequest(commandSocketFD, pList, &radio_info)) {
+        LOG("Policy Engine:: Validating Transmission Parameters.\n");
+        for (size_t i = 0; i < radio_info.numParameters; i++)
+            decision_array[i] = 1;
+
+        LOG("Policy Engine:: Sending Policy decision to Server.\n");
+        SendPEDecision(pList, &radio_info, decision_array);
+
+        LOG("Policy Engine:: Policies Validated.\n");
+    }
+    else
+        ERROR(1, "Call to GetRequest in ValidateParameters failed.\n");
+
+}
+
Index: vtcross/branches/wrodgers/src/policy_engines/Makefile.am
===================================================================
--- vtcross/branches/wrodgers/src/policy_engines/Makefile.am	(revision 161)
+++ vtcross/branches/wrodgers/src/policy_engines/Makefile.am	(revision 161)
@@ -0,0 +1,9 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+AM_CXXFLAGS = -Wall -g
+
+bin_PROGRAMS = policy_demo
+
+policy_demo_SOURCES = PolicyEngine.cpp policy_demo.cpp
+policy_demo_LDADD = ../lib/socketcomm/libsocketcomm.a
+
Index: vtcross/branches/wrodgers/src/shell/CognitiveRadioShell.cpp
===================================================================
--- vtcross/branches/wrodgers/src/shell/CognitiveRadioShell.cpp	(revision 239)
+++ vtcross/branches/wrodgers/src/shell/CognitiveRadioShell.cpp	(revision 239)
@@ -0,0 +1,769 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * LICENSE INFORMATION GOES HERE
+ */
+
+/* DESCRIPTION OF FILE.
+ */
+
+
+#include <cstdlib>
+#include <cstring>
+#include <stdint.h>
+#include <string>
+
+#include <arpa/inet.h>
+#include <iostream>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "tinyxml/tinyxml.h"
+#include "tinyxml/tinystr.h"
+
+#include "vtcross/common.h"
+#include "vtcross/components.h"
+#include "vtcross/containers.h"
+#include "vtcross/debug.h"
+#include "vtcross/error.h"
+#include "vtcross/socketcomm.h"
+
+
+CognitiveRadioShell::CognitiveRadioShell()
+{
+    LOG("Creating Cognitive Radio Shell.\n");
+    SML_present = false;
+    PE_present = false;
+    CE_present = false;
+
+    // TODO =BUG= The params, observables, and utils arrays are not being
+    // allocated here. If an shell object is constructed, and then immediately
+    // destructed, there will be no allocated memory, and the delete operater
+    // will receive a null pointer, which will segfault.
+}
+
+
+CognitiveRadioShell::~CognitiveRadioShell()
+{
+    delete [] params;
+    delete [] observables;
+    delete [] utils;
+}
+
+
+CognitiveRadioShell::CognitiveRadioShell(const char* radioConfig, int16_t p1, \
+        int16_t p2, int16_t p3)
+{
+    LOG("Creating Cognitive Radio Shell.\n");
+
+    params = new Parameter[10];
+    observables = new Observable[10];
+    utils = new Utility[10];
+    radio_info = new Radio_Info;
+
+    LoadRadioConfiguration(radioConfig, params, utils, observables, radio_info);
+
+    primaryPort = p1;
+    policyPort = p2;
+    commandPort = p3;
+}
+
+
+void
+CognitiveRadioShell::SendComponentType(int32_t socketFD)
+{
+    SendMessage(socketFD, "response_shell");
+    LOG("Cognitive Radio Shell responded to GetRemoteComponentType query.\n");
+}
+
+
+std::string 
+CognitiveRadioShell::GetRemoteComponentType(int32_t socketFD)
+{
+    SendMessage(socketFD, "request_component_type");
+
+    char buffer[256];
+    memset(buffer, 0, 256);
+    ReadMessage(socketFD, buffer);
+
+    return std::string(buffer);
+}
+
+
+void 
+CognitiveRadioShell::Shutdown()
+{
+    // TODO should something else be happening here?
+}
+
+
+void
+CognitiveRadioShell::Reset()
+{
+    LOG("Resetting Cognitive Radio Shell.\n");
+}
+
+
+// TODO what is the point of always returning a 1?
+bool
+CognitiveRadioShell::SendRadioConfiguration(int32_t socketFD)
+{
+    LOG("Cognitive Radio Shell:: Sending radio configuration to Cognitive Engine.\n");
+
+    char counter[55];
+    char var[50];
+
+    /* Send utilities */
+    sprintf(counter, "%d", radio_info->numUtilities);
+    SendMessage(socketFD, counter);
+    for(size_t i = 0; i < radio_info->numUtilities; i++) {
+        SendMessage(socketFD, utils[i].name.c_str());
+        SendMessage(socketFD, utils[i].units.c_str());
+        SendMessage(socketFD, utils[i].goal.c_str());
+        sprintf(var,"%f", utils[i].target);
+        SendMessage(socketFD, var);
+    }
+
+    /* Send parameters */
+    sprintf(counter,"%i",radio_info->numParameters);
+    SendMessage(socketFD,counter);
+    for(size_t i = 0; i < radio_info->numParameters; i++) {
+        SendMessage(socketFD, params[i].name.c_str());
+        SendMessage(socketFD, params[i].units.c_str());
+        sprintf(var, "%f", params[i].min);
+        SendMessage(socketFD,var);
+        sprintf(var, "%f", params[i].max);
+        SendMessage(socketFD, var);
+        sprintf(var, "%f", params[i].step);
+        SendMessage(socketFD, var);
+
+        sprintf(counter, "%i", params[i].numAffects); 
+        SendMessage(socketFD, counter);
+        for(size_t j = 0; j < params[i].numAffects; j++) {
+            SendMessage(socketFD, params[i].affection_list[j].u->name.c_str());
+            SendMessage(socketFD, params[i].affection_list[j].relation.c_str());
+        }
+    }
+
+    /* Send observables */
+    sprintf(counter,"%i",radio_info->numObservables);
+    SendMessage(socketFD, counter);
+    for(size_t i = 0; i < radio_info->numObservables; i++) {
+        SendMessage(socketFD, observables[i].name.c_str());
+        
+        sprintf(counter, "%i", observables[i].numAffects); 
+        SendMessage(socketFD, counter);
+        for(size_t j = 0; j < observables[i].numAffects; j++) {
+            SendMessage(socketFD, observables[i].affection_list[j].u->name.c_str());
+            SendMessage(socketFD, observables[i].affection_list[j].relation.c_str());
+        }
+    }
+    
+    /* Receive ACK for radio configuration */
+    char buffer[256];
+    memset(buffer, 0, 256); 
+    ReadMessage(socketFD, buffer);
+
+    if(strcmp(buffer, "receive_config_ack") != 0) {
+        LOG("Cognitive Radio Shell:: Unexpected response: %s\n", buffer);
+        return 0;
+    }
+
+    return 1;
+}
+
+bool
+CognitiveRadioShell::SendRadioExperience(int32_t socketFD)
+{
+
+    LOG("Cognitive Radio Shell:: Sending radio experience to Cognitive Engine.\n");
+    int32_t numberExp = 4;
+    char numberExpString[50];
+
+    sprintf(numberExpString, "%i", numberExp);
+    SendMessage(socketFD, numberExpString); 
+
+    char buffer[256];
+    memset(buffer, 0, 256); 
+    ReadMessage(socketFD, buffer);
+    if(strcmp(buffer, "receive_exp_ack") != 0) {
+        // TODO perhaps this should be a WARNING instead of a LOG?
+        LOG("Cognitive Radio Shell:: Unexpected response: %s\n", buffer);
+        return 0;
+    }
+
+    return 1;
+}
+
+
+void
+CognitiveRadioShell::RegisterCognitiveEngine(int32_t socketFD)
+{
+    LOG("Cognitive Radio Shell:: Received registration message from Cognitive Engine.\n");
+   
+    SendRadioConfiguration(socketFD);
+    SendRadioExperience(socketFD);
+
+    numberOfCognitiveEngines++;
+    CE_present = true;
+}
+
+
+void 
+CognitiveRadioShell::DeregisterCognitiveEngine(int32_t socketFD)
+{
+    LOG("Cognitive Radio Shell:: Received deregistration message from Cognitive Engine.\n");
+
+    numberOfCognitiveEngines--;
+    if(numberOfCognitiveEngines == 0)
+        CE_present = false;
+
+    SendMessage(socketFD, "deregister_ack");
+    shutdown(socketFD, 2);
+    close(socketFD);
+    LOG("Cognitive Radio Shell:: Socket closed.\n");
+}
+
+
+void
+CognitiveRadioShell::RegisterPolicyEngine(int32_t socketFD)
+{
+    LOG("Cognitive Radio Shell:: Received registration message from Policy Engine.\n");
+    PE_present = true;
+}
+
+
+void 
+CognitiveRadioShell::DeregisterPolicyEngine(int32_t socketFD)
+{
+    LOG("Cognitive Radio Shell:: Received deregistration message from Policy Engine.\n");
+
+    PE_present = false;
+    
+    SendMessage(socketFD, "deregister_ack");
+    shutdown(socketFD, 2);
+    close(socketFD);
+    LOG("Cognitive Radio Shell:: Socket closed.\n");
+}
+
+
+void
+CognitiveRadioShell::RegisterSML(int32_t socketFD)
+{
+    LOG("Cognitive Radio Shell:: Received registration message from SML.\n");
+
+    SML_present = true;
+}
+
+
+void 
+CognitiveRadioShell::DeregisterSML(int32_t socketFD)
+{
+    LOG("Cognitive Radio Shell:: Received deregistration message from SML.\n");
+
+    SML_present = false;
+
+    SendMessage(socketFD, "deregister_ack");
+    shutdown(socketFD, 2);
+    close(socketFD);
+    LOG("Cognitive Radio Shell:: Socket closed.\n");
+}
+
+
+int32_t 
+CognitiveRadioShell::LoadRadioConfiguration(const char* radioConfig, \
+        Parameter* &pList, Utility* &uList, Observable* &oList, \
+        Radio_Info* radioInfo)
+{
+    TiXmlElement *pElem;
+    TiXmlElement *pChild;
+    TiXmlElement *pChild1;
+    TiXmlElement *pSecondChild;
+    TiXmlHandle hRoot(0);
+
+    int32_t count = 0;
+    size_t item_count = 0;
+    size_t affect_count = 0;
+    uint32_t attribute_count = 0;
+    bool match_found = false;
+
+    LOG("Cognitive Radio Shell:: Loading radio configuration.\n");
+
+    TiXmlDocument doc( radioConfig );
+    bool loadOkay = doc.LoadFile();
+    if(!loadOkay)
+        ERROR(1,"Loading radio configuration failed: %s\n", radioConfig);
+
+    TiXmlHandle hDoc(&doc);
+    
+    pElem = hDoc.FirstChildElement().Element();
+
+    if(!pElem) 
+        ERROR(1, "No valid root!");
+
+    hRoot = TiXmlHandle(pElem);
+
+    pElem = hRoot.FirstChild("utilities").Element();
+    pChild1 = hRoot.Child("utilities", count).Element();
+
+    for(pChild = pChild1->FirstChildElement("utility"); pChild; \
+        pChild = pChild->NextSiblingElement()) {
+
+        const char *uName = pChild->Attribute("name");
+        if(uName)
+            uList[item_count].name = uName;    
+
+        const char *uUnits = pChild->Attribute("units");
+        if(uUnits) 
+            uList[item_count].units = uUnits;
+
+        const char *uGoal = pChild->Attribute("goal");
+        if(uGoal) 
+            uList[item_count].goal = uGoal;
+
+        if(pChild->QueryFloatAttribute("target", &uList[item_count].target) != TIXML_SUCCESS) 
+            uList[item_count].target = -1;
+
+        item_count++;
+    }
+
+    radio_info->numUtilities = item_count;    
+    LOG("Cognitive Radio Shell:: Parsed %d utilities.\n", radioInfo->numUtilities);
+
+    item_count = 0;
+    pElem = hRoot.FirstChild("observables").Element();
+    pChild1 = hRoot.Child("observables", count).Element();
+
+    for(pChild = pChild1->FirstChildElement("observable"); pChild; \
+        pChild = pChild->NextSiblingElement()) {
+
+        const char *oName = pChild->Attribute("name");
+        if(oName) 
+            oList[item_count].name = oName;
+        
+        affect_count = 0;
+        for(pSecondChild = pChild->FirstChildElement("affect"); pSecondChild; \
+            pSecondChild = pSecondChild->NextSiblingElement()) {
+
+            const char *oUtilName = pSecondChild->Attribute("utility");
+            if(oUtilName) {
+                for(attribute_count = 0; attribute_count < radio_info->numUtilities; attribute_count++ ) {
+                    if(uList[attribute_count].name == oUtilName) {
+
+                        oList[item_count].affection_list[affect_count].u = &uList[attribute_count];
+                        const char *oRelate = pSecondChild->Attribute("relationship");
+                        if(oRelate) 
+                            oList[item_count].affection_list[affect_count].relation = oRelate;
+
+                        affect_count++;
+                        match_found = true;
+                        break;
+                    }
+                }
+            }
+
+            if(!match_found) { 
+                ERROR(1, "Error: %s: %s is not a valid utility.\n", \
+                    oList[item_count].name.c_str(), oUtilName);
+            }
+            else
+                match_found = false;    
+        }
+        oList[item_count].numAffects = affect_count; 
+        item_count++;
+    }
+
+    radioInfo->numObservables = item_count;    
+    LOG("Cognitive Radio Shell:: Parsed %d observables.\n", radioInfo->numObservables);
+
+    pElem = hRoot.FirstChild("parameters").Element();
+    pChild1 = hRoot.Child("parameters", count).Element();
+    
+    item_count = 0;
+    for(pChild = pChild1->FirstChildElement("parameter"); pChild; \
+        pChild = pChild->NextSiblingElement()) {
+
+        const char *pName = pChild->Attribute("name");
+        if(pName) 
+            pList[item_count].name = pName;    
+
+        const char *pUnits = pChild->Attribute("units");
+        if(pUnits) 
+            pList[item_count].units = pUnits;
+
+        if(pChild->QueryFloatAttribute("min", &pList[item_count].min) != TIXML_SUCCESS) 
+            pList[item_count].min = -1;
+
+        if(pChild->QueryFloatAttribute("max", &pList[item_count].max) != TIXML_SUCCESS) 
+            pList[item_count].max = -1;
+
+        if(pChild->QueryFloatAttribute("step", &pList[item_count].step) != TIXML_SUCCESS) 
+            pList[item_count].step = -1;
+        
+        affect_count = 0;
+        for(pSecondChild = pChild->FirstChildElement("affect"); pSecondChild; \
+
+            pSecondChild = pSecondChild->NextSiblingElement()) {
+            const char *pUtilName = pSecondChild->Attribute("utility");
+            if(pUtilName) {
+                for(attribute_count = 0; attribute_count < radio_info->numUtilities; attribute_count++) {
+                    if(uList[attribute_count].name == pUtilName) {
+                        pList[item_count].affection_list[affect_count].u = &uList[attribute_count];    
+
+                        const char *pRelate = pSecondChild->Attribute("relationship");
+                        if(pRelate)
+                            pList[item_count].affection_list[affect_count].relation = pRelate;
+                        else
+                            LOG("Error: No relation found.\n");
+
+                        match_found = true;
+                        affect_count++;
+                        break;
+                    }
+                }
+            }
+
+            if(!match_found) {
+                ERROR(1, "Error: %s: %s is not a valid utility.\n", \
+                    pList[item_count].name.c_str(), pUtilName);
+            }
+
+            match_found = false;    
+        }
+
+        pList[item_count].numAffects = affect_count;
+        item_count++;
+    }
+
+    radioInfo->numParameters = item_count;
+    LOG("Cognitive Radio Shell:: Parsed %d parameters.\n", radioInfo->numParameters);
+
+    return 1;
+}
+
+
+void
+CognitiveRadioShell::GetOptimalParameters(int32_t socketFD)
+{
+    char buffer[256];
+    char counter[55];
+    char var[50];
+
+    /* Receive Set of Observables */
+    LOG("Cognitive Radio Shell:: Got request for optimization.\n");
+    memset(buffer, 0, 256);
+    ReadMessage(commandSocketFD, buffer);
+    uint32_t numObservables = atoi(buffer);
+  
+    LOG("Cognitive Radio Shell:: Attempting to get %i observables.\n", numObservables);
+    Observable *o = new Observable[numObservables];
+ 
+    for(size_t i = 0; i < numObservables; i++) {
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        o[i].name = std::string(buffer);
+   
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        o[i].value = atof(buffer);
+    }
+
+    /* Receive Set of Current Parameters */
+    memset(buffer, 0, 256);
+    ReadMessage(commandSocketFD,buffer);
+    uint32_t numCurrentParameters = atoi(buffer);
+  
+    LOG("Cognitive Radio Shell:: Attempting to get %i parameters.\n",numCurrentParameters);
+    Parameter * cp = new Parameter[numCurrentParameters];
+
+    for (size_t i = 0; i < numCurrentParameters; i++){
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD,buffer);
+        cp[i].name = std::string(buffer);
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD,buffer);
+        cp[i].value = atof(buffer);
+    }
+
+    /* Send to Cognitive Engine 
+     * TODO: With multiple CEs we need to make a decision about where
+     * to send this information
+     */
+    if(!SML_present) { 
+        LOG("Cognitive Radio Shell:: Passing on observables to Cognitive Engine\n");
+        SendMessage(ceSocketFD,"request_optimization");
+        sprintf(counter,"%i",numObservables);
+        SendMessage(ceSocketFD,counter);
+        for(size_t i = 0; i < numObservables; i++) {
+            SendMessage(ceSocketFD,o[i].name.c_str());
+            sprintf(var,"%f",o[i].value);
+            SendMessage(ceSocketFD,var);
+        }
+        
+        LOG("Cognitive Radio Shell:: Passing on current parameters to Cognitive Engine\n");
+        sprintf(counter,"%i",numCurrentParameters);
+        SendMessage(ceSocketFD,counter);
+        for(size_t i = 0; i < numCurrentParameters; i++) {
+            SendMessage(ceSocketFD,cp[i].name.c_str());
+            sprintf(var,"%f",cp[i].value);
+            SendMessage(ceSocketFD,var);
+        }
+    }
+
+    LOG("Cognitive Radio Shell:: Receiving optimized parameters from Cognitive Engine.\n");
+    /* Receive Set of Parameters */
+    memset(buffer, 0, 256);
+    ReadMessage(ceSocketFD, buffer);
+    uint32_t numParameters = atoi(buffer);
+   
+    Parameter *p = new Parameter[numParameters];
+ 
+    for(size_t i = 0; i < numParameters; i++) {
+        memset(buffer, 0, 256);
+        ReadMessage(ceSocketFD, buffer);
+        p[i].name = std::string(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(ceSocketFD, buffer);
+        p[i].value = atof(buffer);
+    }
+
+    /* Send to Application 
+     */
+    LOG("Cognitive Radio Shell:: Sending optimized parameters to Application.\n");
+    memset(counter, 0, 55);
+    sprintf(counter, "%i", numParameters);
+    SendMessage(commandSocketFD, counter);
+    for(size_t i = 0; i < numParameters; i++) {
+        SendMessage(commandSocketFD, p[i].name.c_str());
+        sprintf(var, "%f", p[i].value);
+        SendMessage(commandSocketFD, var);
+    }
+
+    delete [] o;
+    delete [] p;
+}
+
+// TODO point of always returning 1?
+bool
+CognitiveRadioShell::UpdateParameterPerformance(int32_t socketFD)
+{
+    char counter[55];
+    char var[50];
+    char buffer[256];
+
+    /* Receive Set of Parameters */
+    memset(buffer, 0, 256);
+    ReadMessage(commandSocketFD,buffer);
+    uint32_t numParameters = atoi(buffer);
+  
+    Parameter *p = new Parameter[numParameters];
+
+    for (size_t i = 0; i < numParameters; i++){
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD,buffer);
+        p[i].name = std::string(buffer);
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD,buffer);
+        p[i].value = atof(buffer);
+    }
+
+    /* Receive Set of Observables */
+    memset(buffer, 0, 256);
+    ReadMessage(commandSocketFD, buffer);
+    uint32_t numObservables = atoi(buffer);
+  
+    Observable *o = new Observable[numObservables];
+ 
+    for(size_t i = 0; i < numObservables; i++) {
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        o[i].name = std::string(buffer);
+   
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        o[i].value = atof(buffer);
+    }
+
+    SendMessage(ceSocketFD, "update_performance");
+   
+    /* Send Parameters */
+    memset(counter, 0, 55);
+    sprintf(counter, "%i", numParameters);
+    SendMessage(ceSocketFD, counter);
+    
+    for(size_t i = 0; i < numParameters; i++) {
+        SendMessage(ceSocketFD,p[i].name.c_str());
+        sprintf(var,"%f",p[i].value);
+        SendMessage(ceSocketFD,var);  
+    }   
+    
+    /* Send Observables */
+    sprintf(counter, "%i", numObservables);
+    SendMessage(ceSocketFD, counter);
+    for(size_t i = 0; i < numObservables; i++) {
+        SendMessage(ceSocketFD, o[i].name.c_str());
+        sprintf(var, "%f", o[i].value);
+        SendMessage(ceSocketFD, var); 
+    }   
+
+    delete [] p;
+    delete [] o;
+    
+    return 1;
+}
+
+
+void
+CognitiveRadioShell::HandleMessage(int32_t socketFD)
+{
+    char buffer[256];
+
+    ReadMessage(socketFD, buffer);
+
+    // TODO trying to read this code lock makes my eyes bleed
+    if(strcmp(buffer, "register_engine_cognitive") == 0) { 
+        RegisterCognitiveEngine(socketFD);
+    } else if(strcmp(buffer, "deregister_engine_cognitive") == 0) {
+        DeregisterCognitiveEngine(socketFD);
+    } else if(strcmp(buffer, "register_engine_policy") == 0) {
+        RegisterPolicyEngine(socketFD);
+    } else if(strcmp(buffer, "deregister_engine_policy") == 0) {
+        DeregisterPolicyEngine(socketFD);
+    } else if(strcmp(buffer, "register_sml") == 0) {
+        RegisterSML(socketFD);
+    } else if(strcmp(buffer, "deregister_sml") == 0) {
+        DeregisterSML(socketFD);
+    } else if(strcmp(buffer, "update_performance") == 0) {
+        UpdateParameterPerformance(socketFD);
+    } else if(strcmp(buffer, "get_number_utilities") == 0) {
+        char numUtilities[20];
+        sprintf(numUtilities, "%i", radio_info->numUtilities);
+        SendMessage(commandSocketFD, numUtilities);
+    } else if(strcmp(buffer, "get_number_observables") == 0) {
+        char numObservables[20];
+        sprintf(numObservables, "%i", radio_info->numObservables);
+        SendMessage(commandSocketFD, numObservables);
+    } else if(strcmp(buffer, "get_number_parameters") == 0) {
+        char numParameters[20];
+        sprintf(numParameters, "%i", radio_info->numParameters);
+        SendMessage(commandSocketFD, numParameters);
+    } else if(strcmp(buffer, "request_optimization") == 0) {
+        /* Receive optimization request and current environment */
+        GetOptimalParameters(socketFD);  
+    } else if(strcmp(buffer, "request_optimization_service") == 0) {
+        /* Receive optimization request and current environment */
+        //GetOptimalParametersService(socketFD);  
+    }
+}
+
+
+void
+CognitiveRadioShell::StartShellServer()
+{
+    struct timeval selTimeout;
+    int32_t primary = 0;
+    int32_t policy = 1;
+    int32_t command = 2;
+    int32_t running = 1;
+    int32_t port, rc, new_sd = 1;
+    int32_t desc_ready = 1;
+    int32_t timeout = 10;
+    fd_set sockSet;
+
+    int32_t *servSock = new int32_t[3];
+
+    servSock[primary] = CreateTCPServerSocket(primaryPort);
+    servSock[policy] = CreateTCPServerSocket(policyPort);
+    servSock[command] = CreateTCPServerSocket(commandPort);
+
+    int32_t maxDescriptor; 
+
+    if(servSock[primary] > servSock[policy])
+        maxDescriptor = servSock[primary];
+    else 
+        maxDescriptor = servSock[policy];
+
+    if(servSock[command] > maxDescriptor)
+        maxDescriptor = servSock[command];
+
+    if(InitializeTCPServerPort(servSock[primary]) == -1)
+        ERROR(1,"Error initializing primary port\n");
+ 
+    if(InitializeTCPServerPort(servSock[policy]) == -1)
+        ERROR(1,"Error initializing policy port\n");
+
+    if(InitializeTCPServerPort(servSock[command]) == -1)
+        ERROR(1,"Error initializing command port\n");
+
+    while (running) {
+        /* Zero socket descriptor vector and set for server sockets */
+        /* This must be reset every time select() is called */
+        FD_ZERO(&sockSet);
+        FD_SET(servSock[primary], &sockSet);
+        FD_SET(servSock[policy], &sockSet);
+        FD_SET(servSock[command], &sockSet);
+
+        /* Timeout specification */
+        /* This must be reset every time select() is called */
+        selTimeout.tv_sec = timeout;       /* timeout (secs.) */
+        selTimeout.tv_usec = 0;            /* 0 microseconds */
+
+        /* Suspend program until descriptor is ready or timeout */
+        rc = select(maxDescriptor + 1, &sockSet, NULL, NULL, &selTimeout); 
+        if(rc == 0)
+            LOG("No echo requests for %i secs...Server still alive\n", timeout);
+        else {
+            desc_ready = rc;
+
+            for(port = 0; port <= maxDescriptor && desc_ready > 0; port++) {
+                if(FD_ISSET(port, &sockSet)) {
+                    desc_ready -= 1;
+
+                    /* Check if request is new or on an existing open descriptor */
+                    if((port == servSock[primary]) || (port == servSock[policy]) || (port == servSock[command])) { 
+                        do {
+                            new_sd = AcceptTCPConnection(port);
+                            if(new_sd < 0) 
+                                break;
+                           
+                            if(port == servSock[primary])
+                                ceSocketFD = new_sd;
+                            if(port == servSock[command])
+                                commandSocketFD = new_sd;
+                            if(port == servSock[policy])
+                                policySocketFD = new_sd;
+
+                            HandleMessage(new_sd);
+                            FD_SET(new_sd,&sockSet);
+                            if(new_sd > maxDescriptor) 
+                                maxDescriptor = new_sd;
+                            //LOG("New incoming connection - %i\n\n",new_sd);
+                        } while(new_sd != -1);
+                    } 
+                    else {
+                        //LOG("Request on already open descriptor.\n\n");
+                        HandleMessage(port);
+                    }
+                }
+            }
+        }
+    }
+
+
+    /* Close sockets */
+    close(servSock[primary]);
+    close(servSock[policy]);
+    close(servSock[command]);
+
+    /* Free list of sockets */
+    delete servSock;
+
+    return;
+}
Index: vtcross/branches/wrodgers/src/shell/Makefile.am
===================================================================
--- vtcross/branches/wrodgers/src/shell/Makefile.am	(revision 207)
+++ vtcross/branches/wrodgers/src/shell/Makefile.am	(revision 207)
@@ -0,0 +1,9 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+AM_CXXFLAGS = -Wall -g
+
+bin_PROGRAMS = shell_demo
+
+shell_demo_SOURCES = CognitiveRadioShell.cpp shell_demo.cpp
+shell_demo_LDADD = ../lib/tinyxml/libtinyxml.a ../lib/socketcomm/libsocketcomm.a
+
Index: vtcross/branches/wrodgers/src/shell/shell_demo.cpp
===================================================================
--- vtcross/branches/wrodgers/src/shell/shell_demo.cpp	(revision 214)
+++ vtcross/branches/wrodgers/src/shell/shell_demo.cpp	(revision 214)
@@ -0,0 +1,31 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * TODO LICENSE INFORMATION GOES HERE
+ */
+
+/* TODO DESCRIPTION OF FILE.
+ */
+
+
+#include <cstdlib>
+#include <stdint.h>
+
+#include "vtcross/common.h"
+#include "vtcross/components.h"
+#include "vtcross/error.h"
+
+
+int32_t 
+main(int32_t argc, char *argv[])
+{
+    if(argc < 3)
+       ERROR(1, "Usage: %s config_file primary_port policy_port command_port\n", argv[0]);
+    
+    CognitiveRadioShell cognitiveRadioShell(argv[1], atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));
+
+    cognitiveRadioShell.StartShellServer();
+
+    return 0;
+}
+
Index: vtcross/branches/wrodgers/src/service_management_layer/sml_demo.cpp
===================================================================
--- vtcross/branches/wrodgers/src/service_management_layer/sml_demo.cpp	(revision 200)
+++ vtcross/branches/wrodgers/src/service_management_layer/sml_demo.cpp	(revision 200)
@@ -0,0 +1,42 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * TODO LICENSE INFORMATION GOES HERE
+ */
+
+/* TODO DESCRIPTION OF FILE.
+ *
+ * This file is a temporary demo of a service management layer using some of 
+ * our socket communication functions. This is *not* an actual implementation 
+ * of our defined ServiceManagement class.
+ */
+
+
+#include <cstdlib>
+#include <cstring>
+#include <stdint.h>
+
+#include "vtcross/common.h"
+#include "vtcross/components.h"
+#include "vtcross/containers.h"
+#include "vtcross/debug.h"
+#include "vtcross/error.h"
+#include "vtcross/socketcomm.h"
+
+
+int32_t 
+main(int32_t argc, char *argv[])
+{
+    if(argc < 3)
+       ERROR(1, "Usage: %s hostname port\n", argv[0]);
+    
+    ServiceManagementLayer sml;
+
+    LOG("Waiting for signal...\n");
+    while(1) {
+//        policyEngine.WaitForSignal();
+    }
+
+    return 0;
+}
+
Index: vtcross/branches/wrodgers/src/service_management_layer/Makefile.am
===================================================================
--- vtcross/branches/wrodgers/src/service_management_layer/Makefile.am	(revision 200)
+++ vtcross/branches/wrodgers/src/service_management_layer/Makefile.am	(revision 200)
@@ -0,0 +1,9 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+AM_CXXFLAGS = -Wall -g
+
+bin_PROGRAMS = sml_demo
+
+sml_demo_SOURCES = ServiceManagementLayer.cpp sml_demo.cpp
+sml_demo_LDADD = ../lib/socketcomm/libsocketcomm.a
+
Index: vtcross/branches/wrodgers/src/service_management_layer/SML_Test.cpp
===================================================================
--- vtcross/branches/wrodgers/src/service_management_layer/SML_Test.cpp	(revision 275)
+++ vtcross/branches/wrodgers/src/service_management_layer/SML_Test.cpp	(revision 275)
@@ -0,0 +1,145 @@
+#include <cstdlib>
+#include <cstring>
+#include <stdint.h>
+#include <string>
+#include <stdlib.h> 
+
+#include <arpa/inet.h>
+#include <iostream>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "sqlite3.h"
+
+
+
+//#include "tinyxml.h"
+//#include "tinyxml.cpp"
+//#include "tinystr.h"
+
+/*#include "../vtcornet/vtcross/trunk/src/include/vtcross/common.h"*/
+#include "../vtcornet/vtcross/trunk/src/include/vtcross/components.h"
+#include "../vtcornet/vtcross/trunk/src/include/vtcross/containers.h"
+/*#include "../vtcornet/vtcross/trunk/src/include/vtcross/debug.h"
+#include "../vtcornet/vtcross/trunk/src/include/vtcross/error.h"
+#include "../vtcornet/vtcross/trunk/src/include/vtcross/socketcomm.h"*/
+
+//#include "../vtcornet/vtcross/branches/wrodgers/ServiceManagementLayer.cpp"
+
+
+
+/*#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+//#include <iostream>
+#include <stdlib.h>
+#include <string.h>
+#include <sqlite3.h>
+#include <sqlite3ext.h>*/
+
+//#include "common.h"
+
+//using namespace std;
+
+
+int main(int argc, char *argv[])
+{   
+    int shell = CreateTCPServerSocket(1979);
+    //sleep(2);
+    int temp = AcceptTCPConnection(shell); 
+   // SendMessage(temp, "list_services");
+    sleep(1);
+    int FD = ClientSocket("127.0.0.1", "2036"); 
+    SendMessage(FD, "register_engine_cognitive");   
+    SendMessage(FD, "register_service");
+    SendMessage(FD, "test_srv"); 
+    SendMessage(FD, "list_services");
+    int FD2 = ClientSocket("127.0.0.1", "2036"); 
+    SendMessage(FD2, "register_engine_cognitive");   
+    SendMessage(FD2, "register_service");
+    SendMessage(FD2, "test_srv1"); 
+    SendMessage(FD2, "register_service");
+    SendMessage(FD2, "test_srv2");
+    SendMessage(FD2, "list_services");
+    sleep(1);
+    printf("preread1\n");
+
+    char buffer[256];
+    memset(buffer, 0, 256);
+
+    SendMessage(temp, "set_active_mission");
+    SendMessage(temp, "0"); 
+    SendMessage(temp, "request_optimization");
+    SendMessage(temp, "params");
+    ReadMessage(FD, buffer);
+    printf("preread2\n");
+    printf("-----buffer1= %s-------\n", buffer);
+    ReadMessage(FD, buffer);
+    printf("-----buffer2= %s-------\n", buffer);
+    memset(buffer, 0, 256);
+    ReadMessage(FD, buffer);
+    printf("-----buffer3= %s-------\n", buffer);
+    SendMessage(FD, "ACK");
+    SendMessage(FD, "temp");
+    SendMessage(FD, "raw_data");
+    ReadMessage(FD2, buffer);
+    printf("-----buffer4= %s-------\n", buffer);
+    ReadMessage(FD2, buffer);
+    printf("-----buffer5= %s-------\n", buffer);
+    ReadMessage(FD2, buffer);
+    printf("-----buffer6= %s-------\n", buffer);
+    SendMessage(FD2, "ACK");
+    ReadMessage(FD2, buffer);
+    printf("-----buffer7= %s-------\n", buffer);
+    ReadMessage(FD2, buffer);
+    printf("-----buffer8= %s-------\n", buffer);
+    ReadMessage(FD2, buffer);
+    printf("-----buffer9= %s-------\n", buffer);
+    SendMessage(FD2, "ACK");
+    SendMessage(FD2, "trans");
+    ReadMessage(temp, buffer);
+    printf("-----buffer10= %s-------\n", buffer);
+    SendMessage(temp, "ACK");
+    /*ReadMessage(FD, buffer);
+    printf("-----buffer1= %s-------\n", buffer);
+    ReadMessage(FD, buffer);
+    printf("-----buffer2= %s-------\n", buffer);
+    memset(buffer, 0, 256);
+    ReadMessage(FD, buffer);
+    printf("-----buffer3= %s-------\n", buffer);
+    SendMessage(FD, "ACK");
+    SendMessage(FD, "true");
+    SendMessage(FD, "data");
+    ReadMessage(FD2, buffer);
+    printf("-----buffer4= %s-------\n", buffer);
+    ReadMessage(FD2, buffer);
+    printf("-----buffer5= %s-------\n", buffer);
+    memset(buffer, 0, 256);
+    ReadMessage(FD2, buffer);
+    printf("-----buffer6= %s-------\n", buffer);
+    SendMessage(FD2, "ACK");
+    SendMessage(FD2, "trans");
+    ReadMessage(temp, buffer);
+    printf("-----buffer7= %s-------\n", buffer);
+    SendMessage(temp, "ACK");*/
+   
+    
+
+    //SendMessage(temp, "list_services");  
+    while(true){   
+    char buffer[256];
+    memset(buffer, 0, 256);
+    ReadMessage(temp, buffer);
+    printf("------%s------\n", buffer);}
+   /*memset(buffer, 0, 256);
+    ReadMessage(temp, buffer);
+    printf("------%s------\n", buffer);*/
+}
Index: vtcross/branches/wrodgers/src/service_management_layer/ServiceManagementLayer.cpp
===================================================================
--- vtcross/branches/wrodgers/src/service_management_layer/ServiceManagementLayer.cpp	(revision 275)
+++ vtcross/branches/wrodgers/src/service_management_layer/ServiceManagementLayer.cpp	(revision 275)
@@ -0,0 +1,1477 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * LICENSE INFORMATION GOES HERE
+ */
+
+/* Inter-component communication handled by sockets and FD's.  
+ * Server support has been completely implemented and tested.
+ *
+ * Services are stored in a SQLite DB by the ID of the CE that registered them.  Service
+ * support has been completely implemented and tested.
+ *
+ * Missions are loaded from an XML file, connected with services provided by components,
+ * and run.  See the documentation for the "PerformActiveMission" below for important 
+ * info.  
+ *
+ * NOTE THAT the RegisterServices method works differently than it is described in the documentation
+ * this will be fixed in a future release
+ */
+
+//TODO Verify while
+//TODO Add nested conditional support
+//TODO Verify update functionality
+//TODO Better shutdown
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <cstring>
+#include <stdint.h>
+
+#include "../include/vtcross/common.h"
+
+#include "../include/vtcross/components.h"
+#include "../include/vtcross/containers.h"
+#include "../include/vtcross/debug.h"
+#include "../include/vtcross/error.h"
+#include "../include/vtcross/socketcomm.h"
+
+/*#include "../../trunk/src/include/vtcross/common.h"
+
+#include "../../trunk/src/include/vtcross/components.h"
+#include "../../trunk/src/include/vtcross/containers.h"
+#include "../../trunk/src/include/vtcross/debug.h"
+#include "../../trunk/src/include/vtcross/error.h"
+#include "../../trunk/src/include/vtcross/socketcomm.h"*/
+
+
+#include <cstdlib>
+#include <cstring>
+#include <stdint.h>
+#include <math.h>
+
+#include <arpa/inet.h>
+#include <iostream>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+//#include "../../trunk/src/include/tinyxml/tinyxml.h"
+//#include "../../trunk/src/include/tinyxml/tinystr.h"
+
+#include "../include/tinyxml/tinyxml.h"
+#include "../include/tinyxml/tinystr.h"
+
+#include "sqlite3.h"
+//#include "sqlite3ext.h"
+
+typedef struct services_s *services_DB;
+typedef struct data_s *data_DB;
+
+using namespace std;
+
+struct services_s {
+    char filename[64];
+    char tablename[64];
+    char command[2048];
+    sqlite3 *db; 
+    unsigned int num_columns;
+};
+
+struct data_s {
+    char filename[64];
+    char tablename[64];
+    char command[2048];
+    sqlite3 *db; 
+    unsigned int num_columns;
+};
+
+services_DB _services_DB;
+data_DB _data_DB;
+const char *_SML_Config;
+
+//Callback function used internally by some of the SQLite3 commands
+int callback(void *notUsed, int argc, char **argv, char **azColName){
+    int i;
+    for(i=0; i<argc; i++){
+        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
+    }
+    printf("\n");
+    return 0;
+}
+
+
+
+ServiceManagementLayer::ServiceManagementLayer()
+{
+    LOG("Creating Service Management Layer.\n");
+    shellSocketFD = -1;
+    numberOfCognitiveEngines = 0;
+    CE_Present = false;
+    cogEngSrv = 1;
+}
+
+//Free and clear the DB's associated with this SML in the destructor
+//Note that exiting with an error condition will cause SML to not be destructed,
+// resulting in the DB's staying in memory until the destructor is encountered in future executions
+ServiceManagementLayer::~ServiceManagementLayer()
+{
+    char *errorMsg;
+    strcpy(_services_DB->command, "drop table ");
+    strcat(_services_DB->command, _services_DB->tablename);
+    int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "1SQL error: %s\n", errorMsg);
+    strcpy(_services_DB->command, "vacuum");
+    rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "1SQL error: %s\n", errorMsg);
+    free(_services_DB);
+
+    strcpy(_data_DB->command, "drop table ");
+    strcat(_data_DB->command, _data_DB->tablename);
+    rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "2SQL error (1): %s\n", errorMsg);
+    strcpy(_data_DB->command, "vacuum");
+    rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "2SQL error (2): %s\n", errorMsg);
+    free(_data_DB);
+}
+
+//Note that sizes of CE_List, miss, and service are hardcoded for now.
+//Also, their sizes are hardcoded into the code in various places; a fix for a future version.
+ServiceManagementLayer::ServiceManagementLayer(const char* SML_Config, \
+	const char* serverName, const char* serverPort)
+{
+    LOG("Creating Service Management Layer.\n");
+    _SML_Config = SML_Config;
+
+    ConnectToShell(serverName, serverPort);
+    CE_List = (CE_Reg *) malloc(10*sizeof(struct CE_Reg));
+    CE_List = new CE_Reg[10];
+
+    miss = new Mission[10];
+    for(int i = 0; i < 10; i++)
+    	miss[i].services = new Service[20];
+
+    Current_ID = 0;
+
+    LoadConfiguration(SML_Config, miss);
+    CreateServicesDB();
+    CreateDataDB();
+}
+
+/* CALLED BY: constructor
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Create and initialize a DB to hold the services registered by components
+ */
+void
+ServiceManagementLayer::CreateServicesDB()
+{
+    _services_DB = (services_DB) malloc(sizeof(struct services_s));
+    char *errorMsg;
+
+    // create database
+
+    // copy filename
+    unsigned int i=0;
+    strcpy(_services_DB->filename, "Services_Table");
+
+    // execute create database command
+    // database handle
+    //_services_DB->db = NULL;
+    sqlite3_open(_services_DB->filename, &(_services_DB->db));
+    char* cols[] = {(char *)"ID_Num", (char *)"Service_Name"};
+
+    // create table
+
+    // copy tablename
+    strcpy(_services_DB->tablename, "Services");
+
+    // number of columns in the table
+    _services_DB->num_columns = 2;
+
+    // generate command
+    strcpy(_services_DB->command, "CREATE TABLE ");
+    strcat(_services_DB->command, _services_DB->tablename);
+    strcat(_services_DB->command, "(");
+    //strcat(_services_DB->command, "SRVID INTEGER PRIMARY KEY, ");
+    strcat(_services_DB->command, cols[0]);
+    strcat(_services_DB->command, " INT, ");
+    strcat(_services_DB->command, cols[1]);
+    strcat(_services_DB->command, " TEXT");
+    strcat(_services_DB->command, ");");
+
+    // execute create table command
+  sqlite3_stmt *ppStmt;  /* OUT: Statement handle */
+  const char *pzTail;     /* OUT: Pointer to unused portion of zSql */
+
+    int rc = sqlite3_prepare_v2(_services_DB->db, _services_DB->command, 128, &ppStmt, &pzTail);
+    if( rc!=SQLITE_OK && rc!=101 )
+        printf("SQL error(1): %d\n", rc);
+    rc = sqlite3_step(ppStmt);
+    if( rc!=SQLITE_OK && rc!=101 )
+        printf("SQL error(2): %d\n", rc);
+}
+
+/* CALLED BY: constructor
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Create and initialize a DB to hold the data sent by components
+ */
+void
+ServiceManagementLayer::CreateDataDB()
+{
+    _data_DB = (data_DB) malloc(sizeof(struct data_s));
+    char *errorMsg;
+
+    // create database
+
+    // copy filename
+    unsigned int i=0;
+    strcpy(_data_DB->filename, "Data_Table");
+
+    // execute create database command
+    // database handle
+    //_services_DB->db = NULL;
+    sqlite3_open(_data_DB->filename, &(_data_DB->db));
+    char* cols[] = {(char *)"Tag", (char *)"Data"};
+
+    // create table
+
+    // copy tablename
+    strcpy(_data_DB->tablename, "Data");
+
+    // number of columns in the table
+    _data_DB->num_columns = 2;
+
+    // generate command
+    strcpy(_data_DB->command, "CREATE TABLE ");
+    strcat(_data_DB->command, _data_DB->tablename);
+    strcat(_data_DB->command, "(");
+    strcat(_data_DB->command, cols[0]);
+    //First column is the name of the data (coresponding to the name of the output/input pair)
+    //It is the primary key so any subsequent data with the same name will replace the row
+    strcat(_data_DB->command, " TEXT PRIMARY KEY ON CONFLICT REPLACE, ");
+    strcat(_data_DB->command, cols[1]);
+    strcat(_data_DB->command, " TEXT");
+    strcat(_data_DB->command, ");");
+
+    // execute create table command
+  sqlite3_stmt *ppStmt;  /* OUT: Statement handle */
+  const char *pzTail;     /* OUT: Pointer to unused portion of zSql */
+
+    int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, 128, &ppStmt, &pzTail);
+    if( rc!=SQLITE_OK && rc!=101 )
+        printf("SQL error(1): %d\n", rc);
+    rc = sqlite3_step(ppStmt);
+    if( rc!=SQLITE_OK && rc!=101 )
+        printf("SQL error(2): %d\n", rc);
+}
+
+/* CALLED BY: MessageHandler
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Sends a message identifying this component as an SML to the Shell
+ */
+void 
+ServiceManagementLayer::SendComponentType()
+{
+    SendMessage(shellSocketFD, "response_sml");
+    LOG("SML responded to GetRemoteComponentType query.\n");
+}
+
+/* CALLED BY: constructor
+ * INPUTS: |serverName| the IPv4 name of the server (127.0.0.1 for localhost)
+ *	   |serverPort| the port on the server to connect to
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Connecting to the shell takes 2 steps
+ * 1) Establish a client socket for communication
+ * 2) Run the initial Registration/handshake routine
+ */
+void 
+ServiceManagementLayer::ConnectToShell(const char* serverName, \
+        const char* serverPort)
+{
+    shellSocketFD = ClientSocket(serverName, serverPort);
+    RegisterComponent();
+}
+
+/* CALLED BY: StartSMLServer
+ * INPUTS: |ID| The ID number of the CE that has a message wating
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Called whenever a socket is identified as being ready for communication
+ *              This funciton reads the message and calls the appropriate helper
+ */ 
+void
+ServiceManagementLayer::MessageHandler(int32_t ID)
+{
+    char buffer[256];	
+    memset(buffer, 0, 256);  
+    int32_t _FD; 
+    //printf("ID= %d\n", ID); 
+    
+    if(ID != -1)
+	_FD = CE_List[ID].FD;
+    else 
+	_FD = shellSocketFD;
+    ReadMessage(_FD, buffer);
+    /*//printf("FD=%d, shellFD=%d", _FD, shellSocketFD);
+    ssize_t msgLength = recv(_FD, buffer, 256, MSG_PEEK);
+    if(msgLength == 0){
+   	//printf("Error reading from socket.\n");
+	//sleep(5);	
+	return;
+    }
+
+
+    size_t i;
+    for(i = 0; i < 256; i++) {
+        if(strcmp(&buffer[i], "\0") == 0)
+            break;
+    }
+    // Read the message into msgBuffer
+    recv(_FD, buffer, i + 1, 0);*/
+
+    //--------Policy Engine Stuff - no policy engine support in this version-------//
+
+    //printf("********* %s **********\n", buffer);
+    // TODO
+    // If we send integer op codes rather than strings, this process will be
+    // MUCH faster since instead of donig string compares we can simply
+    // switch on the integer value...
+    /*if(strcmp(buffer, "register_service") == 0) {
+        if(strcmp(buffer, "policy_geo") == 0) {
+        }
+        else if(strcmp(buffer, "policy_time") == 0) {
+        }
+        else if(strcmp(buffer, "policy_spectrum") == 0) {
+        }
+        else if(strcmp(buffer, "policy_spacial") == 0) {
+        }
+    }
+    else if(strcmp(buffer, "deregister_service") == 0) {
+        if(strcmp(buffer, "policy_geo") == 0) {
+        }
+        else if(strcmp(buffer, "policy_time") == 0) {
+        }
+        else if(strcmp(buffer, "policy_spectrum") == 0) {
+        }
+        else if(strcmp(buffer, "policy_spacial") == 0) {
+        }
+    }*/
+
+    //Go down the list to call the appropriate function
+    if(strcmp(buffer, "query_component_type") == 0) {
+        SendComponentType();
+    }
+    else if(strcmp(buffer, "reset_sml") == 0) {
+        Reset();
+    }
+    else if(strcmp(buffer, "shutdown_sml") == 0) {
+        Shutdown();
+    }
+    else if(strcmp(buffer, "register_engine_cognitive") == 0) {
+     	RegisterCognitiveEngine(ID);
+    }
+    else if(strcmp(buffer, "register_service") == 0) {
+ 	ReceiveServices(ID);
+    }
+    else if(strcmp(buffer, "send_component_type") == 0) {
+ 	SendComponentType();
+    }
+    else if(strcmp(buffer, "list_services") == 0) {
+ 	ListServices();
+    }
+    else if(strcmp(buffer, "set_active_mission") == 0) {
+	SetActiveMission();
+    }
+    else if(strcmp(buffer, "request_optimization") == 0) {
+	PerformActiveMission();
+    }
+    else if(strcmp(buffer, "deregister_engine_cognitive") == 0) {
+	DeregisterServices(ID);
+	DeregisterCognitiveEngine(ID);
+    }
+}
+
+//TODO Finish
+/* CALLED BY: MessageHandler
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Deregisters the component from the Shell.
+ */ 
+void 
+ServiceManagementLayer::Shutdown()
+{
+    DeregisterComponent();
+}
+
+//TODO Finish
+/* CALLED BY: MessageHandler
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Deregisters the component from the Shell
+ */
+void 
+ServiceManagementLayer::Reset()
+{
+    DeregisterComponent();
+    LoadConfiguration(_SML_Config, miss);
+}
+
+/* CALLED BY: ConnectToShell
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Sends the registration message to the Shell
+ */
+void 
+ServiceManagementLayer::RegisterComponent()
+{
+    SendMessage(shellSocketFD, "register_sml");
+    LOG("ServiceManagementLayer:: Registration message sent.\n");
+}
+
+/* CALLED BY: Shutdown
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Closes the client socket with the shell, sends a deregstration message
+ */
+void 
+ServiceManagementLayer::DeregisterComponent()
+{
+    SendMessage(shellSocketFD, "deregister_sml");
+    LOG("ServiceManagementLayer:: Deregistration message sent.\n");
+
+    shutdown(shellSocketFD, 2);
+    close(shellSocketFD);
+    shellSocketFD = -1;
+    LOG("ServiceManagementLayer:: Shell socket closed.\n");
+}
+
+
+/* CALLED BY: RegisterCognitiveEngine
+ * INPUTS: |ID| The ID number of the component where the data is to be transfered to
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Streams config data directly from the shell to the CE, and checks
+ * for an "ack" message from the CE after every sent message 
+ * to know when to stop communication.
+ */
+
+//TODO backwards check instead of forwords check to avoid waiting every data loop?
+void 
+ServiceManagementLayer::TransferRadioConfiguration(int32_t ID)
+{
+    struct timeval selTimeout;
+    fd_set sockSet;
+    int32_t rc = 0;
+    char buffer[256];
+    //Send data until the CE sends an ACK message back
+    while(rc==0){
+        memset(buffer, 0, 256);
+	//Receive data from Shell
+	ReadMessage(shellSocketFD, buffer);
+	//Send data to CE
+	SendMessage(CE_List[ID].FD, buffer);
+        FD_ZERO(&sockSet);
+        FD_SET(CE_List[ID].FD, &sockSet);
+        selTimeout.tv_sec = 0;
+        selTimeout.tv_usec = 50000;
+        //Check if there is a message on the CE socket ready to be processed
+        rc=select(CE_List[ID].FD + 1, &sockSet, NULL, NULL, &selTimeout);
+    }
+    memset(buffer, 0, 256);
+    ReadMessage(CE_List[ID].FD, buffer);
+    SendMessage(shellSocketFD, buffer);
+}
+
+
+/* CALLED BY: RegisterCognitiveEngine
+ * INPUTS: |ID| The ID number of the component where the data is to be transfered to
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Simmilar to TransferRadioConfig, just with Experience data
+ */
+void 
+ServiceManagementLayer::TransferExperience(int32_t ID)
+{
+    struct timeval selTimeout;
+    fd_set sockSet;
+    int32_t rc = 0;
+    char buffer[256];
+    //Send data until the CE sends an ACK message back
+    while(rc==0){
+        memset(buffer, 0, 256);
+	//Receive data from Shell
+	ReadMessage(shellSocketFD, buffer);
+	//Send data to CE
+	SendMessage(CE_List[ID].FD, buffer);
+        FD_ZERO(&sockSet);
+        FD_SET(CE_List[ID].FD, &sockSet);
+        selTimeout.tv_sec = 0;
+        selTimeout.tv_usec = 50000;
+        //Check if there is a message on the CE socket ready to be processed
+        rc = select(CE_List[ID].FD + 1, &sockSet, NULL, NULL, &selTimeout);
+    }
+    memset(buffer, 0, 256);
+    ReadMessage(CE_List[ID].FD, buffer);
+    SendMessage(shellSocketFD, buffer);
+}
+
+/* CALLED BY: MessageHandler
+ * INPUTS: |ID| The ID number of the component where service is located
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Inserts a service into the DB with the ID of the component where it exists
+ */
+void 
+ServiceManagementLayer::ReceiveServices(int32_t ID)
+{
+    char buffer[256];
+    memset(buffer, 0, 256);
+    ReadMessage(CE_List[ID].FD, buffer);
+    char* cols[] = {(char *)"ID_Num", (char *)"Service_Name"};
+    
+    // generate command
+    //printf("%s\n", _services_DB->command);
+    strcpy(_services_DB->command, "insert into ");
+    strcat(_services_DB->command, _services_DB->tablename); 
+    strcat(_services_DB->command, " (");
+    strcat(_services_DB->command, cols[0]);
+    strcat(_services_DB->command, ", ");
+    strcat(_services_DB->command, cols[1]);
+    strcat(_services_DB->command, ") ");
+    strcat(_services_DB->command, " values(");
+    sprintf(_services_DB->command, "%s%d", _services_DB->command, ID);
+    strcat(_services_DB->command, ", '");
+    strcat(_services_DB->command, buffer);
+    strcat(_services_DB->command, "');");
+    
+    //printf("search command: %s\n", _services_DB->command);
+    // execute add command
+    char *errorMsg;
+    int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "SQL error: %s\n", errorMsg);
+    printf("SML: Registering service '%s' from component number '%d'\n", buffer, ID);
+
+}
+
+/* CALLED BY: MessageHandler
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: This method associates the services that components provide with the services that are requested in the mission
+ * Each service in the mission is given the ID and FD of a component that has registered to provide that service 
+ * Deregistration is okay until this method is called without a reload, but if deregistration occurs after this
+ * method is called it needs to be called again even if other engines also provide the services
+ */
+void 
+ServiceManagementLayer::SetActiveMission()
+{
+    char buffer[256];
+    memset(buffer, 0, 256);
+    ReadMessage(shellSocketFD, buffer);
+    int32_t missID = atoi(buffer);
+    for(activeMission = 0; activeMission < 10; activeMission++)
+    {
+	//Find the active mission by comparing mission ID's
+	if(miss[activeMission].missionID == missID)
+	    break;
+    }
+    //For each service in the mission
+    for(int i = 0; i < miss[activeMission].numServices; i++)
+    {	
+	//Check whether the current service is an actual service or a conditional
+	if(miss[activeMission].services[i].name.compare("if") && miss[activeMission].services[i].name.compare("while")){
+	    //If it is a service, search the database of registered services to find the ID of the component that registered it
+    	    strcpy(_services_DB->command, "select ");
+   	    strcat(_services_DB->command, _services_DB->tablename);
+    	    strcat(_services_DB->command, ".* from ");
+    	    strcat(_services_DB->command, _services_DB->tablename);
+    	    strcat(_services_DB->command, " where Service_Name==");
+	    sprintf(_services_DB->command, "%s'%s';", _services_DB->command, miss[activeMission].services[i].name.c_str());
+	
+            sqlite3_stmt * pStatement;
+            int rc = sqlite3_prepare_v2(_services_DB->db, _services_DB->command, -1, &pStatement, NULL);
+            if (rc == SQLITE_OK){ 
+                if (sqlite3_step(pStatement) == SQLITE_ROW)
+	             miss[activeMission].services[i].componentID =  sqlite3_column_int(pStatement, 0); 
+                else {
+	            printf("services_DB:: Mission requires service not provided by any connected component.\n");
+		    rc=31337;
+	        }
+             } else {
+	        printf("services_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_services_DB->command);
+            }
+
+            sqlite3_finalize(pStatement);
+	    miss[activeMission].services[i].socketFD = CE_List[miss[activeMission].services[i].componentID].FD;
+	    //Set the FD and ID of the service to refer to the component where the service exists
+	}
+	//Nothing to be done for conditionals at this stage
+    }
+
+
+    printf("\nhere ---%d, %d---\n", miss[activeMission].services[0].componentID, miss[activeMission].services[1].componentID);
+}
+
+/* CALLED BY: PerformActiveMission
+ * INPUTS: |sourceID| ID of the service that is being processed
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: This is a helper method for the "PerformActiveMission" function
+ * NOTE: This function has changed durrastically from the previous implementation
+ * Takes an ID of a service
+ * For that service, finds inputs in DB and forwords those on to the engine after sending comm-starting messages
+ * Afterwords, listenes for the outputs so that it can store those in the database for future services or the overall output
+ */
+void
+ServiceManagementLayer::TransactData(int32_t sourceID)
+{
+    printf("transactData\n");
+    char buffer[256];
+    std::string data;
+    char* cols[] = {(char *)"Tag", (char *)"Data"};
+    int i = 0;
+    fd_set sockSet;
+    struct timeval selTimeout;
+    //Transmission starting messages
+    SendMessage(miss[activeMission].services[sourceID].socketFD, "request_optimization_service");
+    SendMessage(miss[activeMission].services[sourceID].socketFD, miss[activeMission].services[sourceID].name.c_str());
+    //Find and load the input data
+    while(i < 3 && !miss[activeMission].services[sourceID].input[i].empty()){
+	printf("pulling input data out of DB for ID#=%d\n", sourceID);
+        strcpy(_data_DB->command, "select ");
+   	strcat(_data_DB->command, _data_DB->tablename);
+    	strcat(_data_DB->command, ".* from ");
+    	strcat(_data_DB->command, _data_DB->tablename);
+    	strcat(_data_DB->command, " where Tag==");
+	sprintf(_data_DB->command, "%s'%s';", _data_DB->command, miss[activeMission].services[sourceID].input[i].c_str());
+        sqlite3_stmt * pStatement;
+        int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, -1, &pStatement, NULL);
+        if (rc == SQLITE_OK){ 
+            if (sqlite3_step(pStatement) == SQLITE_ROW)
+	         data.append((const char*) sqlite3_column_text(pStatement, 1)); 
+            else {
+	            printf("data_DB:: Data not yet in DB.\n");
+		    rc=31337;
+	    }
+        } 
+	else {
+	    printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command);
+        }
+
+        sqlite3_finalize(pStatement);
+	char *data_ch = (char *) data.c_str();
+	//Tokenize the data and pass it along
+	char *token = strtok(data_ch, "@");
+	while(token){
+	    SendMessage(miss[activeMission].services[sourceID].socketFD, token);
+	    token = strtok(NULL, "@");
+	}
+	printf("done pulling input data out of DB for ID#=%d\n", sourceID);
+	i++;
+    }
+
+    int32_t j = 0;
+    FD_ZERO(&sockSet);
+    FD_SET(miss[activeMission].services[sourceID].socketFD, &sockSet);
+    //TODO neccessary?
+    selTimeout.tv_sec = 5;
+    selTimeout.tv_usec = 0;
+    //Use select command to force wait for processing to finish
+    select(miss[activeMission].services[sourceID].socketFD + 1, &sockSet, NULL, NULL, &selTimeout);
+    data.clear();
+    while(j < 3 && !miss[activeMission].services[sourceID].output[j].empty()){
+	int rc;
+	while(true){
+	    //Read the data incrementally and deliminate it with the "@" symbol
+	    memset(buffer, 0, 256);
+	    ReadMessage(miss[activeMission].services[sourceID].socketFD, buffer);
+	    if(strcmp(buffer, "output_finished")==0)
+		break;
+	    data.append(buffer);
+	    data.append("@");
+	}
+	printf("SML: putting output data into DB for ID#=%d\n", sourceID);
+
+	strcpy(_data_DB->command, "insert or replace into ");
+    	strcat(_data_DB->command, _data_DB->tablename); 
+      	strcat(_data_DB->command, " (");
+    	strcat(_data_DB->command, cols[0]);
+    	strcat(_data_DB->command, ", ");
+	strcat(_data_DB->command, cols[1]);
+	strcat(_data_DB->command, ") ");
+	strcat(_data_DB->command, " values('");	
+	strcat(_data_DB->command, miss[activeMission].services[sourceID].output[j].c_str());
+	strcat(_data_DB->command, "', '");
+	strcat(_data_DB->command, data.c_str());
+	strcat(_data_DB->command, "');");
+    	char *errorMsg;
+   	rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg);
+   	if( rc!=SQLITE_OK && rc!=101 )
+   	    fprintf(stderr, "SQL error: %s\n", errorMsg);
+        printf("SML: done putting ouptut data into DB for ID#='%d'\n", sourceID);
+	j++;
+    }
+    printf("done transact data!\n");
+}
+
+
+
+/* CALLED BY: MessageHandler
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: This function works by first sending the inputs from the shell to the appropriate components
+ * The first service should begin immeadiately, as should any others who have all of their input paramaters
+ * When they complete, the output path is found and the data is transfered as it becomes available
+ * Presumably at this point the second function has all of it's paramaters, so it begins to compute, and the cycle repeats
+ * If the generated output is an overall output, it is sent on to the shell
+ * "if" and "while" statements are handled by setting up a faux service that has a true input, a false input, and a boolean flag
+ * If the true input is non-NULL and the flag is true, the statements execute
+ * Likewise, if the false input is non-NULL and the flag is false, the statements execute
+ * These flags are set during execution any time one of these faux services' inputs appear in an output statement  
+ *  
+ * 
+ * Rules for active missions (currently)
+ * -Three inputs/outputs per service and per mission
+ * -Inputs simply define a path, so multiple variables can be transmitted over the same input
+ * -Each component that sends data must include the "output_finished" statement after each output is finished sending it's data
+ * -All ordering constraints have been relaxed in this version; all data is stored locally and only sent when requested
+ * -If support fully implemented
+ * -Conditions must be boolean flags
+ * -Flags are set by putting either the character string "true" or "false" on the buffer
+ * -IMPORTANT: DB uses '@' to seperate individual statements; using '@' in the data stream will result in incorrect behavior
+ */
+void
+ServiceManagementLayer::PerformActiveMission()
+{
+    //TODO verify while
+    int i = 0;
+    std::string data;
+    std::string input;
+    std::string check;
+    char buffer[256];
+    fd_set sockSet;
+    char* cols[] = {(char *)"Tag", (char *)"Data"};
+    struct timeval selTimeout;
+    //Get the inputs
+    while(i < 3 && !miss[activeMission].input[i].empty()){
+	    //New data being added to DB
+	printf("inserting data from shell\n");
+	int rc;
+	while(true){
+	    memset(buffer, 0, 256);
+	    ReadMessage(shellSocketFD, buffer);
+	    if(strcmp(buffer, "input_finished")==0)
+		break;
+	    data.append(buffer);
+	    data.append("@");
+	    /*FD_ZERO(&sockSet);
+	    FD_SET(miss[activeMission].services[sourceID].socketFD, &sockSet);
+	    selTimeout.tv_sec = 0;
+	    selTimeout.tv_usec = 50000;
+	    //Check if there is a message on the CE socket ready to be processed
+	    rc=select(miss[activeMission].services[sourceID].socketFD + 1, &sockSet, NULL, NULL, &selTimeout);*/
+	}//while(rc!=0);;
+
+	strcpy(_data_DB->command, "insert into ");
+    	strcat(_data_DB->command, _data_DB->tablename); 
+      	strcat(_data_DB->command, " (");
+    	strcat(_data_DB->command, cols[0]);
+    	strcat(_data_DB->command, ", ");
+	strcat(_data_DB->command, cols[1]);
+	strcat(_data_DB->command, ") ");
+	strcat(_data_DB->command, " values('");
+	strcat(_data_DB->command, miss[activeMission].input[i].c_str());
+	strcat(_data_DB->command, "', '");
+	strcat(_data_DB->command, data.c_str());
+	strcat(_data_DB->command, "');");
+    	char *errorMsg;
+   	rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg);
+   	if( rc!=SQLITE_OK && rc!=101 )
+   	    fprintf(stderr, "SQL error: %s\n", errorMsg);
+        printf("SML: finished adding data from shell on input %d\n", i);
+        i++;
+
+    }
+    i=0;
+    data.clear();
+    while(i < miss[activeMission].numServices)
+    {
+	if(miss[activeMission].services[i].name.compare("if")==0)
+	{
+	    printf("if detected\n");
+	    input.clear();
+	    check.clear();
+	    if(!miss[activeMission].services[i].input[0].empty()){
+		input=miss[activeMission].services[i].input[0];
+		check = "true@";
+	    }
+	    else{
+		input=miss[activeMission].services[i].input[1];
+		check = "false@";
+	    }
+            strcpy(_data_DB->command, "select ");
+   	    strcat(_data_DB->command, _services_DB->tablename);
+    	    strcat(_data_DB->command, ".* from ");
+    	    strcat(_data_DB->command, _services_DB->tablename);
+    	    strcat(_data_DB->command, " where Tag==");
+	    sprintf(_data_DB->command, "%s'%s';", _data_DB->command, input.c_str());
+            sqlite3_stmt * pStatement;
+            int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, -1, &pStatement, NULL);
+            if (rc == SQLITE_OK){ 
+                if (sqlite3_step(pStatement) == SQLITE_ROW)
+	             data = (const char *) sqlite3_column_text(pStatement, 1); 
+                else {
+	                printf("1 data_DB:: Data not yet in DB. %d\n", i);
+		        rc=31337;
+	        }
+            } else {
+	        printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command);
+            }
+
+    	    sqlite3_finalize(pStatement);
+	    printf("data=%s, check=%s\n", data.c_str(), check.c_str());
+	    if(data.compare(check)==0){
+		printf("if taken\n");
+		for(int k = i + 1; k < i + miss[activeMission].services[i].num_conds; k++)
+		    TransactData(k);
+	    }
+	    else{
+		i+=miss[activeMission].services[i].num_conds;
+		printf("if not taken %d\n", miss[activeMission].services[i].num_conds);
+	    }
+	}
+	//TODO test while
+	else if(miss[activeMission].services[i].name.compare("while")==0)
+	{
+	    printf("while detected\n");
+	    input.clear();
+	    check.clear();
+	    while(true){
+		    if(!miss[activeMission].services[i].input[0].empty()){
+			input=miss[activeMission].services[i].input[0];
+			check = "true@";
+		    }
+		    else{
+			input=miss[activeMission].services[i].input[1];
+			check = "false@";
+		    }
+		    strcpy(_data_DB->command, "select ");
+	   	    strcat(_data_DB->command, _services_DB->tablename);
+	    	    strcat(_data_DB->command, ".* from ");
+	    	    strcat(_data_DB->command, _services_DB->tablename);
+	    	    strcat(_data_DB->command, " where Tag==");
+		    sprintf(_data_DB->command, "%s'%s';", _data_DB->command, input.c_str());
+		    sqlite3_stmt * pStatement;
+		    int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, -1, &pStatement, NULL);
+		    if (rc == SQLITE_OK){ 
+		        if (sqlite3_step(pStatement) == SQLITE_ROW)
+			    data = (const char *) sqlite3_column_text(pStatement, 1); 
+		        else 
+			    printf("1 data_DB:: Data not yet in DB. %d\n", i);
+		    } 
+		    else {
+			printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command);
+		    }
+
+	    	    sqlite3_finalize(pStatement);
+		    printf("data=%s, check=%s\n", data.c_str(), check.c_str());
+		    if(data.compare(check)==0){
+			printf("while taken\n");
+			for(int k = i + 1; k < i + miss[activeMission].services[i].num_conds; k++)
+			    TransactData(k);
+		    }
+		    else{
+			i+=miss[activeMission].services[i].num_conds;
+			printf("if not taken %d\n", miss[activeMission].services[i].num_conds);
+			break;
+		    }
+	    }
+	}
+	else{
+	    TransactData(i);}
+	i++;
+    }
+    i=0;
+    data.clear();
+    //get the ouptuts
+    while(i < 3 && !miss[activeMission].output[i].empty()){
+	printf("sending output data to shell\n");
+        strcpy(_data_DB->command, "select ");
+   	strcat(_data_DB->command, _data_DB->tablename);
+    	strcat(_data_DB->command, ".* from ");
+    	strcat(_data_DB->command, _data_DB->tablename);
+    	strcat(_data_DB->command, " where Tag==");
+	sprintf(_data_DB->command, "%s'%s';", _data_DB->command, miss[activeMission].output[i].c_str());
+        sqlite3_stmt * pStatement;
+        int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command, -1, &pStatement, NULL);
+        if (rc == SQLITE_OK){ 
+            if (sqlite3_step(pStatement) == SQLITE_ROW)
+	         data.append((const char*) sqlite3_column_text(pStatement, 1)); 
+            else {
+	            printf("data_DB:: Data not yet in DB.\n");
+		    rc=31337;
+	    }
+        } 
+	else {
+	    printf("services_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command);
+        }
+        sqlite3_finalize(pStatement);
+	char *data_ch = (char *) data.c_str();
+	char *token = strtok(data_ch, "@");
+	while(token){
+	    SendMessage(shellSocketFD, token);
+	    token = strtok(NULL, "@");
+	}
+	i++;
+	printf("done sending output data to shell\n");
+    }
+}
+
+
+/* CALLED BY: MessageHandler
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Print a list of the services currently registered and the ID's of the components that registered them
+ */
+void 
+ServiceManagementLayer::ListServices()
+{
+    // generate commandi
+    strcpy(_services_DB->command, "select ");
+    strcat(_services_DB->command, _services_DB->tablename);
+    strcat(_services_DB->command, ".* from ");
+    strcat(_services_DB->command, _services_DB->tablename);
+    strcat(_services_DB->command, ";");
+
+    // execute print (select all)  command    
+    char *errorMsg;
+    int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "SQL error: %s\n", errorMsg);
+    printf("database %s, table %s:\n", _services_DB->filename, _services_DB->tablename);
+}
+
+/* CALLED BY: Reset
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Clear and reinitialize the mission array, then reload the configuration file
+ */
+void 
+ServiceManagementLayer::ReloadConfiguration()
+{
+    LOG("ServiceManagementLayer:: Reloading Configuration.\n");
+    free(miss);
+    miss = new Mission[10];
+    for(int i = 0; i < 10; i++)
+    	miss[i].services = new Service[20];
+    LoadConfiguration(_SML_Config, miss);
+}
+
+/* CALLED BY: constructor, Reset
+ * INPUTS: |SML_Config| Address (either relitive or full) of the XML file containing mission data
+ * 	   |mList| Mission array to be modified 
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: IMPORTANT - See formatting instructions for correct parsing of data
+ * Can currently handle 3 inputs and 3 outputs per service, but easily expandable
+ * Also, can handle one layer of nested conditional statements, but could
+ * be expanded to meet additional needs.  Only support now is for straight bool flags,
+ * but support could be added for more complex conditionals later.
+ * 
+ * Components assigned to mission during "set active mission" stage so that
+ * components can still continue to register after the configuration is loaded
+ */
+void 
+ServiceManagementLayer::LoadConfiguration(const char *SML_Config, Mission* &mList)
+{
+    TiXmlElement *pMission;
+    TiXmlElement *pService;
+    TiXmlElement *pChild0, *pChild1, *pChild2, *pChild3;
+    TiXmlHandle hRoot(0);
+    //printf("ServiceManagementLayer:: Loading Configuration.\n");
+    TiXmlDocument doc(".");
+    doc.LoadFile(SML_Config);
+    bool loadOkay = doc.LoadFile();
+    if(!loadOkay)
+        printf("Loading SML configuration failed: %s\n", SML_Config);
+
+    TiXmlHandle hDoc(&doc);
+    
+    pMission = hDoc.FirstChildElement().Element();
+
+    if(!pMission) 
+        printf("No valid root!");
+
+    hRoot = TiXmlHandle(pMission);
+    pService = pMission->FirstChildElement();
+    int32_t mission_num = 0;
+    //Iterate through the missions
+    for(pChild0 = pMission->FirstChildElement(); pChild0 ; \
+        pChild0 = pChild0->NextSiblingElement()) 
+    {
+	int32_t service_num = 0;
+	uint16_t cond_array[] = {0, 0};
+	//printf("mission_num = %d\n", mission_num);
+	memset(cond_array, 0, 2);
+	
+    	for(pChild1  = pChild0->FirstChildElement(); pChild1; \
+      	    pChild1  = pChild1->NextSiblingElement()) 
+    	{
+	    int32_t conditional_0 = service_num;
+	    for(pChild2 = pChild1->FirstChildElement(); \
+		pChild2; pChild2 = pChild2->NextSiblingElement())
+	    {
+		service_num++;
+		int32_t conditional_1 = service_num;
+		for(pChild3 = pChild2->FirstChildElement(); \
+		    pChild3; pChild3 = pChild3 ->NextSiblingElement())
+		{
+		    service_num++;
+		    mList[mission_num].services[service_num].name = pChild3->Attribute("name");
+                    if(pChild3->Attribute("input1"))
+			mList[mission_num].services[service_num].input[0] = pChild3->Attribute("input1");
+                    if(pChild3->Attribute("input2"))
+			mList[mission_num].services[service_num].input[1] = pChild3->Attribute("input2");
+                    if(pChild3->Attribute("input3"))
+			mList[mission_num].services[service_num].input[2] = pChild3->Attribute("input3");
+                    if(pChild3->Attribute("output1"))
+			mList[mission_num].services[service_num].output[0] = pChild3->Attribute("output1");
+                    if(pChild3->Attribute("output2"))
+			mList[mission_num].services[service_num].output[1] = pChild3->Attribute("output2");
+                    if(pChild3->Attribute("output3"))
+			mList[mission_num].services[service_num].output[2] = pChild3->Attribute("output3");
+		    cond_array[1]++;
+		}
+
+		if(conditional_1 != service_num){
+		    mList[mission_num].services[conditional_1].name = pChild2->Value();
+                    if(pChild2->Attribute("input_t"))
+			mList[mission_num].services[conditional_1].input[0] = pChild2->Attribute("input_t");
+                    if(pChild2->Attribute("input_f"))
+			mList[mission_num].services[conditional_1].input[1] = pChild2->Attribute("input_f");
+		}
+		else{
+		    mList[mission_num].services[conditional_1].name = pChild2->Attribute("name");
+                    if(pChild2->Attribute("input1"))
+			mList[mission_num].services[service_num].input[0] = pChild2->Attribute("input1");
+                    if(pChild2->Attribute("input2"))
+			mList[mission_num].services[service_num].input[1] = pChild2->Attribute("input2");
+                    if(pChild2->Attribute("input3"))
+			mList[mission_num].services[service_num].input[2] = pChild2->Attribute("input3");
+                    if(pChild2->Attribute("output1"))
+			mList[mission_num].services[service_num].output[0] = pChild2->Attribute("output1");
+                    if(pChild2->Attribute("output2"))
+			mList[mission_num].services[service_num].output[1] = pChild2->Attribute("output2");
+                    if(pChild2->Attribute("output3"))
+			mList[mission_num].services[service_num].output[2] = pChild2->Attribute("output3");
+		}
+
+		mList[mission_num].services[conditional_1].num_conds = cond_array[1];
+printf("hello\n");
+		cond_array[1] = 0;
+		cond_array[0]++;
+	    }
+	    if(conditional_0 != service_num){
+		mList[mission_num].services[conditional_0].name = pChild1->Value();
+                    if(pChild1->Attribute("input_t"))
+			mList[mission_num].services[conditional_0].input[0] = pChild1->Attribute("input_t");
+                    if(pChild1->Attribute("input_f"))
+			mList[mission_num].services[conditional_0].input[1] = pChild1->Attribute("input_f");
+		printf("---input_t=%s\n", mList[mission_num].services[conditional_0].input[0].c_str());
+	    }
+	    else{
+		mList[mission_num].services[conditional_0].name = pChild1->Attribute("name");
+                if(pChild1->Attribute("input1"))
+	            mList[mission_num].services[service_num].input[0] = pChild1->Attribute("input1");
+                if(pChild1->Attribute("input2"))
+		    mList[mission_num].services[service_num].input[1] = pChild1->Attribute("input2");
+                if(pChild1->Attribute("input3"))
+		    mList[mission_num].services[service_num].input[2] = pChild1->Attribute("input3");
+                if(pChild1->Attribute("output1"))
+		    mList[mission_num].services[service_num].output[0] = pChild1->Attribute("output1");
+                if(pChild1->Attribute("output2"))
+		    mList[mission_num].services[service_num].output[1] = pChild1->Attribute("output2");
+                if(pChild1->Attribute("output3"))
+		    mList[mission_num].services[service_num].output[2] = pChild1->Attribute("output3");
+	    }
+
+	    mList[mission_num].services[conditional_0].num_conds = cond_array[0];
+	    //printf("hello\n");
+            cond_array[0] = 0;
+	    service_num++;
+	}
+	for(int i = 0; i < service_num; i++)
+		printf("%d, input1=%s, output1=%s\n", i, mList[mission_num].services[i].input[0].c_str(), mList[mission_num].services[i].output[0].c_str());
+
+	mList[mission_num].numServices = service_num;
+	mList[mission_num].name = pChild0->Attribute("name");
+	mList[mission_num].missionID = atoi(pChild0->Attribute("id"));
+        if(pChild0->Attribute("input1"))
+	    mList[mission_num].input[0] = pChild0->Attribute("input1");
+        if(pChild0->Attribute("input2"))
+	    mList[mission_num].input[1] = pChild0->Attribute("input2");
+        if(pChild0->Attribute("input3"))
+	    mList[mission_num].input[2] = pChild0->Attribute("input3");
+        if(pChild0->Attribute("output1"))
+	    mList[mission_num].output[0] = pChild0->Attribute("output1");
+        if(pChild0->Attribute("output2"))
+	    mList[mission_num].output[1] = pChild0->Attribute("output2");
+        if(pChild0->Attribute("output3"))
+	    mList[mission_num].output[2] = pChild0->Attribute("output3");
+	printf("mis, input1=%s, output1=%s\n", mList[mission_num].input[0].c_str(), mList[mission_num].output[0].c_str());
+	mission_num++;
+    }
+}
+
+/* CALLED BY: MessageHandler
+ * INPUTS: |ID| The ID number of the engine to be registered
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Sends a registration message onto the shell and sends the ACK back to the component
+ */
+void
+ServiceManagementLayer::RegisterCognitiveEngine(int32_t ID)
+{
+    SendMessage(shellSocketFD, "register_engine_cognitive");
+    LOG("ServiceManagementLayer:: CE registration message forwarded to shell.\n");
+    char buffer[256];
+    memset(buffer, 0, 256);
+    ReadMessage(shellSocketFD, buffer);
+    SendMessage(CE_List[ID].FD, buffer);
+
+    //TODO UNCOMMENT!!!
+    //TODO UNCOMMENT!!!
+    /*TransferRadioConfiguration(ID);
+    memset(buffer, 0, 256);
+    TransferExperience(ID);
+    memset(buffer, 0, 256);*/
+    numberOfCognitiveEngines++;
+    CE_Present = true;
+}
+
+/* CALLED BY: MessageHandler
+ * INPUTS: |ID| The ID number of the engine to have it's services deregistered
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Deleates the services from the DB coresponding to the component ID
+ */
+//----NOTE----
+//The behavior of this method is different than described in the documentation.
+//This function deregisteres all of the services when a component deregistes,
+//whereas the one in the documentation describes a function where an individual
+//service is deregistered.  This may be changed in the future.
+void 
+ServiceManagementLayer::DeregisterServices(int32_t ID)
+{
+    strcpy(_services_DB->command, "DELETE FROM ");
+    strcat(_services_DB->command, _services_DB->tablename);
+    strcat(_services_DB->command, " WHERE ");
+    strcat(_services_DB->command, "ID_Num");
+    strcat(_services_DB->command, "==");
+    sprintf(_services_DB->command, "%s%d;", _services_DB->command, ID);
+    char *errorMsg;
+    int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg);
+    if( rc!=SQLITE_OK && rc!=101 )
+        fprintf(stderr, "SQL error: %s\n", errorMsg);
+}
+
+/* CALLED BY: MessageHandler
+ * INPUTS: |ID| The ID number of the engine to have it's services deregistered
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Deletes the contact info for the cognitive engine, forwards a deregistration message to the shell
+ */
+void 
+ServiceManagementLayer::DeregisterCognitiveEngine(int32_t ID)
+{
+    LOG("ServiceManagementLayer:: CE deregistration message forwarded to shell.\n");
+
+    numberOfCognitiveEngines--;
+    if(numberOfCognitiveEngines == 0)
+        CE_Present = false;
+
+    SendMessage(shellSocketFD, "deregister_engine_cognitive");
+    char buffer[256];
+    memset(buffer, 0, 256);
+    ReadMessage(shellSocketFD, buffer);
+    SendMessage(CE_List[ID].FD, buffer);
+    if(strcmp("deregister_ack", buffer) != 0) {
+	ERROR(1, "SML:: Failed to close CE socket\n");
+    }
+    CE_List[ID].FD = -1;
+    CE_List[ID].ID_num = -1;
+
+    LOG("Cognitive Radio Shell:: Socket closed.\n");
+}
+
+
+/* CALLED BY: test class
+ * INPUTS: <none>
+ * OUTPUTS: <none>
+ *
+ * DESCRIPTION: Sets up a server socket and listens for communication on either that or the shell socket
+ */
+void
+ServiceManagementLayer::StartSMLServer()
+{
+    struct timeval selTimeout;
+    int32_t running = 1;
+    int32_t port, rc, new_sd = 1;
+    int32_t desc_ready = 1;
+    int32_t timeout = 10;
+		//If there is, call the MessageHandler with the Shell_Msg code of -1
+    fd_set sockSet, shellSet;
+
+    cogEngSrv = CreateTCPServerSocket(2044);
+    int32_t maxDescriptor = cogEngSrv;
+
+    if(InitializeTCPServerPort(cogEngSrv) == -1)
+        ERROR(1,"Error initializing primary port\n");
+
+    int i = 10000000;
+    while (i>0) {
+        i--;
+        /* Zero socket descriptor vector and set for server sockets */
+        /* This must be reset every time select() is called */
+        FD_ZERO(&sockSet);
+        FD_SET(cogEngSrv, &sockSet);
+        for(int k = 0; k < Current_ID; k++){
+	    if(CE_List[k].ID_num != -1)
+	        FD_SET(CE_List[k].FD, &sockSet);
+	}
+	    //printf("k=%d, CID=%d\n", k, CE_List[k].FD);
+
+        /* Timeout specification */
+        /* This must be reset every time select() is called */
+        selTimeout.tv_sec = 0;       /* timeout (secs.) */
+        selTimeout.tv_usec = 0;            /* 0 microseconds */
+	//Changed both to zero so that select will check messages from the shell instead of blocking
+	//when there is no command from the CE's to be processed
+
+        //Check if there is a message on the socket waiting to be read
+	rc = select(maxDescriptor + 1, &sockSet, NULL, NULL, &selTimeout); 
+        //printf("rc=%d\n", rc);
+        if(rc == 0){
+            //LOG("No echo requests for %i secs...Server still alive\n", timeout);
+	
+            FD_ZERO(&shellSet);
+            FD_SET(shellSocketFD, &shellSet);
+            selTimeout.tv_sec = 0;
+            selTimeout.tv_usec = 0;
+            //Check if there is a message on the shell socket ready to be processed
+            int rc2 = select(shellSocketFD + 1, &shellSet, NULL, NULL, &selTimeout);
+            //printf("rc2=%d\n", rc2);
+		//If there is, call the MessageHandler with the Shell_Msg code of -1
+	    if(FD_ISSET(shellSocketFD, &shellSet)){
+		//printf("shell_msg, %d\n", rc2);
+	        MessageHandler(-1);}
+	}
+        else { 
+            desc_ready = rc;
+            for(port = 0; port <= maxDescriptor && desc_ready > 0; port++) {
+                if(FD_ISSET(port, &sockSet)) {
+                    desc_ready -= 1;
+
+                    //Check if request is new or on an existing open descriptor
+                    if(port == cogEngSrv) { 
+			//If new, assign it a descriptor and give it an ID
+                        new_sd = AcceptTCPConnection(port);
+			 
+                        if(new_sd < 0) 
+                            break;
+
+                        CE_List[Current_ID].FD = new_sd;
+			CE_List[Current_ID].ID_num = Current_ID;
+                        MessageHandler(Current_ID);
+			Current_ID++;
+	
+			FD_SET(new_sd,&sockSet);
+                        if(new_sd > maxDescriptor) 
+                           maxDescriptor = new_sd;
+                    } 
+                    else {
+			//If old, figure out which ID it coresponds to and handle it accordingly
+			for(int16_t z = 0; z < Current_ID; z++)
+			{
+				if(CE_List[z].FD == port){
+					MessageHandler(z);}
+			}
+                    }
+                }
+            }
+	}
+    }        
+
+    /* Close sockets */
+    close(cogEngSrv);
+
+    //delete &cogEngSrv;
+    return;
+}
+
+
+
+
+    /*TiXmlElement *pMission;
+    TiXmlElement *pService;
+    TiXmlElement *pChild0, *pChild1, *pChild2, *pChild3;
+    TiXmlHandle hRoot(0);
+    //printf("ServiceManagementLayer:: Loading Configuration.\n");
+    TiXmlDocument doc(".");
+    doc.LoadFile(SML_Config);
+    bool loadOkay = doc.LoadFile();
+    if(!loadOkay)
+        printf("Loading SML configuration failed: %s\n", SML_Config);
+
+    TiXmlHandle hDoc(&doc);
+    
+    pMission = hDoc.FirstChildElement().Element();
+
+    if(!pMission) 
+        printf("No valid root!");
+
+    hRoot = TiXmlHandle(pMission);
+    pService = pMission->FirstChildElement();
+    int32_t mission_num = 0;
+    //Iterate through the missions
+    for(pChild0 = pMission->FirstChildElement(); pChild0 ; \
+        pChild0 = pChild0->NextSiblingElement()) 
+    {
+	int32_t service_num = 0;
+	uint16_t cond_array[] = {0, 0};
+	//printf("mission_num = %d\n", mission_num);
+	memset(cond_array, 0, 2);
+	
+    	for(pChild1  = pChild0->FirstChildElement(); pChild1; \
+      	    pChild1  = pChild1->NextSiblingElement()) 
+    	{
+	    int32_t conditional_0 = service_num;
+	    for(pChild2 = pChild1->FirstChildElement(); \
+		pChild2; pChild2 = pChild2->NextSiblingElement())
+	    {
+		service_num++;
+		int32_t conditional_1 = service_num;
+		for(pChild3 = pChild2->FirstChildElement(); \
+		    pChild3; pChild3 = pChild3 ->NextSiblingElement())
+		{
+		    service_num++;
+		    mList[mission_num].services[service_num].name = pChild3->Attribute("name");
+                    if(pChild3->Attribute("input1"))
+			mList[mission_num].services[service_num].input[0] = pChild3->Attribute("input1");
+                    if(pChild3->Attribute("input2"))
+			mList[mission_num].services[service_num].input[1] = pChild3->Attribute("input2");
+                    if(pChild3->Attribute("input3"))
+			mList[mission_num].services[service_num].input[2] = pChild3->Attribute("input3");
+                    if(pChild3->Attribute("output1"))
+			mList[mission_num].services[service_num].output[0] = pChild3->Attribute("output1");
+                    if(pChild3->Attribute("output2"))
+			mList[mission_num].services[service_num].output[1] = pChild3->Attribute("output2");
+                    if(pChild3->Attribute("output3"))
+			mList[mission_num].services[service_num].output[2] = pChild3->Attribute("output3");
+		    cond_array[1]++;
+		}
+
+		if(conditional_1 != service_num){
+		    mList[mission_num].services[conditional_1].name = pChild2->Value();
+                    if(pChild2->Attribute("input_t"))
+			mList[mission_num].services[conditional_1].input[0] = pChild2->Attribute("input_t");
+                    if(pChild2->Attribute("input_f"))
+			mList[mission_num].services[conditional_1].input[1] = pChild2->Attribute("input_f");
+		}
+		else{
+		    mList[mission_num].services[service_num].name = pChild2->Attribute("name");
+                    if(pChild2->Attribute("input1"))
+			mList[mission_num].services[service_num].input[0] = pChild2->Attribute("input1");
+                    if(pChild2->Attribute("input2"))
+			mList[mission_num].services[service_num].input[1] = pChild2->Attribute("input2");
+                    if(pChild2->Attribute("input3"))
+			mList[mission_num].services[service_num].input[2] = pChild2->Attribute("input3");
+                    if(pChild2->Attribute("output1"))
+			mList[mission_num].services[service_num].output[0] = pChild2->Attribute("output1");
+                    if(pChild2->Attribute("output2"))
+			mList[mission_num].services[service_num].output[1] = pChild2->Attribute("output2");
+                    if(pChild2->Attribute("output3"))
+			mList[mission_num].services[service_num].output[2] = pChild2->Attribute("output3");
+		}
+
+		mList[mission_num].services[conditional_1].num_conds = cond_array[1];
+		cond_array[1] = 0;
+		cond_array[0]++;
+	    }
+	    if(conditional_0 != service_num){
+		mList[mission_num].services[conditional_0].name = pChild1->Value();
+                if(pChild1->Attribute("input_t"))
+		    mList[mission_num].services[conditional_0].input[0] = pChild1->Attribute("input_t");
+                if(pChild1->Attribute("input_f"))
+		    mList[mission_num].services[conditional_0].input[1] = pChild1->Attribute("input_f");
+		printf("if detected %s, %s\n", pChild1->Attribute("input_f"), pChild1->Attribute("input_t"));
+	    }
+	    else{
+		mList[mission_num].services[service_num].name = pChild1->Attribute("name");
+                if(pChild1->Attribute("input1"))
+	            mList[mission_num].services[service_num].input[0] = pChild1->Attribute("input1");
+                if(pChild1->Attribute("input2"))
+		    mList[mission_num].services[service_num].input[1] = pChild1->Attribute("input2");
+                if(pChild1->Attribute("input3"))
+		    mList[mission_num].services[service_num].input[2] = pChild1->Attribute("input3");
+                if(pChild1->Attribute("output1"))
+		    mList[mission_num].services[service_num].output[0] = pChild1->Attribute("output1");
+                if(pChild1->Attribute("output2"))
+		    mList[mission_num].services[service_num].output[1] = pChild1->Attribute("output2");
+                if(pChild1->Attribute("output3"))
+		    mList[mission_num].services[service_num].output[2] = pChild1->Attribute("output3");
+	    }
+
+	    mList[mission_num].services[conditional_0].num_conds = cond_array[0];
+	    //printf("hello\n");
+	    
+            cond_array[0] = 0;
+	    service_num++;
+	}
+	for(int i = 0; i < service_num; i++)
+		printf("input1=%s, output1=%s\n", mList[mission_num].services[i].input[0].c_str(), mList[mission_num].services[service_num].output[0].c_str());
+
+	mList[mission_num].numServices = service_num;
+	mList[mission_num].name = pChild0->Attribute("name");
+	mList[mission_num].missionID = atoi(pChild0->Attribute("id"));
+        if(pChild0->Attribute("input1"))
+	    mList[mission_num].input[0] = pChild0->Attribute("input1");
+        if(pChild0->Attribute("input2"))
+	    mList[mission_num].input[1] = pChild0->Attribute("input2");
+        if(pChild0->Attribute("input3"))
+	    mList[mission_num].input[2] = pChild0->Attribute("input3");
+        if(pChild0->Attribute("output1"))
+	    mList[mission_num].output[0] = pChild0->Attribute("output1");
+        if(pChild0->Attribute("output2"))
+	    mList[mission_num].output[1] = pChild0->Attribute("output2");
+        if(pChild0->Attribute("output3"))
+	    mList[mission_num].output[2] = pChild0->Attribute("output3");
+	printf("input1=%s, outpu1=%s\n", mList[mission_num].input[0].c_str(), mList[mission_num].output[0].c_str());
+	mission_num++;
+    }*/
Index: vtcross/branches/wrodgers/src/Makefile.am
===================================================================
--- vtcross/branches/wrodgers/src/Makefile.am	(revision 181)
+++ vtcross/branches/wrodgers/src/Makefile.am	(revision 181)
@@ -0,0 +1,2 @@
+SUBDIRS = lib include policy_engines cognitive_engines service_management_layer \
+		  libvtcross shell
Index: vtcross/branches/wrodgers/src/libvtcross/libvtcross_demo.cpp
===================================================================
--- vtcross/branches/wrodgers/src/libvtcross/libvtcross_demo.cpp	(revision 239)
+++ vtcross/branches/wrodgers/src/libvtcross/libvtcross_demo.cpp	(revision 239)
@@ -0,0 +1,74 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * TODO LICENSE INFORMATION GOES HERE
+ */
+
+/* TODO DESCRIPTION OF FILE.
+ *
+ * This file is a temporary demo of a policy engine using some of our socket
+ * communication functions. This is *not* an actual implementation of our
+ * defined PolicyEngine class.
+ */
+
+
+#include <cstdlib>
+#include <cstring>
+#include <stdint.h>
+
+#include "vtcross/debug.h"
+#include "vtcross/error.h"
+#include "vtcross/libvtcross.h"
+#include "vtcross/socketcomm.h"
+
+int32_t 
+main(int32_t argc, char *argv[])
+{
+    for(size_t i = 0; i < 10; i++) {
+        Observable *o = new Observable[2];
+        Parameter *currentParameters = new Parameter[2];
+        Parameter *p;
+
+        uint32_t numParameters;
+        uint32_t numObservables;
+        uint32_t numUtilities;
+
+        o[0].name = "throughput";
+        o[0].value = 150.00;
+        o[1].name = "PER";
+        o[1].value = 12.00;
+
+        if(i == 0) {
+            currentParameters[0].name = "bandwidth";
+            currentParameters[0].value = 300.0;
+            currentParameters[1].name = "tx_power";
+            currentParameters[1].value = 10.0;
+        } else {
+            currentParameters[0].value = p[0].value;
+            currentParameters[1].value = p[1].value;
+        }
+
+        p = GetOptimalParameters(o,2,currentParameters,2);
+        numParameters = GetNumParameters();
+        numObservables = GetNumObservables();
+        numUtilities = GetNumUtilities();
+
+        LOG("Application:: Received the following parameters.\n");
+        
+        for(size_t i = 0; i < numParameters; i++) {
+            LOG("%s:: %f\n", p[i].name.c_str(), p[i].value);
+        }
+
+        /* Try them out! Do they work? */
+        o[0].value = 0.5*p[0].value + .1*p[1].value;
+        o[1].value = 15-p[1].value;
+
+        UpdateParameterPerformance(p, numParameters, o, numObservables);    
+        
+        delete [] p; 
+        delete [] o; 
+    }
+
+    return 0;
+}
+
Index: vtcross/branches/wrodgers/src/libvtcross/Makefile.am
===================================================================
--- vtcross/branches/wrodgers/src/libvtcross/Makefile.am	(revision 222)
+++ vtcross/branches/wrodgers/src/libvtcross/Makefile.am	(revision 222)
@@ -0,0 +1,11 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+lib_LTLIBRARIES = libvtcross.la
+bin_PROGRAMS = libvtcross_demo
+
+libvtcross_la_SOURCES = libvtcross.cpp
+libvtcross_la_LDFLAGS = -version-info 1:0:0
+libvtcross_la_LIBADD = ../lib/socketcomm/libsocketcomm.a
+
+libvtcross_demo_SOURCES = libvtcross_demo.cpp
+libvtcross_demo_LDADD = libvtcross.la
Index: vtcross/branches/wrodgers/src/libvtcross/libvtcross.cpp
===================================================================
--- vtcross/branches/wrodgers/src/libvtcross/libvtcross.cpp	(revision 232)
+++ vtcross/branches/wrodgers/src/libvtcross/libvtcross.cpp	(revision 232)
@@ -0,0 +1,167 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * LICENSE INFORMATION GOES HERE
+ */
+
+/* Implementation file for the VCROSS Cognitive Radio public API defined in
+ * include/libvtcross.h.
+ *
+ * MORE INFO HERE
+ */
+
+#include <cstdlib>
+
+#include "vtcross/common.h"
+#include "vtcross/debug.h"
+#include "vtcross/libvtcross.h"
+
+
+uint32_t
+ConnectToRemoteComponent()
+{
+    // TODO why is this hardcoded like this??
+       return ClientSocket("localhost", "40000");
+}
+
+// TODO the following three functions all do exactly the same thing.  Why not
+// simply combine them?
+uint32_t
+GetNumObservables()
+{
+    char buffer[256];
+
+    uint32_t socketfd = ConnectToRemoteComponent();
+    SendMessage(socketfd, "get_number_observables");
+    
+    memset(buffer, 0, 256);
+    ReadMessage(socketfd, buffer);
+    uint32_t numObservables = atoi(buffer);
+    
+    return numObservables; 
+}
+
+uint32_t
+GetNumUtilities()
+{
+    char buffer[256];
+
+    uint32_t socketfd = ConnectToRemoteComponent();
+    SendMessage(socketfd, "get_number_utilities");
+    
+    memset(buffer, 0, 256);
+    ReadMessage(socketfd, buffer);
+    uint32_t numUtilities = atoi(buffer);
+    
+    return numUtilities; 
+}
+
+uint32_t
+GetNumParameters()
+{
+    char buffer[256];
+
+    uint32_t socketfd = ConnectToRemoteComponent();
+    SendMessage(socketfd, "get_number_parameters");
+    
+    memset(buffer, 0, 256);
+    ReadMessage(socketfd, buffer);
+    uint32_t numParameters = atoi(buffer);
+    
+    return numParameters; 
+}
+// end previous TODO
+
+/* Given a certain set of observables, ask the radio to find the optimum radio
+ * parameters and return them. 
+ *
+ * TODO I'm a little confused about this function... why would anyone need to
+ * use this?  Shouldn't this be internal to the radio operation? 
+ *
+ * TODO this function is returning a pointer to allocated memory, which is fine,
+ * but we need to document this and make sure the caller is deallocating the
+ * memory when it is done using it.
+ */
+Parameter* 
+GetOptimalParameters(Observable *radioObservables, uint32_t numObservables,
+        Parameter *currentParameters, uint32_t numCurrentParameters)
+{
+    char var[50];
+    char counter[55];
+    char buffer[256];
+
+    uint32_t socketFD = ConnectToRemoteComponent();
+    SendMessage(socketFD, "request_optimization");
+
+    /* Get number of observables to send.  This information needs to be 
+     * sent to the Cognitive Radio Shell also.   
+     */
+
+    /* Send Observables */
+    sprintf(counter, "%i", numObservables);
+    SendMessage(socketFD, counter);
+    for(size_t i = 0; i < numObservables; i++) {
+        SendMessage(socketFD, radioObservables[i].name.c_str());
+        sprintf(var, "%f", radioObservables[i].value);
+        SendMessage(socketFD, var);    
+    }
+
+    /* Send Parameters */
+    memset(counter, 0, 55);
+    sprintf(counter, "%i", numCurrentParameters);
+    SendMessage(socketFD, counter);
+    for(size_t i = 0; i < numCurrentParameters; i++) {
+        SendMessage(socketFD,currentParameters[i].name.c_str());
+        sprintf(var,"%f",currentParameters[i].value);
+        SendMessage(socketFD,var);    
+    }
+
+    /* Receive Set of Parameters */
+    memset(buffer, 0, 256);
+    ReadMessage(socketFD, buffer);
+    uint32_t numParameters = atoi(buffer);
+    Parameter *pList = new Parameter[numParameters];
+    
+    for(ssize_t i = 0; i < numParameters; i++) {
+        memset(buffer, 0, 256);
+        ReadMessage(socketFD, buffer);
+        pList[i].name = std::string(buffer);
+        
+        memset(buffer, 0, 256);
+        ReadMessage(socketFD, buffer);
+        pList[i].value = atof(buffer);
+    }   
+
+    return pList;
+}
+
+bool
+UpdateParameterPerformance(Parameter *p, uint32_t numParameters, Observable *o,
+        uint32_t numObservables)
+{
+    char counter[55];
+    char var[50];
+
+    uint32_t socketFD = ConnectToRemoteComponent();
+    SendMessage(socketFD, "update_performance");
+    
+    // Send Parameters 
+    memset(counter, 0, 55);
+    sprintf(counter, "%i", numParameters);
+    SendMessage(socketFD, counter);
+    
+    for(size_t i = 0; i < numParameters; i++) {
+        SendMessage(socketFD, p[i].name.c_str());
+        sprintf(var, "%f", p[i].value);
+        SendMessage(socketFD, var);    
+    }
+    
+    // Send Observables
+    sprintf(counter, "%i", numObservables);
+    SendMessage(socketFD, counter);
+    for(size_t i = 0; i < numObservables; i++) {
+        SendMessage(socketFD, o[i].name.c_str());
+        sprintf(var, "%f", o[i].value);
+        SendMessage(socketFD, var);    
+    }
+}
