1//--------This file shamelessly stolen from Jeremy Friesner's excellent MUSCLE--------- 2/* This file is Copyright 2000 Level Control Systems. See the included LICENSE.txt file for details. */ 3 4#include <new> 5#include <stdio.h> 6 7#include "StringMatcher.h" 8 9#include <string.h> 10#include <String.h> 11 12StringMatcher::StringMatcher() : _regExpValid(false) 13{ 14 // empty 15} 16 17StringMatcher :: StringMatcher(const char * str) : _regExpValid(false) 18{ 19 SetPattern(str); 20} 21 22StringMatcher::~StringMatcher() 23{ 24 if (_regExpValid) regfree(&_regExp); 25} 26 27bool StringMatcher::SetPattern(const char * str, bool isSimple) 28{ 29 PortableString pattern; 30 31 if (isSimple) 32 { 33 pattern = "^\\("; 34 35 bool escapeMode = false; 36 for (const char * ptr = str; *ptr != '\0'; ptr++) 37 { 38 if (escapeMode) 39 { 40 escapeMode = false; 41 switch(*ptr) 42 { 43 case ',': case '|': case '(': case ')': case '?': 44 pattern += *ptr; 45 break; 46 47 default: 48 pattern += '\\'; 49 pattern += *ptr; 50 break; 51 } 52 } 53 else 54 { 55 switch(*ptr) 56 { 57 case ',': case '|': 58 pattern += "\\|"; 59 break; 60 61 case '.': case '(': case ')': 62 pattern += '\\'; 63 pattern += *ptr; 64 break; 65 66 case '*': 67 pattern += ".*"; 68 break; 69 70 case '?': 71 pattern += '.'; 72 break; 73 74 case '\\': 75 escapeMode = true; 76 break; 77 78 break; 79 80 default: 81 pattern += *ptr; 82 break; 83 } 84 } 85 } 86 pattern += "\\)$"; 87 //printf("OUTPUT: pattern became '%s'.\n", pattern.Cstr()); 88 } 89 90 // Free the old regular expression, if any 91 if (_regExpValid) 92 { 93 regfree(&_regExp); 94 _regExpValid = false; 95 } 96 97 // And compile the new one 98 _regExpValid = (regcomp(&_regExp, (pattern.Length() > 0) ? pattern.String() : str, 0) == 0); 99 return _regExpValid; 100} 101 102 103bool 104StringMatcher::Match(const char *str) const 105{ 106 if (_regExpValid == false) 107 return false; 108 109 int regExpStat = regexec(&_regExp, str, 0, NULL, 0); 110 111 return (regExpStat != REG_NOMATCH); 112} 113 114 115bool IsRegexToken(char c) 116{ 117 switch(c) 118 { 119 case '[': case ']': case '*': case '?': case '\\': case ',': case '|': case '(': case ')': 120 return true; 121 122 default: 123 return false; 124 } 125} 126 127void EscapeRegexTokens(PortableString & s) 128{ 129 const char * str = s.String(); 130 131 PortableString ret; 132 while(*str) 133 { 134 if (IsRegexToken(*str)) ret += '\\'; 135 ret += *str; 136 str++; 137 } 138 s = ret; 139} 140 141bool HasRegexTokens(const char * str) 142{ 143 while(*str) 144 { 145 if (IsRegexToken(*str)) return true; 146 else str++; 147 } 148 return false; 149} 150 151bool MakeRegexCaseInsensitive(PortableString & str) 152{ 153 bool changed = false; 154 PortableString ret; 155 for (uint32 i=0; i<(unsigned)str.Length(); i++) 156 { 157 char next = str[i]; 158 if ((next >= 'A')&&(next <= 'Z')) 159 { 160 char buf[5]; 161 sprintf(buf, "[%c%c]", next, next+('a'-'A')); 162 ret += buf; 163 changed = true; 164 } 165 else if ((next >= 'a')&&(next <= 'z')) 166 { 167 char buf[5]; 168 sprintf(buf, "[%c%c]", next, next+('A'-'a')); 169 ret += buf; 170 changed = true; 171 } 172 else ret += next; 173 } 174 if (changed) str = ret; 175 return changed; 176} 177