www.pudn.com > ICE_1.4.zip > q_xml.cpp


// Class automatically generated by Dev-C++ New Class wizard 
 
#include "q_xml.h" // class's header file 
 
// class constructor 
q_XML::q_XML(const char*filename, eQXML_MODES mode) 
{ 
    std::string open_mode; 
    m_mode = mode; 
    switch(mode) { 
        case QXML_READ: open_mode = "r"; break; 
        case QXML_WRITE: open_mode = "a"; break; 
        case QXML_NUKEWRITE: open_mode = "w"; break; 
    } 
 
	m_fptr = fopen(filename, open_mode.c_str() ); 
 
       //(mode == QXML_READ) ? (mode == QXML_NUKEWRITE) ? "w" : "a" : "r" ); 
	 
	if( m_fptr != NULL ) {  
 
		m_parse = QXMLP_VOID; 
		currTag = ""; 
		currName = ""; 
		currType = ""; 
		currVal = "";  
		m_err = false; 
		 
		if(mode == QXML_READ) { 
			nextNode(); 
			if( m_parse == QXMLP_ERROR || currTag != "node" || currName != "root" || currType != "qXML" ) { 
				QXML_DEBUG( printf("q_XML: malformed qXML file, read failed\n"); ); 
				fclose(m_fptr); 
				return; 
			} 
			QXML_DEBUG( printf("q_XML: qXML node parsed correctly...\n"); ); 
			nextAttr(); 
			if( currTag != "attr" || currName != "version" || currVal != q_XML_VERSION ) { 
				QXML_DEBUG( printf("q_XML: mismatched qXML version, found [%s] expected [%s], read failed\n", currVal.c_str(), q_XML_VERSION); ); 
				fclose(m_fptr); 
				return; 
			} 
			QXML_DEBUG( printf("q_XML: correct qXML version found [%s]...\n", q_XML_VERSION); ); 
			nextNode(); 
			if( m_parse == QXMLP_ERROR || currTag != "node" || currName != "data" || currType != "userdata" ) { 
				QXML_DEBUG( printf("q_XML: malformed qXML file, couldnt find data node, read failed\n"); ); 
				fclose(m_fptr); 
				return; 
			} 
			QXML_DEBUG( printf("q_XML: qXML data node found-- userdata can now be read\n"); ); 
		}else if(m_mode == QXML_NUKEWRITE) { 
			//format new root node 
			QXML_DEBUG( printf("q_XML: NUKEWRITE - creating new header\n"); ); 
			createNewNode("root", "qXML"); 
			QXML_DEBUG( printf("q_XML: NUKEWRITE - writing qXML version\n"); ); 
			addAttrStr("version", q_XML_VERSION); 
			QXML_DEBUG( printf("q_XML: NUKEWRITE - starting data node\n"); ); 
			createNewNode("data", "userdata"); 
			QXML_DEBUG( printf("q_XML: NUKEWRITE - ready for writing\n"); ); 
		} 
 
		m_err = false; 
	}else { 
		QXML_DEBUG( printf("q_XML: failed to open file %s\n", filename); ); 
		m_err = true;  
		return;  
	} 
} 
 
// class destructor 
q_XML::~q_XML() 
{ 
    QXML_DEBUG( printf("q_XML: destroying self \n"); ); 
    if( m_fptr ) { 
        //make sure to close all tags  
        if( m_mode != QXML_READ && m_tokenStack.size() > 0) 
                    endNode(""); 
         
        QXML_DEBUG( printf("q_XML: closed file\n"); ); 
        fclose(m_fptr); 
    } 
 
} 
 
//writing function 
// creates a new XML node 
void q_XML::createNewNode(const char*nodeName, const char*nodeType) { 
    //error checking 
	if(m_fptr == NULL) { //|| m_mode == QXML_READ || m_err) { 
        QXML_DEBUG( printf("q_XML: failed to createNewNode  -- NULL fptr\n"); ); 
        m_err = true; 
        return;  
    } 
	if(m_mode == QXML_READ) { /// || m_err) { 
        QXML_DEBUG( printf("q_XML: failed to createNewNode --- IN READ MODE\n"); ); 
        m_err = true; 
        return;  
    } 
    if(m_err) { 
        QXML_DEBUG( printf("q_XML: failed to createNewNode -- M_ERR = T\n"); ); 
        m_err = true; 
        return;  
    } 
    if(m_fptr == NULL || m_mode == QXML_READ || m_err) { 
        QXML_DEBUG( printf("q_XML: failed to createNewNode\n"); ); 
        m_err = true; 
        return;  
    } 
      
    std::string name = std::string(nodeName); 
    std::string type = std::string(nodeType); 
     
    //store new token level 
    m_tokenStack.push_back(name); 
    std::string out = "< node=\"" + name + "\" type=\"" + nodeType + "\" >\n"; 
     
    for(int x=0; x<(int)m_tokenStack.size()-1; x++) fprintf(m_fptr, "\t"); 
    fwrite(out.c_str(), sizeof(out[0]), out.length(), m_fptr ); 
    QXML_DEBUG( printf("writing: [%s]\n", out.c_str()); ); 
} 
 
