[pulseaudio-discuss] [PATCH v5 7/7] message-params: Add read/write functions for various simple data types

Georg Chini georg at chini.tk
Mon Jan 29 15:17:18 UTC 2018


See doc/messaging_api.txt for the added functions. All read functions
return 1 on success, 0 if end of string is found and -1 on parse error.
Additionally, for the numeric/boolean read functions, 2 is returned if
the list element is empty.
---
 doc/messaging_api.txt      |  15 +++-
 src/map-file               |   9 ++
 src/pulse/message-params.c | 211 +++++++++++++++++++++++++++++++++++++++------
 src/pulse/message-params.h |  35 ++++++++
 4 files changed, 242 insertions(+), 28 deletions(-)

diff --git a/doc/messaging_api.txt b/doc/messaging_api.txt
index 0e6be53f..d080b783 100644
--- a/doc/messaging_api.txt
+++ b/doc/messaging_api.txt
@@ -27,6 +27,11 @@ the structure
 pa_message_param_begin_list() - starts a list
 pa_message_param_end_list() - ends a list
 pa_message_param_write_string() - writes a string to a pa_message_param structure
+pa_message_param_write_double() - writes a double to a pa_message_param structure
+pa_message_param_write_int64() - writes an integer to a pa_message_param structure
+pa_message_param_write_uint64() - writes an unsigned to a pa_message_param structure
+pa_message_param_write_bool() - writes a boolean to a pa_message_param structure
+pa_message_param_write_raw() - writes raw a string to a pa_message_param structure
 
 For string parameters that contain curly braces, those braces must be escaped
 by adding a "\" before them. This however means that a trailing backslash would
@@ -44,9 +49,15 @@ Other strings can be passed without modification.
 For reading, the following functions are available:
 pa_message_param_split_list() - parse message parameter string
 pa_message_param_read_string() - read a string from a parameter list
+pa_message_param_read_double() - read a double from a parameter list
+pa_message_param_read_int64() - read an integer from a parameter list
+pa_message_param_read_uint64() - read an unsigned from a parameter list
+pa_message_param_read_bool() - read a boolean from a parameter list
 
-pa_message_param_read_string() also reverts the changes that
-pa_message_param_write_string() might have introduced.
+All read functions return 1 on success, 0 if end of string is found and -1 on
+parse error. Additionally, for the numeric/boolean read functions, 2 is returned
+if the list element is empty. Also pa_message_param_read_string() reverts the
+changes that pa_message_param_write_string() might have introduced.
 
 Reference:
 
diff --git a/src/map-file b/src/map-file
index 372d190d..ab8c21c6 100644
--- a/src/map-file
+++ b/src/map-file
@@ -228,10 +228,19 @@ pa_mainloop_wakeup;
 pa_message_param_begin_list;
 pa_message_param_end_list;
 pa_message_param_new;
+pa_message_param_read_bool;
+pa_message_param_read_double;
+pa_message_param_read_int64;
 pa_message_param_read_string;
+pa_message_param_read_uint64;
 pa_message_param_split_list;
 pa_message_param_to_string;
+pa_message_param_write_bool;
+pa_message_param_write_double;
+pa_message_param_write_int64;
+pa_message_param_write_raw;
 pa_message_param_write_string;
+pa_message_param_write_uint64;
 pa_msleep;
 pa_operation_cancel;
 pa_operation_get_state;
diff --git a/src/pulse/message-params.c b/src/pulse/message-params.c
index c1abf62b..f4d2c048 100644
--- a/src/pulse/message-params.c
+++ b/src/pulse/message-params.c
@@ -23,6 +23,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <locale.h>
 #include <sys/types.h>
 
 #include <pulse/xmalloc.h>
