wrapexpat.cpp

00001 00002 #include <iostream> 00003 00004 #include "gm/gm.h" 00005 #include "gm/wrapexpat.h" 00006 #include "expat.h" 00007 00008 namespace GNUMessenger { 00009 00010 using namespace std; 00011 00012 // trim_right() family. 00013 string Expat::trim_right ( const string & source, const string & t) 00014 { 00015 string str = source; 00016 return str.erase ( str.find_last_not_of ( t ) + 1 ) ; 00017 } 00018 00019 // trim_left() family. 00020 string Expat::trim_left ( const string & source, const string & t) 00021 { 00022 string str = source; 00023 return str.erase ( 0 , source.find_first_not_of ( t ) ) ; 00024 } 00025 00026 // trim() family. 00027 string Expat::trim ( const string & source, const string & t) 00028 { 00029 string str = source; 00030 return trim_left ( trim_right ( str , t ) , t ) ; 00031 } 00032 00033 Expat::Expat() 00034 { 00035 parser = 0; 00036 init(); 00037 } 00038 00039 Expat::~Expat() 00040 { 00041 cleanup(); 00042 } 00043 00044 void Expat::init() 00045 { 00046 if (parser != 0) 00047 cleanup(); 00048 00049 parser = XML_ParserCreate( NULL ); 00050 XML_SetElementHandler(parser, startElement, endElement); 00051 XML_SetCharacterDataHandler(parser, charData); 00052 XML_SetUserData(parser, (void *)this); 00053 00054 rootRecieved = false; 00055 } 00056 00057 void Expat::cleanup() 00058 { 00059 if (parser == 0) 00060 return; 00061 00062 XML_ParserFree( parser ); 00063 parser = 0; 00064 00065 newNodes.clear(); 00066 while (!fillingNodes.empty()) 00067 fillingNodes.pop(); 00068 } 00069 00070 void Expat::reset() 00071 { 00072 cleanup(); 00073 init(); 00074 } 00075 00076 void Expat::parse(string data) 00077 { 00078 if (!parser) 00079 { 00080 parserError("Expat::parse: Internal error",0); 00081 return; 00082 } 00083 00084 if (!XML_Parse( parser, (const char *)data.c_str(), (long int)data.length(), false )) 00085 { 00086 parserError( XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser)); 00087 return; 00088 } 00089 00090 // Send out any new tags 00091 for (unsigned int i=0;i<newNodes.size();i++) 00092 recievedTag(newNodes[i]); 00093 00094 newNodes.clear(); 00095 } 00096 00097 void Expat::recievedTag( XMLNode &n) 00098 { 00099 LOG_DEBUG(string(n)); 00100 } 00101 00102 void Expat::rootTagRecieved(XMLNode &n) 00103 { 00104 string s("Recieved root tag:"); 00105 s += string(n); 00106 LOG_DEBUG(string(s)); 00107 } 00108 00109 void Expat::rootTagEnded() 00110 { 00111 LOG_DEBUG("Root tag ended."); 00112 } 00113 00114 void Expat::parserError(string errorMsg, int line ) 00115 { 00116 stringstream err; 00117 err << "Expat parser error: " << errorMsg << " at "<< line; 00118 00119 // try to keep object in sane state after throw 00120 reset(); 00121 LOG_THROW(err.str(), ParseFailure); 00122 } 00123 00124 void Expat::startElement(void *userData, const XML_Char *name, const XML_Char **atts) 00125 { 00126 /* get the userdata into a usable form */ 00127 Expat *me = (Expat *)userData; 00128 00129 /* New tag? Well...create one */ 00130 XMLNode t; 00131 00132 t.setName(name); 00133 /* now put on it's parameters */ 00134 int i=0; 00135 00136 if (atts != NULL) 00137 { 00138 while (atts[i] != NULL) 00139 { 00140 t.setProperty(atts[i],atts[i+1]); 00141 i+=2; 00142 } 00143 } 00144 00145 00146 if( !me->rootRecieved ) 00147 { 00148 // This is the first tag...therefore the root tag. 00149 me->rootTagRecieved(t); 00150 me->rootRecieved = true; 00151 return; 00152 } 00153 00154 /* Register it as a sub tag of the previous tag */ 00155 if (!me->fillingNodes.empty()) 00156 me->fillingNodes.top().addChild(t); 00157 00158 /* push this node onto the stack */ 00159 me->fillingNodes.push( t ); 00160 } 00161 00162 void Expat::endElement(void *userData, const XML_Char *) 00163 { 00164 /* get the userdata into a usable form */ 00165 Expat *me = (Expat *)userData; 00166 00167 if (me->fillingNodes.empty()) 00168 { 00169 // If this is 0 then this is the end of the root tag... 00170 me->rootTagEnded(); 00171 return; 00172 } 00173 00174 if (me->fillingNodes.size() == 1) 00175 { 00176 // We used to send them right out from here...but I found out something very nasty can 00177 // happen...suppose that the parser is deleted because of this node (login error...) 00178 me->newNodes.push_back(me->fillingNodes.top()); 00179 00180 // We do not delete the node becuse that job belongs to 00181 // whoever overrid the revieced tag 00182 } 00183 00184 me->fillingNodes.top().setData(trim(me->fillingNodes.top().data(),"\n\r\t ")); 00185 00186 me->fillingNodes.pop(); 00187 } 00188 00189 void Expat::charData(void *userData, const char *s, int length) 00190 { 00191 /* get the userdata into a usable form */ 00192 Expat *me = (Expat *)userData; 00193 00194 char *data; 00195 data = new char[length + 1]; 00196 memcpy(data, s, length); 00197 data[length] = '\0'; 00198 00199 if (me->fillingNodes.empty()) 00200 { 00201 delete [] data; 00202 return; 00203 } 00204 string newData = me->fillingNodes.top().data()+data; 00205 00206 me->fillingNodes.top().setData(newData); 00207 00208 delete[] data; 00209 } 00210 00211 } // !GNUMessenger

Generated on Tue Oct 5 14:41:47 2004 for GNU Messenger by doxygen 1.3.8