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.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 


typelib
Author(s): Sylvain Joyeux/sylvain.joyeux@m4x.org
autogenerated on Thu Jan 2 2014 11:38:41