1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | #define BAD_CRC_IS_ONLY_WARNING1 1 |
48 | |
49 | #include <xercesc/util/PlatformUtils.hpp> |
50 | #include <xercesc/dom/DOMNamedNodeMap.hpp> |
51 | |
52 | #include "XParsers.hpp" |
53 | #include "XString.hpp" |
54 | |
55 | #include <assert.h> |
56 | #include <stdlib.h> |
57 | #include <stdio.h> |
58 | #include <rpc/rpc.h> |
59 | #include <unistd.h> |
60 | #include <xstream/z.h> |
61 | #include <xstream/bz.h> |
62 | #include <xstream/xdr.h> |
63 | #include <xstream/digest.h> |
64 | |
65 | #include <iostream> |
66 | #include <fstream> |
67 | #include <sstream> |
68 | |
69 | #include "particleType.h" |
70 | |
71 | |
72 | #define X(str)XString(str).unicode_str() XString(str).unicode_str() |
73 | #define S(str)str.c_str() str.c_str() |
74 | |
75 | using namespace xercesc; |
76 | |
77 | int explicit_repeat_count = 1; |
78 | |
79 | class XMLmaker |
80 | { |
81 | public: |
82 | std::ofstream xout; |
83 | |
84 | XMLmaker() {}; |
85 | ~XMLmaker() {}; |
86 | |
87 | void writeXML(const XString& s); |
88 | void constructXML(xstream::xdr::istream *ifx, DOMElement* el, |
89 | int size, int depth); |
90 | }; |
91 | |
92 | class istreambuffer : public std::streambuf { |
93 | public: |
94 | istreambuffer(char* buffer, std::streamsize bufferLength) { |
95 | setg(buffer, buffer, buffer + bufferLength); |
96 | } |
97 | |
98 | std::streampos tellg() { |
99 | return gptr() - eback(); |
100 | } |
101 | |
102 | void seekg(std::streampos pos) { |
103 | reset(); |
104 | gbump(pos); |
105 | } |
106 | |
107 | int size() { |
108 | return egptr() - gptr(); |
109 | } |
110 | |
111 | void reset() { |
112 | char *gbegin = eback(); |
113 | char *gend = egptr(); |
114 | setg(gbegin, gbegin, gend); |
115 | } |
116 | |
117 | char *getbuf() { |
118 | return eback(); |
119 | } |
120 | }; |
121 | |
122 | class ostreambuffer : public std::streambuf { |
123 | public: |
124 | ostreambuffer(char* buffer, std::streamsize bufferLength) { |
125 | setp(buffer, buffer + bufferLength); |
126 | } |
127 | |
128 | std::streampos tellp() { |
129 | return pptr() - pbase(); |
130 | } |
131 | |
132 | void seekp(std::streampos pos) { |
133 | reset(); |
134 | pbump(pos); |
135 | } |
136 | |
137 | int size() { |
138 | return pptr() - pbase(); |
139 | } |
140 | |
141 | void reset() { |
142 | char *pbegin = pbase(); |
143 | char *pend = epptr(); |
144 | setp(pbegin, pend); |
145 | } |
146 | |
147 | char *getbuf() { |
148 | return pbase(); |
149 | } |
150 | }; |
151 | |
152 | void usage() |
153 | { |
154 | std::cerr |
155 | << "\nUsage:\n" |
156 | << " hddm-xml [-n count] [-o <filename>] [HDDM file]\n\n" |
157 | << "Options:\n" |
158 | << " -o <filename> write to <filename>.xml" |
159 | << std::endl; |
160 | } |
161 | |
162 | |
163 | int main(int argC, char* argV[]) |
164 | { |
165 | XString xFilename; |
166 | |
167 | try |
168 | { |
169 | XMLPlatformUtils::Initialize(); |
170 | } |
171 | catch (const XMLException* toCatch) |
172 | { |
173 | XString msg(toCatch->getMessage()); |
174 | std::cerr |
175 | << "hddm-xml: Error during initialization! :\n" |
176 | << S(msg)msg.c_str() << std::endl; |
177 | return 1; |
178 | } |
179 | |
180 | int reqcount=-1; |
181 | int argInd; |
182 | for (argInd = 1; argInd < argC; argInd++) |
183 | { |
184 | if (argV[argInd][0] != '-') |
185 | { |
186 | break; |
187 | } |
188 | else if (strcmp(argV[argInd],"-o") == 0) |
189 | { |
190 | xFilename = argV[++argInd]; |
191 | } |
192 | else if (strcmp(argV[argInd],"-n") == 0) |
193 | { |
194 | if (!sscanf(argV[++argInd],"%d",&reqcount)) |
195 | { |
196 | usage(); |
197 | return 1; |
198 | } |
199 | } |
200 | else |
201 | { |
202 | usage(); |
203 | return 1; |
204 | } |
205 | } |
206 | |
207 | XString hddmFile; |
208 | std::istream* ifs; |
209 | if (argInd == argC) |
210 | { |
211 | ifs = &std::cin; |
212 | } |
213 | else if (argInd == argC - 1) |
214 | { |
215 | hddmFile = XString(argV[argInd]); |
216 | ifs = new std::ifstream(hddmFile.c_str()); |
217 | } |
218 | else |
219 | { |
220 | usage(); |
221 | return 1; |
222 | } |
223 | if (!ifs->good()) |
224 | { |
225 | std::cerr |
226 | << "hddm-xml: Error opening input stream " << hddmFile << std::endl; |
227 | exit(1); |
228 | } |
229 | std::ostringstream tmpFileStr; |
230 | tmpFileStr << "tmp" << getpid(); |
231 | std::ofstream ofs(tmpFileStr.str().c_str()); |
232 | if (! ofs.is_open()) |
233 | { |
234 | std::cerr |
235 | << "hddm-xml: Error opening temp file " << tmpFileStr.str() << std::endl; |
236 | exit(2); |
237 | } |
238 | |
239 | ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; |
240 | XString xmlHeader; |
241 | XString line; |
242 | if (getline(*ifs,line)) |
243 | { |
244 | if (line.substr(0,5) == "<?xml") |
245 | { |
246 | std::cerr |
247 | << "hddm-xml: Error reading input stream " << hddmFile |
248 | << std::endl; |
249 | std::cerr |
250 | << "Input file appears to be an xml document!" << std::endl; |
251 | exit(1); |
252 | } |
253 | else if (line.substr(0,5) == "<HDDM") |
254 | { |
255 | xmlHeader = line + "\n"; |
256 | ofs << line; |
257 | } |
258 | else |
259 | { |
260 | std::cerr |
261 | << "hddm-xml: Input stream does not contain valid hddm header" |
262 | << std::endl; |
263 | exit(1); |
264 | } |
265 | } |
266 | else |
267 | { |
268 | std::cerr |
269 | << "hddm-xml: Error reading from input stream " << hddmFile |
270 | << std::endl; |
271 | exit(1); |
272 | } |
273 | while (getline(*ifs,line)) |
274 | { |
275 | ofs << line; |
276 | if (line == "</HDDM>") |
277 | { |
278 | break; |
279 | } |
280 | } |
281 | ofs.close(); |
282 | |
283 | #if defined OLD_STYLE_XERCES_PARSER |
284 | DOMDocument* document = parseInputDocument(tmpFileStr.str().c_str(),false); |
285 | #else |
286 | DOMDocument* document = buildDOMDocument(tmpFileStr.str().c_str(),false); |
287 | #endif |
288 | if (document == 0) |
289 | { |
290 | std::cerr |
291 | << "hddm-xml : Error parsing HDDM document, " |
292 | << "cannot continue" << std::endl; |
293 | return 1; |
294 | } |
295 | unlink(tmpFileStr.str().c_str()); |
296 | |
297 | DOMElement* rootEl = document->getDocumentElement(); |
298 | XString rootS(rootEl->getTagName()); |
299 | if (rootS != "HDDM") |
300 | { |
301 | std::cerr |
302 | << "hddm-xml error: root element of input document is " |
303 | << "\"" << S(rootS)rootS.c_str() << "\", expected \"HDDM\"" |
304 | << std::endl; |
305 | return 1; |
306 | } |
307 | |
308 | XMLmaker builder; |
309 | if (xFilename.size()) |
310 | { |
311 | XString fname(xFilename + ".xml"); |
312 | builder.xout.open(fname.c_str()); |
313 | } |
314 | |
315 | builder.writeXML("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); |
316 | builder.writeXML(xmlHeader); |
317 | |
318 | int event_buffer_size; |
319 | char *event_buffer = new char[event_buffer_size = 1000000]; |
320 | istreambuffer *isbuf = new istreambuffer(event_buffer,event_buffer_size); |
321 | xstream::xdr::istream *ifx = new xstream::xdr::istream(isbuf); |
322 | int integrity_check_mode = 0; |
323 | int compression_mode = 0; |
324 | while (reqcount && ifs->good()) |
325 | { |
326 | DOMNodeList* contList = rootEl->getChildNodes(); |
327 | int contLength = contList->getLength(); |
328 | int tsize; |
329 | ifs->read(event_buffer,4); |
330 | if (ifs->eof()) { |
331 | break; |
332 | } |
333 | isbuf->reset(); |
334 | *ifx >> tsize; |
335 | #ifdef VERBOSE_HDDM_LOGGING |
336 | XString tnameS(rootEl->getTagName()); |
337 | std::cerr << "hddm-xml : tag " << S(tnameS)tnameS.c_str() |
338 | << " found with size " << tsize |
339 | << std::endl; |
340 | #endif |
341 | if (tsize <= 0) |
342 | { |
343 | break; |
344 | } |
345 | else if (tsize == 1) { |
346 | int size, format, flags; |
347 | ifs->read(event_buffer+4,4); |
348 | *ifx >> size; |
349 | ifs->read(event_buffer+8,size); |
350 | *ifx >> format >> flags; |
351 | int compression_flags = flags & 0xf0; |
352 | int integrity_flags = flags & 0x0f; |
353 | std::streambuf *fin_sb = 0; |
354 | xstream::z::istreambuf *zin_sb = 0; |
355 | xstream::bz::istreambuf *bzin_sb = 0; |
356 | if (compression_flags == compression_mode) { |
357 | fin_sb = ifs->rdbuf(); |
| Value stored to 'fin_sb' is never read |
358 | } |
359 | else if (size == 8 && format == 0 && compression_flags == 0x10) { |
360 | if (compression_mode == 0x20) { |
361 | bzin_sb = (xstream::bz::istreambuf*)ifs->rdbuf(); |
362 | } |
363 | compression_mode = compression_flags; |
364 | zin_sb = new xstream::z::istreambuf(ifs->rdbuf()); |
365 | ifs->rdbuf(zin_sb); |
366 | if (bzin_sb != 0) |
367 | delete bzin_sb; |
368 | } |
369 | else if (size == 8 && format == 0 && compression_flags == 0x20) { |
370 | if (compression_mode == 0x10) { |
371 | zin_sb = (xstream::z::istreambuf*)ifs->rdbuf(); |
372 | } |
373 | compression_mode = compression_flags; |
374 | bzin_sb = new xstream::bz::istreambuf(ifs->rdbuf()); |
375 | ifs->rdbuf(bzin_sb); |
376 | if (zin_sb != 0) |
377 | delete zin_sb; |
378 | } |
379 | else { |
380 | if (compression_mode == 0x20) { |
381 | bzin_sb = (xstream::bz::istreambuf*)ifs->rdbuf(); |
382 | fin_sb = bzin_sb->get_streambuf(); |
383 | } |
384 | else if (compression_mode == 0x10) { |
385 | zin_sb = (xstream::z::istreambuf*)ifs->rdbuf(); |
386 | fin_sb = zin_sb->get_streambuf(); |
387 | } |
388 | compression_mode = compression_flags; |
389 | ifs->rdbuf(fin_sb); |
390 | if (zin_sb != 0) |
391 | delete zin_sb; |
392 | if (bzin_sb != 0) |
393 | delete bzin_sb; |
394 | } |
395 | if (size == 8 && format == 0 && integrity_flags == 0x0) { |
396 | integrity_check_mode = 0; |
397 | } |
398 | else if (size == 8 && format == 0 && integrity_flags == 0x1) { |
399 | integrity_check_mode = 1; |
400 | } |
401 | else { |
402 | std::cerr << "hddm-xml error: unrecognized stream modifier" |
403 | " encountered, this stream is no longer readable." |
404 | << std::endl; |
405 | break; |
406 | } |
407 | continue; |
408 | } |
409 | else if (tsize+4 > event_buffer_size) { |
410 | delete ifx; |
411 | delete isbuf; |
412 | char *new_buffer = new char[event_buffer_size = tsize+1000]; |
413 | isbuf = new istreambuffer(new_buffer,event_buffer_size); |
414 | ifx = new xstream::xdr::istream(isbuf); |
415 | memcpy(new_buffer,event_buffer,4); |
416 | *ifx >> tsize; |
417 | delete[] event_buffer; |
418 | event_buffer = new_buffer; |
419 | } |
420 | ifs->read(event_buffer+4,tsize); |
421 | --reqcount; |
422 | |
423 | if (integrity_check_mode == 1) { |
424 | char crcbuf[10]; |
425 | istreambuffer sbuf(crcbuf,10); |
426 | xstream::xdr::istream xstr(&sbuf); |
427 | unsigned int recorded_crc; |
428 | ifs->read(crcbuf,4); |
429 | xstr >> recorded_crc; |
430 | xstream::digest::crc32 crc; |
431 | std::ostream out(&crc); |
432 | out.write(event_buffer,tsize+4); |
433 | out.flush(); |
434 | if (crc.digest() != recorded_crc) { |
435 | #if BAD_CRC_IS_ONLY_WARNING1 |
436 | static int bad_crc_warning_needed = true; |
437 | char errmsg[] = |
438 | "WARNING: data integrity crc check failed on input.\n" |
439 | "This may be the result of a bug in the xstream library\n" |
440 | "if you are analyzing a data file that was generated by\n" |
441 | "code prior to svn rev 18530. If this concerns you, \n" |
442 | "regenerate the file using a newer build of the sim-recon\n" |
443 | "tools and it should go away.\n"; |
444 | if (bad_crc_warning_needed) { |
445 | std::cerr << errmsg << std::endl; |
446 | bad_crc_warning_needed = false; |
447 | } |
448 | #else |
449 | std::cerr << "hddm-xml error: crc32 check error on input stream" |
450 | " encountered, this stream is no longer readable." |
451 | << std::endl; |
452 | break; |
453 | #endif |
454 | } |
455 | } |
456 | |
457 | for (int c = 0; c < contLength; c++) |
458 | { |
459 | DOMNode* cont = contList->item(c); |
460 | short type = cont->getNodeType(); |
461 | if (type == DOMNode::ELEMENT_NODE) |
462 | { |
463 | DOMElement* contEl = (DOMElement*) cont; |
464 | int size; |
465 | *ifx >> size; |
466 | #ifdef VERBOSE_HDDM_LOGGING |
467 | XString cnameS(contEl->getTagName()); |
468 | std::cerr << "hddm-xml : top-level tag " << S(cnameS)cnameS.c_str() |
469 | << " found with size " << size |
470 | << std::endl; |
471 | #endif |
472 | if (size > 0) |
473 | { |
474 | builder.constructXML(ifx,contEl,size,1); |
475 | } |
476 | else { |
477 | XString repS(contEl->getAttribute(X("minOccurs")XString("minOccurs").unicode_str())); |
478 | int rep = (repS == "")? 1 : atoi(S(repS)repS.c_str()); |
479 | if (rep != 0) { |
480 | XString conameS(contEl->getTagName()); |
481 | std::cerr << "hddm-xml warning: top-level tag " << S(conameS)conameS.c_str() |
482 | << " found with zero size " |
483 | << "inside an event with size " << tsize |
484 | << " continue? [y/n] "; |
485 | std::string ans; |
486 | std::cin >> ans; |
487 | if (ans[0] != 'y' && ans[0] != 'Y') { |
488 | exit(5); |
489 | } |
490 | } |
491 | } |
492 | } |
493 | } |
494 | } |
495 | |
496 | builder.writeXML("</HDDM>\n"); |
497 | |
498 | if (ifs != &std::cin) |
499 | { |
500 | ((std::ifstream*)ifs)->close(); |
501 | } |
502 | XMLPlatformUtils::Terminate(); |
503 | return 0; |
504 | } |
505 | |
506 | |
507 | |
508 | void XMLmaker::writeXML(const XString& s) |
509 | { |
510 | if (xout.is_open()) |
511 | { |
512 | xout << s; |
513 | } |
514 | else |
515 | { |
516 | std::cout << s; |
517 | } |
518 | } |
519 | |
520 | |
521 | |
522 | |
523 | |
524 | void XMLmaker::constructXML(xstream::xdr::istream *ifx, |
525 | DOMElement* el, int size, int depth) |
526 | { |
527 | XString tagS(el->getTagName()); |
528 | XString repS(el->getAttribute(X("maxOccurs")XString("maxOccurs").unicode_str())); |
529 | int rep = (repS == "unbounded")? INT_MAX2147483647 : |
530 | (repS == "")? 1 : |
531 | atoi(S(repS)repS.c_str()); |
532 | if (explicit_repeat_count && rep > 1) |
533 | { |
534 | *ifx >> rep; |
535 | size -= 4; |
536 | } |
537 | |
538 | int r; |
539 | for (r = 0; r < rep && size > 0; r++) |
540 | { |
541 | for (int d = 0; d < depth; d++) |
542 | { |
543 | writeXML(" "); |
544 | } |
545 | writeXML("<"); |
546 | writeXML(S(tagS)tagS.c_str()); |
547 | DOMNamedNodeMap* attrList = el->getAttributes(); |
548 | int listLength = attrList->getLength(); |
549 | for (int a = 0; a < listLength; a++) |
550 | { |
551 | XString nameS(attrList->item(a)->getNodeName()); |
552 | XString typeS(attrList->item(a)->getNodeValue()); |
553 | std::ostringstream attrStr; |
554 | if (typeS == "int") |
555 | { |
556 | int32_t value; |
557 | *ifx >> value; |
558 | size -= 4; |
559 | attrStr << " " << nameS << "=\"" << value << "\""; |
560 | } |
561 | else if (typeS == "long") |
562 | { |
563 | int64_t value; |
564 | *ifx >> value; |
565 | size -= 8; |
566 | attrStr << " " << nameS << "=\"" << value << "\""; |
567 | } |
568 | else if (typeS == "float") |
569 | { |
570 | float value; |
571 | *ifx >> value; |
572 | size -= 4; |
573 | attrStr << " " << nameS << "=\"" << value << "\""; |
574 | } |
575 | else if (typeS == "double") |
576 | { |
577 | double value; |
578 | *ifx >> value; |
579 | size -= 8; |
580 | attrStr << " " << nameS << "=\"" << value << "\""; |
581 | } |
582 | else if (typeS == "boolean") |
583 | { |
584 | bool_t value; |
585 | *ifx >> value; |
586 | size -= 4; |
587 | attrStr << " " << nameS << "=\"" << value << "\""; |
588 | } |
589 | else if (typeS == "Particle_t") |
590 | { |
591 | int32_t value; |
592 | *ifx >> value; |
593 | size -= 4; |
594 | attrStr << " " << nameS << "=\"" << ParticleType((Particle_t)value) << "\""; |
595 | } |
596 | else if (typeS == "string" || typeS == "anyURI") |
597 | { |
598 | std::string value; |
599 | *ifx >> value; |
600 | int strsize = value.size(); |
601 | size -= strsize + 4 + ((strsize % 4)? 4-(strsize % 4) : 0); |
602 | attrStr << " " << nameS << "=\"" << value << "\""; |
603 | } |
604 | else if (nameS == "minOccurs" || nameS == "maxOccurs") |
605 | { |
606 | ; |
607 | } |
608 | else |
609 | { |
610 | attrStr << " " << nameS << "=\"" << typeS << "\""; |
611 | } |
612 | writeXML(attrStr.str()); |
613 | } |
614 | |
615 | DOMNodeList* contList = el->getChildNodes(); |
616 | int contLength = contList->getLength(); |
617 | if (contLength > 1) |
618 | { |
619 | writeXML(">\n"); |
620 | } |
621 | else |
622 | { |
623 | writeXML(" />\n"); |
624 | } |
625 | |
626 | for (int c = 0; c < contLength; c++) |
627 | { |
628 | DOMNode* cont = contList->item(c); |
629 | short type = cont->getNodeType(); |
630 | if (type == DOMNode::ELEMENT_NODE) |
631 | { |
632 | DOMElement* contEl = (DOMElement*) cont; |
633 | int csize; |
634 | *ifx >> csize; |
635 | size -= 4; |
636 | #ifdef VERBOSE_HDDM_LOGGING |
637 | XString cnameS(contEl->getTagName()); |
638 | std::cerr << "hddm-xml : tag " << S(cnameS)cnameS.c_str() |
639 | << " found with size " << csize |
640 | << std::endl; |
641 | #endif |
642 | if (csize > 0) { |
643 | constructXML(ifx,contEl,csize,depth +1); |
644 | size -= csize; |
645 | } |
646 | #ifdef VERBOSE_HDDM_LOGGING |
647 | else { |
648 | XString irepS(contEl->getAttribute(X("minOccurs")XString("minOccurs").unicode_str())); |
649 | int irep = (irepS == "")? 1 : atoi(S(irepS)irepS.c_str()); |
650 | if (irep != 0) { |
651 | XString conameS(contEl->getTagName()); |
652 | std::cerr << "hddm-xml warning: tag " << S(conameS)conameS.c_str() |
653 | << " found with zero size, " |
654 | << "continue? [y/n] "; |
655 | std::string ans; |
656 | std::cin >> ans; |
657 | if (ans[0] != 'y' && ans[0] != 'Y') { |
658 | exit(5); |
659 | } |
660 | } |
661 | } |
662 | #endif |
663 | } |
664 | } |
665 | |
666 | if (contLength > 1) |
667 | { |
668 | for (int d = 0; d < depth; d++) |
669 | { |
670 | writeXML(" "); |
671 | } |
672 | XString endTag("</"+tagS+">\n"); |
673 | writeXML(endTag); |
674 | } |
675 | } |
676 | if (size != 0) { |
677 | std::cerr << "hddm-xml : size mismatch in tag " << S(tagS)tagS.c_str() |
678 | << ", remainder is " << size |
679 | << ", cannot continue." << std::endl; |
680 | exit(5); |
681 | } |
682 | else if (explicit_repeat_count && r != rep) { |
683 | std::cerr << "hddm-xml : repeat count mismatch in tag " << S(tagS)tagS.c_str() |
684 | << ", expected " << rep << " but saw " << r |
685 | << ", cannot continue." << std::endl; |
686 | exit(5); |
687 | } |
688 | } |