From a885259e1ffaa6de1d71107d19c815fb7875c86a Mon Sep 17 00:00:00 2001 From: fcolin Date: Fri, 21 Apr 2006 12:13:54 +0000 Subject: Separation du code Regexp dans un module --- src/ivy.c | 290 +++++----------------------------------------------------- src/ivy.h | 2 +- src/ivybind.c | 194 ++++++++++----------------------------- src/ivybind.h | 12 +-- 4 files changed, 79 insertions(+), 419 deletions(-) diff --git a/src/ivy.c b/src/ivy.c index dd8aa04..6502ea8 100644 --- a/src/ivy.c +++ b/src/ivy.c @@ -26,13 +26,6 @@ #include #include -#ifndef USE_PCRE_REGEX -#include -#else -#define OVECSIZE 60 /* must be multiple of 3, for regexp return */ -#include -#endif - #include #include "ivychannel.h" @@ -40,6 +33,7 @@ #include "list.h" #include "ivybuffer.h" #include "ivydebug.h" +#include "ivybind.h" #include "ivy.h" #define VERSION 3 @@ -86,12 +80,7 @@ struct _msg_snd { /* requete de reception d'un client */ MsgSndPtr next; int id; char *str_regexp; /* la regexp sous forme inhumaine */ -#ifndef USE_PCRE_REGEX - regex_t regexp; /* la regexp sous forme machine */ -#else - pcre *regexp; - pcre_extra *inspect; -#endif + IvyBinding binding; /* la regexp sous forme machine */ }; struct _clnt_lst { @@ -116,16 +105,6 @@ static Client broadcast; static const char *ApplicationName = 0; -/* classes de messages emis par l'application utilise pour le filtrage */ -static int messages_classes_count = 0; -static const char **messages_classes = 0; -/* regexp d'extraction du mot clef des regexp client pour le filtrage des regexp , ca va c'est clair ??? */ -#ifndef USE_PCRE_REGEX - regex_t token_extract; -#else - pcre *token_extract; - pcre_extra *token_inspect; -#endif /* callback appele sur reception d'un message direct */ static MsgDirectCallback direct_callback = 0; @@ -194,24 +173,17 @@ static void IvyCleanup() SocketClose( broadcast ); } -#ifdef USE_PCRE_REGEX -static int -MsgCall (const char *message, MsgSndPtr msg, IvyClientPtr client) +static int MsgCall (const char *message, MsgSndPtr msg, IvyClientPtr client) { int waiting = 0; static IvyBuffer buffer = { NULL, 0, 0 }; /* Use satic mem to eliminate multiple call to malloc /free */ int err; - int ovector[OVECSIZE]; int index; - int rc=pcre_exec( - msg->regexp, - msg->inspect, - message, - strlen(message), - 0, /* debut */ - 0, /* no other regexp option */ - ovector, - OVECSIZE); + int arglen; + const char *arg; + + int rc= IvyBindingExec( msg->binding, message ); + if (rc<1) return 0; /* no match */ TRACE( "Sending message id=%d '%s'\n",msg->id,message); @@ -226,8 +198,8 @@ MsgCall (const char *message, MsgSndPtr msg, IvyClientPtr client) index=1; while ( indexbinding, message, index, &arglen, & arg ); + err = make_message_var( &buffer, "%.*s" ARG_END , arglen, arg ); ++index; } err = make_message_var( &buffer, "\n"); @@ -237,65 +209,7 @@ MsgCall (const char *message, MsgSndPtr msg, IvyClientPtr client) return 1; } -#else /* we don't USE_PCRE_REGEX */ -static int -MsgCall (const char *message, MsgSndPtr msg, IvyClientPtr client) -{ - int waiting = 0; - static IvyBuffer buffer = { NULL, 0, 0 }; /* Use satic mem to eliminate multiple call to malloc /free */ - int err; - - regmatch_t match[MAX_MATCHING_ARGS+1]; -#ifdef GNU_REGEXP - regmatch_t* p; -#else - unsigned int i; -#endif - memset( match, -1, sizeof(match )); /* work around bug !!!*/ - if (regexec (&msg->regexp, message, MAX_MATCHING_ARGS, match, 0) != 0) - return 0; - - TRACE( "Sending message id=%d '%s'\n",msg->id,message); - - // il faut essayer d'envoyer le message en une seule fois sur la socket - // pour eviter au maximun de passer dans le select plusieur fois par message du protocole Ivy - // pour eviter la latence ( PB detecte par ivyperf ping roudtrip ) - buffer.offset = 0; - err = make_message_var( &buffer, "%d %d" ARG_START ,Msg, msg->id); - - TRACE( "Send matching args count %ld\n",msg->regexp.re_nsub); - -#ifdef GNU_REGEXP - p = &match[1]; - while ( p->rm_so != -1 ) { - err = make_message_var( &buffer, "%.*s" ARG_END , p->rm_eo - p->rm_so, - message + p->rm_so); - ++p; - } -#else - for ( i = 1; i < msg->regexp.re_nsub+1; i ++ ) { - if ( match[i].rm_so != -1 ) { - - TRACE("Send matching arg%d %d %d\n",i,match[i].rm_so , match[i].rm_eo); - TRACE ("Send matching arg%d %.*s\n",i,(int)(match[i].rm_eo - match[i].rm_so), - message + match[i].rm_so); - - buffer.offset += make_message_var( &buffer, "%.*s" ARG_END ,(int)(match[i].rm_eo - match[i].rm_so), - message + match[i].rm_so); - } else { - buffer.offset += make_message_var( &buffer, ARG_END ); - - TRACE( "Send matching arg%d VIDE\n",i); - } - } -#endif - err = make_message_var( &buffer,"\n"); - SocketSendRaw(client->client, buffer.data , buffer.offset); - return 1; -} -#endif /* USE_PCRE_REGEX */ - static int ClientCall (IvyClientPtr clnt, const char *message) { @@ -307,91 +221,6 @@ ClientCall (IvyClientPtr clnt, const char *message) } return match_count; } -#ifdef USE_PCRE_REGEX -static int ExtractTokenRegexp (const char *exp, char *buffer, int buffersize) -{ -#define TOKEN_OVECSIZE 3*2 /* must be multiple of 3, for regexp return */ - int ovector[TOKEN_OVECSIZE]; - int rc=pcre_exec( - token_extract, - token_inspect, - exp, - strlen(exp), - 0, /* debut */ - 0, /* no other regexp option */ - ovector, - TOKEN_OVECSIZE); - /*if (rc<1) return rc; *//* no match */ - - return pcre_copy_substring(exp, ovector, rc, 1, buffer, buffersize); - - -} - -#else /* we don't USE_PCRE_REGEX */ -static int ExtractTokenRegexp (const char *exp, char *buffer, int buffersize) -{ - int err; - - regmatch_t match[MAX_MATCHING_ARGS+1]; -#ifdef GNU_REGEXP - regmatch_t* p; -#else - unsigned int i; -#endif - memset( match, -1, sizeof(match )); /* work around bug !!!*/ - if (regexec (&msg->regexp, message, MAX_MATCHING_ARGS, match, 0) != 0) - return 0; - -#ifdef GNU_REGEXP - p = &match[1]; - while ( p->rm_so != -1 ) { - err = make_message_var( &buffer, "%.*s" ARG_END , p->rm_eo - p->rm_so, - message + p->rm_so); - ++p; - } -#else - for ( i = 1; i < msg->regexp.re_nsub+1; i ++ ) { - if ( match[i].rm_so != -1 ) { - - TRACE ("Send matching arg%d %d %d\n",i,match[i].rm_so , match[i].rm_eo); - TRACE ("Send matching arg%d %.*s\n",i,(int)(match[i].rm_eo - match[i].rm_so), - message + match[i].rm_so); - - buffer.offset += make_message_var( &buffer, "%.*s" ARG_END ,(int)(match[i].rm_eo - match[i].rm_so), - message + match[i].rm_so); - } else { - buffer.offset += make_message_var( &buffer, ARG_END ); - } - } -#endif - - return 1; -} -#endif /* USE_PCRE_REGEX */ - -static int CheckRegexp(char *exp) -{ - int i; - int err; - int regexp_ok = 1; /* accepte tout par default */ - char token[200]; - - if ( *exp =='^' && messages_classes_count !=0 ) - { - regexp_ok = 0; - - /* extract token */ - err = ExtractTokenRegexp ( exp, token, sizeof(token)); - if ( err < 1 ) return 1; - for ( i = 0 ; i < messages_classes_count; i++ ) - { - if (strncmp( messages_classes[i], token, strlen( token )) == 0) - return 1; - } - } - return regexp_ok; -} static int CheckConnected( IvyClientPtr clnt ) { @@ -428,14 +257,10 @@ static void Receive( Client client, void *data, char *line ) char *argv[MAX_MATCHING_ARGS]; char *arg; int kind_of_msg = Bye; -#ifndef USE_PCRE_REGEX - regex_t regexp; - int reg; -#else - pcre *regexp; + IvyBinding bind; + const char *errbuf; int erroffset; -#endif err = sscanf( line ,"%d %d", &kind_of_msg, &id ); arg = strstr( line , ARG_START ); @@ -465,7 +290,7 @@ static void Receive( Client client, void *data, char *line ) TRACE("Regexp id=%d exp='%s'\n", id, arg); - if ( !CheckRegexp( arg ) ) + if ( !IvyBindingFilter( arg ) ) { TRACE("Warning: regexp '%s' illegal, removing from %s\n",arg,ApplicationName); @@ -476,41 +301,14 @@ static void Receive( Client client, void *data, char *line ) } return; } -#ifndef USE_PCRE_REGEX - reg = regcomp(®exp, arg, REGCOMP_OPT|REG_EXTENDED); - if ( reg == 0 ) - { - IVY_LIST_ADD_START( clnt->msg_send, snd ) - snd->id = id; - snd->str_regexp = strdup( arg ); - snd->regexp = regexp; - if ( application_bind_callback ) - { - (*application_bind_callback)( clnt, application_bind_data, id, snd->str_regexp, IvyAddBind ); - } - IVY_LIST_ADD_END( clnt->msg_send, snd ) - } - else - { - char errbuf[4096]; - regerror (reg, ®exp, errbuf, 4096); - printf("Error compiling '%s', %s\n", arg, errbuf); - MsgSendTo( client, Error, reg, errbuf ); - } -#else - regexp = pcre_compile(arg, PCRE_OPT,&errbuf,&erroffset,NULL); - if ( regexp != NULL ) + + bind = IvyBindingCompile( arg ); + if ( bind != NULL ) { IVY_LIST_ADD_START( clnt->msg_send, snd ) snd->id = id; snd->str_regexp = strdup( arg ); - snd->regexp = regexp; - snd->inspect = pcre_study(regexp,0,&errbuf); - if (errbuf!=NULL) - { - printf("Error studying %s, message: %s\n",arg,errbuf); - } - + snd->binding = bind; if ( application_bind_callback ) { (*application_bind_callback)( clnt, application_bind_data, id, snd->str_regexp, IvyAddBind ); @@ -520,10 +318,11 @@ static void Receive( Client client, void *data, char *line ) } else { + IvyBindingGetCompileError( & erroffset, & errbuf ); printf("Error compiling '%s', %s\n", arg, errbuf); MsgSendTo( client, Error, erroffset, errbuf ); } -#endif + break; case DelRegexp: @@ -536,13 +335,7 @@ static void Receive( Client client, void *data, char *line ) { (*application_bind_callback)( clnt, application_bind_data, id, snd->str_regexp, IvyRemoveBind ); } -#ifndef USE_PCRE_REGEX - free( snd->str_regexp ); -#else - free( snd->str_regexp ); - if (snd->inspect!=NULL) pcre_free(snd->inspect); - pcre_free(snd->regexp); -#endif + IvyBindingFree( snd->binding ); IVY_LIST_REMOVE( clnt->msg_send, snd ); } break; @@ -749,52 +542,15 @@ void IvyInit (const char *appname, const char *ready, ready_message = ready; } -void IvySetBindCallback(IvyBindCallback bind_callback, void *bind_data - ) +void IvySetBindCallback( IvyBindCallback bind_callback, void *bind_data ) { application_bind_callback=bind_callback; application_bind_data=bind_data; } -void IvyClasses( int argc, const char **argv) +void IvySetFilter( int argc, const char **argv) { - -#ifndef USE_PCRE_REGEX - int reg; -#else - const char *errbuf; - int erroffset; -#endif - messages_classes_count = argc; - messages_classes = argv; - - /* compile the token extraction regexp */ -#ifndef USE_PCRE_REGEX - reg = regcomp(&token_extract, "^\\^([a-zA-Z_0-9-]+).*", REGCOMP_OPT|REG_EXTENDED); - if ( reg == 0 ) - { - } - else - { - char errbuf[4096]; - regerror (reg, ®exp, errbuf, 4096); - printf("Error compiling Token Extract regexp: %s\n", errbuf); - } -#else - token_extract = pcre_compile("^\\^([a-zA-Z_0-9-]+).*", PCRE_OPT,&errbuf,&erroffset,NULL); - if ( token_extract != NULL ) - { - token_inspect = pcre_study(token_extract,0,&errbuf); - if (errbuf!=NULL) - { - printf("Error studying Token Extract regexp: %s\n",errbuf); - } - } - else - { - printf("Error compiling Token Extract regexp: %s\n", errbuf); - } -#endif + IvyBindingSetFilter( argc, argv ); } void IvyStart (const char* bus) diff --git a/src/ivy.h b/src/ivy.h index 1056cd1..e892070 100644 --- a/src/ivy.h +++ b/src/ivy.h @@ -54,7 +54,7 @@ typedef void (*MsgDirectCallback)( IvyClientPtr app, void *user_data, int id, ch typedef struct _msg_rcv *MsgRcvPtr; /* filtrage des regexps */ -void IvyClasses( int argc, const char **argv); +void IvySetFilter( int argc, const char **argv); void IvyInit( const char *AppName, /* nom de l'application */ diff --git a/src/ivybind.c b/src/ivybind.c index 237ee78..5e0ffe0 100644 --- a/src/ivybind.c +++ b/src/ivybind.c @@ -37,7 +37,6 @@ #endif #include "list.h" -#include "hash.h" #include "ivybind.h" static int err_offset; @@ -49,10 +48,7 @@ static int err_offset; #endif struct _binding { - IvyBindingType type; - const char *msgname; /* msg tag name first word of message */ - char **msgargs; /* list of msg argument name */ - IvyArgument args; /* result */ + const char *expression; /* regexp*/ #ifdef USE_PCRE_REGEX pcre *regexp; pcre_extra *inspect; @@ -64,45 +60,13 @@ struct _binding { #endif }; - /* classes de messages emis par l'application utilise pour le filtrage */ static int messages_classes_count = 0; static const char **messages_classes = 0; +/* regexp d'extraction du mot clef des regexp client pour le filtrage des regexp , ca va c'est clair ??? */ +static IvyBinding token_extract; - -/* stokage du message parse avant l'execution des regles de binding simple */ -static char *current_msg = NULL; -static char *msgtag; -static HASHTABLE msg_args_values = NULL; - -static IvyBinding IvyBindingCompileSimple( IvyBindingType typ, const char * expression ) -{ - int nb_arg= 0; - char *argname; - char **argv; - char *expr; - IvyBinding bind=0; - - expr = strdup( expression ); //Allocate a new buffer of separated token - /* count nb args */ - argname = expr; - while ( *argname ) - { - if ( *argname++ == ' ' ) nb_arg++; - } - - bind = (IvyBinding)malloc( sizeof( struct _binding )); - memset( bind, 0, sizeof(*bind ) ); - bind->type = IvyBindSimple; - bind->msgname = strtok( expr, " "); - bind->msgargs = malloc ( sizeof( char* ) * ( nb_arg + 1) ); - argv = bind->msgargs; - while ( (argname = strtok( NULL, " ")) ) - *argv++ = argname; - *argv++ = argname; /* end with NULL */ - return bind; -} -static IvyBinding IvyBindingCompileRegexp( IvyBindingType typ, const char * expression ) +IvyBinding IvyBindingCompile( const char * expression ) { IvyBinding bind=0; #ifdef USE_PCRE_REGEX @@ -111,9 +75,13 @@ static IvyBinding IvyBindingCompileRegexp( IvyBindingType typ, const char * expr if ( regexp != NULL ) { bind = (IvyBinding)malloc( sizeof( struct _binding )); + if ( ! bind ) + { + perror( "IvyBindingCompile malloc error: "); + exit(-1); + } memset( bind, 0, sizeof(*bind ) ); bind->regexp = regexp; - bind->type = IvyBindRegexp; bind->inspect = pcre_study(regexp,0,&err_buf); if (err_buf!=NULL) { @@ -144,13 +112,7 @@ static IvyBinding IvyBindingCompileRegexp( IvyBindingType typ, const char * expr #endif return bind; } -IvyBinding IvyBindingCompile( IvyBindingType typ, const char * expression ) -{ - if ( typ == IvyBindRegexp ) - return IvyBindingCompileRegexp( typ, expression); - else - return IvyBindingCompileSimple( typ, expression); -} + void IvyBindingGetCompileError( int *offset, const char **errmessage ) { *offset = err_offset; @@ -159,17 +121,15 @@ void IvyBindingGetCompileError( int *offset, const char **errmessage ) void IvyBindingFree( IvyBinding bind ) { #ifdef USE_PCRE_REGEX - if (bind->inspect!=NULL) pcre_free(bind->inspect); + if (bind->inspect!=NULL) + pcre_free(bind->inspect); pcre_free(bind->regexp); #else + free( bind->regexp ); #endif - if (bind->msgname) - free ( bind->msgname ); - if (bind->msgargs) - free ( bind->msgargs ); free ( bind ); } -int IvyBindingExecRegexp( IvyBinding bind, const char * message ) +int IvyBindingExec( IvyBinding bind, const char * message ) { int nb_match = 0; #ifdef USE_PCRE_REGEX @@ -200,123 +160,69 @@ int IvyBindingExecRegexp( IvyBinding bind, const char * message ) #endif return nb_match; } -int IvyBindingExecSimple( IvyBinding bind, const char * message ) -{ - char **msg_args; - if ( strcmp( bind->msgname, msgtag ) != 0 ) - return 0; - msg_args = bind->msgargs; - bind->args = IvyArgumentNew( 0,NULL ); - while( *msg_args ) - { - char *value; - value = hash_lookup(msg_args_values, (HASHKEYTYPE)*msg_args++); - if ( !value ) value = ""; /* TODO should we report matching ??? */ - IvyAddChildValue( bind->args, strlen( value ), value); - } - return 1; -} -int IvyBindingExec( IvyBinding bind, const char * message ) -{ - if ( bind->type == IvyBindRegexp ) - return IvyBindingExecRegexp( bind, message); - else - return IvyBindingExecSimple( bind, message); -} -static IvyArgument IvyBindingMatchSimple( IvyBinding bind, const char *message) -{ - return bind->args; -} -static IvyArgument IvyBindingMatchRegexp( IvyBinding bind, const char *message) + +void IvyBindingMatch( IvyBinding bind, const char *message, int argnum, int *arglen, const char **arg) { - int index=1;// firts arg wall string ??? - int arglen; - const void* arg; - IvyArgument args; - args = IvyArgumentNew( 0,NULL ); #ifdef USE_PCRE_REGEX - while ( indexnb_match ) { - arglen = bind->ovector[2*index+1]- bind->ovector[2*index]; - arg = message + bind->ovector[2*index]; - index++; + + *arglen = bind->ovector[2*argnum+1]- bind->ovector[2*argnum]; + *arg = message + bind->ovector[2*argnum]; #else /* we don't USE_PCRE_REGEX */ - for ( index = 1; index < MAX_MSG_FIELDS; index++ ) - { + regmatch_t* p; - p = &bind->match[index]; + p = &bind->match[argnum+1]; if ( p->rm_so != -1 ) { - arglen = p->rm_eo - p->rm_so; - arg = message + p->rm_so; + *arglen = p->rm_eo - p->rm_so; + *arg = message + p->rm_so; } else { // ARG VIDE - arglen = 0; - arg = NULL; + *arglen = 0; + *arg = NULL; } #endif // USE_PCRE_REGEX - IvyAddChildValue( args, arglen, arg ); - } - return args; -} -IvyArgument IvyBindingMatch( IvyBinding bind, const char *message) -{ - if ( bind->type == IvyBindRegexp ) - return IvyBindingMatchRegexp( bind, message); - else - return IvyBindingMatchSimple( bind, message); + } //filter Expression Bind void IvyBindingSetFilter( int argc, const char **argv) { + const char *errbuf; + int erroffset; + messages_classes_count = argc; messages_classes = argv; -} -void IvyBindingParseMessage( const char *msg ) -{ - char *arg; - if ( current_msg ) free( current_msg ); - if ( msg_args_values ) hash_destroy( msg_args_values ); - current_msg = strdup( msg ); - msg_args_values = hash_create( 256, TRUE ); - msgtag = strtok( current_msg, " " ); - while( (arg = strtok( NULL, " =" )) ) + /* compile the token extraction regexp */ + + token_extract = IvyBindingCompile("^\\^([a-zA-Z_0-9-]+).*"); + if ( !token_extract ) { - char *val = strtok( NULL, " ="); - if ( arg && val ) - hash_addstring( msg_args_values, arg, val ); + IvyBindingGetCompileError( & erroffset, & errbuf ); + printf("Error compiling Token Extract regexp: %s\n", errbuf); } } -int IvyBindingFilter(IvyBindingType typ, int len, const char *exp) + +int IvyBindingFilter(const char *expression) { - /* TODO check args limits !!!*/ int i; - /* accepte tout par default */ - int regexp_ok = 1; - // TODO simplify test 3 conditions - if ( typ == IvyBindRegexp ) - { - if ( *exp =='^' && messages_classes_count !=0 ) - { - regexp_ok = 0; - for ( i = 0 ; i < messages_classes_count; i++ ) - { - if (strncmp( messages_classes[i], exp+1, strlen( messages_classes[i] )) == 0) - return 1; - } - } - } - else - { - if ( messages_classes_count !=0 ) + int err; + int regexp_ok = 1; /* accepte tout par default */ + int tokenlen; + const char *token; + + if ( *expression =='^' && messages_classes_count !=0 ) { regexp_ok = 0; + + /* extract token */ + err = IvyBindingExec( token_extract, expression ); + if ( err < 1 ) return 1; + IvyBindingMatch( token_extract, expression , 0, &tokenlen, &token ); for ( i = 0 ; i < messages_classes_count; i++ ) { - if (strncmp( messages_classes[i], exp, strlen( messages_classes[i] )) == 0) + if (strncmp( messages_classes[i], token, tokenlen ) == 0) return 1; } } - } return regexp_ok; -} \ No newline at end of file +} diff --git a/src/ivybind.h b/src/ivybind.h index 9846d3f..40f6932 100644 --- a/src/ivybind.h +++ b/src/ivybind.h @@ -14,18 +14,16 @@ * Please refer to file version.h for the * copyright notice regarding this software */ -#include "ivyargument.h" - /* Module de gestion de la syntaxe des messages Ivy */ typedef struct _binding *IvyBinding; -typedef enum { IvyBindRegexp, IvyBindSimple } IvyBindingType; -void IvyBindingParseMessage( const char *msg ); void IvyBindingSetFilter( int argc, const char ** argv ); -int IvyBindingFilter( IvyBindingType typ, int len, const char *exp ); -IvyBinding IvyBindingCompile( IvyBindingType typ, const char * expression ); +int IvyBindingFilter( const char *expression ); + +IvyBinding IvyBindingCompile( const char *expression ); void IvyBindingGetCompileError( int *erroffset, const char **errmessage ); void IvyBindingFree( IvyBinding bind ); + int IvyBindingExec( IvyBinding bind, const char * message ); -IvyArgument IvyBindingMatch( IvyBinding bind, const char *message ); +void IvyBindingMatch( IvyBinding bind, const char *message, int argnum, int *arglen, const char **arg ); -- cgit v1.1