gitlab.com/evatix-go/core@v1.3.55/regexnew/LazyRegex.go (about) 1 package regexnew 2 3 import ( 4 "errors" 5 "regexp" 6 ) 7 8 // LazyRegex 9 // 10 // lazy regex for future unwrapping or compiled but only once. 11 type LazyRegex struct { 12 isCompiled bool 13 isApplicable bool // no err, pattern defined, not null 14 pattern string 15 regex *regexp.Regexp 16 compiledErr error 17 compiler func(pattern string) ( 18 *regexp.Regexp, error, 19 ) // must be a locked function, cannot use non lock version 20 } 21 22 func (it *LazyRegex) IsNull() bool { 23 return it == nil 24 } 25 26 func (it *LazyRegex) IsDefined() bool { 27 return it != nil && it.pattern != "" && it.compiler != nil 28 } 29 30 func (it *LazyRegex) IsUndefined() bool { 31 return it == nil || it.pattern == "" || it.compiler == nil 32 } 33 34 // IsApplicable 35 // 36 // it unwraps the regex and compiles so take memory for once. 37 func (it *LazyRegex) IsApplicable() bool { 38 if it.isApplicable { 39 return true 40 } 41 42 if it.IsUndefined() { 43 return false 44 } 45 46 // compile required 47 // fine to swallow err 48 // updates isApplicable 49 it.Compile() 50 51 return it.isApplicable 52 } 53 54 // Compile 55 // 56 // it is done through the locking mechanism 57 func (it *LazyRegex) Compile() (regex *regexp.Regexp, err error) { 58 if it.IsCompiled() { 59 return it.regex, it.compiledErr 60 } 61 62 if it.IsUndefined() { 63 return nil, errors.New("lazy regex is undefined or nil") 64 } 65 66 // defined 67 compiledRegex, regExErr := it.compiler(it.pattern) // compiler should be locked func, must be 68 it.isApplicable = compiledRegex != nil && regExErr == nil 69 it.regex = compiledRegex 70 it.compiledErr = regExErr 71 it.isCompiled = true 72 73 return compiledRegex, regExErr 74 } 75 76 func (it *LazyRegex) CompileMust() (regex *regexp.Regexp) { 77 regexCompiled, err := it.Compile() 78 79 if err != nil { 80 panic(err) 81 } 82 83 return regexCompiled 84 } 85 86 func (it *LazyRegex) IsCompiled() bool { 87 return it != nil && it.isCompiled 88 } 89 90 func (it *LazyRegex) OnRequiredCompiled() error { 91 if it == nil { 92 return errors.New("nil LazyRegex cannot compile") 93 } 94 95 if it.IsCompiled() { 96 return it.compiledErr 97 } 98 99 _, err := it.Compile() 100 101 return err 102 } 103 104 func (it *LazyRegex) OnRequiredCompiledMust() { 105 err := it.CompileMust() 106 107 if err != nil { 108 panic(err) 109 } 110 } 111 112 func (it *LazyRegex) HasError() bool { 113 // fine to swallow 114 it.OnRequiredCompiled() 115 116 return it != nil && it.compiledErr != nil 117 } 118 119 func (it *LazyRegex) HasAnyIssues() bool { 120 if it == nil { 121 return true 122 } 123 124 return !it.IsApplicable() 125 } 126 127 func (it *LazyRegex) IsInvalid() bool { 128 if it == nil { 129 return true 130 } 131 132 return !it.IsApplicable() 133 } 134 135 func (it *LazyRegex) CompiledError() error { 136 return it.OnRequiredCompiled() 137 } 138 139 func (it *LazyRegex) Error() error { 140 return it.OnRequiredCompiled() 141 } 142 143 func (it *LazyRegex) MustBeSafe() { 144 compiledErr := it.CompiledError() 145 146 if compiledErr != nil { 147 panic(compiledErr) 148 } 149 } 150 151 func (it *LazyRegex) String() (pattern string) { 152 if it == nil { 153 return "" 154 } 155 156 return it.pattern 157 } 158 159 func (it *LazyRegex) FullString() (detail string) { 160 if it == nil { 161 return "" 162 } 163 164 isApplicable := it.IsApplicable() 165 isCompiled := it.IsCompiled() 166 compiledErr := it.CompiledError() 167 168 newMap := map[string]interface{}{ 169 "pattern": it.Pattern(), 170 "isCompiled": isCompiled, 171 "isApplicable": isApplicable, 172 "error": compiledErr, 173 } 174 175 return prettyJson(newMap) 176 } 177 178 func (it *LazyRegex) Pattern() (pattern string) { 179 if it == nil { 180 return "" 181 } 182 183 return it.pattern 184 } 185 186 func (it *LazyRegex) MatchError(matchingPattern string) error { 187 regEx, compiledErr := it.Compile() 188 189 if regEx != nil && regEx.MatchString(matchingPattern) { 190 return nil 191 } 192 193 return regExMatchValidationError( 194 it.pattern, 195 matchingPattern, 196 compiledErr, 197 regEx) 198 } 199 200 // MatchUsingFuncError 201 // 202 // creates new regex using lock 203 // and then calls match. 204 // On condition mismatch returns error 205 // or else nil 206 func (it *LazyRegex) MatchUsingFuncError( 207 comparing string, 208 matchFunc RegexValidationFunc, 209 ) error { 210 regEx, compiledErr := it.Compile() 211 212 if regEx != nil && matchFunc(regEx, comparing) { 213 return nil 214 } 215 216 return regExMatchValidationError( 217 it.pattern, 218 comparing, 219 compiledErr, 220 regEx) 221 } 222 223 func (it *LazyRegex) IsMatch( 224 comparing string, 225 ) bool { 226 regEx, compiledErr := it.Compile() 227 228 if regEx == nil || compiledErr != nil { 229 return false 230 } 231 232 return regEx.MatchString(comparing) 233 } 234 235 func (it *LazyRegex) IsMatchBytes( 236 comparingBytes []byte, 237 ) bool { 238 regEx, compiledErr := it.Compile() 239 240 if regEx == nil || compiledErr != nil { 241 return false 242 } 243 244 return regEx.Match(comparingBytes) 245 } 246 247 func (it *LazyRegex) IsFailedMatch( 248 comparing string, 249 ) bool { 250 regEx, compiledErr := it.Compile() 251 252 if regEx == nil || compiledErr != nil { 253 return true 254 } 255 256 return !regEx.MatchString(comparing) 257 } 258 259 func (it *LazyRegex) IsFailedMatchBytes( 260 comparingBytes []byte, 261 ) bool { 262 regEx, compiledErr := it.Compile() 263 264 if regEx == nil || compiledErr != nil { 265 return true 266 } 267 268 return !regEx.Match(comparingBytes) 269 } 270 271 func (it *LazyRegex) FirstMatchLine( 272 content string, 273 ) (firstMatch string, isInvalidMatch bool) { 274 regEx, compiledErr := it.Compile() 275 276 if regEx == nil || compiledErr != nil { 277 return "", true 278 } 279 280 lines := regEx.FindStringSubmatch(content) 281 282 if len(lines) > 0 { 283 // valid 284 return lines[0], false 285 } 286 287 // invalid 288 return "", true 289 }