From cdfd50e166d1693a2941c8e82796e28bcd4b020a Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue, 18 May 2021 15:18:14 +1000
Subject: [PATCH] spa: add spa_atob() to convert a string to a boolean

This replaces the manual check for "true" and some (inconsistent) return value
of atoi. All those instances now require either "true" or "1" to parse as
true, any other value (including NULL) is boolean false.
---
 spa/include/spa/utils/string.h          | 11 +++++++++++
 spa/plugins/alsa/acp/acp.c              | 10 +++++-----
 spa/plugins/alsa/alsa-acp-device.c      |  4 ++--
 spa/plugins/alsa/alsa-pcm-sink.c        |  6 +++---
 spa/plugins/alsa/alsa-pcm-source.c      |  6 +++---
 spa/plugins/alsa/alsa-udev.c            |  2 +-
 spa/plugins/audioconvert/channelmix.c   |  9 +++------
 spa/plugins/audioconvert/merger.c       |  2 +-
 spa/plugins/audioconvert/resample.c     |  2 +-
 spa/plugins/bluez5/backend-hsphfpd.c    |  2 +-
 spa/plugins/bluez5/backend-native.c     |  2 +-
 spa/plugins/bluez5/backend-ofono.c      |  2 +-
 spa/plugins/bluez5/bluez5-dbus.c        |  4 ++--
 spa/plugins/support/logger.c            |  6 +++---
 spa/plugins/support/node-driver.c       |  2 +-
 spa/plugins/videoconvert/videoadapter.c |  2 +-
 spa/tests/test-utils.c                  | 17 +++++++++++++++++
 src/pipewire/pipewire.c                 |  3 +--
 18 files changed, 58 insertions(+), 34 deletions(-)

diff --git a/spa/include/spa/utils/string.h b/spa/include/spa/utils/string.h
index 31b3a5c8a5..3c7ec94c1d 100644
--- a/spa/include/spa/utils/string.h
+++ b/spa/include/spa/utils/string.h
@@ -82,6 +82,17 @@ static inline bool spa_atoi32(const char *str, int32_t *val, int base)
 	return true;
 }
 
+/**
+ * Convert \a str to a boolean. Allowed boolean values are "true" and a
+ * literal "1", anything else is false.
+ *
+ * \return true on success, false otherwise
+ */
+static inline bool spa_atob(const char *str)
+{
+	return spa_streq(str, "true") || spa_streq(str, "1");
+}
+
 #ifdef __cplusplus
 }  /* extern "C" */
 #endif
