Home | History | Annotate | Download | only in unicode
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 ******************************************************************************
      5 *
      6 *   Copyright (C) 2009-2015, International Business Machines
      7 *   Corporation and others.  All Rights Reserved.
      8 *
      9 ******************************************************************************
     10 *
     11 *  FILE NAME : icuplug.h
     12 *
     13 *   Date         Name        Description
     14 *   10/29/2009   sl          New.
     15 ******************************************************************************
     16 */
     17 
     18 /**
     19  * \file
     20  * \brief C API: ICU Plugin API
     21  *
     22  * <h2>C API: ICU Plugin API</h2>
     23  *
     24  * <p>C API allowing run-time loadable modules that extend or modify ICU functionality.</p>
     25  *
     26  * <h3>Loading and Configuration</h3>
     27  *
     28  * <p>At ICU startup time, the environment variable "ICU_PLUGINS" will be
     29  * queried for a directory name.  If it is not set, the preprocessor symbol
     30  * "DEFAULT_ICU_PLUGINS" will be checked for a default value.</p>
     31  *
     32  * <p>Within the above-named directory, the file  "icuplugins##.txt" will be
     33  * opened, if present, where ## is the major+minor number of the currently
     34  * running ICU (such as, 44 for ICU 4.4, thus icuplugins44.txt)</p>
     35  *
     36  * <p>The configuration file has this format:</p>
     37  *
     38  * <ul>
     39  * <li>Hash (#) begins a comment line</li>
     40  *
     41  * <li>Non-comment lines have two or three components:
     42  * LIBRARYNAME     ENTRYPOINT     [ CONFIGURATION .. ]</li>
     43  *
     44  * <li>Tabs or spaces separate the three items.</li>
     45  *
     46  * <li>LIBRARYNAME is the name of a shared library, either a short name if
     47  * it is on the loader path,  or a full pathname.</li>
     48  *
     49  * <li>ENTRYPOINT is the short (undecorated) symbol name of the plugin's
     50  * entrypoint, as above.</li>
     51  *
     52  * <li>CONFIGURATION is the entire rest of the line . It's passed as-is to
     53  * the plugin.</li>
     54  * </ul>
     55  *
     56  * <p>An example configuration file is, in its entirety:</p>
     57  *
     58  * \code
     59  * # this is icuplugins44.txt
     60  * testplug.dll    myPlugin        hello=world
     61  * \endcode
     62  * <p>Plugins are categorized as "high" or "low" level.  Low level are those
     63  * which must be run BEFORE high level plugins, and before any operations
     64  * which cause ICU to be 'initialized'.  If a plugin is low level but
     65  * causes ICU to allocate memory or become initialized, that plugin is said
     66  * to cause a 'level change'. </p>
     67  *
     68  * <p>At load time, ICU first queries all plugins to determine their level,
     69  * then loads all 'low' plugins first, and then loads all 'high' plugins.
     70  * Plugins are otherwise loaded in the order listed in the configuration file.</p>
     71  *
     72  * <h3>Implementing a Plugin</h3>
     73  * \code
     74  * U_CAPI UPlugTokenReturn U_EXPORT2
     75  * myPlugin (UPlugData *plug, UPlugReason reason, UErrorCode *status) {
     76  *   if(reason==UPLUG_REASON_QUERY) {
     77  *      uplug_setPlugName(plug, "Simple Plugin");
     78  *      uplug_setPlugLevel(plug, UPLUG_LEVEL_HIGH);
     79  *    } else if(reason==UPLUG_REASON_LOAD) {
     80  *       ... Set up some ICU things here....
     81  *    } else if(reason==UPLUG_REASON_UNLOAD) {
     82  *       ... unload, clean up ...
     83  *    }
     84  *   return UPLUG_TOKEN;
     85  *  }
     86  * \endcode
     87  *
     88  * <p>The UPlugData*  is an opaque pointer to the plugin-specific data, and is
     89  * used in all other API calls.</p>
     90  *
     91  * <p>The API contract is:</p>
     92  * <ol><li>The plugin MUST always return UPLUG_TOKEN as a return value- to
     93  * indicate that it is a valid plugin.</li>
     94  *
     95  * <li>When the 'reason' parameter is set to UPLUG_REASON_QUERY,  the
     96  * plugin MUST call uplug_setPlugLevel() to indicate whether it is a high
     97  * level or low level plugin.</li>
     98  *
     99  * <li>When the 'reason' parameter is UPLUG_REASON_QUERY, the plugin
    100  * SHOULD call uplug_setPlugName to indicate a human readable plugin name.</li></ol>
    101  *
    102  *
    103  * \internal ICU 4.4 Technology Preview
    104  */
    105 
    106 
    107 #ifndef ICUPLUG_H
    108 #define ICUPLUG_H
    109 
    110 #include "unicode/utypes.h"
    111 
    112 
    113 #if UCONFIG_ENABLE_PLUGINS
    114 
    115 
    116 
    117 /* === Basic types === */
    118 
    119 #ifndef U_HIDE_INTERNAL_API
    120 /**
    121  * @{
    122  * Opaque structure passed to/from a plugin.
    123  * use the APIs to access it.
    124  * @internal ICU 4.4 Technology Preview
    125  */
    126 
    127 struct UPlugData;
    128 typedef struct UPlugData UPlugData;
    129 
    130 /** @} */
    131 
    132 /**
    133  * Random Token to identify a valid ICU plugin. Plugins must return this
    134  * from the entrypoint.
    135  * @internal ICU 4.4 Technology Preview
    136  */
    137 #define UPLUG_TOKEN 0x54762486
    138 
    139 /**
    140  * Max width of names, symbols, and configuration strings
    141  * @internal ICU 4.4 Technology Preview
    142  */
    143 #define UPLUG_NAME_MAX              100
    144 
    145 
    146 /**
    147  * Return value from a plugin entrypoint.
    148  * Must always be set to UPLUG_TOKEN
    149  * @see UPLUG_TOKEN
    150  * @internal ICU 4.4 Technology Preview
    151  */
    152 typedef uint32_t UPlugTokenReturn;
    153 
    154 /**
    155  * Reason code for the entrypoint's call
    156  * @internal ICU 4.4 Technology Preview
    157  */
    158 typedef enum {
    159     UPLUG_REASON_QUERY = 0,     /**< The plugin is being queried for info. **/
    160     UPLUG_REASON_LOAD = 1,     /**< The plugin is being loaded. **/
    161     UPLUG_REASON_UNLOAD = 2,   /**< The plugin is being unloaded. **/
    162     /**
    163      * Number of known reasons.
    164      * @internal The numeric value may change over time, see ICU ticket #12420.
    165      */
    166     UPLUG_REASON_COUNT
    167 } UPlugReason;
    168 
    169 
    170 /**
    171  * Level of plugin loading
    172  *     INITIAL:  UNKNOWN
    173  *       QUERY:   INVALID ->  { LOW | HIGH }
    174  *     ERR -> INVALID
    175  * @internal ICU 4.4 Technology Preview
    176  */
    177 typedef enum {
    178     UPLUG_LEVEL_INVALID = 0,     /**< The plugin is invalid, hasn't called uplug_setLevel, or can't load. **/
    179     UPLUG_LEVEL_UNKNOWN = 1,     /**< The plugin is waiting to be installed. **/
    180     UPLUG_LEVEL_LOW     = 2,     /**< The plugin must be called before u_init completes **/
    181     UPLUG_LEVEL_HIGH    = 3,     /**< The plugin can run at any time. **/
    182     /**
    183      * Number of known levels.
    184      * @internal The numeric value may change over time, see ICU ticket #12420.
    185      */
    186     UPLUG_LEVEL_COUNT
    187 } UPlugLevel;
    188 
    189 /**
    190  * Entrypoint for an ICU plugin.
    191  * @param plug the UPlugData handle.
    192  * @param status the plugin's extended status code.
    193  * @return A valid plugin must return UPLUG_TOKEN
    194  * @internal ICU 4.4 Technology Preview
    195  */
    196 typedef UPlugTokenReturn (U_EXPORT2 UPlugEntrypoint) (
    197                   UPlugData *plug,
    198                   UPlugReason reason,
    199                   UErrorCode *status);
    200 
    201 /* === Needed for Implementing === */
    202 
    203 /**
    204  * Request that this plugin not be unloaded at cleanup time.
    205  * This is appropriate for plugins which cannot be cleaned up.
    206  * @see u_cleanup()
    207  * @param plug plugin
    208  * @param dontUnload  set true if this plugin can't be unloaded
    209  * @internal ICU 4.4 Technology Preview
    210  */
    211 U_INTERNAL void U_EXPORT2
    212 uplug_setPlugNoUnload(UPlugData *plug, UBool dontUnload);
    213 
    214 /**
    215  * Set the level of this plugin.
    216  * @param plug plugin data handle
    217  * @param level the level of this plugin
    218  * @internal ICU 4.4 Technology Preview
    219  */
    220 U_INTERNAL void U_EXPORT2
    221 uplug_setPlugLevel(UPlugData *plug, UPlugLevel level);
    222 
    223 /**
    224  * Get the level of this plugin.
    225  * @param plug plugin data handle
    226  * @return the level of this plugin
    227  * @internal ICU 4.4 Technology Preview
    228  */
    229 U_INTERNAL UPlugLevel U_EXPORT2
    230 uplug_getPlugLevel(UPlugData *plug);
    231 
    232 /**
    233  * Get the lowest level of plug which can currently load.
    234  * For example, if UPLUG_LEVEL_LOW is returned, then low level plugins may load
    235  * if UPLUG_LEVEL_HIGH is returned, then only high level plugins may load.
    236  * @return the lowest level of plug which can currently load
    237  * @internal ICU 4.4 Technology Preview
    238  */
    239 U_INTERNAL UPlugLevel U_EXPORT2
    240 uplug_getCurrentLevel(void);
    241 
    242 
    243 /**
    244  * Get plug load status
    245  * @return The error code of this plugin's load attempt.
    246  * @internal ICU 4.4 Technology Preview
    247  */
    248 U_INTERNAL UErrorCode U_EXPORT2
    249 uplug_getPlugLoadStatus(UPlugData *plug);
    250 
    251 /**
    252  * Set the human-readable name of this plugin.
    253  * @param plug plugin data handle
    254  * @param name the name of this plugin. The first UPLUG_NAME_MAX characters willi be copied into a new buffer.
    255  * @internal ICU 4.4 Technology Preview
    256  */
    257 U_INTERNAL void U_EXPORT2
    258 uplug_setPlugName(UPlugData *plug, const char *name);
    259 
    260 /**
    261  * Get the human-readable name of this plugin.
    262  * @param plug plugin data handle
    263  * @return the name of this plugin
    264  * @internal ICU 4.4 Technology Preview
    265  */
    266 U_INTERNAL const char * U_EXPORT2
    267 uplug_getPlugName(UPlugData *plug);
    268 
    269 /**
    270  * Return the symbol name for this plugin, if known.
    271  * @param plug plugin data handle
    272  * @return the symbol name, or NULL
    273  * @internal ICU 4.4 Technology Preview
    274  */
    275 U_INTERNAL const char * U_EXPORT2
    276 uplug_getSymbolName(UPlugData *plug);
    277 
    278 /**
    279  * Return the library name for this plugin, if known.
    280  * @param plug plugin data handle
    281  * @param status error code
    282  * @return the library name, or NULL
    283  * @internal ICU 4.4 Technology Preview
    284  */
    285 U_INTERNAL const char * U_EXPORT2
    286 uplug_getLibraryName(UPlugData *plug, UErrorCode *status);
    287 
    288 /**
    289  * Return the library used for this plugin, if known.
    290  * Plugins could use this to load data out of their
    291  * @param plug plugin data handle
    292  * @return the library, or NULL
    293  * @internal ICU 4.4 Technology Preview
    294  */
    295 U_INTERNAL void * U_EXPORT2
    296 uplug_getLibrary(UPlugData *plug);
    297 
    298 /**
    299  * Return the plugin-specific context data.
    300  * @param plug plugin data handle
    301  * @return the context, or NULL if not set
    302  * @internal ICU 4.4 Technology Preview
    303  */
    304 U_INTERNAL void * U_EXPORT2
    305 uplug_getContext(UPlugData *plug);
    306 
    307 /**
    308  * Set the plugin-specific context data.
    309  * @param plug plugin data handle
    310  * @param context new context to set
    311  * @internal ICU 4.4 Technology Preview
    312  */
    313 U_INTERNAL void U_EXPORT2
    314 uplug_setContext(UPlugData *plug, void *context);
    315 
    316 
    317 /**
    318  * Get the configuration string, if available.
    319  * The string is in the platform default codepage.
    320  * @param plug plugin data handle
    321  * @return configuration string, or else null.
    322  * @internal ICU 4.4 Technology Preview
    323  */
    324 U_INTERNAL const char * U_EXPORT2
    325 uplug_getConfiguration(UPlugData *plug);
    326 
    327 /**
    328  * Return all currently installed plugins, from newest to oldest
    329  * Usage Example:
    330  * \code
    331  *    UPlugData *plug = NULL;
    332  *    while(plug=uplug_nextPlug(plug)) {
    333  *        ... do something with 'plug' ...
    334  *    }
    335  * \endcode
    336  * Not thread safe- do not call while plugs are added or removed.
    337  * @param prior pass in 'NULL' to get the first (most recent) plug,
    338  *  otherwise pass the value returned on a prior call to uplug_nextPlug
    339  * @return the next oldest plugin, or NULL if no more.
    340  * @internal ICU 4.4 Technology Preview
    341  */
    342 U_INTERNAL UPlugData* U_EXPORT2
    343 uplug_nextPlug(UPlugData *prior);
    344 
    345 /**
    346  * Inject a plugin as if it were loaded from a library.
    347  * This is useful for testing plugins.
    348  * Note that it will have a 'NULL' library pointer associated
    349  * with it, and therefore no llibrary will be closed at cleanup time.
    350  * Low level plugins may not be able to load, as ordering can't be enforced.
    351  * @param entrypoint entrypoint to install
    352  * @param config user specified configuration string, if available, or NULL.
    353  * @param status error result
    354  * @return the new UPlugData associated with this plugin, or NULL if error.
    355  * @internal ICU 4.4 Technology Preview
    356  */
    357 U_INTERNAL UPlugData* U_EXPORT2
    358 uplug_loadPlugFromEntrypoint(UPlugEntrypoint *entrypoint, const char *config, UErrorCode *status);
    359 
    360 
    361 /**
    362  * Inject a plugin from a library, as if the information came from a config file.
    363  * Low level plugins may not be able to load, and ordering can't be enforced.
    364  * @param libName DLL name to load
    365  * @param sym symbol of plugin (UPlugEntrypoint function)
    366  * @param config configuration string, or NULL
    367  * @param status error result
    368  * @return the new UPlugData associated with this plugin, or NULL if error.
    369  * @internal ICU 4.4 Technology Preview
    370  */
    371 U_INTERNAL UPlugData* U_EXPORT2
    372 uplug_loadPlugFromLibrary(const char *libName, const char *sym, const char *config, UErrorCode *status);
    373 
    374 /**
    375  * Remove a plugin.
    376  * Will request the plugin to be unloaded, and close the library if needed
    377  * @param plug plugin handle to close
    378  * @param status error result
    379  * @internal ICU 4.4 Technology Preview
    380  */
    381 U_INTERNAL void U_EXPORT2
    382 uplug_removePlug(UPlugData *plug, UErrorCode *status);
    383 #endif  /* U_HIDE_INTERNAL_API */
    384 
    385 #endif /* UCONFIG_ENABLE_PLUGINS */
    386 
    387 #endif /* _ICUPLUG */
    388 
    389