$search
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 /* Returns true if \c name1 is either in a more in-depth namespace than 00022 * name2 (i.e. name2 == /A/B/class and name1 == /A/B/C/class2 or if 00023 * name2 < name1 (lexicographic sort). Otherwise, returns false 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 // we sort /A/B/C/ before /A/B/C/class 00037 // and /A/B/C/class2 after /A/B/class1 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 //cout << ns1 << " " << ns2 << endl; 00046 } 00047 00048 if (it1 == tok1.end()) 00049 return true; // there is namespace names left in name1, and not in name2 00050 if (it2 == tok2.end()) 00051 return false; // there is namespace names left in name2, and not in name1 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 // Merge non aliased types. Aliases are never used by type model classes 00151 // so we can safely call merge() 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 // Either the alias already points to a concrete type, and 00161 // we must check that it is the same concrete type, or 00162 // we have to add the alias 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 // we are sure the concrete type we are pointing to is 00174 // already in the target registry 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 // Copy now the aliases 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 // Merge non aliased types. Aliases are never used by type model classes 00224 // so we can safely call merge() 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 // Either the alias already points to a concrete type, and 00235 // we must check that it is the same concrete type, or 00236 // we have to add the alias 00237 if (!it.isAlias()) continue; 00238 if (auto_types.has(it.getName())) continue; 00239 // Do not continue if it is a typedef on a type that we don't need 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 // Check if there is already a type with the same relative name 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 // If there are any aliases for any of the type's dependencies, trigger 00373 // modifiedDependencyAliases() 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 // If base_type is in use in any type, trigger 00407 // modifiedDependencyAliases() on it 00408 // 00409 // We do it in two stages as modifying a container while iterating on it 00410 // is evil ... 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 // We remove the aliases from +m_global+ and recompute m_current from 00431 // scratch 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 // Set the type pointer to 0 on aliases 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 // ... then delete the objects 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 // First, do a copy of new_sizes for our own use. Most importantly, we 00555 // resolve aliases 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 }; // namespace Typelib 00648