$search
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 // Try to get the type object in the registry 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 // build the list of array dimensions 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