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.get_(basename);
00028 if (!m_type)
00029 throw Undefined(basename);
00030 }
00031 TypeBuilder::TypeBuilder(Registry& registry, const Type* base)
00032 : m_type(const_cast<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 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* array = dynamic_cast<Array*>(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 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 void TypeBuilder::setSize(int size)
00086 {
00087 m_type->setSize(size);
00088 }
00089
00090 const Type& TypeBuilder::build(Registry& registry, const TypeSpec& spec, int size)
00091 {
00092 const Type* base = spec.first;
00093 const ModifierList& stack(spec.second);
00094
00095 TypeBuilder builder(registry, base);
00096 for (ModifierList::const_iterator it = stack.begin(); it != stack.end(); ++it)
00097 {
00098 Type::Category category = it -> category;
00099 int size = it -> size;
00100
00101 if (category == Type::Pointer)
00102 builder.addPointer(size);
00103 else if (category == Type::Array)
00104 builder.addArrayMajor(size);
00105 }
00106
00107 if (size != 0)
00108 builder.setSize(size);
00109 return builder.getType();
00110 }
00111
00112 struct InvalidIndirectName : public std::runtime_error
00113 {
00114 InvalidIndirectName(std::string const& what)
00115 : std::runtime_error(what) {}
00116 };
00117
00118 TypeBuilder::TypeSpec TypeBuilder::parse(const Registry& registry, const std::string& full_name)
00119 {
00120 static const char* first_chars = "*[";
00121
00122 TypeSpec spec;
00123
00124 size_t end = full_name.find_first_of(first_chars);
00125 string base_name = full_name.substr(0, end);
00126 spec.first = registry.get(base_name);
00127 if (! spec.first) throw Undefined(base_name);
00128
00129 size_t full_length(full_name.length());
00130 ModifierList& modlist(spec.second);
00131 while (end < full_length)
00132 {
00133 Modifier new_mod;
00134 if (full_name[end] == '[')
00135 {
00136 new_mod.category = Type::Array;
00137 new_mod.size = atoi(&full_name[end] + 1);
00138 end = full_name.find(']', end) + 1;
00139 }
00140 else if (full_name[end] == '*')
00141 {
00142 new_mod.category = Type::Pointer;
00143 new_mod.size = 1;
00144 ++end;
00145 }
00146 else
00147 throw InvalidIndirectName(full_name + " is not a valid type name");
00148 modlist.push_back(new_mod);
00149 }
00150
00151 return spec;
00152 }
00153
00154 const Type* TypeBuilder::build(Registry& registry, const std::string& full_name, int size)
00155 {
00156 TypeSpec spec;
00157 try { spec = parse(registry, full_name); }
00158 catch(Undefined) { return NULL; }
00159
00160 return &build(registry, spec, size);
00161 }
00162
00163 const Type* TypeBuilder::getBaseType(const Registry& registry, const std::string& full_name)
00164 {
00165 TypeSpec spec;
00166 try { spec = parse(registry, full_name); }
00167 catch(Undefined) { return NULL; }
00168 return spec.first;
00169 }
00170
00171 std::string TypeBuilder::getBaseTypename(const std::string& full_name)
00172 {
00173 static const char* first_chars = "*[";
00174
00175 size_t end = full_name.find_first_of(first_chars);
00176 return string(full_name, 0, end);
00177 }
00178 };
00179