MINOR: pattern/map/acl: Centralization of the file parsers

The acl and map function do the same work with the file parsing. This
patch merge these code in only one.

Note that the function map_read_entries_from_file() in the file "map.c"
is moved to the the function pat_ref_read_from_file_smp() in the file
"pattern.c". The code of this function is not modified, only the the
name and the arguments order has changed.
This commit is contained in:
Thierry FOURNIER 2014-01-29 13:29:45 +01:00 committed by Willy Tarreau
parent 9356c68727
commit 39bef456fb
4 changed files with 130 additions and 157 deletions

View File

@ -186,7 +186,7 @@ int pat_ref_load(struct pat_ref *ref, struct pattern_expr *expr, int patflags, i
*/
void pattern_init_head(struct pattern_head *head);
void pattern_prune(struct pattern_head *head);
int pattern_read_from_file(struct pattern_head *head, unsigned int refflags, const char *filename, int patflags, char **err, const char *display);
int pattern_read_from_file(struct pattern_head *head, unsigned int refflags, const char *filename, int patflags, int load_smp, char **err, const char *display);
/*
* pattern_expr manipulation.

View File

@ -451,7 +451,7 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *
snprintf(trash.str, trash.size, "acl(s) loaded from file '%s'", args[1]);
trash.str[trash.size - 1] = '\0';
if (!pattern_read_from_file(&expr->pat, PAT_REF_ACL, args[1], patflags | PAT_F_FROM_FILE, err, trash.str))
if (!pattern_read_from_file(&expr->pat, PAT_REF_ACL, args[1], patflags | PAT_F_FROM_FILE, 0, err, trash.str))
goto out_free_expr;
is_loaded = 1;
args++;

134
src/map.c
View File

@ -108,107 +108,6 @@ static struct map_descriptor *map_create_descriptor(struct sample_conv *conv)
return desc;
}
/* Reads patterns from a file. If <err_msg> is non-NULL, an error message will
* be returned there on errors and the caller will have to free it.
*
* The file contains one key + value per line. Lines which start with '#' are
* ignored, just like empty lines. Leading tabs/spaces are stripped. The key is
* then the first "word" (series of non-space/tabs characters), and the value is
* what follows this series of space/tab till the end of the line excluding
* trailing spaces/tabs.
*
* Example :
*
* # this is a comment and is ignored
* 62.212.114.60 1wt.eu \n
* <-><-----------><---><----><---->
* | | | | `--- trailing spaces ignored
* | | | `-------- value
* | | `--------------- middle spaces ignored
* | `------------------------ key
* `-------------------------------- leading spaces ignored
*
* Return non-zero in case of succes, otherwise 0.
*/
static int map_read_entries_from_file(const char *filename,
struct pat_ref *ref,
char **err)
{
FILE *file;
char *c;
int ret = 0;
int line = 0;
char *key_beg;
char *key_end;
char *value_beg;
char *value_end;
file = fopen(filename, "r");
if (!file) {
memprintf(err, "failed to open pattern file <%s>", filename);
return 0;
}
/* now parse all patterns. The file may contain only one pattern
* followed by one value per line. The start spaces, separator spaces
* and and spaces are stripped. Each can contain comment started by '#'
*/
while (fgets(trash.str, trash.size, file) != NULL) {
line++;
c = trash.str;
/* ignore lines beginning with a dash */
if (*c == '#')
continue;
/* strip leading spaces and tabs */
while (*c == ' ' || *c == '\t')
c++;
/* empty lines are ignored too */
if (*c == '\0' || *c == '\r' || *c == '\n')
continue;
/* look for the end of the key */
key_beg = c;
while (*c && *c != ' ' && *c != '\t' && *c != '\n' && *c != '\r')
c++;
key_end = c;
/* strip middle spaces and tabs */
while (*c == ' ' || *c == '\t')
c++;
/* look for the end of the value, it is the end of the line */
value_beg = c;
while (*c && *c != '\n' && *c != '\r')
c++;
value_end = c;
/* trim possibly trailing spaces and tabs */
while (value_end > value_beg && (value_end[-1] == ' ' || value_end[-1] == '\t'))
value_end--;
/* set final \0 and check entries */
*key_end = '\0';
*value_end = '\0';
/* insert values */
if (!pat_ref_append(ref, key_beg, value_beg, line)) {
memprintf(err, "out of memory");
goto out_close;
}
}
/* succes */
ret = 1;
out_close:
fclose(file);
return ret;
}
/* This function load the map file according with data type declared into
* the "struct sample_conv".
*
@ -217,28 +116,7 @@ static int map_read_entries_from_file(const char *filename,
*/
static int sample_load_map(struct arg *arg, struct sample_conv *conv, char **err)
{
struct pat_ref *ref;
struct map_descriptor *desc;
struct pattern_expr *expr;
/* look for existing map reference. The reference is the
* file encountered in the first argument. arg[0] with string
* type is guaranteed by the parser.
*
* If the reference dosn't exists, create it and load file.
*/
ref = pat_ref_lookup(arg[0].data.str.str);
if (!ref) {
snprintf(trash.str, trash.size, "map(s) loaded from file '%s'", arg[0].data.str.str);
trash.str[trash.size - 1] = '\0';
ref = pat_ref_new(arg[0].data.str.str, trash.str, PAT_REF_MAP);
if (!ref) {
memprintf(err, "out of memory");
return 0;
}
if (!map_read_entries_from_file(arg[0].data.str.str, ref, err))
return 0;
}
/* create new map descriptor */
desc = map_create_descriptor(conv);
@ -273,13 +151,13 @@ static int sample_load_map(struct arg *arg, struct sample_conv *conv, char **err
return 0;
}
/* Create new pattern expression for this reference. */
expr = pattern_new_expr(&desc->pat, ref, err);
if (!expr)
return 0;
/* Build displayed message. */
snprintf(trash.str, trash.size, "map(s) loaded from file '%s'", arg[0].data.str.str);
trash.str[trash.size - 1] = '\0';
/* Load the reference content in the pattern expression. */
if (!pat_ref_load(ref, expr, 0, 1, err))
/* Load map. */
if (!pattern_read_from_file(&desc->pat, PAT_REF_MAP, arg[0].data.str.str, 0,
1, err, trash.str))
return 0;
/* The second argument is the default value */

View File

@ -1696,27 +1696,6 @@ void pat_ref_prune(struct pat_ref *ref)
expr->pat_head->prune(expr);
}
/* This function browse <ref> and try to index each entries in the <expr>.
* If the flag <soe> (stop on error) is set, this function stop on the first
* error, <err> is filled and return 0. If is not set, the function try to
* load each entries and 1 is always returned.
*/
int pat_ref_load(struct pat_ref *ref, struct pattern_expr *expr,
int patflags, int soe, char **err)
{
struct pat_ref_elt *elt;
list_for_each_entry(elt, &ref->head, list) {
if (soe && !pat_ref_push(elt, expr, patflags, err)) {
if (elt->line > 0)
memprintf(err, "%s at line %d of file '%s'",
*err, elt->line, ref->reference);
return 0;
}
}
return 1;
}
/* This function lookup for existing reference <ref> in pattern_head <head>. */
struct pattern_expr *pattern_lookup_expr(struct pattern_head *head, struct pat_ref *ref)
{
@ -1802,6 +1781,105 @@ struct pattern_expr *pattern_new_expr(struct pattern_head *head, struct pat_ref
return expr;
}
/* Reads patterns from a file. If <err_msg> is non-NULL, an error message will
* be returned there on errors and the caller will have to free it.
*
* The file contains one key + value per line. Lines which start with '#' are
* ignored, just like empty lines. Leading tabs/spaces are stripped. The key is
* then the first "word" (series of non-space/tabs characters), and the value is
* what follows this series of space/tab till the end of the line excluding
* trailing spaces/tabs.
*
* Example :
*
* # this is a comment and is ignored
* 62.212.114.60 1wt.eu \n
* <-><-----------><---><----><---->
* | | | | `--- trailing spaces ignored
* | | | `-------- value
* | | `--------------- middle spaces ignored
* | `------------------------ key
* `-------------------------------- leading spaces ignored
*
* Return non-zero in case of succes, otherwise 0.
*/
int pat_ref_read_from_file_smp(struct pat_ref *ref, const char *filename, char **err)
{
FILE *file;
char *c;
int ret = 0;
int line = 0;
char *key_beg;
char *key_end;
char *value_beg;
char *value_end;
file = fopen(filename, "r");
if (!file) {
memprintf(err, "failed to open pattern file <%s>", filename);
return 0;
}
/* now parse all patterns. The file may contain only one pattern
* followed by one value per line. The start spaces, separator spaces
* and and spaces are stripped. Each can contain comment started by '#'
*/
while (fgets(trash.str, trash.size, file) != NULL) {
line++;
c = trash.str;
/* ignore lines beginning with a dash */
if (*c == '#')
continue;
/* strip leading spaces and tabs */
while (*c == ' ' || *c == '\t')
c++;
/* empty lines are ignored too */
if (*c == '\0' || *c == '\r' || *c == '\n')
continue;
/* look for the end of the key */
key_beg = c;
while (*c && *c != ' ' && *c != '\t' && *c != '\n' && *c != '\r')
c++;
key_end = c;
/* strip middle spaces and tabs */
while (*c == ' ' || *c == '\t')
c++;
/* look for the end of the value, it is the end of the line */
value_beg = c;
while (*c && *c != '\n' && *c != '\r')
c++;
value_end = c;
/* trim possibly trailing spaces and tabs */
while (value_end > value_beg && (value_end[-1] == ' ' || value_end[-1] == '\t'))
value_end--;
/* set final \0 and check entries */
*key_end = '\0';
*value_end = '\0';
/* insert values */
if (!pat_ref_append(ref, key_beg, value_beg, line)) {
memprintf(err, "out of memory");
goto out_close;
}
}
/* succes */
ret = 1;
out_close:
fclose(file);
return ret;
}
/* Reads patterns from a file. If <err_msg> is non-NULL, an error message will
* be returned there on errors and the caller will have to free it.
*/
@ -1859,11 +1937,12 @@ int pat_ref_read_from_file(struct pat_ref *ref, const char *filename, char **err
}
int pattern_read_from_file(struct pattern_head *head, unsigned int refflags,
const char *filename, int patflags,
const char *filename, int patflags, int load_smp,
char **err, const char *display)
{
struct pat_ref *ref;
struct pattern_expr *expr;
struct pat_ref_elt *elt;
/* Lookup for the existing reference. */
ref = pat_ref_lookup(filename);
@ -1876,8 +1955,18 @@ int pattern_read_from_file(struct pattern_head *head, unsigned int refflags,
return 0;
}
if (!pat_ref_read_from_file(ref, filename, err))
return 0;
if (load_smp) {
if (!pat_ref_read_from_file_smp(ref, filename, err))
return 0;
}
else {
if (!pat_ref_read_from_file(ref, filename, err))
return 0;
}
}
else {
/* The reference already exists, Merge flags. */
ref->flags |= refflags;
}
/* Now, we can loading patterns from the reference. */
@ -1892,9 +1981,15 @@ int pattern_read_from_file(struct pattern_head *head, unsigned int refflags,
return 0;
}
/* Load reference content in expression. */
if (!pat_ref_load(ref, expr, patflags, 1, err))
return 0;
/* Load reference content in the pattern expression. */
list_for_each_entry(elt, &ref->head, list) {
if (!pat_ref_push(elt, expr, patflags, err)) {
if (elt->line > 0)
memprintf(err, "%s at line %d of file '%s'",
*err, elt->line, filename);
return 0;
}
}
return 1;
}