/piklab-0.15.12/src/xml_to_data/prog_xml_to_data.h

# · C Header · 218 lines · 187 code · 18 blank · 13 comment · 25 complexity · 12c1ca0508683aeab691922cdcdaf3db MD5 · raw file

  1. /***************************************************************************
  2. * Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
  3. * *
  4. * This program is free software; you can redistribute it and/or modify *
  5. * it under the terms of the GNU General Public License as published by *
  6. * the Free Software Foundation; either version 2 of the License, or *
  7. * (at your option) any later version. *
  8. ***************************************************************************/
  9. #ifndef PROG_XML_TO_DATA_H
  10. #define PROG_XML_TO_DATA_H
  11. #include <qfile.h>
  12. #include <qtextstream.h>
  13. #include <qmap.h>
  14. #include "xml_to_data.h"
  15. #include "devices/list/device_list.h"
  16. //----------------------------------------------------------------------------
  17. template <class Data>
  18. class ExtXmlToData : public ::XmlToData
  19. {
  20. public:
  21. ExtXmlToData(const QString &basename, const QString &namespac)
  22. : _basename(basename), _namespace(namespac) {}
  23. protected:
  24. QString _basename, _namespace;
  25. virtual bool hasFamilies() const { return true; }
  26. const QStringList &families() const { return _families; }
  27. virtual uint familyIndex(const QString &family) const { return _families.findIndex(family); }
  28. virtual void parseData(QDomElement, Data &) = 0;
  29. virtual void includes(QTextStream &) const {}
  30. virtual void outputData(const Data &, QTextStream &) const {}
  31. virtual void outputFunctions(QTextStream &) const {}
  32. virtual QString currentDevice() const { return _current; }
  33. virtual void parseDevice(QDomElement element);
  34. ::Group::Support extractSupport(const QString &s) const;
  35. bool hasDevice(const QString &device) const { return _map.contains(device); }
  36. virtual void parse();
  37. protected:
  38. QString _current;
  39. class PData {
  40. public:
  41. uint family;
  42. ::Group::Support support;
  43. Data data;
  44. };
  45. QMap<QString, PData> _map;
  46. QStringList _families;
  47. virtual void output();
  48. };
  49. template <class Data>
  50. Group::Support ExtXmlToData<Data>::extractSupport(const QString &s) const
  51. {
  52. if ( s.isEmpty() ) return Group::Support::Untested;
  53. Group::Support support = Group::Support::fromKey(s);
  54. if ( support==Group::Support::None ) qFatal("Cannot be \"not supported\"");
  55. if ( support==Group::Support::Nb_Types ) qFatal("Unknown support type");
  56. return support;
  57. }
  58. template <class Data>
  59. void ExtXmlToData<Data>::parseDevice(QDomElement element)
  60. {
  61. if (element.nodeName() != "device") qFatal("Root node child should be named \"device\"");
  62. _current = element.attribute("name").upper();
  63. if (Device::Lister::instance().data(_current) == NULL) qFatal(QString("Device name \"%1\" unknown").arg(_current));
  64. if (_map.contains(_current)) qFatal(QString("Device \"%1\" already parsed").arg(_current));
  65. PData data;
  66. if (hasFamilies()) {
  67. QString family = element.attribute("family");
  68. if (family.isEmpty()) qFatal(QString("Family is empty").arg(family));
  69. if (_families.find(family) == _families.end()) _families.append(family);
  70. data.family = familyIndex(family);
  71. }
  72. data.support = extractSupport(element.attribute("support_type"));
  73. parseData(element, data.data);
  74. _map[_current] = data;
  75. }
  76. template <class Data>
  77. void ExtXmlToData<Data>::parse()
  78. {
  79. QDomDocument doc = parseFile(_basename + ".xml");
  80. QDomElement root = doc.documentElement();
  81. if ( root.nodeName()!="type" ) qFatal("Root node should be \"type\"");
  82. if ( root.attribute("name")!=_basename ) qFatal(QString("Root node name is not \"%1\"").arg(_basename));
  83. QDomNode child = root.firstChild();
  84. while ( !child.isNull() ) {
  85. if ( child.isComment() ) qDebug("comment: %s", child.toComment().data().latin1());
  86. else {
  87. if ( !child.isElement() ) qFatal("Root node child should be an element");
  88. parseDevice(child.toElement());
  89. }
  90. child = child.nextSibling();
  91. }
  92. }
  93. template <class Data>
  94. void ExtXmlToData<Data>::output()
  95. {
  96. // write .cpp file
  97. QFile file(_basename + "_data.cpp");
  98. if ( !file.open(IO_WriteOnly) ) qFatal(QString("Cannot open output file \"%1\"").arg(file.name()));
  99. QTextStream s(&file);
  100. s << "// #### Do not edit: this file is autogenerated !!!" << endl << endl;
  101. s << "#include \"devices/list/device_list.h\"" << endl;
  102. s << "#include \"" + _basename + ".h\"" << endl;
  103. s << "#include \"" + _basename + "_data.h\"" << endl;
  104. includes(s);
  105. s << endl;
  106. s << "namespace " << _namespace << endl;
  107. s << "{" << endl;
  108. s << "struct CData {" << endl;
  109. s << " const char *name;" << endl;
  110. if ( hasFamilies() ) s << " uint family;" << endl;
  111. s << " uint support;" << endl;
  112. s << " Data data;" << endl;
  113. s << "};" << endl;
  114. s << endl;
  115. // data list
  116. typename QMap<QString, PData>::const_iterator it = _map.begin();
  117. for (; it!=_map.end(); ++it) {
  118. s << "const CData PIC" << it.key() << "_DATA = {";
  119. s << " \"" << it.key() << "\", ";
  120. if ( hasFamilies() ) s << it.data().family << ", ";
  121. s << it.data().support.type() << ", ";
  122. s << "{ ";
  123. outputData(it.data().data, s);
  124. s << " }";
  125. s << " };" << endl;
  126. }
  127. s << endl;
  128. s << "const CData *DATA_LIST[] = {" << endl;
  129. uint i = 0;
  130. it = _map.begin();
  131. for (; it!=_map.end(); ++it) {
  132. s << "&PIC" << it.key() << "_DATA,";
  133. i++;
  134. if ( (i%10)==0 ) s << endl;
  135. }
  136. s << "0 " << endl;
  137. s << "};" << endl;
  138. // functions
  139. s << endl;
  140. s << "const CData *cdata(const QString &device)" << endl;
  141. s << "{" << endl;
  142. s << " for(uint i=0; DATA_LIST[i]; i++)" << endl;
  143. s << " if ( device==DATA_LIST[i]->name ) return DATA_LIST[i];" << endl;
  144. s << " return 0;" << endl;
  145. s << "}" << endl;
  146. s << "bool isSupported(const QString &device)" << endl;
  147. s << "{" << endl;
  148. s << " return cdata(device);" << endl;
  149. s << "}" << endl;
  150. if ( hasFamilies() ) {
  151. s << "uint family(const QString &device)" << endl;
  152. s << "{" << endl;
  153. s << " return cdata(device)->family;" << endl;
  154. s << "}" << endl;
  155. }
  156. s << "::Group::Support support(const QString &device)" << endl;
  157. s << "{" << endl;
  158. s << " return ::Group::Support::Type(cdata(device)->support);" << endl;
  159. s << "}" << endl;
  160. s << "const Data &data(const QString &device)" << endl;
  161. s << "{" << endl;
  162. s << " return cdata(device)->data;" << endl;
  163. s << "}" << endl;
  164. s << endl;
  165. outputFunctions(s);
  166. s << endl;
  167. s << "}" << endl;
  168. }
  169. //----------------------------------------------------------------------------
  170. namespace Programmer
  171. {
  172. template <class Data>
  173. class XmlToData : public ExtXmlToData<Data>
  174. {
  175. public:
  176. XmlToData(const QString &basename, const QString &namespac)
  177. : ExtXmlToData<Data>(basename, namespac) {}
  178. protected:
  179. virtual void outputFunctions(QTextStream &s) const;
  180. virtual void includes(QTextStream &) const;
  181. };
  182. template <class Data>
  183. void Programmer::XmlToData<Data>::outputFunctions(QTextStream &s) const
  184. {
  185. s << "void Group::initSupported()" << endl;
  186. s << "{" << endl;
  187. s << " for (uint i=0; DATA_LIST[i]; i++) {" << endl;
  188. s << " const Device::Data *data = Device::Lister::instance().data(DATA_LIST[i]->name);" << endl;
  189. s << " addDevice(data->name(), data, ::Group::Support::Type(DATA_LIST[i]->support));" << endl;
  190. s << " }" << endl;
  191. s << "}" << endl;
  192. s << endl;
  193. }
  194. template <class Data>
  195. void Programmer::XmlToData<Data>::includes(QTextStream &s) const
  196. {
  197. s << "#include \"" << ExtXmlToData<Data>::_basename << "_prog.h\"" << endl;
  198. }
  199. } // namespace
  200. #endif