@@ -58,7 +59,7 @@ int pa_message_param_split_list(char *c, char **result, void **state) {
 
     /* Empty or no string */
     if (!*current || *c == 0)
-        return 0;
+        return PA_PARAM_LIST_END;
 
     /* Find opening brace */
     while (*current != 0) {
@@ -75,7 +76,7 @@ int pa_message_param_split_list(char *c, char **result, void **state) {
 
         /* unexpected closing brace, parse error */
         if (*current == '}' && !found_backslash)
-            return -1;
+            return PA_PARAM_PARSE_ERROR;
 
         found_backslash = false;
         current++;
@@ -83,7 +84,7 @@ int pa_message_param_split_list(char *c, char **result, void **state) {
 
     /* No opening brace found, end of string */
     if (*current == 0)
-        return 0;
+        return PA_PARAM_LIST_END;
 
     *result = current + 1;
     found_backslash = false;
@@ -109,7 +110,7 @@ int pa_message_param_split_list(char *c, char **result, void **state) {
     /* Parse error, closing brace missing */
     if (open_braces != 0) {
         *result = NULL;
-        return -1;
+        return PA_PARAM_PARSE_ERROR;
     }
 
     /* Replace } with 0 */
@@ -117,48 +118,154 @@ int pa_message_param_split_list(char *c, char **result, void **state) {
 
     *state = current + 1;
 
-    return 1;
+    return PA_PARAM_OK;
 }
 
 /* Read a string from the parameter list. The state pointer is
- * advanced to the next element of the list Escaping is removed
+ * advanced to the next element of the list. Escaping is removed
  * from the string. */
 int pa_message_param_read_string(char *c, char **result, void **state) {
     char *start_pos;
+    char *value, *tmp;
     int err;
 
     pa_assert(result);
 
     *result = NULL;
 
-    if ((err = pa_message_param_split_list(c, &start_pos, state)) > 0)
-        *result = pa_xstrdup(start_pos);
+    if ((err = pa_message_param_split_list(c, &start_pos, state)) != PA_PARAM_OK)
+        return err;
 
-    if (*result) {
-        char *value, *tmp;
+    *result = pa_xstrdup(start_pos);
+    value = *result;
 
-        value = *result;
+    /* Remove leading and trailing quotes if present */
+    if (*value == '\'' && value[strlen(value) - 1] == '\'') {
+        memmove(value, value + 1, strlen(value));
+        value[strlen(value) - 1] = 0;
+    }
 
-        /* Remove leading and trailing quotes if present */
-        if (*value == '\'' && value[strlen(value) - 1] == '\'') {
-            memmove(value, value + 1, strlen(value));
-            value[strlen(value) - 1] = 0;
-        }
+    /* Remove escape character from curly braces if present. */
+    while ((tmp = strstr(value, "\\{")))
+        memmove(tmp, tmp + 1, strlen(value) - (size_t)(tmp  - value));
+    while ((tmp = strstr(value, "\\}")))
+        memmove(tmp, tmp + 1, strlen(value) - (size_t)(tmp  - value));
+
+    /* Remove trailing 0's. */
+    tmp = pa_xstrdup(value);
+    pa_xfree(value);
+
+    *result = tmp;
+
+    return PA_PARAM_OK;
+}
+
+/* Read a double from the parameter list. The state pointer is
+ * advanced to the next element of the list. */
+int pa_message_param_read_double(char *c, double *result, void **state) {
+    char *start_pos, *s;
+    int err;
+    struct lconv *locale;
+
+    pa_assert(result);
 
-        /* Remove escape character from curly braces if present. */
-        while ((tmp = strstr(value, "\\{")))
-            memmove(tmp, tmp + 1, strlen(value) - (size_t)(tmp  - value));
-        while ((tmp = strstr(value, "\\}")))
-            memmove(tmp, tmp + 1, strlen(value) - (size_t)(tmp  - value));
+    *result = 0;
 
-        /* Remove trailing 0's. */
-        tmp = pa_xstrdup(value);
-        pa_xfree(value);
+    if ((err = pa_message_param_split_list(c, &start_pos, state)) != PA_PARAM_OK)
+        return err;
 
-        *result = tmp;
+    /* Empty element */
+    if (strlen(start_pos) == 0)
+        return PA_PARAM_IS_NULL;
+
+    locale = localeconv();
+
+    /* Replace decimal point with the correct character for the
+     * current locale. This assumes that no thousand separator
+     * is used. */
+    for (s = start_pos; *s; s++) {
+        if (*s == '.' || *s == ',')
+            *s = *locale->decimal_point;
     }
 
-    return err;
+    errno = 0;
+    *result = strtod(start_pos, NULL);
+
+    if (errno != 0)
+        return PA_PARAM_PARSE_ERROR;
+
+    return PA_PARAM_OK;
+}
+
+/* Read an integer from the parameter list. The state pointer is
+ * advanced to the next element of the list. */
+int pa_message_param_read_int64(char *c, int64_t *result, void **state) {
+    char *start_pos;
+    int err;
+
+    pa_assert(result);
+
+    *result = 0;
+
+    if ((err = pa_message_param_split_list(c, &start_pos, state)) != PA_PARAM_OK)
+        return err;
+
+    /* Empty element */
+    if (strlen(start_pos) == 0)
+        return PA_PARAM_IS_NULL;
+
+    errno = 0;
+    *result = strtol(start_pos, NULL, 0);
+
+    if (errno != 0)
+        return PA_PARAM_PARSE_ERROR;
+
+    return PA_PARAM_OK;
+}
+
+/* Read an unsigned integer from the parameter list. The state pointer is
+ * advanced to the next element of the list. */
+int pa_message_param_read_uint64(char *c, uint64_t *result, void **state) {
+    char *start_pos;
+    int err;
+
+    pa_assert(result);
+
+    *result = 0;
+
+    if ((err = pa_message_param_split_list(c, &start_pos, state)) != PA_PARAM_OK)
+        return err;
+
+    /* Empty element */
+    if (strlen(start_pos) == 0)
+        return PA_PARAM_IS_NULL;
+
+    errno = 0;
+    *result = strtoul(start_pos, NULL, 0);
+
+    if (errno != 0)
+        return PA_PARAM_PARSE_ERROR;
+
+    return PA_PARAM_OK;
+}
+
+/* Read a boolean from the parameter list. The state pointer is
+ * advanced to the next element of the list. */
+int pa_message_param_read_bool(char *c, bool *result, void **state) {
+    int err;
+    uint64_t value;
+
+    pa_assert(result);
+
+    *result = false;
+
+    if ((err = pa_message_param_read_uint64(c, &value, state)) != PA_PARAM_OK)
+        return err;
+
+    if (value)
+        *result = true;
+
+    return PA_PARAM_OK;
 }
 
 /* Write functions. The functions are wrapper functions around pa_strbuf,
@@ -259,3 +366,55 @@ void pa_message_param_write_string(pa_message_param *param, const char *value, b
     pa_strbuf_puts(param->buffer, output);
     pa_xfree(output);
 }
+
+/* Writes a raw string to the pa_message_param structure. This is needed
+ * if a string cannot be written in one step. */
+void pa_message_param_write_raw(pa_message_param *param, const char *value) {
+    pa_assert(param);
+
+    /* Null value is not written */
+    if (!value)
+        return;
+
+    pa_strbuf_puts(param->buffer, value);
+}
+
+/* Writes a double to a message_param structure, adding curly braces.
+ * precision gives the number of significant digits, not digits after
+ * the decimal point. */
+void pa_message_param_write_double(pa_message_param *param, double value, int precision) {
+
+    pa_assert(param);
+
+    /* We do not care about locale because we do not know which locale is
+     * used on the server side. The decimal point character is converted
+     * to the server locale by the read function. */
+    pa_strbuf_printf(param->buffer, "{%.*g}",  precision, value);
+}
+
+/* Writes an integer to a message_param structure, adding curly braces. */
+void pa_message_param_write_int64(pa_message_param *param, int64_t value) {
+
+    pa_assert(param);
+
+    pa_strbuf_printf(param->buffer, "{%li}", value);
+}
+
+/* Writes an unsigned integer to a message_param structure, adding curly braces. */
+void pa_message_param_write_uint64(pa_message_param *param, uint64_t value) {
+
+    pa_assert(param);
+
+    pa_strbuf_printf(param->buffer, "{%lu}", value);
+}
+
+/* Writes a boolean to a message_param structure, adding curly braces. */
+void pa_message_param_write_bool(pa_message_param *param, bool value) {
+
+    pa_assert(param);
+
+    if (value)
+        pa_strbuf_puts(param->buffer, "{1}");
+    else
+        pa_strbuf_puts(param->buffer, "{0}");
+}
diff --git a/src/pulse/message-params.h b/src/pulse/message-params.h
index d24b4a54..80419965 100644
--- a/src/pulse/message-params.h
+++ b/src/pulse/message-params.h
@@ -32,6 +32,14 @@ PA_C_DECL_BEGIN
 
 typedef struct pa_message_param pa_message_param;
 
+/* Read function return values */
+enum {
+    PA_PARAM_PARSE_ERROR = -1,
+    PA_PARAM_LIST_END = 0,
+    PA_PARAM_OK = 1,
+    PA_PARAM_IS_NULL = 2,
+};
+
 /** Read functions */
 
 /** Split message parameter string into list elements */
@@ -40,6 +48,18 @@ int pa_message_param_split_list(char *c, char **result, void **state);
 /** Read a string from the parameter list. */
 int pa_message_param_read_string(char *c, char **result, void **state);
 
+/** Read a double from the parameter list. */
+int pa_message_param_read_double(char *c, double *result, void **state);
+
+/** Read an integer from the parameter list. */
+int pa_message_param_read_int64(char *c, int64_t *result, void **state);
+
+/** Read an unsigned integer from the parameter list. */
+int pa_message_param_read_uint64(char *c, uint64_t *result, void **state);
+
+/** Read a boolean from the parameter list. */
+int pa_message_param_read_bool(char *c, bool *result, void **state);
+
 /** Write functions */
 
 /** Create a new pa_message_param structure */
@@ -57,6 +77,21 @@ void pa_message_param_end_list(pa_message_param *param);
 /** Append string to parameter list */
 void pa_message_param_write_string(pa_message_param *param, const char *value, bool do_escape);
 
+/** Append a double to parameter list */
+void pa_message_param_write_double(pa_message_param *param, double value, int precision);
+
+/** Append an integer to parameter list */
+void pa_message_param_write_int64(pa_message_param *param, int64_t value);
+
+/** Append an unsigned integer to parameter list */
+void pa_message_param_write_uint64(pa_message_param *param, uint64_t value);
+
+/** Append a boolean to parameter list */
+void pa_message_param_write_bool(pa_message_param *param, bool value);
+
+/** Append a  raw string to parameter list */
+void pa_message_param_write_raw(pa_message_param *param, const char *value);
+
 PA_C_DECL_END
 
 #endif
-- 
2.14.1



More information about the pulseaudio-discuss mailing list