Browse Source

Lazy compilation of regexp

Serj Kalichev 5 months ago
parent
commit
b135c0e4ba
3 changed files with 29 additions and 18 deletions
  1. 2 2
      clish/ptype.h
  2. 8 2
      clish/ptype/private.h
  3. 19 14
      clish/ptype/ptype.c

+ 2 - 2
clish/ptype.h

@@ -65,7 +65,7 @@ void clish_ptype_free(void *instance);
  *   may not be identical to that passed in. e.g. it may have been
  *   a case-modified "select" or a preprocessed value.
  */
-char *clish_ptype_validate(const clish_ptype_t * instance, const char *text);
+char *clish_ptype_validate(clish_ptype_t * instance, const char *text);
 /**
  * This is the translation method for the specified type. The text is
  * first validated then translated into the form which should be used
@@ -76,7 +76,7 @@ char *clish_ptype_validate(const clish_ptype_t * instance, const char *text);
  *   may not be identical to that passed in. e.g. it may have been
  *   a translated "select" value.
  */
-char *clish_ptype_translate(const clish_ptype_t * instance, const char *text);
+char *clish_ptype_translate(clish_ptype_t * instance, const char *text);
 /**
  * This is used to perform parameter auto-completion
  */

+ 8 - 2
clish/ptype/private.h

@@ -18,6 +18,12 @@ struct clish_ptype_select_s {
 	lub_argv_t *items;
 };
 
+typedef struct clish_ptype_regex_s clish_ptype_regex_t;
+struct clish_ptype_regex_s {
+	bool_t is_compiled;
+	regex_t re;
+};
+
 struct clish_ptype_s {
 	char *name;
 	char *text;
@@ -25,9 +31,9 @@ struct clish_ptype_s {
 	char *range;
 	clish_ptype_method_e method;
 	clish_ptype_preprocess_e preprocess;
-	unsigned last_name;	/* index used for auto-completion */
+	unsigned int last_name; /* Index used for auto-completion */
 	union {
-		regex_t regexp;
+		clish_ptype_regex_t regex;
 		clish_ptype_integer_t integer;
 		clish_ptype_select_t select;
 	} u;

+ 19 - 14
clish/ptype/ptype.c

@@ -55,7 +55,8 @@ static void clish_ptype_fini(clish_ptype_t * this)
 	if (this->pattern) {
 		switch (this->method) {
 		case CLISH_PTYPE_METHOD_REGEXP:
-			regfree(&this->u.regexp);
+			if (this->u.regex.is_compiled)
+				regfree(&this->u.regex.re);
 			break;
 		case CLISH_PTYPE_METHOD_INTEGER:
 		case CLISH_PTYPE_METHOD_UNSIGNEDINTEGER:
@@ -287,7 +288,7 @@ void clish_ptype_word_generator(clish_ptype_t * this,
 }
 
 /*--------------------------------------------------------- */
-static char *clish_ptype_validate_or_translate(const clish_ptype_t * this,
+static char *clish_ptype_validate_or_translate(clish_ptype_t * this,
 	const char *text, bool_t translate)
 {
 	char *result = lub_string_dup(text);
@@ -326,8 +327,18 @@ static char *clish_ptype_validate_or_translate(const clish_ptype_t * this,
 	switch (this->method) {
 	/*------------------------------------------------- */
 	case CLISH_PTYPE_METHOD_REGEXP:
-		/* test the regular expression against the string */
-		if (0 != regexec(&this->u.regexp, result, 0, NULL, 0)) {
+		/* Lazy compilation of the regular expression */
+		if (!this->u.regex.is_compiled) {
+			if (regcomp(&this->u.regex.re, this->pattern,
+				REG_NOSUB | REG_EXTENDED)) {
+				lub_string_free(result);
+				result = NULL;
+				break;
+			}
+			this->u.regex.is_compiled = BOOL_TRUE;
+		}
+
+		if (regexec(&this->u.regex.re, result, 0, NULL, 0)) {
 			lub_string_free(result);
 			result = NULL;
 		}
@@ -423,13 +434,13 @@ static char *clish_ptype_validate_or_translate(const clish_ptype_t * this,
 }
 
 /*--------------------------------------------------------- */
-char *clish_ptype_validate(const clish_ptype_t * this, const char *text)
+char *clish_ptype_validate(clish_ptype_t * this, const char *text)
 {
 	return clish_ptype_validate_or_translate(this, text, BOOL_FALSE);
 }
 
 /*--------------------------------------------------------- */
-char *clish_ptype_translate(const clish_ptype_t * this, const char *text)
+char *clish_ptype_translate(clish_ptype_t * this, const char *text)
 {
 	return clish_ptype_validate_or_translate(this, text, BOOL_TRUE);
 }
@@ -452,17 +463,11 @@ void clish_ptype__set_pattern(clish_ptype_t * this,
 	/*------------------------------------------------- */
 	case CLISH_PTYPE_METHOD_REGEXP:
 	{
-		int result;
-
-		/* only the expression is allowed */
 		lub_string_cat(&this->pattern, "^");
 		lub_string_cat(&this->pattern, pattern);
 		lub_string_cat(&this->pattern, "$");
-
-		/* compile the regular expression for later use */
-		result = regcomp(&this->u.regexp, this->pattern,
-			REG_NOSUB | REG_EXTENDED);
-		assert(0 == result);
+		/* Use lazy mechanism to compile regular expressions */
+		this->u.regex.is_compiled = BOOL_FALSE;
 		break;
 	}
 	/*------------------------------------------------- */