/ include / lscore / registration.h
registration.h
  1  // SPDX-FileCopyrightText: 2023-2025 Le'Sec Core collective
  2  //
  3  // SPDX-License-Identifier: LGPL-3.0-or-later
  4  
  5  #ifndef LSC_REGISTRATION_H
  6  # define LSC_REGISTRATION_H
  7  
  8  # include <lscore/export.h>
  9  # include <lscore/environment.h>
 10  
 11  # ifdef __cplusplus
 12  extern "C" {
 13  # endif
 14  
 15    // Registration of implementations means storing a reference into
 16    // a bag in an environment.  This type is that bag.
 17    LSC_DATA_SET_TYPES(implementation_bag);
 18    LSC_DATA_SET_STRUCT(implementation_bag) {
 19      LSC_DATA_SET_STRUCT_FIELDS(implementation_bag);
 20    };
 21  
 22    // Because the implementation bag in itself is a type common to all
 23    // types of implementations, and that registration is centered around
 24    // the bag, the exact same set of LSC_NR_ values are used collectively
 25    // for all of them.
 26    enum {
 27      LSC_NR_register_implementation = (0 + LSC_NR__data_set_class_start),
 28      LSC_NR_deregister_implementation = (1 + LSC_NR__data_set_class_start),
 29      LSC_NR_find_implementation = (2 + LSC_NR__data_set_class_start),
 30      LSC_NR_do_all_implementations = (3 + LSC_NR__data_set_class_start),
 31    };
 32  
 33    // Registration and deregistration functions factory
 34  # define LSC_REGISTRATION_CALLBACK_TYPES(lsc_name)                      \
 35    typedef LE_STATUS                                                     \
 36    LSC_NAME(do_all_##lsc_name##_implementations_callback_fn)             \
 37      (const char *class, const char *id,                                 \
 38       const LSC_plugin_t *plugin, const LSC_env_t *env,                  \
 39       LSC_NAME(lsc_name##_dispatch_fn) *dispatch_function,               \
 40       LSC_NAME(lsc_name##_destroy_fn) *destroy_function,                 \
 41       const void *dispatch_data,                                         \
 42       const char *docstring,                                             \
 43       void *user_arg)
 44  # define LSC_REGISTRATION_FUNCTIONS(lsc_prefix, lsc_name)               \
 45    LSC_REGISTRATION_CALLBACK_TYPES(lsc_name);                            \
 46    static inline LE_STATUS                                               \
 47    LSC_NAME(register_##lsc_name##_implementation)                        \
 48      (LSC_env_t *env, LSC_plugin_t *plugin, const char *id,              \
 49       LSC_NAME(lsc_name##_dispatch_fn) *dispatch_function,               \
 50       LSC_NAME(lsc_name##_destroy_fn) *destroy_function,                 \
 51       const void *dispatch_data,                                         \
 52       const char *docstring)                                             \
 53    {                                                                     \
 54      LE_STATUS sts;                                                      \
 55      LSC_implementation_bag_t *t;                                        \
 56      const char *class = lsc_prefix #lsc_name;                           \
 57                                                                          \
 58      sts = LSC_get_environment_implementation_bag(env, class, &t);       \
 59      if (LE_status_is_OK(sts))                                           \
 60        sts = t->lsc_dispatch(t, LSC_NR_register_implementation,          \
 61                              plugin, id,                                 \
 62                              dispatch_function, destroy_function,        \
 63                              dispatch_data, docstring);                  \
 64      return sts;                                                         \
 65    }                                                                     \
 66    static inline LE_STATUS                                               \
 67    LSC_NAME(deregister_##lsc_name##_implementation)                      \
 68      (LSC_env_t *env, LSC_plugin_t *plugin, const char *id,              \
 69       LSC_NAME(lsc_name##_dispatch_fn) *dispatch_function,               \
 70       LSC_NAME(lsc_name##_destroy_fn) *destroy_function,                 \
 71       const void *dispatch_data,                                         \
 72       const char *docstring)                                             \
 73    {                                                                     \
 74      LE_STATUS sts;                                                      \
 75      LSC_implementation_bag_t *t;                                        \
 76      const char *class = lsc_prefix #lsc_name;                           \
 77                                                                          \
 78      sts = LSC_get_environment_implementation_bag(env, class, &t);       \
 79      if (LE_status_is_OK(sts))                                           \
 80        sts = t->lsc_dispatch(t, LSC_NR_deregister_implementation,        \
 81                              plugin, id,                                 \
 82                              dispatch_function, destroy_function,        \
 83                              dispatch_data, docstring);                  \
 84      return sts;                                                         \
 85    }                                                                     \
 86    static inline LE_STATUS                                               \
 87    LSC_NAME(find_##lsc_name##_implementation)                            \
 88      (LSC_env_t *env, const char *id, LSC_plugin_t **plugin,             \
 89       LSC_NAME(lsc_name##_dispatch_fn) **dispatch_function,              \
 90       LSC_NAME(lsc_name##_destroy_fn) **destroy_function,                \
 91       const void **dispatch_data,                                        \
 92       const char **docstring)                                            \
 93    {                                                                     \
 94      LE_STATUS sts;                                                      \
 95      LSC_implementation_bag_t *t;                                        \
 96      const char *class = lsc_prefix #lsc_name;                           \
 97                                                                          \
 98      sts = LSC_get_environment_implementation_bag(env, class, &t);       \
 99      if (LE_status_is_OK(sts))                                           \
100        sts = t->lsc_dispatch(t, LSC_NR_find_implementation,              \
101                              id, plugin,                                 \
102                              dispatch_function, destroy_function,        \
103                              dispatch_data, docstring);                  \
104      return sts;                                                         \
105    }                                                                     \
106    static inline LE_STATUS                                               \
107    LSC_NAME(do_all_##lsc_name##_implementations)                         \
108      (LSC_env_t *env,                                                    \
109       LSC_NAME(do_all_##lsc_name##_implementations_callback_fn) *fn,     \
110       void *user_arg)                                                    \
111    {                                                                     \
112      LE_STATUS sts;                                                      \
113      LSC_implementation_bag_t *t;                                        \
114      const char *tag = lsc_prefix #lsc_name;                             \
115                                                                          \
116      sts = LSC_get_environment_implementation_bag(env, tag, &t);         \
117      if (LE_status_is_OK(sts))                                           \
118        sts = t->lsc_dispatch(t, LSC_NR_do_all_implementations,           \
119                              fn, user_arg);                              \
120      return sts;                                                         \
121    }
122  
123  # ifdef __cplusplus
124  }
125  # endif
126  
127  #endif