243{
244 static const char *Hdr0 = "<statistics ";
245 static const int H0Len = strlen(Hdr0);
246
249 VarInfo vHead[] = {{"tod", 0}, {"ver", 0}, {"src", 0}, {"tos", 0},
250 {"pgm", 0}, {"ins", 0}, {"pid", 0}, {0, 0}};
251 VarInfo vStat[] = {{"id", 0}, {0, 0}};
252 VarInfo vTail[] = {{"toe", 0}, {0, 0}};
253 char *lP = ibuff, *oP = obuff, *tP, *vP;
254 int i, rc;
255
256
257
258 if (!(lP = (char *)index(lP, '>')))
259 return xmlErr("Invalid xml stream: ", ibuff);
260 *lP++ = '\n';
261
262
263
264 while(*lP)
265 {if (*lP == '>' || (*lP == '<' && *(lP+1) == '/')) *lP = ' ';
266 lP++;
267 }
268
269
270
271 if (!(lP = Data.GetLine()) || strncmp(Hdr0, lP, H0Len))
272 return xmlErr("Stream does not start with '<statistics'.");
273 Data.GetToken(); getVars(Data, vHead);
274
275
276
277 for (i = 0; vHead[i].Name; i++)
278 {if (vHead[i].Data) oP = Add(oP, vHead[i].Name, vHead[i].Data);}
279
280
281
282 if (Host) oP = Add(oP, "host", Host);
283
284
285
286 if (!Data.GetLine()) return xmlErr("Null xml stream after header.");
287
288
289
290 while((tP = Data.GetToken()) && strcmp(tP, "/statistics"))
291 { if (*tP == '/')
292 {if (!xVar.Pop(strcmp("/stats", tP) ? tP+1 : 0))
293 return xmlErr(tP, "invalid end for ", xVar.Var());
294 }
295 else if (*tP == '<')
296 {if (strcmp("<stats", tP)) rc = xVar.Push(tP+1);
297 else {getVars(Data, vStat);
298 rc = (vStat[0].Data ? xVar.Push(vStat[0].Data)
299 : xVar.Push(tP+1));
300 }
301 if (!rc) return xmlErr("Nesting too deep for ", xVar.Var());
302 }
303 else {if ((vP = index(tP, '<'))) *vP = '\0';
304 if (*tP == '"')
305 {i = strlen(tP)-1;
306 if (*(tP+i) == '"') {*(tP+i) = '\0'; i = 1;}
307 } else i = 0;
308 oP = Add(oP, xVar.Var(), tP+i);
309 if (vP) {*vP = '<';
310 if (vP != tP) memset(tP, ' ', vP - tP);
311 Data.RetToken();
312 }
313 }
314 }
315 if (!tP) return xmlErr("Missing '</statistics>' in xml stream.");
316 getVars(Data, vTail);
317 if (vTail[0].Data) oP = Add(oP, vTail[0].Name, vTail[0].Data);
318 if (*(oP-1) == '&') oP--;
319 *oP++ = '\n';
320 return oP - obuff;
321}