[libsoup] SoupURI: add SOUP_URI_IS_VALID() and use it for basic precondition checks



commit 675979d4aa6a72d8415294f989aeb20a6eae2ab6
Author: Simon McVittie <simon mcvittie collabora co uk>
Date:   Fri Feb 3 14:13:32 2012 +0000

    SoupURI: add SOUP_URI_IS_VALID() and use it for basic precondition checks
    
    In this patch, field setters don't have precondition checks for the
    validity of the URI object itself, only a non-NULL check, to avoid
    breaking existing code if it calls soup_uri_new (NULL) and then sets
    fields in an unexpected order:
    
        uri = soup_uri_new (NULL);                    /* uri is invalid */
        soup_uri_set_host (uri, "www.google.com");
        soup_uri_set_query (uri, "q=badgers");
        soup_uri_set_scheme (uri, "http");            /* still invalid... */
        soup_uri_set_path (uri, "/search");           /* finally valid */
    
    Also annotate nullable setter parameters as (allow-none), to justify
    why they don't have a precondition check.
    
    Signed-off-by: Simon McVittie <simon mcvittie collabora co uk>
    Bug: https://bugzilla.gnome.org/show_bug.cgi?id=667637
    Bug-NB: NB#294977

 libsoup/soup-uri.c |  101 +++++++++++++++++++++++++++++++++++++++++++++-------
 libsoup/soup-uri.h |    1 +
 2 files changed, 89 insertions(+), 13 deletions(-)
---
diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c
index f53decd..0e4c31c 100644
--- a/libsoup/soup-uri.c
+++ b/libsoup/soup-uri.c
@@ -81,6 +81,21 @@
  **/
 
 /**
+ * SOUP_URI_IS_VALID:
+ * @uri: a #SoupURI
+ *
+ * Tests whether @uri is a valid #SoupURI; that is, that it is non-%NULL
+ * and its @scheme and @path members are also non-%NULL.
+ *
+ * This macro does not check whether http and https URIs have a non-%NULL
+ * @host member.
+ *
+ * Return value: %TRUE if @uri is valid for use.
+ *
+ * Since: 2.38
+ **/
+
+/**
  * SOUP_URI_VALID_FOR_HTTP:
  * @uri: a #SoupURI
  *
@@ -148,6 +163,9 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string)
 	gboolean remove_dot_segments = TRUE;
 	int len;
 
+	g_return_val_if_fail (base == NULL || SOUP_URI_IS_VALID (base), NULL);
+	g_return_val_if_fail (uri_string != NULL, NULL);
+
 	/* First some cleanup steps (which are supposed to all be no-ops,
 	 * but...). Skip initial whitespace, strip out internal tabs and
 	 * line breaks, and ignore trailing whitespace.
@@ -428,7 +446,7 @@ soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query)
 	GString *str;
 	char *return_result;
 
-	g_return_val_if_fail (uri != NULL, NULL);
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri), NULL);
 
 	/* IF YOU CHANGE ANYTHING IN THIS FUNCTION, RUN
 	 * tests/uri-parsing AFTERWARD.
@@ -487,7 +505,7 @@ soup_uri_copy (SoupURI *uri)
 {
 	SoupURI *dup;
 
-	g_return_val_if_fail (uri != NULL, NULL);
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri), NULL);
 
 	dup = g_slice_new0 (SoupURI);
 	dup->scheme   = uri->scheme;
@@ -524,6 +542,9 @@ parts_equal (const char *one, const char *two, gboolean insensitive)
 gboolean 
 soup_uri_equal (SoupURI *uri1, SoupURI *uri2)
 {
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri1), FALSE);
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri2), FALSE);
+
 	if (uri1->scheme != uri2->scheme                         ||
 	    uri1->port   != uri2->port                           ||
 	    !parts_equal (uri1->user, uri2->user, FALSE)         ||
@@ -591,6 +612,8 @@ soup_uri_encode (const char *part, const char *escape_extra)
 	GString *str;
 	char *encoded;
 
+	g_return_val_if_fail (part != NULL, NULL);
+
 	str = g_string_new (NULL);
 	append_uri_encoded (str, part, escape_extra);
 	encoded = str->str;
@@ -608,6 +631,8 @@ uri_decoded_copy (const char *part, int length)
 	unsigned char *s, *d;
 	char *decoded = g_strndup (part, length);
 
+	g_return_val_if_fail (part != NULL, NULL);
+
 	s = d = (unsigned char *)decoded;
 	do {
 		if (*s == '%') {
@@ -640,6 +665,8 @@ uri_decoded_copy (const char *part, int length)
 char *
 soup_uri_decode (const char *part)
 {
+	g_return_val_if_fail (part != NULL, NULL);
+
 	return uri_decoded_copy (part, strlen (part));
 }
 
@@ -727,6 +754,8 @@ uri_normalized_copy (const char *part, int length,
 char *
 soup_uri_normalize (const char *part, const char *unescape_extra)
 {
+	g_return_val_if_fail (part != NULL, NULL);
+
 	return uri_normalized_copy (part, strlen (part), unescape_extra);
 }
 
@@ -744,6 +773,9 @@ soup_uri_normalize (const char *part, const char *unescape_extra)
 gboolean
 soup_uri_uses_default_port (SoupURI *uri)
 {
+	g_return_val_if_fail (uri != NULL, FALSE);
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri), FALSE);
+
 	return uri->port == soup_scheme_default_port (uri->scheme);
 }
 
@@ -774,6 +806,8 @@ soup_uri_uses_default_port (SoupURI *uri)
 const char *
 soup_uri_get_scheme (SoupURI *uri)
 {
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri), NULL);
+
 	return uri->scheme;
 }
 
@@ -788,6 +822,9 @@ soup_uri_get_scheme (SoupURI *uri)
 void
 soup_uri_set_scheme (SoupURI *uri, const char *scheme)
 {
+	g_return_if_fail (uri != NULL);
+	g_return_if_fail (scheme != NULL);
+
 	uri->scheme = soup_uri_parse_scheme (scheme, strlen (scheme));
 	uri->port = soup_scheme_default_port (uri->scheme);
 }
@@ -805,19 +842,23 @@ soup_uri_set_scheme (SoupURI *uri, const char *scheme)
 const char *
 soup_uri_get_user (SoupURI *uri)
 {
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri), NULL);
+
 	return uri->user;
 }
 
 /**
  * soup_uri_set_user:
  * @uri: a #SoupURI
- * @user: the username, or %NULL
+ * @user: (allow-none): the username, or %NULL
  *
  * Sets @uri's user to @user.
  **/
 void
 soup_uri_set_user (SoupURI *uri, const char *user)
 {
+	g_return_if_fail (uri != NULL);
+
 	g_free (uri->user);
 	uri->user = g_strdup (user);
 }
