github.com/iDigitalFlame/xmt@v0.5.4/util/text/r_regexp.go (about) 1 //go:build regexp 2 // +build regexp 3 4 // Copyright (C) 2020 - 2023 iDigitalFlame 5 // 6 // This program is free software: you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation, either version 3 of the License, or 9 // any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program. If not, see <https://www.gnu.org/licenses/>. 18 // 19 20 package text 21 22 import ( 23 "regexp" 24 "strconv" 25 "strings" 26 27 "github.com/iDigitalFlame/xmt/util" 28 ) 29 30 type inverseRegexp string 31 32 // String parses this MatchString value and will preform any replacements and 33 // fill any variables contained. 34 func (s Matcher) String() string { 35 if len(s) == 0 { 36 return string(s) 37 } 38 m := regxBuild.FindAllStringSubmatchIndex(string(s), -1) 39 if len(m) == 0 { 40 return string(s) 41 } 42 var ( 43 l int 44 err error 45 b = builders.Get().(*util.Builder) 46 ) 47 b.Grow(len(s)) 48 for x, v, c := 0, 0, ""; x < len(m); x++ { 49 if m[x][0] < 0 || m[x][1] < m[x][0] { 50 continue 51 } 52 if m[x][4] > 0 && m[x][5] > m[x][4] { 53 if s[m[x][5]-1] == 'f' { 54 v, err = strconv.Atoi(string(s[m[x][4] : m[x][5]-1])) 55 } else { 56 v, err = strconv.Atoi(string(s[m[x][4]:m[x][5]])) 57 } 58 if err != nil { 59 v = -1 60 } 61 } else { 62 v = -1 63 } 64 switch { 65 case s[m[x][1]-1] == 'n' && s[m[x][1]-2] == 'f' && v > 0: 66 c = Rand.StringNumber(v) 67 case s[m[x][1]-1] == 'c' && s[m[x][1]-2] == 'f' && v > 0: 68 c = Rand.StringCharacters(v) 69 case s[m[x][1]-1] == 'u' && s[m[x][1]-2] == 'f' && v > 0: 70 c = Rand.StringUpper(v) 71 case s[m[x][1]-1] == 'l' && s[m[x][1]-2] == 'f' && v > 0: 72 c = Rand.StringLower(v) 73 case s[m[x][1]-1] == 's' && s[m[x][1]-2] == 'f' && v > 0: 74 c = Rand.String(v) 75 case s[m[x][1]-1] == 'd' && s[m[x][1]-2] == 'f' && v >= 0: 76 c = util.Uitoa(uint64(v)) 77 case s[m[x][1]-1] == 'h' && s[m[x][1]-2] == 'f' && v >= 0: 78 c = util.Uitoa16(uint64(v)) 79 case s[m[x][1]-1] == 'd' && v >= 0: 80 c = util.Uitoa(uint64(util.FastRandN(v))) 81 case s[m[x][1]-1] == 'h' && v >= 0: 82 c = util.Uitoa16(uint64(util.FastRandN(v))) 83 case s[m[x][1]-1] == 'n' && v > 0: 84 c = Rand.StringNumberRange(1, v) 85 case s[m[x][1]-1] == 'c' && v > 0: 86 c = Rand.StringCharactersRange(1, v) 87 case s[m[x][1]-1] == 'u' && v > 0: 88 c = Rand.StringUpperRange(1, v) 89 case s[m[x][1]-1] == 'l' && v > 0: 90 c = Rand.StringLowerRange(1, v) 91 case s[m[x][1]-1] == 's' && v > 0: 92 c = Rand.StringRange(1, v) 93 case s[m[x][1]-1] == 's': 94 c = Rand.StringRange(1, 1+int(util.FastRandN(256))) 95 case s[m[x][1]-1] == 'd': 96 c = util.Uitoa(uint64(util.FastRand())) 97 case s[m[x][1]-1] == 'h': 98 c = util.Uitoa16(uint64(util.FastRand())) 99 default: 100 c = string(s[m[x][0]:m[x][1]]) 101 } 102 b.WriteString(string(s[l:m[x][0]])) 103 b.WriteString(c) 104 c, l = "", m[x][1] 105 } 106 if l < len(s) { 107 b.WriteString(string(s[l:])) 108 } 109 o := b.String() 110 b.Reset() 111 builders.Put(b) 112 return o 113 } 114 func (i inverseRegexp) String() string { 115 return string(i) 116 } 117 118 // MatchEx returns a valid Regexp struct that is guaranteed to match any string 119 // generated by the Matcher's 'String' function. MatchEx returns an inverse 120 // matcher if the bool is false. 121 func (s Matcher) MatchEx(o bool) Regexp { 122 if len(s) == 0 { 123 return MatchAny 124 } 125 if s == "*" { 126 return MatchAny 127 } 128 m := regxBuild.FindAllStringSubmatchIndex(string(s), -1) 129 if len(m) == 0 { 130 if !o { 131 return inverseRegexp(s) 132 } 133 if r, err := regexp.Compile(`^(` + regexp.QuoteMeta(string(s)) + `)$`); err == nil { 134 return r 135 } 136 return MatchNone 137 } 138 var ( 139 l int 140 d string 141 err error 142 b = builders.Get().(*util.Builder) 143 ) 144 if b.WriteString("^("); !o { 145 d = "^" 146 } 147 for x, v, c, q := 0, 0, "", ""; x < len(m); x++ { 148 if m[x][0] < 0 || m[x][1] < m[x][0] { 149 continue 150 } 151 if m[x][4] > 0 && m[x][5] > m[x][4] { 152 if s[m[x][5]-1] == 'f' { 153 v, err = strconv.Atoi(string(s[m[x][4] : m[x][5]-1])) 154 } else { 155 v, err = strconv.Atoi(string(s[m[x][4]:m[x][5]])) 156 } 157 if err != nil { 158 v, q = -1, "0" 159 } else { 160 q = util.Uitoa(uint64(v)) 161 } 162 } else { 163 v = -1 164 } 165 switch { 166 case s[m[x][1]-1] == 'd': 167 c = `([` + d + `0-9]+)` 168 case s[m[x][1]-1] == 'h': 169 c = `([` + d + `a-fA-F0-9]+)` 170 case s[m[x][1]-1] == 'n' && s[m[x][1]-2] == 'f' && v > 0: 171 c = `([` + d + `0-9]{` + q + `})` 172 case s[m[x][1]-1] == 'c' && s[m[x][1]-2] == 'f' && v > 0: 173 c = `([` + d + `a-zA-Z]{` + q + `})` 174 case s[m[x][1]-1] == 'u' && s[m[x][1]-2] == 'f' && v > 0: 175 c = `([` + d + `A-Z]{` + q + `})` 176 case s[m[x][1]-1] == 'l' && s[m[x][1]-2] == 'f' && v > 0: 177 c = `([` + d + `a-z]{` + q + `})` 178 case s[m[x][1]-1] == 's' && s[m[x][1]-2] == 'f' && v > 0: 179 c = `([` + d + `a-zA-Z0-9]{` + q + `})` 180 case s[m[x][1]-1] == 'n' && v > 0: 181 c = `([` + d + `0-9]{1,` + q + `})` 182 case s[m[x][1]-1] == 'c' && v > 0: 183 c = `([` + d + `a-zA-Z]{1,` + q + `})` 184 case s[m[x][1]-1] == 'u' && v > 0: 185 c = `([` + d + `A-Z]{1,` + q + `})` 186 case s[m[x][1]-1] == 'l' && v > 0: 187 c = `([` + d + `a-z]{1,` + q + `})` 188 case s[m[x][1]-1] == 's' && v > 0: 189 c = `([` + d + `a-zA-Z0-9]{1,` + q + `})` 190 case s[m[x][1]-1] == 's': 191 c = `([` + d + `a-zA-Z0-9]+)` 192 default: 193 c = string(s[m[x][0]:m[x][1]]) 194 } 195 b.WriteString(strings.Replace(regexp.QuoteMeta(string(s[l:m[x][0]])), "/", "\\/", -1)) 196 b.WriteString(c) 197 l = m[x][1] 198 } 199 if l < len(s) { 200 b.WriteString(strings.Replace(regexp.QuoteMeta(string(s[l:])), "/", "\\/", -1)) 201 } 202 b.WriteString(")$") 203 r, err := regexp.Compile(b.Output()) 204 if builders.Put(b); err != nil { 205 return MatchAny 206 } 207 return r 208 } 209 func (i inverseRegexp) Match(b []byte) bool { 210 return string(i) != string(b) 211 } 212 func (i inverseRegexp) MatchString(s string) bool { 213 return string(i) != s 214 }