func TestNumSubexp(t *testing.T) {
for _, c := range numSubexpCases {
- re, _ := Compile(c.input)
+ re := MustCompile(c.input)
n := re.NumSubexp()
if n != c.expected {
t.Errorf("NumSubexp for %q returned %d, expected %d", c.input, n, c.expected)
func BenchmarkLiteral(b *testing.B) {
x := strings.Repeat("x", 50)
b.StopTimer()
- re, _ := Compile(x)
+ re := MustCompile(x)
b.StartTimer()
for i := 0; i < b.N; i++ {
if !re.MatchString(x) {
func BenchmarkNotLiteral(b *testing.B) {
x := strings.Repeat("x", 49)
b.StopTimer()
- re, _ := Compile("^" + x)
+ re := MustCompile("^" + x)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ if !re.MatchString(x) {
+ println("no match!")
+ break
+ }
+ }
+}
+
+func BenchmarkMatchClass(b *testing.B) {
+ b.StopTimer()
+ x := strings.Repeat("xxxx", 20) + "w"
+ re := MustCompile("[abcdw]")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ if !re.MatchString(x) {
+ println("no match!")
+ break
+ }
+ }
+}
+
+func BenchmarkMatchClass_InRange(b *testing.B) {
+ b.StopTimer()
+ // 'b' is betwen 'a' and 'c', so the charclass
+ // range checking is no help here.
+ x := strings.Repeat("bbbb", 20) + "c"
+ re := MustCompile("[ac]")
b.StartTimer()
for i := 0; i < b.N; i++ {
if !re.MatchString(x) {
func BenchmarkReplaceAll(b *testing.B) {
x := "abcdefghijklmnopqrstuvwxyz"
b.StopTimer()
- re, _ := Compile("[cjrw]")
+ re := MustCompile("[cjrw]")
b.StartTimer()
for i := 0; i < b.N; i++ {
re.ReplaceAllString(x, "")
type _CharClass struct {
common
- char int
negate bool // is character class negated? ([^a-z])
// vector of int, stored pairwise: [a-z] is (a,z); x is (x,x):
- ranges *vector.IntVector
+ ranges *vector.IntVector
+ cmin, cmax int
}
func (cclass *_CharClass) kind() int { return _CHARCLASS }
// range is a through b inclusive
cclass.ranges.Push(a)
cclass.ranges.Push(b)
+ if a < cclass.cmin {
+ cclass.cmin = a
+ }
+ if b > cclass.cmax {
+ cclass.cmax = b
+ }
}
func (cclass *_CharClass) matches(c int) bool {
- for i := 0; i < cclass.ranges.Len(); i = i + 2 {
- min := cclass.ranges.At(i)
- max := cclass.ranges.At(i + 1)
- if min <= c && c <= max {
+ if c < cclass.cmin || c > cclass.cmax {
+ return cclass.negate
+ }
+ ranges := []int(*cclass.ranges)
+ for i := 0; i < len(ranges); i = i + 2 {
+ if ranges[i] <= c && c <= ranges[i+1] {
return !cclass.negate
}
}
func newCharClass() *_CharClass {
c := new(_CharClass)
c.ranges = new(vector.IntVector)
+ c.cmin = 0x10FFFF + 1 // MaxRune + 1
+ c.cmax = -1
return c
}