All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ucm: Allow cset commands to have values with spaces.
@ 2012-08-09 13:43 Tanu Kaskinen
  2012-08-09 14:07 ` Takashi Iwai
  2012-08-09 15:16 ` [PATCH v2] " Tanu Kaskinen
  0 siblings, 2 replies; 6+ messages in thread
From: Tanu Kaskinen @ 2012-08-09 13:43 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai, Tanu Kaskinen

An example:
    cset "name='Input Select' Digital Mic"

The old parsing code interpreted "name='Input Select' Digital"
as the element id, which of course didn't work.

Signed-off-by: Tanu Kaskinen <tanu.kaskinen@digia.com>
---
 src/ucm/main.c |   19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/ucm/main.c b/src/ucm/main.c
index 4b37776..05a7b0a 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -170,8 +170,23 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
 	snd_ctl_elem_value_malloc(&value);
 	snd_ctl_elem_info_malloc(&info);
 
-	pos = strrchr(cset, ' ');
-	if (pos == NULL) {
+	/* Find the space after the element id, taking quoting with
+	   single-quotes into account. */
+	for (pos = cset; *pos != '\0'; pos += strcspn(pos, "' ")) {
+		if (*pos == ' ')
+			break;
+		if (*pos == '\'') {
+			pos++;
+			pos += strcspn(pos, "'");
+			if (*pos == '\0') {
+				uc_error("invalid element id (closing single-quote not found): %s", cset);
+				err = -EINVAL;
+				goto __fail;
+			}
+			pos++;
+		}
+	}
+	if (*pos == '\0') {
 		uc_error("undefined value for cset >%s<", cset);
 		err = -EINVAL;
 		goto __fail;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] ucm: Allow cset commands to have values with spaces.
  2012-08-09 13:43 [PATCH] ucm: Allow cset commands to have values with spaces Tanu Kaskinen
@ 2012-08-09 14:07 ` Takashi Iwai
  2012-08-09 14:44   ` Kaskinen Tanu
  2012-08-09 15:16 ` [PATCH v2] " Tanu Kaskinen
  1 sibling, 1 reply; 6+ messages in thread
From: Takashi Iwai @ 2012-08-09 14:07 UTC (permalink / raw)
  To: Tanu Kaskinen; +Cc: alsa-devel

At Thu, 9 Aug 2012 16:43:31 +0300,
Tanu Kaskinen wrote:
> 
> An example:
>     cset "name='Input Select' Digital Mic"
> 
> The old parsing code interpreted "name='Input Select' Digital"
> as the element id, which of course didn't work.
> 
> Signed-off-by: Tanu Kaskinen <tanu.kaskinen@digia.com>
> ---
>  src/ucm/main.c |   19 +++++++++++++++++--
>  1 file changed, 17 insertions(+), 2 deletions(-)
> 
> diff --git a/src/ucm/main.c b/src/ucm/main.c
> index 4b37776..05a7b0a 100644
> --- a/src/ucm/main.c
> +++ b/src/ucm/main.c
> @@ -170,8 +170,23 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
>  	snd_ctl_elem_value_malloc(&value);
>  	snd_ctl_elem_info_malloc(&info);
>  
> -	pos = strrchr(cset, ' ');
> -	if (pos == NULL) {
> +	/* Find the space after the element id, taking quoting with
> +	   single-quotes into account. */
> +	for (pos = cset; *pos != '\0'; pos += strcspn(pos, "' ")) {
> +		if (*pos == ' ')
> +			break;
> +		if (*pos == '\'') {

A double-quote can be supported easily here...


Takashi

> +			pos++;
> +			pos += strcspn(pos, "'");
> +			if (*pos == '\0') {
> +				uc_error("invalid element id (closing single-quote not found): %s", cset);
> +				err = -EINVAL;
> +				goto __fail;
> +			}
> +			pos++;
> +		}
> +	}
> +	if (*pos == '\0') {
>  		uc_error("undefined value for cset >%s<", cset);
>  		err = -EINVAL;
>  		goto __fail;
> -- 
> 1.7.9.5
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] ucm: Allow cset commands to have values with spaces.
  2012-08-09 14:07 ` Takashi Iwai
@ 2012-08-09 14:44   ` Kaskinen Tanu
  2012-08-09 15:12     ` Takashi Iwai
  0 siblings, 1 reply; 6+ messages in thread
From: Kaskinen Tanu @ 2012-08-09 14:44 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel

On Thu, 2012-08-09 at 16:07 +0200, Takashi Iwai wrote:
> At Thu, 9 Aug 2012 16:43:31 +0300,
> Tanu Kaskinen wrote:
> > @@ -170,8 +170,23 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
> >  	snd_ctl_elem_value_malloc(&value);
> >  	snd_ctl_elem_info_malloc(&info);
> >  
> > -	pos = strrchr(cset, ' ');
> > -	if (pos == NULL) {
> > +	/* Find the space after the element id, taking quoting with
> > +	   single-quotes into account. */
> > +	for (pos = cset; *pos != '\0'; pos += strcspn(pos, "' ")) {
> > +		if (*pos == ' ')
> > +			break;
> > +		if (*pos == '\'') {
> 
> A double-quote can be supported easily here...

True, I'll post v2 soon.

-- 
Tanu

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] ucm: Allow cset commands to have values with spaces.
  2012-08-09 14:44   ` Kaskinen Tanu
@ 2012-08-09 15:12     ` Takashi Iwai
  2012-08-09 15:23       ` Kaskinen Tanu
  0 siblings, 1 reply; 6+ messages in thread
From: Takashi Iwai @ 2012-08-09 15:12 UTC (permalink / raw)
  To: Kaskinen Tanu; +Cc: alsa-devel

At Thu, 9 Aug 2012 17:44:12 +0300,
Kaskinen Tanu wrote:
> 
> On Thu, 2012-08-09 at 16:07 +0200, Takashi Iwai wrote:
> > At Thu, 9 Aug 2012 16:43:31 +0300,
> > Tanu Kaskinen wrote:
> > > @@ -170,8 +170,23 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
> > >  	snd_ctl_elem_value_malloc(&value);
> > >  	snd_ctl_elem_info_malloc(&info);
> > >  
> > > -	pos = strrchr(cset, ' ');
> > > -	if (pos == NULL) {
> > > +	/* Find the space after the element id, taking quoting with
> > > +	   single-quotes into account. */
> > > +	for (pos = cset; *pos != '\0'; pos += strcspn(pos, "' ")) {
> > > +		if (*pos == ' ')
> > > +			break;
> > > +		if (*pos == '\'') {
> > 
> > A double-quote can be supported easily here...
> 
> True, I'll post v2 soon.

On the second thought, parsing the string intensively at that point
doesn't make sense.  The string will be parsed anyway in
snd_ctl_ascii_elem_id_parse(), then why not just let it give the next
pointer from there?

Below is a quick hack (untested at all!).  Could you check whether it
works?


Takashi

---
diff --git a/src/control/ctlparse.c b/src/control/ctlparse.c
index a16f96a..b0c4ef3 100644
--- a/src/control/ctlparse.c
+++ b/src/control/ctlparse.c
@@ -143,21 +143,19 @@ char *snd_ctl_ascii_elem_id_get(snd_ctl_elem_id_t *id)
 	return strdup(buf);
 }
 
-/**
- * \brief parse ASCII string as CTL element identifier
- * \param dst destination CTL identifier
- * \param str source ASCII string
- * \return zero on success, otherwise a negative error code
- */
-int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
+#ifndef DOC_HIDDEN
+/* used by UCM parser, too */
+int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str,
+				  const char **ret_ptr)
 {
 	int c, size, numid;
+	int err = -EINVAL;
 	char *ptr;
 
-	while (*str == ' ' || *str == '\t')
+	while (isspace(*str))
 		str++;
 	if (!(*str))
-		return -EINVAL;
+		goto out;
 	snd_ctl_elem_id_set_interface(dst, SND_CTL_ELEM_IFACE_MIXER);	/* default */
 	while (*str) {
 		if (!strncasecmp(str, "numid=", 6)) {
@@ -165,7 +163,7 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
 			numid = atoi(str);
 			if (numid <= 0) {
 				fprintf(stderr, "amixer: Invalid numid %d\n", numid);
-				return -EINVAL;
+				goto out;
 			}
 			snd_ctl_elem_id_set_numid(dst, atoi(str));
 			while (isdigit(*str))
@@ -191,7 +189,7 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
 				snd_ctl_elem_id_set_interface(dst, SND_CTL_ELEM_IFACE_SEQUENCER);
 				str += 9;
 			} else {
-				return -EINVAL;
+				goto out;
 			}
 		} else if (!strncasecmp(str, "name=", 5)) {
 			char buf[64];
@@ -239,11 +237,33 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
 		if (*str == ',') {
 			str++;
 		} else {
+			/* when ret_ptr is given, allow to terminate gracefully
+			 * at the next space letter
+			 */
+			if (ret_ptr && isspace(*str))
+				break;
 			if (*str)
-				return -EINVAL;
+				goto out;
 		}
 	}			
-	return 0;
+	err = 0;
+
+ out:
+	if (ret_ptr)
+		*ret_ptr = str;
+	return err;
+}
+#endif
+
+/**
+ * \brief parse ASCII string as CTL element identifier
+ * \param dst destination CTL identifier
+ * \param str source ASCII string
+ * \return zero on success, otherwise a negative error code
+ */
+int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
+{
+	return __snd_ctl_ascii_elem_id_parse(dst, str, NULL);
 }
 
 static int get_ctl_enum_item_index(snd_ctl_t *handle,
diff --git a/src/ucm/main.c b/src/ucm/main.c
index 4b37776..bd5c348 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -31,6 +31,7 @@
  */
 
 #include "ucm_local.h"
+#include <ctype.h>
 #include <stdarg.h>
 #include <pthread.h>
 
@@ -158,9 +159,13 @@ static int open_ctl(snd_use_case_mgr_t *uc_mgr,
 	return 0;
 }
 
+extern int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst,
+					 const char *str,
+					 const char **ret_ptr);
+
 static int execute_cset(snd_ctl_t *ctl, char *cset)
 {
-	char *pos;
+	const char *pos;
 	int err;
 	snd_ctl_elem_id_t *id;
 	snd_ctl_elem_value_t *value;
@@ -170,16 +175,16 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
 	snd_ctl_elem_value_malloc(&value);
 	snd_ctl_elem_info_malloc(&info);
 
-	pos = strrchr(cset, ' ');
-	if (pos == NULL) {
+	err = __snd_ctl_ascii_elem_id_parse(id, cset, &pos);
+	if (err < 0)
+		goto __fail;
+	while (*pos && isspace(*pos))
+		pos++;
+	if (!*pos) {
 		uc_error("undefined value for cset >%s<", cset);
 		err = -EINVAL;
 		goto __fail;
 	}
-	*pos = '\0';
-	err = snd_ctl_ascii_elem_id_parse(id, cset);
-	if (err < 0)
-		goto __fail;
 	snd_ctl_elem_value_set_id(value, id);
 	snd_ctl_elem_info_set_id(info, id);
 	err = snd_ctl_elem_read(ctl, value);
@@ -188,7 +193,7 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
 	err = snd_ctl_elem_info(ctl, info);
 	if (err < 0)
 		goto __fail;
-	err = snd_ctl_ascii_value_parse(ctl, value, info, pos + 1);
+	err = snd_ctl_ascii_value_parse(ctl, value, info, pos);
 	if (err < 0)
 		goto __fail;
 	err = snd_ctl_elem_write(ctl, value);
@@ -196,9 +201,6 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
 		goto __fail;
 	err = 0;
       __fail:
-	if (pos != NULL)
-		*pos = ' ';
-
 	if (id != NULL)
 		free(id);
 	if (value != NULL)

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2] ucm: Allow cset commands to have values with spaces.
  2012-08-09 13:43 [PATCH] ucm: Allow cset commands to have values with spaces Tanu Kaskinen
  2012-08-09 14:07 ` Takashi Iwai
@ 2012-08-09 15:16 ` Tanu Kaskinen
  1 sibling, 0 replies; 6+ messages in thread
From: Tanu Kaskinen @ 2012-08-09 15:16 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai, Tanu Kaskinen

An example:
    cset "name='Input Select' Digital Mic"

The old parsing code interpreted "name='Input Select' Digital"
as the element id, which of course didn't work.

Signed-off-by: Tanu Kaskinen <tanu.kaskinen@digia.com>
---
 src/ucm/main.c |   22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/src/ucm/main.c b/src/ucm/main.c
index 4b37776..518349a 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -162,6 +162,7 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
 {
 	char *pos;
 	int err;
+	int nulled = 0;
 	snd_ctl_elem_id_t *id;
 	snd_ctl_elem_value_t *value;
 	snd_ctl_elem_info_t *info;
@@ -170,13 +171,28 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
 	snd_ctl_elem_value_malloc(&value);
 	snd_ctl_elem_info_malloc(&info);
 
-	pos = strrchr(cset, ' ');
-	if (pos == NULL) {
+	/* Find the space after the element id, taking quoting into account. */
+	for (pos = cset; *pos != ' ' && *pos != '\0'; pos += strcspn(pos, " '\"")) {
+		if (*pos == '\'' || *pos == '"') {
+			char quote = *pos;
+
+			pos++;
+			pos = strchr(pos, quote);
+			if (pos == NULL) {
+				uc_error("invalid element id (closing quote not found): %s", cset);
+				err = -EINVAL;
+				goto __fail;
+			}
+			pos++;
+		}
+	}
+	if (*pos == '\0') {
 		uc_error("undefined value for cset >%s<", cset);
 		err = -EINVAL;
 		goto __fail;
 	}
 	*pos = '\0';
+	nulled = 1;
 	err = snd_ctl_ascii_elem_id_parse(id, cset);
 	if (err < 0)
 		goto __fail;
@@ -196,7 +212,7 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
 		goto __fail;
 	err = 0;
       __fail:
-	if (pos != NULL)
+	if (nulled)
 		*pos = ' ';
 
 	if (id != NULL)
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] ucm: Allow cset commands to have values with spaces.
  2012-08-09 15:12     ` Takashi Iwai
@ 2012-08-09 15:23       ` Kaskinen Tanu
  0 siblings, 0 replies; 6+ messages in thread
From: Kaskinen Tanu @ 2012-08-09 15:23 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel

On Thu, 2012-08-09 at 17:12 +0200, Takashi Iwai wrote:
> At Thu, 9 Aug 2012 17:44:12 +0300,
> Kaskinen Tanu wrote:
> > 
> > On Thu, 2012-08-09 at 16:07 +0200, Takashi Iwai wrote:
> > > At Thu, 9 Aug 2012 16:43:31 +0300,
> > > Tanu Kaskinen wrote:
> > > > @@ -170,8 +170,23 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
> > > >  	snd_ctl_elem_value_malloc(&value);
> > > >  	snd_ctl_elem_info_malloc(&info);
> > > >  
> > > > -	pos = strrchr(cset, ' ');
> > > > -	if (pos == NULL) {
> > > > +	/* Find the space after the element id, taking quoting with
> > > > +	   single-quotes into account. */
> > > > +	for (pos = cset; *pos != '\0'; pos += strcspn(pos, "' ")) {
> > > > +		if (*pos == ' ')
> > > > +			break;
> > > > +		if (*pos == '\'') {
> > > 
> > > A double-quote can be supported easily here...
> > 
> > True, I'll post v2 soon.
> 
> On the second thought, parsing the string intensively at that point
> doesn't make sense.  The string will be parsed anyway in
> snd_ctl_ascii_elem_id_parse(), then why not just let it give the next
> pointer from there?
> 
> Below is a quick hack (untested at all!).  Could you check whether it
> works?

It does :)

-- 
Tanu

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-08-09 14:53 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-09 13:43 [PATCH] ucm: Allow cset commands to have values with spaces Tanu Kaskinen
2012-08-09 14:07 ` Takashi Iwai
2012-08-09 14:44   ` Kaskinen Tanu
2012-08-09 15:12     ` Takashi Iwai
2012-08-09 15:23       ` Kaskinen Tanu
2012-08-09 15:16 ` [PATCH v2] " Tanu Kaskinen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.