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