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 #if defined( _WIN32 )
142 const char* envVar =
"PATH";
143 const char sep =
';';
145 const char* envVar =
"LD_LIBRARY_PATH";
146 const char sep =
':';
148 char* search_path = ::getenv( envVar );
150 logger().
debug( std::string(
"searching factories in " ) + envVar );
151 std::string
path( search_path );
152 std::string::size_type pos = 0;
153 std::string::size_type newpos = 0;
154 while ( pos != std::string::npos ) {
157 newpos =
path.find( sep, pos );
158 if ( newpos != std::string::npos ) {
159 dirName =
path.substr( pos, newpos - pos );
162 dirName =
path.substr( pos );
165 logger().
debug( std::string(
" looking into " ) + dirName );
167 DIR* dir = opendir( dirName.c_str() );
169 struct dirent* entry;
170 while ( ( entry = readdir( dir ) ) ) {
171 std::string
name( entry->d_name );
173 std::string::size_type extpos =
name.find(
".components" );
174 if ( ( extpos != std::string::npos ) && ( ( extpos + 11 ) ==
name.size() ) ) {
175 std::string fullPath = ( dirName +
'/' +
name );
178 stat( fullPath.c_str(), &buf );
179 if ( !S_ISREG( buf.st_mode ) )
continue;
185 int factoriesCount = 0;
192 if (
line.empty() ||
line[0] ==
'#' )
continue;
194 if (
line.substr( 0, 4 ) ==
"v1::" )
199 auto pos =
line.find(
':' );
200 if ( pos == std::string::npos ) {
201 logger().
warning(
"failed to parse line " + fullPath +
':' + std::to_string( lineCount ) );
204 const std::string lib(
line, 0, pos );
205 const std::string fact(
line, pos + 1 );
207 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
209 std::string old_name = old_style_name( fact );
210 if ( fact != old_name ) {
219 logger().
debug(
" found " + std::to_string( factoriesCount ) +
" factories" );
230 const std::string& rtype,
const std::string& className,
232 auto _guard = std::scoped_lock{
m_mutex };
234 auto entry = facts.find(
id );
235 if ( entry == facts.end() ) {
237 entry = facts.emplace(
id,
FactoryInfo(
"unknown", factory,
type, rtype, className,
props ) ).first;
240 if ( !entry->second.ptr ) entry->second.ptr = factory;
241 factoryInfoSetHelper( entry->second.type,
type,
"type",
id );
242 factoryInfoSetHelper( entry->second.rtype, rtype,
"return type",
id );
243 factoryInfoSetHelper( entry->second.className, className,
"class",
id );
245 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
247 std::string old_name = old_style_name(
id );
248 if (
id != old_name )
251 return entry->second;
255 auto _guard = std::scoped_lock{
m_mutex };
257 auto f = facts.find(
id );
258 if ( f != facts.end() ) {
259 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
261 if (
props.find(
"ReflexName" ) !=
props.end() )
265 f->second.className +
"' instead" );
267 if ( !f->second.ptr ) {
268 if ( !dlopen( f->second.library.c_str(), RTLD_LAZY | RTLD_GLOBAL ) ) {
269 logger().
warning(
"cannot load " + f->second.library +
" for factory " +
id );
270 char* dlmsg = dlerror();
274 f = facts.find(
id );
276 if ( f->second.type ==
type )
return f->second.ptr;
284 auto _guard = std::scoped_lock{
m_mutex };
287 auto f = facts.find(
id );
288 return ( f != facts.end() ) ? f->second : unknown;
292 auto _guard = std::scoped_lock{
m_mutex };
294 auto f = facts.find(
id );
295 if ( f != facts.end() ) f->second.properties[k] =
v;
300 auto _guard = std::scoped_lock{
m_mutex };
303 if ( f.second.ptr )
l.insert( f.first );
309 static const char* levels[] = {
"DEBUG : ",
"INFO : ",
"WARNING: ",
"ERROR : " };
310 if ( lvl >=
level() ) { std::cerr << levels[lvl] <<
msg << std::endl; }
313 static auto s_logger = std::make_unique<Logger>();
320 using namespace Details;
322 if ( debugLevel > 1 )
324 else if ( debugLevel > 0 )
331 using namespace Details;