00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "xode.h"
00028
00029
00030
00031
00032 static void _xode_put_expatattribs(xode owner, const char** atts)
00033 {
00034 int i = 0;
00035 if (atts == NULL) return;
00036 while (atts[i] != '\0')
00037 {
00038 xode_put_attrib(owner, atts[i], atts[i+1]);
00039 i += 2;
00040 }
00041 }
00042
00043
00044 static void _xode_stream_startElement(xode_stream xs, const char* name, const char** atts)
00045 {
00046 xode_pool p;
00047
00048
00049 if(xs->status > XODE_STREAM_NODE) return;
00050
00051 if(xs->node == NULL)
00052 {
00053 p = xode_pool_heap(5*1024);
00054 xs->node = xode_new_frompool(p,name);
00055 _xode_put_expatattribs(xs->node, atts);
00056
00057 if(xs->status == XODE_STREAM_ROOT)
00058 {
00059 xs->status = XODE_STREAM_NODE;
00060 (xs->f)(XODE_STREAM_ROOT, xs->node, xs->arg);
00061 xs->node = NULL;
00062 }
00063 }else{
00064 xs->node = xode_insert_tag(xs->node, name);
00065 _xode_put_expatattribs(xs->node, atts);
00066 }
00067
00068
00069 xs->depth++;
00070 if(xs->depth > XODE_STREAM_MAXDEPTH)
00071 xs->status = XODE_STREAM_ERROR;
00072 }
00073
00074
00075 static void _xode_stream_endElement(xode_stream xs, const char* name)
00076 {
00077 xode parent;
00078
00079
00080 if(xs->status > XODE_STREAM_NODE) return;
00081
00082
00083 if(xs->node == NULL)
00084 {
00085 xs->status = XODE_STREAM_CLOSE;
00086 (xs->f)(XODE_STREAM_CLOSE, NULL, xs->arg);
00087 }else{
00088 parent = xode_get_parent(xs->node);
00089
00090
00091 if(parent == NULL)
00092 (xs->f)(XODE_STREAM_NODE, xs->node, xs->arg);
00093
00094 xs->node = parent;
00095 }
00096 xs->depth--;
00097 }
00098
00099
00100 static void _xode_stream_charData(xode_stream xs, const char *str, int len)
00101 {
00102
00103 if(xs->status > XODE_STREAM_NODE) return;
00104
00105 if(xs->node == NULL)
00106 {
00107
00108 return;
00109 }
00110
00111 xode_insert_cdata(xs->node, str, len);
00112 }
00113
00114
00115 static void _xode_stream_cleanup(void *arg)
00116 {
00117 xode_stream xs = (xode_stream)arg;
00118
00119 xode_free(xs->node);
00120 XML_ParserFree(xs->parser);
00121 }
00122
00123
00124
00125 xode_stream xode_stream_new(xode_pool p, xode_stream_onNode f, void *arg)
00126 {
00127 xode_stream newx;
00128
00129 if(p == NULL || f == NULL)
00130 {
00131 fprintf(stderr,"Fatal Programming Error: xode_streamnew() was improperly called with NULL.\n");
00132 return NULL;
00133 }
00134
00135 newx = xode_pool_malloco(p, sizeof(_xode_stream));
00136 newx->p = p;
00137 newx->f = f;
00138 newx->arg = arg;
00139
00140
00141 newx->parser = XML_ParserCreate(NULL);
00142 XML_SetUserData(newx->parser, (void *)newx);
00143 XML_SetElementHandler(newx->parser,
00144 (void (*)(void*, const char*, const char**))_xode_stream_startElement,
00145 (void (*)(void*, const char*))_xode_stream_endElement);
00146 XML_SetCharacterDataHandler(newx->parser,
00147 (void (*)(void*, const char*, int))_xode_stream_charData);
00148 xode_pool_cleanup(p, _xode_stream_cleanup, (void *)newx);
00149
00150 return newx;
00151 }
00152
00153
00154 int xode_stream_eat(xode_stream xs, char *buff, int len)
00155 {
00156 char *err;
00157 xode xerr;
00158 static char maxerr[] = "maximum node size reached";
00159 static char deeperr[] = "maximum node depth reached";
00160
00161 if(xs == NULL)
00162 {
00163 fprintf(stderr,"Fatal Programming Error: xode_streameat() was improperly called with NULL.\n");
00164 return XODE_STREAM_ERROR;
00165 }
00166
00167 if(len == 0 || buff == NULL)
00168 return xs->status;
00169
00170 if(len == -1)
00171 len = strlen(buff);
00172
00173 if(!XML_Parse(xs->parser, buff, len, 0))
00174 {
00175 err = (char *)XML_ErrorString(XML_GetErrorCode(xs->parser));
00176 xs->status = XODE_STREAM_ERROR;
00177 }else if(xode_pool_size(xode_get_pool(xs->node)) > XODE_STREAM_MAXNODE || xs->cdata_len > XODE_STREAM_MAXNODE){
00178 err = maxerr;
00179 xs->status = XODE_STREAM_ERROR;
00180 }else if(xs->status == XODE_STREAM_ERROR){
00181 err = deeperr;
00182 }else{
00183 err = deeperr;
00184 }
00185
00186
00187 if(xs->status == XODE_STREAM_ERROR)
00188 {
00189 xerr = xode_new("error");
00190 xode_insert_cdata(xerr,err,-1);
00191 (xs->f)(XODE_STREAM_ERROR, xerr, xs->arg);
00192 }
00193
00194 return xs->status;
00195 }