Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hddm-py.cpp
Go to the documentation of this file.
1 /*
2  * hddm-py : tool that reads in a HDDM document (Hall D Data Model)
3  * and writes a c++ class library that expresses the model as a
4  * python extension module. It does this by wrapping the classes
5  * of the c++ API as python classes, adding convenience methods
6  * to provide natural pythonic semantics for handling hddm files
7  * and objects.
8  *
9  * author: richard.t.jones at uconn.edu
10  * version: june 24, 2016 - original release.
11  *
12  */
13 
14 #include "XString.hpp"
15 #include "XParsers.hpp"
16 #include <xercesc/util/XMLUri.hpp>
17 
18 #include <particleType.h>
19 #include <errno.h>
20 
21 #include <string>
22 #include <vector>
23 #include <map>
24 #include <fstream>
25 
26 #define X(str) XString(str).unicode_str()
27 #define S(str) str.c_str()
28 
29 using namespace xercesc;
30 
32 
33 void usage()
34 {
35  std::cerr
36  << "\nUsage:\n"
37  << " hddm-py [-v | -o <filename>] {HDDM file}\n\n"
38  << "Options:\n"
39  << " -v validate only\n"
40  << " -o <filename> write to <filename>.cpy"
41  << std::endl;
42 }
43 
44 std::string guessType(const std::string &literal);
46 
47 class XtString : public XString
48 {
49 /* XString class with a few extra methods for creating type
50  * strings that are useful in creating class names
51  */
52  public:
53  XtString() {};
54  XtString(const char* s): XString(s) {};
55  XtString(const XMLCh* p): XString(p) {};
56  XtString(const std::string& s): XString(s) {};
57  XtString(const XString& x): XString(x) {};
58  XtString(const XtString& t): XString((XString&)t) {};
59  ~XtString() {};
60 
61  XtString plural();
62  XtString simpleType();
63  XtString listType();
64  XtString linkType();
65 };
66 
67 class CodeBuilder
68 {
69 /* The methods in this class are used to write the c++ code
70  * that implements the hddm python extension library.
71  */
72  public:
73  std::ofstream pyFile;
74 
77 
78  void checkConsistency(DOMElement* el, DOMElement* elref);
79  void writeClassdef(DOMElement* el);
80  void writeClassimp(DOMElement* el);
81  void constructDocument(DOMElement* el);
82  void constructGroup(DOMElement* el);
83  void constructIOstreams(DOMElement* el);
84  void constructMethods(DOMElement* el);
85  void constructStreamers(DOMElement* el);
86  void writeStreamers(DOMElement* el);
87 
88  typedef struct {
92  } method_descr;
93 
94  std::map<XtString,XtString> typesList;
95 
96  private:
97  std::vector<DOMElement*> tagList;
98  typedef std::vector<DOMNode*> parentList_t;
99  typedef std::map<const XtString,parentList_t> parentTable_t;
100  parentList_t parentList;
101  parentTable_t parents;
102  parentTable_t children;
103  int element_in_list(XtString &name, parentList_t list);
104 };
105 
106 
107 int main(int argC, char* argV[])
108 {
109  try
110  {
111  XMLPlatformUtils::Initialize();
112  }
113  catch (const XMLException* toCatch)
114  {
115  XtString msg(toCatch->getMessage());
116  std::cerr
117  << "hddm-py: Error during initialization! :\n"
118  << msg << std::endl;
119  return 1;
120  }
121 
122  if (argC < 2)
123  {
124  usage();
125  return 1;
126  }
127  else if ((argC == 2) && (strcmp(argV[1], "-?") == 0))
128  {
129  usage();
130  return 2;
131  }
132 
133  XtString xmlFile;
134  XtString pyFilename;
135  bool verifyOnly = false;
136  int argInd;
137  for (argInd = 1; argInd < argC; argInd++)
138  {
139  if (argV[argInd][0] != '-')
140  {
141  break;
142  }
143  if (strcmp(argV[argInd],"-v") == 0)
144  {
145  verifyOnly = true;
146  }
147  else if (strcmp(argV[argInd],"-o") == 0)
148  {
149  pyFilename = XtString(argV[++argInd]);
150  }
151  else
152  {
153  std::cerr
154  << "Unknown option \'" << argV[argInd]
155  << "\', ignoring it\n" << std::endl;
156  }
157  }
158 
159  if (argInd != argC - 1)
160  {
161  usage();
162  return 1;
163  }
164  xmlFile = XtString(argV[argInd]);
165 
166 #if defined OLD_STYLE_XERCES_PARSER
167  DOMDocument* document = parseInputDocument(xmlFile.c_str(),false);
168 #else
169  DOMDocument* document = buildDOMDocument(xmlFile.c_str(),false);
170 #endif
171  if (document == 0)
172  {
173  std::cerr
174  << "hddm-py : Error parsing HDDM document, "
175  << "cannot continue" << std::endl;
176  return 1;
177  }
178 
179  DOMElement* rootEl = document->getDocumentElement();
180  XtString rootS(rootEl->getTagName());
181  if (rootS != "HDDM")
182  {
183  std::cerr
184  << "hddm-py error: root element of input document is "
185  << "\"" << rootS << "\", expected \"HDDM\""
186  << std::endl;
187  return 1;
188  }
189 
190  XtString classS(rootEl->getAttribute(X("class")));
191  classPrefix = classS;
192 
193  XtString pyname;
194  if (verifyOnly)
195  {
196  pyname = "/dev/null";
197  }
198  else if (pyFilename.size())
199  {
200  pyname = pyFilename + ".cpy";
201  }
202  else
203  {
204  pyname = "pyhddm_" + classPrefix + ".cpy";
205  }
206 
207  CodeBuilder builder;
208  builder.pyFile.open(pyname.c_str());
209  if (! builder.pyFile.is_open())
210  {
211  std::cerr
212  << "hddm-py error: unable to open output file "
213  << pyname << std::endl;
214  return 1;
215  }
216 
217  builder.pyFile <<
218  "/*\n"
219  " * pyhddm_" << classPrefix << ".cpy - DO NOT EDIT THIS FILE\n"
220  " *\n"
221  " * This file was generated automatically by hddm-py from the file\n"
222  << " * " << xmlFile << std::endl <<
223  "\n"
224  " * This source file contains the Python/C++ API wrappers that\n"
225  " * provide a python interface to the hddm classes and methods\n"
226  " * generated by hddm-cpp from " << xmlFile << ".\n"
227  " *\n"
228  " * The hddm data model tool set was written by\n"
229  " * Richard Jones, University of Connecticut.\n"
230  " *\n"
231  " * For more information see the following web site\n"
232  " *\n"
233  " * http://zeus.phys.uconn.edu/halld/datamodel/doc\n"
234  " *\n"
235  " */\n"
236  "\n"
237  "#include <Python.h>\n"
238  "#include <structmember.h>\n"
239  "\n"
240  "#include <hddm_" << classPrefix << ".hpp>\n"
241  "#include <fstream>\n"
242  "#include <iostream>\n"
243  "#include <exception>\n"
244  "#include <particleType.h>\n"
245  "\n"
246  "using namespace hddm_" << classPrefix << ";\n"
247  "\n"
248  "#if PY_MAJOR_VERSION >= 3\n"
249  " #define PyInt_FromLong PyLong_FromLong\n"
250  " #define PyInt_AsLong PyLong_AsLong\n"
251  "#endif\n"
252  "\n"
253  "\n"
254  "inline void LOG_NEW(PyTypeObject *t, PyTypeObject *subt=0, int own=0) {\n"
255  "#if 0\n"
256  " if (subt == 0)\n"
257  " std::cout << \"creating a new element of \" << t->tp_name\n"
258  " << \" \" << ((own == 0)? \"(borrowed)\" : \"(owned)\")\n"
259  " << std::endl;\n"
260  " else\n"
261  " std::cout << \"creating a new list of \" << subt->tp_name\n"
262  " << \" \" << ((own == 0)? \"(borrowed)\" : \"(owned)\")\n"
263  " << std::endl;\n"
264  "#endif\n"
265  "}\n"
266  "\n"
267  "inline void LOG_DEALLOC(PyTypeObject *t, PyTypeObject *subt=0, int own=0) {\n"
268  "#if 0\n"
269  " if (subt == 0)\n"
270  " std::cout << \"destroying an element of \" << t->tp_name\n"
271  " << \" \" << ((own == 0)? \"(borrowed)\" : \"(owned)\")\n"
272  " << std::endl;\n"
273  " else\n"
274  " std::cout << \"destroying a list of \" << subt->tp_name\n"
275  " << \" \" << ((own == 0)? \"(borrowed)\" : \"(owned)\")\n"
276  " << std::endl;\n"
277  "#endif\n"
278  "}\n"
279  "\n"
280  "inline void My_INCREF(PyObject *o) {\n"
281  " //std::cout << \"incrementing reference at \" << o << std::endl;\n"
282  " Py_INCREF(o);\n"
283  "}\n"
284  "\n"
285  "inline void My_DECREF(PyObject *o) {\n"
286  " //std::cout << \"decrementing reference at \" << o << std::endl;\n"
287  " Py_DECREF(o);\n"
288  "}\n"
289  "\n"
290  "// wrap base class hddm_" << classPrefix << "::HDDM_Element"
291  " as hddm_" << classPrefix << ".HDDM_Element\n"
292  "\n"
293  "typedef struct {\n"
294  " PyObject_HEAD\n"
295  " HDDM_Element *elem;\n"
296  " PyObject *host;\n"
297  "} _HDDM_Element;\n"
298  "\n"
299  "static void\n"
300  "_HDDM_Element_dealloc(_HDDM_Element* self)\n"
301  "{\n"
302  " if (self->elem != 0) {\n"
303  " LOG_DEALLOC(Py_TYPE(self), 0, self->host == (PyObject*)self);\n"
304  " if (self->host == (PyObject*)self)\n"
305  " delete self->elem;\n"
306  " else\n"
307  " My_DECREF(self->host);\n"
308  " }\n"
309  " Py_TYPE(self)->tp_free((PyObject*)self);\n"
310  "}\n"
311  "\n"
312  "static PyObject*\n"
313  "_HDDM_Element_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n"
314  "{\n"
315  " _HDDM_Element *self;\n"
316  " self = (_HDDM_Element*)type->tp_alloc(type, 0);\n"
317  " if (self != NULL) {\n"
318  " self->elem = 0;\n"
319  " self->host = 0;\n"
320  " }\n"
321  " return (PyObject*)self;\n"
322  "}\n"
323  "\n"
324  "static int\n"
325  "_HDDM_Element_init(_HDDM_Element *self, PyObject *args, PyObject *kwds)\n"
326  "{\n"
327  " PyErr_SetString(PyExc_RuntimeError, \"illegal constructor\");\n"
328  " return -1;\n"
329  "}\n"
330  "\n"
331  "static PyObject*\n"
332  "_HDDM_Element_getAttribute(PyObject *self, PyObject *args)\n"
333  "{\n"
334  " char *attr;\n"
335  " if (! PyArg_ParseTuple(args, \"s\", &attr)) {\n"
336  " return NULL;\n"
337  " }\n"
338  " _HDDM_Element *me = (_HDDM_Element*)self;\n"
339  " if (me->elem == 0) {\n"
340  " PyErr_SetString(PyExc_RuntimeError, \"lookup attempted on invalid"
341  " element\");\n"
342  " return NULL;\n"
343  " }\n"
344  " hddm_type atype;\n"
345  " void *val((int*)me->elem->getAttribute(std::string(attr),&atype));\n"
346  " if (val == 0) {\n"
347  " Py_INCREF(Py_None);\n"
348  " return Py_None;\n"
349  " }\n"
350  " else if (atype == k_hddm_int) {\n"
351  " return PyLong_FromLong(*(int*)val);\n"
352  " }\n"
353  " else if (atype == k_hddm_long) {\n"
354  " return PyLong_FromLong(*(long*)val);\n"
355  " }\n"
356  " else if (atype == k_hddm_float) {\n"
357  " return PyFloat_FromDouble(double(*(float*)val));\n"
358  " }\n"
359  " else if (atype == k_hddm_double) {\n"
360  " return PyFloat_FromDouble(*(double*)val);\n"
361  " }\n"
362  " else if (atype == k_hddm_boolean) {\n"
363  " if (*(bool*)val == 0) {\n"
364  " Py_INCREF(Py_False);\n"
365  " return Py_False;\n"
366  " }\n"
367  " else {\n"
368  " Py_INCREF(Py_True);\n"
369  " return Py_True;\n"
370  " }\n"
371  " }\n"
372  " else if (atype == k_hddm_string) {\n"
373  " return PyUnicode_FromString(((std::string*)val)->c_str());\n"
374  " }\n"
375  " else if (atype == k_hddm_anyURI) {\n"
376  " return PyUnicode_FromString(((std::string*)val)->c_str());\n"
377  " }\n"
378  " else if (atype == k_hddm_Particle_t) {\n"
379  " return PyUnicode_FromString(ParticleType(*(Particle_t*)val));\n"
380  " }\n"
381  " return PyUnicode_FromString(((std::string*)val)->c_str());\n"
382  "}\n\n"
383  "static PyMemberDef _HDDM_Element_members[] = {\n"
384  " {NULL} /* Sentinel */\n"
385  "};\n"
386  "\n"
387  "static PyMethodDef _HDDM_Element_methods[] = {\n"
388  " {\"getAttribute\", _HDDM_Element_getAttribute, METH_VARARGS,\n"
389  " \"look up named attribute in this element\"},\n"
390  " {NULL} /* Sentinel */\n"
391  "};\n"
392  "\n"
393  "static PyTypeObject _HDDM_Element_type = {\n"
394  " PyVarObject_HEAD_INIT(NULL,0)\n"
395  " \"hddm_" << classPrefix << ".HDDM_Element\", /*tp_name*/\n"
396  " sizeof(_HDDM_Element), /*tp_basicsize*/\n"
397  " 0, /*tp_itemsize*/\n"
398  " (destructor)_HDDM_Element_dealloc, /*tp_dealloc*/\n"
399  " 0, /*tp_print*/\n"
400  " 0, /*tp_getattr*/\n"
401  " 0, /*tp_setattr*/\n"
402  " 0, /*tp_compare*/\n"
403  " 0, /*tp_repr*/\n"
404  " 0, /*tp_as_number*/\n"
405  " 0, /*tp_as_sequence*/\n"
406  " 0, /*tp_as_mapping*/\n"
407  " 0, /*tp_hash */\n"
408  " 0, /*tp_call*/\n"
409  " 0, /*tp_str*/\n"
410  " 0, /*tp_getattro*/\n"
411  " 0, /*tp_setattro*/\n"
412  " 0, /*tp_as_buffer*/\n"
413  " Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/\n"
414  " \"hddm_" << classPrefix << " basic element\", /* tp_doc */\n"
415  " 0, /* tp_traverse */\n"
416  " 0, /* tp_clear */\n"
417  " 0, /* tp_richcompare */\n"
418  " 0, /* tp_weaklistoffset */\n"
419  " 0, /* tp_iter */\n"
420  " 0, /* tp_iternext */\n"
421  " _HDDM_Element_methods, /* tp_methods */\n"
422  " _HDDM_Element_members, /* tp_members */\n"
423  " 0, /* tp_getset */\n"
424  " 0, /* tp_base */\n"
425  " 0, /* tp_dict */\n"
426  " 0, /* tp_descr_get */\n"
427  " 0, /* tp_descr_set */\n"
428  " 0, /* tp_dictoffset */\n"
429  " (initproc)_HDDM_Element_init, /* tp_init */\n"
430  " 0, /* tp_alloc */\n"
431  " _HDDM_Element_new, /* tp_new */\n"
432  "};\n"
433  "\n"
434  "\n"
435  "// wrap base class hddm_" << classPrefix << "::HDDM_ElementList"
436  " as hddm_" << classPrefix << ".HDDM_ElementList\n"
437  "\n"
438  "typedef struct {\n"
439  " PyObject_HEAD\n"
440  " PyTypeObject *subtype; // type of wrapper derived from _HDDM_Element\n"
441  " HDDM_ElementList<HDDM_Element> *list;\n"
442  " PyObject *host;\n"
443  " int borrowed;\n"
444  "} _HDDM_ElementList;\n"
445  "\n"
446  "static void\n"
447  "_HDDM_ElementList_dealloc(_HDDM_ElementList* self)\n"
448  "{\n"
449  " if (self->list != 0) {\n"
450  " LOG_DEALLOC(Py_TYPE(self), self->subtype, self->borrowed == 0);\n"
451  " if (self->borrowed == 0)\n"
452  " delete self->list;\n"
453  " My_DECREF(self->host);\n"
454  " }\n"
455  " Py_TYPE(self)->tp_free((PyObject*)self);\n"
456  "}\n"
457  "\n"
458  "static PyObject*\n"
459  "_HDDM_ElementList_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n"
460  "{\n"
461  " _HDDM_ElementList *self;\n"
462  " self = (_HDDM_ElementList*)type->tp_alloc(type, 0);\n"
463  " if (self != NULL) {\n"
464  " self->subtype = 0;\n"
465  " self->borrowed = 0;\n"
466  " self->host = 0;\n"
467  " }\n"
468  " return (PyObject*)self;\n"
469  "}\n"
470  "\n"
471  "static int\n"
472  "_HDDM_ElementList_init(_HDDM_ElementList *self, PyObject *args, PyObject *kwds)\n"
473  "{\n"
474  " PyErr_SetString(PyExc_RuntimeError, \"illegal constructor\");\n"
475  " return -1;\n"
476  "}\n"
477  "\n"
478  "static Py_ssize_t\n"
479  "_HDDM_ElementList_size(_HDDM_ElementList *self, void *closure)\n"
480  "{\n"
481  " if (self->list == 0) {\n"
482  " PyErr_SetString(PyExc_RuntimeError, \"size attempted on invalid list\");\n"
483  " return -1;\n"
484  " }\n"
485  " return self->list->size();\n"
486  "}\n"
487  "\n"
488  "static PyObject*\n"
489  "_HDDM_ElementList_item(_HDDM_ElementList *self, Py_ssize_t i)\n"
490  "{\n"
491  " if (self->list == 0)\n"
492  " return NULL;\n"
493  " int len = self->list->size();\n"
494  " if (i < 0 || i >= len) {\n"
495  " PyErr_Format(PyExc_IndexError, \"index \\%ld out of bounds.\", i);\n"
496  " return NULL;\n"
497  " }\n"
498  " PyObject *elem_obj = _HDDM_Element_new(self->subtype, 0, 0);\n"
499  " ((_HDDM_Element*)elem_obj)->elem = &(HDDM_Element&)(*self->list)(i);\n"
500  " ((_HDDM_Element*)elem_obj)->host = self->host;\n"
501  " My_INCREF(self->host);\n"
502  " LOG_NEW(self->subtype);\n"
503  " return elem_obj;\n"
504  "}\n"
505  "\n"
506  "extern PyTypeObject _HDDM_ElementList_type;\n"
507  "\n"
508  "static PyObject *\n"
509  "_HDDM_ElementList_add(PyObject *self, PyObject *args)\n"
510  "{\n"
511  " int count=0;\n"
512  " int start=-1;\n"
513  " if (! PyArg_ParseTuple(args, \"i|i\", &count, &start)) {\n"
514  " return NULL;\n"
515  " }\n"
516  " _HDDM_ElementList *me = (_HDDM_ElementList*)self;\n"
517  " if (me->list == 0) {\n"
518  " PyErr_SetString(PyExc_RuntimeError, \"add attempted on invalid list\");\n"
519  " return NULL;\n"
520  " }\n"
521  " PyObject *list = _HDDM_ElementList_new(&_HDDM_ElementList_type, 0, 0);\n"
522  " ((_HDDM_ElementList*)list)->subtype = me->subtype;\n"
523  " ((_HDDM_ElementList*)list)->list = (HDDM_ElementList<HDDM_Element>*)\n"
524  " new HDDM_ElementList<HDDM_Element>(me->list->add(count, start));\n"
525  " ((_HDDM_ElementList*)list)->borrowed = 0;\n"
526  " ((_HDDM_ElementList*)list)->host = me->host;\n"
527  " My_INCREF(me->host);\n"
528  " LOG_NEW(Py_TYPE(self), me->subtype, 1);\n"
529  " return list;\n"
530  "}\n"
531  "\n"
532  "static PyObject *\n"
533  "_HDDM_ElementList_del(PyObject *self, PyObject *args)\n"
534  "{\n"
535  " int start=0;\n"
536  " int count=-1;\n"
537  " if (! PyArg_ParseTuple(args, \"|ii\", &count, &start)) {\n"
538  " return NULL;\n"
539  " }\n"
540  " _HDDM_ElementList *list_obj;\n"
541  " list_obj = (_HDDM_ElementList*)self;\n"
542  " if (list_obj->list == 0) {\n"
543  " PyErr_SetString(PyExc_RuntimeError, \"del attempted on invalid list\");\n"
544  " return NULL;\n"
545  " }\n"
546  " list_obj->list->del(count, start);\n"
547  " Py_INCREF(self);\n"
548  " return self;\n"
549  "}\n"
550  "\n"
551  "static PyObject *\n"
552  "_HDDM_ElementList_clear(PyObject *self, PyObject *args)\n"
553  "{\n"
554  " _HDDM_ElementList *list_obj;\n"
555  " list_obj = (_HDDM_ElementList*)self;\n"
556  " if (list_obj->list == 0) {\n"
557  " PyErr_SetString(PyExc_RuntimeError, \"clear attempted on invalid list\");\n"
558  " return NULL;\n"
559  " }\n"
560  " list_obj->list->clear();\n"
561  " Py_INCREF(self);\n"
562  " return self;\n"
563  "}\n"
564  "\n"
565  "static PyMemberDef _HDDM_ElementList_members[] = {\n"
566  " {NULL} /* Sentinel */\n"
567  "};\n"
568  "\n"
569  "static PyMethodDef _HDDM_ElementList_methods[] = {\n"
570  " {\"add\", _HDDM_ElementList_add, METH_VARARGS,\n"
571  " \"add (or insert) a new element to the list.\"},\n"
572  " {\"del\", _HDDM_ElementList_del, METH_VARARGS,\n"
573  " \"delete an existing element from the list.\"},\n"
574  " {\"clear\", _HDDM_ElementList_clear, METH_NOARGS,\n"
575  " \"reset the list to zero elements.\"},\n"
576  " {NULL} /* Sentinel */\n"
577  "};\n"
578  "\n"
579  "static PySequenceMethods _HDDM_ElementList_as_sequence = {\n"
580  " (lenfunc)_HDDM_ElementList_size, /* sq_length */\n"
581  " 0, /* sq_concat */\n"
582  " 0, /* sq_repeat */\n"
583  " (ssizeargfunc)_HDDM_ElementList_item, /* sq_item */\n"
584  " 0, /* sq_slice */\n"
585  " 0, /* sq_ass_item */\n"
586  " 0, /* sq_ass_slice */\n"
587  " 0, /* sq_contains */\n"
588  " 0, /* sq_inplace_concat */\n"
589  " 0, /* sq_inplace_repeat */\n"
590  "};\n"
591  "\n"
592  "PyTypeObject _HDDM_ElementList_type = {\n"
593  " PyVarObject_HEAD_INIT(NULL,0)\n"
594  " \"hddm_" << classPrefix << ".HDDM_ElementList\", /*tp_name*/\n"
595  " sizeof(_HDDM_ElementList), /*tp_basicsize*/\n"
596  " 0, /*tp_itemsize*/\n"
597  " (destructor)_HDDM_ElementList_dealloc, /*tp_dealloc*/\n"
598  " 0, /*tp_print*/\n"
599  " 0, /*tp_getattr*/\n"
600  " 0, /*tp_setattr*/\n"
601  " 0, /*tp_compare*/\n"
602  " 0, /*tp_repr*/\n"
603  " 0, /*tp_as_number*/\n"
604  " &_HDDM_ElementList_as_sequence, /*tp_as_sequence*/\n"
605  " 0, /*tp_as_mapping*/\n"
606  " 0, /*tp_hash */\n"
607  " 0, /*tp_call*/\n"
608  " 0, /*tp_str*/\n"
609  " 0, /*tp_getattro*/\n"
610  " 0, /*tp_setattro*/\n"
611  " 0, /*tp_as_buffer*/\n"
612  " Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/\n"
613  " \"hddm_" << classPrefix << " output stream\", /* tp_doc */\n"
614  " 0, /* tp_traverse */\n"
615  " 0, /* tp_clear */\n"
616  " 0, /* tp_richcompare */\n"
617  " 0, /* tp_weaklistoffset */\n"
618  " 0, /* tp_iter */\n"
619  " 0, /* tp_iternext */\n"
620  " _HDDM_ElementList_methods, /* tp_methods */\n"
621  " _HDDM_ElementList_members, /* tp_members */\n"
622  " 0, /* tp_getset */\n"
623  " 0, /* tp_base */\n"
624  " 0, /* tp_dict */\n"
625  " 0, /* tp_descr_get */\n"
626  " 0, /* tp_descr_set */\n"
627  " 0, /* tp_dictoffset */\n"
628  " (initproc)_HDDM_ElementList_init, /* tp_init */\n"
629  " 0, /* tp_alloc */\n"
630  " _HDDM_ElementList_new, /* tp_new */\n"
631  "};\n"
632  ;
633 
634  builder.constructGroup(rootEl);
635  builder.constructIOstreams(rootEl);
636  builder.constructMethods(rootEl);
637  builder.constructStreamers(rootEl);
638 
639  builder.typesList["HDDM_Element"] = "_HDDM_Element_type";
640  builder.typesList["HDDM_ElementList"] = "_HDDM_ElementList_type";
641  builder.typesList["streamposition"] = "_streamposition_type";
642  builder.typesList["ostream"] = "_ostream_type";
643  builder.typesList["istream"] = "_istream_type";
644 
645  builder.pyFile <<
646  "\n"
647  "\n"
648  "// wrap class hddm_" << classPrefix << "::streamposition"
649  " as hddm_" << classPrefix << ".streamposition\n"
650  "\n"
651  "typedef struct {\n"
652  " PyObject_HEAD\n"
653  " streamposition *streampos;\n"
654  "} _streamposition;\n"
655  "\n"
656  "static void\n"
657  "_streamposition_dealloc(_streamposition* self)\n"
658  "{\n"
659  " if (self->streampos != 0)\n"
660  " delete self->streampos;\n"
661  " Py_TYPE(self)->tp_free((PyObject*)self);\n"
662  "}\n"
663  "\n"
664  "static PyObject*\n"
665  "_streamposition_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n"
666  "{\n"
667  " _streamposition *self;\n"
668  " self = (_streamposition*)type->tp_alloc(type, 0);\n"
669  " if (self != NULL)\n"
670  " self->streampos = 0;\n"
671  " return (PyObject*)self;\n"
672  "}\n"
673  "\n"
674  "static int\n"
675  "_streamposition_init(_streamposition *self, PyObject *args, PyObject *kwds)\n"
676  "{\n"
677  " const char *kwlist[] = {\"start\", \"offset\", \"status\", NULL};\n"
678  " uint64_t start = 0;\n"
679  " uint32_t offset = 0;\n"
680  " uint32_t status = 0;\n"
681  " if (PyArg_ParseTuple(args, \"\") ||\n"
682  " PyArg_ParseTupleAndKeywords(args, kwds, \"kII\", (char**)kwlist, \n"
683  " &start, &offset, &status))\n"
684  " {\n"
685  " PyErr_Clear();\n"
686  " if (self->streampos != 0)\n"
687  " delete self->streampos;\n"
688  " self->streampos = new streamposition(start, offset, status);\n"
689  " return 0;\n"
690  " }\n"
691  " return -1; \n"
692  "}\n"
693  "\n"
694  "static PyObject*\n"
695  "_streamposition_richcompare(PyObject *a, PyObject *b, int op)\n"
696  "{\n"
697  " int res = 0;\n"
698  " streamposition *apos = ((_streamposition*)a)->streampos;\n"
699  " streamposition *bpos = ((_streamposition*)b)->streampos;\n"
700  " if (op == Py_LT)\n"
701  " res = (*apos < *bpos);\n"
702  " else if (op == Py_LE)\n"
703  " res = (*apos <= *bpos);\n"
704  " else if (op == Py_EQ)\n"
705  " res = (*apos == *bpos);\n"
706  " else if (op == Py_NE)\n"
707  " res = (*apos != *bpos);\n"
708  " else if (op == Py_GT)\n"
709  " res = (*apos > *bpos);\n"
710  " else if (op == Py_GE)\n"
711  " res = (*apos >= *bpos);\n"
712  " if (res) {\n"
713  " Py_INCREF(Py_True);\n"
714  " return Py_True;\n"
715  " }\n"
716  " else {\n"
717  " Py_INCREF(Py_False);\n"
718  " return Py_False;\n"
719  " }\n"
720  "}\n"
721  "static PyObject*\n"
722  "_streamposition_toString(PyObject *self, PyObject *args=0)\n"
723  "{\n"
724  " std::stringstream ostr;\n"
725  " ostr << \"hddm_" << classPrefix << ".streamposition(\"\n"
726  " << ((_streamposition*)self)->streampos->block_start << \",\"\n"
727  " << ((_streamposition*)self)->streampos->block_offset << \",\"\n"
728  " << ((_streamposition*)self)->streampos->block_status\n"
729  " << \")\";\n"
730  " return PyUnicode_FromString(ostr.str().c_str());\n"
731  "}\n"
732  "\n"
733  "static PyObject*\n"
734  "_streamposition_toRepr(PyObject *self, PyObject *args=0)\n"
735  "{\n"
736  " std::stringstream ostr;\n"
737  " ostr << \"\\\'\";\n"
738  " ostr << \"hddm_" << classPrefix << ".streamposition(\"\n"
739  " << ((_streamposition*)self)->streampos->block_start << \",\"\n"
740  " << ((_streamposition*)self)->streampos->block_offset << \",\"\n"
741  " << ((_streamposition*)self)->streampos->block_status\n"
742  " << \")\";\n"
743  " ostr << \"\\\'\";\n"
744  " return PyUnicode_FromString(ostr.str().c_str());\n"
745  "}\n"
746  "\n"
747  "static PyObject*\n"
748  "_streamposition_getstart(_streamposition *self, void *closure)\n"
749  "{\n"
750  " return Py_BuildValue(\"k\", self->streampos->block_start);\n"
751  "}\n"
752  "\n"
753  "static int\n"
754  "_streamposition_setstart(_streamposition *self, PyObject *value, void *closure)\n"
755  "{\n"
756  " if (value == NULL) {\n"
757  " PyErr_SetString(PyExc_TypeError, \"unexpected null argument\");\n"
758  " return -1;\n"
759  " }\n"
760  " long start = PyInt_AsLong(value);\n"
761  " if (start < 0 && PyErr_Occurred()) {\n"
762  " return -1;\n"
763  " }\n"
764  " self->streampos->block_start = start;\n"
765  " return 0;\n"
766  "}\n"
767  "\n"
768  "static PyObject*\n"
769  "_streamposition_getoffset(_streamposition *self, void *closure)\n"
770  "{\n"
771  " return Py_BuildValue(\"I\", self->streampos->block_offset);\n"
772  "}\n"
773  "\n"
774  "static int\n"
775  "_streamposition_setoffset(_streamposition *self, PyObject *value, void *closure)\n"
776  "{\n"
777  " if (value == NULL) {\n"
778  " PyErr_SetString(PyExc_TypeError, \"unexpected null argument\");\n"
779  " return -1;\n"
780  " }\n"
781  " long offset = PyInt_AsLong(value);\n"
782  " if (offset < 0 && PyErr_Occurred()) {\n"
783  " return -1;\n"
784  " }\n"
785  " self->streampos->block_offset = offset;\n"
786  " return 0;\n"
787  "}\n"
788  "\n"
789  "static PyObject*\n"
790  "_streamposition_getstatus(_streamposition *self, void *closure)\n"
791  "{\n"
792  " return Py_BuildValue(\"I\", self->streampos->block_status);\n"
793  "}\n"
794  "\n"
795  "static int\n"
796  "_streamposition_setstatus(_streamposition *self, PyObject *value, void *closure)\n"
797  "{\n"
798  " if (value == NULL) {\n"
799  " PyErr_SetString(PyExc_TypeError, \"unexpected null argument\");\n"
800  " return -1;\n"
801  " }\n"
802  " long status = PyInt_AsLong(value);\n"
803  " if (status == -1 && PyErr_Occurred()) {\n"
804  " return -1;\n"
805  " }\n"
806  " self->streampos->block_status = status;\n"
807  " return 0;\n"
808  "}\n"
809  "\n"
810  "static PyGetSetDef _streamposition_getsetters[] = {\n"
811  " {(char*)\"start\", \n"
812  " (getter)_streamposition_getstart, (setter)_streamposition_setstart,\n"
813  " (char*)\"block start position\",\n"
814  " NULL},\n"
815  " {(char*)\"offset\", \n"
816  " (getter)_streamposition_getoffset, (setter)_streamposition_setoffset,\n"
817  " (char*)\"block offset position\",\n"
818  " NULL},\n"
819  " {(char*)\"status\", \n"
820  " (getter)_streamposition_getstatus, (setter)_streamposition_setstatus,\n"
821  " (char*)\"block status flags\",\n"
822  " NULL},\n"
823  " {NULL} /* Sentinel */\n"
824  "};\n"
825  "\n"
826  "static PyMemberDef _streamposition_members[] = {\n"
827  " {NULL} /* Sentinel */\n"
828  "};\n"
829  "\n"
830  "static PyMethodDef _streamposition_methods[] = {\n"
831  " {NULL} /* Sentinel */\n"
832  "};\n"
833  "\n"
834  "static PyTypeObject _streamposition_type = {\n"
835  " PyVarObject_HEAD_INIT(NULL,0)\n"
836  " \"hddm_" << classPrefix << ".streamposition\", /*tp_name*/\n"
837  " sizeof(_streamposition), /*tp_basicsize*/\n"
838  " 0, /*tp_itemsize*/\n"
839  " (destructor)_streamposition_dealloc, /*tp_dealloc*/\n"
840  " 0, /*tp_print*/\n"
841  " 0, /*tp_getattr*/\n"
842  " 0, /*tp_setattr*/\n"
843  " 0, /*tp_compare*/\n"
844  " (reprfunc)_streamposition_toRepr, /*tp_repr*/\n"
845  " 0, /*tp_as_number*/\n"
846  " 0, /*tp_as_sequence*/\n"
847  " 0, /*tp_as_mapping*/\n"
848  " 0, /*tp_hash */\n"
849  " 0, /*tp_call*/\n"
850  " (reprfunc)_streamposition_toString, /*tp_str*/\n"
851  " 0, /*tp_getattro*/\n"
852  " 0, /*tp_setattro*/\n"
853  " 0, /*tp_as_buffer*/\n"
854  " Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/\n"
855  " \"hddm_" << classPrefix << " streamposition objects\", /* tp_doc */\n"
856  " 0, /* tp_traverse */\n"
857  " 0, /* tp_clear */\n"
858  " _streamposition_richcompare, /* tp_richcompare */\n"
859  " 0, /* tp_weaklistoffset */\n"
860  " 0, /* tp_iter */\n"
861  " 0, /* tp_iternext */\n"
862  " _streamposition_methods, /* tp_methods */\n"
863  " _streamposition_members, /* tp_members */\n"
864  " _streamposition_getsetters, /* tp_getset */\n"
865  " 0, /* tp_base */\n"
866  " 0, /* tp_dict */\n"
867  " 0, /* tp_descr_get */\n"
868  " 0, /* tp_descr_set */\n"
869  " 0, /* tp_dictoffset */\n"
870  " (initproc)_streamposition_init, /* tp_init */\n"
871  " 0, /* tp_alloc */\n"
872  " _streamposition_new, /* tp_new */\n"
873  "};\n"
874  "\n"
875  "\n"
876  "// wrap class hddm_" << classPrefix << "::ostream"
877  " as hddm_" << classPrefix << ".ostream\n"
878  "\n"
879  "typedef struct {\n"
880  " PyObject_HEAD\n"
881  " std::string *fname;\n"
882  " std::ofstream *fstr;\n"
883  " ostream *ostr;\n"
884  "} _ostream;\n"
885  "\n"
886  "static void\n"
887  "_ostream_dealloc(_ostream* self)\n"
888  "{\n"
889  " if (self->fname != 0)\n"
890  " delete self->fname;\n"
891  " if (self->ostr != 0)\n"
892  " delete self->ostr;\n"
893  " if (self->fstr != 0)\n"
894  " delete self->fstr;\n"
895  " Py_TYPE(self)->tp_free((PyObject*)self);\n"
896  "}\n"
897  "\n"
898  "static PyObject*\n"
899  "_ostream_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n"
900  "{\n"
901  " _ostream *self;\n"
902  " self = (_ostream*)type->tp_alloc(type, 0);\n"
903  " if (self != NULL) {\n"
904  " self->fname = 0;\n"
905  " self->fstr = 0;\n"
906  " self->ostr = 0;\n"
907  " }\n"
908  " return (PyObject*)self;\n"
909  "}\n"
910  "\n"
911  "static int\n"
912  "_ostream_init(_ostream *self, PyObject *args, PyObject *kwds)\n"
913  "{\n"
914  " const char *kwlist[] = {\"file\", NULL};\n"
915  " char *filename;\n"
916  " if (PyArg_ParseTupleAndKeywords(args, kwds, \"s\", (char**)kwlist, &filename))\n"
917  " {\n"
918  " if (self->fname != 0)\n"
919  " delete self->fname;\n"
920  " if (self->ostr != 0)\n"
921  " delete self->ostr;\n"
922  " if (self->fstr != 0)\n"
923  " delete self->fstr;\n"
924  " self->fname = new std::string(filename);\n"
925  " self->fstr = new std::ofstream(filename);\n"
926  " if (! self->fstr->good()) {\n"
927  " PyErr_Format(PyExc_IOError, \"Cannot open output file \\%s\", filename);\n"
928  " return -1;\n"
929  " }\n"
930  " try {\n"
931  " self->ostr = new ostream(*self->fstr);\n"
932  " }\n"
933  " catch (std::exception& e) {\n"
934  " PyErr_SetString(PyExc_RuntimeError, e.what());\n"
935  " return -1;\n"
936  " }\n"
937  " return 0;\n"
938  " }\n"
939  " return -1; \n"
940  "}\n"
941  "\n"
942  "static PyObject*\n"
943  "_ostream_getCompression(_ostream *self, void *closure)\n"
944  "{\n"
945  " return Py_BuildValue(\"i\", self->ostr->getCompression());\n"
946  "}\n"
947  "\n"
948  "static int\n"
949  "_ostream_setCompression(_ostream *self, PyObject *value, void *closure)\n"
950  "{\n"
951  " if (value == NULL) {\n"
952  " PyErr_SetString(PyExc_TypeError, \"unexpected null argument\");\n"
953  " return -1;\n"
954  " }\n"
955  " long flags = PyInt_AsLong(value);\n"
956  " if (flags == -1 && PyErr_Occurred()) {\n"
957  " return -1;\n"
958  " }\n"
959  " try {\n"
960  " self->ostr->setCompression(flags);\n"
961  " }\n"
962  " catch (std::exception& e) {\n"
963  " PyErr_SetString(PyExc_RuntimeError, e.what());\n"
964  " return -1;\n"
965  " }\n"
966  " return 0;\n"
967  "}\n"
968  "\n"
969  "static PyObject*\n"
970  "_ostream_getIntegrityChecks(_ostream *self, void *closure)\n"
971  "{\n"
972  " PyObject *flags = Py_BuildValue(\"i\", self->ostr->getIntegrityChecks());\n"
973  " return flags;\n"
974  "}\n"
975  "\n"
976  "static int\n"
977  "_ostream_setIntegrityChecks(_ostream *self, PyObject *value, void *closure)\n"
978  "{\n"
979  " if (value == NULL) {\n"
980  " PyErr_SetString(PyExc_TypeError, \"unexpected null argument\");\n"
981  " return -1;\n"
982  " }\n"
983  " long flags = PyInt_AsLong(value);\n"
984  " if (flags == -1 && PyErr_Occurred()) {\n"
985  " return -1;\n"
986  " }\n"
987  " try {\n"
988  " self->ostr->setIntegrityChecks(flags);\n"
989  " }\n"
990  " catch (std::exception& e) {\n"
991  " PyErr_SetString(PyExc_RuntimeError, e.what());\n"
992  " return -1;\n"
993  " }\n"
994  " return 0;\n"
995  "}\n"
996  "\n"
997  "static PyObject*\n"
998  "_ostream_getPosition(_ostream *self, void *closure)\n"
999  "{\n"
1000  " streamposition *pos = new streamposition();\n"
1001  " if (self->ostr != 0)\n"
1002  " *pos = self->ostr->getPosition();\n"
1003  " PyObject *pos_obj = _streamposition_new(&_streamposition_type, 0, 0);\n"
1004  " ((_streamposition*)pos_obj)->streampos = pos;\n"
1005  " return pos_obj;\n"
1006  "}\n"
1007  "\n"
1008  "static PyObject*\n"
1009  "_ostream_getRecordsWritten(_ostream *self, void *closure)\n"
1010  "{\n"
1011  " int records = 0;\n"
1012  " if (self->ostr != 0)\n"
1013  " try {\n"
1014  " records = self->ostr->getRecordsWritten();\n"
1015  " }\n"
1016  " catch (std::exception& e) {\n"
1017  " PyErr_SetString(PyExc_RuntimeError, e.what());\n"
1018  " return NULL;\n"
1019  " }\n"
1020  " return PyLong_FromLong(records);\n"
1021  "}\n"
1022  "\n"
1023  "static PyObject*\n"
1024  "_ostream_getBytesWritten(_ostream *self, void *closure)\n"
1025  "{\n"
1026  " int bytes = 0;\n"
1027  " if (self->ostr != 0)\n"
1028  " try {\n"
1029  " bytes = self->ostr->getBytesWritten();\n"
1030  " }\n"
1031  " catch (std::exception& e) {\n"
1032  " PyErr_SetString(PyExc_RuntimeError, e.what());\n"
1033  " return NULL;\n"
1034  " }\n"
1035  " return PyLong_FromLong(bytes);\n"
1036  "}\n"
1037  "\n"
1038  "static PyObject*\n"
1039  "_ostream_write(PyObject *self, PyObject *args)\n"
1040  "{\n"
1041  " _HDDM *record_obj;\n"
1042  " if (! PyArg_ParseTuple(args, \"O!\", &_HDDM_type, (PyObject*)&record_obj))\n"
1043  " return NULL;\n"
1044  " ostream *ostr = ((_ostream*)self)->ostr;\n"
1045  " try {\n"
1046  " Py_BEGIN_ALLOW_THREADS\n"
1047  " *ostr << *record_obj->elem;\n"
1048  " Py_END_ALLOW_THREADS\n"
1049  " }\n"
1050  " catch (std::exception& e) {\n"
1051  " PyErr_SetString(PyExc_RuntimeError, e.what());\n"
1052  " return NULL;\n"
1053  " }\n"
1054  " Py_INCREF(Py_None);\n"
1055  " return Py_None;\n"
1056  "}\n"
1057  "\n"
1058  "static PyObject*\n"
1059  "_ostream_toString(PyObject *self, PyObject *args=0)\n"
1060  "{\n"
1061  " std::stringstream ostr;\n"
1062  " if (((_ostream*)self)->fname != 0)\n"
1063  " ostr << \"hddm_" << classPrefix << ".ostream(\\\"\"\n"
1064  " << *((_ostream*)self)->fname << \"\\\")\";\n"
1065  " else\n"
1066  " ostr << \"hddm_" << classPrefix << ".ostream(NULL)\";\n"
1067  " return PyUnicode_FromString(ostr.str().c_str());\n"
1068  "}\n"
1069  "\n"
1070  "static PyObject*\n"
1071  "_ostream_toRepr(PyObject *self, PyObject *args=0)\n"
1072  "{\n"
1073  " std::stringstream ostr;\n"
1074  " ostr << \"\\\'\";\n"
1075  " if (((_ostream*)self)->fname != 0)\n"
1076  " ostr << \"hddm_" << classPrefix << ".ostream(\\\"\"\n"
1077  " << *((_ostream*)self)->fname << \"\\\")\";\n"
1078  " else\n"
1079  " ostr << \"hddm_" << classPrefix << ".ostream()\";\n"
1080  " ostr << \"\\\'\";\n"
1081  " return PyUnicode_FromString(ostr.str().c_str());\n"
1082  "}\n"
1083  "\n"
1084  "static PyGetSetDef _ostream_getsetters[] = {\n"
1085  " {(char*)\"compression\", \n"
1086  " (getter)_ostream_getCompression, (setter)_ostream_setCompression,\n"
1087  " (char*)\"ostream compression mode (k_no_compression, k_z_compression, ...)\",\n"
1088  " NULL},\n"
1089  " {(char*)\"integrityChecks\", \n"
1090  " (getter)_ostream_getIntegrityChecks, (setter)_ostream_setIntegrityChecks,\n"
1091  " (char*)\"ostream data integrity checking mode (k_no_integrity, ...)\",\n"
1092  " NULL},\n"
1093  " {(char*)\"position\", \n"
1094  " (getter)_ostream_getPosition, 0,\n"
1095  " (char*)\"output stream position\",\n"
1096  " NULL},\n"
1097  " {(char*)\"recordsWritten\", \n"
1098  " (getter)_ostream_getRecordsWritten, 0,\n"
1099  " (char*)\"total records written to ostream\",\n"
1100  " NULL},\n"
1101  " {(char*)\"bytesWritten\", \n"
1102  " (getter)_ostream_getBytesWritten, 0,\n"
1103  " (char*)\"total bytes written to ostream\",\n"
1104  " NULL},\n"
1105  " {NULL} /* Sentinel */\n"
1106  "};\n"
1107  "\n"
1108  "static PyMemberDef _ostream_members[] = {\n"
1109  " {NULL} /* Sentinel */\n"
1110  "};\n"
1111  "\n"
1112  "static PyMethodDef _ostream_methods[] = {\n"
1113  " {\"write\", _ostream_write, METH_VARARGS,\n"
1114  " \"write a HDDM record to the output stream.\"},\n"
1115  " {NULL} /* Sentinel */\n"
1116  "};\n"
1117  "\n"
1118  "static PyTypeObject _ostream_type = {\n"
1119  " PyVarObject_HEAD_INIT(NULL,0)\n"
1120  " \"hddm_" << classPrefix << ".ostream\", /*tp_name*/\n"
1121  " sizeof(_ostream), /*tp_basicsize*/\n"
1122  " 0, /*tp_itemsize*/\n"
1123  " (destructor)_ostream_dealloc, /*tp_dealloc*/\n"
1124  " 0, /*tp_print*/\n"
1125  " 0, /*tp_getattr*/\n"
1126  " 0, /*tp_setattr*/\n"
1127  " 0, /*tp_compare*/\n"
1128  " (reprfunc)_ostream_toRepr, /*tp_repr*/\n"
1129  " 0, /*tp_as_number*/\n"
1130  " 0, /*tp_as_sequence*/\n"
1131  " 0, /*tp_as_mapping*/\n"
1132  " 0, /*tp_hash */\n"
1133  " 0, /*tp_call*/\n"
1134  " (reprfunc)_ostream_toString, /*tp_str*/\n"
1135  " 0, /*tp_getattro*/\n"
1136  " 0, /*tp_setattro*/\n"
1137  " 0, /*tp_as_buffer*/\n"
1138  " Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/\n"
1139  " \"hddm_" << classPrefix << " output stream\", /* tp_doc */\n"
1140  " 0, /* tp_traverse */\n"
1141  " 0, /* tp_clear */\n"
1142  " 0, /* tp_richcompare */\n"
1143  " 0, /* tp_weaklistoffset */\n"
1144  " 0, /* tp_iter */\n"
1145  " 0, /* tp_iternext */\n"
1146  " _ostream_methods, /* tp_methods */\n"
1147  " _ostream_members, /* tp_members */\n"
1148  " _ostream_getsetters, /* tp_getset */\n"
1149  " 0, /* tp_base */\n"
1150  " 0, /* tp_dict */\n"
1151  " 0, /* tp_descr_get */\n"
1152  " 0, /* tp_descr_set */\n"
1153  " 0, /* tp_dictoffset */\n"
1154  " (initproc)_ostream_init, /* tp_init */\n"
1155  " 0, /* tp_alloc */\n"
1156  " _ostream_new, /* tp_new */\n"
1157  "};\n"
1158  "\n"
1159  "\n"
1160  "// wrap class hddm_" << classPrefix << "::istream"
1161  " as hddm_" << classPrefix << ".istream\n"
1162  "\n"
1163  "typedef struct {\n"
1164  " PyObject_HEAD\n"
1165  " std::string *fname;\n"
1166  " std::ifstream *fstr;\n"
1167  " istream *istr;\n"
1168  "} _istream;\n"
1169  "\n"
1170  "static void\n"
1171  "_istream_dealloc(_istream* self)\n"
1172  "{\n"
1173  " if (self->fname != 0)\n"
1174  " delete self->fname;\n"
1175  " if (self->istr != 0)\n"
1176  " delete self->istr;\n"
1177  " if (self->fstr != 0)\n"
1178  " delete self->fstr;\n"
1179  " Py_TYPE(self)->tp_free((PyObject*)self);\n"
1180  "}\n"
1181  "\n"
1182  "static PyObject*\n"
1183  "_istream_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n"
1184  "{\n"
1185  " _istream *self;\n"
1186  " self = (_istream*)type->tp_alloc(type, 0);\n"
1187  " if (self != NULL) {\n"
1188  " self->fname = 0;\n"
1189  " self->fstr = 0;\n"
1190  " self->istr = 0;\n"
1191  " }\n"
1192  " return (PyObject*)self;\n"
1193  "}\n"
1194  "\n"
1195  "static int\n"
1196  "_istream_init(_istream *self, PyObject *args, PyObject *kwds)\n"
1197  "{\n"
1198  " const char *kwlist[] = {\"file\", NULL};\n"
1199  " char *filename;\n"
1200  " if (PyArg_ParseTupleAndKeywords(args, kwds, \"s\", (char**)kwlist, &filename))\n"
1201  " {\n"
1202  " if (self->fname != 0)\n"
1203  " delete self->fname;\n"
1204  " if (self->istr != 0)\n"
1205  " delete self->istr;\n"
1206  " if (self->fstr != 0)\n"
1207  " delete self->fstr;\n"
1208  " self->fname = new std::string(filename);\n"
1209  " self->fstr = new std::ifstream(filename);\n"
1210  " if (! self->fstr->good()) {\n"
1211  " PyErr_Format(PyExc_IOError, \"Cannot open input file \\%s\", filename);\n"
1212  " return -1;\n"
1213  " }\n"
1214  " try {\n"
1215  " self->istr = new istream(*self->fstr);\n"
1216  " }\n"
1217  " catch (std::exception& e) {\n"
1218  " PyErr_SetString(PyExc_RuntimeError, e.what());\n"
1219  " return -1;\n"
1220  " }\n"
1221  " return 0;\n"
1222  " }\n"
1223  " return -1; \n"
1224  "}\n"
1225  "\n"
1226  "static PyObject*\n"
1227  "_istream_getCompression(_istream *self, void *closure)\n"
1228  "{\n"
1229  " return Py_BuildValue(\"i\", self->istr->getCompression());\n"
1230  "}\n"
1231  "\n"
1232  "static PyObject*\n"
1233  "_istream_getIntegrityChecks(_istream *self, void *closure)\n"
1234  "{\n"
1235  " return Py_BuildValue(\"i\", self->istr->getIntegrityChecks());\n"
1236  "}\n"
1237  "\n"
1238  "static PyObject*\n"
1239  "_istream_getPosition(_istream *self, void *closure)\n"
1240  "{\n"
1241  " streamposition *pos = new streamposition();\n"
1242  " if (self->istr != 0)\n"
1243  " try {\n"
1244  " *pos = self->istr->getPosition();\n"
1245  " }\n"
1246  " catch (std::exception& e) {\n"
1247  " PyErr_SetString(PyExc_RuntimeError, e.what());\n"
1248  " return NULL;\n"
1249  " }\n"
1250  " PyObject *pos_obj = _streamposition_new(&_streamposition_type, 0, 0);\n"
1251  " ((_streamposition*)pos_obj)->streampos = pos;\n"
1252  " return pos_obj;\n"
1253  "}\n"
1254  "\n"
1255  "static int\n"
1256  "_istream_setPosition(_istream *self, PyObject *value, void *closure)\n"
1257  "{\n"
1258  " if (Py_TYPE(value) != &_streamposition_type)\n"
1259  " {\n"
1260  " PyErr_SetString(PyExc_TypeError, \"unexpected argument type\");\n"
1261  " return -1;\n"
1262  " }\n"
1263  " streamposition *pos = ((_streamposition*)value)->streampos;\n"
1264  " if (pos == 0) {\n"
1265  " PyErr_SetString(PyExc_TypeError, \"unexpected null argument\");\n"
1266  " return -1;\n"
1267  " }\n"
1268  " try {\n"
1269  " self->istr->setPosition(*pos);\n"
1270  " }\n"
1271  " catch (std::exception& e) {\n"
1272  " PyErr_SetString(PyExc_RuntimeError, e.what());\n"
1273  " return -1;\n"
1274  " }\n"
1275  " return 0;\n"
1276  "}\n"
1277  "\n"
1278  "static PyObject*\n"
1279  "_istream_getRecordsRead(_istream *self, void *closure)\n"
1280  "{\n"
1281  " int records = 0;\n"
1282  " if (self->istr != 0)\n"
1283  " try {\n"
1284  " records = self->istr->getRecordsRead();\n"
1285  " }\n"
1286  " catch (std::exception& e) {\n"
1287  " PyErr_SetString(PyExc_RuntimeError, e.what());\n"
1288  " return NULL;\n"
1289  " }\n"
1290  " return PyLong_FromLong(records);\n"
1291  "}\n"
1292  "\n"
1293  "static PyObject*\n"
1294  "_istream_getBytesRead(_istream *self, void *closure)\n"
1295  "{\n"
1296  " int bytes = 0;\n"
1297  " if (self->istr != 0)\n"
1298  " try {\n"
1299  " bytes = self->istr->getBytesRead();\n"
1300  " }\n"
1301  " catch (std::exception& e) {\n"
1302  " PyErr_SetString(PyExc_RuntimeError, e.what());\n"
1303  " return NULL;\n"
1304  " }\n"
1305  " return PyLong_FromLong(bytes);\n"
1306  "}\n"
1307  "\n"
1308  "static PyObject*\n"
1309  "_istream_skip(PyObject *self, PyObject *args)\n"
1310  "{\n"
1311  " int count=0;\n"
1312  " if (! PyArg_ParseTuple(args, \"I\", &count)) {\n"
1313  " PyErr_SetString(PyExc_TypeError, \"missing argument in skip\");\n"
1314  " return NULL;\n"
1315  " }\n"
1316  " else if (count < 0) {\n"
1317  " PyErr_SetString(PyExc_TypeError, \"skip count cannot be negative\");\n"
1318  " return NULL;\n"
1319  " }\n"
1320  " istream *istr = ((_istream*)self)->istr;\n"
1321  " if (istr == 0) {\n"
1322  " PyErr_SetString(PyExc_TypeError, \"unexpected null istream ptr\");\n"
1323  " return NULL;\n"
1324  " }\n"
1325  " istr->skip(count);\n"
1326  " return PyLong_FromLong(0);\n"
1327  "}\n"
1328  "\n"
1329  "static PyObject*\n"
1330  "_istream_read(PyObject *self, PyObject *args)\n"
1331  "{\n"
1332  " istream *istr = ((_istream*)self)->istr;\n"
1333  " if (istr == 0) {\n"
1334  " PyErr_SetString(PyExc_TypeError, \"unexpected null input stream\");\n"
1335  " return NULL;\n"
1336  " }\n"
1337  " _HDDM *record_obj = (_HDDM*)_HDDM_new(&_HDDM_type, 0, 0);\n"
1338  " record_obj->elem = new HDDM();\n"
1339  " record_obj->host = (PyObject*)record_obj;\n"
1340  " try {\n"
1341  " Py_BEGIN_ALLOW_THREADS\n"
1342  " *istr >> *record_obj->elem;\n"
1343  " Py_END_ALLOW_THREADS\n"
1344  " }\n"
1345  " catch (std::exception& e) {\n"
1346  " PyErr_SetString(PyExc_RuntimeError, e.what());\n"
1347  " return NULL;\n"
1348  " }\n"
1349  " if (*istr) {\n"
1350  " LOG_NEW(Py_TYPE(record_obj), 0, 1);\n"
1351  " return (PyObject*)record_obj;\n"
1352  " }\n"
1353  " return NULL;\n"
1354  "}\n"
1355  "\n"
1356  "static PyObject*\n"
1357  "_istream_toString(PyObject *self, PyObject *args=0)\n"
1358  "{\n"
1359  " std::stringstream ostr;\n"
1360  " if (((_ostream*)self)->fname != 0)\n"
1361  " ostr << \"hddm_" << classPrefix << ".istream(\\\"\"\n"
1362  " << *((_istream*)self)->fname << \"\\\")\";\n"
1363  " else\n"
1364  " ostr << \"hddm_" << classPrefix << ".istream(NULL)\";\n"
1365  " return PyUnicode_FromString(ostr.str().c_str());\n"
1366  "}\n"
1367  "\n"
1368  "static PyObject*\n"
1369  "_istream_toRepr(PyObject *self, PyObject *args=0)\n"
1370  "{\n"
1371  " std::stringstream ostr;\n"
1372  " ostr << \"\\\'\";\n"
1373  " if (((_ostream*)self)->fname != 0)\n"
1374  " ostr << \"hddm_" << classPrefix << ".istream(\\\"\"\n"
1375  " << *((_istream*)self)->fname << \"\\\")\";\n"
1376  " else\n"
1377  " ostr << \"hddm_" << classPrefix << ".istream()\";\n"
1378  " ostr << \"\\\'\";\n"
1379  " return PyUnicode_FromString(ostr.str().c_str());\n"
1380  "}\n"
1381  "\n"
1382  "static PyObject*\n"
1383  "_istream_iter(PyObject *self)\n"
1384  "{\n"
1385  " Py_INCREF(self);\n"
1386  " return self;\n"
1387  "}\n"
1388  "static PyObject*\n"
1389  "_istream_next(PyObject *self)\n"
1390  "{\n"
1391  " PyObject *rec = _istream_read(self, 0);\n"
1392  " if (rec == NULL)\n"
1393  " PyErr_SetString(PyExc_StopIteration, \"no more data on input stream\");\n"
1394  " return rec;\n"
1395  "}\n"
1396  "\n"
1397  "static PyGetSetDef _istream_getsetters[] = {\n"
1398  " {(char*)\"compression\", \n"
1399  " (getter)_istream_getCompression, 0,\n"
1400  " (char*)\"istream compression mode (k_no_compression, k_z_compression, ...)\",\n"
1401  " NULL},\n"
1402  " {(char*)\"integrityChecks\", \n"
1403  " (getter)_istream_getIntegrityChecks, 0,\n"
1404  " (char*)\"istream data integrity checking mode (k_no_integrity, ...)\",\n"
1405  " NULL},\n"
1406  " {(char*)\"position\", \n"
1407  " (getter)_istream_getPosition, (setter)_istream_setPosition,\n"
1408  " (char*)\"input stream position\",\n"
1409  " NULL},\n"
1410  " {(char*)\"recordsRead\", \n"
1411  " (getter)_istream_getRecordsRead, 0,\n"
1412  " (char*)\"total records read from istream\",\n"
1413  " NULL},\n"
1414  " {(char*)\"bytesRead\", \n"
1415  " (getter)_istream_getBytesRead, 0,\n"
1416  " (char*)\"total bytes read from istream\",\n"
1417  " NULL},\n"
1418  " {NULL} /* Sentinel */\n"
1419  "};\n"
1420  "\n"
1421  "static PyMemberDef _istream_members[] = {\n"
1422  " {NULL} /* Sentinel */\n"
1423  "};\n"
1424  "\n"
1425  "static PyMethodDef _istream_methods[] = {\n"
1426  " {\"read\", _istream_read, METH_NOARGS,\n"
1427  " \"read a HDDM record from the input stream.\"},\n"
1428  " {\"skip\", _istream_skip, METH_VARARGS,\n"
1429  " \"skip ahead given number of HDDM records in the input stream.\"},\n"
1430  " {NULL} /* Sentinel */\n"
1431  "};\n"
1432  "\n"
1433  "static PyTypeObject _istream_type = {\n"
1434  " PyVarObject_HEAD_INIT(NULL,0)\n"
1435  " \"hddm_" << classPrefix << ".istream\", /*tp_name*/\n"
1436  " sizeof(_istream), /*tp_basicsize*/\n"
1437  " 0, /*tp_itemsize*/\n"
1438  " (destructor)_istream_dealloc, /*tp_dealloc*/\n"
1439  " 0, /*tp_print*/\n"
1440  " 0, /*tp_getattr*/\n"
1441  " 0, /*tp_setattr*/\n"
1442  " 0, /*tp_compare*/\n"
1443  " (reprfunc)_istream_toRepr, /*tp_repr*/\n"
1444  " 0, /*tp_as_number*/\n"
1445  " 0, /*tp_as_sequence*/\n"
1446  " 0, /*tp_as_mapping*/\n"
1447  " 0, /*tp_hash */\n"
1448  " 0, /*tp_call*/\n"
1449  " (reprfunc)_istream_toString, /*tp_str*/\n"
1450  " 0, /*tp_getattro*/\n"
1451  " 0, /*tp_setattro*/\n"
1452  " 0, /*tp_as_buffer*/\n"
1453  " Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/\n"
1454  " \"hddm_" << classPrefix << " output stream\", /* tp_doc */\n"
1455  " 0, /* tp_traverse */\n"
1456  " 0, /* tp_clear */\n"
1457  " 0, /* tp_richcompare */\n"
1458  " 0, /* tp_weaklistoffset */\n"
1459  " _istream_iter, /* tp_iter */\n"
1460  " _istream_next, /* tp_iternext */\n"
1461  " _istream_methods, /* tp_methods */\n"
1462  " _istream_members, /* tp_members */\n"
1463  " _istream_getsetters, /* tp_getset */\n"
1464  " 0, /* tp_base */\n"
1465  " 0, /* tp_dict */\n"
1466  " 0, /* tp_descr_get */\n"
1467  " 0, /* tp_descr_set */\n"
1468  " 0, /* tp_dictoffset */\n"
1469  " (initproc)_istream_init, /* tp_init */\n"
1470  " 0, /* tp_alloc */\n"
1471  " _istream_new, /* tp_new */\n"
1472  "};\n"
1473  ;
1474 
1475  builder.pyFile <<
1476  "\n"
1477  "\n"
1478  "// module declarations\n"
1479  "\n"
1480  "static PyMethodDef hddm_" << classPrefix << "_methods[] = {\n"
1481  " {NULL} /* Sentinel */\n"
1482  "};\n"
1483  "\n"
1484  "char hddm_" << classPrefix << "_doc[] = \"Python module for "
1485  "hddm_" << classPrefix << " i/o package\";\n"
1486  "\n"
1487  "#if PY_MAJOR_VERSION >= 3\n"
1488  " static struct PyModuleDef moduledef = {\n"
1489  " PyModuleDef_HEAD_INIT,\n"
1490  " \"hddm_" << classPrefix << "\", /* m_name */\n"
1491  " hddm_" << classPrefix << "_doc, /* m_doc */\n"
1492  " -1, /* m_size */\n"
1493  " hddm_" << classPrefix << "_methods, /* m_methods */\n"
1494  " NULL, /* m_reload */\n"
1495  " NULL, /* m_traverse */\n"
1496  " NULL, /* m_clear */\n"
1497  " NULL, /* m_free */\n"
1498  " };\n"
1499  "#endif\n"
1500  "\n"
1501  "static PyObject *\n"
1502  "hddm_" << classPrefix << "_init(void) \n"
1503  "{\n"
1504  " PyObject* m;\n"
1505  "\n"
1506  "#if PY_MAJOR_VERSION >= 3\n"
1507  " m = PyModule_Create(&moduledef);\n"
1508  "#else\n"
1509  " m = Py_InitModule3(\"hddm_" << classPrefix << "\","
1510  " hddm_" << classPrefix << "_methods,"
1511  " hddm_" << classPrefix << "_doc);\n"
1512  "#endif\n"
1513  "\n"
1514  " if (m == NULL)\n"
1515  " return NULL;\n"
1516  "\n"
1517  ;
1518 
1519  std::map<XtString,XtString>::iterator titer;
1520  for (titer = builder.typesList.begin();
1521  titer != builder.typesList.end(); ++titer)
1522  {
1523  builder.pyFile <<
1524  " if (PyType_Ready(&" << titer->second << ") < 0)\n"
1525  " return NULL;\n"
1526  " Py_INCREF(&" << titer->second << ");\n"
1527  " PyModule_AddObject(m, \"" << titer->first << "\","
1528  " (PyObject*)&" << titer->second << ");\n"
1529  ;
1530  }
1531 
1532  builder.pyFile <<
1533  "\n"
1534  " PyModule_AddIntConstant(m, \"k_default_status\", k_default_status);\n"
1535  " PyModule_AddIntConstant(m, \"k_bits_compression\", k_bits_compression);\n"
1536  " PyModule_AddIntConstant(m, \"k_no_compression\", k_no_compression);\n"
1537  " PyModule_AddIntConstant(m, \"k_z_compression\", k_z_compression);\n"
1538  " PyModule_AddIntConstant(m, \"k_bz2_compression\", k_bz2_compression);\n"
1539  " PyModule_AddIntConstant(m, \"k_bits_integrity\", k_bits_integrity);\n"
1540  " PyModule_AddIntConstant(m, \"k_no_integrity\", k_no_integrity);\n"
1541  " PyModule_AddIntConstant(m, \"k_crc32_integrity\", k_crc32_integrity);\n"
1542  " PyModule_AddIntConstant(m, \"k_bits_randomaccess\", k_bits_randomaccess);\n"
1543  " PyModule_AddIntConstant(m, \"k_can_reposition\", k_can_reposition);\n"
1544  " PyModule_AddIntConstant(m, \"k_hddm_unknown\", k_hddm_unknown);\n"
1545  " PyModule_AddIntConstant(m, \"k_hddm_int\", k_hddm_int);\n"
1546  " PyModule_AddIntConstant(m, \"k_hddm_long\", k_hddm_long);\n"
1547  " PyModule_AddIntConstant(m, \"k_hddm_float\", k_hddm_float);\n"
1548  " PyModule_AddIntConstant(m, \"k_hddm_double\", k_hddm_double);\n"
1549  " PyModule_AddIntConstant(m, \"k_hddm_boolean\", k_hddm_boolean);\n"
1550  " PyModule_AddIntConstant(m, \"k_hddm_string\", k_hddm_string);\n"
1551  " PyModule_AddIntConstant(m, \"k_hddm_anyURI\", k_hddm_anyURI);\n"
1552  " PyModule_AddIntConstant(m, \"k_hddm_Particle_t\", k_hddm_Particle_t);\n"
1553  " std::string docstring = HDDM::DocumentString();\n"
1554  " PyModule_AddStringConstant(m, \"DocumentString\", docstring.c_str());\n"
1555  "\n"
1556  " return m;\n"
1557  "}\n"
1558  "\n"
1559  "#if PY_MAJOR_VERSION < 3\n"
1560  " PyMODINIT_FUNC\n"
1561  " inithddm_" << classPrefix << "(void)\n"
1562  " {\n"
1563  " hddm_" << classPrefix << "_init();\n"
1564  " }\n"
1565  "#else\n"
1566  " PyMODINIT_FUNC\n"
1567  " PyInit_hddm_" << classPrefix << "(void)\n"
1568  " {\n"
1569  " return hddm_" << classPrefix << "_init();\n"
1570  " }\n"
1571  "#endif\n"
1572  ;
1573 
1574 /* convert cpy filename "<dirpath>/hddm_X.cpy"
1575  * to setup filename "<dirpath>/setup_hddm_X.py"
1576  */
1577  size_t p1 = pyname.rfind("pyhddm_");
1578  pyname.erase(p1, 2);
1579  pyname.insert(p1, "setup_");
1580  size_t p2 = pyname.rfind("cpy");
1581  pyname.erase(p2, 1);
1582 
1583  std::ofstream pysetup(pyname.c_str());
1584  pysetup <<
1585  "import os\n"
1586  "from distutils.core import setup, Extension\n"
1587  "from shutil import copyfile, rmtree\n"
1588  "import re\n"
1589  "\n"
1590  "source_dir = os.path.realpath(__file__)\n"
1591  "m = re.sub(r'/[^/]*$', '', source_dir)\n"
1592  "if m:\n"
1593  " source_dir = m\n"
1594  "else:\n"
1595  " source_dir = '.'\n"
1596  "source_file = 'pyhddm_" + classPrefix + ".cxx'\n"
1597  "source_files = [source_file, source_dir + '/hddm_" + classPrefix + "++.cpp']\n"
1598  "copyfile(source_dir + '/pyhddm_" + classPrefix + ".cpy', source_file)\n"
1599  "\n"
1600  "module1 = Extension('hddm_" + classPrefix + "',\n"
1601  " include_dirs = [os.environ['HALLD_RECON_HOME'] + '/' +\n"
1602  " os.environ['BMS_OSNAME'] + '/include',\n"
1603  " os.environ['HALLD_RECON_HOME'] + \n"
1604  " '/src/libraries/include',\n"
1605  " source_dir],\n"
1606  " libraries = ['HDDM', 'xstream', 'bz2', 'z'],\n"
1607  " library_dirs = [os.environ['HALLD_RECON_HOME'] + '/' +\n"
1608  " os.environ['BMS_OSNAME'] + '/lib'],\n"
1609  " extra_compile_args = ['-std=c++11'],\n"
1610  " sources = source_files)\n"
1611  "\n"
1612  "setup (name = 'hddm_" << classPrefix << "',\n"
1613  " version = '1.0',\n"
1614  " description = 'HDDM data model i/o package',\n"
1615  " ext_modules = [module1])\n"
1616  "\n"
1617  "os.remove(source_file)\n"
1618  "for dname in os.listdir('build_hddm_" << classPrefix << "'):\n"
1619  " for soname in os.listdir('build_hddm_" << classPrefix << "/' + dname):\n"
1620  " if re.match(r'.*\\.so', soname):\n"
1621  " src = 'build_hddm_" << classPrefix << "/' + dname + '/' + soname\n"
1622  " dest = source_dir + '/' + soname\n"
1623  " copyfile(src, dest)\n"
1624  "rmtree('build_hddm_" + classPrefix << "')\n"
1625  ;
1626 
1627  XMLPlatformUtils::Terminate();
1628  return 0;
1629 }
1630 
1632 {
1633  XtString p(*this);
1634  XtString::size_type len = p.size();
1635  if (len > 3 && p.substr(len-3,3) == "tum")
1636  {
1637  p.replace(len-3,3,"ta");
1638  }
1639  else if (len > 1 && p.substr(len-3,3) == "ies")
1640  {
1641  p.replace(len-3,3,"iesList");
1642  }
1643  else if (len > 2 && p.substr(len-2,2) == "ex")
1644  {
1645  p.replace(len-2,2,"ices");
1646  }
1647  else if (len > 2 && p.substr(len-2,2) == "sh")
1648  {
1649  p.replace(len-2,2,"shes");
1650  }
1651  else if (len > 1 && p.substr(len-1,1) == "s")
1652  {
1653  p.replace(len-1,1,"ses");
1654  }
1655  else if (len > 1)
1656  {
1657  p += "s";
1658  }
1659  return p;
1660 }
1661 
1662 /* Map from tag name to name of the corresponding class
1663  * for the case of simple tags (those that do not repeat)
1664  */
1666 {
1667  XtString p(*this);
1668  p[0] = toupper(p[0]);
1669  return p;
1670 }
1671 
1672 /* Map from tag name to name of the corresponding class
1673  * for the case of list tags (those that may repeat)
1674  */
1676 {
1677  XtString r(*this);
1678  r[0] = toupper(r[0]);
1679  r = r + "List";
1680  return r;
1681 }
1682 
1683 /* Map from tag name to name of the corresponding class
1684  * for the case of link tags (those that do not repeat)
1685  */
1687 {
1688  XtString r(*this);
1689  r[0] = toupper(r[0]);
1690  r = r + "Link";
1691  return r;
1692 }
1693 
1694 /* Look for a named element in a list of element pointers
1695  * and return index of first instance in the list if found,
1696  * otherwise return -1;
1697  */
1698 int CodeBuilder::element_in_list(XtString &name, parentList_t list)
1699 {
1700  int n=0;
1701  parentList_t::iterator iter;
1702  for (iter = list.begin(); iter != list.end(); ++iter, ++n)
1703  {
1704  DOMElement *el = (DOMElement*)(*iter);
1705  XtString cnameS(el->getTagName());
1706  if (cnameS == name) {
1707  return n;
1708  }
1709  }
1710  return -1;
1711 }
1712 
1713 /* Verify that the tag group under this element does not collide
1714  * with existing tag group elref, otherwise exit with fatal error
1715  */
1716 void CodeBuilder::checkConsistency(DOMElement* el, DOMElement* elref)
1717 {
1718  XtString tagS(el->getTagName());
1719  if (el->getParentNode() == elref->getParentNode())
1720  {
1721  std::cerr
1722  << "hddm-py error: tag " << "\"" << tagS
1723  << "\" is duplicated within one context in xml document."
1724  << std::endl;
1725  exit(1);
1726  }
1727 
1728  DOMNamedNodeMap* oldAttr = elref->getAttributes();
1729  DOMNamedNodeMap* newAttr = el->getAttributes();
1730  unsigned int listLength = oldAttr->getLength();
1731  for (unsigned int n = 0; n < listLength; n++)
1732  {
1733  XtString nameS(oldAttr->item(n)->getNodeName());
1734  XtString oldS(elref->getAttribute(X(nameS)));
1735  XtString newS(el->getAttribute(X(nameS)));
1736  if (nameS == "minOccurs")
1737  {
1738  continue;
1739  }
1740  else if (nameS == "maxOccurs")
1741  {
1742  int maxold = (oldS == "unbounded")? INT_MAX : atoi(S(oldS));
1743  int maxnew = (newS == "unbounded")? INT_MAX : atoi(S(newS));
1744  if ((maxold < 2 && maxnew > 1) || (maxold > 1 && maxnew < 2))
1745  {
1746  std::cerr
1747  << "hddm-py error: inconsistent maxOccurs usage by tag "
1748  << "\"" << tagS << "\" in xml document." << std::endl;
1749  exit(1);
1750  }
1751  }
1752  else if (newS != oldS)
1753  {
1754  std::cerr
1755  << "hddm-py error: inconsistent usage of attribute "
1756  << "\"" << nameS << "\" in tag "
1757  << "\"" << tagS << "\" in xml document." << std::endl;
1758  exit(1);
1759  }
1760  }
1761  listLength = newAttr->getLength();
1762  for (unsigned int n = 0; n < listLength; n++)
1763  {
1764  XtString nameS(newAttr->item(n)->getNodeName());
1765  XtString oldS(elref->getAttribute(X(nameS)));
1766  XtString newS(el->getAttribute(X(nameS)));
1767  if (nameS == "minOccurs")
1768  {
1769  continue;
1770  }
1771  else if (nameS == "maxOccurs")
1772  {
1773  int maxold = (oldS == "unbounded")? INT_MAX : atoi(S(oldS));
1774  int maxnew = (newS == "unbounded")? INT_MAX : atoi(S(newS));
1775  if ((maxold < 2 && maxnew > 1) || (maxold > 1 && maxnew < 2))
1776  {
1777  std::cerr
1778  << "hddm-py error: inconsistent maxOccurs usage by tag "
1779  << "\"" << tagS << "\" in xml document." << std::endl;
1780  exit(1);
1781  }
1782  }
1783  else if (newS != oldS)
1784  {
1785  std::cerr
1786  << "hddm-py error: inconsistent usage of attribute "
1787  << "\"" << nameS << "\" in tag "
1788  << "\"" << tagS << "\" in xml document." << std::endl;
1789  exit(1);
1790  }
1791  }
1792  DOMNodeList* oldList = elref->getChildNodes();
1793  DOMNodeList* newList = el->getChildNodes();
1794  listLength = oldList->getLength();
1795  if (newList->getLength() != listLength)
1796  {
1797  std::cerr
1798  << "hddm-py error: inconsistent usage of tag "
1799  << "\"" << tagS << "\" in xml document." << std::endl;
1800  exit(1);
1801  }
1802  for (unsigned int n = 0; n < listLength; n++)
1803  {
1804  DOMNode* cont = oldList->item(n);
1805  XtString nameS(cont->getNodeName());
1806  short type = cont->getNodeType();
1807  if (type == DOMNode::ELEMENT_NODE)
1808  {
1809  DOMNodeList* contList = el->getElementsByTagName(X(nameS));
1810  if (contList->getLength() != 1)
1811  {
1812  std::cerr
1813  << "hddm-py error: inconsistent usage of tag "
1814  << "\"" << tagS << "\" in xml document." << std::endl;
1815  exit(1);
1816  }
1817  }
1818  }
1819 }
1820 
1821 /* Write declaration of the classes for this tag */
1822 
1823 void CodeBuilder::writeClassdef(DOMElement* el)
1824 {
1825  XtString tagS(el->getTagName());
1826  pyFile <<
1827  "\n\n"
1828  "// wrap element class hddm_" << classPrefix << "::" << tagS.simpleType() <<
1829  " as hddm_" << classPrefix << "." << tagS.simpleType() << "\n"
1830  "\n"
1831  "typedef struct {\n"
1832  " PyObject_HEAD\n"
1833  " " << tagS.simpleType() << " *elem;\n"
1834  " PyObject *host;\n"
1835  "} _" << tagS.simpleType() << ";\n"
1836  "\n"
1837  "static void\n"
1838  "_" << tagS.simpleType() << "_dealloc(_" << tagS.simpleType() << "* self)\n"
1839  "{\n"
1840  " if (self->elem != 0) {\n"
1841  " LOG_DEALLOC(Py_TYPE(self), 0, self->host == (PyObject*)self);\n"
1842  " if (self->host == (PyObject*)self)\n"
1843  " delete self->elem;\n"
1844  " else\n"
1845  " My_DECREF(self->host);\n"
1846  " }\n"
1847  " Py_TYPE(self)->tp_free((PyObject*)self);\n"
1848  "}\n"
1849  "\n"
1850  "static PyObject*\n"
1851  "_" << tagS.simpleType() <<
1852  "_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n"
1853  "{\n"
1854  " _" << tagS.simpleType() << " *self;\n"
1855  " self = (_" << tagS.simpleType() << "*)type->tp_alloc(type, 0);\n"
1856  " if (self != NULL) {\n"
1857  " self->elem = 0;\n"
1858  " self->host = 0;\n"
1859  " }\n"
1860  " return (PyObject*)self;\n"
1861  "}\n"
1862  "\n"
1863  ;
1864 
1865  if (tagS == "HDDM")
1866  {
1867  pyFile <<
1868  "static int\n"
1869  "_HDDM_init(_HDDM *self, PyObject *args, PyObject *kwds)\n"
1870  "{\n"
1871  " LOG_NEW(Py_TYPE(self), 0, 1);\n"
1872  " self->elem = new HDDM();\n"
1873  " if (self->elem == 0) {\n"
1874  " PyErr_SetString(PyExc_RuntimeError, \"HDDM new constructor failed\");\n"
1875  " return -1;\n"
1876  " }\n"
1877  " self->host = (PyObject*)self;\n"
1878  " return 0;\n"
1879  "}\n"
1880  "\n"
1881  ;
1882  }
1883  else
1884  {
1885  pyFile <<
1886  "static int\n"
1887  "_" << tagS.simpleType() << "_init(_" << tagS.simpleType() <<
1888  " *self, PyObject *args, PyObject *kwds)\n"
1889  "{\n"
1890  " PyErr_SetString(PyExc_RuntimeError, \"illegal constructor\");\n"
1891  " return -1;\n"
1892  "}\n"
1893  "\n"
1894  ;
1895  }
1896 
1897  std::map<XtString,XtString> attrList;
1898  DOMNamedNodeMap *myAttr = el->getAttributes();
1899  for (unsigned int n = 0; n < myAttr->getLength(); n++)
1900  {
1901  XtString attrS(myAttr->item(n)->getNodeName());
1902  XtString typeS(el->getAttribute(X(attrS)));
1903  attrList[attrS] = typeS;
1904  }
1905  parentList_t::iterator iter;
1906  for (iter = parents[tagS].begin(); iter != parents[tagS].end(); ++iter)
1907  {
1908  DOMElement *hostEl = (DOMElement*)(*iter);
1909  XtString hostS(hostEl->getTagName());
1910  DOMNamedNodeMap *hostAttr = hostEl->getAttributes();
1911  for (unsigned int n = 0; n < hostAttr->getLength(); n++)
1912  {
1913  XtString attrS(hostAttr->item(n)->getNodeName());
1914  if (attrList.find(attrS) != attrList.end())
1915  {
1916  continue;
1917  }
1918  XtString typeS(hostEl->getAttribute(X(attrS)));
1919  attrList[attrS] = typeS;
1920  XtString getS("get" + attrS.simpleType());
1921  pyFile << "static PyObject*\n" <<
1922  "_" << tagS.simpleType() << "_" << getS <<
1923  "(_" << tagS.simpleType() << " *self, void *closure)\n"
1924  "{\n";
1925  if (typeS == "int")
1926  {
1927  pyFile << " return PyLong_FromLong(self->elem->"
1928  << getS << "());\n";
1929  }
1930  else if (typeS == "long")
1931  {
1932  pyFile << " return PyLong_FromLong(self->elem->"
1933  << getS << "());\n";
1934  }
1935  else if (typeS == "float")
1936  {
1937  pyFile << " return PyFloat_FromDouble(self->elem->"
1938  << getS << "());\n";
1939  }
1940  else if (typeS == "double")
1941  {
1942  pyFile << " return PyFloat_FromDouble(self->elem->"
1943  << getS << "());\n";
1944  }
1945  else if (typeS == "boolean")
1946  {
1947  pyFile << " return PyBool_FromLong(self->elem->"
1948  << getS << "());\n";
1949  }
1950  else if (typeS == "string")
1951  {
1952  pyFile << " std::string val(self->elem->"
1953  << getS << "());\n"
1954  << " return PyUnicode_FromString(val.c_str());\n";
1955  attrList[attrS] = "string";
1956  }
1957  else if (typeS == "anyURI")
1958  {
1959  pyFile << " std::string val(self->elem->"
1960  << getS << "());\n"
1961  << " return PyUnicode_FromString(val.c_str());\n";
1962  attrList[attrS] = "string";
1963  }
1964  else if (typeS == "Particle_t")
1965  {
1966  pyFile << " Particle_t p(self->elem->"
1967  << getS << "());\n"
1968  << " std::string val(ParticleType(p));\n"
1969  << " return PyUnicode_FromString(val.c_str());\n";
1970  }
1971  else if (guessType(typeS) == "int")
1972  {
1973  pyFile << " return PyLong_FromLong(self->elem->"
1974  << getS << "());\n";
1975  }
1976  else if (guessType(typeS) == "long")
1977  {
1978  pyFile << " return PyLong_FromLong(self->elem->"
1979  << getS << "());\n";
1980  }
1981  else if (guessType(typeS) == "float")
1982  {
1983  pyFile << " return PyFloat_FromDouble(self->elem->"
1984  << getS << "());\n";
1985  }
1986  else if (guessType(typeS) == "double")
1987  {
1988  pyFile << " return PyFloat_FromDouble(self->elem->"
1989  << getS << "());\n";
1990  }
1991  else if (guessType(typeS) == "boolean")
1992  {
1993  pyFile << " return PyBool_FromLong(self->elem->"
1994  << getS << "());\n";
1995  }
1996  else if (guessType(typeS) == "Particle_t")
1997  {
1998  pyFile << " Particle_t p(self->elem->"
1999  << getS << "());\n"
2000  << " std::string val(ParticleType(p));\n"
2001  << " return PyUnicode_FromString(val.c_str());\n";
2002  }
2003  else /* any values not matching the above are strings */
2004  {
2005  pyFile << " std::string val(self->elem->"
2006  << getS << "());\n"
2007  << " return PyUnicode_FromString(val.c_str());\n";
2008  attrList[attrS] = "string";
2009  }
2010  pyFile << "}\n\n";
2011  }
2012  }
2013 
2014  std::map<XtString,int> setters;
2015  myAttr = el->getAttributes();
2016  for (unsigned int n = 0; n < myAttr->getLength(); n++)
2017  {
2018  XtString attrS(myAttr->item(n)->getNodeName());
2019  XtString typeS(el->getAttribute(X(attrS)));
2020  XtString getS("get" + attrS.simpleType());
2021  pyFile << "static PyObject*\n" <<
2022  "_" << tagS.simpleType() << "_" << getS <<
2023  "(_" << tagS.simpleType() << " *self, void *closure)\n"
2024  "{\n";
2025  if (typeS == "int")
2026  {
2027  pyFile << " return PyLong_FromLong(self->elem->"
2028  << getS << "());\n";
2029  }
2030  else if (typeS == "long")
2031  {
2032  pyFile << " return PyLong_FromLong(self->elem->"
2033  << getS << "());\n";
2034  }
2035  else if (typeS == "float")
2036  {
2037  pyFile << " return PyFloat_FromDouble(self->elem->"
2038  << getS << "());\n";
2039  }
2040  else if (typeS == "double")
2041  {
2042  pyFile << " return PyFloat_FromDouble(self->elem->"
2043  << getS << "());\n";
2044  }
2045  else if (typeS == "boolean")
2046  {
2047  pyFile << " return PyBool_FromLong(self->elem->"
2048  << getS << "());\n";
2049  }
2050  else if (typeS == "string")
2051  {
2052  pyFile << " std::string val(self->elem->"
2053  << getS << "());\n"
2054  << " return PyUnicode_FromString(val.c_str());\n";
2055  }
2056  else if (typeS == "anyURI")
2057  {
2058  pyFile << " std::string val(self->elem->"
2059  << getS << "());\n"
2060  << " return PyUnicode_FromString(val.c_str());\n";
2061  }
2062  else if (typeS == "Particle_t")
2063  {
2064  pyFile << " Particle_t p(self->elem->"
2065  << getS << "());\n"
2066  << " std::string val(ParticleType(p));\n"
2067  << " return PyUnicode_FromString(val.c_str());\n";
2068  }
2069  else if (guessType(typeS) == "int")
2070  {
2071  pyFile << " return PyLong_FromLong(self->elem->"
2072  << getS << "());\n";
2073  }
2074  else if (guessType(typeS) == "long")
2075  {
2076  pyFile << " return PyLong_FromLong(self->elem->"
2077  << getS << "());\n";
2078  }
2079  else if (guessType(typeS) == "float")
2080  {
2081  pyFile << " return PyFloat_FromDouble(self->elem->"
2082  << getS << "());\n";
2083  }
2084  else if (guessType(typeS) == "double")
2085  {
2086  pyFile << " return PyFloat_FromDouble(self->elem->"
2087  << getS << "());\n";
2088  }
2089  else if (guessType(typeS) == "boolean")
2090  {
2091  pyFile << " return PyBool_FromLong(self->elem->"
2092  << getS << "());\n";
2093  }
2094  else if (guessType(typeS) == "Particle_t")
2095  {
2096  pyFile << " Particle_t p(self->elem->"
2097  << getS << "());\n"
2098  << " std::string val(ParticleType(p));\n"
2099  << " return PyUnicode_FromString(val.c_str());\n";
2100  }
2101  else /* any values not matching the above are strings */
2102  {
2103  pyFile << " std::string val(self->elem->"
2104  << getS << "());\n"
2105  << " return PyUnicode_FromString(val.c_str());\n";
2106  }
2107  pyFile << "}\n\n";
2108 
2109  XtString setS("set" + attrS.simpleType());
2110  if (typeS == "int")
2111  {
2112  pyFile << "static int\n" <<
2113  "_" << tagS.simpleType() << "_" << setS <<
2114  "(_" << tagS.simpleType() <<
2115  " *self, PyObject *value, void *closure)\n"
2116  "{\n"
2117  " long var = PyInt_AsLong(value);\n"
2118  " if (var == -1 && PyErr_Occurred()) {\n"
2119  " return -1;\n"
2120  " }\n"
2121  " self->elem->" << setS << "(var);\n"
2122  " return 0;\n"
2123  "}\n\n";
2124  setters[attrS] = 1;
2125  }
2126  else if (typeS == "long")
2127  {
2128  pyFile << "static int\n" <<
2129  "_" << tagS.simpleType() << "_" << setS <<
2130  "(_" << tagS.simpleType() <<
2131  " *self, PyObject *value, void *closure)\n"
2132  "{\n"
2133  " long var = PyInt_AsLong(value);\n"
2134  " if (var == -1 && PyErr_Occurred()) {\n"
2135  " return -1;\n"
2136  " }\n"
2137  " self->elem->" << setS << "(var);\n"
2138  " return 0;\n"
2139  "}\n\n";
2140  setters[attrS] = 1;
2141  }
2142  else if (typeS == "float")
2143  {
2144  pyFile << "static int\n" <<
2145  "_" << tagS.simpleType() << "_" << setS <<
2146  "(_" << tagS.simpleType() <<
2147  " *self, PyObject *value, void *closure)\n"
2148  "{\n"
2149  " double var = PyFloat_AsDouble(value);\n"
2150  " if (var == -1 && PyErr_Occurred()) {\n"
2151  " return 1;\n"
2152  " }\n"
2153  " self->elem->" << setS << "(var);\n"
2154  " return 0;\n"
2155  "}\n\n";
2156  setters[attrS] = 1;
2157  }
2158  else if (typeS == "double")
2159  {
2160  pyFile << "static int\n" <<
2161  "_" << tagS.simpleType() << "_" << setS <<
2162  "(_" << tagS.simpleType() <<
2163  " *self, PyObject *value, void *closure)\n"
2164  "{\n"
2165  " double var = PyFloat_AsDouble(value);\n"
2166  " if (var == -1 && PyErr_Occurred()) {\n"
2167  " return -1;\n"
2168  " }\n"
2169  " self->elem->" << setS << "(var);\n"
2170  " return 0;\n"
2171  "}\n\n";
2172  setters[attrS] = 1;
2173  }
2174  else if (typeS == "boolean")
2175  {
2176  pyFile << "static int\n" <<
2177  "_" << tagS.simpleType() << "_" << setS <<
2178  "(_" << tagS.simpleType() <<
2179  " *self, PyObject *value, void *closure)\n"
2180  "{\n"
2181  " long var = PyInt_AsLong(value);\n"
2182  " if (var == -1 && PyErr_Occurred()) {\n"
2183  " return -1;\n"
2184  " }\n"
2185  " self->elem->" << setS << "((var==0)? false : true);\n"
2186  " return 0;\n"
2187  "}\n\n";
2188  setters[attrS] = 1;
2189  }
2190  else if (typeS == "string")
2191  {
2192  pyFile << "static int\n" <<
2193  "_" << tagS.simpleType() << "_" << setS <<
2194  "(_" << tagS.simpleType() <<
2195  " *self, PyObject *value, void *closure)\n"
2196  "{\n"
2197  " PyObject *str=0;\n"
2198  " if (PyUnicode_Check(value))\n"
2199  " str = PyUnicode_AsEncodedString(value, \"ASCII\", \"strict\");\n"
2200  " else\n"
2201  " str = value;\n"
2202  "#if PY_MAJOR_VERSION < 3\n"
2203  " char *var = PyString_AsString(str);\n"
2204  "#else\n"
2205  " char *var = PyBytes_AsString(str);\n"
2206  "#endif\n"
2207  " if (var == 0) {\n"
2208  " return -1;\n"
2209  " }\n"
2210  " self->elem->" << setS << "(std::string(var));\n"
2211  " if (str != value) {\n"
2212  " Py_DECREF(str);\n"
2213  " }\n"
2214  " return 0;\n"
2215  "}\n\n";
2216  setters[attrS] = 1;
2217  }
2218  else if (typeS == "anyURI")
2219  {
2220  pyFile << "static int\n" <<
2221  "_" << tagS.simpleType() << "_" << setS <<
2222  "(_" << tagS.simpleType() <<
2223  " *self, PyObject *value, void *closure)\n"
2224  "{\n"
2225  " PyObject *str=0;\n"
2226  " if (PyUnicode_Check(value))\n"
2227  " str = PyUnicode_AsEncodedString(value, \"ASCII\", \"strict\");\n"
2228  " else\n"
2229  " str = value;\n"
2230  "#if PY_MAJOR_VERSION < 3\n"
2231  " char *var = PyString_AsString(str);\n"
2232  "#else\n"
2233  " char *var = PyBytes_AsString(str);\n"
2234  "#endif\n"
2235  " if (var == 0) {\n"
2236  " return -1;\n"
2237  " }\n"
2238  " self->elem->" << setS << "(std::string(var));\n"
2239  " if (str != value) {\n"
2240  " Py_DECREF(str);\n"
2241  " }\n"
2242  " return 0;\n"
2243  "}\n\n";
2244  setters[attrS] = 1;
2245  }
2246  else if (typeS == "Particle_t")
2247  {
2248  pyFile << "static int\n" <<
2249  "_" << tagS.simpleType() << "_" << setS <<
2250  "(_" << tagS.simpleType() <<
2251  " *self, PyObject *value, void *closure)\n"
2252  "{\n"
2253  " long var = PyInt_AsLong(value);\n"
2254  " if (var == -1 && PyErr_Occurred()) {\n"
2255  " return -1;\n"
2256  " }\n"
2257  " self->elem->" << setS << "((Particle_t)var);\n"
2258  " return 0;\n"
2259  "}\n\n";
2260  setters[attrS] = 1;
2261  }
2262  }
2263 
2264  std::map<XtString,method_descr> methods;
2265 
2266  if (tagS == "HDDM") {
2267  parentTable_t::iterator piter;
2268  for (piter = parents.begin(); piter != parents.end(); ++piter)
2269  {
2270  XtString cnameS(piter->first);
2271  if (cnameS != "HDDM" && element_in_list(cnameS,children[tagS]) == -1)
2272  {
2273  XtString getS("_" + tagS.simpleType() + "_get"
2274  + cnameS.plural().simpleType());
2275  pyFile << "static PyObject*\n" << getS <<
2276  "(PyObject *self, PyObject *args)\n"
2277  "{\n"
2278  " _" << tagS.simpleType() <<
2279  " *me = (_" << tagS.simpleType() << "*)self;\n"
2280  " if (me->elem == 0) {\n"
2281  " PyErr_SetString(PyExc_RuntimeError, "
2282  "\"lookup attempted on invalid " << tagS <<
2283  " element\");\n"
2284  " return NULL;\n"
2285  " }\n"
2286  " PyObject *list = _HDDM_ElementList"
2287  "_new(&_HDDM_ElementList_type, 0, 0);\n"
2288  " ((_HDDM_ElementList*)list)->subtype = "
2289  "&_" << cnameS.simpleType() << "_type;\n"
2290  " ((_HDDM_ElementList*)list)->list = "
2291  "(HDDM_ElementList<HDDM_Element>*)\n" << " "
2292  "new " << cnameS.listType() << "("
2293  "me->elem->get" << cnameS.plural().simpleType() << "());\n"
2294  " ((_HDDM_ElementList*)list)->borrowed = 0;\n"
2295  " ((_HDDM_ElementList*)list)->host = me->host;\n"
2296  " My_INCREF(me->host);\n"
2297  " LOG_NEW(Py_TYPE(list), "
2298  "((_HDDM_ElementList*)list)->subtype, 1);\n"
2299  " return list;\n"
2300  "}\n\n"
2301  ;
2302  method_descr meth_getS = {"get" + cnameS.plural().simpleType(),
2303  "METH_NOARGS",
2304  "get complete list of " + cnameS +
2305  " objects for this record"};
2306  methods[getS] = meth_getS;
2307  }
2308  }
2309  }
2310 
2311  parentList_t::iterator citer;
2312  for (citer = children[tagS].begin(); citer != children[tagS].end(); ++citer)
2313  {
2314  DOMElement *childEl = (DOMElement*)(*citer);
2315  XtString cnameS(childEl->getTagName());
2316  XtString repS(childEl->getAttribute(X("maxOccurs")));
2317  int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS));
2318  XtString getS("_" + tagS.simpleType() + "_get" + cnameS.simpleType());
2319  pyFile << "static PyObject*\n" << getS <<
2320  "(PyObject *self, PyObject *args)\n"
2321  "{\n"
2322  " int index=0;\n"
2323  " if (! PyArg_ParseTuple(args, \"|i\", &index)) {\n"
2324  " return NULL;\n"
2325  " }\n"
2326  " _" << tagS.simpleType() <<
2327  " *me = (_" << tagS.simpleType() << "*)self;\n"
2328  " if (me->elem == 0) {\n"
2329  " PyErr_SetString(PyExc_RuntimeError, "
2330  "\"lookup attempted on invalid " << tagS <<
2331  " element\");\n"
2332  " return NULL;\n"
2333  " }\n"
2334  " PyObject *obj = _" << cnameS.simpleType() <<
2335  "_new(&_" << cnameS.simpleType() << "_type, 0, 0);\n"
2336  " ((_" << cnameS.simpleType() <<
2337  "*)obj)->elem = &me->elem->get" << cnameS.simpleType()
2338  << ((rep > 1)? "(index)" : "()") << ";\n"
2339  " ((_" << cnameS.simpleType() << "*)obj)->host = me->host;\n"
2340  " My_INCREF(me->host);\n"
2341  " LOG_NEW(Py_TYPE(obj));\n"
2342  " return obj;\n"
2343  "}\n\n"
2344  ;
2345  method_descr meth_getS = {"get" + cnameS.simpleType(),
2346  "METH_VARARGS",
2347  "get an individual " + cnameS +
2348  " object from this " + tagS};
2349  methods[getS] = meth_getS;
2350 
2351  XtString gelS("_" + tagS.simpleType()
2352  + "_get" + cnameS.plural().simpleType());
2353  pyFile << "static PyObject*\n" << gelS <<
2354  "(PyObject *self, PyObject *args)\n"
2355  "{\n"
2356  " _" << tagS.simpleType() <<
2357  " *me = (_" << tagS.simpleType() << "*)self;\n"
2358  " if (me->elem == 0) {\n"
2359  " PyErr_SetString(PyExc_RuntimeError, "
2360  "\"lookup attempted on invalid " << tagS <<
2361  " element\");\n"
2362  " return NULL;\n"
2363  " }\n"
2364  " PyObject *list = _HDDM_ElementList_new"
2365  "(&_HDDM_ElementList_type, 0, 0);\n"
2366  " ((_HDDM_ElementList*)list)->subtype ="
2367  " &_" << cnameS.simpleType() << "_type;\n"
2368  " ((_HDDM_ElementList*)list)->list = "
2369  "(HDDM_ElementList<HDDM_Element>*)\n" << " "
2370  "&me->elem->get" << cnameS.plural().simpleType() << "();\n"
2371  " ((_HDDM_ElementList*)list)->borrowed = 1;\n"
2372  " ((_HDDM_ElementList*)list)->host = me->host;\n"
2373  " My_INCREF(me->host);\n"
2374  " LOG_NEW(Py_TYPE(list), "
2375  "((_HDDM_ElementList*)list)->subtype, 0);\n"
2376  " return list;\n"
2377  "}\n\n"
2378  ;
2379  method_descr meth_gelS = {"get" + cnameS.plural().simpleType(),
2380  "METH_NOARGS",
2381  "get list of " + cnameS +
2382  " objects for this " + tagS};
2383  methods[gelS] = meth_gelS;
2384 
2385  XtString addS("_" + tagS.simpleType()
2386  + "_add" + cnameS.plural().simpleType());
2387  pyFile << "static PyObject*\n" << addS <<
2388  "(PyObject *self, PyObject *args)\n"
2389  "{\n"
2390  " int count=1;\n"
2391  " int start=-1;\n"
2392  " if (! PyArg_ParseTuple(args, \"|ii\", &count, &start)) {\n"
2393  " return NULL;\n"
2394  " }\n;"
2395  " _" << tagS.simpleType() <<
2396  " *me = (_" << tagS.simpleType() << "*)self;\n"
2397  " if (me->elem == 0) {\n"
2398  " PyErr_SetString(PyExc_RuntimeError, "
2399  "\"add attempted on invalid " << tagS <<
2400  " element\");\n"
2401  " return NULL;\n"
2402  " }\n"
2403  " PyObject *list = _HDDM_ElementList_new"
2404  "(&_HDDM_ElementList_type, 0, 0);\n"
2405  " ((_HDDM_ElementList*)list)->subtype ="
2406  " &_" << cnameS.simpleType() << "_type;\n"
2407  " ((_HDDM_ElementList*)list)->list = "
2408  "(HDDM_ElementList<HDDM_Element>*)\n" << " "
2409  "new " << cnameS.listType() << "("
2410  "me->elem->add" << cnameS.plural().simpleType() <<
2411  "(count, start));\n"
2412  " ((_HDDM_ElementList*)list)->borrowed = 0;\n"
2413  " ((_HDDM_ElementList*)list)->host = me->host;\n"
2414  " My_INCREF(me->host);\n"
2415  " LOG_NEW(Py_TYPE(list), "
2416  "((_HDDM_ElementList*)list)->subtype, 1);\n"
2417  " return list;\n"
2418  "}\n\n"
2419  ;
2420  method_descr meth_addS = {"add" + cnameS.plural().simpleType(),
2421  "METH_VARARGS",
2422  "extend (or insert into) the list of " + cnameS +
2423  " objects for this " + tagS};
2424  methods[addS] = meth_addS;
2425 
2426  XtString delS("_" + tagS.simpleType()
2427  + "_delete" + cnameS.plural().simpleType());
2428  pyFile << "static PyObject*\n" << delS <<
2429  "(PyObject *self, PyObject *args)\n"
2430  "{\n"
2431  " int count=-1;\n"
2432  " int start=0;\n"
2433  " if (! PyArg_ParseTuple(args, \"|ii\", &count, &start)) {\n"
2434  " return NULL;\n"
2435  " }\n;"
2436  " _" << tagS.simpleType() <<
2437  " *me = (_" << tagS.simpleType() << "*)self;\n"
2438  " if (me->elem == 0) {\n"
2439  " PyErr_SetString(PyExc_RuntimeError, "
2440  "\"delete attempted on invalid " << tagS <<
2441  " element\");\n"
2442  " return NULL;\n"
2443  " }\n"
2444  " me->elem->delete" << cnameS.plural().simpleType() <<
2445  "(count, start);\n"
2446  " Py_INCREF(Py_None);\n"
2447  " return Py_None;\n"
2448  "}\n\n"
2449  ;
2450  method_descr meth_delS = {"delete" + cnameS.plural().simpleType(),
2451  "METH_VARARGS",
2452  "delete " + cnameS + " objects for this " + tagS};
2453  methods[delS] = meth_delS;
2454  }
2455 
2456  if (tagS == "HDDM")
2457  {
2458  XtString clrS("_" + tagS.simpleType() + "_clear");
2459  pyFile << "static PyObject*\n" << clrS <<
2460  "(PyObject *self, PyObject *args)\n"
2461  "{\n"
2462  " _" << tagS.simpleType() <<
2463  " *me = (_" << tagS.simpleType() << "*)self;\n"
2464  " if (me->elem == 0) {\n"
2465  " PyErr_SetString(PyExc_RuntimeError, "
2466  "\"lookup attempted on invalid " << tagS <<
2467  " element\");\n"
2468  " return NULL;\n"
2469  " }\n"
2470  " me->elem->clear();\n"
2471  " Py_INCREF(Py_None);\n"
2472  " return Py_None;\n"
2473  "}\n\n"
2474  ;
2475  method_descr meth_clrS = {"clear", "METH_NOARGS",
2476  "clear all contents from this " + tagS};
2477  methods[clrS] = meth_clrS;
2478  }
2479 
2480  XtString strS("_" + tagS.simpleType() + "_toString");
2481  pyFile << "static PyObject*\n" << strS <<
2482  "(PyObject *self, PyObject *args=0)\n"
2483  "{\n"
2484  " _" << tagS.simpleType() <<
2485  " *me = (_" << tagS.simpleType() << "*)self;\n"
2486  " if (me->elem == 0) {\n"
2487  " PyErr_SetString(PyExc_RuntimeError, "
2488  "\"lookup attempted on invalid " << tagS <<
2489  " element\");\n"
2490  " return NULL;\n"
2491  " }\n"
2492  " std::string str(me->elem->toString());\n"
2493  " return PyUnicode_FromString(str.c_str());\n"
2494  "}\n\n"
2495  ;
2496  method_descr str_method = {"toString", "METH_NOARGS",
2497  "show element as a human-readable string"};
2498  methods[strS] = str_method;
2499 
2500  XtString xmlS("_" + tagS.simpleType() + "_toXML");
2501  pyFile << "static PyObject*\n" << xmlS <<
2502  "(PyObject *self, PyObject *args=0)\n"
2503  "{\n"
2504  " _" << tagS.simpleType() <<
2505  " *me = (_" << tagS.simpleType() << "*)self;\n"
2506  " if (me->elem == 0) {\n"
2507  " PyErr_SetString(PyExc_RuntimeError, "
2508  "\"lookup attempted on invalid " << tagS <<
2509  " element\");\n"
2510  " return NULL;\n"
2511  " }\n"
2512  " std::string str(me->elem->toXML());\n"
2513  " return PyUnicode_FromString(str.c_str());\n"
2514  "}\n\n"
2515  ;
2516  method_descr xml_method = {"toXML", "METH_NOARGS",
2517  "show element as a XML fragment"};
2518  methods[xmlS] = xml_method;
2519 
2520  pyFile << "static PyGetSetDef _" << tagS.simpleType()
2521  << "_getsetters[] = {\n";
2522  std::map<XtString,XtString>::iterator aiter;
2523  for (aiter = attrList.begin(); aiter != attrList.end(); ++aiter) {
2524  XtString attrS = aiter->first;
2525  XtString getterS("_" + tagS.simpleType() + "_" + "get" + attrS.simpleType());
2526  XtString setterS("_" + tagS.simpleType() + "_" + "set" + attrS.simpleType());
2527  pyFile << " {(char*)\"" << attrS << "\",\n"
2528  << " (getter)" << getterS << ", ";
2529  if (setters.find(attrS) != setters.end()) {
2530  pyFile << "(setter)" << setterS << ",\n";
2531  }
2532  else {
2533  pyFile << "0,\n";
2534  }
2535  if (aiter->second == "string") {
2536  pyFile << " (char*)\"" << attrS << " string\",\n";
2537  }
2538  else {
2539  pyFile << " (char*)\"" << attrS << " value\",\n";
2540  }
2541  pyFile << " NULL},\n";
2542  }
2543  pyFile << " {NULL} /* Sentinel */\n"
2544  "};\n\n";
2545 
2546  pyFile << "static PyMemberDef _" << tagS.simpleType()
2547  << "_members[] = {\n"
2548  << " {NULL} /* Sentinel */\n"
2549  << "};\n\n";
2550 
2551  pyFile << "static PyMethodDef _" << tagS.simpleType()
2552  << "_methods[] = {\n";
2553  std::map<XtString,method_descr>::iterator miter;
2554  for (miter = methods.begin(); miter != methods.end(); ++miter) {
2555  pyFile << " {\"" << miter->second.name << "\", "
2556  << miter->first << ", " << miter->second.args << ",\n"
2557  << " \"" << miter->second.docs << "\"},\n";
2558  }
2559  pyFile << " {NULL} /* Sentinel */\n"
2560  << "};\n\n";
2561 
2562  typesList[tagS] = "_" + tagS.simpleType() + "_type";
2563 
2564  pyFile <<
2565  "static PyTypeObject _" << tagS.simpleType() << "_type = {\n"
2566  " PyVarObject_HEAD_INIT(NULL,0)\n"
2567  " \"hddm_" << classPrefix << "." << tagS.simpleType() << "\","
2568  " /*tp_name*/\n"
2569  " sizeof(_" << tagS.simpleType() <<
2570  "), /*tp_basicsize*/\n"
2571  " 0, /*tp_itemsize*/\n"
2572  " (destructor)_" << tagS.simpleType() <<
2573  "_dealloc, /*tp_dealloc*/\n"
2574  " 0, /*tp_print*/\n"
2575  " 0, /*tp_getattr*/\n"
2576  " 0, /*tp_setattr*/\n"
2577  " 0, /*tp_compare*/\n"
2578  " 0, /*tp_repr*/\n"
2579  " 0, /*tp_as_number*/\n"
2580  " 0, /*tp_as_sequence*/\n"
2581  " 0, /*tp_as_mapping*/\n"
2582  " 0, /*tp_hash */\n"
2583  " 0, /*tp_call*/\n"
2584  " (reprfunc)_" << tagS.simpleType() << "_toString, /*tp_str*/\n"
2585  " 0, /*tp_getattro*/\n"
2586  " 0, /*tp_setattro*/\n"
2587  " 0, /*tp_as_buffer*/\n"
2588  " Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/\n"
2589  " \"hddm_" << classPrefix << " " << tagS <<
2590  " element\", /* tp_doc */\n"
2591  " 0, /* tp_traverse */\n"
2592  " 0, /* tp_clear */\n"
2593  " 0, /* tp_richcompare */\n"
2594  " 0, /* tp_weaklistoffset */\n"
2595  " 0, /* tp_iter */\n"
2596  " 0, /* tp_iternext */\n"
2597  " _" << tagS.simpleType() << "_methods, /* tp_methods */\n"
2598  " _" << tagS.simpleType() << "_members, /* tp_members */\n"
2599  " _" << tagS.simpleType() << "_getsetters, /* tp_getset */\n"
2600  " &_HDDM_Element_type, /* tp_base */\n"
2601  " 0, /* tp_dict */\n"
2602  " 0, /* tp_descr_get */\n"
2603  " 0, /* tp_descr_set */\n"
2604  " 0, /* tp_dictoffset */\n"
2605  " (initproc)_" << tagS.simpleType() << "_init, /* tp_init */\n"
2606  " 0, /* tp_alloc */\n"
2607  " _" << tagS.simpleType() << "_new, /* tp_new */\n"
2608  "};\n\n"
2609  ;
2610 }
2611 
2612 /* Generate class declarations for this tag and its descendants;
2613  * this function calls itself recursively
2614  */
2615 
2616 void CodeBuilder::constructGroup(DOMElement* el)
2617 {
2618  XtString tagS(el->getTagName());
2619  parentList_t::iterator piter;
2620  parents[tagS].insert(parents[tagS].begin(),
2621  parentList.begin(),parentList.end());
2622  std::vector<DOMElement*>::iterator iter;
2623  for (iter = tagList.begin(); iter != tagList.end(); iter++)
2624  {
2625  DOMElement* targEl = *iter;
2626  XtString targS(targEl->getTagName());
2627  if (tagS == targS)
2628  {
2629  checkConsistency(el,targEl);
2630  return;
2631  }
2632  }
2633 
2634  parentList.push_back(el);
2635  DOMNodeList* contList = el->getChildNodes();
2636  int contLength = contList->getLength();
2637  for (int c = 0; c < contLength; c++)
2638  {
2639  DOMNode* cont = contList->item(c);
2640  short type = cont->getNodeType();
2641  if (type == DOMNode::ELEMENT_NODE)
2642  {
2643  DOMElement* contEl = (DOMElement*) cont;
2644  XtString contS(contEl->getTagName());
2645  children[tagS].push_back(contEl);
2646  constructGroup(contEl);
2647  }
2648  }
2649  parentList.pop_back();
2650 
2651  tagList.push_back(el);
2652 
2653  if (tagS == "HDDM")
2654  {
2655  std::vector<DOMElement*>::iterator iter;
2656  for (iter = tagList.begin(); iter != tagList.end(); iter++)
2657  {
2658  writeClassdef(*iter);
2659  }
2660  }
2661 }
2662 
2663 /* Write method implementation of the classes for this tag */
2664 
2665 void CodeBuilder::writeClassimp(DOMElement* el)
2666 {
2667 }
2668 
2669 /* Generate implementation code for data model classes */
2670 
2671 void CodeBuilder::constructMethods(DOMElement* el)
2672 {
2673  std::vector<DOMElement*>::iterator iter;
2674  for (iter = tagList.begin(); iter != tagList.end(); iter++)
2675  {
2676  writeClassimp(*iter);
2677  }
2678 }
2679 
2680 /* Generate methods for serializing classes to a stream and back again */
2681 
2682 void CodeBuilder::writeStreamers(DOMElement* el)
2683 {
2684 }
2685 
2686 void CodeBuilder::constructStreamers(DOMElement* el)
2687 {
2688  std::vector<DOMElement*>::iterator iter;
2689  for (iter = tagList.begin(); iter != tagList.end(); ++iter)
2690  {
2691  writeStreamers(*iter);
2692  }
2693 }
2694 
2695 /* Generate methods to read from binary stream into classes */
2696 
2697 void CodeBuilder::constructIOstreams(DOMElement* el)
2698 {
2699 }
2700 
2701 /* Generate the xml template in normal form and store in a string */
2702 
2703 void CodeBuilder::constructDocument(DOMElement* el)
2704 {
2705  static int indent = 0;
2706  pyFile << "\"";
2707  for (int n = 0; n < indent; n++)
2708  {
2709  pyFile << " ";
2710  }
2711 
2712  XtString tagS(el->getTagName());
2713  pyFile << "<" << tagS;
2714  DOMNamedNodeMap* attrList = el->getAttributes();
2715  int attrListLength = attrList->getLength();
2716  for (int a = 0; a < attrListLength; a++)
2717  {
2718  DOMNode* node = attrList->item(a);
2719  XtString nameS(node->getNodeName());
2720  XtString valueS(node->getNodeValue());
2721  pyFile << " " << nameS << "=\\\"" << valueS << "\\\"";
2722  }
2723 
2724  DOMNodeList* contList = el->getChildNodes();
2725  int contListLength = contList->getLength();
2726  if (contListLength > 0)
2727  {
2728  pyFile << ">\\n\"" << std::endl;
2729  indent++;
2730  for (int c = 0; c < contListLength; c++)
2731  {
2732  DOMNode* node = contList->item(c);
2733  if (node->getNodeType() == DOMNode::ELEMENT_NODE)
2734  {
2735  DOMElement* contEl = (DOMElement*) node;
2736  constructDocument(contEl);
2737  }
2738  }
2739  indent--;
2740  pyFile << "\"";
2741  for (int n = 0; n < indent; n++)
2742  {
2743  pyFile << " ";
2744  }
2745  pyFile << "</" << tagS << ">\\n\"" << std::endl;
2746  }
2747  else
2748  {
2749  pyFile << " />\\n\"" << std::endl;
2750  }
2751 }
2752 
2753 std::string guessType(const std::string &literal)
2754 {
2755  const char *str = literal.c_str();
2756  char *endptr;
2757  errno=0;
2758  long long int llvalue = strtoll(str,&endptr,0);
2759  if (errno == 0 && *endptr == 0) {
2760  errno=0;
2761  int lvalue = strtol(str,&endptr,0);
2762  if (errno == 0 && *endptr == 0 && lvalue == llvalue) {
2763  return "int";
2764  }
2765  else {
2766  return "long";
2767  }
2768  }
2769  errno=0;
2770  strtof(str,&endptr);
2771  if (errno == 0 && *endptr == 0) {
2772  return "float";
2773  }
2774  errno=0;
2775  strtod(str,&endptr);
2776  if (errno == 0 && *endptr == 0) {
2777  return "double";
2778  }
2779  if (literal == "true" || literal == "false") {
2780  return "boolean";
2781  }
2782  if ((int)lookupParticle(literal) != 0) {
2783  return "Particle_t";
2784  }
2785  if (XMLUri::isValidURI(false,X(literal))) {
2786  return "anyURI";
2787  }
2788  return "string";
2789 }
2790 
2792 {
2793  for (int p=0; p<100; ++p) {
2794  if (ParticleType((Particle_t)p) == name) {
2795  return (Particle_t)p;
2796  }
2797  }
2798  return Unknown;
2799 }
int element_in_list(XtString &name, parentList_t list)
Definition: hddm-cpp.cpp:1891
void constructGroup(DOMElement *el)
Definition: hddm-c.cpp:804
std::string guessType(const std::string &literal)
Definition: hddm-cpp.cpp:3489
char str[256]
XString classPrefix
Definition: hddm-c.cpp:88
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
std::ofstream pyFile
Definition: hddm-py.cpp:73
char string[256]
#define c
xercesc::DOMDocument * buildDOMDocument(const XString &xmlFile, bool keep)
Definition: XParsers.cpp:142
void constructIOstreams(DOMElement *el)
Definition: hddm-cpp.cpp:3241
void checkConsistency(DOMElement *el, DOMElement *elref)
Definition: hddm-c.cpp:598
XtString(const XString &x)
Definition: hddm-py.cpp:57
void usage()
Definition: t_rest.cxx:114
void writeStreamers(DOMElement *el)
Definition: hddm-cpp.cpp:3155
static char * ParticleType(Particle_t p)
Definition: particleType.h:142
#define X(str)
Definition: hddm-py.cpp:26
XtString(const XMLCh *p)
Definition: hddm-py.cpp:55
xercesc::DOMDocument * parseInputDocument(const XString &xmlFile, bool keep)
Definition: XParsers.cpp:73
#define S(str)
Definition: hddm-py.cpp:27
std::map< XtString, XtString > typesList
Definition: hddm-py.cpp:94
XtString simpleType()
Definition: hddm-c.cpp:576
std::vector< DOMNode * > parentList_t
Definition: hddm-py.cpp:98
XtString(const XtString &t)
Definition: hddm-py.cpp:58
XtString plural()
Definition: hddm-c.cpp:542
XtString listType()
Definition: hddm-c.cpp:587
~CodeBuilder()
Definition: hddm-py.cpp:76
void constructDocument(DOMElement *el)
Definition: hddm-c.cpp:2033
Particle_t lookupParticle(const std::string &name)
Definition: hddm-cpp.cpp:3527
XtString linkType()
Definition: hddm-cpp.cpp:1879
XtString(const char *s)
Definition: hddm-py.cpp:54
void writeClassimp(DOMElement *el)
Definition: hddm-cpp.cpp:2388
void constructMethods(DOMElement *el)
Definition: hddm-cpp.cpp:3144
XtString()
Definition: hddm-py.cpp:53
XtString(const std::string &s)
Definition: hddm-py.cpp:56
void writeClassdef(DOMElement *el)
Definition: hddm-cpp.cpp:2016
std::map< const XtString, parentList_t > parentTable_t
Definition: hddm-py.cpp:99
int main(int argc, char *argv[])
Definition: gendoc.cc:6
~XtString()
Definition: hddm-py.cpp:59
void constructStreamers(DOMElement *el)
Definition: hddm-cpp.cpp:3230
Particle_t
Definition: particleType.h:12