static unsigned int squash_atomic_cas (volatile unsigned int* var, unsigned int orig, unsigned int val) { unsigned int res; SQUASH_MTX_LOCK(atomic_ref); res = *var; if (res == orig) *var = val; SQUASH_MTX_UNLOCK(atomic_ref); return res; }
/** * @brief Initialize a codec * @private * * @param plugin The plugin. * @param codec The codec to initialize. * @param impl The function table to fill. * @returns A status code. */ SquashStatus squash_plugin_init_codec (SquashPlugin* plugin, SquashCodec* codec, SquashCodecImpl* impl) { SquashStatus res = SQUASH_OK; assert (plugin != NULL); if (plugin->plugin == NULL) { res = squash_plugin_init (plugin); if (res != SQUASH_OK) { return res; } } if (codec->initialized == 0) { SquashStatus (*init_codec_func) (SquashCodec*, SquashCodecImpl*); #if !defined(_WIN32) *(void **) (&init_codec_func) = dlsym (plugin->plugin, "squash_plugin_init_codec"); #else *(void **) (&init_codec_func) = GetProcAddress (plugin->plugin, "squash_plugin_init_codec"); #endif if (SQUASH_UNLIKELY(init_codec_func == NULL)) { return squash_error (SQUASH_UNABLE_TO_LOAD); } SQUASH_MTX_LOCK(codec_init); if (SQUASH_LIKELY(codec->initialized == 0)) { res = init_codec_func (codec, impl); codec->initialized = (res == SQUASH_OK); assert ((codec->impl.info & SQUASH_CODEC_INFO_AUTO_MASK) == 0); if (codec->impl.process_stream != NULL) codec->impl.info |= (SquashCodecInfo) SQUASH_CODEC_INFO_NATIVE_STREAMING; if (codec->impl.get_uncompressed_size != NULL || (codec->impl.info & SQUASH_CODEC_INFO_WRAP_SIZE)) codec->impl.info |= (SquashCodecInfo) SQUASH_CODEC_INFO_KNOWS_UNCOMPRESSED_SIZE; } SQUASH_MTX_UNLOCK(codec_init); } return res; }
/** * @brief load a %SquashPlugin * * @note This function is generally only useful inside of a callback * passed to ::squash_foreach_plugin. Every other way to get a plugin * (such as ::squash_get_plugin) will initialize the plugin as well * (and return *NULL* instead of the plugin if initialization fails). * The foreach functions, however, do not initialize the plugin since * doing so requires actually loading the plugin. * * @param plugin The plugin to load. * @return A status code. * @retval SQUASH_OK The plugin has been loaded. * @retval SQUASH_UNABLE_TO_LOAD Unable to load plugin. */ SquashStatus squash_plugin_init (SquashPlugin* plugin) { if (plugin->plugin == NULL) { #if !defined(_WIN32) void* handle; #else HMODULE handle; #endif char* plugin_file_name; size_t plugin_dir_length; size_t plugin_name_length; size_t plugin_file_name_max_length; size_t squash_version_api_length = strlen (SQUASH_VERSION_API); plugin_dir_length = strlen (plugin->directory); plugin_name_length = strlen (plugin->name); plugin_file_name_max_length = plugin_dir_length + squash_version_api_length + plugin_name_length + 19 + strlen (SQUASH_SHARED_LIBRARY_SUFFIX); plugin_file_name = (char*) malloc (plugin_file_name_max_length + 1); snprintf (plugin_file_name, plugin_file_name_max_length + 1, "%s/libsquash%s-plugin-%s%s", plugin->directory, SQUASH_VERSION_API, plugin->name, SQUASH_SHARED_LIBRARY_SUFFIX); #if !defined(_WIN32) handle = dlopen (plugin_file_name, RTLD_LAZY); #else handle = LoadLibrary (TEXT(plugin_file_name)); #endif if (handle == NULL) { fprintf (stderr, "=== %s\n", dlerror ()); } free (plugin_file_name); if (handle != NULL) { SQUASH_MTX_LOCK(plugin_init); if (plugin->plugin == NULL) { plugin->plugin = handle; handle = NULL; } SQUASH_MTX_UNLOCK(plugin_init); } else { return squash_error (SQUASH_UNABLE_TO_LOAD); } if (handle != NULL) { #if !defined(_WIN32) dlclose (handle); #else FreeLibrary (handle); #endif } else { SquashStatus (*init_func) (SquashPlugin*); #if !defined(_WIN32) *(void **) (&init_func) = dlsym (plugin->plugin, "squash_plugin_init"); #else *(void **) (&init_func) = GetProcAddress (handle, "squash_plugin_init"); #endif if (init_func != NULL) { init_func (plugin); } } } return (plugin->plugin != NULL) ? SQUASH_OK : squash_error (SQUASH_UNABLE_TO_LOAD); }
/** * @brief load a %SquashPlugin * * @note This function is generally only useful inside of a callback * passed to ::squash_foreach_plugin. Every other way to get a plugin * (such as ::squash_get_plugin) will initialize the plugin as well * (and return *NULL* instead of the plugin if initialization fails). * The foreach functions, however, do not initialize the plugin since * doing so requires actually loading the plugin. * * @param plugin The plugin to load. * @return A status code. * @retval SQUASH_OK The plugin has been loaded. * @retval SQUASH_UNABLE_TO_LOAD Unable to load plugin. */ SquashStatus squash_plugin_init (SquashPlugin* plugin) { if (plugin->plugin == NULL) { #if !defined(_WIN32) void* handle; #else HMODULE handle; #endif char* plugin_file_name; plugin_file_name = squash_strdup_printf ("%s/%ssquash%s-plugin-%s%s", plugin->directory, SQUASH_SHARED_LIBRARY_PREFIX, SQUASH_VERSION_API, plugin->name, SQUASH_SHARED_LIBRARY_SUFFIX); if (plugin_file_name == NULL) return squash_error (SQUASH_MEMORY); #if !defined(_WIN32) handle = dlopen (plugin_file_name, RTLD_LAZY); #else handle = LoadLibrary (TEXT(plugin_file_name)); if (handle == NULL) { squash_free (plugin_file_name); #if defined(_DEBUG) plugin_file_name = squash_strdup_printf ("%s/Debug/%ssquash%s-plugin-%s%s", plugin->directory, SQUASH_SHARED_LIBRARY_PREFIX, SQUASH_VERSION_API, plugin->name, SQUASH_SHARED_LIBRARY_SUFFIX); #else plugin_file_name = squash_strdup_printf ("%s/Release/%ssquash%s-plugin-%s%s", plugin->directory, SQUASH_SHARED_LIBRARY_PREFIX, SQUASH_VERSION_API, plugin->name, SQUASH_SHARED_LIBRARY_SUFFIX); #endif handle = LoadLibrary (TEXT(plugin_file_name)); } #endif squash_free (plugin_file_name); if (SQUASH_LIKELY(handle != NULL)) { SQUASH_MTX_LOCK(plugin_init); if (plugin->plugin == NULL) { plugin->plugin = handle; handle = NULL; } SQUASH_MTX_UNLOCK(plugin_init); } else { return squash_error (SQUASH_UNABLE_TO_LOAD); } if (handle != NULL) { #if !defined(_WIN32) dlclose (handle); #else FreeLibrary (handle); #endif } else { SquashStatus (*init_func) (SquashPlugin*); #if !defined(_WIN32) *(void **) (&init_func) = dlsym (plugin->plugin, "squash_plugin_init_plugin"); #else *(void **) (&init_func) = GetProcAddress (plugin->plugin, "squash_plugin_init_plugin"); #endif if (init_func != NULL) { init_func (plugin); } } } return SQUASH_LIKELY(plugin->plugin != NULL) ? SQUASH_OK : squash_error (SQUASH_UNABLE_TO_LOAD); }