Bug Summary

File:/home/sdobbs/work/clang/halld_recon/src/programs/Utilities/hddm/hddm-root.cpp
Warning:line 383, column 19
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -main-file-name hddm-root.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /w/halld-scifs17exp/home/sdobbs/clang/llvm-project/install/lib/clang/12.0.0 -D HAVE_TMVA=1 -I . -I libraries -I libraries/include -I /w/halld-scifs17exp/home/sdobbs/clang/halld_recon/Linux_CentOS7.7-x86_64-gcc4.8.5/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/xerces-c/xerces-c-3.1.4/include -I external/xstream/include -I /usr/include/tirpc -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/root/root-6.08.06/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/backward -internal-isystem /usr/local/include -internal-isystem /w/halld-scifs17exp/home/sdobbs/clang/llvm-project/install/lib/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /home/sdobbs/work/clang/halld_recon/src -ferror-limit 19 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-01-21-110224-160369-1 -x c++ programs/Utilities/hddm/hddm-root.cpp
1/*
2 * hddm-root : tool that reads in a HDDM document (Hall D Data Model)
3 * and copies the contents into root trees for easy browsing.
4 *
5 * author: richard.t.jones at uconn.edu
6 * version: january 2, 2017
7 *
8 */
9
10#include <xercesc/util/PlatformUtils.hpp>
11#include <xercesc/dom/DOMNamedNodeMap.hpp>
12
13#include "XParsers.hpp"
14#include "XString.hpp"
15
16#include <assert.h>
17#include <stdlib.h>
18#include <stdio.h>
19#include <rpc/rpc.h>
20#include <unistd.h>
21#include <xstream/z.h>
22#include <xstream/bz.h>
23#include <xstream/xdr.h>
24#include <xstream/digest.h>
25
26#include <string.h>
27#include <iostream>
28#include <fstream>
29#include <sstream>
30#include <map>
31
32#include <TTree.h>
33#include <TFile.h>
34
35#include "particleType.h"
36
37
38#define X(str)XString(str).unicode_str() XString(str).unicode_str()
39#define S(str)str.c_str() str.c_str()
40
41using namespace xercesc;
42
43int explicit_repeat_count = 1;
44int write_xml_output_to_stdout = 0;
45
46void usage()
47{
48 std::cerr
49 << "\nUsage:\n"
50 << " hddm-root [-x] [-n <count>] [-o <filename>] [HDDM file]\n\n"
51 << "Options:\n"
52 << " -o <filename> write to output root file <filename>\n"
53 << " -n <count> limit output to <count> rows\n"
54 << " -x write xml to stdout"
55 << " (in addition to root file output)\n"
56 << std::endl;
57}
58
59typedef xstream::xdr::istream ixstream;
60
61class attribute_t {
62 protected:
63 attribute_t() : fName(""), fType("") {}
64 attribute_t(XString name) : fName(name), fType("") {}
65 attribute_t(XString name, XString type) : fName(name), fType(type) {}
66 virtual ~attribute_t() {}
67
68 public:
69 virtual void reset() = 0;
70 virtual void *address() = 0;
71 virtual std::string toString() = 0;
72 virtual int read(ixstream *ifx) = 0;
73 virtual XString get_name() { return fName; }
74 virtual XString get_type() { return fType; }
75
76 private:
77 attribute_t(const attribute_t &src);
78 attribute_t &operator=(const attribute_t &src);
79
80 protected:
81 XString fName;
82 XString fType;
83};
84
85class int_attribute_t : public attribute_t {
86 public:
87 int_attribute_t() : attribute_t("", "int"), value(0) {}
88 int_attribute_t(XString name) : attribute_t(name, "int"), value(0) {}
89 virtual ~int_attribute_t() {}
90
91 int_attribute_t &operator=(const int_attribute_t &src) {
92 fName = src.fName;
93 value = src.value;
94 return *this;
95 }
96
97 virtual void reset() {
98 value = 0;
99 }
100 virtual void set(int val) {
101 value = val;
102 }
103 virtual void *address() {
104 return &value;
105 }
106 virtual std::string toString() {
107 std::stringstream str;
108 str << value;
109 return str.str();
110 }
111 virtual int read(ixstream *ifx) {
112 *ifx >> value;
113 return 4;
114 }
115
116 int value;
117};
118
119class boolean_attribute_t : public attribute_t {
120 public:
121 boolean_attribute_t() : attribute_t("", "boolean"), value(0) {}
122 boolean_attribute_t(XString name) : attribute_t(name, "boolean"), value(0) {}
123 virtual ~boolean_attribute_t() {}
124
125 boolean_attribute_t &operator=(const boolean_attribute_t &src) {
126 fName = src.fName;
127 value = src.value;
128 return *this;
129 }
130
131 virtual void reset() {
132 value = 0;
133 }
134 virtual void set(int val) {
135 value = val;
136 }
137 virtual void *address() {
138 return &value;
139 }
140 virtual std::string toString() {
141 std::stringstream str;
142 str << value;
143 return str.str();
144 }
145 virtual int read(ixstream *ifx) {
146 *ifx >> value;
147 return 4;
148 }
149
150 int value;
151};
152
153class Particle_attribute_t : public attribute_t {
154 public:
155 Particle_attribute_t() : attribute_t("", "Particle_t"), value(Unknown) {}
156 Particle_attribute_t(XString name) : attribute_t(name, "Particle_t"),
157 value(Unknown) {}
158 virtual ~Particle_attribute_t() {}
159
160 Particle_attribute_t &operator=(const Particle_attribute_t &src) {
161 fName = src.fName;
162 value = src.value;
163 return *this;
164 }
165
166 virtual void reset() {
167 value = Unknown;
168 }
169 virtual void set(Particle_t val) {
170 value = val;
171 }
172 virtual void *address() {
173 return &value;
174 }
175 virtual std::string toString() {
176 std::stringstream str;
177 str << ParticleType(value);
178 return str.str();
179 }
180 virtual int read(ixstream *ifx) {
181 int val;
182 *ifx >> val;
183 value = (Particle_t)val;
184 return 4;
185 }
186
187 Particle_t value;
188};
189
190class long_attribute_t : public attribute_t {
191 public:
192 long_attribute_t() : attribute_t("", "long"), value(0) {}
193 long_attribute_t(XString name) : attribute_t(name, "long"), value(0) {}
194 virtual ~long_attribute_t() {}
195
196 long_attribute_t &operator=(const long_attribute_t &src) {
197 fName = src.fName;
198 value = src.value;
199 return *this;
200 }
201
202 virtual void reset() {
203 value = 0;
204 }
205 virtual void set(long int val) {
206 value = val;
207 }
208 virtual void *address() {
209 return &value;
210 }
211 virtual std::string toString() {
212 std::stringstream str;
213 str << value;
214 return str.str();
215 }
216 virtual int read(ixstream *ifx) {
217 *ifx >> value;
218 return 8;
219 }
220
221#if __APPLE__
222 int64_t value;
223#else
224 long int value;
225#endif
226};
227
228class float_attribute_t : public attribute_t {
229 public:
230 float_attribute_t() : attribute_t("", "float"), value(0) {}
231 float_attribute_t(XString name) : attribute_t(name, "float"), value(0) {}
232 virtual ~float_attribute_t() {}
233
234 float_attribute_t &operator=(const float_attribute_t &src) {
235 fName = src.fName;
236 value = src.value;
237 return *this;
238 }
239
240 virtual void reset() {
241 value = 0;
242 }
243 virtual void set(float val) {
244 value = val;
245 }
246 virtual void *address() {
247 return &value;
248 }
249 virtual std::string toString() {
250 std::stringstream str;
251 str << value;
252 return str.str();
253 }
254 virtual int read(ixstream *ifx) {
255 *ifx >> value;
256 return 4;
257 }
258
259 float value;
260};
261
262class double_attribute_t : public attribute_t {
263 public:
264 double_attribute_t() : attribute_t("", "double"), value(0) {}
265 double_attribute_t(XString name) : attribute_t(name, "double"), value(0) {}
266 ~double_attribute_t() {}
267
268 double_attribute_t &operator=(const double_attribute_t &src) {
269 fName = src.fName;
270 value = src.value;
271 return *this;
272 }
273
274 virtual void reset() {
275 value = 0;
276 }
277 virtual void set(double val) {
278 value = val;
279 }
280 virtual void *address() {
281 return &value;
282 }
283 virtual std::string toString() {
284 std::stringstream str;
285 str << value;
286 return str.str();
287 }
288 virtual int read(ixstream *ifx) {
289 *ifx >> value;
290 return 8;
291 }
292
293 double value;
294};
295
296class string_attribute_t : public attribute_t {
297 public:
298 string_attribute_t() : attribute_t("", "string") { reset(); }
299 string_attribute_t(XString name) : attribute_t(name, "string") { reset(); }
300 ~string_attribute_t() {}
301
302 string_attribute_t &operator=(const string_attribute_t &src) {
303 fName = src.fName;
304 strncpy(value, src.value, 80);
305 return *this;
306 }
307
308 virtual void reset() {
309 strncpy(value, "", 80);
310 }
311 virtual void set(char *val) {
312 strncpy(value, val, 80);
313 }
314 virtual void *address() {
315 return &value;
316 }
317 virtual std::string toString() {
318 return std::string(value);
319 }
320 virtual int read(ixstream *ifx) {
321 std::string val;
322 *ifx >> val;
323 strncpy(value, val.c_str(), 80);
324 return (val.size() + 7) / 4 * 4;
325 }
326
327 char value[80];
328};
329
330class anyURI_attribute_t : public attribute_t {
331 public:
332 anyURI_attribute_t() : attribute_t("", "anyURI") { reset(); }
333 anyURI_attribute_t(XString name) : attribute_t(name, "anyURI") { reset(); }
334 ~anyURI_attribute_t() {}
335
336 anyURI_attribute_t &operator=(const anyURI_attribute_t &src) {
337 fName = src.fName;
338 strncpy(value, src.value, 80);
339 return *this;
340 }
341
342 virtual void reset() {
343 strncpy(value, "", 80);
344 }
345 virtual void set(char *val) {
346 strncpy(value, val, 80);
347 }
348 virtual void *address() {
349 return &value;
350 }
351 virtual std::string toString() {
352 return std::string(value);
353 }
354 virtual int read(ixstream *ifx) {
355 std::string val;
356 *ifx >> val;
357 strncpy(value, val.c_str(), 80);
358 return (val.size() + 7) / 4 * 4;
359 }
360
361 char value[80];
362};
363
364class constant_attribute_t : public attribute_t {
365 public:
366 constant_attribute_t() : attribute_t("", "constant"), value(0)
367 { reset(); }
368 constant_attribute_t(XString name) : attribute_t(name, "constant"), value(0)
369 { reset(); }
370 ~constant_attribute_t() {}
371
372 void reset() {
373 if (value)
374 delete value;
375 value = new char[4];
376 strncpy(value, "", 4);
377 }
378 void set(const char *str) {
379 if (value)
3
Assuming field 'value' is non-null
4
Taking true branch
380 delete value;
5
Memory is released
381 if (!str
5.1
'str' is non-null
)
6
Taking false branch
382 return;
383 int size = (strlen(str) + 7) / 4 * 4;
7
Use of memory after it is freed
384 value = new char[size];
385 strncpy(value, str, size);
386 }
387
388 constant_attribute_t &operator=(const constant_attribute_t &src) {
1
Assuming src == *this
389 fName = src.fName;
390 set(src.value);
2
Calling 'constant_attribute_t::set'
391 return *this;
392 }
393
394 virtual void *address() {
395 return value;
396 }
397 virtual std::string toString() {
398 return std::string(value);
399 }
400 virtual int read(ixstream *ifx) {
401 return 0;
402 }
403
404 char *value;
405};
406
407class element_t {
408 public:
409 element_t(TTree *tree)
410 : fKey(0), fTree(tree), fRepeats(0) {}
411 element_t(TTree *tree, XString name)
412 : fKey(0), fTree(tree), fName(name), fRepeats(0) {}
413 ~element_t() {}
414
415 void add_attribute(attribute_t *attr) {
416 fAttributes.push_back(attr);
417 }
418 void add_element(element_t *elem) {
419 fElements.push_back(elem);
420 }
421 void add_key(int_attribute_t *attr) {
422 fKey = attr;
423 }
424 void set_repeating() {
425 fRepeats = 1;
426 }
427
428 int read(ixstream *ifx) {
429 int size;
430 *ifx >> size;
431 if (size == 0)
432 return 4;
433 int seen;
434 int reps=1;
435 if (fRepeats) {
436 *ifx >> reps;
437 seen = 4;
438 }
439 else {
440 seen = 0;
441 }
442
443 static int indent = 0;
444 if (write_xml_output_to_stdout) {
445 if (indent == 0) {
446 std::cout << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
447 << std::endl
448 << "<HDDM class=\"s\" version=\"1.0\" "
449 << "xmlns=\"http://www.gluex.org/hddm\">"
450 << std::endl;
451 ++indent;
452 }
453 }
454 while (seen < size) {
455 if (write_xml_output_to_stdout) {
456 for (int i=0; i < indent; ++i)
457 std::cout << " ";
458 std::cout << "<" << fName;
459 }
460 std::list<attribute_t*>::iterator ater;
461 for (ater = fAttributes.begin(); ater != fAttributes.end(); ++ater) {
462 seen += (*ater)->read(ifx);
463 if (write_xml_output_to_stdout) {
464 std::cout << " " << (*ater)->get_name() << "=\""
465 << (*ater)->toString() << "\"";
466 }
467 }
468 if (fElements.size() == 0) {
469 if (write_xml_output_to_stdout) {
470 std::cout << " />" << std::endl;
471 }
472 if (fTree)
473 fTree->Fill();
474 if (fKey)
475 ++fKey->value;
476 }
477 else {
478 if (write_xml_output_to_stdout) {
479 std::cout << ">" << std::endl;
480 ++indent;
481 }
482 std::list<element_t*>::iterator eter;
483 for (eter = fElements.begin(); eter != fElements.end(); ++eter) {
484 seen += (*eter)->read(ifx);
485 }
486 if (write_xml_output_to_stdout) {
487 --indent;
488 for (int i=0; i < indent; ++i) {
489 std::cout << " ";
490 }
491 std::cout << "</" << fName << ">" << std::endl;
492 }
493 if (fTree)
494 fTree->Fill();
495 }
496 --reps;
497 }
498 assert (seen == size)((seen == size) ? static_cast<void> (0) : __assert_fail
("seen == size", "programs/Utilities/hddm/hddm-root.cpp", 498
, __PRETTY_FUNCTION__))
;
499 if (fRepeats)
500 assert (reps == 0)((reps == 0) ? static_cast<void> (0) : __assert_fail ("reps == 0"
, "programs/Utilities/hddm/hddm-root.cpp", 500, __PRETTY_FUNCTION__
))
;
501 return size + 4;
502 }
503
504 std::list<attribute_t*> fAttributes;
505 std::list<element_t*> fElements;
506 int_attribute_t *fKey;
507 TTree *fTree;
508 XString fName;
509 int fRepeats;
510
511 private:
512 element_t(const element_t &src);
513 element_t &operator=(const element_t &src);
514};
515
516typedef std::map<XString,XString> attribute_list;
517typedef std::map<XString,attribute_t*> attribute_table;
518
519class TreeMaker
520{
521 public:
522 TreeMaker(XString filename) {
523 fRootFile = new TFile(S(filename)filename.c_str(), "recreate");
524 }
525 ~TreeMaker() {
526 delete fRootFile;
527 }
528
529 void build(const DOMElement* elem, element_t *parent_element,
530 attribute_list columns);
531 int filltrees(ixstream *ifx, element_t *parent_element);
532 int savetrees(element_t *parent_element);
533
534 private:
535 TreeMaker(const TreeMaker &src) {}
536 TreeMaker operator=(const TreeMaker &src) {
537 TreeMaker copy(*this);
538 return copy;
539 }
540
541 protected:
542 TFile *fRootFile;
543 std::list<element_t*> fElements;
544 attribute_table fColumns;
545};
546
547class istreambuffer : public std::streambuf {
548 public:
549 istreambuffer(char* buffer, std::streamsize bufferLength) {
550 setg(buffer, buffer, buffer + bufferLength);
551 }
552
553 std::streampos tellg() {
554 return gptr() - eback();
555 }
556
557 void seekg(std::streampos pos) {
558 reset();
559 gbump(pos);
560 }
561
562 int size() {
563 return egptr() - gptr();
564 }
565
566 void reset() {
567 char *gbegin = eback();
568 char *gend = egptr();
569 setg(gbegin, gbegin, gend);
570 }
571
572 char *getbuf() {
573 return eback();
574 }
575};
576
577int main(int argC, char* argV[])
578{
579 XString rootFilename;
580
581 try
582 {
583 XMLPlatformUtils::Initialize();
584 }
585 catch (const XMLException* toCatch)
586 {
587 XString msg(toCatch->getMessage());
588 std::cerr
589 << "hddm-root: Error during initialization! :\n"
590 << S(msg)msg.c_str() << std::endl;
591 return 1;
592 }
593
594 int reqcount=-1;
595 int argInd;
596 for (argInd = 1; argInd < argC; argInd++)
597 {
598 if (argV[argInd][0] != '-')
599 {
600 break;
601 }
602 else if (strcmp(argV[argInd],"-x") == 0)
603 {
604 write_xml_output_to_stdout = 1;
605 }
606 else if (strcmp(argV[argInd],"-o") == 0)
607 {
608 rootFilename = argV[++argInd];
609 }
610 else if (strcmp(argV[argInd],"-n") == 0)
611 {
612 if (!sscanf(argV[++argInd],"%d",&reqcount))
613 {
614 usage();
615 return 1;
616 }
617 }
618 else
619 {
620 usage();
621 return 1;
622 }
623 }
624
625 XString hddmFile;
626 std::istream* ifs;
627 if (argInd == argC)
628 {
629 ifs = &std::cin;
630 }
631 else if (argInd == argC - 1)
632 {
633 hddmFile = XString(argV[argInd]);
634 ifs = new std::ifstream(hddmFile.c_str());
635 }
636 else
637 {
638 usage();
639 return 1;
640 }
641 if (!ifs->good())
642 {
643 std::cerr
644 << "hddm-root: Error opening input stream " << hddmFile << std::endl;
645 exit(1);
646 }
647 std::ostringstream doc;
648 std::ostringstream tmpFileStr;
649 tmpFileStr << "tmp" << getpid();
650 std::ofstream ofs(tmpFileStr.str().c_str());
651 if (! ofs.is_open())
652 {
653 std::cerr
654 << "hddm-root: Error opening temp file " << tmpFileStr.str() << std::endl;
655 exit(2);
656 }
657
658 ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
659 doc << std::endl;
660 XString xmlHeader;
661 XString line;
662 if (getline(*ifs,line))
663 {
664 if (line.substr(0,5) == "<?xml")
665 {
666 std::cerr
667 << "hddm-root: Error reading input stream " << hddmFile
668 << std::endl;
669 std::cerr
670 << "Input file appears to be an xml document!" << std::endl;
671 exit(1);
672 }
673 else if (line.substr(0,5) == "<HDDM")
674 {
675 xmlHeader = line + "\n";
676 ofs << line << std::endl;
677 doc << line << std::endl;
678 }
679 else
680 {
681 std::cerr
682 << "hddm-root: Input stream does not contain valid hddm header"
683 << std::endl;
684 exit(1);
685 }
686 }
687 else
688 {
689 std::cerr
690 << "hddm-root: Error reading from input stream " << hddmFile
691 << std::endl;
692 exit(1);
693 }
694 while (getline(*ifs,line))
695 {
696 ofs << line << std::endl;
697 doc << line << std::endl;
698 if (line == "</HDDM>")
699 {
700 break;
701 }
702 }
703 ofs.close();
704
705#if defined OLD_STYLE_XERCES_PARSER
706 DOMDocument* document = parseInputDocument(tmpFileStr.str().c_str(),false);
707#else
708 DOMDocument* document = buildDOMDocument(tmpFileStr.str().c_str(),false);
709#endif
710 if (document == 0)
711 {
712 std::cerr
713 << "hddm-root : Error parsing HDDM document, "
714 << "cannot continue" << std::endl;
715 return 1;
716 }
717 unlink(tmpFileStr.str().c_str());
718
719 DOMElement* rootEl = document->getDocumentElement();
720 XString rootS(rootEl->getTagName());
721 if (rootS != "HDDM")
722 {
723 std::cerr
724 << "hddm-root error: root element of input document is "
725 << "\"" << S(rootS)rootS.c_str() << "\", expected \"HDDM\""
726 << std::endl;
727 return 1;
728 }
729
730 // open root file for output and initialize the trees for writing
731 TreeMaker builder(rootFilename);
732 attribute_list columns;
733 element_t root_element(0);
734 builder.build(rootEl, &root_element, columns);
735
736 int event_buffer_size;
737 char *event_buffer = new char[event_buffer_size = 1000000];
738 istreambuffer *isbuf = new istreambuffer(event_buffer,event_buffer_size);
739 ixstream *ifx = new ixstream(isbuf);
740 int integrity_check_mode = 0;
741 int compression_mode = 0;
742 while (reqcount && ifs->good())
743 {
744 int tsize;
745 ifs->read(event_buffer,4);
746 if (ifs->eof()) {
747 break;
748 }
749 isbuf->reset();
750 *ifx >> tsize;
751#ifdef VERBOSE_HDDM_LOGGING
752 XString tnameS(rootEl->getTagName());
753 std::cerr << "hddm-root : tag " << S(tnameS)tnameS.c_str()
754 << " found with size " << tsize
755 << std::endl;
756#endif
757 if (tsize <= 0)
758 {
759 break;
760 }
761 else if (tsize == 1) {
762 int size, format, flags;
763 ifs->read(event_buffer+4,4);
764 *ifx >> size;
765 ifs->read(event_buffer+8,size);
766 *ifx >> format >> flags;
767 int compression_flags = flags & 0xf0;
768 int integrity_flags = flags & 0x0f;
769 std::streambuf *fin_sb = 0;
770 xstream::z::istreambuf *zin_sb = 0;
771 xstream::bz::istreambuf *bzin_sb = 0;
772 int *leftovers = new int[100];
773 int sizeof_leftovers = sizeof(int[100]);
774 leftovers[0] = 0;
775 if (compression_flags == compression_mode) {
776 fin_sb = ifs->rdbuf();
777 }
778 else if (size == 8 && format == 0 && compression_flags == 0x10) {
779 if (compression_mode == 0x20) {
780 bzin_sb = (xstream::bz::istreambuf*)ifs->rdbuf();
781 }
782 compression_mode = compression_flags;
783 zin_sb = new xstream::z::istreambuf(ifs->rdbuf(),
784 leftovers, sizeof_leftovers);
785 ifs->rdbuf(zin_sb);
786 if (bzin_sb != 0)
787 delete bzin_sb;
788 }
789 else if (size == 8 && format == 0 && compression_flags == 0x20) {
790 if (compression_mode == 0x10) {
791 zin_sb = (xstream::z::istreambuf*)ifs->rdbuf();
792 }
793 compression_mode = compression_flags;
794 bzin_sb = new xstream::bz::istreambuf(ifs->rdbuf(),
795 leftovers, sizeof_leftovers);
796 ifs->rdbuf(bzin_sb);
797 if (zin_sb != 0)
798 delete zin_sb;
799 }
800 else {
801 if (compression_mode == 0x20) {
802 bzin_sb = (xstream::bz::istreambuf*)ifs->rdbuf();
803 fin_sb = bzin_sb->get_streambuf();
804 }
805 else if (compression_mode == 0x10) {
806 zin_sb = (xstream::z::istreambuf*)ifs->rdbuf();
807 fin_sb = zin_sb->get_streambuf();
808 }
809 compression_mode = compression_flags;
810 ifs->rdbuf(fin_sb);
811 if (zin_sb != 0)
812 delete zin_sb;
813 if (bzin_sb != 0)
814 delete bzin_sb;
815 }
816 if (size == 8 && format == 0 && integrity_flags == 0x0) {
817 integrity_check_mode = 0;
818 }
819 else if (size == 8 && format == 0 && integrity_flags == 0x1) {
820 integrity_check_mode = 1;
821 }
822 else {
823 std::cerr << "hddm-root error: unrecognized stream modifier"
824 " encountered, this stream is no longer readable."
825 << std::endl;
826 break;
827 }
828 continue;
829 }
830 else if (tsize+4 > event_buffer_size) {
831 delete ifx;
832 delete isbuf;
833 char *new_buffer = new char[event_buffer_size = tsize+1000];
834 isbuf = new istreambuffer(new_buffer,event_buffer_size);
835 ifx = new ixstream(isbuf);
836 memcpy(new_buffer,event_buffer,4);
837 *ifx >> tsize;
838 delete[] event_buffer;
839 event_buffer = new_buffer;
840 }
841 ifs->read(event_buffer+4,tsize);
842 --reqcount;
843
844 if (integrity_check_mode == 1) {
845 char crcbuf[10];
846 istreambuffer sbuf(crcbuf,10);
847 ixstream xstr(&sbuf);
848 unsigned int recorded_crc;
849 ifs->read(crcbuf,4);
850 xstr >> recorded_crc;
851 xstream::digest::crc32 crc;
852 std::ostream out(&crc);
853 out.write(event_buffer,tsize+4);
854 out.flush();
855 if (crc.digest() != recorded_crc) {
856#if BAD_CRC_IS_ONLY_WARNING
857 static int bad_crc_warning_needed = true;
858 char errmsg[] =
859 "WARNING: data integrity crc check failed on input.\n"
860 "This may be the result of a bug in the xstream library\n"
861 "if you are analyzing a data file that was generated by\n"
862 "code prior to svn rev 18530. If this concerns you, \n"
863 "regenerate the file using a newer build of the sim-recon\n"
864 "tools and it should go away.\n";
865 if (bad_crc_warning_needed) {
866 std::cerr << errmsg << std::endl;
867 bad_crc_warning_needed = false;
868 }
869#else
870 std::cerr << "hddm-root error: crc32 check error on input stream"
871 " encountered, this stream is no longer readable."
872 << std::endl;
873 break;
874#endif
875 }
876 }
877 builder.filltrees(ifx, &root_element);
878 }
879 if (write_xml_output_to_stdout) {
880 std::cout << "</HDDM>" << std::endl;
881 }
882 builder.savetrees(&root_element);
883 TNamed docString("document_metadata_XML", doc.str().c_str());
884 docString.Write();
885
886 if (ifs != &std::cin)
887 {
888 ((std::ifstream*)ifs)->close();
889 }
890
891 XMLPlatformUtils::Terminate();
892 return 0;
893}
894
895void TreeMaker::build(const DOMElement* elem, element_t *parent_element,
896 attribute_list columns)
897{
898 // Recursively create TTree objects to hold the contents of the hddm model
899 // in the form of a row/column table, like a relational database model.
900
901 XString elemS(elem->getTagName());
902 std::list<element_t*>::iterator eter;
903 for (eter = fElements.begin(); eter != fElements.end(); ++eter) {
904 if (elemS == (*eter)->fName) {
905 elemS = parent_element->fName + "_" + elemS;
906 }
907 }
908 TTree *tree = new TTree(S(elemS)elemS.c_str(), S(XString(elemS + " tree"))XString(elemS + " tree").c_str());
909 element_t *this_element = new element_t(tree, elemS);
910 fElements.push_back(this_element);
911
912 XString repS(elem->getAttribute(X("maxOccurs")XString("maxOccurs").unicode_str()));
913 int rep = (repS == "unbounded")? INT_MAX2147483647 :
914 (repS == "")? 1 :
915 atoi(S(repS)repS.c_str());
916 if (explicit_repeat_count && rep > 1)
917 this_element->set_repeating();
918
919 // Create a new column called "key" to hold synchronization
920 // information between rows in different trees, similar to
921 // the way keys are used in relational databases (eg. JOIN).
922
923 XString keyS("HDDM_MASTER_ORDERING_KEY");
924 if (fColumns.find(keyS) == fColumns.end()) {
925 int_attribute_t *key = new int_attribute_t("key");
926 fColumns[keyS] = key;
927 }
928 tree->Branch("key", fColumns[keyS]->address(), "key/I");
929 this_element->add_key((int_attribute_t*)fColumns[keyS]);
930
931 // Add branches for attributes inherited from parent elements
932
933 attribute_list::iterator iter;
934 for (iter = columns.begin(); iter != columns.end(); ++iter) {
935 XString colS = iter->first;
936 XString nameS = iter->second;
937 XString typeS = fColumns[colS]->get_type();
938 if (typeS == "int" || typeS == "boolean" || typeS == "Particle_t")
939 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
940 S(XString(nameS + "/I"))XString(nameS + "/I").c_str());
941 else if (typeS == "long")
942 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
943 S(XString(nameS + "/L"))XString(nameS + "/L").c_str());
944 else if (typeS == "float")
945 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
946 S(XString(nameS + "/F"))XString(nameS + "/F").c_str());
947 else if (typeS == "double")
948 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
949 S(XString(nameS + "/D"))XString(nameS + "/D").c_str());
950 else if (typeS == "string" || typeS == "anyURI")
951 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
952 S(XString(nameS + "/C"))XString(nameS + "/C").c_str());
953 else {
954 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
955 S(XString(nameS + "/C"))XString(nameS + "/C").c_str());
956 }
957 }
958
959 // Add branches for the element's own attributes
960
961 DOMNamedNodeMap* attrList = elem->getAttributes();
962 int attrListLength = attrList->getLength();
963 for (int a = 0; a < attrListLength; a++) {
964 DOMNode* node = attrList->item(a);
965 XString nameS(node->getNodeName());
966 XString typeS(node->getNodeValue());
967 XString colS(elemS + "_" + nameS);
968 if (columns.find(nameS) != columns.end())
969 nameS = colS;
970 if (typeS == "int") {
971 fColumns[colS] = new int_attribute_t(nameS);
972 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
973 S(XString(nameS + "/I"))XString(nameS + "/I").c_str());
974 }
975 else if (typeS == "boolean") {
976 fColumns[colS] = new boolean_attribute_t(nameS);
977 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
978 S(XString(nameS + "/I"))XString(nameS + "/I").c_str());
979 }
980 else if (typeS == "Particle_t") {
981 fColumns[colS] = new Particle_attribute_t(nameS);
982 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
983 S(XString(nameS + "/I"))XString(nameS + "/I").c_str());
984 }
985 else if (typeS == "long") {
986 fColumns[colS] = new long_attribute_t(nameS);
987 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
988 S(XString(nameS + "/L"))XString(nameS + "/L").c_str());
989 }
990 else if (typeS == "float") {
991 fColumns[colS] = new float_attribute_t(nameS);
992 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
993 S(XString(nameS + "/F"))XString(nameS + "/F").c_str());
994 }
995 else if (typeS == "double") {
996 fColumns[colS] = new double_attribute_t(nameS);
997 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
998 S(XString(nameS + "/D"))XString(nameS + "/D").c_str());
999 }
1000 else if (typeS == "string") {
1001 fColumns[colS] = new string_attribute_t(nameS);
1002 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
1003 S(XString(nameS + "/C"))XString(nameS + "/C").c_str());
1004 }
1005 else if (typeS == "anyURI") {
1006 fColumns[colS] = new anyURI_attribute_t(nameS);
1007 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
1008 S(XString(nameS + "/C"))XString(nameS + "/C").c_str());
1009 }
1010 else if (nameS == "minOccurs" || nameS == "maxOccurs") {
1011 continue;
1012 }
1013 else {
1014 fColumns[colS] = new constant_attribute_t(nameS);
1015 tree->Branch(S(nameS)nameS.c_str(), fColumns[colS]->address(),
1016 S(XString(nameS + "/C"))XString(nameS + "/C").c_str());
1017 ((constant_attribute_t*)fColumns[colS])->set(S(typeS)typeS.c_str());
1018 }
1019 columns[colS] = nameS;
1020 this_element->add_attribute(fColumns[colS]);
1021 }
1022
1023 parent_element->add_element(this_element);
1024
1025 // Recursively build any elements contained within this one
1026
1027 DOMNodeList* contList = elem->getChildNodes();
1028 int contLength = contList->getLength();
1029 for (int c = 0; c < contLength; c++) {
1030 DOMNode* cont = contList->item(c);
1031 short type = cont->getNodeType();
1032 if (type == DOMNode::ELEMENT_NODE) {
1033 DOMElement* contEl = (DOMElement*) cont;
1034 build(contEl, this_element, columns);
1035 }
1036 }
1037}
1038
1039int TreeMaker::filltrees(ixstream *ifx, element_t *parent_element)
1040{
1041 element_t *HDDMelement = *parent_element->fElements.begin();
1042 std::list<element_t*>::iterator iter;
1043 int size = 0;
1044 for (iter = HDDMelement->fElements.begin();
1045 iter != HDDMelement->fElements.end();
1046 ++iter)
1047 {
1048 size += (*iter)->read(ifx);
1049#ifdef VERBOSE_HDDM_LOGGING
1050 XString cnameS((*iter)->fName);
1051 std::cerr << "hddm-root : top-level tag " << S(cnameS)cnameS.c_str()
1052 << " found with size " << size
1053 << std::endl;
1054#endif
1055 }
1056 return size;
1057}
1058
1059int TreeMaker::savetrees(element_t *parent_element)
1060{
1061 int count = 0;
1062 std::list<element_t*>::iterator iter;
1063 for (iter = parent_element->fElements.begin();
1064 iter != parent_element->fElements.end();
1065 ++iter)
1066 {
1067 if ((*iter)->fTree) {
1068 (*iter)->fTree->Write();
1069 ++count;
1070 }
1071 count += savetrees(*iter);
1072 }
1073 return count;
1074}