From 9adc9e9d0dea849093e4520091dd06c9fb850e6f Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 1 Feb 2008 15:23:31 +0000 Subject: [PATCH] new * libsoup/soup-date.c (soup_date_to_time_t): new * libsoup/soup-form.c (soup_form_decode): Remove "_urlencoded" from name. (And add back-compat #define.) (soup_form_encode): New, takes varargs parameters for each form construction. (soup_form_encode_hash, soup_form_encode_datalist): renamed, with back-compat #defines (soup_form_request_new, soup_form_request_new_from_hash) (soup_form_request_new_from_datalist): New methods to construct a GET or POST message with form data. * libsoup/soup-uri.c (soup_uri_set_query_from_fields): New, takes varargs like soup_form_encode(). * libsoup/soup-value-utils.c (soup_value_hash_new_with_vals) (soup_value_hash_insert_vals, soup_value_hash_lookup_vals): New routines to work with multiple value hash values at once. (soup_value_array_new): tiny wrapper, for naming consistency (soup_value_array_new_with_vals, soup_value_array_append_vals): New routines to work with multiple value array values at once. svn path=/trunk/; revision=1063 --- ChangeLog | 24 ++++++ gtk-doc.make | 42 +++++++--- libsoup/soup-date.c | 51 ++++++++++++ libsoup/soup-date.h | 2 + libsoup/soup-form.c | 194 +++++++++++++++++++++++++++++++++++++++++---- libsoup/soup-form.h | 28 ++++++- libsoup/soup-uri.c | 27 ++++++- libsoup/soup-uri.h | 83 +++++++++---------- libsoup/soup-value-utils.c | 183 ++++++++++++++++++++++++++++++++++++++++++ libsoup/soup-value-utils.h | 69 +++++++++------- tests/Makefile.am | 1 + tests/query-test.c | 14 +--- 12 files changed, 606 insertions(+), 112 deletions(-) diff --git a/ChangeLog b/ChangeLog index 62bcf11..aeb1e0d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2008-01-31 Dan Winship + + * libsoup/soup-date.c (soup_date_to_time_t): new + + * libsoup/soup-form.c (soup_form_decode): Remove "_urlencoded" + from name. (And add back-compat #define.) + (soup_form_encode): New, takes varargs parameters for each form + construction. + (soup_form_encode_hash, soup_form_encode_datalist): renamed, with + back-compat #defines + (soup_form_request_new, soup_form_request_new_from_hash) + (soup_form_request_new_from_datalist): New methods to construct a + GET or POST message with form data. + + * libsoup/soup-uri.c (soup_uri_set_query_from_fields): New, takes + varargs like soup_form_encode(). + + * libsoup/soup-value-utils.c (soup_value_hash_new_with_vals) + (soup_value_hash_insert_vals, soup_value_hash_lookup_vals): New + routines to work with multiple value hash values at once. + (soup_value_array_new): tiny wrapper, for naming consistency + (soup_value_array_new_with_vals, soup_value_array_append_vals): + New routines to work with multiple value array values at once. + 2008-01-28 Dan Winship * configure.in: post-release bump to 2.3.1 diff --git a/gtk-doc.make b/gtk-doc.make index 8056cd6..354ffb7 100644 --- a/gtk-doc.make +++ b/gtk-doc.make @@ -5,11 +5,11 @@ #################################### if GTK_DOC_USE_LIBTOOL -GTKDOC_CC = $(LIBTOOL) --mode=compile $(CC) $(INCLUDES) $(AM_CFLAGS) $(CFLAGS) -GTKDOC_LD = $(LIBTOOL) --mode=link $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) +GTKDOC_CC = $(LIBTOOL) --mode=compile $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(LIBTOOL) --mode=link $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) else -GTKDOC_CC = $(CC) $(INCLUDES) $(AM_CFLAGS) $(CFLAGS) -GTKDOC_LD = $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) +GTKDOC_CC = $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) endif # We set GPATH here; this gives us semantics for GNU make @@ -38,7 +38,12 @@ SCANOBJ_FILES = \ $(DOC_MODULE).prerequisites \ $(DOC_MODULE).signals -CLEANFILES = $(SCANOBJ_FILES) $(DOC_MODULE)-unused.txt $(DOC_STAMPS) +REPORT_FILES = \ + $(DOC_MODULE)-undocumented.txt \ + $(DOC_MODULE)-undeclared.txt \ + $(DOC_MODULE)-unused.txt + +CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) if ENABLE_GTK_DOC all-local: html-build.stamp @@ -79,6 +84,10 @@ tmpl-build.stamp: $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections tmpl.stamp: tmpl-build.stamp @true +tmpl/*.sgml: + @true + + #### xml #### sgml-build.stamp: tmpl.stamp $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(srcdir)/tmpl/*.sgml $(expand_content_files) @@ -96,11 +105,11 @@ sgml.stamp: sgml-build.stamp html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) @echo 'gtk-doc: Building HTML' @-chmod -R u+w $(srcdir) - rm -rf $(srcdir)/html + rm -rf $(srcdir)/html mkdir $(srcdir)/html cd $(srcdir)/html && gtkdoc-mkhtml $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) html ) - @echo 'gtk-doc: Fixing cross-references' + @echo 'gtk-doc: Fixing cross-references' cd $(srcdir) && gtkdoc-fixxref --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) touch html-build.stamp @@ -110,11 +119,16 @@ clean-local: rm -f *~ *.bak rm -rf .libs +distclean-local: + cd $(srcdir) && \ + rm -rf xml $(REPORT_FILES) \ + $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + maintainer-clean-local: clean - cd $(srcdir) && rm -rf xml html $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + cd $(srcdir) && rm -rf xml html install-data-local: - installfiles=`echo $(srcdir)/html/*`; \ + -installfiles=`echo $(srcdir)/html/*`; \ if test "$$installfiles" = '$(srcdir)/html/*'; \ then echo '-- Nothing to install' ; \ else \ @@ -125,7 +139,10 @@ install-data-local: done; \ echo '-- Installing $(srcdir)/html/index.sgml' ; \ $(INSTALL_DATA) $(srcdir)/html/index.sgml $(DESTDIR)$(TARGET_DIR) || :; \ + which gtkdoc-rebase >/dev/null && \ + gtkdoc-rebase --relative --dest-dir=$(DESTDIR) --html-dir=$(DESTDIR)$(TARGET_DIR) ; \ fi + uninstall-local: rm -f $(DESTDIR)$(TARGET_DIR)/* @@ -148,8 +165,9 @@ dist-hook: dist-check-gtkdoc dist-hook-local -cp $(srcdir)/tmpl/*.sgml $(distdir)/tmpl -cp $(srcdir)/xml/*.xml $(distdir)/xml cp $(srcdir)/html/* $(distdir)/html - if test -f $(srcdir)/$(DOC_MODULE).types; then \ - cp $(srcdir)/$(DOC_MODULE).types $(distdir)/$(DOC_MODULE).types; \ - fi + -cp $(srcdir)/$(DOC_MODULE).types $(distdir)/ + -cp $(srcdir)/$(DOC_MODULE)-sections.txt $(distdir)/ + cd $(distdir) && rm -f $(DISTCLEANFILES) + -gtkdoc-rebase --online --relative --html-dir=$(distdir)/html .PHONY : dist-hook-local docs diff --git a/libsoup/soup-date.c b/libsoup/soup-date.c index 7dddb8a..02a26ec 100644 --- a/libsoup/soup-date.c +++ b/libsoup/soup-date.c @@ -497,6 +497,57 @@ soup_date_to_string (SoupDate *date, SoupDateFormat format) } /** + * soup_date_to_time_t: + * @date: a #SoupDate + * + * Converts @date to a %time_t + * + * Return value: @date as a %time_t + **/ +time_t +soup_date_to_time_t (SoupDate *date) +{ +#ifndef HAVE_TIMEGM + time_t tt; + static const int days_before[] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 + }; +#endif + struct tm tm; + + /* FIXME: offset, etc */ + + tm.tm_year = date->year - 1900; + tm.tm_mon = date->month - 1; + tm.tm_mday = date->day; + tm.tm_hour = date->hour; + tm.tm_min = date->minute; + tm.tm_sec = date->second; + +#if HAVE_TIMEGM + return timegm (&tm); +#else + /* We check the month because (a) if we don't, the + * days_before[] part below may access random memory, and (b) + * soup_date_parse() doesn't check the return value of + * parse_month(). The caller is responsible for ensuring the + * sanity of everything else. + */ + if (tm.tm_mon < 0 || tm.tm_mon > 11) + return (time_t)-1; + + tt = (tm.tm_year - 70) * 365; + tt += (tm.tm_year - 68) / 4; + tt += days_before[tm.tm_mon] + tm.tm_mday - 1; + if (tm.tm_year % 4 == 0 && tm.tm_mon < 2) + tt--; + tt = ((((tt * 24) + tm.tm_hour) * 60) + tm.tm_min) * 60 + tm.tm_sec; + + return tt; +#endif +} + +/** * soup_date_copy: * @date: a #SoupDate * diff --git a/libsoup/soup-date.h b/libsoup/soup-date.h index 106b082..a079e8e 100644 --- a/libsoup/soup-date.h +++ b/libsoup/soup-date.h @@ -50,6 +50,8 @@ SoupDate *soup_date_new_from_now (int offset_seconds); char *soup_date_to_string (SoupDate *date, SoupDateFormat format); +time_t soup_date_to_time_t (SoupDate *date); + SoupDate *soup_date_copy (SoupDate *date); void soup_date_free (SoupDate *date); diff --git a/libsoup/soup-form.c b/libsoup/soup-form.c index 299fc88..0984ad8 100644 --- a/libsoup/soup-form.c +++ b/libsoup/soup-form.c @@ -12,6 +12,8 @@ #include #include "soup-form.h" +#include "soup-message.h" +#include "soup-uri.h" #define XDIGIT(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10) #define HEXCHAR(s) ((XDIGIT (s[1]) << 4) + XDIGIT (s[2])) @@ -39,7 +41,7 @@ form_decode (char *part) } /** - * soup_form_decode_urlencoded: + * soup_form_decode: * @encoded_form: data of type "application/x-www-form-urlencoded" * * Decodes @form, which is an urlencoded dataset as defined in the @@ -49,7 +51,7 @@ form_decode (char *part) * @encoded_form, which you can free with g_hash_table_destroy(). **/ GHashTable * -soup_form_decode_urlencoded (const char *encoded_form) +soup_form_decode (const char *encoded_form) { GHashTable *form_data_set; char **pairs, *eq, *name, *value; @@ -111,23 +113,52 @@ hash_encode_foreach (gpointer name, gpointer value, gpointer str) } /** - * soup_form_encode_urlencoded: - * @form_data_set: a hash table containing name/value pairs + * soup_form_encode: + * @first_field: name of the first form field + * @...: value of @first_field, followed by additional field names + * and values, terminated by %NULL. + * + * Encodes the given field names and values into a value of type + * "application/x-www-form-urlencoded", as defined in the HTML 4.01 + * spec. + * + * This method requires you to know the names of the form fields (or + * at the very least, the total number of fields) at compile time; for + * working with dynamic forms, use soup_form_encode_hash() or + * soup_form_encode_datalist(). + * + * Return value: the encoded form + **/ +char * +soup_form_encode (const char *first_field, ...) +{ + va_list args; + char *encoded; + + va_start (args, first_field); + encoded = soup_form_encode_valist (first_field, args); + va_end (args); + + return encoded; +} + +/** + * soup_form_encode_hash: + * @form_data_set: a hash table containing name/value pairs (as strings) * * Encodes @form_data_set into a value of type * "application/x-www-form-urlencoded", as defined in the HTML 4.01 * spec. * - * Note that the spec states that "The control names/values are listed - * in the order they appear in the document." Since - * soup_form_encode_urlencoded() takes a hash table, this cannot be - * enforced; if you care about the ordering of the form fields, use - * soup_form_encode_urlencoded_list(). + * Note that the HTML spec states that "The control names/values are + * listed in the order they appear in the document." Since this method + * takes a hash table, it cannot enforce that; if you care about the + * ordering of the form fields, use soup_form_encode_datalist(). * * Return value: the encoded form **/ char * -soup_form_encode_urlencoded (GHashTable *form_data_set) +soup_form_encode_hash (GHashTable *form_data_set) { GString *str = g_string_new (NULL); @@ -142,22 +173,153 @@ datalist_encode_foreach (GQuark key_id, gpointer value, gpointer str) } /** - * soup_form_encode_urlencoded_list: - * @form_data_set: a hash table containing name/value pairs + * soup_form_encode_datalist: + * @form_data_set: a datalist containing name/value pairs * * Encodes @form_data_set into a value of type * "application/x-www-form-urlencoded", as defined in the HTML 4.01 - * spec. Unlike soup_form_encode_urlencoded(), this preserves the - * ordering of the form elements, which may be required in some - * situations. + * spec. Unlike soup_form_encode_hash(), this preserves the ordering + * of the form elements, which may be required in some situations. * * Return value: the encoded form **/ char * -soup_form_encode_urlencoded_list (GData **form_data_set) +soup_form_encode_datalist (GData **form_data_set) { GString *str = g_string_new (NULL); g_datalist_foreach (form_data_set, datalist_encode_foreach, str); return g_string_free (str, FALSE); } + +/** + * soup_form_encode_valist: + * @first_field: name of the first form field + * @args: pointer to additional values, as in soup_form_encode() + * + * See soup_form_encode(). This is mostly an internal method, used by + * various other methods such as soup_uri_set_query_from_fields() and + * soup_form_request_new(). + * + * Return value: the encoded form + **/ +char * +soup_form_encode_valist (const char *first_field, va_list args) +{ + GString *str = g_string_new (NULL); + const char *name, *value; + + name = first_field; + value = va_arg (args, const char *); + while (name && value) { + encode_pair (str, name, value); + + name = va_arg (args, const char *); + if (name) + value = va_arg (args, const char *); + } + + return g_string_free (str, FALSE); +} + +static SoupMessage * +soup_form_request_for_data (const char *method, const char *uri_string, + char *form_data) +{ + SoupMessage *msg; + SoupURI *uri; + + uri = soup_uri_new (uri_string); + if (!uri) + return NULL; + + if (!strcmp (method, "GET")) { + g_free (uri->query); + uri->query = form_data; + form_data = NULL; + } + + msg = soup_message_new_from_uri (method, uri); + + if (!strcmp (method, "POST")) { + soup_message_set_request ( + msg, "application/x-www-form-urlencoded", + SOUP_MEMORY_TAKE, + form_data, strlen (form_data)); + form_data = NULL; + } + + if (form_data) { + g_warning ("invalid method passed to soup_form_request_new"); + g_free (form_data); + } + + return msg; +} + +/** + * soup_form_request_new: + * @method: the HTTP method, either "GET" or "POST" + * @uri: the URI to send the form data to + * @first_field: name of the first form field + * @...: value of @first_field, followed by additional field names + * and values, terminated by %NULL. + * + * Creates a new %SoupMessage and sets it up to send the given data + * to @uri via @method. (That is, if @method is "GET", it will encode + * the form data into @uri's query field, and if @method is "POST", it + * will encode it into the %SoupMessage's request_body.) + * + * Return value: the new %SoupMessage + **/ +SoupMessage * +soup_form_request_new (const char *method, const char *uri, + const char *first_field, ...) +{ + va_list args; + char *form_data; + + va_start (args, first_field); + form_data = soup_form_encode_valist (first_field, args); + va_end (args); + + return soup_form_request_for_data (method, uri, form_data); +} + +/** + * soup_form_request_new_from_hash: + * @method: the HTTP method, either "GET" or "POST" + * @uri: the URI to send the form data to + * @form_data_set: the data to send to @uri + * + * Creates a new %SoupMessage and sets it up to send @form_data_set to + * @uri via @method, as with soup_form_request_new(). + * + * Return value: the new %SoupMessage + **/ +SoupMessage * +soup_form_request_new_from_hash (const char *method, const char *uri, + GHashTable *form_data_set) +{ + return soup_form_request_for_data ( + method, uri, soup_form_encode_hash (form_data_set)); +} + +/** + * soup_form_request_new_from_datalist: + * @method: the HTTP method, either "GET" or "POST" + * @uri: the URI to send the form data to + * @form_data_set: the data to send to @uri + * + * Creates a new %SoupMessage and sets it up to send @form_data_set to + * @uri via @method, as with soup_form_request_new(). + * + * Return value: the new %SoupMessage + **/ +SoupMessage * +soup_form_request_new_from_datalist (const char *method, const char *uri, + GData **form_data_set) +{ + return soup_form_request_for_data ( + method, uri, soup_form_encode_datalist (form_data_set)); +} diff --git a/libsoup/soup-form.h b/libsoup/soup-form.h index 9502244..9db5abf 100644 --- a/libsoup/soup-form.h +++ b/libsoup/soup-form.h @@ -10,10 +10,32 @@ G_BEGIN_DECLS -GHashTable *soup_form_decode_urlencoded (const char *encoded_form); +GHashTable *soup_form_decode (const char *encoded_form); -char *soup_form_encode_urlencoded (GHashTable *form_data_set); -char *soup_form_encode_urlencoded_list (GData **form_data_set); +char *soup_form_encode (const char *first_field, + ...) G_GNUC_NULL_TERMINATED; +char *soup_form_encode_hash (GHashTable *form_data_set); +char *soup_form_encode_datalist (GData **form_data_set); +char *soup_form_encode_valist (const char *first_field, + va_list args); + +#ifndef LIBSOUP_DISABLE_DEPRECATED +/* Compatibility with libsoup 2.3.0 */ +#define soup_form_decode_urlencoded soup_form_decode +#define soup_form_encode_urlencoded soup_form_encode_hash +#define soup_form_encode_urlencoded_list soup_form_encode_datalist +#endif + +SoupMessage *soup_form_request_new (const char *method, + const char *uri, + const char *first_field, + ...) G_GNUC_NULL_TERMINATED; +SoupMessage *soup_form_request_new_from_hash (const char *method, + const char *uri, + GHashTable *form_data_set); +SoupMessage *soup_form_request_new_from_datalist (const char *method, + const char *uri, + GData **form_data_set); G_END_DECLS diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index b9569c7..63bf93e 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -883,8 +883,7 @@ soup_uri_set_query (SoupURI *uri, const char *query) * @form: a #GHashTable containing HTML form information * * Sets @uri's query to the result of encoding @form according to the - * HTML form rules. See soup_form_encode_urlencoded() for more - * information. + * HTML form rules. See soup_form_encode_hash() for more information. **/ void soup_uri_set_query_from_form (SoupURI *uri, GHashTable *form) @@ -894,6 +893,30 @@ soup_uri_set_query_from_form (SoupURI *uri, GHashTable *form) } /** + * soup_uri_set_query_from_fields: + * @uri: a #SoupURI + * @first_field: name of the first form field to encode into query + * @...: value of @first_field, followed by additional field names + * and values, terminated by %NULL. + * + * Sets @uri's query to the result of encoding the given form fields + * and values according to the * HTML form rules. See + * soup_form_encode() for more information. + **/ +void +soup_uri_set_query_from_fields (SoupURI *uri, + const char *first_field, + ...) +{ + va_list args; + + g_free (uri->query); + va_start (args, first_field); + uri->query = soup_form_encode_valist (first_field, args); + va_end (args); +} + +/** * soup_uri_set_fragment: * @uri: a #SoupURI * @fragment: the fragment diff --git a/libsoup/soup-uri.h b/libsoup/soup-uri.h index e939b1b..34a9457 100644 --- a/libsoup/soup-uri.h +++ b/libsoup/soup-uri.h @@ -33,46 +33,49 @@ GType soup_uri_get_type (void); #define SOUP_URI_SCHEME_HTTP (g_intern_static_string ("http")) #define SOUP_URI_SCHEME_HTTPS (g_intern_static_string ("https")) -SoupURI *soup_uri_new_with_base (SoupURI *base, - const char *uri_string); -SoupURI *soup_uri_new (const char *uri_string); - -char *soup_uri_to_string (SoupURI *uri, - gboolean just_path_and_query); - -SoupURI *soup_uri_copy (SoupURI *uri); - -gboolean soup_uri_equal (SoupURI *uri1, - SoupURI *uri2); - -void soup_uri_free (SoupURI *uri); - -char *soup_uri_encode (const char *part, - const char *escape_extra); -char *soup_uri_decode (const char *part); -char *soup_uri_normalize (const char *part, - const char *unescape_extra); - -gboolean soup_uri_uses_default_port (SoupURI *uri); - -void soup_uri_set_scheme (SoupURI *uri, - const char *scheme); -void soup_uri_set_user (SoupURI *uri, - const char *user); -void soup_uri_set_password (SoupURI *uri, - const char *password); -void soup_uri_set_host (SoupURI *uri, - const char *host); -void soup_uri_set_port (SoupURI *uri, - guint port); -void soup_uri_set_path (SoupURI *uri, - const char *path); -void soup_uri_set_query (SoupURI *uri, - const char *query); -void soup_uri_set_query_from_form (SoupURI *uri, - GHashTable *form); -void soup_uri_set_fragment (SoupURI *uri, - const char *fragment); +SoupURI *soup_uri_new_with_base (SoupURI *base, + const char *uri_string); +SoupURI *soup_uri_new (const char *uri_string); + +char *soup_uri_to_string (SoupURI *uri, + gboolean just_path_and_query); + +SoupURI *soup_uri_copy (SoupURI *uri); + +gboolean soup_uri_equal (SoupURI *uri1, + SoupURI *uri2); + +void soup_uri_free (SoupURI *uri); + +char *soup_uri_encode (const char *part, + const char *escape_extra); +char *soup_uri_decode (const char *part); +char *soup_uri_normalize (const char *part, + const char *unescape_extra); + +gboolean soup_uri_uses_default_port (SoupURI *uri); + +void soup_uri_set_scheme (SoupURI *uri, + const char *scheme); +void soup_uri_set_user (SoupURI *uri, + const char *user); +void soup_uri_set_password (SoupURI *uri, + const char *password); +void soup_uri_set_host (SoupURI *uri, + const char *host); +void soup_uri_set_port (SoupURI *uri, + guint port); +void soup_uri_set_path (SoupURI *uri, + const char *path); +void soup_uri_set_query (SoupURI *uri, + const char *query); +void soup_uri_set_query_from_form (SoupURI *uri, + GHashTable *form); +void soup_uri_set_query_from_fields (SoupURI *uri, + const char *first_field, + ...); +void soup_uri_set_fragment (SoupURI *uri, + const char *fragment); G_END_DECLS diff --git a/libsoup/soup-value-utils.c b/libsoup/soup-value-utils.c index af214f3..ce0b7d4 100644 --- a/libsoup/soup-value-utils.c +++ b/libsoup/soup-value-utils.c @@ -57,6 +57,48 @@ soup_value_hash_new (void) g_free, soup_value_hash_value_free); } +static void +soup_value_hash_insert_valist (GHashTable *hash, const char *first_key, + va_list args) +{ + const char *key; + GType type; + GValue value; + + key = first_key; + while (key) { + type = va_arg (args, GType); + SOUP_VALUE_SETV (&value, type, args); + + soup_value_hash_insert_value (hash, key, &value); + key = va_arg (args, const char *); + } +} + +/** + * soup_value_hash_new_with_vals: + * @first_key: the key for the first value + * @...: the type of @first_key, followed by the value, followed + * by additional key/type/value triplets, terminated by %NULL + * + * Creates a #GHashTable whose keys are strings and whose values + * are #GValue, and initializes it with the provided data. As + * with soup_value_hash_insert(), the keys and values are copied + * rather than being inserted directly. + **/ +GHashTable * +soup_value_hash_new_with_vals (const char *first_key, ...) +{ + GHashTable *hash = soup_value_hash_new (); + va_list args; + + va_start (args, first_key); + soup_value_hash_insert_valist (hash, first_key, args); + va_end (args); + + return hash; +} + /** * soup_value_hash_insert_value: * @hash: a value hash @@ -99,6 +141,27 @@ soup_value_hash_insert (GHashTable *hash, const char *key, GType type, ...) } /** + * soup_value_hash_insert_vals: + * @hash: a value hash + * @first_key: the key for the first value + * @...: the type of @first_key, followed by the value, followed + * by additional key/type/value triplets, terminated by %NULL + * + * Inserts the given data into @hash. As with + * soup_value_hash_insert(), the keys and values are copied rather + * than being inserted directly. + **/ +void +soup_value_hash_insert_vals (GHashTable *hash, const char *first_key, ...) +{ + va_list args; + + va_start (args, first_key); + soup_value_hash_insert_valist (hash, first_key, args); + va_end (args); +} + +/** * soup_value_hash_lookup: * @hash: a value hash * @key: the key to look up @@ -128,6 +191,51 @@ soup_value_hash_lookup (GHashTable *hash, const char *key, GType type, ...) return TRUE; } +/** + * soup_value_hash_lookup_vals: + * @hash: a value hash + * @first_key: the first key to look up + * @...: the type of @first_key, a pointer to that type, and + * then additional key/type/pointer triplets, terminated + * by %NULL. + * + * Looks up a number of keys in @hash and returns their values. + * + * Return value: %TRUE if all of the keys were found, %FALSE + * if any were missing; note that you will generally need to + * initialize each destination variable to a reasonable default + * value, since there is no way to tell which keys were found + * and which were not. + **/ +gboolean +soup_value_hash_lookup_vals (GHashTable *hash, const char *first_key, ...) +{ + va_list args; + GValue *value; + const char *key; + GType type; + gboolean found_all = TRUE; + + va_start (args, first_key); + key = first_key; + while (key) { + type = va_arg (args, GType); + + value = g_hash_table_lookup (hash, key); + if (!value || !G_VALUE_HOLDS (value, type)) { + found_all = FALSE; + /* skip a pointer */ + va_arg (args, gpointer); + } else + SOUP_VALUE_GETV (value, type, args); + + key = va_arg (args, const char *); + } + va_end (args); + + return found_all; +} + /** * soup_value_array_from_args: @@ -187,6 +295,60 @@ soup_value_array_to_args (GValueArray *array, va_list args) } /** + * soup_value_array_new: + * + * Creates a new %GValueArray. (This is just a wrapper around + * g_value_array_new(), for naming consistency purposes.) + * + * Return value: a new %GValueArray + **/ +GValueArray * +soup_value_array_new (void) +{ + return g_value_array_new (1); +} + +static void +soup_value_array_append_valist (GValueArray *array, + GType first_type, va_list args) +{ + GType type; + GValue value; + + type = first_type; + while (type != G_TYPE_INVALID) { + SOUP_VALUE_SETV (&value, type, args); + + g_value_array_append (array, &value); + type = va_arg (args, GType); + } +} + +/** + * soup_value_array_new_with_vals: + * @first_type: the type of the first value to add + * @...: the first value to add, followed by other type/value + * pairs, terminated by %G_TYPE_INVALID + * + * Creates a new %GValueArray and copies the provided values + * into it. + * + * Return value: a new %GValueArray + **/ +GValueArray * +soup_value_array_new_with_vals (GType first_type, ...) +{ + GValueArray *array = soup_value_array_new (); + va_list args; + + va_start (args, first_type); + soup_value_array_append_valist (array, first_type, args); + va_end (args); + + return array; +} + +/** * soup_value_array_insert: * @array: a #GValueArray * @index_: the index to insert at @@ -232,6 +394,27 @@ soup_value_array_append (GValueArray *array, GType type, ...) } /** + * soup_value_array_append_values: + * @array: a #GValueArray + * @first_type: the type of the first value to add + * @...: the first value to add, followed by other type/value + * pairs, terminated by %G_TYPE_INVALID + * + * Appends the provided values into @array as with + * g_value_array_append(). (The provided data is copied rather than + * being inserted directly.) + **/ +void +soup_value_array_append_vals (GValueArray *array, GType first_type, ...) +{ + va_list args; + + va_start (args, first_type); + soup_value_array_append_valist (array, first_type, args); + va_end (args); +} + +/** * soup_value_array_get_nth: * @array: a #GValueArray * @index_: the index to look up diff --git a/libsoup/soup-value-utils.h b/libsoup/soup-value-utils.h index 19f7cce..a7f48b6 100644 --- a/libsoup/soup-value-utils.h +++ b/libsoup/soup-value-utils.h @@ -31,37 +31,52 @@ G_STMT_START { \ g_free (error); \ } G_STMT_END -GHashTable *soup_value_hash_new (void); -void soup_value_hash_insert_value (GHashTable *hash, - const char *key, - GValue *value); -void soup_value_hash_insert (GHashTable *hash, - const char *key, - GType type, - ...); -gboolean soup_value_hash_lookup (GHashTable *hash, - const char *key, - GType type, - ...); +GHashTable *soup_value_hash_new (void); +GHashTable *soup_value_hash_new_with_vals (const char *first_key, + ...) G_GNUC_NULL_TERMINATED; +void soup_value_hash_insert_value (GHashTable *hash, + const char *key, + GValue *value); +void soup_value_hash_insert (GHashTable *hash, + const char *key, + GType type, + ...); +void soup_value_hash_insert_vals (GHashTable *hash, + const char *first_key, + ...) G_GNUC_NULL_TERMINATED; +gboolean soup_value_hash_lookup (GHashTable *hash, + const char *key, + GType type, + ...); +gboolean soup_value_hash_lookup_vals (GHashTable *hash, + const char *first_key, + ...); -GValueArray *soup_value_array_from_args (va_list args); -gboolean soup_value_array_to_args (GValueArray *array, - va_list args); +GValueArray *soup_value_array_from_args (va_list args); +gboolean soup_value_array_to_args (GValueArray *array, + va_list args); -void soup_value_array_insert (GValueArray *array, - guint index_, - GType type, - ...); -void soup_value_array_append (GValueArray *array, - GType type, - ...); -gboolean soup_value_array_get_nth (GValueArray *array, - guint index_, - GType type, - ...); +GValueArray *soup_value_array_new (void); +GValueArray *soup_value_array_new_with_vals (GType first_type, + ...) G_GNUC_NULL_TERMINATED; +void soup_value_array_insert (GValueArray *array, + guint index_, + GType type, + ...); +void soup_value_array_append (GValueArray *array, + GType type, + ...); +void soup_value_array_append_vals (GValueArray *array, + GType first_type, + ...) G_GNUC_NULL_TERMINATED; +gboolean soup_value_array_get_nth (GValueArray *array, + guint index_, + GType type, + ...); -GType soup_byte_array_get_type (void); + +GType soup_byte_array_get_type (void); #define SOUP_TYPE_BYTE_ARRAY (soup_byte_array_get_type ()) G_END_DECLS diff --git a/tests/Makefile.am b/tests/Makefile.am index 4ce7ac9..df885af 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,7 @@ INCLUDES = \ -I$(top_srcdir) \ -DSRCDIR=\""$(srcdir)"\" \ + -DLIBSOUP_DISABLE_DEPRECATED \ $(XML_CFLAGS) \ $(GLIB_CFLAGS) \ $(LIBGNUTLS_CFLAGS) diff --git a/tests/query-test.c b/tests/query-test.c index 682e938..46be99e 100644 --- a/tests/query-test.c +++ b/tests/query-test.c @@ -60,7 +60,6 @@ static void do_test (int n, gboolean extra, const char *uri) { GPtrArray *args; - GHashTable *form_data_set; char *title_arg = NULL, *name_arg = NULL; char *stdout = NULL; @@ -69,24 +68,16 @@ do_test (int n, gboolean extra, const char *uri) tests[n].name ? tests[n].name : "(null)", extra ? " + extra" : ""); - form_data_set = g_hash_table_new (g_str_hash, g_str_equal); - args = g_ptr_array_new (); g_ptr_array_add (args, "curl"); g_ptr_array_add (args, "-G"); if (tests[n].title) { - g_hash_table_insert (form_data_set, "title", tests[n].title); - title_arg = soup_form_encode_urlencoded (form_data_set); - g_hash_table_remove_all (form_data_set); - + title_arg = soup_form_encode ("title", tests[n].title, NULL); g_ptr_array_add (args, "-d"); g_ptr_array_add (args, title_arg); } if (tests[n].name) { - g_hash_table_insert (form_data_set, "name", tests[n].name); - name_arg = soup_form_encode_urlencoded (form_data_set); - g_hash_table_remove_all (form_data_set); - + name_arg = soup_form_encode ("name", tests[n].name, NULL); g_ptr_array_add (args, "-d"); g_ptr_array_add (args, name_arg); } @@ -116,7 +107,6 @@ do_test (int n, gboolean extra, const char *uri) errors++; } g_ptr_array_free (args, TRUE); - g_hash_table_destroy (form_data_set); g_free (title_arg); g_free (name_arg); } -- 2.7.4