@@ -835,19 +876,23 @@ soup_uri_set_user (SoupURI *uri, const char *user)
 const char *
 soup_uri_get_password (SoupURI *uri)
 {
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri), NULL);
+
 	return uri->password;
 }
 
 /**
  * soup_uri_set_password:
  * @uri: a #SoupURI
- * @password: the password, or %NULL
+ * @password: (allow-none): the password, or %NULL
  *
  * Sets @uri's password to @password.
  **/
 void
 soup_uri_set_password (SoupURI *uri, const char *password)
 {
+	g_return_if_fail (uri != NULL);
+
 	g_free (uri->password);
 	uri->password = g_strdup (password);
 }
@@ -865,23 +910,29 @@ soup_uri_set_password (SoupURI *uri, const char *password)
 const char *
 soup_uri_get_host (SoupURI *uri)
 {
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri), NULL);
+
 	return uri->host;
 }
 
 /**
  * soup_uri_set_host:
  * @uri: a #SoupURI
- * @host: the hostname or IP address, or %NULL
+ * @host: (allow-none): the hostname or IP address, or %NULL
  *
  * Sets @uri's host to @host.
  *
  * If @host is an IPv6 IP address, it should not include the brackets
  * required by the URI syntax; they will be added automatically when
  * converting @uri to a string.
+ *
+ * http and https URIs should not have a %NULL @host.
  **/
 void
 soup_uri_set_host (SoupURI *uri, const char *host)
 {
+	g_return_if_fail (uri != NULL);
+
 	g_free (uri->host);
 	uri->host = g_strdup (host);
 }
@@ -899,6 +950,8 @@ soup_uri_set_host (SoupURI *uri, const char *host)
 guint
 soup_uri_get_port (SoupURI *uri)
 {
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri), 0);
+
 	return uri->port;
 }
 
@@ -913,6 +966,8 @@ soup_uri_get_port (SoupURI *uri)
 void
 soup_uri_set_port (SoupURI *uri, guint port)
 {
+	g_return_if_fail (uri != NULL);
+
 	uri->port = port;
 }
 
@@ -929,19 +984,24 @@ soup_uri_set_port (SoupURI *uri, guint port)
 const char *
 soup_uri_get_path (SoupURI *uri)
 {
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri), NULL);
+
 	return uri->path;
 }
 
 /**
  * soup_uri_set_path:
  * @uri: a #SoupURI
- * @path: the path
+ * @path: the non-%NULL path
  *
  * Sets @uri's path to @path.
  **/
 void
 soup_uri_set_path (SoupURI *uri, const char *path)
 {
+	g_return_if_fail (uri != NULL);
+	g_return_if_fail (path != NULL);
+
 	g_free (uri->path);
 	uri->path = g_strdup (path);
 }