//writing function 
void q_XML::addAttribute(const char*attrType, const char*attrName, const char*attrVal) { 
    if(m_fptr == NULL || m_mode == QXML_READ || m_err) { 
        QXML_DEBUG( printf("q_XML: failed to addAttribute\n"); ); 
        m_err = true; 
        return;  
    } 
    std::string name = std::string(attrName); 
    std::string type = std::string(attrType); 
    std::string val  = std::string(attrVal); 
    std::string out = "< attr=\"" + name + "\" type=\"" + type + "\" value=\""+ val  + "\" >\n"; 
 
    for(int x=0; x<(int)m_tokenStack.size(); x++) fprintf(m_fptr, "\t"); 
    fwrite(out.c_str(), sizeof(out[0]), out.length(), m_fptr ); 
    QXML_DEBUG( printf("writing: [%s]\n", out.c_str()); ); 
} 
 
//writing function 
void q_XML::endCurrNode() { 
    if(m_fptr == NULL || m_mode == QXML_READ || m_err || m_parse != QXMLP_VOID) { 
        QXML_DEBUG( printf("q_XML: failed to endCurrNode\n"); ); 
        m_err = true; 
        return;  
    } 
    std::string name = m_tokenStack.back(); 
    std::string out = "\n"; 
    m_tokenStack.pop_back(); 
     
    for(int x=0; x<(int)m_tokenStack.size(); x++) fprintf(m_fptr, "\t"); 
    fwrite(out.c_str(), sizeof(out[0]), out.length(), m_fptr ); 
    QXML_DEBUG( printf("writing: [%s]\n", out.c_str()); ); 
} 
 
//writing function 
// if node name does not exist, this will end all of the current nodes 
void q_XML::endNode(const char*nodeName) { 
    if(m_fptr == NULL || m_mode == QXML_READ || m_err || m_parse != QXMLP_VOID) { 
        QXML_DEBUG( printf("q_XML: failed to endNode\n"); ); 
        m_err = true; 
        return;  
    } 
 
     
    int stackSize = (int)m_tokenStack.size(); 
     
    while(1) { 
        std::string name = m_tokenStack.back(); 
        endCurrNode(); 
         
        if( name == std::string(nodeName) || m_tokenStack.size() == 0 ) return; 
    } 
} 
 
//writing function 
void q_XML::addAttrInt(const char*attrName, int attrVal) { 
    char buffer[64]; 
    sprintf(buffer, "%d", attrVal); 
    addAttribute("int", attrName, buffer ); 
} 
//writing function 
void q_XML::addAttrFloat(const char*attrName, float attrVal) { 
    char buffer[64]; 
    sprintf(buffer, "%.4f", attrVal); 
    addAttribute("float", attrName, buffer ); 
} 
//writing function 
void q_XML::addAttrStr(const char*attrName, const char* attrVal) { 
    addAttribute("string", attrName, attrVal ); 
} 
//writing function 
void q_XML::addAttrBool(const char*attrName, bool attrVal) { 
    addAttribute("bool", attrName, attrVal ? "T" : "F" ); 
} 
 	 
