Aggiunte le regular expression al metodo match() delle TString
git-svn-id: svn://10.65.10.50/trunk@2230 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
b2aa454ff0
commit
1a552db81e
196
include/regexp.cpp
Executable file
196
include/regexp.cpp
Executable file
@ -0,0 +1,196 @@
|
|||||||
|
#ifndef __REGEXP_H
|
||||||
|
#include <regexp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// codici di ritorno della matche()
|
||||||
|
#define regexp_MATCH_PATTERN (6) // pattern non valido
|
||||||
|
#define regexp_MATCH_LITERAL (5) // il pattern non coincide su un carattere comune
|
||||||
|
#define regexp_MATCH_RANGE (4) // il pattern non coincide in un costrutto [..]
|
||||||
|
#define regexp_MATCH_ABORT (3) // il stringa da confrontare è terminata anticipatamente
|
||||||
|
#define regexp_MATCH_END (2) // il pattern è terminato anticipatamente
|
||||||
|
#define regexp_MATCH_VALID (1) // pattern e stringa coincidono
|
||||||
|
|
||||||
|
// codici di ritorno della is_valid_pattern()
|
||||||
|
#define regexp_PATTERN_VALID (0) // il pattern è valido
|
||||||
|
#define regexp_PATTERN_ESC (-1) // è presente un escape aperto a fine pattern
|
||||||
|
#define regexp_PATTERN_RANGE (-2) // c'è un range non chiuso all'interno di un costrutto [..]
|
||||||
|
#define regexp_PATTERN_CLOSE (-3) // manca la parentesi di chiusura in un costrutto [..]
|
||||||
|
#define regexp_PATTERN_EMPTY (-4) // c'è un costrutto vuoto
|
||||||
|
|
||||||
|
// prototipi delle funzioni interne
|
||||||
|
HIDDEN int matche(const char *pat, const char *str); // ritorna un codice della classe regexp_MATCH che indica se e in che modo pattern e stringa coincidono
|
||||||
|
HIDDEN int matche_after_star(const char *pat, const char *str); // chiama ricorsivamente la matche() con i segmenti puri del pattern e della stringa
|
||||||
|
HIDDEN bool is_pattern(const char *pat); // ritorna TRUE se la stringa è un pattern
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
30
include/regexp.h
Executable file
30
include/regexp.h
Executable file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef __REGEXP_H
|
||||||
|
#define __REGEXP_H
|
||||||
|
|
||||||
|
#ifndef __STDTYPES_H
|
||||||
|
#include <stdtypes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#include <stddef.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Composizione delle regular expression:
|
||||||
|
// -------------------------------------
|
||||||
|
// - '*' sostituisce una qualunque sottostringa (0 o più caratteri)
|
||||||
|
// - '?' sostituisce un carattere qualunque (necessariamente presente)
|
||||||
|
// - [RANGE] sostituisce un carattere presente nel RANGE specificato
|
||||||
|
// I range si compongono di singoli caratteri o di sottoinsiemi di caratteri,
|
||||||
|
// indicati con un carattere iniziale, un segno meno ('-') e un carattere
|
||||||
|
// finale. Esempio [0-9a-fL] comprende i caratteri dallo '0' al '9', dalla 'a'
|
||||||
|
// alla 'z' e la lettera 'L'. I range possono essere prefissati da '!' o
|
||||||
|
// '^' per indicare che l'insieme dei caratteri specificati sono esclusi
|
||||||
|
// e non inclusi. Esempio [!jkwxy] indica la sostituzione di qualunque
|
||||||
|
// carattere tranne 'j', 'k', 'w', 'x', 'y' e 'z'.
|
||||||
|
// Per specificare nei pattern gli stessi metacaratteri con cui si formano i
|
||||||
|
// pattern basta prefissarli con l'escape '\'. Esempio [\[\]] sostituisce un
|
||||||
|
// carattere di parentesi quadra aperta o chiusa.
|
||||||
|
|
||||||
|
bool match(const char *pat, const char *str); // ritorna TRUE se il pattern (primo parametro) e la stringa (secondo) coincidono
|
||||||
|
|
||||||
|
#endif
|
@ -315,20 +315,6 @@ int TString::find(
|
|||||||
return p ? int(p - _str) : -1;
|
return p ? int(p - _str) : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Certified 50%
|
|
||||||
// @mfunc Confronta usando i caratteri jolly
|
|
||||||
bool TString::match(
|
|
||||||
const char* s) const // @parm Stringa da confrontare
|
|
||||||
|
|
||||||
// @comm Confronta se la stringa e' parzialmente uguale ad un'altra, cioe' non confrontando
|
|
||||||
// tutti i caratteri, ma solo quelli non jolly
|
|
||||||
{
|
|
||||||
if (strchr(s, '?') == NULL) return operator ==(s);
|
|
||||||
|
|
||||||
for (const char* me = _str; *s && *me; s++, me++)
|
|
||||||
if (*s != '?' && *s != *me) break;
|
|
||||||
return *s == '\0' && *me == '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
#if XVT_OS != XVT_OS_WIN
|
#if XVT_OS != XVT_OS_WIN
|
||||||
HIDDEN char* strstr(const char* string1, const char* string2)
|
HIDDEN char* strstr(const char* string1, const char* string2)
|
||||||
|
@ -9,6 +9,11 @@
|
|||||||
#include <array.h>
|
#include <array.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __REGEXP_H
|
||||||
|
#include <regexp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// @doc EXTERNAL
|
// @doc EXTERNAL
|
||||||
|
|
||||||
// @class Classe per la definizione della stringhe
|
// @class Classe per la definizione della stringhe
|
||||||
@ -222,8 +227,9 @@ public:
|
|||||||
// @cmember Controlla se una stringa e piu' corta o uguale ad un'altra
|
// @cmember Controlla se una stringa e piu' corta o uguale ad un'altra
|
||||||
bool operator <=(const char* s) const
|
bool operator <=(const char* s) const
|
||||||
{ return strcmp(_str, s) <= 0; }
|
{ return strcmp(_str, s) <= 0; }
|
||||||
// @cmember Confronta usando i caratteri jolly
|
// @cmember Confronta usando le regular expression
|
||||||
bool match(const char* s) const;
|
bool match(const char* pat) const
|
||||||
|
{ return ::match(pat, _str); }
|
||||||
// @cmember Compara due stringhe (o i primi max caratteri)
|
// @cmember Compara due stringhe (o i primi max caratteri)
|
||||||
int compare(const char* s, int max = -1, bool ignorecase = FALSE) const;
|
int compare(const char* s, int max = -1, bool ignorecase = FALSE) const;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user