From 3f0c36f57af40e853ece2c5889a05120129f649b Mon Sep 17 00:00:00 2001 From: Alexandre Quessy Date: Wed, 19 Jul 2006 00:27:57 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r5374, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/aalex/; revision=5375 --- pcre.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 pcre.c (limited to 'pcre.c') diff --git a/pcre.c b/pcre.c new file mode 100644 index 0000000..7477938 --- /dev/null +++ b/pcre.c @@ -0,0 +1,172 @@ +/** + * The [pcre] class in Pure Data is an external to verify that a subject + * matches a Perl-compatible regular expression mask. + * + * http://alexandre.quessy.net + * + * @author Alexandre Quessy + * @c GNU General Public License 2006 + */ + +#include "m_pd.h" +#include +#include +#include + +#define CAPTUREVECTORSIZE 30 /* multiple of 3 */ +#define pdpcre_ERROR_PREFIX "[pdpcre]: " +#define pdpcre_FALSE_MASK "xxxxxxxxxxxxxxxxxxxxxx" +#define pdpcre_DECIMAL_PRECISION_SIZE_T 4 + +/** variables of the pd object */ +typedef struct pdpcre { + t_object x_ob; /* contient inlets et outlets */ + t_outlet *x_outlet; + pcre *regex; /* mask */ +} t_pdpcre; + +/** functions */ +char *_str_replace(const char search, const char replace, const char *subject); +int _isMatching(t_pdpcre *x, char *text); +void _compile_pattern(t_pdpcre *x, const char *pattern); + + +/** left inlet: subject */ +void pdpcre_symbol0(t_pdpcre *x, t_symbol *arg) { + int isOk =_isMatching(x, arg->s_name); + outlet_float(x->x_outlet, isOk); +} + +/* left inlet: subject (when a float) +void pdpcre_float0(t_pdpcre *x, t_floatarg arg) { + char *str_float = sprintf("%f0", arg); + int isOk =_isMatching(x, str_float); + outlet_float(x->x_outlet, isOk); +} +*/ + + +/** right inlet : mask */ +void pdpcre_symbol1(t_pdpcre *x, t_symbol *arg) { + _compile_pattern(x, arg->s_name); +} + +/* right inlet +void pdpcre_float1(t_pdpcre *x, t_floatarg arg) { + char *str_float = sprintf("%f0", arg); + _compile_pattern(x, str_float); +} +*/ +t_class *pdpcre_class; + +/** constructor */ +void *pdpcre_new(t_symbol *selector, int argc, t_atom *argv) { + int is_valid = 0; + t_pdpcre *x = (t_pdpcre *) pd_new(pdpcre_class); + + /* set the mask */ + if (argc < 1) { + post("%s No mask given as argument. Please supply one as message.\n", pdpcre_ERROR_PREFIX); + } else { + if (argv[0].a_type == A_SYMBOL) { + t_symbol *tmp = atom_getsymbol(&argv[0]); + _compile_pattern(x, tmp->s_name); + is_valid = 1; + } else { + post("%s Argument should be a symbol\n", pdpcre_ERROR_PREFIX); + } + } + if (is_valid == 0) { + _compile_pattern(x, pdpcre_FALSE_MASK); + } + /* add inlets */ + inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("symbol"), gensym("mask")); /* selecteur, renomme mask */ + + /* add outlet */ + x->x_outlet = outlet_new(&x->x_ob, gensym("float")); + return (void *)x; +} + +/** setup */ +void pcre_setup(void) { + pdpcre_class = class_new(gensym("pcre"), (t_newmethod) pdpcre_new, 0, sizeof(t_pdpcre), 0, A_GIMME, 0); + class_addmethod(pdpcre_class, (t_method) pdpcre_symbol0, gensym("symbol"), A_SYMBOL, 0); + class_addmethod(pdpcre_class, (t_method) pdpcre_symbol1, gensym("mask"), A_SYMBOL, 0); +} + + + + +/* ############################### functions ###################### */ + + + + +/** clone of the PHP function */ +char *_str_replace(const char search, const char replace, const char *subject) { + int i, len; + char *result = strdup(subject); + len = strlen(result); + for (i = 0; i <= len; i++) { + if(result[i] == search) { + result[i] = replace; + } + } + return result; +} + +/** + * returns 1 if pdpcre, 0 if not + * TODO use stdbool.h, I think + */ +int _isMatching(t_pdpcre *x, char *text) { /* 2nd is const */ + int capturevector[CAPTUREVECTORSIZE]; + int rc; + int i; + int result = 0; + + rc = pcre_exec(x->regex, NULL, text, (int) strlen(text), 0, 0, capturevector, CAPTUREVECTORSIZE); + + if (rc < 0) { + result = 0; + } else { + result = 1; + } + + /* ok, a partir d'ici c'est different de l'autre exemple, sauf qu'on avait mis des parentheses dans le pattern */ + if (rc == 0) { + rc = CAPTUREVECTORSIZE / 3; + post("ovector only has room for %d captured substrings\n", rc - 1); + } + for (i = 0; i < rc; i++) { + char *substring_start = text + capturevector[2 * i]; /* ovector */ + int substring_length = capturevector[2 * i + 1] - capturevector[2 * i]; + //post("%2d matching: %.*s", i, substring_length, substring_start); + } + /* I think that from here I should clean up my memory */ + + return result; +} + +/* ############## begin class pdpcre ####################### */ + +/** + * private method to set and compile the mask + * TODO : use pcre_malloc() and pcre_free() + */ +void _compile_pattern(t_pdpcre *x, const char *pattern) { + pcre *regex; + const char *regex_error; + int erroroffset; + char *mask = _str_replace('`', '\\', pattern); + + regex = pcre_compile(mask, 0, ®ex_error, &erroroffset, NULL); + if (regex == NULL) { + post("%s Compilation failed at offset %d : %s", pdpcre_ERROR_PREFIX, erroroffset, regex_error); + regex = pcre_compile(pdpcre_FALSE_MASK, 0, ®ex_error, &erroroffset, NULL); /* will always return false if invalid pattern */ + } else { + post("%s New PCRE mask: %s", pdpcre_ERROR_PREFIX, mask); + } + /* free(x->regex); */ + x->regex = regex; +} -- cgit v1.2.1