Go to the documentation of this file.00001 #include "export.hh"
00002 #include <iostream>
00003
00004 #include <typelib/typevisitor.hh>
00005
00006 namespace
00007 {
00008 using namespace std;
00009 using namespace Typelib;
00010 class TlbExportVisitor : public TypeVisitor
00011 {
00012 ostream& m_stream;
00013 string m_indent;
00014 string m_source_id;
00015 string emitSourceID() const;
00016 string emitMetaData(Type const& type) const;
00017 string emitMetaData(MetaData const& metadata) const;
00018
00019 protected:
00020 bool visit_(Compound const& type);
00021 bool visit_(Compound const& type, Field const& field);
00022
00023 bool visit_(Numeric const& type);
00024
00025 bool visit_(Pointer const& type);
00026 bool visit_(Array const& type);
00027
00028 bool visit_(Enum const& type);
00029
00030 bool visit_(NullType const& type);
00031 bool visit_(OpaqueType const& type);
00032 bool visit_(Container const& type);
00033
00034 public:
00035 TlbExportVisitor(ostream& stream, string const& base_indent, std::string const& source_id);
00036 };
00037
00038 struct Indent
00039 {
00040 string& m_indent;
00041 string m_save;
00042 Indent(string& current)
00043 : m_indent(current), m_save(current)
00044 { m_indent += " "; }
00045 ~Indent() { m_indent = m_save; }
00046 };
00047
00048 TlbExportVisitor::TlbExportVisitor(ostream& stream, string const& base_indent, std::string const& source_id)
00049 : m_stream(stream), m_indent(base_indent), m_source_id(source_id) {}
00050
00051 std::string xmlEscape(std::string const& source)
00052 {
00053 string result = source;
00054 size_t pos = result.find_first_of("<>");
00055 while (pos != string::npos)
00056 {
00057 if (result[pos] == '<')
00058 result.replace(pos, 1, "<");
00059 else if (result[pos] == '>')
00060 result.replace(pos, 1, ">");
00061 pos = result.find_first_of("<>");
00062 }
00063
00064 return result;
00065 }
00066
00067 std::string TlbExportVisitor::emitMetaData(Type const& type) const
00068 {
00069 return emitMetaData(type.getMetaData());
00070 }
00071 std::string TlbExportVisitor::emitMetaData(MetaData const& metadata) const
00072 {
00073 std::ostringstream stream;
00074 MetaData::Map const& map = metadata.get();
00075 for (MetaData::Map::const_iterator it = map.begin(); it != map.end(); ++it)
00076 {
00077 std::string key = it->first;
00078 MetaData::Values values = it->second;
00079 for (MetaData::Values::const_iterator it_value = values.begin(); it_value != values.end(); ++it_value)
00080 stream << "<metadata key=\"" << key << "\"><![CDATA[" << *it_value << "]]></metadata>\n";
00081 }
00082 return stream.str();
00083 }
00084
00085 std::string TlbExportVisitor::emitSourceID() const
00086 {
00087 if (!m_source_id.empty())
00088 return "source_id=\"" + xmlEscape(m_source_id) + "\"";
00089 else return std::string();
00090 }
00091
00092 bool TlbExportVisitor::visit_(OpaqueType const& type)
00093 {
00094 m_stream << "<opaque name=\"" << xmlEscape(type.getName()) << "\" size=\"" << type.getSize() << "\" " << emitSourceID() << ">\n";
00095 m_stream << m_indent << emitMetaData(type) << "\n";
00096 m_stream << m_indent << "</opaque>";
00097 return true;
00098 }
00099
00100 bool TlbExportVisitor::visit_(Compound const& type)
00101 {
00102 m_stream << "<compound name=\"" << xmlEscape(type.getName()) << "\" size=\"" << type.getSize() << "\" " << emitSourceID() << ">\n";
00103
00104 { Indent indenter(m_indent);
00105 TypeVisitor::visit_(type);
00106 }
00107
00108 m_stream << m_indent << emitMetaData(type) << "\n";
00109 m_stream << m_indent << "</compound>";
00110
00111 return true;
00112 }
00113 bool TlbExportVisitor::visit_(Compound const& type, Field const& field)
00114 {
00115 m_stream
00116 << m_indent
00117 << "<field name=\"" << field.getName() << "\""
00118 << " type=\"" << xmlEscape(field.getType().getName()) << "\""
00119 << " offset=\"" << field.getOffset() << "\">\n";
00120 m_stream << m_indent << emitMetaData(field.getMetaData()) << "\n";
00121 m_stream << m_indent << "</field>\n";
00122 return true;
00123 }
00124
00125 namespace
00126 {
00127 char const* getStringCategory(Numeric::NumericCategory category)
00128 {
00129 switch(category)
00130 {
00131 case Numeric::SInt:
00132 return "sint";
00133 case Numeric::UInt:
00134 return "uint";
00135 case Numeric::Float:
00136 return "float";
00137 default:
00138 throw "invalid category";
00139 }
00140 }
00141 }
00142
00143 bool TlbExportVisitor::visit_(Numeric const& type)
00144 {
00145 m_stream
00146 << "<numeric name=\"" << type.getName() << "\" "
00147 << "category=\"" << getStringCategory(type.getNumericCategory()) << "\" "
00148 << "size=\"" << type.getSize() << "\" " << emitSourceID() << ">\n";
00149 m_stream << m_indent << emitMetaData(type) << "\n";
00150 m_stream << m_indent << "</numeric>";
00151
00152 return true;
00153 }
00154 bool TlbExportVisitor::visit_ (NullType const& type)
00155 {
00156 m_stream << "<null " << " name=\"" << type.getName() << "\" " << emitSourceID() << ">\n";
00157 m_stream << m_indent << emitMetaData(type) << "\n";
00158 m_stream << m_indent << "</null>";
00159 return true;
00160 }
00161
00162 void indirect(ostream& stream, Indirect const& type)
00163 {
00164 stream
00165 << " name=\"" << xmlEscape(type.getName())
00166 << "\" of=\"" << xmlEscape(type.getIndirection().getName()) << "\"";
00167 }
00168
00169 bool TlbExportVisitor::visit_ (Pointer const& type)
00170 {
00171 m_stream << "<pointer ";
00172 indirect(m_stream, type);
00173 m_stream << " " << emitSourceID() << ">\n";
00174 m_stream << m_indent << emitMetaData(type) << "\n";
00175 m_stream << m_indent << "</pointer>";
00176 return true;
00177 }
00178 bool TlbExportVisitor::visit_ (Array const& type)
00179 {
00180 m_stream << "<array ";
00181 indirect(m_stream, type);
00182 m_stream << " dimension=\"" << type.getDimension() << "\" " << emitSourceID() << ">\n";
00183 m_stream << m_indent << emitMetaData(type) << "\n";
00184 m_stream << m_indent << "</array>";
00185 return true;
00186 }
00187 bool TlbExportVisitor::visit_(Container const& type)
00188 {
00189 m_stream << "<container ";
00190 indirect(m_stream, type);
00191 m_stream
00192 << " size=\"" << type.getSize() << "\""
00193 << " kind=\"" << xmlEscape(type.kind()) << "\""
00194 << " " << emitSourceID() << ">\n";
00195 m_stream << m_indent << emitMetaData(type) << "\n";
00196 m_stream << m_indent << "</container>";
00197 return true;
00198 }
00199
00200 bool TlbExportVisitor::visit_ (Enum const& type)
00201 {
00202 Enum::ValueMap const& values = type.values();
00203 m_stream << "<enum name=\"" << type.getName() << "\" " << emitSourceID() << ">\n";
00204 { Indent indenter(m_indent);
00205 Enum::ValueMap::const_iterator it;
00206 for (it = values.begin(); it != values.end(); ++it)
00207 m_stream << m_indent << "<value symbol=\"" << it->first << "\" value=\"" << it->second << "\"/>\n";
00208 }
00209 m_stream << m_indent << emitMetaData(type) << "\n";
00210 m_stream << m_indent << "</enum>";
00211
00212 return true;
00213 }
00214
00215 }
00216
00217 using namespace std;
00218 void TlbExport::begin
00219 ( ostream& stream
00220 , Typelib::Registry const& )
00221 {
00222 stream <<
00223 "<?xml version=\"1.0\"?>\n"
00224 "<typelib>\n";
00225 }
00226 void TlbExport::end
00227 ( ostream& stream
00228 , Typelib::Registry const& )
00229 {
00230 stream <<
00231 "</typelib>\n";
00232 }
00233
00234 bool TlbExport::save
00235 ( ostream& stream
00236 , Typelib::RegistryIterator const& type )
00237 {
00238 if (type.isAlias())
00239 {
00240 stream << " <alias "
00241 "name=\"" << xmlEscape(type.getName()) << "\" "
00242 "source=\"" << xmlEscape(type->getName()) << "\"/>\n";
00243 }
00244 else
00245 {
00246 stream << " ";
00247 TlbExportVisitor exporter(stream, " ", type.getSource());
00248 exporter.apply(*type);
00249 stream << "\n";
00250 }
00251 return true;
00252 }
00253