//reading function 
// moves to the next qXML node 
// returns "" if no more nodes or EOF 
std::string q_XML::nextNode() { 
	if(m_fptr == 0 || m_mode != QXML_READ || m_parse != QXMLP_VOID) { 
        QXML_DEBUG( printf("q_XML: nextNode() failed\n"); ); 
		dump(); 
		m_parse = QXMLP_ERROR; 
        m_err = true; 
        return std::string("");  
	} 
 
READNODE: 
	// move to first node 
	if(! nextTag() ) { 
		QXML_DEBUG( printf("q_XML: nextNode() could not find next tag, failed\n"); ); 
		m_parse = QXMLP_ERROR; 
		m_err = true; 
		return std::string("");  
	} 
 
	if(! readTag() ) { 
		QXML_DEBUG( printf("q_XML: nextNode() could not read tag, failed\n"); ); 
		m_parse = QXMLP_ERROR; 
		m_err = true; 
		return std::string("");  
	} 
	if(currTag != "node") { 
		QXML_DEBUG( printf("q_XML: nextNode() found a non-node, skipping\n"); ); 
		goto READNODE; 
	} 
 
	//TODO: if skipped, repeat until found node 
 
	return currName; 
} 
//reading function 
// moves to the next qXML attr (or node if at end of curr attrs) 
// returns "" if no more attrs or EOF 
std::string q_XML::nextAttr() { 
	//TODO 
 
	if(m_fptr == 0 || m_mode != QXML_READ || m_parse != QXMLP_VOID) { 
        QXML_DEBUG( printf("q_XML: nextAttr() failed\n"); ); 
		m_parse = QXMLP_ERROR; 
        m_err = true; 
        return std::string("");;  
	} 
 
 	// move to first node 
	if(! nextTag() ) { 
		QXML_DEBUG( printf("q_XML: nextAttr() could not find next tag, failed\n"); ); 
		m_parse = QXMLP_ERROR; 
		m_err = true; 
		return std::string("");  
	} 
 
	if(! readTag() ) { 
		QXML_DEBUG( printf("q_XML: nextAttr() could not read tag, failed\n"); ); 
		m_parse = QXMLP_ERROR; 
		m_err = true; 
		return std::string("");  
	} 
	if(currTag != "attr") { 
		QXML_DEBUG( printf("q_XML: nextAttr() found a non-attr, ... stopping ??? \n"); ); 
		return std::string(""); 
	} 
 
	//TODO: if not attr-- stop? 
 
	return currName; 
} 
 
//advance thru VOID (whitespace) to next tag "<" 
bool q_XML::nextTag() { 
	if(m_fptr == 0 || m_mode != QXML_READ || m_parse != QXMLP_VOID) { 
        QXML_DEBUG( printf("q_XML: nextTag() failed\n"); ); 
		m_parse = QXMLP_ERROR; 
        m_err = true; 
        return false; 
	} 
	char ch = (char)fgetc(m_fptr); 
	while(ch != '<' ) { 
		ch = (char)fgetc(m_fptr); 
		if( ch == EOF ) { 
			QXML_DEBUG( printf("q_XML: nextNode() reached unexpected EOF\n"); ); 
			m_parse = QXMLP_ERROR; 
			m_err = true; 
			return false; 
		} 
	} 
	m_parse = QXMLP_TAG_START; 
	QXML_DEBUG( printf("q_XML: nextTag() found TagStart\n"); ); 
	return true; 
} 
 
