Go to the documentation of this file.00001 #include "typebuilder.hh"
00002 #include "registry.hh"
00003 #include "typemodel.hh"
00004
00005 #include <numeric>
00006 #include <sstream>
00007
00008 using std::string;
00009 using std::list;
00010
00011 namespace
00012 {
00013 static string join(const string& acc, const string& add)
00014 {
00015 if (acc.empty()) return add;
00016 return acc + ' ' + add;
00017 }
00018 }
00019
00020 namespace Typelib
00021 {
00022 TypeBuilder::TypeBuilder(Registry& registry, const std::list<std::string>& name)
00023 : m_registry(registry)
00024 {
00025 string basename = accumulate(name.begin(), name.end(), string(), join);
00026
00027 m_type = m_registry.build(basename);
00028 if (!m_type)
00029 throw Undefined(basename);
00030 }
00031 TypeBuilder::TypeBuilder(Registry& registry, const Type* base)
00032 : m_type(base), m_registry(registry) { }
00033
00034
00035
00036 const Type& TypeBuilder::getType() const { return *m_type; }
00037 void TypeBuilder::addPointer(int level)
00038 {
00039 for (; level; --level)
00040 {
00041
00042 const Type* base_type = m_registry.get(Pointer::getPointerName(m_type->getName()));
00043 if (base_type)
00044 m_type = base_type;
00045 else
00046 {
00047 Type* new_type = new Pointer(*m_type);
00048 m_registry.add(new_type);
00049 m_type = new_type;
00050 }
00051 }
00052 }
00053
00054 void TypeBuilder::addArrayMinor(int new_dim)
00055 {
00056
00057 std::vector<int> dims;
00058
00059 while(m_type->getCategory() == Type::Array)
00060 {
00061 Array const* array = dynamic_cast<Array const*>(m_type);
00062 dims.push_back(array->getDimension());
00063 m_type = const_cast<Type*>(&array->getIndirection());
00064 }
00065
00066 addArrayMajor(new_dim);
00067 for (std::vector<int>::reverse_iterator it = dims.rbegin();
00068 it != dims.rend(); ++it)
00069 addArrayMajor(*it);
00070 }
00071
00072 void TypeBuilder::addArrayMajor(int new_dim)
00073 {
00074 const Type* base_type = m_registry.get(Array::getArrayName(m_type->getName(), new_dim));
00075 if (base_type)
00076 m_type = base_type;
00077 else
00078 {
00079 Type* new_type = new Array(*m_type, new_dim);
00080 m_registry.add(new_type);
00081 m_type = new_type;
00082 }
00083 }
00084
00085 const Type& TypeBuilder::build(Registry& registry, const TypeSpec& spec)
00086 {
00087 const Type* base = spec.first;
00088 const ModifierList& stack(spec.second);
00089
00090 TypeBuilder builder(registry, base);
00091 for (ModifierList::const_iterator it = stack.begin(); it != stack.end(); ++it)
00092 {
00093 Type::Category category = it -> category;
00094 int size = it -> size;
00095
00096 if (category == Type::Pointer)
00097 builder.addPointer(size);
00098 else if (category == Type::Array)
00099 builder.addArrayMajor(size);
00100 }
00101
00102 return builder.getType();
00103 }
00104
00105 struct InvalidIndirectName : public std::runtime_error
00106 {
00107 InvalidIndirectName(std::string const& what)
00108 : std::runtime_error(what) {}
00109 };
00110
00111 TypeBuilder::TypeSpec TypeBuilder::parse(const Registry& registry, const std::string& full_name)
00112 {
00113 static const char* first_chars = "*[";
00114
00115 TypeSpec spec;
00116
00117 size_t end = full_name.find_first_of(first_chars);
00118 string base_name = full_name.substr(0, end);
00119 spec.first = registry.get(base_name);
00120 if (! spec.first) throw Undefined(base_name);
00121
00122 size_t full_length(full_name.length());
00123 ModifierList& modlist(spec.second);
00124 while (end < full_length)
00125 {
00126 Modifier new_mod;
00127 if (full_name[end] == '[')
00128 {
00129 new_mod.category = Type::Array;
00130 new_mod.size = atoi(&full_name[end] + 1);
00131 end = full_name.find(']', end) + 1;
00132 }
00133 else if (full_name[end] == '*')
00134 {
00135 new_mod.category = Type::Pointer;
00136 new_mod.size = 1;
00137 ++end;
00138 }
00139 else
00140 throw InvalidIndirectName(full_name + " is not a valid type name");
00141 modlist.push_back(new_mod);
00142 }
00143
00144 return spec;
00145 }
00146
00147 const Type* TypeBuilder::build(Registry& registry, const std::string& full_name)
00148 {
00149 TypeSpec spec;
00150 try { spec = parse(registry, full_name); }
00151 catch(Undefined) { return 0; }
00152
00153 return &build(registry, spec);
00154 }
00155
00156 const Type* TypeBuilder::getBaseType(const Registry& registry, const std::string& full_name)
00157 {
00158 TypeSpec spec;
00159 try { spec = parse(registry, full_name); }
00160 catch(Undefined) { return 0; }
00161 return spec.first;
00162 }
00163
00164 std::string TypeBuilder::getBaseTypename(const std::string& full_name)
00165 {
00166 static const char* first_chars = "*[";
00167
00168 size_t end = full_name.find_first_of(first_chars);
00169 return string(full_name, 0, end);
00170 }
00171 };
00172