/* * hddm-cpp : tool that reads in a HDDM document (Hall D Data Model) * and writes a c++ class library that expresses the model * in c++ classes. It also generates input/output methods * for serializing/deserializing these classes in a form * suitable for passing over a network or storing on disk. * * author: richard.t.jones at uconn.edu * version: January 25, 2006 - original release. * January 13, 2012 - added support for compression through * the xstream zip and bzip2 facilities. * * * Programmer's Notes: * ------------------- * 1. The HDDM specification describes data files using xml. For * information about the contents and structure of HDDM documents * see the web page that describes the data model. * * 2. Access by hddm-cpp to the xml source is through the industry- * standard Document Object Model (DOM) interface. * * 3. The code has been tested with the xerces-c DOM implementation from * Apache, and is intended to be used with the xerces-c library. * * 4. Output is sent to .hpp and .cpp where * is by default "hddm_X" and can be changed with the -o option, where * X is the user-defined HDDM class string defined in the HDDM tag. * * 5. As a by-product of using the DOM parser to access the xml source, * hddm-cpp verifies the source for well-formedness. Therefore it may * also be used to check the xml data model document. * * * Implementation Notes: * --------------------- * 1. The binary stream consists of the hddm data model in the form * of a well-formed xml header, followed by binary data. * * 2. The binary data consist of a sequence of event records, which are * repetitions of the basic data model in a serial representation. * * 3. Each element is output to the stream in the order it appears in * the data model, prefixed by an exclusive byte count. * * 4. Any c++ application compiled with the hddm header file that is * generated by hddm-cpp is able to read any hddm binary file that * was written using the same hddm class, ie. the * document tags must be a non-colliding set (see matching rules). * * 5. The input/output features of the class library produced by hddm-cpp * are implemented on top of the "xstream" binary i/o class by Claudio * Valente which provides serialization/deserialization of binary data * using network byte-ordering (RFC-1832), compression/decompression, * and error checking capability used to make the hddm i/o facility * flexible and robust. * * 6. The matching rules between the built-in data model and the data * found in an arbitrary input file are as follows: * a) The attribute list for any given tag must be identical in content * and order wherever it appears, otherwise there is a collision. * b) The content list for any given tag must be internally consistent * within each model, but there are no requirements for agreement * between the classes and the binary stream models. Only the * contents which appear in both models will be unpacked, however. */ #include "XString.hpp" #include "XParsers.hpp" #include #include #include #include #define X(str) XString(str).unicode_str() #define S(str) str.c_str() using namespace xercesc; XString classPrefix; void usage() { std::cerr << "\nUsage:\n" << " hddm-cpp [-v | -o ] {HDDM file}\n\n" << "Options:\n" << " -v validate only\n" << " -o write to .h" << std::endl; } class XtString : public XString { /* XString class with a few extra methods for creating type * strings that are useful in creating class names */ public: XtString() {}; XtString(const char* s): XString(s) {}; XtString(const XMLCh* p): XString(p) {}; XtString(const std::string& s): XString(s) {}; XtString(const XString& x): XString(x) {}; XtString(const XtString& t): XString((XString&)t) {}; ~XtString() {}; XtString plural(); XtString simpleType(); XtString listType(); XtString linkType(); }; class CodeBuilder { /* The methods in this class are used to write the c++ code * that implements the hddm class library. */ public: std::ofstream hFile; std::ofstream cFile; CodeBuilder() {}; ~CodeBuilder() {}; void checkConsistency(DOMElement* el, DOMElement* elref); void writeClassdef(DOMElement* el); void writeClassimp(DOMElement* el); void constructDocument(DOMElement* el); void constructGroup(DOMElement* el); void constructIOstreams(DOMElement* el); void constructMethods(DOMElement* el); void constructStreamers(DOMElement* el); void writeStreamers(DOMElement* el); private: std::vector tagList; typedef std::vector parentList_t; typedef std::map parentTable_t; parentList_t parentList; parentTable_t parents; parentTable_t children; int element_in_list(XtString &name, parentList_t list); }; int main(int argC, char* argV[]) { try { XMLPlatformUtils::Initialize(); } catch (const XMLException* toCatch) { XtString msg(toCatch->getMessage()); std::cerr << "hddm-cpp: Error during initialization! :\n" << msg << std::endl; return 1; } if (argC < 2) { usage(); return 1; } else if ((argC == 2) && (strcmp(argV[1], "-?") == 0)) { usage(); return 2; } XtString xmlFile; XtString hFilename; bool verifyOnly = false; int argInd; for (argInd = 1; argInd < argC; argInd++) { if (argV[argInd][0] != '-') { break; } if (strcmp(argV[argInd],"-v") == 0) { verifyOnly = true; } else if (strcmp(argV[argInd],"-o") == 0) { hFilename = XtString(argV[++argInd]); } else { std::cerr << "Unknown option \'" << argV[argInd] << "\', ignoring it\n" << std::endl; } } if (argInd != argC - 1) { usage(); return 1; } xmlFile = XtString(argV[argInd]); #if defined OLD_STYLE_XERCES_PARSER DOMDocument* document = parseInputDocument(xmlFile.c_str(),false); #else DOMDocument* document = buildDOMDocument(xmlFile.c_str(),false); #endif if (document == 0) { std::cerr << "hddm-cpp : Error parsing HDDM document, " << "cannot continue" << std::endl; return 1; } DOMElement* rootEl = document->getDocumentElement(); XtString rootS(rootEl->getTagName()); if (rootS != "HDDM") { std::cerr << "hddm-cpp error: root element of input document is " << "\"" << rootS << "\", expected \"HDDM\"" << std::endl; return 1; } XtString classS(rootEl->getAttribute(X("class"))); classPrefix = classS; XtString hname; if (verifyOnly) { hname = "/dev/null"; } else if (hFilename.size()) { hname = hFilename + ".hpp"; } else { hname = "hddm_" + classPrefix + ".hpp"; } CodeBuilder builder; builder.hFile.open(hname.c_str()); if (! builder.hFile.is_open()) { std::cerr << "hddm-cpp error: unable to open output file " << hname << std::endl; return 1; } XtString cname; if (verifyOnly) { cname = "/dev/null"; } else if (hFilename.size()) { cname = hFilename + ".cpp"; } else { cname = "hddm_" + classPrefix + ".cpp"; } builder.cFile.open(cname.c_str()); if (! builder.cFile.is_open()) { std::cerr << "hddm-cpp error: unable to open output file " << cname << std::endl; return 1; } builder.hFile << "/*\n" " * hddm_" << classPrefix << ".hpp - DO NOT EDIT THIS FILE\n" " *\n" " * This file was generated automatically by hddm-cpp from the file\n" " * exam2.xml\n" "\n" " * This header file defines the c++ classes that hold the data\n" " * described in the data model (from exam2.xml). \n" " *\n" " * The hddm data model tool set was written by\n" " * Richard Jones, University of Connecticut.\n" " *\n" " * For more information see the following web site\n" " *\n" " * http://zeus.phys.uconn.edu/halld/datamodel/doc\n" " *\n" " */\n" "\n" "#ifndef SAW_" << classPrefix << "_HDDM\n" "#define SAW_" << classPrefix << "_HDDM\n" "\n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "\n" "namespace hddm_" << classPrefix << " {\n" "\n" "const int k_bits_compression = 0xf0;\n" "const int k_no_compression = 0x00;\n" "const int k_z_compression = 0x10;\n" "const int k_bz2_compression = 0x20;\n" "const int k_default_status = 0x0;\n" "\n" "class HDDM;\n" "class istream;\n" "class ostream;\n" "\n" "class streamable {\n" " public:\n" " virtual ~streamable() {}\n" " virtual void streamer(istream &istr) {}\n" " virtual void streamer(ostream &ostr) {}\n" "};\n" "\n" "class ostream {\n" " public:\n" " ostream(std::ostream &src);\n" " ~ostream();\n" " ostream &operator<<(HDDM &record);\n" " ostream &operator<<(streamable &object);\n" " int getCompression() const;\n" " void setCompression(int flags);\n" " void clear_streambufs();\n" " xstream::xdr::ostream *m_xstr;\n" " private:\n" " void configure_streambufs();\n" " std::ostream &m_ostr;\n" " std::ostringstream m_sstr;\n" " std::streambuf *m_xcmp;\n" " std::streambuf *m_xraw;\n" " char *m_event_buffer;\n" " int m_event_buffer_size;\n" " int m_status_bits;\n" "};\n" "\n" "class codon {\n" " public:\n" " codon(): m_order(0) {}\n" " int m_order;\n" " std::string m_tagname;\n" " std::vector m_sequence;\n" " std::deque m_target;\n" "};\n" "\n" "typedef std::vector chromosome;\n" "\n" "class istream {\n" " public:\n" " istream(std::istream &src);\n" " ~istream();\n" " istream &operator>>(HDDM &record);\n" " istream &operator>>(streamable &object);\n" " void sequencer(streamable &object);\n" " void skip(int count);\n" " int getCompression() const;\n" " void configure_streambufs();\n" " void clear_streambufs();\n" " xstream::xdr::istream *m_xstr;\n" " int m_sequencing;\n" " private:\n" " codon m_genome;\n" " codon *m_codon;\n" " std::string m_documentString;\n" " chromosome synthesize(const std::string &src, int p_src,\n" " const std::string &ref, int p_ref);\n" " int getTag(const std::string &src, int p_src, std::string &tag, int &level);\n" " int getEndTag(const std::string &src, int p_src, const std::string &tag);\n" " void collide(const std::string &itag, const std::string &rtag);\n" " std::istream &m_istr;\n" " std::istringstream m_sstr;\n" " std::streambuf *m_xcmp;\n" " std::streambuf *m_xraw;\n" " int m_events_to_skip;\n" " char *m_event_buffer;\n" " int m_event_buffer_size;\n" " int m_next_event_size;\n" " int m_status_bits;\n" "};\n" "\n" "class HDDM_Element: public streamable {\n" " public:\n" " ~HDDM_Element() {}\n" " virtual const void *getAttribute(const std::string &name) const {\n" " return 0;\n" " }\n" " protected:\n" " HDDM_Element() : m_parent(0), m_host(0) {}\n" " HDDM_Element(HDDM_Element *parent)\n" " : m_parent(parent),\n" " m_host(parent->m_host)\n" " {}\n" " HDDM_Element(HDDM_Element &src)\n" " : m_parent(src.m_parent),\n" " m_host(src.m_host)\n" " {}\n" " HDDM_Element *m_parent;\n" " HDDM *m_host;\n" "};\n" "\n" "template \n" "class HDDM_ElementList: public streamable {\n" " public:\n" " HDDM_ElementList(typename std::list *plist,\n" " typename std::list::iterator begin,\n" " typename std::list::iterator end,\n" " HDDM_Element *parent=0)\n" " : m_host_plist(plist),\n" " m_first_iter(begin),\n" " m_last_iter(end),\n" " m_parent(parent)\n" " {\n" " for (m_size = 0; begin != end; ++m_size, ++begin) {}\n" " if (m_size) {\n" " --m_last_iter;\n" " }\n" " }\n" "\n" " HDDM_ElementList(const HDDM_ElementList &src)\n" " : m_host_plist(src.m_host_plist),\n" " m_first_iter(src.m_first_iter),\n" " m_last_iter(src.m_last_iter),\n" " m_parent(src.m_parent),\n" " m_size(src.m_size)\n" " {}\n" "\n" " bool empty() const { return (m_size == 0); }\n" " int size() const { return m_size; }\n" " T &front() const { return *m_first_iter; }\n" " T &back() const { return *m_last_iter; }\n" " T &operator()() { return *m_first_iter; }\n" " T &operator()(int index) {\n" " if (index == 0) {\n" " return *m_first_iter;\n" " }\n" " else if (index == -1) {\n" " return *m_last_iter;\n" " }\n" " else if (index > 0) {\n" " return *(m_first_iter + index);\n" " }\n" " else {\n" " return *(m_last_iter + (++index));\n" " }\n" " }\n" "\n" " class iterator: public std::list::iterator {\n" " public:\n" " iterator() {}\n" " iterator(typename std::list::iterator src)\n" " : std::list::iterator(src) {}\n" "\n" " T *operator->() const { \n" " return *(typename std::list::iterator)(*this);\n" " }\n" "\n" " T &operator*() const {\n" " return **(typename std::list::iterator)(*this);\n" " }\n" "\n" " iterator operator+=(int offset) {\n" " if (offset > 0) {\n" " for (int i=0; ioffset; --i, --(*this)) {}\n" " }\n" " return *this;\n" " }\n" "\n" " iterator operator-=(int offset) {\n" " if (offset > 0) {\n" " for (int i=0; ioffset; --i, ++(*this)) {}\n" " }\n" " return *this;\n" " }\n" "\n" " iterator operator+(int offset) const {\n" " iterator iter(*this);\n" " return iter += offset;\n" " }\n" "\n" " iterator operator-(int offset) const {\n" " iterator iter(*this);\n" " return iter -= offset;\n" " }\n" "\n" " int operator-(iterator iter) const {\n" " if (*this == iter) {\n" " return 0;\n" " }\n" " iterator iter2(iter);\n" " for (int n=1; n < m_size; ++n) {\n" " if (++iter == *this) {\n" " return n;\n" " }\n" " else if (--iter2 == *this) {\n" " return -n;\n" " }\n" " }\n" " return m_size;\n" " }\n" " };\n" "\n" " class const_iterator: public std::list::const_iterator {\n" " public:\n" " const_iterator() {}\n" " const_iterator(const typename std::list::const_iterator src)\n" " : std::list::const_iterator(src) {}\n" "\n" " const_iterator(const typename std::list::iterator src)\n" " : std::list::const_iterator(src) {}\n" "\n" " const T *operator->() const { \n" " return *(typename std::list::const_iterator)(*this);\n" " }\n" "\n" " const T &operator*() const { \n" " return **(typename std::list::const_iterator)(*this);\n" " }\n" "\n" " const const_iterator operator+=(int offset) {\n" " if (offset > 0) {\n" " for (int i=0; ioffset; --i, --(*this)) {}\n" " }\n" " return *this;\n" " }\n" "\n" " const const_iterator operator-=(int offset) {\n" " if (offset > 0) {\n" " for (int i=0; i 0) {\n" " for (int i=0; i>offset; --i, ++(*this)) {}\n" " }\n" " return *this;\n" " }\n" "\n" " const const_iterator operator+(int offset) const {\n" " const_iterator iter(*this);\n" " return iter += offset;\n" " }\n" "\n" " const const_iterator operator-(int offset) const {\n" " const_iterator iter(*this);\n" " return iter -= offset;\n" " }\n" "\n" " int operator-(const_iterator iter) const {\n" " if (*this == iter) {\n" " return 0;\n" " }\n" " const_iterator iter2(iter);\n" " for (int n=1; n < m_size; ++n) {\n" " if (++iter == *this) {\n" " return n;\n" " }\n" " else if (--iter2 == *this) {\n" " return -n;\n" " }\n" " }\n" " return m_size;\n" " }\n" " };\n" "\n" " iterator begin() const { return m_first_iter; }\n" " iterator end() const { return (m_size)? m_last_iter + 1 : m_last_iter; }\n" " void clear() { del(); }\n" "\n" " HDDM_ElementList add(int count=1, int start=-1) {\n" " if (m_parent == 0) {\n" " throw std::runtime_error(\"HDDM_ElementList error - \"\n" " \"attempt to add to immutable list\");\n" " }\n" " iterator it = insert(start, count);\n" " typename std::list::iterator iter(it);\n" " for (int n=0; n= 0) {\n" " iter_begin = iter_end - count;\n" " }\n" " }\n" " else {\n" " iter_begin += start;\n" " if (count >= 0) {\n" " iter_end = iter_begin + start;\n" " }\n" " }\n" " typename std::list::iterator iter;\n" " for (iter = iter_begin; iter != iter_end; ++iter) {\n" " delete *iter;\n" " }\n" " erase(start, count);\n" " }\n" "\n" " void streamer(istream &istr) {\n" " clear();\n" " int size;\n" " *istr.m_xstr >> size;\n" " if (size) {\n" " iterator iter = add(size).begin();\n" " for (int n=0; n < size; ++n, ++iter) {\n" " istr.sequencer(*iter);\n" " }\n" " }\n" " istr.m_sequencing = 0;\n" " }\n" "\n" " void streamer(ostream &ostr) {\n" " if (m_size) {\n" " *ostr.m_xstr << m_size;\n" " for (iterator iter = begin(); iter != end(); ++iter) {\n" " iter->streamer(ostr);\n" " }\n" " }\n" " }\n" "\n" " private:\n" " HDDM_ElementList() {}\n" "\n" " iterator insert(int start, int count) {\n" " if (m_size == 0) {\n" " if (count > 0) {\n" " if (m_first_iter == m_host_plist->begin()) {\n" " m_host_plist->insert(m_first_iter,count,(T*)0);\n" " m_first_iter = m_host_plist->begin();\n" " }\n" " else {\n" " m_host_plist->insert(m_first_iter--,count,(T*)0);\n" " ++m_first_iter;\n" " }\n" " --m_last_iter;\n" " m_size = count;\n" " }\n" " return m_first_iter;\n" " }\n" " else if (start == 0) {\n" " if (count > 0) {\n" " if (m_first_iter == m_host_plist->begin()) {\n" " m_host_plist->insert(m_first_iter,count,(T*)0);\n" " m_first_iter = m_host_plist->begin();\n" " }\n" " else {\n" " m_host_plist->insert(m_first_iter--,count,(T*)0);\n" " ++m_first_iter;\n" " }\n" " m_size += count;\n" " }\n" " return m_first_iter;\n" " }\n" " else if (start == -1) {\n" " if (count > 0) {\n" " iterator pos(m_last_iter);\n" " m_host_plist->insert(++m_last_iter,count,(T*)0);\n" " --m_last_iter;\n" " m_size += count;\n" " return ++pos;\n" " }\n" " return m_last_iter;\n" " }\n" " else if (start > 0) {\n" " if (count > 0) {\n" " iterator pos(m_first_iter);\n" " iterator pos2(pos += start-1);\n" " m_host_plist->insert(++pos,count,(T*)0);\n" " if (m_last_iter == pos2) {\n" " m_last_iter = --pos;\n" " }\n" " m_size += count;\n" " return ++pos2;\n" " }\n" " return m_first_iter + start;\n" " }\n" " else {\n" " if (count > 0) {\n" " iterator pos(m_last_iter);\n" " iterator pos2(pos += start);\n" " m_host_plist->insert(++pos,count,(T*)0);\n" " m_size += count;\n" " return ++pos2;\n" " }\n" " return m_last_iter + (start+1);\n" " }\n" " }\n" "\n" " iterator erase(int start, int count) {\n" " if (m_size == 0) {\n" " return m_first_iter+start;\n" " }\n" " else if ((count >= m_size || count == -1) &&\n" " (start == 0 || start <= -m_size)) {\n" " m_host_plist->erase(m_first_iter,++m_last_iter);\n" " m_first_iter = m_last_iter;\n" " m_size = 0;\n" " return m_first_iter;\n" " }\n" " else if (start > 0 && start <= m_size) {\n" " ++m_last_iter;\n" " count = (count < 0)? m_size-start : count;\n" " iterator pos(m_first_iter + start);\n" " iterator pos2(pos + count);\n" " m_host_plist->erase(pos,pos2);\n" " m_size -= count;\n" " --m_last_iter;\n" " return pos2;\n" " }\n" " else if (start < 0 && start >= -m_size) {\n" " ++m_last_iter;\n" " count = (count < 0)? -start : count;\n" " iterator pos(m_last_iter + (start+1));\n" " iterator pos2(pos + count);\n" " m_host_plist->erase(pos,pos2);\n" " if (m_size -= count) {\n" " --m_last_iter;\n" " }\n" " else {\n" " m_first_iter = m_last_iter;\n" " }\n" " return pos2;\n" " }\n" " return m_last_iter+1;\n" " }\n" "\n" " protected:\n" " std::list *m_host_plist;\n" " iterator m_first_iter;\n" " iterator m_last_iter;\n" " HDDM_Element *m_parent;\n" " int m_size;\n" "};\n" "\n" "template \n" "class HDDM_ElementLink: public HDDM_ElementList {\n" " public:\n" " HDDM_ElementLink(typename std::list *plist,\n" " typename std::list::iterator begin,\n" " typename std::list::iterator end,\n" " HDDM_Element *parent)\n" " : HDDM_ElementList(plist,begin,end,parent)\n" " {}\n" " HDDM_ElementLink(const HDDM_ElementList &src)\n" " : HDDM_ElementList(src)\n" " {}\n" "\n" " void streamer(istream &istr) {\n" " HDDM_ElementList::clear();\n" " HDDM_ElementList::add().begin()->streamer(istr);\n" " }\n" "\n" " void streamer(ostream &ostr) {\n" " if (HDDM_ElementList::m_size) {\n" " HDDM_ElementList::begin()->streamer(ostr);\n" " }\n" " }\n" "\n" " protected:\n" " HDDM_ElementLink() {}\n" "};\n" "\n" ; builder.cFile << "/*\n" " * hddm_" << classPrefix << ".cpp - DO NOT EDIT THIS FILE\n" " *\n" " * This file was generated automatically by hddm-cpp from the file\n" " * exam2.xml\n" "\n" " * This c++ source implements the methods for the classes \n" " * described in the data model (from exam2.xml). \n" " *\n" " * The hddm data model tool set was written by\n" " * Richard Jones, University of Connecticut.\n" " *\n" " * For more information see the following web site\n" " *\n" " * http://zeus.phys.uconn.edu/halld/datamodel/doc\n" " */\n" "\n" "#include \"hddm_" << classPrefix << ".hpp\"\n" "\n" "#ifndef _FILE_OFFSET_BITS\n" "# define _FILE_OFFSET_BITS 64\n" "#endif\n" "\n" "using namespace hddm_" << classPrefix << ";\n" "\n" ; builder.constructGroup(rootEl); builder.constructIOstreams(rootEl); builder.constructMethods(rootEl); builder.constructStreamers(rootEl); builder.hFile << "}\n" "#endif /* SAW_" << classPrefix << "_HDDM */\n" ; builder.cFile << "std::string DocumentString(\n"; builder.constructDocument(rootEl); builder.cFile << ");\n" << std::endl; builder.cFile << "istream::istream(std::istream &src)\n" " : m_xstr(0),\n" " m_istr(src),\n" " m_xcmp(0),\n" " m_xraw(0),\n" " m_status_bits(0)\n" "{\n" " std::string line;\n" " m_documentString = \"\";\n" " while(std::getline(src,line).good()) {\n" " m_documentString += line + \"\\n\";\n" " if (line == \"\") {\n" " break;\n" " }\n" " }\n" " if (src.bad()) {\n" " throw std::runtime_error(\"istream::istream - invalid hddm header\");\n" " }\n" " m_genome.m_tagname = \"HDDM\";\n" " m_genome.m_sequence = synthesize(m_documentString,0,DocumentString,0);\n" " m_event_buffer = new char[m_event_buffer_size = 100000];\n" " m_sstr.rdbuf()->pubsetbuf(m_event_buffer,m_event_buffer_size);\n" " configure_streambufs();\n" " m_next_event_size = 0;\n" " m_events_to_skip = 0;\n" "}\n" "\n" "istream::~istream() {\n" " delete m_event_buffer;\n" " clear_streambufs();\n" "}\n" "\n" "void istream::configure_streambufs() {\n" " clear_streambufs();\n" " m_xstr = new xstream::xdr::istream(m_sstr);\n" " if (m_status_bits & k_z_compression) {\n" " //std::cerr << \"input switched on z compression\" << std::endl;\n" " m_xraw = m_istr.rdbuf();\n" " m_xcmp = new xstream::z::istreambuf(m_xraw);\n" " m_istr.rdbuf(m_xcmp);\n" " }\n" " else if (m_status_bits & k_bz2_compression) {\n" " //std::cerr << \"input switched on bz2 compression\" << std::endl;\n" " m_xraw = m_istr.rdbuf();\n" " m_xcmp = new xstream::bz::istreambuf(m_xraw);\n" " m_istr.rdbuf(m_xcmp);\n" " }\n" " else if (m_status_bits & k_bits_compression) {\n" " throw std::runtime_error(\"hddm_x::istream::configure_streambufs error - \"\n" " \"unrecognized compression flag requested.\");\n" " }\n" "}\n" "\n" "void istream::clear_streambufs() {\n" " if (m_xraw) {\n" " m_istr.rdbuf(m_xraw);\n" " m_xraw = 0;\n" " }\n" " if (m_xcmp) {\n" " delete m_xcmp;\n" " m_xcmp = 0;\n" " }\n" " if (m_xstr) {\n" " delete m_xstr;\n" " m_xstr = 0;\n" " }\n" "}\n" "\n" "istream &istream::operator>>(HDDM &record) {\n" " if (m_next_event_size == 0) {\n" " m_istr.read(m_event_buffer,4);\n" " if (!m_istr.good()) {\n" " throw std::runtime_error(\"istream::operator>> error - \"\n" " \"attempt to read past end of file!\");\n" " }\n" " m_sstr.seekg(0);\n" " *m_xstr >> m_next_event_size;\n" " return *this >> record;\n" " }\n" " else if (m_next_event_size == 1) {\n" " m_istr.read(m_event_buffer+4,4);\n" " int size;\n" " *m_xstr >> size;\n" " m_istr.read(m_event_buffer+8,size);\n" " int format, flags;\n" " *m_xstr >> format >> flags;\n" " if (format != 0) {\n" " throw std::runtime_error(\"istream::operator>> error - \"\n" " \"unsupported compression format!\");\n" " }\n" " else if (flags != m_status_bits) {\n" " m_status_bits = flags;\n" " configure_streambufs();\n" " }\n" " m_next_event_size = 0;\n" " return *this >> record;\n" " }\n" " else if (m_next_event_size+4 > m_event_buffer_size) {\n" " char *newbuf = new char[m_event_buffer_size = m_next_event_size+1000];\n" " m_sstr.rdbuf()->pubsetbuf(newbuf, m_event_buffer_size);\n" " memcpy(newbuf,m_event_buffer,4);\n" " delete m_event_buffer;\n" " m_event_buffer = newbuf;\n" " }\n" " \n" " m_istr.read(m_event_buffer+4,m_next_event_size);\n" " \n" " if (m_events_to_skip) {\n" " --m_events_to_skip;\n" " m_next_event_size = 0;\n" " return *this >> record;\n" " }\n" " m_sstr.seekg(0);\n" " m_sequencing = 0;\n" " m_codon = &m_genome;\n" " *this >> (streamable&)record;\n" " m_istr.read(m_event_buffer,4);\n" " m_sstr.seekg(0);\n" " *m_xstr >> m_next_event_size;\n" " return *this;\n" "}\n" "\n" "ostream::ostream(std::ostream &src)\n" " : m_xstr(0),\n" " m_ostr(src),\n" " m_xcmp(0),\n" " m_xraw(0),\n" " m_status_bits(k_default_status)\n" "{\n" " m_ostr << DocumentString;\n" " m_event_buffer = new char[m_event_buffer_size = 100000];\n" " m_sstr.rdbuf()->pubsetbuf(m_event_buffer,m_event_buffer_size);\n" " configure_streambufs();\n" "}\n" "\n" "ostream::~ostream() {\n" " delete m_event_buffer;\n" " clear_streambufs();\n" "}\n" "\n" "void ostream::setCompression(int flags) {\n" " if ((flags ^ m_status_bits) & k_bits_compression) {\n" " if ((m_status_bits & k_bits_compression) != k_no_compression) {\n" " std::cerr << \"hddm_" << classPrefix << "::ostream::setCompression warning - \"\n" " << \"compression already enabled, cannot change.\"\n" " << std::endl;\n" " return;\n" " }\n" " m_status_bits &= ~k_bits_compression;\n" " m_status_bits |= flags;\n" " m_sstr.str(\"\");\n" " *m_xstr << 1 << 8 << 0 << m_status_bits;\n" " m_ostr << m_sstr.str();\n" " configure_streambufs();\n" " }\n" "}\n" "\n" "void ostream::configure_streambufs() {\n" " clear_streambufs();\n" " m_xstr = new xstream::xdr::ostream(m_sstr);\n" " if (m_status_bits & k_z_compression) {\n" " //std::cerr << \"output switched on z compression\" << std::endl;\n" " m_xraw = m_ostr.rdbuf();\n" " m_xcmp = new xstream::z::ostreambuf(m_xraw);\n" " m_ostr.rdbuf(m_xcmp);\n" " }\n" " else if (m_status_bits & k_bz2_compression) {\n" " //std::cerr << \"output switched on bz2 compression\" << std::endl;\n" " m_xraw = m_ostr.rdbuf();\n" " m_xcmp = new xstream::bz::ostreambuf(m_xraw);\n" " m_ostr.rdbuf(m_xcmp);\n" " }\n" " else if (m_status_bits & k_bits_compression) {\n" " throw std::runtime_error(\"ostream::configure_streambufs error - \"\n" " \"unrecognized compression flag requested.\");\n" " }\n" "}\n" "\n" "void ostream::clear_streambufs() {\n" " if (m_xstr) {\n" " delete m_xstr;\n" " m_xstr = 0;\n" " }\n" " if (m_xraw) {\n" " m_ostr.flush();\n" " m_ostr.rdbuf(m_xraw);\n" " m_xraw = 0;\n" " }\n" " if (m_xcmp) {\n" " delete m_xcmp;\n" " m_xcmp = 0;\n" " }\n" "}\n" "\n" "int istream::getTag(const std::string &src, int start,\n" " std::string &tag, int &level)\n" "{\n" " tag = \"\";\n" " size_t p_btag = src.find(\"<\",start);\n" " size_t p_bline = src.find_last_of(\"\\n\",p_btag);\n" " if (p_bline == std::string::npos)\n" " {\n" " p_bline = 0;\n" " }\n" " else\n" " {\n" " ++p_bline;\n" " }\n" " level = (p_btag-p_bline)/2;\n" " size_t p_etag = p_btag;\n" " for (size_t quotes=0; p_etag < src.size(); ++p_etag) {\n" " if (src[p_etag] == '\"') {\n" " tag += \"\\\"\";\n" " ++quotes;\n" " }\n" " else if (quotes/2*2 != quotes) {\n" " tag += src[p_etag];\n" " }\n" " else if (src.find_first_of(\" \\t\\n\",p_etag) == 0) {\n" " tag += \" \";\n" " p_etag = src.find_first_not_of(\" \\t\\n\",p_etag)-1;\n" " }\n" " else if (src[p_etag] == '>') {\n" " tag += \">\";\n" " break;\n" " }\n" " else {\n" " tag += src[p_etag];\n" " }\n" " }\n" " if (p_etag == src.size()) {\n" " throw std::runtime_error(\"istream::getTag - bad header format\");\n" " }\n" " return p_etag+2;\n" "}\n" "\n" "int istream::getEndTag(const std::string &src, int start,\n" " const std::string &tag)\n" "{\n" " if (tag.rfind(\"/>\") == tag.size()-2) {\n" " return start + tag.size()+1;\n" " }\n" " else {\n" " std::string etag = \"\";\n" " size_t p_etag = src.find(etag,start);\n" " size_t p_quote = src.find_first_of('\"',start);\n" " while (p_quote != std::string::npos && p_quote < p_etag) {\n" " p_quote = src.find_first_of('\"',p_quote+1);\n" " if (p_quote > p_etag) {\n" " p_etag = src.find(etag,p_quote+1);\n" " }\n" " p_quote = src.find_first_of('\"',p_quote+1);\n" " }\n" " if (p_etag == std::string::npos) {\n" " throw std::runtime_error(\"istream::getEndTag - bad header format\");\n" " }\n" " return p_etag + etag.size()+1;\n" " }\n" "}\n" "\n" "void istream::collide(const std::string &itag, const std::string &rtag) {\n" " std::string itagname = itag.substr(1,itag.find(\" \"));\n" " std::string rtagname = rtag.substr(1,rtag.find(\" \"));\n" " std::cerr << \"HDDM warning: \"\n" " << \"tag \" << itagname << \" in input file \"\n" " << \"does not match c++ header hddm_" << classPrefix << ".hpp\"\n" " << std::endl\n" " << \" input file: \" << itag << std::endl\n" " << \" c++ header: \" << rtag << std::endl\n" " << \" === Tag \" << itagname << \" will be ignored,\"\n" " << \" rebuild to cure the problem ===\"\n" " << std::endl;\n" "}\n" "\n" "chromosome istream::synthesize(const std::string &src, int p_src,\n" " const std::string &ref, int p_ref)\n" "{\n" " chromosome chrom;\n" " int slevel, rlevel;\n" " std::string stag, rtag;\n" " p_src = getTag(src,p_src,stag,slevel);\n" " p_ref = getTag(ref,p_ref,rtag,rlevel);\n" " std::string stagname = stag.substr(1,stag.find(\" \")-1);\n" " std::string rtagname = rtag.substr(1,rtag.find(\" \")-1);\n" " if (stagname != rtagname) {\n" " throw std::runtime_error(\"matching algorithm error #2\");\n" " }\n" " else if (stag != rtag) {\n" " collide(stag,rtag);\n" " return chrom;\n" " }\n" "\n" " int p2_src, p2_ref;\n" " int s2level, r2level;\n" " std::string s2tag, r2tag;\n" " getTag(src,p2_src=p_src,s2tag,s2level);\n" " while (s2level > slevel) {\n" " codon *gene = new codon();\n" " std::string s2tagname = s2tag.substr(1,s2tag.find(\" \")-1);\n" " getTag(ref,p2_ref=p_ref,r2tag,r2level);\n" " int order_of_this_tag_in_ref = 1;\n" " while (r2level == s2level) {\n" " std::string r2tagname = r2tag.substr(1,r2tag.find(\" \")-1);\n" " if (s2tagname == r2tagname) {\n" " if (s2tag != r2tag) {\n" " collide(s2tag,r2tag);\n" " break;\n" " }\n" " else {\n" " gene->m_order = order_of_this_tag_in_ref;\n" " }\n" " gene->m_sequence = synthesize(src,p2_src,ref,p2_ref);\n" " break;\n" " }\n" " p2_ref = getEndTag(ref,p2_ref,r2tag);\n" " getTag(ref,p2_ref,r2tag,r2level);\n" " ++order_of_this_tag_in_ref;\n" " }\n" " gene->m_tagname = s2tagname;\n" " chrom.push_back(*gene);\n" " delete gene;\n" " p2_src = getEndTag(src,p2_src,s2tag);\n" " getTag(src,p2_src,s2tag,s2level);\n" " }\n" " return chrom;\n" "}\n" ; XMLPlatformUtils::Terminate(); return 0; } XtString XtString::plural() { XtString p(*this); XtString::size_type len = p.size(); if (len > 3 && p.substr(len-3,3) == "tum") { p.replace(len-3,3,"ta"); } else if (len > 1 && p.substr(len-3,3) == "ies") { p.replace(len-3,3,"iesList"); } else if (len > 2 && p.substr(len-2,2) == "ex") { p.replace(len-2,2,"ices"); } else if (len > 2 && p.substr(len-2,2) == "sh") { p.replace(len-2,2,"shes"); } else if (len > 1 && p.substr(len-1,1) == "s") { p.replace(len-1,1,"ses"); } else if (len > 1) { p += "s"; } return p; } /* Map from tag name to name of the corresponding class * for the case of simple tags (those that do not repeat) */ XtString XtString::simpleType() { XtString p(*this); p[0] = toupper(p[0]); return p; } /* Map from tag name to name of the corresponding class * for the case of list tags (those that may repeat) */ XtString XtString::listType() { XtString r(*this); r[0] = toupper(r[0]); r = r + "List"; return r; } /* Map from tag name to name of the corresponding class * for the case of link tags (those that do not repeat) */ XtString XtString::linkType() { XtString r(*this); r[0] = toupper(r[0]); r = r + "Link"; return r; } /* Look for a named element in a list of element pointers * and return index of first instance in the list if found, * otherwise return -1; */ int CodeBuilder::element_in_list(XtString &name, parentList_t list) { int n; parentList_t::iterator iter; for (iter = list.begin(); iter != list.end(); ++iter, ++n) { DOMElement *el = (DOMElement*)(*iter); XtString cnameS(el->getTagName()); if (cnameS == name) { return n; } } return -1; } /* Verify that the tag group under this element does not collide * with existing tag group elref, otherwise exit with fatal error */ void CodeBuilder::checkConsistency(DOMElement* el, DOMElement* elref) { XtString tagS(el->getTagName()); if (el->getParentNode() == elref->getParentNode()) { std::cerr << "hddm-cpp error: tag " << "\"" << tagS << "\" is duplicated within one context in xml document." << std::endl; exit(1); } DOMNamedNodeMap* oldAttr = elref->getAttributes(); DOMNamedNodeMap* newAttr = el->getAttributes(); int listLength = oldAttr->getLength(); for (int n = 0; n < listLength; n++) { XtString nameS(oldAttr->item(n)->getNodeName()); XtString oldS(elref->getAttribute(X(nameS))); XtString newS(el->getAttribute(X(nameS))); if (nameS == "minOccurs") { continue; } else if (nameS == "maxOccurs") { int maxold = (oldS == "unbounded")? INT_MAX : atoi(S(oldS)); int maxnew = (newS == "unbounded")? INT_MAX : atoi(S(newS)); if (maxold < 2 && maxnew > 1 || maxold > 1 && maxnew < 2) { std::cerr << "hddm-cpp error: inconsistent maxOccurs usage by tag " << "\"" << tagS << "\" in xml document." << std::endl; exit(1); } } else if (newS != oldS) { std::cerr << "hddm-cpp error: inconsistent usage of attribute " << "\"" << nameS << "\" in tag " << "\"" << tagS << "\" in xml document." << std::endl; exit(1); } } listLength = newAttr->getLength(); for (int n = 0; n < listLength; n++) { XtString nameS(newAttr->item(n)->getNodeName()); XtString oldS(elref->getAttribute(X(nameS))); XtString newS(el->getAttribute(X(nameS))); if (nameS == "minOccurs") { continue; } else if (nameS == "maxOccurs") { int maxold = (oldS == "unbounded")? INT_MAX : atoi(S(oldS)); int maxnew = (newS == "unbounded")? INT_MAX : atoi(S(newS)); if (maxold < 2 && maxnew > 1 || maxold > 1 && maxnew < 2) { std::cerr << "hddm-cpp error: inconsistent maxOccurs usage by tag " << "\"" << tagS << "\" in xml document." << std::endl; exit(1); } } else if (newS != oldS) { std::cerr << "hddm-cpp error: inconsistent usage of attribute " << "\"" << nameS << "\" in tag " << "\"" << tagS << "\" in xml document." << std::endl; exit(1); } } DOMNodeList* oldList = elref->getChildNodes(); DOMNodeList* newList = el->getChildNodes(); listLength = oldList->getLength(); if (newList->getLength() != listLength) { std::cerr << "hddm-cpp error: inconsistent usage of tag " << "\"" << tagS << "\" in xml document." << std::endl; exit(1); } for (int n = 0; n < listLength; n++) { DOMNode* cont = oldList->item(n); XtString nameS(cont->getNodeName()); short type = cont->getNodeType(); if (type == DOMNode::ELEMENT_NODE) { DOMNodeList* contList = el->getElementsByTagName(X(nameS)); if (contList->getLength() != 1) { std::cerr << "hddm-cpp error: inconsistent usage of tag " << "\"" << tagS << "\" in xml document." << std::endl; exit(1); } } } } /* Write declaration of the classes for this tag to the header file */ void CodeBuilder::writeClassdef(DOMElement* el) { XtString tagS(el->getTagName()); hFile << "class " << tagS.simpleType() << ": public HDDM_Element {" << std::endl << " public:" << std::endl; if (tagS == "HDDM") { hFile << " HDDM();" << std::endl; } hFile << " ~" << tagS.simpleType() << "();" << std::endl; std::map attrList; DOMNamedNodeMap *myAttr = el->getAttributes(); for (int n = 0; n < myAttr->getLength(); n++) { XtString attrS(myAttr->item(n)->getNodeName()); XtString typeS(el->getAttribute(X(attrS))); attrList[attrS] = typeS; } parentList_t::iterator iter; for (iter = parents[tagS].begin(); iter != parents[tagS].end(); ++iter) { DOMElement *hostEl = (DOMElement*)(*iter); XtString hostS(hostEl->getTagName()); DOMNamedNodeMap *hostAttr = hostEl->getAttributes(); for (int n = 0; n < hostAttr->getLength(); n++) { XtString attrS(hostAttr->item(n)->getNodeName()); if (attrList.find(attrS) != attrList.end()) { continue; } XtString typeS(hostEl->getAttribute(X(attrS))); attrList[attrS] = typeS; XtString getS("get"+attrS.simpleType()); if (typeS == "int") { hFile << " int " << getS << "() const;" << std::endl; } else if (typeS == "long") { hFile << " int64_t " << getS << "() const;" << std::endl; } else if (typeS == "float") { hFile << " float " << getS << "() const;" << std::endl; } else if (typeS == "double") { hFile << " double " << getS << "() const;" << std::endl; } else if (typeS == "boolean") { hFile << " bool " << getS << "() const;" << std::endl; } else if (typeS == "string") { hFile << " const std::string &" << getS << "() const;" << std::endl; } else if (typeS == "anyURI") { hFile << " const std::string &" << getS << "() const;" << std::endl; } else if (typeS == "Particle_t") { hFile << " Particle_t " << getS << "() const;" << std::endl; } else { /* ignore attributes with unrecognized values */ } } } myAttr = el->getAttributes(); for (int n = 0; n < myAttr->getLength(); n++) { XtString attrS(myAttr->item(n)->getNodeName()); XtString typeS(el->getAttribute(X(attrS))); XtString getS("get" + attrS.simpleType()); XtString setS("set" + attrS.simpleType()); if (typeS == "int") { hFile << " int " << getS << "() const;" << std::endl << " void " << setS << "(int " << attrS << ");" << std::endl; } else if (typeS == "long") { hFile << " int64_t " << getS << "() const;" << std::endl << " void " << setS << "(int64_t " << attrS << ");" << std::endl; } else if (typeS == "float") { hFile << " float " << getS << "() const;" << std::endl << " void " << setS << "(float " << attrS << ");" << std::endl; } else if (typeS == "double") { hFile << " double " << getS << "() const;" << std::endl << " void " << setS << "(double " << attrS << ");" << std::endl; } else if (typeS == "boolean") { hFile << " bool " << getS << "() const;" << std::endl << " void " << setS << "(bool " << attrS << ");" << std::endl; } else if (typeS == "string") { hFile << " const std::string &" << getS << "() const;" << std::endl << " void " << setS << "(const std::string &" << attrS << ");" << std::endl; } else if (typeS == "anyURI") { hFile << " const std::string &" << getS << "() const;" << std::endl << " void " << setS << "(const std::string &" << attrS << ");" << std::endl; } else if (typeS == "Particle_t") { hFile << " Particle_t " << getS << "() const;" << std::endl << " void " << setS << "(Particle_t " << attrS << ");" << std::endl; } else { /* ignore attributes with unrecognized values */ } } if (tagS == "HDDM") { parentTable_t::iterator piter; for (piter = parents.begin(); piter != parents.end(); ++piter) { XtString cnameS(piter->first); if (cnameS != "HDDM" && element_in_list(cnameS,children[tagS]) == -1) { hFile << " " << cnameS.listType() << " get" << cnameS.plural().simpleType() << "();" << std::endl; } } } parentList_t::iterator citer; for (citer = children[tagS].begin(); citer != children[tagS].end(); ++citer) { DOMElement *childEl = (DOMElement*)(*citer); XtString cnameS(childEl->getTagName()); XtString repS(childEl->getAttribute(X("maxOccurs"))); int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS)); hFile << " " << cnameS.simpleType() << " &get" << cnameS.simpleType() << ((rep > 1)? "(int index=0);" : "();") << std::endl; hFile << " " << cnameS.listType() << " &get" << cnameS.plural().simpleType() << "();" << std::endl; hFile << " " << cnameS.listType() << " add" << cnameS.plural().simpleType() << "(int count=1, int start=-1);" << std::endl; hFile << " void delete" << cnameS.plural().simpleType() << "(int count=-1, int start=0);" << std::endl; } if (tagS == "HDDM") { hFile << " void clear();" << std::endl; parentTable_t::iterator piter; for (piter = parents.begin(); piter != parents.end(); ++piter) { XtString cnameS(piter->first); if (cnameS != "HDDM") { hFile << " friend class " << cnameS.simpleType() << ";" << std::endl; } } hFile << " private:" << std::endl; } else { hFile << " const void *getAttribute" << "(const std::string &name) const;" << std::endl; hFile << " friend class HDDM_ElementList<" << tagS.simpleType() << ">;" << std::endl << " friend class HDDM_ElementLink<" << tagS.simpleType() << ">;" << std::endl; hFile << " private:" << std::endl << " " << tagS.simpleType() << "(HDDM_Element *parent=0);" << std::endl; } hFile << " void streamer(istream &istr);" << std::endl << " void streamer(ostream &ostr);" << std::endl; for (int n = 0; n < myAttr->getLength(); n++) { XtString attrS(myAttr->item(n)->getNodeName()); XtString typeS(el->getAttribute(X(attrS))); if (typeS == "int") { hFile << " int m_" << attrS << ";" << std::endl; } else if (typeS == "long") { hFile << " int64_t m_" << attrS << ";" << std::endl; } else if (typeS == "float") { hFile << " float m_" << attrS << ";" << std::endl; } else if (typeS == "double") { hFile << " double m_" << attrS << ";" << std::endl; } else if (typeS == "boolean") { hFile << " int m_" << attrS << ";" << std::endl; } else if (typeS == "string") { hFile << " std::string m_" << attrS << ";" << std::endl; } else if (typeS == "anyURI") { hFile << " std::string m_" << attrS << ";" << std::endl; } else if (typeS == "Particle_t") { hFile << " int m_" << attrS << ";" << std::endl; } else { /* ignore attributes with unrecognized values */ } } if (tagS == "HDDM") { parentTable_t::iterator piter; for (piter = parents.begin(); piter != parents.end(); ++piter) { XtString dnameS(piter->first); if (dnameS != "HDDM") { hFile << " std::list<" << dnameS.simpleType() << "*> m_" << dnameS << "_plist;" << std::endl; } } } for (citer = children[tagS].begin(); citer != children[tagS].end(); ++citer) { DOMElement *childEl = (DOMElement*)(*citer); XtString cnameS(childEl->getTagName()); XtString repS(childEl->getAttribute(X("maxOccurs"))); int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS)); hFile << " " << ((rep > 1)? cnameS.listType() : cnameS.linkType()) << " m_" << cnameS << ((rep > 1)? "_list;" : "_link;") << std::endl; } hFile << "};" << std::endl << std::endl; if (tagS != "HDDM") { hFile << "typedef HDDM_ElementList<" << tagS.simpleType() << "> " << tagS.listType() << ";" << std::endl << "typedef HDDM_ElementLink<" << tagS.simpleType() << "> " << tagS.linkType() << ";" << std::endl << std::endl; } } /* Generate class declarations for this tag and its descendants; * this function calls itself recursively */ void CodeBuilder::constructGroup(DOMElement* el) { XtString tagS(el->getTagName()); parentList_t::iterator piter; parents[tagS].insert(parents[tagS].begin(), parentList.begin(),parentList.end()); std::vector::iterator iter; for (iter = tagList.begin(); iter != tagList.end(); iter++) { DOMElement* targEl = *iter; XtString targS(targEl->getTagName()); if (tagS == targS) { checkConsistency(el,targEl); return; } } parentList.push_back(el); DOMNodeList* contList = el->getChildNodes(); int contLength = contList->getLength(); for (int c = 0; c < contLength; c++) { DOMNode* cont = contList->item(c); short type = cont->getNodeType(); if (type == DOMNode::ELEMENT_NODE) { DOMElement* contEl = (DOMElement*) cont; XtString contS(contEl->getTagName()); children[tagS].push_back(contEl); constructGroup(contEl); } } parentList.pop_back(); tagList.push_back(el); if (tagS == "HDDM") { std::vector::iterator iter; for (iter = tagList.begin(); iter != tagList.end(); iter++) { writeClassdef(*iter); } } } /* Write method implementation of the classes for this tag to the header file */ void CodeBuilder::writeClassimp(DOMElement* el) { XtString tagS(el->getTagName()); if (tagS == "HDDM") { hFile << "inline " << tagS.simpleType() << "::" << tagS.simpleType() << "()" << std::endl << " : HDDM_Element()"; } else { hFile << "inline " << tagS.simpleType() << "::" << tagS.simpleType() << "(HDDM_Element *parent)" << std::endl << " : HDDM_Element(parent)"; } DOMNamedNodeMap *myAttr = el->getAttributes(); for (int n = 0; n < myAttr->getLength(); n++) { XtString attrS(myAttr->item(n)->getNodeName()); XtString typeS(el->getAttribute(X(attrS))); if (typeS == "int") { hFile << "," << std::endl << " m_" << attrS << "(0)"; } else if (typeS == "long") { hFile << "," << std::endl << " m_" << attrS << "(0)"; } else if (typeS == "float") { hFile << "," << std::endl << " m_" << attrS << "(0)"; } else if (typeS == "double") { hFile << "," << std::endl << " m_" << attrS << "(0)"; } else if (typeS == "boolean") { hFile << "," << std::endl << " m_" << attrS << "(0)"; } else if (typeS == "string") { hFile << "," << std::endl << " m_" << attrS << "(\"\")"; } else if (typeS == "anyURI") { hFile << "," << std::endl << " m_" << attrS << "(\"\")"; } else if (typeS == "Particle_t") { hFile << "," << std::endl << " m_" << attrS << "(0)"; } else { /* ignore attributes with unrecognized values */ } } parentList_t::iterator citer; for (citer = children[tagS].begin(); citer != children[tagS].end(); ++citer) { DOMElement *childEl = (DOMElement*)(*citer); XtString cnameS(childEl->getTagName()); XtString repS(childEl->getAttribute(X("maxOccurs"))); int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS)); XtString hostS("m_host->"); if (tagS == "HDDM") { hFile << "," << std::endl << " m_" << cnameS << "_plist()"; hostS = ""; } hFile << "," << std::endl << " m_" << cnameS << ((rep > 1)? "_list" : "_link") << "(&" << hostS << "m_" << cnameS << "_plist," << std::endl << " " << hostS << "m_" << cnameS << "_plist.end()," << std::endl << " " << hostS << "m_" << cnameS << "_plist.end()," << std::endl << " " << "this)"; } if (tagS == "HDDM") { hFile << std::endl << "{" << std::endl << " m_host = this;" << std::endl << "}" << std::endl << std::endl; } else { hFile << std::endl << "{}" << std::endl << std::endl; } hFile << "inline " << tagS.simpleType() << "::~" << tagS.simpleType() << "() {" << ((children[tagS].size())? "\n" : ""); for (citer = children[tagS].begin(); citer != children[tagS].end(); ++citer) { DOMElement *childEl = (DOMElement*)(*citer); XtString cnameS(childEl->getTagName()); hFile << " delete" << cnameS.plural().simpleType() << "();" << std::endl; } hFile << "}" << std::endl << std::endl; std::map attrList; myAttr = el->getAttributes(); for (int n = 0; n < myAttr->getLength(); n++) { XtString attrS(myAttr->item(n)->getNodeName()); XtString typeS(el->getAttribute(X(attrS))); attrList[attrS] = typeS; } parentList_t::iterator iter; for (iter = parents[tagS].begin(); iter != parents[tagS].end(); ++iter) { DOMElement *hostEl = (DOMElement*)(*iter); DOMNamedNodeMap *hostAttr = hostEl->getAttributes(); for (int n = 0; n < hostAttr->getLength(); n++) { XtString attrS(hostAttr->item(n)->getNodeName()); if (attrList.find(attrS) != attrList.end()) { continue; } XtString typeS(hostEl->getAttribute(X(attrS))); attrList[attrS] = typeS; XtString getS("get" + attrS.simpleType()); if (typeS == "int") { hFile << "inline int " << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return *(int*)m_parent->getAttribute(\"" << attrS << "\");" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "long") { hFile << "inline int64_t " << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return *(int64_t*)m_parent->getAttribute(\"" << attrS << "\");" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "float") { hFile << "inline float " << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return *(float*)m_parent->getAttribute(\"" << attrS << "\");" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "double") { hFile << "inline double " << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return *(double*)m_parent->getAttribute(\"" << attrS << "\");" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "boolean") { hFile << "inline bool " << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return *(bool*)m_parent->getAttribute(\"" << attrS << "\");" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "string") { hFile << "inline const std::string &" << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return *(const std::string*)m_parent->getAttribute(\"" << attrS << "\");" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "anyURI") { hFile << "inline const std::string &" << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return *(const std::string*)m_parent->getAttribute(\"" << attrS << "\");" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "Particle_t") { hFile << "inline Particle_t " << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return *(Particle_t*)m_parent->getAttribute(\"" << attrS << "\");" << std::endl << "}" << std::endl << std::endl; } else { /* ignore attributes with unrecognized values */ } } } for (int n = 0; n < myAttr->getLength(); n++) { XtString attrS(myAttr->item(n)->getNodeName()); XtString typeS(el->getAttribute(X(attrS))); XtString getS("get" + attrS.simpleType()); XtString setS("set" + attrS.simpleType()); if (typeS == "int") { hFile << "inline int " << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return m_" << attrS << ";" << std::endl << "}" << std::endl << std::endl << "inline void " << tagS.simpleType() << "::" << setS << "(int " << attrS << ") {" << std::endl << " m_" << attrS << " = " << attrS << ";" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "long") { hFile << "inline int64_t " << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return m_" << attrS << ";" << std::endl << "}" << std::endl << std::endl << "inline void " << tagS.simpleType() << "::" << setS << "(int64_t " << attrS << ") {" << std::endl << " m_" << attrS << " = " << attrS << ";" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "float") { hFile << "inline float " << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return m_" << attrS << ";" << std::endl << "}" << std::endl << std::endl << "inline void " << tagS.simpleType() << "::" << setS << "(float " << attrS << ") {" << std::endl << " m_" << attrS << " = " << attrS << ";" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "double") { hFile << "inline double " << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return m_" << attrS << ";" << std::endl << "}" << std::endl << std::endl << "inline void " << tagS.simpleType() << "::" << setS << "(double " << attrS << ") {" << std::endl << " m_" << attrS << " = " << attrS << ";" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "boolean") { hFile << "inline bool " << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return m_" << attrS << ";" << std::endl << "}" << std::endl << std::endl << "inline void " << tagS.simpleType() << "::" << setS << "(bool " << attrS << ") {" << std::endl << " m_" << attrS << " = " << attrS << ";" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "string") { hFile << "inline const std::string &" << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return m_" << attrS << ";" << std::endl << "}" << std::endl << std::endl << "inline void " << tagS.simpleType() << "::" << setS << "(const std::string &" << attrS << ") {" << std::endl << " m_" << attrS << " = " << attrS << ";" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "anyURI") { hFile << "inline const std::string &" << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return m_" << attrS << ";" << std::endl << "}" << std::endl << std::endl << "inline void " << tagS.simpleType() << "::" << setS << "(const std::string &" << attrS << ") {" << std::endl << " m_" << attrS << " = " << attrS << ";" << std::endl << "}" << std::endl << std::endl; } else if (typeS == "Particle_t") { hFile << "inline Particle_t " << tagS.simpleType() << "::" << getS << "() const {" << std::endl << " return (Particle_t)m_" << attrS << ";" << std::endl << "}" << std::endl << std::endl << "inline void " << tagS.simpleType() << "::" << setS << "(Particle_t " << attrS << ") {" << std::endl << " m_" << attrS << " = " << attrS << ";" << std::endl << "}" << std::endl << std::endl; } else { /* ignore attributes with unrecognized values */ } } if (tagS == "HDDM") { hFile << "inline void HDDM::clear() {" << std::endl; for (citer = children[tagS].begin(); citer != children[tagS].end(); ++citer) { DOMElement *childEl = (DOMElement*)(*citer); XtString cnameS(childEl->getTagName()); hFile << " delete" << cnameS.simpleType().plural() << "();" << std::endl; } hFile << "}" << std::endl << std::endl; } else { hFile << "inline const void *" << tagS.simpleType() << "::getAttribute(const std::string &name) const {" << std::endl << " return "; for (int n = 0; n < myAttr->getLength(); n++) { XtString attrS(myAttr->item(n)->getNodeName()); XtString typeS(el->getAttribute(X(attrS))); if (typeS == "int" || typeS == "long" || typeS == "float" || typeS == "double" || typeS == "boolean" || typeS == "string" || typeS == "anyURI" || typeS == "Particle_t") { hFile << "(name == \"" << attrS << "\")? &m_" << attrS << ":" << std::endl << " "; } } hFile << "m_parent->getAttribute(name);" << std::endl << "}" << std::endl << std::endl; } for (citer = children[tagS].begin(); citer != children[tagS].end(); ++citer) { DOMElement *childEl = (DOMElement*)(*citer); XtString cnameS(childEl->getTagName()); XtString repS(childEl->getAttribute(X("maxOccurs"))); int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS)); if (rep > 1) { hFile << "inline " << cnameS.simpleType() << " &" << tagS.simpleType() << "::get" << cnameS.simpleType() << "(int index) {" << std::endl << " return m_" << cnameS << "_list(index);" << std::endl << "}" << std::endl << std::endl << "inline " << cnameS.listType() << " &" << tagS.simpleType() << "::get" << cnameS.plural().simpleType() << "() {" << std::endl << " return m_" << cnameS << "_list;" << std::endl << "}" << std::endl << std::endl << "inline " << cnameS.listType() << " " << tagS.simpleType() << "::add" << cnameS.plural().simpleType() << "(int count, int start) {" << std::endl << " return m_" << cnameS << "_list.add(count,start);" << std::endl << "}" << std::endl << std::endl << "inline void " << tagS.simpleType() << "::delete" << cnameS.simpleType().plural() << "(int count, int start) {" << std::endl << " m_" << cnameS << "_list.del(count,start);" << std::endl << "}" << std::endl << std::endl; } else { hFile << "inline " << cnameS.simpleType() << " &" << tagS.simpleType() << "::get" << cnameS.simpleType() << "() {" << std::endl << " return m_" << cnameS << "_link.front();" << std::endl << "}" << std::endl << std::endl << "inline " << cnameS.listType() << " &" << tagS.simpleType() << "::get" << cnameS.plural().simpleType() << "() {" << std::endl << " return m_" << cnameS << "_link;" << std::endl << "}" << std::endl << std::endl << "inline " << cnameS.listType() << " " << tagS.simpleType() << "::add" << cnameS.plural().simpleType() << "(int count, int start) {" << std::endl << " return m_" << cnameS << "_link.add(count,start);" << std::endl << "}" << std::endl << std::endl << "inline void " << tagS.simpleType() << "::delete" << cnameS.simpleType().plural() << "(int count, int start) {" << std::endl << " m_" << cnameS << "_link.del(count,start);" << std::endl << "}" << std::endl << std::endl; } } if (tagS == "HDDM") { parentTable_t::iterator piter; for (piter = parents.begin(); piter != parents.end(); ++piter) { XtString cnameS(piter->first); if (cnameS != "HDDM" && element_in_list(cnameS,children[tagS]) == -1) { hFile << "inline " << cnameS.listType() << " " << "HDDM::get" << cnameS.plural().simpleType() << "() {" << std::endl << " return " << cnameS.listType() << "(&m_" << cnameS << "_plist," << std::endl << " " << "m_" << cnameS << "_plist.begin()," << std::endl << " " << "m_" << cnameS << "_plist.end());" << std::endl << "}" << std::endl << std::endl; } } } } /* Generate implementation code for data model classes */ void CodeBuilder::constructMethods(DOMElement* el) { std::vector::iterator iter; for (iter = tagList.begin(); iter != tagList.end(); iter++) { writeClassimp(*iter); } } /* Generate methods for serializing classes to a stream and back again */ void CodeBuilder::writeStreamers(DOMElement* el) { XtString tagS(el->getTagName()); std::vector attrV; DOMNamedNodeMap *myAttr = el->getAttributes(); for (int n = 0; n < myAttr->getLength(); n++) { XtString attrS(myAttr->item(n)->getNodeName()); XtString typeS(el->getAttribute(X(attrS))); if (typeS == "int" || typeS == "long" || typeS == "float" || typeS == "double" || typeS == "boolean" || typeS == "string" || typeS == "anyURI" || typeS == "Particle_t") { attrV.push_back(attrS); } } std::vector contV; DOMNodeList* contList = el->getChildNodes(); int contListLength = contList->getLength(); for (int c = 0; c < contListLength; c++) { DOMNode* node = contList->item(c); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { DOMElement *contEl = (DOMElement*)node; XtString contS(contEl->getTagName()); XtString repS(contEl->getAttribute(X("maxOccurs"))); int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS)); contV.push_back(contS + ((rep > 1)? "_list" : "_link")); } } hFile << "inline void " << tagS.simpleType() << "::streamer" << "(istream &istr) {" << std::endl; if (attrV.size()) { hFile << " *istr.m_xstr"; for (int n=0; n < attrV.size(); ++n) { hFile << " >> m_" << attrV[n]; } hFile << ";" << std::endl; } if (contV.size()) { hFile << " istr"; for (int n=0; n < contV.size(); ++n) { hFile << " >> m_" << contV[n]; } hFile << ";" << std::endl; } hFile << "}" << std::endl << std::endl; hFile << "inline void " << tagS.simpleType() << "::streamer" << "(ostream &ostr) {" << std::endl; if (attrV.size()) { hFile << " *ostr.m_xstr"; for (int n=0; n < attrV.size(); ++n) { hFile << " << m_" << attrV[n]; } hFile << ";" << std::endl; } if (contV.size()) { hFile << " ostr"; for (int n=0; n < contV.size(); ++n) { hFile << " << m_" << contV[n]; } hFile << ";" << std::endl; } hFile << "}" << std::endl << std::endl; } void CodeBuilder::constructStreamers(DOMElement* el) { std::vector::iterator iter; for (iter = tagList.begin(); iter != tagList.end(); ++iter) { writeStreamers(*iter); } } /* Generate methods to read from binary stream into classes */ void CodeBuilder::constructIOstreams(DOMElement* el) { hFile << "inline void istream::skip(int count) {\n" " m_events_to_skip = count;\n" "}\n" "\n" "inline int istream::getCompression() const {\n" " return m_status_bits & k_bits_compression;\n" "}\n" "\n" "inline int ostream::getCompression() const {\n" " return m_status_bits & k_bits_compression;\n" "}\n" "\n" "inline istream &istream::operator>>(streamable &object) {\n" " if (m_sequencing) {\n" " m_codon->m_target.push_back(&object);\n" " }\n" " else {\n" " int size;\n" " *m_xstr >> size;\n" " if (size > 0) {\n" " std::streampos start = m_sstr.tellg();\n" " sequencer(object);\n" " m_sstr.seekg(start+(std::streamoff)size);\n" " }\n" " }\n" " return *this;\n" "}\n" "\n" "inline void istream::sequencer(streamable &object) {\n" " m_sequencing = 1;\n" " m_codon->m_target.clear();\n" " object.streamer(*this);\n" " if (m_sequencing) {\n" " m_sequencing = 0;\n" " codon &gene = *m_codon;\n" " streamable null_streamable;\n" " gene.m_target.push_front(&null_streamable);\n" " chromosome::iterator iter;\n" " for (iter = gene.m_sequence.begin();\n" " iter != gene.m_sequence.end();\n" " ++iter)\n" " {\n" " m_codon = &(*iter);\n" " *this >> *gene.m_target[iter->m_order];\n" " }\n" " m_codon = &gene;\n" " }\n" "}\n" "\n" "inline ostream &ostream::operator<<(HDDM &record) {\n" " m_sstr.str(\"\");\n" " *this << (streamable&)record;\n" " m_ostr << m_sstr.str();\n" " return *this;\n" "}\n" "\n" "inline ostream &ostream::operator<<(streamable &object) {\n" " *m_xstr << 0;\n" " std::streampos start = m_sstr.tellp();\n" " object.streamer(*this);\n" " std::streampos end = m_sstr.tellp();\n" " m_sstr.seekp(start-std::streamoff(4));\n" " *m_xstr << (int)(end-start);\n" " m_sstr.seekp(end);\n" " return *this;\n" "}\n\n" ; } /* Generate the xml template in normal form and store in a string */ void CodeBuilder::constructDocument(DOMElement* el) { static int indent = 0; cFile << "\""; for (int n = 0; n < indent; n++) { cFile << " "; } XtString tagS(el->getTagName()); cFile << "<" << tagS; DOMNamedNodeMap* attrList = el->getAttributes(); int attrListLength = attrList->getLength(); for (int a = 0; a < attrListLength; a++) { DOMNode* node = attrList->item(a); XtString nameS(node->getNodeName()); XtString valueS(node->getNodeValue()); cFile << " " << nameS << "=\\\"" << valueS << "\\\""; } DOMNodeList* contList = el->getChildNodes(); int contListLength = contList->getLength(); if (contListLength > 0) { cFile << ">\\n\"" << std::endl; indent++; for (int c = 0; c < contListLength; c++) { DOMNode* node = contList->item(c); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { DOMElement* contEl = (DOMElement*) node; constructDocument(contEl); } } indent--; cFile << "\""; for (int n = 0; n < indent; n++) { cFile << " "; } cFile << "\\n\"" << std::endl; } else { cFile << " />\\n\"" << std::endl; } }