14 #define GAUDI_PLUGIN_SERVICE_V1
30 std::mutex registrySingletonMutex;
39 constexpr
struct is_space_t {
40 bool operator()(
int i )
const {
return std::isspace( i ); }
44 static inline std::string& ltrim( std::string&
s ) {
45 s.erase(
s.begin(), std::find_if_not(
s.begin(),
s.end(), is_space ) );
50 static inline std::string& rtrim( std::string&
s ) {
51 s.erase( std::find_if_not(
s.rbegin(),
s.rend(), is_space ).base(),
s.end() );
55 static inline std::string& trim( std::string&
s ) {
return ltrim( rtrim(
s ) ); }
62 inline void factoryInfoSetHelper( std::string&
dest,
const std::string& value,
const std::string& desc,
63 const std::string&
id ) {
66 }
else if (
dest != value ) {
68 ": " +
dest +
" != " + value );
74 void operator()(
const char c ) {
83 name.push_back(
'_' );
86 name.push_back(
'r' );
89 name.push_back(
'p' );
100 std::string old_style_name(
const std::string&
name ) {
106 namespace PluginService {
119 auto realname = std::unique_ptr<char, decltype( free )*>(
120 abi::__cxa_demangle(
id.c_str(),
nullptr,
nullptr, &status ), free );
121 if ( !realname )
return id;
122 return std::regex_replace(
124 std::regex{
"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >( (?=>))?" },
130 auto _guard = std::scoped_lock{ ::registrySingletonMutex };
138 auto _guard = std::scoped_lock{
m_mutex };
141 const char* envVar =
"LD_LIBRARY_PATH";
142 const char sep =
':';
143 char* search_path = ::getenv( envVar );
145 logger().
debug( std::string(
"searching factories in " ) + envVar );
146 std::string
path( search_path );
147 std::string::size_type pos = 0;
148 std::string::size_type newpos = 0;
149 while ( pos != std::string::npos ) {
152 newpos =
path.find( sep, pos );
153 if ( newpos != std::string::npos ) {
154 dirName =
path.substr( pos, newpos - pos );
157 dirName =
path.substr( pos );
160 logger().
debug( std::string(
" looking into " ) + dirName );
162 DIR* dir = opendir( dirName.c_str() );
164 struct dirent* entry;
165 while ( ( entry = readdir( dir ) ) ) {
166 std::string
name( entry->d_name );
168 std::string::size_type extpos =
name.find(
".components" );
169 if ( ( extpos != std::string::npos ) && ( ( extpos + 11 ) ==
name.size() ) ) {
170 std::string fullPath = ( dirName +
'/' +
name );
173 stat( fullPath.c_str(), &buf );
174 if ( !S_ISREG( buf.st_mode ) )
continue;
180 int factoriesCount = 0;
187 if (
line.empty() ||
line[0] ==
'#' )
continue;
189 if (
line.substr( 0, 4 ) ==
"v1::" )
194 auto pos =
line.find(
':' );
195 if ( pos == std::string::npos ) {
196 logger().
warning(
"failed to parse line " + fullPath +
':' + std::to_string( lineCount ) );
199 const std::string lib(
line, 0, pos );
200 const std::string fact(
line, pos + 1 );
202 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
204 std::string old_name = old_style_name( fact );
205 if ( fact != old_name ) {
214 logger().
debug(
" found " + std::to_string( factoriesCount ) +
" factories" );
225 const std::string& rtype,
const std::string& className,
227 auto _guard = std::scoped_lock{
m_mutex };
229 auto entry = facts.find(
id );
230 if ( entry == facts.end() ) {
232 entry = facts.emplace(
id,
FactoryInfo(
"unknown", factory,
type, rtype, className,
props ) ).first;
235 if ( !entry->second.ptr ) entry->second.ptr = factory;
236 factoryInfoSetHelper( entry->second.type,
type,
"type",
id );
237 factoryInfoSetHelper( entry->second.rtype, rtype,
"return type",
id );
238 factoryInfoSetHelper( entry->second.className, className,
"class",
id );
240 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
242 std::string old_name = old_style_name(
id );
243 if (
id != old_name )
246 return entry->second;
250 auto _guard = std::scoped_lock{
m_mutex };
252 auto f = facts.find(
id );
253 if ( f != facts.end() ) {
254 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
256 if (
props.find(
"ReflexName" ) !=
props.end() )
260 f->second.className +
"' instead" );
262 if ( !f->second.ptr ) {
263 if ( !dlopen( f->second.library.c_str(), RTLD_LAZY | RTLD_GLOBAL ) ) {
264 logger().
warning(
"cannot load " + f->second.library +
" for factory " +
id );
265 char* dlmsg = dlerror();
269 f = facts.find(
id );
271 if ( f->second.type ==
type )
return f->second.ptr;
279 auto _guard = std::scoped_lock{
m_mutex };
282 auto f = facts.find(
id );
283 return ( f != facts.end() ) ? f->second : unknown;
287 auto _guard = std::scoped_lock{
m_mutex };
289 auto f = facts.find(
id );
290 if ( f != facts.end() ) f->second.properties[k] =
v;
295 auto _guard = std::scoped_lock{
m_mutex };
298 if ( f.second.ptr )
l.insert( f.first );
304 static const char* levels[] = {
"DEBUG : ",
"INFO : ",
"WARNING: ",
"ERROR : " };
305 if ( lvl >=
level() ) { std::cerr << levels[lvl] <<
msg << std::endl; }
308 static auto s_logger = std::make_unique<Logger>();
315 using namespace Details;
317 if ( debugLevel > 1 )
319 else if ( debugLevel > 0 )
326 using namespace Details;