@@ -959,19 +1019,23 @@ soup_uri_set_path (SoupURI *uri, const char *path)
 const char *
 soup_uri_get_query (SoupURI *uri)
 {
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri), NULL);
+
 	return uri->query;
 }
 
 /**
  * soup_uri_set_query:
  * @uri: a #SoupURI
- * @query: the query
+ * @query: (allow-none): the query
  *
  * Sets @uri's query to @query.
  **/
 void
 soup_uri_set_query (SoupURI *uri, const char *query)
 {
+	g_return_if_fail (uri != NULL);
+
 	g_free (uri->query);
 	uri->query = g_strdup (query);
 }
@@ -988,6 +1052,8 @@ soup_uri_set_query (SoupURI *uri, const char *query)
 void
 soup_uri_set_query_from_form (SoupURI *uri, GHashTable *form)
 {
+	g_return_if_fail (uri != NULL);
+
 	g_free (uri->query);
 	uri->query = soup_form_encode_hash (form);
 }
@@ -1010,6 +1076,8 @@ soup_uri_set_query_from_fields (SoupURI    *uri,
 {
 	va_list args;
 
+	g_return_if_fail (uri != NULL);
+
 	g_free (uri->query);
 	va_start (args, first_field);
 	uri->query = soup_form_encode_valist (first_field, args);
@@ -1029,19 +1097,23 @@ soup_uri_set_query_from_fields (SoupURI    *uri,
 const char *
 soup_uri_get_fragment (SoupURI *uri)
 {
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri), NULL);
+
 	return uri->fragment;
 }
 
 /**
  * soup_uri_set_fragment:
  * @uri: a #SoupURI
- * @fragment: the fragment
+ * @fragment: (allow-none): the fragment
  *
  * Sets @uri's fragment to @fragment.
  **/
 void
 soup_uri_set_fragment (SoupURI *uri, const char *fragment)
 {
+	g_return_if_fail (uri != NULL);
+
 	g_free (uri->fragment);
 	uri->fragment = g_strdup (fragment);
 }
@@ -1061,7 +1133,7 @@ soup_uri_copy_host (SoupURI *uri)
 {
 	SoupURI *dup;
 
-	g_return_val_if_fail (uri != NULL, NULL);
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri), NULL);
 
 	dup = soup_uri_new (NULL);
 	dup->scheme = uri->scheme;
@@ -1074,7 +1146,7 @@ soup_uri_copy_host (SoupURI *uri)
 
 /**
  * soup_uri_host_hash:
- * @key: (type Soup.URI): a #SoupURI
+ * @key: (type Soup.URI): a #SoupURI with a non-%NULL @host member
  *
  * Hashes @key, considering only the scheme, host, and port.
  *
@@ -1087,7 +1159,8 @@ soup_uri_host_hash (gconstpointer key)
 {
 	const SoupURI *uri = key;
 
-	g_return_val_if_fail (uri != NULL && uri->host != NULL, 0);
+	g_return_val_if_fail (SOUP_URI_IS_VALID (uri), 0);
+	g_return_val_if_fail (uri->host != NULL, 0);
 
 	return GPOINTER_TO_UINT (uri->scheme) + uri->port +
 		soup_str_case_hash (uri->host);
@@ -1095,8 +1168,8 @@ soup_uri_host_hash (gconstpointer key)
 
 /**
  * soup_uri_host_equal:
- * @v1: (type Soup.URI): a #SoupURI
- * @v2: (type Soup.URI): a #SoupURI
+ * @v1: (type Soup.URI): a #SoupURI with a non-%NULL @host member
+ * @v2: (type Soup.URI): a #SoupURI with a non-%NULL @host member
  *
  * Compares @v1 and @v2, considering only the scheme, host, and port.
  *
@@ -1112,6 +1185,8 @@ soup_uri_host_equal (gconstpointer v1, gconstpointer v2)
 	const SoupURI *two = v2;
 
 	g_return_val_if_fail (one != NULL && two != NULL, one == two);
+	g_return_val_if_fail (SOUP_URI_IS_VALID (one), FALSE);
+	g_return_val_if_fail (SOUP_URI_IS_VALID (two), FALSE);
 	g_return_val_if_fail (one->host != NULL && two->host != NULL, one->host == two->host);
 
 	if (one->scheme != two->scheme)
diff --git a/libsoup/soup-uri.h b/libsoup/soup-uri.h
index a5c54a6..b851dbe 100644
--- a/libsoup/soup-uri.h
+++ b/libsoup/soup-uri.h
@@ -97,6 +97,7 @@ guint       soup_uri_host_hash             (gconstpointer key);
 gboolean    soup_uri_host_equal            (gconstpointer v1,
 					    gconstpointer v2);
 
+#define   SOUP_URI_IS_VALID(uri)       ((uri) && (uri)->scheme && (uri)->path)
 #define   SOUP_URI_VALID_FOR_HTTP(uri) ((uri) && ((uri)->scheme == SOUP_URI_SCHEME_HTTP || (uri)->scheme == SOUP_URI_SCHEME_HTTPS) && (uri)->host && (uri)->path)
 
 G_END_DECLS



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]