lib_common: new class for module visibility

Add MODULE_FLAG_ALIAS (+ complete API) for modules that are not hidden
as technical/deprecated moudles but rather an alias.

The difference is important for GUI not to print aliased module twice.
This commit is contained in:
Martin Pulec
2025-08-28 16:11:23 +02:00
parent 7ac13a3032
commit b0739571ce
2 changed files with 51 additions and 22 deletions

View File

@@ -3,7 +3,7 @@
* @author Martin Pulec <pulec@cesnet.cz>
*/
/*
* Copyright (c) 2012-2023 CESNET, z. s. p. o.
* Copyright (c) 2012-2025 CESNET
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -215,7 +215,7 @@ void open_all(const char *pattern, list<void *> &libs) {
struct lib_info {
const void *data;
int abi_version;
bool hidden;
unsigned visibility_flag;
};
// http://stackoverflow.com/questions/1801892/making-mapfind-operation-case-insensitive
@@ -247,13 +247,22 @@ static auto& get_libmap(){
return libraries;
}
void register_library(const char *name, const void *data, enum library_class cls, int abi_version, int hidden)
/**
* @param name module name (used in listing and on cmdline for spec)
* @param cls module class
* @param name class-specific metadata structure (with callbacks)
* @param abi_version class-specific ABI version
* @param visibility_flag usually 0 or flag from @ref enum module_flag
*/
void
register_library(const char *name, const void *info, enum library_class cls,
int abi_version, unsigned visibility_flag)
{
auto& map = get_libmap()[cls];
if (map.find(name) != map.end()) {
LOG(LOG_LEVEL_ERROR) << "Module \"" << name << "\" (class " << cls << ") multiple initialization!\n";
}
map[name] = {data, abi_version, static_cast<bool>(hidden)};
map[name] = {info, abi_version, visibility_flag};
}
const void *load_library(const char *name, enum library_class cls, int abi_version)
@@ -293,10 +302,12 @@ const void *load_library(const char *name, enum library_class cls, int abi_versi
/**
* Prints list of modules of given class
* @param full include hidden modules
* @param full include hidden modules and aliases
*/
void list_modules(enum library_class cls, int abi_version, bool full) {
const auto & class_set = get_libraries_for_class(cls, abi_version, full);
const auto &class_set = get_libraries_for_class(
cls, abi_version,
full ? MODULE_SHOW_ALL : MODULE_SHOW_VISIBLE_ONLY);
for (auto && item : class_set) {
col() << "\t" << SBOLD(item.first.c_str()) << "\n";
}
@@ -333,7 +344,9 @@ bool list_all_modules() {
return ret;
}
map<string, const void *> get_libraries_for_class(enum library_class cls, int abi_version, bool include_hidden)
map<string, const void *>
get_libraries_for_class(enum library_class cls, int abi_version,
unsigned include_flags)
{
map<string, const void *> ret;
auto& libraries = get_libmap();
@@ -341,7 +354,9 @@ map<string, const void *> get_libraries_for_class(enum library_class cls, int ab
if (it != libraries.end()) {
for (auto && item : it->second) {
if (abi_version == item.second.abi_version) {
if (include_hidden || !item.second.hidden) {
if (item.second.visibility_flag == 0 ||
(include_flags &
item.second.visibility_flag) != 0U) {
ret[item.first] = item.second.data;
}
} else {
@@ -354,4 +369,3 @@ map<string, const void *> get_libraries_for_class(enum library_class cls, int ab
return ret;
}

View File

@@ -3,7 +3,7 @@
* @author Martin Pulec <pulec@cesnet.cz>
*/
/*
* Copyright (c) 2011-2023 CESNET, z. s. p. o.
* Copyright (c) 2011-2025 CESNET
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -85,45 +85,59 @@ enum library_class {
LIBRARY_CLASS_AUDIO_FILTER,
};
const void *load_library(const char *name, enum library_class, int abi_version);
void register_library(const char *name, const void *info, enum library_class, int abi_version, int hidden);
void register_library(const char *name, const void *info, enum library_class,
int abi_version, unsigned visibility_flag);
void list_modules(enum library_class, int abi_version, bool full);
bool list_all_modules();
#ifdef __cplusplus
}
#endif
enum module_flag {
MODULE_SHOW_VISIBLE_ONLY = 0, ///< display only modules w/o flag
MODULE_FLAG_HIDDEN = 1 << 0, ///< flag - do not show in listing
MODULE_FLAG_ALIAS =
1 << 1, ///< ditto + hide for GUI, for explicit init only
MODULE_SHOW_ALL =
MODULE_FLAG_HIDDEN | MODULE_FLAG_ALIAS, ///< display all modules
};
#ifdef __cplusplus
#include <map>
#include <string>
std::map<std::string, const void *> get_libraries_for_class(enum library_class cls, int abi_version, bool include_hidden = true);
std::map<std::string, const void *>
get_libraries_for_class(enum library_class cls, int abi_version,
unsigned include_flags = MODULE_FLAG_HIDDEN);
#endif
/**
* Placeholder that installs module via constructor for every macro
* REGISTER_MODULE/REGISTER_MODULE_HIDDEN call
* REGISTER_MODULE* call
* @param name non-quoted module name
* @param lclass class of the module
* @param abi abi version (specific for every class)
* @param funcname unique function name that will be used to register
* the module (as a constructor)
* @param hidden 0/1 - whether the module should be visible by eg. '-c help'
* (for technical and deprecated modules), default true
* @param flag optional flag to limit visibility (@ref module_flag;
* for technical, deprecated modules and aliases), default 0
*/
#define REGISTER_MODULE_FUNCNAME(name, info, lclass, abi, funcname, hidden) static void funcname(void) __attribute__((constructor));\
#define REGISTER_MODULE_FUNCNAME(name, info, lclass, abi, funcname, flag) \
static void funcname(void) __attribute__((constructor)); \
\
static void funcname(void)\
{\
register_library(#name, info, lclass, abi, hidden);\
register_library(#name, info, lclass, abi, flag);\
}\
struct NOT_DEFINED_STRUCT_THAT_SWALLOWS_SEMICOLON
#define REGISTER_MODULE_FUNC_FUNCNAME(name, func, lclass, abi, funcname, hidden) static void funcname(void) __attribute__((constructor));\
#define REGISTER_MODULE_FUNC_FUNCNAME(name, func, lclass, abi, funcname, flag) \
static void funcname(void) __attribute__((constructor)); \
\
static void funcname(void)\
{\
const void *info = func();\
if (info) {\
register_library(#name, info, lclass, abi, hidden);\
register_library(#name, info, lclass, abi, flag);\
}\
}\
struct NOT_DEFINED_STRUCT_THAT_SWALLOWS_SEMICOLON
@@ -150,10 +164,11 @@ struct NOT_DEFINED_STRUCT_THAT_SWALLOWS_SEMICOLON
#define REGISTER_MODULE_WITH_FUNC(name, func, lclass, abi) REGISTER_MODULE_FUNC_FUNCNAME(name, func, lclass, abi, UNIQUE_LABEL, 0)
/**
* Similar to @ref REGISTER_MODULE but do not show the module under help
* of corresponding class (usable for technical or deprecated modules).
* Similar to @ref REGISTER_MODULE but allow @ref module_flag to be added to limit visibility.
*/
#define REGISTER_HIDDEN_MODULE(name, info, lclass, abi) REGISTER_MODULE_FUNCNAME(name, info, lclass, abi, UNIQUE_LABEL, 1)
#define REGISTER_MODULE_WITH_FLAG(name, info, lclass, abi, flag) \
REGISTER_MODULE_FUNCNAME(name, info, lclass, abi, UNIQUE_LABEL, flag)
#define REGISTER_HIDDEN_MODULE(name, info, lclass, abi) REGISTER_MODULE_WITH_FLAG(name, info, lclass, abi, MODULE_FLAG_HIDDEN)
#endif // defined LIB_COMMON_H