diff options
author | Ross Burton <ross@linux.intel.com> | 2010-07-06 11:24:41 +0100 |
---|---|---|
committer | Ross Burton <ross@linux.intel.com> | 2010-07-08 21:17:06 +0100 |
commit | 23de181bdb4eae9fe769a8f20d5359cbf443e52a (patch) | |
tree | 4018c30910f2b65d9d5e937c08f1d5834f467a0a | |
parent | 69598d828dc7d1af656ceab8aa2b878885e957a3 (diff) | |
download | librest-23de181bdb4eae9fe769a8f20d5359cbf443e52a.tar.gz |
rest: add RestParam and RestParams types
-rw-r--r-- | docs/reference/rest/rest-docs.sgml | 2 | ||||
-rw-r--r-- | docs/reference/rest/rest-sections.txt | 35 | ||||
-rw-r--r-- | rest/Makefile.am | 7 | ||||
-rw-r--r-- | rest/rest-param.c | 309 | ||||
-rw-r--r-- | rest/rest-param.h | 83 | ||||
-rw-r--r-- | rest/rest-params.c | 242 | ||||
-rw-r--r-- | rest/rest-params.h | 53 |
7 files changed, 730 insertions, 1 deletions
diff --git a/docs/reference/rest/rest-docs.sgml b/docs/reference/rest/rest-docs.sgml index 9b90b99..9069bf8 100644 --- a/docs/reference/rest/rest-docs.sgml +++ b/docs/reference/rest/rest-docs.sgml @@ -8,6 +8,8 @@ <chapter> <title>REST Proxies</title> + <xi:include href="xml/rest-param.xml"/> + <xi:include href="xml/rest-params.xml"/> <xi:include href="xml/rest-proxy.xml"/> <xi:include href="xml/rest-proxy-call.xml"/> <xi:include href="xml/oauth-proxy.xml"/> diff --git a/docs/reference/rest/rest-sections.txt b/docs/reference/rest/rest-sections.txt index d8fb8b9..0c67108 100644 --- a/docs/reference/rest/rest-sections.txt +++ b/docs/reference/rest/rest-sections.txt @@ -36,6 +36,7 @@ rest_proxy_call_add_headers_from_valist rest_proxy_call_lookup_header rest_proxy_call_remove_header rest_proxy_call_add_param +rest_proxy_call_add_param_full rest_proxy_call_add_params rest_proxy_call_add_params_from_valist rest_proxy_call_lookup_param @@ -174,3 +175,37 @@ OAUTH_PROXY_CLASS OAUTH_IS_PROXY_CLASS OAUTH_PROXY_GET_CLASS </SECTION> + +<SECTION> +<FILE>rest-params</FILE> +<TITLE>RestParams</TITLE> +RestParams +RestParamsIter +rest_params_new +rest_params_free +rest_params_add +rest_params_get +rest_params_remove +rest_params_are_strings +rest_params_as_string_hash_table +rest_params_iter_init +rest_params_iter_next +</SECTION> + +<SECTION> +<FILE>rest-param</FILE> +<TITLE>RestParam</TITLE> +RestMemoryUse +RestParam +rest_param_new_string +rest_param_new_full +rest_param_new_with_owner +rest_param_is_string +rest_param_get_name +rest_param_get_content_type +rest_param_get_file_name +rest_param_get_content +rest_param_get_content_length +rest_param_ref +rest_param_unref +</SECTION> diff --git a/rest/Makefile.am b/rest/Makefile.am index a5bbf0e..c77c39c 100644 --- a/rest/Makefile.am +++ b/rest/Makefile.am @@ -3,6 +3,8 @@ CLEANFILES = # For some reason I can't use $(librest_@API_VERSION@_la_SOURCES) in # test_runner_SOURCES, so we have to do this lib_sources = \ + rest-param.c \ + rest-params.c \ rest-proxy.c \ rest-proxy-call.c \ rest-proxy-call-private.h \ @@ -17,7 +19,10 @@ lib_sources = \ oauth2-proxy-private.h \ sha1.c \ sha1.h -lib_headers = rest-proxy.h \ +lib_headers = \ + rest-param.h \ + rest-params.h \ + rest-proxy.h \ rest-proxy-call.h \ oauth-proxy.h \ oauth-proxy-call.h \ diff --git a/rest/rest-param.c b/rest/rest-param.c new file mode 100644 index 0000000..2709c88 --- /dev/null +++ b/rest/rest-param.c @@ -0,0 +1,309 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2010 Intel Corporation. + * + * Authors: Ross Burton <ross@linux.intel.com> + * Rob Bradford <rob@linux.intel.com> + * + * RestParam is inspired by libsoup's SoupBuffer + * Copyright (C) 2000-2030 Ximian, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <config.h> +#include <string.h> +#include "rest-param.h" + +/** + * SECTION:rest-param + * @short_description: Name/value parameter data type with intelligent memory + * management + * @see_also: #RestParams, #RestProxyCall. + */ + +/* Internal RestMemoryUse values */ +enum { + REST_MEMORY_OWNED = REST_MEMORY_COPY + 1 +}; + +struct _RestParam { + char *name; + RestMemoryUse use; + gconstpointer data; + gsize length; + const char *content_type; + char *filename; + + volatile gint ref_count; + gpointer owner; + GDestroyNotify owner_dnotify; +}; + +/** + * rest_param_new_full: + * @name: the parameter name + * @use: the #RestMemoryUse describing how the memory can be used + * @data: a pointer to the start of the data + * @length: the length of the data + * @content_type: the content type of the data + * @filename: the original filename, or %NULL + * + * Create a new #RestParam called @name with @length bytes of @data as the + * value. @content_type is the type of the data as a MIME type, for example + * "text/plain" for simple string parameters. + * + * If the parameter is a file upload it can be passed as @filename. + * + * Returns: a new #RestParam. + **/ +RestParam * +rest_param_new_full (const char *name, + RestMemoryUse use, + gconstpointer data, + gsize length, + const char *content_type, + const char *filename) +{ + RestParam *param; + + param = g_slice_new0 (RestParam); + + if (use == REST_MEMORY_COPY) { + data = g_memdup (data, length); + use = REST_MEMORY_TAKE; + } + + param->name = g_strdup (name); + param->use = use; + param->data = data; + param->length = length; + + param->content_type = g_intern_string (content_type); + param->filename = g_strdup (filename); + + param->ref_count = 1; + + if (use == REST_MEMORY_TAKE) { + param->owner = (gpointer)data; + param->owner_dnotify = g_free; + } + + return param; +} + +/** + * rest_param_new_with_owner: + * @name: the parameter name + * @data: a pointer to the start of the data + * @length: the length of the data + * @content_type: the content type of the data + * @filename: the original filename, or %NULL + * @owner: pointer to an object that owns @data + * @owner_dnotify: a function to free/unref @owner when the buffer is freed + * + * Create a new #RestParam called @name with @length bytes of @data as the + * value. @content_type is the type of the data as a MIME type, for example + * "text/plain" for simple string parameters. + * + * If the parameter is a file upload it can be passed as @filename. + * + * When the #RestParam is freed, it will call @owner_dnotify, passing @owner to + * it. This allows you to do something like this: + * + * |[ + * GMappedFile *map = g_mapped_file_new (filename, FALSE, &error); + * RestParam *param = rest_param_new_with_owner ("media", + * g_mapped_file_get_contents (map), + * g_mapped_file_get_length (map), + * "image/jpeg", + * filename, + * map, + * (GDestroyNotify)g_mapped_file_unref); + * ]| + * + * Returns: a new #RestParam. + **/ +RestParam * +rest_param_new_with_owner (const char *name, + gconstpointer data, + gsize length, + const char *content_type, + const char *filename, + gpointer owner, + GDestroyNotify owner_dnotify) +{ + RestParam *param; + + param = g_slice_new0 (RestParam); + + param->name = g_strdup (name); + + param->use = REST_MEMORY_OWNED; + param->data = data; + param->length = length; + + param->content_type = g_intern_string (content_type); + param->filename = g_strdup (filename); + + param->ref_count = 1; + + param->owner = owner; + param->owner_dnotify = owner_dnotify; + + return param; +} + +/** + * rest_param_new_string: + * @name: the parameter name + * @use: the #RestMemoryUse describing how the memory can be used + * @string: the parameter value + * + * A convience constructor to create a #RestParam from a given UTF-8 string. + * The resulting #RestParam will have a content type of "text/plain". + * + * Returns: a new #RestParam. + **/ +RestParam * +rest_param_new_string (const char *name, + RestMemoryUse use, + const char *string) +{ + return rest_param_new_full (name, + use, string, strlen (string) + 1, + g_intern_static_string ("text/plain"), + NULL); +} + +/** + * rest_param_get_name: + * @param: a valid #RestParam + * + * Get the name of the parameter. + * + * Returns: the parameter name. + **/ +const char * +rest_param_get_name (RestParam *param) +{ + return param->name; +} + +/** + * rest_param_get_content_type: + * @param: a valid #RestParam + * + * Get the MIME type of the parameter. For example, basic strings have the MIME + * type "text/plain". + * + * Returns: the MIME type + **/ +const char * +rest_param_get_content_type (RestParam *param) +{ + return param->content_type; +} + +/** + * rest_param_get_file_name: + * @param: a valid #RestParam + * + * Get the original file name of the parameter, if one is available. + * + * Returns: the filename if set, or %NULL. + **/ +const char * +rest_param_get_file_name (RestParam *param) +{ + return param->filename; +} + +gboolean +rest_param_is_string (RestParam *param) +{ + return param->content_type == g_intern_static_string ("text/plain"); +} + +/** + * rest_param_get_content: + * @param: a valid #RestParam + * + * Get the content of @param. The content should be treated as read-only and + * not modified in any way. + * + * Returns: the content. + **/ +gconstpointer +rest_param_get_content (RestParam *param) +{ + return param->data; +} + +/** + * rest_param_get_content_length: + * @param: a valid #RestParam + * + * Get the length of the content of @param. + * + * Returns: the length of the content + **/ +gsize +rest_param_get_content_length (RestParam *param) +{ + return param->length; +} + +/** + * rest_param_ref: + * @param: a valid #RestParam + * + * Increase the reference count on @param. + * + * Returns: the #RestParam + **/ +RestParam * +rest_param_ref (RestParam *param) +{ + /* TODO: bring back REST_MEMORY_TEMPORARY? */ + g_return_val_if_fail (param, NULL); + g_return_val_if_fail (param->ref_count > 0, NULL); + + g_atomic_int_inc (¶m->ref_count); + + return param; +} + +/** + * rest_param_unref: + * @param: a valid #RestParam + * + * Decrease the reference count on @param, destroying it if the reference count + * reaches 0. + **/ +void +rest_param_unref (RestParam *param) +{ + g_return_if_fail (param); + + if (g_atomic_int_dec_and_test (¶m->ref_count)) { + if (param->owner_dnotify) + param->owner_dnotify (param->owner); + g_free (param->name); + g_free (param->filename); + + g_slice_free (RestParam, param); + } +} diff --git a/rest/rest-param.h b/rest/rest-param.h new file mode 100644 index 0000000..49bf0e1 --- /dev/null +++ b/rest/rest-param.h @@ -0,0 +1,83 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2010 Intel Corporation. + * + * Authors: Ross Burton <ross@linux.intel.com> + * Rob Bradford <rob@linux.intel.com> + * + * RestParam is inspired by libsoup's SoupBuffer + * Copyright (C) 2000-2030 Ximian, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _REST_PARAM +#define _REST_PARAM + +#include <glib-object.h> + +G_BEGIN_DECLS + +/** + * RestMemoryUse: + * @REST_MEMORY_STATIC: the memory block can be assumed to always exist for the + * lifetime of the parameter, #RestParam will use it directly. + * @REST_MEMORY_TAKE: #RestParam will take ownership of the memory block, and + * g_free() it when it isn't used. + * @REST_MEMORY_COPY: #RestParam will make a copy of the memory block. + */ +typedef enum { + REST_MEMORY_STATIC, + REST_MEMORY_TAKE, + REST_MEMORY_COPY, +} RestMemoryUse; + + +typedef struct _RestParam RestParam; + +RestParam *rest_param_new_string (const char *name, + RestMemoryUse use, + const char *string); + +RestParam *rest_param_new_full (const char *name, + RestMemoryUse use, + gconstpointer data, + gsize length, + const char *content_type, + const char *filename); + +RestParam *rest_param_new_with_owner (const char *name, + gconstpointer data, + gsize length, + const char *content_type, + const char *filename, + gpointer owner, + GDestroyNotify owner_dnotify); + + +gboolean rest_param_is_string (RestParam *param); + +const char *rest_param_get_name (RestParam *param); +const char *rest_param_get_content_type (RestParam *param); +const char *rest_param_get_file_name (RestParam *param); +gconstpointer rest_param_get_content (RestParam *param); +gsize rest_param_get_content_length (RestParam *param); + +RestParam *rest_param_ref (RestParam *param); +void rest_param_unref (RestParam *param); + +G_END_DECLS + +#endif /* _REST_PARAM */ diff --git a/rest/rest-params.c b/rest/rest-params.c new file mode 100644 index 0000000..dc48fd8 --- /dev/null +++ b/rest/rest-params.c @@ -0,0 +1,242 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <config.h> +#include <glib-object.h> +#include "rest-params.h" + +/** + * SECTION:rest-params + * @short_description: Container for call parameters + * @see_also: #RestParam, #RestProxyCall. + */ + +/* + * RestParams is an alias for GHashTable achieved by opaque types in the public + * headers and casting internally. This has several limitations, mainly + * supporting multiple parameters with the same name and preserving the ordering + * of parameters. + * + * These are not requirements for the bulk of the web services, but this + * limitation does mean librest can't be used for a few web services. + * + * TODO: this should be a list to support multiple parameters with the same + * name. + */ + +/** + * rest_params_new: + * + * Create a new #RestParams. + * + * Returns: A empty #RestParams. + **/ +RestParams * +rest_params_new (void) +{ + /* The key is a string that is owned by the RestParam, so we don't need to + explicitly free it on removal. */ + return (RestParams *) + g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, (GDestroyNotify)rest_param_unref); +} + +/** + * rest_params_free: + * @params: a valid #RestParams + * + * Destroy the #RestParams and the #RestParam objects that it contains. + **/ +void +rest_params_free (RestParams *params) +{ + GHashTable *hash = (GHashTable *)params; + + g_return_if_fail (params); + + g_hash_table_destroy (hash); +} + +/** + * rest_params_add: + * @params: a valid #RestParams + * @param: a valid #RestParam + * + * Add @param to @params. + **/ +void +rest_params_add (RestParams *params, RestParam *param) +{ + GHashTable *hash = (GHashTable *)params; + + g_return_if_fail (params); + g_return_if_fail (param); + + g_hash_table_insert (hash, (gpointer)rest_param_get_name (param), param); +} + +/** + * rest_params_get: + * @params: a valid #RestParams + * @name: a parameter name + * + * Return the #RestParam called @name, or %NULL if it doesn't exist. + * + * Returns: a #RestParam or %NULL if the name doesn't exist + **/ +RestParam * +rest_params_get (RestParams *params, const char *name) +{ + GHashTable *hash = (GHashTable *)params; + + g_return_val_if_fail (params, NULL); + g_return_val_if_fail (name, NULL); + + return g_hash_table_lookup (hash, name); +} + +/** + * rest_params_remove: + * @params: a valid #RestParams + * @name: a parameter name + * + * Remove the #RestParam called @name. + **/ +void +rest_params_remove (RestParams *params, const char *name) +{ + GHashTable *hash = (GHashTable *)params; + + g_return_if_fail (params); + g_return_if_fail (name); + + g_hash_table_remove (hash, name); +} + +/** + * rest_params_are_strings: + * @params: a valid #RestParams + * + * Checks if the parameters are all simple strings (have a content type of + * "text/plain"). + * + * Returns: %TRUE if all of the parameters are simple strings, %FALSE otherwise. + **/ +gboolean +rest_params_are_strings (RestParams *params) +{ + GHashTable *hash = (GHashTable *)params; + GHashTableIter iter; + RestParam *param; + + g_return_val_if_fail (params, FALSE); + + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, NULL, (gpointer)¶m)) { + if (!rest_param_is_string (param)) + return FALSE; + } + + return TRUE; + +} + +/** + * rest_params_as_string_hash_table: + * @params: a valid #RestParams + * + * Create a new #GHashTable which contains the name and value of all string + * (content type of text/plain) parameters. + * + * The values are owned by the #RestParams, so don't destroy the #RestParams + * before the hash table. + * + * Returns: a new #GHashTable. + **/ +GHashTable * +rest_params_as_string_hash_table (RestParams *params) +{ + GHashTable *hash, *strings; + GHashTableIter iter; + const char *name = NULL; + RestParam *param = NULL; + + g_return_val_if_fail (params, NULL); + g_return_val_if_fail (rest_params_are_strings (params), NULL); + + hash = (GHashTable *)params; + strings = g_hash_table_new (g_str_hash, g_str_equal); + + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, (gpointer)&name, (gpointer)¶m)) { + g_hash_table_insert (strings, (gpointer)name, (gpointer)rest_param_get_content (param)); + } + + return strings; +} + +/** + * rest_params_iter_init: + * @iter: an uninitialized #RestParamIter + * @params: a valid #RestParams + * + * Initialize a parameter iterator over @params. Modifying @params after calling + * this function invalidates the returned iterator. + * |[ + * RestParamsIter iter; + * const char *name; + * RestParam *param; + * + * rest_params_iter_init (&iter, params); + * while (rest_params_iter_next (&iter, &name, ¶m)) { + * /* do something with name and param */ + * } + * ]| + **/ +void +rest_params_iter_init (RestParamsIter *iter, RestParams *params) +{ + g_return_if_fail (iter); + g_return_if_fail (params); + + g_hash_table_iter_init ((GHashTableIter *)iter, (GHashTable *)params); +} + +/** + * rest_params_iter_next: + * @iter: an initialized #RestParamsIter + * @name: a location to store the name, or %NULL + * @param: a location to store the #RestParam, or %NULL + * + * Advances @iter and retrieves the name and/or parameter that are now pointed + * at as a result of this advancement. If FALSE is returned, @name and @param + * are not set and the iterator becomes invalid. + * + * Returns: %FALSE if the end of the #RestParams has been reached, %TRUE otherwise. + **/ +gboolean +rest_params_iter_next (RestParamsIter *iter, const char **name, RestParam **param) +{ + g_return_val_if_fail (iter, FALSE); + + return g_hash_table_iter_next ((GHashTableIter *)iter, (gpointer)name, (gpointer)param); +} diff --git a/rest/rest-params.h b/rest/rest-params.h new file mode 100644 index 0000000..caace9d --- /dev/null +++ b/rest/rest-params.h @@ -0,0 +1,53 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _REST_PARAMS +#define _REST_PARAMS + +#include <glib-object.h> +#include "rest-param.h" + +G_BEGIN_DECLS + +typedef struct _RestParams RestParams; +typedef struct _GHashTableIter RestParamsIter; + +RestParams * rest_params_new (void); + +void rest_params_free (RestParams *params); + +void rest_params_add (RestParams *params, RestParam *param); + +RestParam *rest_params_get (RestParams *params, const char *name); + +void rest_params_remove (RestParams *params, const char *name); + +gboolean rest_params_are_strings (RestParams *params); + +GHashTable * rest_params_as_string_hash_table (RestParams *params); + +void rest_params_iter_init (RestParamsIter *iter, RestParams *params); +gboolean rest_params_iter_next (RestParamsIter *iter, const char **name, RestParam **param); + +G_END_DECLS + +#endif /* _REST_PARAMS */ |