#diff --git a/spa/plugins/alsa/acp/acp.c b/spa/plugins/alsa/acp/acp.c
#index 21cb9b4e8b..16531a6ac4 100644
#--- a/spa/plugins/alsa/acp/acp.c
#+++ b/spa/plugins/alsa/acp/acp.c
#@@ -1480,19 +1480,19 @@ struct acp_card *acp_card_new(uint32_t index, const struct acp_dict *props)
# 
# 	if (props) {
# 		if ((s = acp_dict_lookup(props, "api.alsa.use-ucm")) != NULL)
#-			impl->use_ucm = (spa_streq(s, "true") || atoi(s) == 1);
#+			impl->use_ucm = spa_atob(s);
# 		if ((s = acp_dict_lookup(props, "api.alsa.soft-mixer")) != NULL)
#-			impl->soft_mixer = (spa_streq(s, "true") || atoi(s) == 1);
#+			impl->soft_mixer = spa_atob(s);
# 		if ((s = acp_dict_lookup(props, "api.alsa.ignore-dB")) != NULL)
#-			ignore_dB = (spa_streq(s, "true") || atoi(s) == 1);
#+			ignore_dB = spa_atob(s);
# 		if ((s = acp_dict_lookup(props, "device.profile-set")) != NULL)
# 			profile_set = s;
# 		if ((s = acp_dict_lookup(props, "device.profile")) != NULL)
# 			profile = s;
# 		if ((s = acp_dict_lookup(props, "api.acp.auto-profile")) != NULL)
#-			impl->auto_profile = (spa_streq(s, "true") || atoi(s) == 1);
#+			impl->auto_profile = spa_atob(s);
# 		if ((s = acp_dict_lookup(props, "api.acp.auto-port")) != NULL)
#-			impl->auto_port = (spa_streq(s, "true") || atoi(s) == 1);
#+			impl->auto_port = spa_atob(s);
# 	}
# 
# 	impl->ucm.default_sample_spec.format = PA_SAMPLE_S16NE;
#diff --git a/spa/plugins/alsa/alsa-acp-device.c b/spa/plugins/alsa/alsa-acp-device.c
#index a0e8c3013e..a700c1364a 100644
#--- a/spa/plugins/alsa/alsa-acp-device.c
#+++ b/spa/plugins/alsa/alsa-acp-device.c
#@@ -959,9 +959,9 @@ impl_init(const struct spa_handle_factory *factory,
# 		if ((str = spa_dict_lookup(info, SPA_KEY_API_ALSA_PATH)) != NULL)
# 			snprintf(this->props.device, sizeof(this->props.device), "%s", str);
# 		if ((str = spa_dict_lookup(info, "api.acp.auto-port")) != NULL)
#-			this->props.auto_port = spa_streq(str, "true") || atoi(str) != 0;
#+			this->props.auto_port = spa_atob(str);
# 		if ((str = spa_dict_lookup(info, "api.acp.auto-profile")) != NULL)
#-			this->props.auto_profile = spa_streq(str, "true") || atoi(str) != 0;
#+			this->props.auto_profile = spa_atob(str);
# 
# 		items = alloca((info->n_items) * sizeof(*items));
# 		spa_dict_for_each(it, info)
#diff --git a/spa/plugins/alsa/alsa-pcm-sink.c b/spa/plugins/alsa/alsa-pcm-sink.c
#index 5718bef2ac..c52241cc7c 100644
#--- a/spa/plugins/alsa/alsa-pcm-sink.c
#+++ b/spa/plugins/alsa/alsa-pcm-sink.c
#@@ -808,11 +808,11 @@ impl_init(const struct spa_handle_factory *factory,
# 		} else if (spa_streq(k, "api.alsa.start-delay")) {
# 			this->default_start_delay = atoi(s);
# 		} else if (spa_streq(k, "api.alsa.disable-mmap")) {
#-			this->disable_mmap = (spa_streq(s, "true") || atoi(s) == 1);
#+			this->disable_mmap = spa_atob(s);
# 		} else if (spa_streq(k, "api.alsa.disable-batch")) {
#-			this->disable_batch = (spa_streq(s, "true") || atoi(s) == 1);
#+			this->disable_batch = spa_atob(s);
# 		} else if (spa_streq(k, "api.alsa.use-chmap")) {
#-			this->props.use_chmap = (spa_streq(s, "true") || atoi(s) == 1);
#+			this->props.use_chmap = spa_atob(s);
# 		}
# 	}
# 	return 0;
#diff --git a/spa/plugins/alsa/alsa-pcm-source.c b/spa/plugins/alsa/alsa-pcm-source.c
#index c710590f2c..273139e8e8 100644
#--- a/spa/plugins/alsa/alsa-pcm-source.c
#+++ b/spa/plugins/alsa/alsa-pcm-source.c
#@@ -826,11 +826,11 @@ impl_init(const struct spa_handle_factory *factory,
# 		} else if (spa_streq(k, "api.alsa.headroom")) {
# 			this->default_headroom = atoi(s);
# 		} else if (spa_streq(k, "api.alsa.disable-mmap")) {
#-			this->disable_mmap = (spa_streq(s, "true") || atoi(s) == 1);
#+			this->disable_mmap = spa_atob(s);
# 		} else if (spa_streq(k, "api.alsa.disable-batch")) {
#-			this->disable_batch = (spa_streq(s, "true") || atoi(s) == 1);
#+			this->disable_batch = spa_atob(s);
# 		} else if (spa_streq(k, "api.alsa.use-chmap")) {
#-			this->props.use_chmap = (spa_streq(s, "true") || atoi(s) == 1);
#+			this->props.use_chmap = spa_atob(s);
# 		}
# 	}
# 	return 0;
#diff --git a/spa/plugins/alsa/alsa-udev.c b/spa/plugins/alsa/alsa-udev.c
#index 2f5e70d9ce..99741c807b 100644
#--- a/spa/plugins/alsa/alsa-udev.c
#+++ b/spa/plugins/alsa/alsa-udev.c
#@@ -768,7 +768,7 @@ impl_init(const struct spa_handle_factory *factory,
# 
# 	if (info) {
# 		if ((str = spa_dict_lookup(info, "alsa.use-acp")) != NULL)
#-			this->use_acp = spa_streq(str, "true") || atoi(str) != 0;
#+			this->use_acp = spa_atob(str);
# 	}
# 
# 	return 0;
#diff --git a/spa/plugins/audioconvert/channelmix.c b/spa/plugins/audioconvert/channelmix.c
#index 2c8bd65a88..c1a39660e8 100644
#--- a/spa/plugins/audioconvert/channelmix.c
#+++ b/spa/plugins/audioconvert/channelmix.c
#@@ -1392,14 +1392,11 @@ impl_init(const struct spa_handle_factory *factory,
# 	for (i = 0; info && i < info->n_items; i++) {
# 		const char *k = info->items[i].key;
# 		const char *s = info->items[i].value;
#-		if (spa_streq(k, "channelmix.normalize") &&
#-		    (spa_streq(s, "true") || atoi(s) != 0))
#+		if (spa_streq(k, "channelmix.normalize") && spa_atob(s))
# 			this->mix.options |= CHANNELMIX_OPTION_NORMALIZE;
#-		if (spa_streq(k, "channelmix.mix-lfe") &&
#-		    (spa_streq(s, "true") || atoi(s) != 0))
#+		if (spa_streq(k, "channelmix.mix-lfe") && spa_atob(s))
# 			this->mix.options |= CHANNELMIX_OPTION_MIX_LFE;
#-		if (spa_streq(k, "channelmix.upmix") &&
#-		    (spa_streq(s, "true") || atoi(s) != 0))
#+		if (spa_streq(k, "channelmix.upmix") && spa_atob(s))
# 			this->mix.options |= CHANNELMIX_OPTION_UPMIX;
# 		if (spa_streq(k, "channelmix.lfe-cutoff"))
# 			this->mix.lfe_cutoff = atoi(s);
#diff --git a/spa/plugins/audioconvert/merger.c b/spa/plugins/audioconvert/merger.c
#index 0702f10519..ef1ea5923a 100644
#--- a/spa/plugins/audioconvert/merger.c
#+++ b/spa/plugins/audioconvert/merger.c
#@@ -1385,7 +1385,7 @@ impl_init(const struct spa_handle_factory *factory,
# 	this->monitor_channel_volumes = false;
# 	if (info) {
# 		if ((str = spa_dict_lookup(info, "monitor.channel-volumes")) != NULL)
#-			this->monitor_channel_volumes = spa_streq(str, "true") || atoi(str) == 1;
#+			this->monitor_channel_volumes = spa_atob(str);
# 	}
# 
# 	this->node.iface = SPA_INTERFACE_INIT(
#diff --git a/spa/plugins/audioconvert/resample.c b/spa/plugins/audioconvert/resample.c
#index 2e9d475d82..3e769bd64c 100644
#--- a/spa/plugins/audioconvert/resample.c
#+++ b/spa/plugins/audioconvert/resample.c
#@@ -1007,7 +1007,7 @@ impl_init(const struct spa_handle_factory *factory,
# 		if ((str = spa_dict_lookup(info, "resample.quality")) != NULL)
# 			this->props.quality = atoi(str);
# 		if ((str = spa_dict_lookup(info, "resample.peaks")) != NULL)
#-			this->peaks = spa_streq(str, "true") || atoi(str) == 1;
#+			this->peaks = spa_atob(str);
# 		if ((str = spa_dict_lookup(info, "factory.mode")) != NULL) {
# 			if (spa_streq(str, "split"))
# 				this->mode = MODE_SPLIT;
#diff --git a/spa/plugins/bluez5/backend-hsphfpd.c b/spa/plugins/bluez5/backend-hsphfpd.c
#index 6fe4616bcc..feeb1c1dfc 100644
#--- a/spa/plugins/bluez5/backend-hsphfpd.c
#+++ b/spa/plugins/bluez5/backend-hsphfpd.c
#@@ -1508,7 +1508,7 @@ struct spa_bt_backend *backend_hsphfpd_new(struct spa_bt_monitor *monitor,
# 	backend->main_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Loop);
# 	backend->conn = dbus_connection;
# 	if (info && (str = spa_dict_lookup(info, "bluez5.msbc-support")))
#-		backend->msbc_supported = spa_streq(str, "true") || atoi(str) == 1;
#+		backend->msbc_supported = spa_atob(str);
# 	else
# 		backend->msbc_supported = false;
# 
#diff --git a/spa/plugins/bluez5/backend-native.c b/spa/plugins/bluez5/backend-native.c
#index c2a1a8c62f..eca88e4198 100644
#--- a/spa/plugins/bluez5/backend-native.c
#+++ b/spa/plugins/bluez5/backend-native.c
#@@ -1478,7 +1478,7 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag
# 	spa_list_append(&backend->rfcomm_list, &rfcomm->link);
# 
# 	if (d->settings && (str = spa_dict_lookup(d->settings, "bluez5.msbc-support")))
#-		rfcomm->msbc_support_enabled_in_config = spa_streq(str, "true") || atoi(str) == 1;
#+		rfcomm->msbc_support_enabled_in_config = spa_atob(str);
# 	else
# 		rfcomm->msbc_support_enabled_in_config = false;
# 
#diff --git a/spa/plugins/bluez5/backend-ofono.c b/spa/plugins/bluez5/backend-ofono.c
#index 82f456876c..d87b4c36c2 100644
#--- a/spa/plugins/bluez5/backend-ofono.c
#+++ b/spa/plugins/bluez5/backend-ofono.c
#@@ -789,7 +789,7 @@ struct spa_bt_backend *backend_ofono_new(struct spa_bt_monitor *monitor,
# 	backend->main_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Loop);
# 	backend->conn = dbus_connection;
# 	if (info && (str = spa_dict_lookup(info, "bluez5.msbc-support")))
#-		backend->msbc_supported = spa_streq(str, "true") || atoi(str) == 1;
#+		backend->msbc_supported = spa_atob(str);
# 	else
# 		backend->msbc_supported = false;
# 
#diff --git a/spa/plugins/bluez5/bluez5-dbus.c b/spa/plugins/bluez5/bluez5-dbus.c
#index 04684e20ba..b75060dc70 100644
#--- a/spa/plugins/bluez5/bluez5-dbus.c
#+++ b/spa/plugins/bluez5/bluez5-dbus.c
#@@ -3876,7 +3876,7 @@ impl_init(const struct spa_handle_factory *factory,
# 		uint32_t tmp;
# 
# 		if ((str = spa_dict_lookup(info, "api.bluez5.connection-info")) != NULL &&
#-		    (spa_streq(str, "true") || atoi(str)))
#+		    spa_atob(str))
# 			this->connection_info_supported = true;
# 
# 		if ((str = spa_dict_lookup(info, "bluez5.default.rate")) != NULL &&
#@@ -3888,7 +3888,7 @@ impl_init(const struct spa_handle_factory *factory,
# 			this->default_audio_info.channels = tmp;
# 
# 		if ((str = spa_dict_lookup(info, "bluez5.sbc-xq-support")) != NULL &&
#-		    (spa_streq(str, "true") || atoi(str)))
#+		    spa_atob(str))
# 			this->enable_sbc_xq = true;
# 	}
# 
#diff --git a/spa/plugins/support/logger.c b/spa/plugins/support/logger.c
#index 79061255c0..10eb62fafa 100644
#--- a/spa/plugins/support/logger.c
#+++ b/spa/plugins/support/logger.c
#@@ -266,11 +266,11 @@ impl_init(const struct spa_handle_factory *factory,
# 	}
# 	if (info) {
# 		if ((str = spa_dict_lookup(info, SPA_KEY_LOG_TIMESTAMP)) != NULL)
#-			this->timestamp = (spa_streq(str, "true") || atoi(str) == 1);
#+			this->timestamp = spa_atob(str);
# 		if ((str = spa_dict_lookup(info, SPA_KEY_LOG_LINE)) != NULL)
#-			this->line = (spa_streq(str, "true") || atoi(str) == 1);
#+			this->line = spa_atob(str);
# 		if ((str = spa_dict_lookup(info, SPA_KEY_LOG_COLORS)) != NULL)
#-			this->colors = (spa_streq(str, "true") || atoi(str) == 1);
#+			this->colors = spa_atob(str);
# 		if ((str = spa_dict_lookup(info, SPA_KEY_LOG_LEVEL)) != NULL)
# 			this->log.level = atoi(str);
# 		if ((str = spa_dict_lookup(info, SPA_KEY_LOG_FILE)) != NULL) {
#diff --git a/spa/plugins/support/node-driver.c b/spa/plugins/support/node-driver.c
#index 041d0771d6..a669ce4507 100644
#--- a/spa/plugins/support/node-driver.c
#+++ b/spa/plugins/support/node-driver.c
#@@ -360,7 +360,7 @@ impl_init(const struct spa_handle_factory *factory,
# 
# 	if (info) {
# 		if ((str = spa_dict_lookup(info, "node.freewheel")) != NULL)
#-			this->props.freewheel = (spa_streq(str, "true") || atoi(str) == 1);
#+			this->props.freewheel = spa_atob(str);
# 	}
# 
# 	spa_loop_add_source(this->data_loop, &this->timer_source);
#diff --git a/spa/plugins/videoconvert/videoadapter.c b/spa/plugins/videoconvert/videoadapter.c
#index 74d1230531..68d24785e7 100644
#--- a/spa/plugins/videoconvert/videoadapter.c
#+++ b/spa/plugins/videoconvert/videoadapter.c
#@@ -337,7 +337,7 @@ static void follower_info(void *data, const struct spa_node_info *info)
# 
# 	if (info->props) {
# 		if ((str = spa_dict_lookup(info->props, SPA_KEY_NODE_DRIVER)) != NULL)
#-			this->driver = spa_streq(str, "true") || atoi(str) == 1;
#+			this->driver = spa_atob(str);
# 	}
# }
# 
#diff --git a/spa/tests/test-utils.c b/spa/tests/test-utils.c
#index 2706652754..cbdb5e9d90 100644
#--- a/spa/tests/test-utils.c
#+++ b/spa/tests/test-utils.c
#@@ -493,6 +493,22 @@ static void test_streq(void)
# 	spa_assert(!spa_strneq(NULL, "abc", 7));
# }
# 
#+static void test_atob(void)
#+{
#+	spa_assert(spa_atob("true"));
#+	spa_assert(spa_atob("1"));
#+	spa_assert(!spa_atob("0"));
#+	spa_assert(!spa_atob("-1"));
#+	spa_assert(!spa_atob("10"));
#+	spa_assert(!spa_atob("11"));
#+	spa_assert(!spa_atob("t"));
#+	spa_assert(!spa_atob("yes"));
#+	spa_assert(!spa_atob("no"));
#+	spa_assert(!spa_atob(NULL));
#+	spa_assert(!spa_atob("True")); /* lower-case required */
#+	spa_assert(!spa_atob("TRUE"));
#+}
#+
# int main(int argc, char *argv[])
# {
#     test_abi();
#@@ -504,5 +520,6 @@ int main(int argc, char *argv[])
#     test_ringbuffer();
#     test_strtol();
#     test_streq();
#+    test_atob();
#     return 0;
# }
#diff --git a/src/pipewire/pipewire.c b/src/pipewire/pipewire.c
#index 6b99549796..a7ecd012e5 100644
#--- a/src/pipewire/pipewire.c
#+++ b/src/pipewire/pipewire.c
#@@ -525,8 +525,7 @@ void pw_init(int *argc, char **argv[])
# 			pw_log_set(log);
# 
# #ifdef HAVE_SYSTEMD
#-		if ((str = getenv("PIPEWIRE_LOG_SYSTEMD")) == NULL ||
#-				spa_streq(str, "true") || atoi(str) != 0) {
#+		if ((str = getenv("PIPEWIRE_LOG_SYSTEMD")) == NULL || spa_atob(str)) {
# 			log = load_journal_logger(support);
# 			if (log)
# 				pw_log_set(log);
#-- 
#GitLab
#
