diff options
Diffstat (limited to 'src/xml_to_data/prog_xml_to_data.h')
-rw-r--r-- | src/xml_to_data/prog_xml_to_data.h | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/src/xml_to_data/prog_xml_to_data.h b/src/xml_to_data/prog_xml_to_data.h new file mode 100644 index 0000000..f4e820b --- /dev/null +++ b/src/xml_to_data/prog_xml_to_data.h @@ -0,0 +1,218 @@ +/*************************************************************************** + * Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef PROG_XML_TO_DATA_H +#define PROG_XML_TO_DATA_H + +#include <qfile.h> +#include <qtextstream.h> +#include <qmap.h> + +#include "xml_to_data.h" +#include "devices/list/device_list.h" + +//---------------------------------------------------------------------------- +template <class Data> +class ExtXmlToData : public ::XmlToData +{ +public: + ExtXmlToData(const QString &basename, const QString &namespac) + : _basename(basename), _namespace(namespac) {} + +protected: + QString _basename, _namespace; + virtual bool hasFamilies() const { return true; } + const QStringList &families() const { return _families; } + virtual uint familyIndex(const QString &family) const { return _families.findIndex(family); } + virtual void parseData(QDomElement, Data &) = 0; + virtual void includes(QTextStream &) const {} + virtual void outputData(const Data &, QTextStream &) const {} + virtual void outputFunctions(QTextStream &) const {} + virtual QString currentDevice() const { return _current; } + virtual void parseDevice(QDomElement element); + ::Group::Support extractSupport(const QString &s) const; + bool hasDevice(const QString &device) const { return _map.contains(device); } + virtual void parse(); + +protected: + QString _current; + class PData { + public: + uint family; + ::Group::Support support; + Data data; + }; + QMap<QString, PData> _map; + QStringList _families; + + virtual void output(); +}; + +template <class Data> +Group::Support ExtXmlToData<Data>::extractSupport(const QString &s) const +{ + if ( s.isEmpty() ) return Group::Support::Untested; + Group::Support support = Group::Support::fromKey(s); + if ( support==Group::Support::None ) qFatal("Cannot be \"not supported\""); + if ( support==Group::Support::Nb_Types ) qFatal("Unknown support type"); + return support; +} + +template <class Data> +void ExtXmlToData<Data>::parseDevice(QDomElement element) +{ + if ( element.nodeName()!="device" ) qFatal("Root node child should be named \"device\""); + _current = element.attribute("name").upper(); + if ( Device::lister().data(_current)==0 ) qFatal(QString("Device name \"%1\" unknown").arg(_current)); + if ( _map.contains(_current) ) qFatal(QString("Device \"%1\" already parsed").arg(_current)); + PData data; + if ( hasFamilies() ) { + QString family = element.attribute("family"); + if ( family.isEmpty() ) qFatal(QString("Family is empty").arg(family)); + if ( _families.find(family)==_families.end() ) _families.append(family); + data.family = familyIndex(family); + } + data.support = extractSupport(element.attribute("support_type")); + parseData(element, data.data); + _map[_current] = data; +} + +template <class Data> +void ExtXmlToData<Data>::parse() +{ + QDomDocument doc = parseFile(_basename + ".xml"); + QDomElement root = doc.documentElement(); + if ( root.nodeName()!="type" ) qFatal("Root node should be \"type\""); + if ( root.attribute("name")!=_basename ) qFatal(QString("Root node name is not \"%1\"").arg(_basename)); + QDomNode child = root.firstChild(); + while ( !child.isNull() ) { + if ( child.isComment() ) qDebug("comment: %s", child.toComment().data().latin1()); + else { + if ( !child.isElement() ) qFatal("Root node child should be an element"); + parseDevice(child.toElement()); + } + child = child.nextSibling(); + } +} + +template <class Data> +void ExtXmlToData<Data>::output() +{ + // write .cpp file + QFile file(_basename + "_data.cpp"); + if ( !file.open(IO_WriteOnly) ) qFatal(QString("Cannot open output file \"%1\"").arg(file.name())); + QTextStream s(&file); + s << "// #### Do not edit: this file is autogenerated !!!" << endl << endl; + s << "#include \"devices/list/device_list.h\"" << endl; + s << "#include \"" + _basename + ".h\"" << endl; + s << "#include \"" + _basename + "_data.h\"" << endl; + includes(s); + s << endl; + s << "namespace " << _namespace << endl; + s << "{" << endl; + s << "struct CData {" << endl; + s << " const char *name;" << endl; + if ( hasFamilies() ) s << " uint family;" << endl; + s << " uint support;" << endl; + s << " Data data;" << endl; + s << "};" << endl; + s << endl; + + // data list + typename QMap<QString, PData>::const_iterator it = _map.begin(); + for (; it!=_map.end(); ++it) { + s << "const CData PIC" << it.key() << "_DATA = {"; + s << " \"" << it.key() << "\", "; + if ( hasFamilies() ) s << it.data().family << ", "; + s << it.data().support.type() << ", "; + s << "{ "; + outputData(it.data().data, s); + s << " }"; + s << " };" << endl; + } + s << endl; + s << "const CData *DATA_LIST[] = {" << endl; + uint i = 0; + it = _map.begin(); + for (; it!=_map.end(); ++it) { + s << "&PIC" << it.key() << "_DATA,"; + i++; + if ( (i%10)==0 ) s << endl; + } + s << "0 " << endl; + s << "};" << endl; + + // functions + s << endl; + s << "const CData *cdata(const QString &device)" << endl; + s << "{" << endl; + s << " for(uint i=0; DATA_LIST[i]; i++)" << endl; + s << " if ( device==DATA_LIST[i]->name ) return DATA_LIST[i];" << endl; + s << " return 0;" << endl; + s << "}" << endl; + s << "bool isSupported(const QString &device)" << endl; + s << "{" << endl; + s << " return cdata(device);" << endl; + s << "}" << endl; + if ( hasFamilies() ) { + s << "uint family(const QString &device)" << endl; + s << "{" << endl; + s << " return cdata(device)->family;" << endl; + s << "}" << endl; + } + s << "::Group::Support support(const QString &device)" << endl; + s << "{" << endl; + s << " return ::Group::Support::Type(cdata(device)->support);" << endl; + s << "}" << endl; + s << "const Data &data(const QString &device)" << endl; + s << "{" << endl; + s << " return cdata(device)->data;" << endl; + s << "}" << endl; + s << endl; + outputFunctions(s); + s << endl; + s << "}" << endl; +} + +//---------------------------------------------------------------------------- +namespace Programmer +{ +template <class Data> +class XmlToData : public ExtXmlToData<Data> +{ +public: + XmlToData(const QString &basename, const QString &namespac) + : ExtXmlToData<Data>(basename, namespac) {} + +protected: + virtual void outputFunctions(QTextStream &s) const; + virtual void includes(QTextStream &) const; +}; + +template <class Data> +void Programmer::XmlToData<Data>::outputFunctions(QTextStream &s) const +{ + s << "void Group::initSupported()" << endl; + s << "{" << endl; + s << " for (uint i=0; DATA_LIST[i]; i++) {" << endl; + s << " const Device::Data *data = Device::lister().data(DATA_LIST[i]->name);" << endl; + s << " addDevice(data->name(), data, ::Group::Support::Type(DATA_LIST[i]->support));" << endl; + s << " }" << endl; + s << "}" << endl; + s << endl; +} + +template <class Data> +void Programmer::XmlToData<Data>::includes(QTextStream &s) const +{ + s << "#include \"" << ExtXmlToData<Data>::_basename << "_prog.h\"" << endl; +} + +} // namespace + +#endif |