diff options
author | jmarshallnz <jmarshallnz@svn> | 2010-05-20 08:33:35 +0000 |
---|---|---|
committer | jmarshallnz <jmarshallnz@svn> | 2010-05-20 08:33:35 +0000 |
commit | 308ef534600e061929392f5c55341fa451cfcb64 (patch) | |
tree | c40bdeb0d4b099d23ca6379556a7ba142722f502 /lib | |
parent | c368caa329ba9ca7ba7e408fe684f6cb69fe9b7a (diff) |
added: load_plugin_descriptor_from_memory function to c-pluff
git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@30332 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
Diffstat (limited to 'lib')
-rw-r--r-- | lib/cpluff/libcpluff/cpluff.h | 19 | ||||
-rw-r--r-- | lib/cpluff/libcpluff/ploader.c | 179 |
2 files changed, 198 insertions, 0 deletions
diff --git a/lib/cpluff/libcpluff/cpluff.h b/lib/cpluff/libcpluff/cpluff.h index 12d65a7956..584ed0124a 100644 --- a/lib/cpluff/libcpluff/cpluff.h +++ b/lib/cpluff/libcpluff/cpluff.h @@ -1080,6 +1080,25 @@ CP_C_API int cp_is_logged(cp_context_t *ctx, cp_log_severity_t severity) CP_GCC_ CP_C_API cp_plugin_info_t * cp_load_plugin_descriptor(cp_context_t *ctx, const char *path, cp_status_t *status) CP_GCC_NONNULL(1, 2); /** + * Loads a plug-in descriptor from the specified block of memory and returns + * information about the plug-in. The plug-in descriptor + * is validated during loading. Possible loading errors are reported via the + * specified plug-in context. The plug-in is not installed to the context. + * If operation fails or the descriptor + * is invalid then NULL is returned. The caller must release the returned + * information by calling ::cp_release_plugin_info when it does not + * need the information anymore. + * The returned plug-in information must not be modified. + * + * @param ctx the plug-in context + * @param buffer the buffer containing the plug-in descriptor. + * @param buffer_len the length of the buffer. + * @param status a pointer to the location where status code is to be stored, or NULL + * @return pointer to the information structure or NULL if error occurs + */ +CP_C_API cp_plugin_info_t * cp_load_plugin_descriptor_from_memory(cp_context_t *context, const char *buffer, unsigned int buffer_len, cp_status_t *error) CP_GCC_NONNULL(1, 2); + +/** * Installs the plug-in described by the specified plug-in information * structure to the specified plug-in context. The plug-in information * must have been loaded using ::cp_load_plugin_descriptor with the same diff --git a/lib/cpluff/libcpluff/ploader.c b/lib/cpluff/libcpluff/ploader.c index 1e4c0ffb34..6c9a741f1d 100644 --- a/lib/cpluff/libcpluff/ploader.c +++ b/lib/cpluff/libcpluff/ploader.c @@ -1184,3 +1184,182 @@ CP_C_API cp_plugin_info_t * cp_load_plugin_descriptor(cp_context_t *context, con return plugin; } + +CP_C_API cp_plugin_info_t * cp_load_plugin_descriptor_from_memory(cp_context_t *context, const char *buffer, unsigned int buffer_len, cp_status_t *error) { + char *file = NULL; + const char *path = "memory"; + cp_status_t status = CP_OK; + XML_Parser parser = NULL; + ploader_context_t *plcontext = NULL; + cp_plugin_info_t *plugin = NULL; + + CHECK_NOT_NULL(context); + CHECK_NOT_NULL(buffer); + cpi_lock_context(context); + cpi_check_invocation(context, CPI_CF_ANY, __func__); + do { + int path_len = 6; + file = malloc((path_len + 1) * sizeof(char)); + if (file == NULL) { + status = CP_ERR_RESOURCE; + break; + } + strcpy(file, path); + + // Initialize the XML parsing + parser = XML_ParserCreate(NULL); + if (parser == NULL) { + status = CP_ERR_RESOURCE; + break; + } + XML_SetElementHandler(parser, + start_element_handler, + end_element_handler); + + // Initialize the parsing context + if ((plcontext = malloc(sizeof(ploader_context_t))) == NULL) { + status = CP_ERR_RESOURCE; + break; + } + memset(plcontext, 0, sizeof(ploader_context_t)); + if ((plcontext->plugin = malloc(sizeof(cp_plugin_info_t))) == NULL) { + status = CP_ERR_RESOURCE; + break; + } + plcontext->context = context; + plcontext->configuration = NULL; + plcontext->value = NULL; + plcontext->parser = parser; + plcontext->file = file; + plcontext->state = PARSER_BEGIN; + memset(plcontext->plugin, 0, sizeof(cp_plugin_info_t)); + plcontext->plugin->name = NULL; + plcontext->plugin->identifier = NULL; + plcontext->plugin->version = NULL; + plcontext->plugin->provider_name = NULL; + plcontext->plugin->abi_bw_compatibility = NULL; + plcontext->plugin->api_bw_compatibility = NULL; + plcontext->plugin->plugin_path = NULL; + plcontext->plugin->req_cpluff_version = NULL; + plcontext->plugin->imports = NULL; + plcontext->plugin->runtime_lib_name = NULL; + plcontext->plugin->runtime_funcs_symbol = NULL; + plcontext->plugin->ext_points = NULL; + plcontext->plugin->extensions = NULL; + XML_SetUserData(parser, plcontext); + + // Parse the plug-in descriptor + do { + void *xml_buffer; + int i; + + // Get buffer from Expat + if ((xml_buffer = XML_GetBuffer(parser, buffer_len)) + == NULL) { + status = CP_ERR_RESOURCE; + break; + } + + // Read data into buffer + memcpy(xml_buffer, buffer, buffer_len); + + // Parse the data + if (!(i = XML_ParseBuffer(parser, buffer_len, 1)) + && context != NULL) { + cpi_lock_context(context); + cpi_errorf(context, + N_("XML parsing error in %s, line %d, column %d (%s)."), + file, + XML_GetErrorLineNumber(parser), + XML_GetErrorColumnNumber(parser) + 1, + XML_ErrorString(XML_GetErrorCode(parser))); + cpi_unlock_context(context); + } + if (!i || plcontext->state == PARSER_ERROR) { + status = CP_ERR_MALFORMED; + break; + } + } while (0); + if (status == CP_OK) { + if (plcontext->state != PARSER_END || plcontext->error_count > 0) { + status = CP_ERR_MALFORMED; + } + if (plcontext->resource_error_count > 0) { + status = CP_ERR_RESOURCE; + } + } + if (status != CP_OK) { + break; + } + + // Initialize the plug-in path + *(file + path_len) = '\0'; + plcontext->plugin->plugin_path = file; + file = NULL; + + // Increase plug-in usage count + if ((status = cpi_register_info(context, plcontext->plugin, (void (*)(cp_context_t *, void *)) dealloc_plugin_info)) != CP_OK) { + break; + } + + } while (0); + + // Report possible errors + if (status != CP_OK) { + switch (status) { + case CP_ERR_MALFORMED: + cpi_errorf(context, + N_("Plug-in descriptor in %s is invalid."), path); + break; + case CP_ERR_IO: + cpi_debugf(context, + N_("An I/O error occurred while loading a plug-in descriptor from %s."), path); + break; + case CP_ERR_RESOURCE: + cpi_errorf(context, + N_("Insufficient system resources to load a plug-in descriptor from %s."), path); + break; + default: + cpi_errorf(context, + N_("Failed to load a plug-in descriptor from %s."), path); + break; + } + } + cpi_unlock_context(context); + + // Release persistently allocated data on failure + if (status != CP_OK) { + if (file != NULL) { + free(file); + file = NULL; + } + if (plcontext != NULL && plcontext->plugin != NULL) { + cpi_free_plugin(plcontext->plugin); + plcontext->plugin = NULL; + } + } + + // Otherwise copy the plug-in pointer + else { + plugin = plcontext->plugin; + } + + // Release data allocated for parsing + if (parser != NULL) { + XML_ParserFree(parser); + } + if (plcontext != NULL) { + if (plcontext->value != NULL) { + free(plcontext->value); + } + free(plcontext); + plcontext = NULL; + } + + // Return error code + if (error != NULL) { + *error = status; + } + + return plugin; +} |