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 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
41 | using namespace xercesc; | |||
42 | ||||
43 | int explicit_repeat_count = 1; | |||
44 | int write_xml_output_to_stdout = 0; | |||
45 | ||||
46 | void 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 | ||||
59 | typedef xstream::xdr::istream ixstream; | |||
60 | ||||
61 | class 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 | ||||
85 | class 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 | ||||
119 | class 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 | ||||
153 | class 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 | ||||
190 | class 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 | ||||
228 | class 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 | ||||
262 | class 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 | ||||
296 | class 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 | ||||
330 | class 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 | ||||
364 | class 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) | |||
380 | delete value; | |||
381 | if (!str
| |||
382 | return; | |||
383 | int size = (strlen(str) + 7) / 4 * 4; | |||
| ||||
384 | value = new char[size]; | |||
385 | strncpy(value, str, size); | |||
386 | } | |||
387 | ||||
388 | constant_attribute_t &operator=(const constant_attribute_t &src) { | |||
| ||||
389 | fName = src.fName; | |||
390 | set(src.value); | |||
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 | ||||
407 | class 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 | ||||
516 | typedef std::map<XString,XString> attribute_list; | |||
517 | typedef std::map<XString,attribute_t*> attribute_table; | |||
518 | ||||
519 | class 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 | ||||
547 | class 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 | ||||
577 | int 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 | ||||
895 | void 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 | ||||
1039 | int 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 | ||||
1059 | int 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 | } |