//identify type of tag, and read it 
bool q_XML::readTag() { 
	if(m_fptr == 0 || m_mode != QXML_READ || m_parse != QXMLP_TAG_START) { 
        QXML_DEBUG( printf("q_XML: readTag() failed\n"); ); 
		m_parse = QXMLP_ERROR; 
        m_err = true; 
        return false; 
	} 
 
	currTag = ""; 
	currName = ""; 
	currType = ""; 
	currVal = ""; 
 
	//expect space between "<" and tag-name 
	char ch = fgetc(m_fptr); 
	if(ch == '/') {  
		QXML_DEBUG( printf("q_XML: readTag() found '/' must be TAG_CLOSE\n"); ); 
		m_parse = QXMLP_TAG_CLOSE;  
		currTag = "close"; 
		//TODO: make sure readClose matches name on token stack 
		if( readClose() == "" ) { 
			QXML_DEBUG( printf("q_XML: readTag() could not read close tag, failed\n"); ); 
			m_parse = QXMLP_ERROR; 
			m_err = true; 
			return false; 
		} 
 
		QXML_DEBUG( printf("q_XML: readTag() looking for end of CLOSE tag..\n"); ); 
		if(!seekTagEnd() ){ 
			QXML_DEBUG( printf("q_XML: readTag() could not read end of tag, failed\n"); ); 
			m_parse = QXMLP_ERROR; 
			m_err = true; 
			return false; 
		} 
 
		QXML_DEBUG( printf("q_XML: readTag() TAG_CLOSE completed on %s\n", currName.c_str()); ); 
		return true;  
	}else if(ch != ' ') { 
		QXML_DEBUG( printf("q_XML: readTag() didnt find expected ' ', failed\n"); ); 
		m_parse = QXMLP_ERROR; 
		m_err = true; 
		return false; 
	} 
	 
	//get tag-type 
	char buffer[64]; 
	int buff_itr = 0; 
 
	while(buff_itr < 63) { 
		ch = fgetc(m_fptr); 
		if(ch == ' ') { 
			QXML_DEBUG( printf("q_XML: readTag() found unexpected ' ', failed\n"); ); 
			m_parse = QXMLP_ERROR; 
			m_err = true; 
		} 
		if(ch == EOF) { 
			QXML_DEBUG( printf("q_XML: readTag() found unexpected EOF, failed\n"); ); 
			m_parse = QXMLP_ERROR; 
			m_err = true; 
		} 
		if(ch == '=') break; 
		buffer[buff_itr++] = ch; 
	} 
	buffer[buff_itr] = '\0'; 
	QXML_DEBUG( printf("q_XML: readTag() completed tag-type, \"%s\"\n", buffer); ); 
 
	currTag = std::string(buffer); 
	//ch = fgetc(m_fptr);  move into begining of readNode/readAttr 
 
	//get tag name, type, (and value if attr) 
	if(currTag == "node") { 
		m_parse = QXMLP_TAG_NODE; 
		QXML_DEBUG( printf("q_XML: readTag() recognized  tag-type, \"%s\"\n", buffer); ); 
		if(! readNode() ){ 
			QXML_DEBUG( printf("q_XML: readTag() could not read Node tag, failed\n"); ); 
			m_parse = QXMLP_ERROR; 
			m_err = true; 
			return false; 
		} 
 
	}else if( currTag == "attr" ) { 
		m_parse = QXMLP_TAG_ATTR; 
		QXML_DEBUG( printf("q_XML: readTag() recognized  tag-type, \"%s\"\n", buffer); ); 
		if(! readAttr() ){ 
			QXML_DEBUG( printf("q_XML: readTag() could not read Attr tag, failed\n"); ); 
			m_parse = QXMLP_ERROR; 
			m_err = true; 
			return false; 
		} 
	}else { 
		QXML_DEBUG( printf("q_XML: readTag() unrecognized tag name \"%s\", failed\n", currTag.c_str()); ); 
		m_parse = QXMLP_ERROR; 
		m_err = true; 
		return false; 
	} 
QXML_DEBUG( printf("q_XML: readTag() looking for end tag..\n"); ); 
	if(!seekTagEnd() ){ 
		QXML_DEBUG( printf("q_XML: readTag() could not read end of tag, failed\n"); ); 
		m_parse = QXMLP_ERROR; 
		m_err = true; 
		return false; 
	} 
 
	QXML_DEBUG( printf("q_XML: readTag() completed tag\n"); ); 
	return true; 
 
} 
 
std::string q_XML::readVal() { 
	if(m_fptr == 0 || m_mode != QXML_READ || m_parse != QXMLP_IN_VAL) { 
        QXML_DEBUG( printf("q_XML: readVal() failed\n"); ); 
		m_parse = QXMLP_ERROR; 
        m_err = true; 
        return std::string(""); 
	} 
QXML_DEBUG( printf("q_XML: readVal() starting to read value.. \""); ); 
	char buffer[64]; 
	int buff_itr = 0; 
	char ch = getc(m_fptr); 
 
	while(buff_itr < 63) { 
		if( ch == '"') break; 
		if( ch == EOF ){ 
			QXML_DEBUG( printf("q_XML: readVal() reached unexpected EOF\n"); ); 
			m_parse = QXMLP_ERROR; 
			m_err = true; 
			return std::string(""); 
		} 
		buffer[buff_itr++] = ch; 
QXML_DEBUG( printf("%c", ch); ); 
		ch = getc(m_fptr); 
	} 
	buffer[buff_itr] = '\0'; 
QXML_DEBUG( printf("\"\n"); ); 
 
	std::string val = std::string(buffer); 
	return val; 
} 
 
bool q_XML::seekTagEnd() { 
	printf(""); 
	if(m_fptr == 0 || m_mode != QXML_READ || (m_parse != QXMLP_TAG_NODE && m_parse != QXMLP_TAG_ATTR && m_parse != QXMLP_TAG_CLOSE) ) { 
        QXML_DEBUG( printf("q_XML: seekTagEnd() failed\n"); ); 
		m_parse = QXMLP_ERROR; 
        m_err = true; 
        return false; 
	} 
	char ch; 
	char skip_str[] = " >"; 
	for(unsigned int i=0; i