# HG changeset patch
# Node ID d8691c5be92b1d45f242792bed156bb11f630e24
# Parent  09f990cc6a9af21009e0d707bd679d7927f46b6d
diff --git a/hasl/haslcontext.c b/hasl/haslcontext.c
--- a/hasl/haslcontext.c
+++ b/hasl/haslcontext.c
@@ -22,6 +22,7 @@
 #include "haslmechanismanonymous.h"
 #include "haslmechanismexternal.h"
 #include "haslmechanismplain.h"
+#include "haslstring.h"
 
 enum {
 	PROP_0,
@@ -496,12 +497,12 @@
 		const char *mechanisms = ctx->allowed_mechanisms;
 
 		/* No client side mechanisms, try the server advertised ones. */
-		if(mechanisms == NULL || mechanisms[0] == '\0') {
+		if(hasl_str_is_empty(mechanisms)) {
 			mechanisms = ctx->server_mechanisms;
 		}
 
 		/* No server advertised mechanisms, we fall back to supported below. */
-		if(mechanisms == NULL || mechanisms[0] == '\0') {
+		if(hasl_str_is_empty(mechanisms)) {
 			mechanisms = NULL;
 		}
 
diff --git a/hasl/haslgs2header.c b/hasl/haslgs2header.c
--- a/hasl/haslgs2header.c
+++ b/hasl/haslgs2header.c
@@ -22,6 +22,7 @@
 #include "haslgs2header.h"
 
 #include "haslenums.h"
+#include "haslstring.h"
 
 enum {
 	PROP_0,
@@ -252,7 +253,7 @@
 		/* Handle the cbname field. */
 		value = g_match_info_fetch_named(info, "cbname");
 		if(cbname_required) {
-			if(value[0] == '\0') {
+			if(hasl_str_is_empty(value)) {
 				g_clear_pointer(&value, g_free);
 				g_clear_object(&header);
 				g_clear_pointer(&regex, g_regex_unref);
@@ -266,7 +267,7 @@
 			}
 
 			hasl_gs2_header_set_channel_binding_name(header, value);
-		} else if(value[0] != '\0') {
+		} else if(!hasl_str_is_empty(value)) {
 			g_clear_pointer(&value, g_free);
 			g_clear_object(&header);
 			g_clear_pointer(&regex, g_regex_unref);
@@ -311,9 +312,7 @@
 	if(header->channel_binding == HaslGs2HeaderChannelBindingClientSupported) {
 		gboolean invalid = FALSE;
 
-		if(header->channel_binding_name == NULL ||
-		   header->channel_binding_name[0] == '\0')
-		{
+		if(hasl_str_is_empty(header->channel_binding_name)) {
 			g_set_error_literal(error, HASL_GS2_HEADER_DOMAIN, 0,
 			                    "channel binding was set to supported but no "
 			                    "name was given.");
diff --git a/hasl/haslmechanismanonymous.c b/hasl/haslmechanismanonymous.c
--- a/hasl/haslmechanismanonymous.c
+++ b/hasl/haslmechanismanonymous.c
@@ -22,6 +22,7 @@
 #include "haslmechanismanonymous.h"
 
 #include "haslcore.h"
+#include "haslstring.h"
 
 struct _HaslMechanismAnonymous {
 	HaslMechanism parent;
@@ -41,7 +42,7 @@
 	const char *value = NULL;
 
 	value = hasl_context_get_username(context);
-	if(value == NULL || value[0] == '\0') {
+	if(hasl_str_is_empty(value)) {
 		g_set_error_literal(error, HASL_MECHANISM_ANONYMOUS_DOMAIN, 0,
 		                    _("missing username"));
 
@@ -75,7 +76,7 @@
 	int res = 0;
 
 	username = hasl_context_get_username(ctx);
-	if(username == NULL || username[0] == '\0') {
+	if(hasl_str_is_empty(username)) {
 		g_set_error_literal(error, HASL_MECHANISM_ANONYMOUS_DOMAIN, 0,
 		                    _("no username provided"));
 
diff --git a/hasl/haslmechanismplain.c b/hasl/haslmechanismplain.c
--- a/hasl/haslmechanismplain.c
+++ b/hasl/haslmechanismplain.c
@@ -20,6 +20,7 @@
 #include "haslmechanismplain.h"
 
 #include "haslcore.h"
+#include "haslstring.h"
 
 struct _HaslMechanismPlain {
 	HaslMechanism parent;
@@ -38,7 +39,7 @@
 	const char *value = NULL;
 
 	value = hasl_context_get_username(context);
-	if(value == NULL || value[0] == '\0') {
+	if(hasl_str_is_empty(value)) {
 		g_set_error_literal(error, HASL_MECHANISM_PLAIN_DOMAIN, 0,
 		                    _("missing username"));
 
@@ -46,7 +47,7 @@
 	}
 
 	value = hasl_context_get_password(context);
-	if(value == NULL || value[0] == '\0') {
+	if(hasl_str_is_empty(value)) {
 		g_set_error_literal(error, HASL_MECHANISM_PLAIN_DOMAIN, 0,
 		                    _("missing password"));
 
@@ -82,7 +83,7 @@
 	authzid = hasl_context_get_authzid(ctx);
 
 	username = hasl_context_get_username(ctx);
-	if(username == NULL || username[0] == '\0') {
+	if(hasl_str_is_empty(username)) {
 		g_set_error_literal(error, HASL_MECHANISM_PLAIN_DOMAIN, 0,
 		                    _("no username provided"));
 
@@ -90,7 +91,7 @@
 	}
 
 	password = hasl_context_get_password(ctx);
-	if(password == NULL || password[0] == '\0') {
+	if(hasl_str_is_empty(password)) {
 		g_set_error_literal(error, HASL_MECHANISM_PLAIN_DOMAIN, 0,
 		                    _("no password provided"));
 
@@ -101,7 +102,7 @@
 	data = g_byte_array_new();
 
 	/* authzid can be null, so we need to check it before appending it. */
-	if(authzid != NULL && authzid[0] != '\0') {
+	if(!hasl_str_is_empty(authzid)) {
 		g_byte_array_append(data, (guint8 *)authzid, strlen(authzid));
 	}
 
diff --git a/hasl/haslstring.h b/hasl/haslstring.h
new file mode 100644
--- /dev/null
+++ b/hasl/haslstring.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023-2025 Hasl Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that 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 library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef HASL_STRING_H
+#define HASL_STRING_H
+
+#include <glib.h>
+
+#include "haslversion.h"
+
+G_BEGIN_DECLS
+
+/**
+ * hasl_str_is_empty:
+ * @str: (nullable): the string to check
+ *
+ * Determines if @str is empty or not.
+ *
+ * Returns: true if @str is empty; false otherwise.
+ *
+ * Since: 0.5
+ */
+HASL_AVAILABLE_STATIC_INLINE_IN_0_5
+static inline gboolean
+hasl_str_is_empty(const char *str) {
+	return (str == NULL || str[0] == '\0');
+}
+
+G_END_DECLS
+
+#endif /* HASL_STRING_H */
diff --git a/hasl/haslversion.h b/hasl/haslversion.h
--- a/hasl/haslversion.h
+++ b/hasl/haslversion.h
@@ -203,10 +203,12 @@
 #if HASL_VERSION_MAX_ALLOWED < HASL_VERSION_0_5
 #define HASL_AVAILABLE_IN_0_5 HASL_UNAVAILABLE(0, 5)
 #define HASL_AVAILABLE_ENUMERATOR_IN_0_5 HASL_UNAVAILABLE_ENUMERATOR(0, 5)
+#define HASL_AVAILABLE_STATIC_INLINE_IN_0_5 HASL_UNAVAILABLE_STATIC_INLINE(0, 5)
 #define HASL_DEPRECATED_ENUMERATOR_IN_0_5_FOR(f) HASL_DEPRECATED_ENUMERATOR_FOR(f)
 #else
 #define HASL_AVAILABLE_IN_0_5 _HASL_EXTERN
 #define HASL_AVAILABLE_ENUMERATOR_IN_0_5
+#define HASL_AVAILABLE_STATIC_INLINE_IN_0_5
 #define HASL_DEPRECATED_ENUMERATOR_IN_0_5_FOR(f)
 #endif
 
diff --git a/hasl/meson.build b/hasl/meson.build
--- a/hasl/meson.build
+++ b/hasl/meson.build
@@ -16,6 +16,7 @@
   'haslmechanismanonymous.h',
   'haslmechanismexternal.h',
   'haslmechanismplain.h',
+  'haslstring.h',
   'haslversion.h',
 ]
 
