00001 #include "registry.hh"
00002 #include "registryiterator.hh"
00003 #include "typebuilder.hh"
00004 #include "typedisplay.hh"
00005
00006 #include <memory>
00007 #include <iostream>
00008 #include <set>
00009 using namespace std;
00010
00011 #include <ctype.h>
00012
00013 #include <boost/static_assert.hpp>
00014 #include <boost/lexical_cast.hpp>
00015 using boost::lexical_cast;
00016
00017 #include <typelib/pluginmanager.hh>
00018
00019 using namespace Typelib;
00020
00021
00022
00023
00024
00025 bool Typelib::nameSort( const std::string& name1, const std::string& name2 )
00026 {
00027 if (name1 == name2)
00028 return false;
00029
00030 NameTokenizer tok1(name1);
00031 NameTokenizer tok2(name2);
00032 NameTokenizer::const_iterator it1 = tok1.begin();
00033 NameTokenizer::const_iterator it2 = tok2.begin();
00034
00035 std::string ns1, ns2;
00036
00037
00038 for (; it1 != tok1.end() && it2 != tok2.end(); ++it1, ++it2)
00039 {
00040 ns1 = *it1;
00041 ns2 = *it2;
00042
00043 int value = ns1.compare(ns2);
00044 if (value) return value < 0;
00045
00046 }
00047
00048 if (it1 == tok1.end())
00049 return true;
00050 if (it2 == tok2.end())
00051 return false;
00052 int value = ns1.compare(ns2);
00053 if (value)
00054 return value < 0;
00055
00056 return false;
00057 }
00058
00059 namespace Typelib
00060 {
00061 Type const& Registry::null() {
00062 static NullType const null_type("/nil");
00063 return null_type;
00064 }
00065
00066 Registry::Registry()
00067 : m_global(nameSort)
00068 {
00069 PluginManager::self manager;
00070 manager->registerPluginTypes(*this);
00071 setDefaultNamespace("/");
00072 }
00073 Registry::~Registry() { clear(); }
00074
00075 void Registry::updateCurrentNameMap()
00076 {
00077 m_current.clear();
00078
00079 for (TypeMap::iterator it = m_global.begin(); it != m_global.end(); ++it)
00080 m_current.insert( make_pair(it->first, it->second) );
00081
00082 importNamespace(NamespaceMarkString);
00083 std::string cur_space = NamespaceMarkString;
00084 NameTokenizer tokens( m_namespace );
00085 NameTokenizer::const_iterator ns_it = tokens.begin();
00086 for (; ns_it != tokens.end(); ++ns_it)
00087 {
00088 cur_space += *ns_it + NamespaceMarkString;
00089 importNamespace(cur_space, true);
00090 }
00091 }
00092
00093 std::string Registry::getDefaultNamespace() const { return m_namespace; }
00094 bool Registry::setDefaultNamespace(const std::string& space)
00095 {
00096 if (! isValidNamespace(space, true))
00097 return false;
00098
00099 m_namespace = getNormalizedNamespace(space);
00100 updateCurrentNameMap();
00101 return true;
00102 }
00103
00104 void Registry::importNamespace(const std::string& name, bool erase_existing)
00105 {
00106 const std::string norm_name(getNormalizedNamespace(name));
00107 const int norm_length(norm_name.length());
00108
00109 TypeMap::const_iterator it = m_global.lower_bound(norm_name);
00110
00111 while ( it != m_global.end() && isInNamespace(it->first, norm_name, true) )
00112 {
00113 const std::string rel_name(it->first, norm_length, string::npos);
00114 if (erase_existing)
00115 m_current.erase(rel_name);
00116 m_current.insert( make_pair(rel_name, it->second) );
00117 ++it;
00118 }
00119 }
00120
00121 std::string Registry::getFullName(const std::string& name) const
00122 {
00123 if (isAbsoluteName(name))
00124 return name;
00125 return m_namespace + name;
00126 }
00127
00128 namespace {
00129 template<typename T>
00130 Numeric* make_std_numeric(char const* name)
00131 {
00132 typedef numeric_limits<T> limits;
00133 Numeric::NumericCategory category = limits::is_signed ? Numeric::SInt : Numeric::UInt;
00134 unsigned int size = (limits::digits + 1) / 8;
00135 return new Numeric(name, size, category);
00136 }
00137 }
00138
00140 bool Registry::isIncluded(Type const& type) const
00141 {
00142 Type const* this_type = get(type.getName());
00143 return (this_type == &type);
00144 }
00145
00146 void Registry::merge(Registry const& registry)
00147 {
00148 Typelib::Type::RecursionStack stack;
00149
00150
00151
00152 for(Iterator it = registry.begin(); it != registry.end(); ++it)
00153 {
00154 if (it.isAlias()) continue;
00155 it->merge(*this, stack);
00156 }
00157
00158 for (Iterator it = registry.begin(); it != registry.end(); ++it)
00159 {
00160
00161
00162
00163 if (!it.isAlias()) continue;
00164
00165 Type const* old_type = get(it.getName());
00166 if (old_type)
00167 {
00168 if (!old_type->isSame(*it))
00169 throw DefinitionMismatch(it.getName());
00170 }
00171 else
00172 {
00173
00174
00175 alias(it->getName(), it.getName(), it.isPersistent(), it.getSource());
00176 }
00177 }
00178 copySourceIDs(registry);
00179 }
00180
00181 void Registry::copySourceIDs(Registry const& registry)
00182 {
00183 for (Iterator it = begin(); it != end(); ++it)
00184 {
00185 RegistryIterator other_it = registry.find(it.getName());
00186 if (other_it == registry.end())
00187 continue;
00188
00189 string source_id = other_it.getSource();
00190 if (!source_id.empty() && it.getSource().empty())
00191 setSourceID(*it, source_id);
00192 }
00193 }
00194
00195 Registry* Registry::minimal(std::string const& name, bool with_aliases) const
00196 {
00197 auto_ptr<Registry> result(new Registry);
00198 Type const* type = get(name);
00199 if (!type)
00200 throw std::runtime_error("there is not type '" + name + "' in this registry");
00201
00202 type->merge(*result);
00203
00204
00205 if (with_aliases)
00206 {
00207 for(Iterator it = begin(); it != end(); ++it)
00208 {
00209 if (!it.isAlias()) continue;
00210 if (result->has(it->getName(), false))
00211 result->alias(it->getName(), it.getName());
00212 }
00213 }
00214
00215 result->copySourceIDs(*this);
00216 return result.release();
00217 }
00218
00219 Registry* Registry::minimal(Registry const& auto_types) const
00220 {
00221 auto_ptr<Registry> result(new Registry);
00222
00223
00224
00225 for(Iterator it = begin(); it != end(); ++it)
00226 {
00227 if (it.isAlias()) continue;
00228 if (!auto_types.has(it->getName()))
00229 it->merge(*result);
00230 }
00231
00232 for (Iterator it = begin(); it != end(); ++it)
00233 {
00234
00235
00236
00237 if (!it.isAlias()) continue;
00238 if (auto_types.has(it.getName())) continue;
00239
00240 if (!result->has(it->getName())) continue;
00241
00242 Type const* old_type = result->get(it.getName());
00243 if (old_type)
00244 {
00245 if (!old_type->isSame(*it))
00246 throw DefinitionMismatch(it.getName());
00247 }
00248 else
00249 {
00250 result->alias(it->getName(), it.getName(), it.isPersistent(), it.getSource());
00251 }
00252 }
00253
00254 return result.release();
00255 }
00256
00257 bool Registry::has(const std::string& name, bool build_if_missing) const
00258 {
00259 if (m_current.find(name) != m_current.end())
00260 return true;
00261
00262 if (! build_if_missing)
00263 return false;
00264
00265 const Type* base_type = TypeBuilder::getBaseType(*this, getFullName(name));
00266 return base_type;
00267 }
00268
00269 const Type* Registry::build(const std::string& name)
00270 {
00271 const Type* type = get(name);
00272 if (type)
00273 return type;
00274
00275 return TypeBuilder::build(*this, getFullName(name));
00276 }
00277
00278 Type* Registry::get_(const std::string& name)
00279 {
00280 NameMap::const_iterator it = m_current.find(name);
00281 if (it != m_current.end())
00282 return it->second.type;
00283 return 0;
00284 }
00285
00286 Type& Registry::get_(Type const& type)
00287 { return *get_(type.getName()); }
00288
00289 const Type* Registry::get(const std::string& name) const
00290 {
00291 NameMap::const_iterator it = m_current.find(name);
00292 if (it != m_current.end())
00293 return it->second.type;
00294 return 0;
00295 }
00296
00297 RegistryIterator Registry::find(std::string const& name) const
00298 {
00299 TypeMap::const_iterator global_it =
00300 m_global.find(name);
00301 return RegistryIterator(*this, global_it);
00302 }
00303
00304 bool Registry::isPersistent(std::string const& name, Type const& type, std::string const& source_id)
00305 {
00306 if (name != type.getName())
00307 return true;
00308
00309 switch(type.getCategory())
00310 {
00311 case Type::Pointer:
00312 case Type::Array:
00313 return false;
00314 default:
00315 return true;
00316 };
00317 }
00318
00319 void Registry::add(std::string const& name, Type* new_type, bool persistent, std::string const& source_id)
00320 {
00321 if (! isValidTypename(name, true))
00322 throw BadName(name);
00323
00324 const Type* old_type = get(name);
00325 if (old_type == new_type)
00326 return;
00327 else if (old_type)
00328 throw AlreadyDefined(name);
00329
00330 RegistryType regtype =
00331 { new_type
00332 , persistent
00333 , source_id };
00334
00335 m_global.insert (make_pair(name, regtype));
00336 m_current.insert(make_pair(name, regtype));
00337
00338 NameTokenizer tokens( m_namespace );
00339 NameTokenizer::const_iterator ns_it = tokens.begin();
00340 std::string cur_space = NamespaceMarkString;
00341 while(true)
00342 {
00343 if (name.size() <= cur_space.size() || string(name, 0, cur_space.size()) != cur_space)
00344 break;
00345
00346 string cur_name = getRelativeName(name, cur_space);
00347
00348
00349 TypeMap::iterator it = m_current.find(cur_name);
00350 if (it == m_current.end() || !nameSort(it->second.type->getName(), name))
00351 {
00352 m_current.erase(cur_name);
00353 m_current.insert(make_pair(cur_name, regtype));
00354 }
00355
00356 if (ns_it == tokens.end())
00357 break;
00358 cur_space += *ns_it + NamespaceMarkString;
00359 ++ns_it;
00360 }
00361 }
00362
00363 void Registry::add(Type* new_type, const std::string& source_id)
00364 {
00365 return add(new_type, isPersistent(new_type->getName(), *new_type, source_id), source_id);
00366 }
00367
00368 void Registry::add(Type* new_type, bool persistent, const std::string& source_id)
00369 {
00370 add(new_type->getName(), new_type, persistent, source_id);
00371
00372
00373
00374 set<Type const*> dependencies = new_type->dependsOn();
00375 for (set<Type const*>::const_iterator dep_it = dependencies.begin();
00376 dep_it != dependencies.end(); ++dep_it)
00377 {
00378 if (!getAliasesOf(**dep_it).empty())
00379 {
00380 new_type->modifiedDependencyAliases(*this);
00381 break;
00382 }
00383 }
00384 }
00385
00386 void Registry::alias(std::string const& base, std::string const& newname, std::string const& source_id)
00387 {
00388 Type* base_type = get_(base);
00389 if (! base_type)
00390 throw Undefined(base);
00391
00392 return alias(base, newname, isPersistent(newname, *base_type, source_id), source_id);
00393 }
00394
00395 void Registry::alias(std::string const& base, std::string const& newname, bool persistent, std::string const& source_id)
00396 {
00397 if (! isValidTypename(newname, true))
00398 throw BadName(newname);
00399
00400 Type* base_type = get_(base);
00401 if (! base_type)
00402 throw Undefined(base);
00403
00404 add(newname, base_type, persistent, source_id);
00405
00406
00407
00408
00409
00410
00411 std::list<Type const*> triggers;
00412 RegistryIterator const end = this->end();
00413 for (RegistryIterator it = begin(); it != end; ++it)
00414 {
00415 if (it.isAlias()) continue;
00416 set<Type const*> dependencies = it->dependsOn();
00417 if (dependencies.count(base_type))
00418 triggers.push_back(&(*it));
00419 }
00420
00421 for (list<Type const*>::const_iterator trigger_it = triggers.begin();
00422 trigger_it != triggers.end(); ++trigger_it)
00423 {
00424 (*trigger_it)->modifiedDependencyAliases(*this);
00425 }
00426 }
00427
00428 void Registry::clearAliases()
00429 {
00430
00431
00432 TypeMap::iterator global_it = m_global.begin(), global_end = m_global.end();
00433 while (global_it != global_end)
00434 {
00435 if (global_it->first != global_it->second.type->getName())
00436 m_global.erase(global_it++);
00437 else ++global_it;
00438 }
00439
00440 updateCurrentNameMap();
00441 }
00442
00443 size_t Registry::size() const { return m_global.size(); }
00444 void Registry::clear()
00445 {
00446
00447 for (TypeMap::iterator it = m_global.begin(); it != m_global.end(); ++it)
00448 {
00449 if (it->first != it->second.type->getName())
00450 it->second.type = 0;
00451 }
00452
00453
00454 for (TypeMap::iterator it = m_global.begin(); it != m_global.end(); ++it)
00455 delete it->second.type;
00456
00457 m_global.clear();
00458 m_current.clear();
00459 }
00460
00461 namespace
00462 {
00463 bool filter_source(std::string const& filter, std::string const& source)
00464 {
00465 if (filter == "*")
00466 return true;
00467 return filter == source;
00468 }
00469 }
00470
00471 void Registry::dump(std::ostream& stream, int mode, const std::string& source_filter) const
00472 {
00473 stream << "Types in registry";
00474 if (source_filter == "")
00475 stream << " not defined in any type library";
00476 else if (source_filter != "*")
00477 stream << " defined in " << source_filter;
00478 stream << endl;
00479
00480 TypeDisplayVisitor display(stream, "");
00481 for (TypeMap::const_iterator it = m_global.begin(); it != m_global.end(); ++it)
00482 {
00483 RegistryType regtype(it->second);
00484 if (! regtype.persistent)
00485 continue;
00486 if (!filter_source(source_filter, regtype.source_id))
00487 continue;
00488
00489 if (mode & WithSourceId)
00490 {
00491 string it_source_id = regtype.source_id;
00492 if (it_source_id.empty()) stream << "\t\t";
00493 else stream << it_source_id << "\t";
00494 }
00495
00496 Type const* type = regtype.type;
00497 if (mode & AllType)
00498 {
00499 if (type->getName() == it->first)
00500 {
00501 display.apply(*type);
00502 stream << "\n";
00503 }
00504 else
00505 stream << it->first << " is an alias for " << type->getName() << "\n";
00506 }
00507 else
00508 stream << "\t" << type->getName() << endl;
00509 }
00510 }
00511
00512 RegistryIterator Registry::begin() const { return RegistryIterator(*this, m_global.begin()); }
00513 RegistryIterator Registry::end() const { return RegistryIterator(*this, m_global.end()); }
00514 RegistryIterator Registry::begin(std::string const& prefix) const
00515 {
00516 RegistryIterator it(*this, m_global.lower_bound(prefix));
00517 RegistryIterator const end = this->end();
00518 if (it != end && it.getName().compare(0, prefix.length(), prefix) == 0)
00519 return it;
00520 else return end;
00521 }
00522 RegistryIterator Registry::end(std::string const& prefix) const
00523 {
00524 RegistryIterator it(begin(prefix));
00525 RegistryIterator const end = this->end();
00526 while (it != end && it.getName().compare(0, prefix.length(), prefix) == 0)
00527 ++it;
00528
00529 return it;
00530 }
00531
00532 bool Registry::isSame(Registry const& other) const
00533 {
00534 if (m_global.size() != other.m_global.size())
00535 return false;
00536
00537 TypeMap::const_iterator
00538 left_it = m_global.begin(),
00539 left_end = m_global.end(),
00540 right_it = other.m_global.begin();
00541
00542 while (left_it != left_end)
00543 {
00544 if (!left_it->second.type->isSame(*right_it->second.type))
00545 return false;
00546 left_it++; left_end++;
00547 }
00548 return true;
00549 }
00550
00551 void Registry::resize(std::map<std::string, size_t> const& new_sizes)
00552 {
00553 typedef std::map<std::string, std::pair<size_t, size_t> > SizeMap;
00554
00555
00556 SizeMap sizes;
00557 for (std::map<std::string, size_t>::const_iterator it = new_sizes.begin();
00558 it != new_sizes.end(); ++it)
00559 {
00560 Type& t = *get_(it->first);
00561 sizes.insert(make_pair(t.getName(),
00562 make_pair(t.getSize(), it->second)
00563 ));
00564 t.setSize(it->second);
00565 }
00566
00567 for(Iterator it = begin(); it != end(); ++it)
00568 {
00569 if (it.isAlias()) continue;
00570 it.get_().resize(*this, sizes);
00571 }
00572 }
00573
00574 std::set<Type const*> Registry::reverseDepends(Type const& type) const
00575 {
00576 std::set<Type const*> result;
00577 result.insert(&type);
00578
00579 RegistryIterator const end = this->end();
00580 for (RegistryIterator it = this->begin(); it != end; ++it)
00581 {
00582 Type const& t = *it;
00583 if (it.isAlias()) continue;
00584
00585 std::set<Type const*> dependencies = t.dependsOn();
00586 if (dependencies.count(&type))
00587 result.insert(&t);
00588 }
00589
00590 return result;
00591 }
00592
00593 std::set<Type*> Registry::reverseDepends(Type const& type)
00594 {
00595 std::set<Type*> result;
00596
00597 std::set<Type const*> const_result =
00598 static_cast<Registry const*>(this)->reverseDepends(type);
00599 std::set<Type const*>::const_iterator it, end;
00600 for (it = const_result.begin(); it != const_result.end(); ++it)
00601 result.insert(const_cast<Type*>(*it));
00602
00603 return result;
00604 }
00605
00606 std::set<Type *> Registry::remove(Type const& type)
00607 {
00608 std::set<Type*> types = reverseDepends(type);
00609
00610 TypeMap::iterator global_it = m_global.begin(), global_end = m_global.end();
00611 while (global_it != global_end)
00612 {
00613 if (types.count(global_it->second.type))
00614 m_global.erase(global_it++);
00615 else ++global_it;
00616 }
00617
00618 NameMap::iterator current_it = m_current.begin(), current_end = m_current.end();
00619 while (current_it != current_end)
00620 {
00621 if (types.count(current_it->second.type))
00622 m_current.erase(current_it++);
00623 else ++current_it;
00624 }
00625
00626 return types;
00627 }
00628
00629 std::set<std::string> Registry::getAliasesOf(Type const& type) const
00630 {
00631 set<string> result;
00632 RegistryIterator const end = this->end();
00633 for (RegistryIterator it = begin(); it != end; ++it)
00634 {
00635 if (it.isAlias() && *it == type)
00636 result.insert(it.getName());
00637 }
00638 return result;
00639 }
00640
00641 void Registry::setSourceID(Type const& type, std::string const& source_id)
00642 {
00643 TypeMap::iterator it = m_global.find(type.getName());
00644 if (it != m_global.end())
00645 it->second.source_id = source_id;
00646 }
00647 };
00648