Skip to contentSkip to conversation

add for_each_substring() and match_substring()

PATCH In review Martin Peschke 3 participants 3 messages Mar 6, 2007 – Mar 8, 2007 Library code

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 add for_each_substring() and match_substring()

This adds for_each_substring() and match_substring() to lib/parser.c. Using these instead of strsep() and match_token() is more comfortable, less error prone and safer.

strsep() is destructive; it changes the string it is working on. match_token() needs strsep() to chop a large string up into smaller \0-terminated pieces. Callers might need to create a working copy of the string to be parsed.

In contrast, match_substring() contents itself with non-\0-terminated substrings provided by for_each_substring().

Converting users of strsep() / match_token() to for_each_substring() / match_substring(), e.g. all the stuff in fs/, should not be difficult.

---

 include/linux/parser.h |    7 +++++++
 lib/parser.c           |   45 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 51 insertions(+), 1 deletion(-)
include/linux/parser.h +7 -0
Index: linux/include/linux/parser.h
===================================================================
@@ -26,9 +26,16 @@ typedef struct {
 } substring_t;
 
 int match_token(char *, match_table_t table, substring_t args[]);
+int match_substring(substring_t *, match_table_t table, substring_t args[]);
 int match_int(substring_t *, int *result);
 int match_octal(substring_t *, int *result);
 int match_hex(substring_t *, int *result);
 void match_strcpy(char *, substring_t *);
 char *match_strdup(substring_t *);
+char *match_to(const char *cs, const char *ct);
 int match_s64(substring_t *, s64 *result, int);
+
+#define for_each_substring(s, start, delim) \
+	for ((s)->from = start, (s)->to = match_to((s)->from, delim); \
+	     (s)->to; \
+	     (s)->from = (s)->to + 1, (s)->to = match_to((s)->from, delim))
lib/parser.c +44 -1

66 lines not on this page · raw message

#1 lore raw
Quoted 9 lines · On Tue, 06 Mar 2007 20:19:23 +0100 Martin Peschke wrote:

This adds for_each_substring() and match_substring() to lib/parser.c. Using these instead of strsep() and match_token() is more comfortable, less error prone and safer.

strsep() is destructive; it changes the string it is working on. match_token() needs strsep() to chop a large string up into smaller \0-terminated pieces. Callers might need to create a working copy of the string to be parsed.

Quoted 8 lines

In contrast, match_substring() contents itself with non-\0-terminated substrings provided by for_each_substring().

Converting users of strsep() / match_token() to for_each_substring() / match_substring(), e.g. all the stuff in fs/, should not be difficult.

---

Hi,
When a patch applies only to -mm, please let us know that. Thanks.

Quoted 94 lines
 include/linux/parser.h |    7 +++++++
 lib/parser.c           |   45 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 51 insertions(+), 1 deletion(-)

Index: linux/include/linux/parser.h
===================================================================

include/linux/parser.h +7 -0
@@ -26,9 +26,16 @@ typedef struct {
 } substring_t;
 
 int match_token(char *, match_table_t table, substring_t args[]);
+int match_substring(substring_t *, match_table_t table, substring_t args[]);
 int match_int(substring_t *, int *result);
 int match_octal(substring_t *, int *result);
 int match_hex(substring_t *, int *result);
 void match_strcpy(char *, substring_t *);
 char *match_strdup(substring_t *);
+char *match_to(const char *cs, const char *ct);
 int match_s64(substring_t *, s64 *result, int);
+
+#define for_each_substring(s, start, delim) \
+	for ((s)->from = start, (s)->to = match_to((s)->from, delim); \
+	     (s)->to; \
+	     (s)->from = (s)->to + 1, (s)->to = match_to((s)->from, delim))

Index: linux/lib/parser.c
===================================================================

lib/parser.c +42 -1
@@ -27,7 +27,7 @@ static int match_one(char *s, char *p, s
 	char *meta;
 	int argc = 0;
 
-	if (!p)
+	if (!p || !s)
 		return 1;
 
 	while(1) {
@@ -111,6 +111,36 @@ int match_token(char *s, match_table_t t
 }
 
 /**
+ * match_substring: - Find a token (and optional args) in a substring
+ * @sub: the substring to examine for token/argument pairs
+ * @table: match_table_t describing the set of allowed option tokens and the
+ * arguments that may be associated with them. Must be terminated with a
+ * &struct match_token whose pattern is set to the NULL pointer.
+ * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match
+ * locations.
+ *
+ * Description: Detects which if any of a set of token strings has been passed
+ * to it. Tokens can include up to MAX_OPT_ARGS instances of basic c-style
+ * format identifiers which will be taken into account when matching the
+ * tokens, and whose locations will be returned in the @args array.
+ */
+int match_substring(substring_t *sub, match_table_t table, substring_t args[])
+{
+	char *s;
+	int token, i;
+
+	memset(args, 0, MAX_OPT_ARGS * sizeof(substring_t));
+	s = match_strdup(sub);
+	token = match_token(s, table, args);
+	for (i = 0; i < MAX_OPT_ARGS; i++) {
+		args[i].from += sub->from - s;
+		args[i].to += sub->from - s;
+	}
+	kfree(s);
+	return token;
+}
+
+/**
  * match_number: scan a number in the given base from a substring_t
  * @s: substring to be scanned
  * @result: resulting integer on success
@@ -237,6 +267,17 @@ char *match_strdup(substring_t *s)
 	return p;
 }
 
+char *match_to(const char *cs, const char *ct)
+{
+	char *delim = strpbrk(cs, ct);
+	if (delim)
+		return delim;
+	else if (*cs != '\0')
+		return (char *)(cs + strlen(cs));
+	else
+		return NULL;
+}
+
 EXPORT_SYMBOL(match_token);
 EXPORT_SYMBOL(match_int);
 EXPORT_SYMBOL(match_octal);

lib/parser.c EXPORT_SYMBOL(match_hex); · line 289

Quoted 5 lines
lib/parser.c +2 -0
@@ -244,3 +285,5 @@ EXPORT_SYMBOL(match_hex);
 EXPORT_SYMBOL(match_strcpy);
 EXPORT_SYMBOL(match_strdup);
 EXPORT_SYMBOL(match_s64);
+EXPORT_SYMBOL(match_to);
+EXPORT_SYMBOL(match_substring);

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

#2 lore raw
In reply to Martin Peschke

lib/parser.c char *match_strdup(substring_t *s) · line 276

Quoted 7 lines · Martin Peschke
lib/parser.c +7 -0
+char *match_to(const char *cs, const char *ct)
+{
+	char *delim = strpbrk(cs, ct);
+	if (delim)
+		return delim;
+	else if (*cs != '\0')
+		return (char *)(cs + strlen(cs));

This disallows the use of match_to with a real constant char array, please remove the const from the prototyp.

Bastian

Signature · 4 lines
	"Get back to your stations!"
	"We're beaming down to the planet, sir."
		-- Kirk and Mr. Leslie, "This Side of Paradise",
		   stardate 3417.3