diff --git a/include/regexp.cpp b/include/regexp.cpp index e1902d8f8..0f1e11255 100755 --- a/include/regexp.cpp +++ b/include/regexp.cpp @@ -1,6 +1,7 @@ #ifndef __REGEXP_H #include #endif +#include // codici di ritorno della matche() #define regexp_MATCH_PATTERN (6) // pattern non valido @@ -24,173 +25,173 @@ HIDDEN bool is_pattern(const char *pat); // ritorna TRUE se la stringa HIDDEN bool is_valid_pattern(const char *pat, int *err= NULL); // ritorna TRUE se la stringa è un pattern valido, indica un codice di ritorno della classe regexp_PATTERN nel secondo parametro HIDDEN bool is_pattern(const char *p) { - while (*p) { - switch (*p++) { - case '?': - case '*': - case '[': - case '\\': - return TRUE; - } - } - return FALSE; + while (*p) { + switch (*p++) { + case '?': + case '*': + case '[': + case '\\': + return TRUE; + } + } + return FALSE; } HIDDEN bool is_valid_pattern(const char *p, int *error_type) { - if (error_type != NULL) *error_type= regexp_PATTERN_VALID; // inizializzazione del tipo d'errore - while (*p) { // ciclo all'interno del pattern fino a fine stringa - switch(*p) { // determinazione del tipo di wild card nel pattern - case '\\': // controllo dell'escape, non può essere a fine pattern - if (!*++p) { - if (error_type != NULL) *error_type= regexp_PATTERN_ESC; - return FALSE; - } - p++; - break; - case '[': // controllo della costruzione del costrutto [..] - p++; - if (*p == ']') { // se il prossimo carattere è ']' il costrutto è vuoto - if (error_type != NULL) *error_type= regexp_PATTERN_EMPTY; - return FALSE; - } - if (!*p) { // se si è a fine stringa il costrutto non è chiuso - if (error_type != NULL) *error_type= regexp_PATTERN_CLOSE; - return FALSE; - } - while (*p != ']') { // ciclo fino a fine costrutto [..] - if (*p == '\\') { // controllo per gli escape - p++; - if (!*p++) { // controllo che l'escape non sia a fine pattern - if (error_type != NULL) *error_type= regexp_PATTERN_ESC; - return FALSE; - } - } else p++; - if (!*p) { // se si è a fine stringa il costrutto non è chiuso - if (error_type != NULL) *error_type= regexp_PATTERN_CLOSE; - return FALSE; - } - if (*p == '-') { // controllo di un eventuale range - if (!*++p || *p == ']') { // deve esistere una fine del range - if (error_type != NULL) *error_type= regexp_PATTERN_RANGE; - return FALSE; - } else { - if (*p == '\\') p++; // controllo degli escape - if (!*p++) { // controllo che l'escape non sia a fine pattern - if (error_type != NULL) *error_type= regexp_PATTERN_ESC; - return FALSE; - } - } - } - } - break; - case '*': // tutti gli altri caratteri sono elementi validi del pattern - case '?': - default: - p++; // caratteri normali - break; - } - } - return TRUE; + if (error_type != NULL) *error_type= regexp_PATTERN_VALID; // inizializzazione del tipo d'errore + while (*p) { // ciclo all'interno del pattern fino a fine stringa + switch(*p) { // determinazione del tipo di wild card nel pattern + case '\\': // controllo dell'escape, non può essere a fine pattern + if (!*++p) { + if (error_type != NULL) *error_type= regexp_PATTERN_ESC; + return FALSE; + } + p++; + break; + case '[': // controllo della costruzione del costrutto [..] + p++; + if (*p == ']') { // se il prossimo carattere è ']' il costrutto è vuoto + if (error_type != NULL) *error_type= regexp_PATTERN_EMPTY; + return FALSE; + } + if (!*p) { // se si è a fine stringa il costrutto non è chiuso + if (error_type != NULL) *error_type= regexp_PATTERN_CLOSE; + return FALSE; + } + while (*p != ']') { // ciclo fino a fine costrutto [..] + if (*p == '\\') { // controllo per gli escape + p++; + if (!*p++) { // controllo che l'escape non sia a fine pattern + if (error_type != NULL) *error_type= regexp_PATTERN_ESC; + return FALSE; + } + } else p++; + if (!*p) { // se si è a fine stringa il costrutto non è chiuso + if (error_type != NULL) *error_type= regexp_PATTERN_CLOSE; + return FALSE; + } + if (*p == '-') { // controllo di un eventuale range + if (!*++p || *p == ']') { // deve esistere una fine del range + if (error_type != NULL) *error_type= regexp_PATTERN_RANGE; + return FALSE; + } else { + if (*p == '\\') p++; // controllo degli escape + if (!*p++) { // controllo che l'escape non sia a fine pattern + if (error_type != NULL) *error_type= regexp_PATTERN_ESC; + return FALSE; + } + } + } + } + break; + case '*': // tutti gli altri caratteri sono elementi validi del pattern + case '?': + default: + p++; // caratteri normali + break; + } + } + return TRUE; } HIDDEN int matche_after_star(const char *p, const char *t) { - int match= 0; - while (*p == '?' || *p == '*') { // salto degli eventuali '*' e '?' - if (*p == '?') // salto di un carattere per ciascun '?' - if (!*t++) return regexp_MATCH_ABORT; // se la stringa termina qui non c'è coincidenza - p++; // posizionamento sul prossimo carattere del pattern - } - if (!*p) return regexp_MATCH_VALID; //se il pattern è concluso c'è coincidenza - int nextp= *p; // prelevamento del prossimo carattere, normale o '[' - if (nextp == '\\') { - nextp= p[1]; - if (!nextp) return regexp_MATCH_PATTERN; // se il pattern termina qui non è valido - } - do { // ciclo fino a conclusione di stringa o pattern - if (nextp == *t || nextp == '[') match= matche(p, t); // è necessario che il carattere corrente del testo coincida con il carattere corrente del pattern, oppure che il pattern abbia un inizio di costrutto [..] - if (!*t++) match= regexp_MATCH_ABORT; // se la stringa termina qui non c'è coincidenza - } while (match != regexp_MATCH_VALID && match != regexp_MATCH_ABORT && match != regexp_MATCH_PATTERN); - return match; // ritorno del risultato + int match= 0; + while (*p == '?' || *p == '*') { // salto degli eventuali '*' e '?' + if (*p == '?') // salto di un carattere per ciascun '?' + if (!*t++) return regexp_MATCH_ABORT; // se la stringa termina qui non c'è coincidenza + p++; // posizionamento sul prossimo carattere del pattern + } + if (!*p) return regexp_MATCH_VALID; //se il pattern è concluso c'è coincidenza + int nextp= *p; // prelevamento del prossimo carattere, normale o '[' + if (nextp == '\\') { + nextp= p[1]; + if (!nextp) return regexp_MATCH_PATTERN; // se il pattern termina qui non è valido + } + do { // ciclo fino a conclusione di stringa o pattern + if (nextp == *t || nextp == '[') match= matche(p, t); // è necessario che il carattere corrente del testo coincida con il carattere corrente del pattern, oppure che il pattern abbia un inizio di costrutto [..] + if (!*t++) match= regexp_MATCH_ABORT; // se la stringa termina qui non c'è coincidenza + } while (match != regexp_MATCH_VALID && match != regexp_MATCH_ABORT && match != regexp_MATCH_PATTERN); + return match; // ritorno del risultato } HIDDEN int matche(const char *p, const char *t) { - for (; *p; p++, t++) { - if (!*t) // se si è alla fine della stringa, il confronto è concluso - return (*p == '*' && *++p == '\0') ? regexp_MATCH_VALID : regexp_MATCH_ABORT; - switch (*p) { // determina il tipo di wild card del pattern - case '?': // carattere singolo, qualunque carattere coincide - break; - case '*': // sottostringa, coincide qualunque sequenza di caratteri - return matche_after_star (p, t); - case '[': { // costrutto [..], controllo di coincidenza per inclusione o esclusione su un solo carattere - p++; // posizionamento all'inizio del range - bool invert= FALSE; // controllo di inclusione o esclusione del costrutto - if (*p == '!' || *p == '^') { - invert= TRUE; - p++; - } - if (*p == ']') // se si è su una chiusura di costrutto il pattern non è valido - return regexp_MATCH_PATTERN; - bool member_match= FALSE; - bool loop= TRUE; - while (loop) { - char range_start, range_end; // inizio e fine del range corrente - if (*p == ']') { // se si è alla fine del costrutto il ciclo si conclude - loop= FALSE; - continue; - } - if (*p == '\\') // controllo di coincidenza su un metacarattere, dopo un escape - range_start= range_end= *++p; - else - range_start= range_end= *p; - if (!*p) return regexp_MATCH_PATTERN; // se il pattern termina non è valido - if (*++p == '-') { // controllo del segno di sottoinsieme - range_end= *++p; // impostazione della fine del range - if (range_end == '\0' || range_end == ']') return regexp_MATCH_PATTERN; // se il costrutto [..] o il pattern terminano qui allora il pattern non è valido - if (range_end == '\\') { // la fine del range è un metacarattere - range_end= *++p; - if (!range_end) return regexp_MATCH_PATTERN; // se il pattern termina non è valido - } - p++; // posizionamento oltre il range - } - if (range_start < range_end) { // confronto del carattere corrente con il costrutto, controllo della sequenzialità degli estremi del range - if (*t >= range_start && *t <= range_end) { - member_match= TRUE; - loop= FALSE; - } - } else { - if (*t >= range_end && *t <= range_start) { - member_match= TRUE; - loop= FALSE; - } - } - } - if ((invert && member_match) || !(invert || member_match)) // controllo del risultato dell'ultimo confronto nel costrutto [..] - return regexp_MATCH_RANGE; - if (member_match) { // salto del resto del costrutto se non è esclusivo - while (*p != ']') { - if (!*p) return regexp_MATCH_PATTERN; // se si è a fine pattern il costrutto non è valido - if (*p == '\\') { // salto di un confronto con un metacarattere - p++; - if (!*p) return regexp_MATCH_PATTERN; // se il pattern termina qui non è valido - } - p++; // posizionamento sul prossimo carattere del pattern - } - } - break; - } - case '\\': // confronto con un metacarattere - p++; // posizionamento sul carattere da confrontare - if (!*p) return regexp_MATCH_PATTERN; // se il pattern termina qui non è valido - default: // confronto con un carattere normale - if (*p != *t) return regexp_MATCH_LITERAL; - } - } - if (*t) return regexp_MATCH_END; // se la stringa non è conclusa non c'è coincidenza - else return regexp_MATCH_VALID; + for (; *p; p++, t++) { + if (!*t) // se si è alla fine della stringa, il confronto è concluso + return (*p == '*' && *++p == '\0') ? regexp_MATCH_VALID : regexp_MATCH_ABORT; + switch (*p) { // determina il tipo di wild card del pattern + case '?': // carattere singolo, qualunque carattere coincide + break; + case '*': // sottostringa, coincide qualunque sequenza di caratteri + return matche_after_star (p, t); + case '[': { // costrutto [..], controllo di coincidenza per inclusione o esclusione su un solo carattere + p++; // posizionamento all'inizio del range + bool invert= FALSE; // controllo di inclusione o esclusione del costrutto + if (*p == '!' || *p == '^') { + invert= TRUE; + p++; + } + if (*p == ']') // se si è su una chiusura di costrutto il pattern non è valido + return regexp_MATCH_PATTERN; + bool member_match= FALSE; + bool loop= TRUE; + while (loop) { + char range_start, range_end; // inizio e fine del range corrente + if (*p == ']') { // se si è alla fine del costrutto il ciclo si conclude + loop= FALSE; + continue; + } + if (*p == '\\') // controllo di coincidenza su un metacarattere, dopo un escape + range_start= range_end= *++p; + else + range_start= range_end= *p; + if (!*p) return regexp_MATCH_PATTERN; // se il pattern termina non è valido + if (*++p == '-') { // controllo del segno di sottoinsieme + range_end= *++p; // impostazione della fine del range + if (range_end == '\0' || range_end == ']') return regexp_MATCH_PATTERN; // se il costrutto [..] o il pattern terminano qui allora il pattern non è valido + if (range_end == '\\') { // la fine del range è un metacarattere + range_end= *++p; + if (!range_end) return regexp_MATCH_PATTERN; // se il pattern termina non è valido + } + p++; // posizionamento oltre il range + } + if (range_start < range_end) { // confronto del carattere corrente con il costrutto, controllo della sequenzialità degli estremi del range + if (*t >= range_start && *t <= range_end) { + member_match= TRUE; + loop= FALSE; + } + } else { + if (*t >= range_end && *t <= range_start) { + member_match= TRUE; + loop= FALSE; + } + } + } + if ((invert && member_match) || !(invert || member_match)) // controllo del risultato dell'ultimo confronto nel costrutto [..] + return regexp_MATCH_RANGE; + if (member_match) { // salto del resto del costrutto se non è esclusivo + while (*p != ']') { + if (!*p) return regexp_MATCH_PATTERN; // se si è a fine pattern il costrutto non è valido + if (*p == '\\') { // salto di un confronto con un metacarattere + p++; + if (!*p) return regexp_MATCH_PATTERN; // se il pattern termina qui non è valido + } + p++; // posizionamento sul prossimo carattere del pattern + } + } + break; + } + case '\\': // confronto con un metacarattere + p++; // posizionamento sul carattere da confrontare + if (!*p) return regexp_MATCH_PATTERN; // se il pattern termina qui non è valido + default: // confronto con un carattere normale + if (*p != *t) return regexp_MATCH_LITERAL; + } + } + if (*t) return regexp_MATCH_END; // se la stringa non è conclusa non c'è coincidenza + else return regexp_MATCH_VALID; } bool match(const char *pat, const char *str) { - int err= matche(pat, str); - return (err == regexp_MATCH_VALID); // ritorna TRUE se il pattern e la stringa coincidono + int err= matche(pat, str); + return (err == regexp_MATCH_VALID); // ritorna TRUE se il pattern e la stringa coincidono }