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
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
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
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
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
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
00127
Expat *me = (
Expat *)userData;
00128
00129
00130
XMLNode t;
00131
00132 t.
setName(name);
00133
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
00149 me->
rootTagRecieved(t);
00150 me->
rootRecieved =
true;
00151
return;
00152 }
00153
00154
00155
if (!me->
fillingNodes.empty())
00156 me->
fillingNodes.top().addChild(t);
00157
00158
00159 me->
fillingNodes.push( t );
00160 }
00161
00162
void Expat::endElement(
void *userData,
const XML_Char *)
00163 {
00164
00165 Expat *me = (Expat *)userData;
00166
00167
if (me->fillingNodes.empty())
00168 {
00169
00170 me->rootTagEnded();
00171
return;
00172 }
00173
00174
if (me->fillingNodes.size() == 1)
00175 {
00176
00177
00178 me->newNodes.push_back(me->fillingNodes.top());
00179
00180
00181
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
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 }