]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/modargs.c
Fighting rewinds: Reduce calls to handle_seek
[pulseaudio] / src / pulsecore / modargs.c
index 866e6e0ce8df9de63b272a4cc8af5e964b8d4730..e78cdb9a8ca425f842d62389aaae3c88d9e1a6c6 100644 (file)
@@ -5,7 +5,7 @@
 
   PulseAudio 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 of the License,
+  by the Free Software Foundation; either version 2.1 of the License,
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
@@ -84,8 +84,11 @@ pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) {
         KEY,
         VALUE_START,
         VALUE_SIMPLE,
+        VALUE_SIMPLE_ESCAPED,
         VALUE_DOUBLE_QUOTES,
-        VALUE_TICKS
+        VALUE_DOUBLE_QUOTES_ESCAPED,
+        VALUE_TICKS,
+        VALUE_TICKS_ESCAPED
     } state;
 
     const char *p, *key = NULL, *value = NULL;
@@ -131,9 +134,16 @@ pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) {
                     value = p+1;
                     value_len = 0;
                 } else if (isspace(*p)) {
-                    if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrdup(""), valid_keys) < 0)
+                    if (add_key_value(map,
+                                      pa_xstrndup(key, key_len),
+                                      pa_xstrdup(""),
+                                      valid_keys) < 0)
                         goto fail;
                     state = WHITESPACE;
+                } else if (*p == '\\') {
+                    state = VALUE_SIMPLE_ESCAPED;
+                    value = p;
+                    value_len = 1;
                 } else {
                     state = VALUE_SIMPLE;
                     value = p;
@@ -143,30 +153,63 @@ pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) {
 
             case VALUE_SIMPLE:
                 if (isspace(*p)) {
-                    if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrndup(value, value_len), valid_keys) < 0)
+                    if (add_key_value(map,
+                                      pa_xstrndup(key, key_len),
+                                      pa_unescape(pa_xstrndup(value, value_len)),
+                                      valid_keys) < 0)
                         goto fail;
                     state = WHITESPACE;
+                } else if (*p == '\\') {
+                    state = VALUE_SIMPLE_ESCAPED;
+                    value_len++;
                 } else
                     value_len++;
                 break;
 
+            case VALUE_SIMPLE_ESCAPED:
+                state = VALUE_SIMPLE;
+                value_len++;
+                break;
+
             case VALUE_DOUBLE_QUOTES:
                 if (*p == '"') {
-                    if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrndup(value, value_len), valid_keys) < 0)
+                    if (add_key_value(map,
+                                      pa_xstrndup(key, key_len),
+                                      pa_unescape(pa_xstrndup(value, value_len)),
+                                      valid_keys) < 0)
                         goto fail;
                     state = WHITESPACE;
+                } else if (*p == '\\') {
+                    state = VALUE_DOUBLE_QUOTES_ESCAPED;
+                    value_len++;
                 } else
                     value_len++;
                 break;
 
+            case VALUE_DOUBLE_QUOTES_ESCAPED:
+                state = VALUE_DOUBLE_QUOTES;
+                value_len++;
+                break;
+
             case VALUE_TICKS:
                 if (*p == '\'') {
-                    if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrndup(value, value_len), valid_keys) < 0)
+                    if (add_key_value(map,
+                                      pa_xstrndup(key, key_len),
+                                      pa_unescape(pa_xstrndup(value, value_len)),
+                                      valid_keys) < 0)
                         goto fail;
                     state = WHITESPACE;
+                } else if (*p == '\\') {
+                    state = VALUE_TICKS_ESCAPED;
+                    value_len++;
                 } else
                     value_len++;
                 break;
+
+            case VALUE_TICKS_ESCAPED:
+                state = VALUE_TICKS;
+                value_len++;
+                break;
         }
     }
 
@@ -274,11 +317,15 @@ int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *rss) {
     pa_assert(rss);
 
     ss = *rss;
-    if ((pa_modargs_get_value_u32(ma, "rate", &ss.rate)) < 0)
+    if ((pa_modargs_get_value_u32(ma, "rate", &ss.rate)) < 0 ||
+        ss.rate <= 0 ||
+        ss.rate > PA_RATE_MAX)
         return -1;
 
     channels = ss.channels;
-    if ((pa_modargs_get_value_u32(ma, "channels", &channels)) < 0)
+    if ((pa_modargs_get_value_u32(ma, "channels", &channels)) < 0 ||
+        channels <= 0 ||
+        channels >= PA_CHANNELS_MAX)
         return -1;
     ss.channels = (uint8_t) channels;
 
@@ -314,7 +361,12 @@ int pa_modargs_get_channel_map(pa_modargs *ma, const char *name, pa_channel_map
     return 0;
 }
 
-int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *rss, pa_channel_map *rmap, pa_channel_map_def_t def) {
+int pa_modargs_get_sample_spec_and_channel_map(
+        pa_modargs *ma,
+        pa_sample_spec *rss,
+        pa_channel_map *rmap,
+        pa_channel_map_def_t def) {
+
     pa_sample_spec ss;
     pa_channel_map map;
 
@@ -327,7 +379,10 @@ int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *r
     if (pa_modargs_get_sample_spec(ma, &ss) < 0)
         return -1;
 
-    pa_channel_map_init_extend(&map, ss.channels, def);
+    map = *rmap;
+
+    if (ss.channels != map.channels)
+        pa_channel_map_init_extend(&map, ss.channels, def);
 
     if (pa_modargs_get_channel_map(ma, NULL, &map) < 0)
         return -1;
@@ -340,3 +395,33 @@ int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *r
 
     return 0;
 }
+
+int pa_modargs_get_proplist(pa_modargs *ma, const char *name, pa_proplist *p, pa_update_mode_t m) {
+    const char *v;
+    pa_proplist *n;
+
+    pa_assert(ma);
+    pa_assert(name);
+    pa_assert(p);
+
+    if (!(v = pa_modargs_get_value(ma, name, NULL)))
+        return 0;
+
+    if (!(n = pa_proplist_from_string(v)))
+        return -1;
+
+    pa_proplist_update(p, m, n);
+    pa_proplist_free(n);
+
+    return 0;
+}
+
+const char *pa_modargs_iterate(pa_modargs *ma, void **state) {
+    pa_hashmap *map = (pa_hashmap*) ma;
+    struct entry *e;
+
+    if (!(e = pa_hashmap_iterate(map, state, NULL)))
+        return NULL;
+
+    return e->key;
+}