Skip to content
Snippets Groups Projects
AlgorithmRegistry.cpp 7.37 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <registry/AlgorithmRegistry.hpp>
    #include <registry/CastRegistry.hpp>
    
    Jan Travnicek's avatar
    Jan Travnicek committed
    
    
    #include <alib/foreach>
    
    Jan Travnicek's avatar
    Jan Travnicek committed
    #include <alib/algorithm>
    
    #include <exception>
    
    #include <common/OverloadResolution.hpp>
    
    
    #include <abstraction/RawAbstraction.hpp>
    
    
    namespace abstraction {
    
    
    std::shared_ptr < abstraction::OperationAbstraction > AlgorithmRegistry::RawImpl::getAbstraction ( ) const {
    	return std::make_shared < abstraction::RawAbstraction > ( getEntryInfo ( ).getParams ( ), m_rawCallback );
    }
    
    
    ext::map < ext::pair < std::string, ext::vector < std::string > >, ext::list < std::unique_ptr < AlgorithmRegistry::Entry > > > & AlgorithmRegistry::getEntries ( ) {
    	static ext::map < ext::pair < std::string, ext::vector < std::string > >, ext::list < std::unique_ptr < Entry > > > algorithmGroups;
    
    bool AlgorithmRegistry::isRegistered ( const std::string & algorithm, const ext::vector < std::string > & templateParams, const AlgorithmBaseInfo & entryInfo ) {
    
    	const auto & group = getEntries ( ) [ ext::tie ( algorithm, templateParams ) ];
    
    	return std::any_of ( group.begin ( ), group.end ( ), [ & ] ( const std::unique_ptr < Entry > & entry ) { return entry->getEntryInfo ( ).getCategory ( ) == entryInfo.getCategory ( ) && entry->getEntryInfo ( ).getParams ( ) == entryInfo.getParams ( ); } );
    
    void AlgorithmRegistry::registerInternal ( std::string algorithm, ext::vector < std::string > templateParams, std::unique_ptr < Entry > value ) {
    
    	if ( isRegistered ( algorithm, templateParams, value->getEntryInfo ( ) ) )
    		throw std::invalid_argument ( "Callback for " + algorithm + " with params " + ext::to_string ( value->getEntryInfo ( ).getParams ( ) ) + " already registered." );
    
    	auto & group = getEntries ( ) [ ext::make_pair ( std::move ( algorithm ), std::move ( templateParams ) ) ];
    
    	group.insert ( group.end ( ), std::move ( value ) );
    
    void AlgorithmRegistry::unregisterInternal ( const std::string & algorithm, const ext::vector < std::string > & templateParams, const AlgorithmBaseInfo & entryInfo ) {
    	auto & group = getEntries ( ) [ ext::tie ( algorithm, templateParams ) ];
    
    	auto iter = find_if ( group.begin ( ), group.end ( ), [ & ] ( const std::unique_ptr < Entry > & entry ) {
    
    				return entry->getEntryInfo ( ).getCategory ( ) == entryInfo.getCategory ( ) && entry->getEntryInfo ( ).getParams ( ) == entryInfo.getParams ( );
    
    	if ( iter == group.end ( ) ) {
    
    		if ( templateParams.empty ( ) )
    
    			throw std::invalid_argument ( "Entry " + algorithm + " with parameters " + ext::to_string ( entryInfo.getParams ( ) ) + " not registered." );
    
    			throw std::invalid_argument ( "Templated entry " + algorithm + " < " + ext::to_string ( templateParams ) + " > with parameters " + ext::to_string ( entryInfo.getParams ( ) ) + " not registered." );
    
    	}
    	group.erase ( iter );
    
    	if ( group.empty ( ) )
    
    		getEntries ( ).erase ( ext::tie ( algorithm, templateParams ) );
    
    void AlgorithmRegistry::setDocumentation ( const std::string & algorithm, const ext::vector < std::string > & templateParams, const AlgorithmBaseInfo & entryInfo, std::string documentation ) {
    	auto & group = getEntries ( ) [ ext::tie ( algorithm, templateParams ) ];
    
    	auto iter = find_if ( group.begin ( ), group.end ( ), [ & ] ( const std::unique_ptr < Entry > & entry ) {
    
    				return entry->getEntryInfo ( ).getCategory ( ) == entryInfo.getCategory ( ) && entry->getEntryInfo ( ).getParams ( ) == entryInfo.getParams ( );
    
    		if ( templateParams.empty ( ) )
    
    			throw std::invalid_argument ( "Entry " + algorithm + " with parameters " + ext::to_string ( entryInfo.getParams ( ) ) + " not registered." );
    
    			throw std::invalid_argument ( "Templated entry " + algorithm + " < " + ext::to_string ( templateParams ) + " > with parameters " + ext::to_string ( entryInfo.getParams ( ) ) + " not registered." );
    
    	}
    	(*iter)->setDocumentation ( std::move ( documentation ) );
    }
    
    
    ext::list < std::unique_ptr < AlgorithmRegistry::Entry > > & AlgorithmRegistry::findAbstractionGroup ( const std::string & name, const ext::vector < std::string > & templateParams ) {
    
    	auto group = getEntries ( ).find ( ext::tie ( name, templateParams ) );
    
    	if ( group == getEntries ( ).end ( ) ) {
    		for ( auto iter = getEntries ( ).begin ( ); iter != getEntries ( ).end ( ); ++ iter ) {
    
    			if ( ext::is_same_type ( name, iter->first.first ) && ext::are_same_types ( templateParams, iter->first.second ) ) {
    
    				if ( group == getEntries ( ).end ( ) )
    					group = iter;
    
    				else if ( templateParams.empty ( ) )
    
    					throw std::invalid_argument ( "Name " + name + " is ambigous " );
    
    				else
    					throw std::invalid_argument ( "Templated name " + name + " < " + ext::to_string ( templateParams ) + " > is ambigous " );
    
    	if ( group == getEntries ( ).end ( ) ) {
    
    		if ( templateParams.empty ( ) )
    
    			throw std::invalid_argument ( "Entry " + name + " not available" );
    		else
    			throw std::invalid_argument ( "Templated entry " + name + " < " + ext::to_string ( templateParams ) + " > not available" );
    	}
    
    	return group->second;
    
    std::shared_ptr < abstraction::OperationAbstraction > AlgorithmRegistry::getAbstraction ( const std::string & name, const ext::vector < std::string > & templateParams, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::TypeQualifiers::TypeQualifierSet > & typeQualifiers, AlgorithmCategories::AlgorithmCategory category ) {
    
    	const auto & group = findAbstractionGroup ( name, templateParams );
    
    		return getOverload ( group, paramTypes, typeQualifiers, category );
    
    	} catch ( ... ) {
    
    		if ( templateParams.empty ( ) )
    
    			std::throw_with_nested ( std::invalid_argument ( "Entry overload " + name + " " + ext::to_string ( paramTypes ) + " not available" ) );
    
    			std::throw_with_nested ( std::invalid_argument ( "Templated entry overload " + name + " < " + ext::to_string ( templateParams ) + " > " + ext::to_string ( paramTypes ) + " not available" ) );
    
    ext::set < ext::pair < std::string, ext::vector < std::string > > > AlgorithmRegistry::listGroup ( const std::string & group ) {
    	ext::set < ext::pair < std::string, ext::vector < std::string > > > res;
    
    	for ( const std::pair < const ext::pair < std::string, ext::vector < std::string > >, ext::list < std::unique_ptr < Entry > > > & entry : getEntries ( ) )
    
    		if ( entry.first.first.find ( group ) == 0 ) //found at the begining
    
    			res.insert ( entry.first );
    
    	return res;
    
    ext::list < ext::tuple < AlgorithmFullInfo, std::optional < std::string > > > AlgorithmRegistry::listOverloads ( const std::string & algorithm, const ext::vector < std::string > & templateParams ) {
    
    	auto & group = findAbstractionGroup ( algorithm, templateParams );
    
    	ext::list < ext::tuple < AlgorithmFullInfo, std::optional < std::string > > > res;
    
    
    	std::transform ( group.begin ( ), group.end ( ), std::back_inserter ( res ), [ ] ( const std::unique_ptr < Entry > & overloads ) {
    		return ext::make_tuple ( overloads->getEntryInfo ( ), overloads->getDocumentation ( ) );
    	} );
    
    ext::set < ext::pair < std::string, ext::vector < std::string > > > AlgorithmRegistry::list ( ) {
    	ext::set < ext::pair < std::string, ext::vector < std::string > > > res;
    
    	std::transform ( getEntries ( ).begin ( ), getEntries ( ).end ( ), std::inserter ( res, res.begin ( ) ), [ ] ( const std::pair < const ext::pair < std::string, ext::vector < std::string > >, ext::list < std::unique_ptr < Entry > > > & entry ) {
    		return entry.first;
    	} );
    
    }
    
    } /* namespace abstraction */