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


typelib
Author(s): Sylvain Joyeux/sylvain.joyeux@m4x.org
autogenerated on Sat Jun 8 2019 18:49:22