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