Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(707)

Side by Side Diff: src/pkg/regexp/fallback.go

Issue 5971058: code review 5971058: regexp: implement backtracking with pcre fallback (Closed)
Patch Set: diff -r 15a98eba66e0 https://go.googlecode.com/hg/ Created 13 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/regexp/exec.go ('k') | src/pkg/regexp/find_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // +build !cmd_go_bootstrap
adg 2012/04/01 04:07:49 put the build line after the copyright
bradfitz 2012/04/01 04:11:45 Actually I was bit by this recently, when the copy
2
3 // Copyright 2012 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 package regexp
8
9 import (
10 "io"
11 "regexp/pcre"
12 "regexp/syntax"
13 "strings"
14 "unicode/utf8"
15 "unsafe"
16 )
17
18 func init() {
19 fallbackCompile = func(expr string, err error) (*Regexp, error) {
20 // Try PCRE if Go's regexp package can't handle the pattern.
21 if strings.Contains(expr, `\C`) {
22 // ... unless it contains \C, because we don't
23 // care about that and it break tests that
24 // assume it's broken. Whatever.
25 return nil, err
26 }
27 pre, perr := pcre.Compile(expr, 0)
28 if perr != nil {
29 return nil, perr
30 }
31 err = nil
32 r := &Regexp{
33 expr: expr,
34 prog: &syntax.Prog{
35 NumCap: pre.Groups(),
36 },
37 numSubexp: pre.Groups(),
38 fallbackExec: func(r io.RuneReader, b []byte, s string, pos int, ncap int) []int {
39 return pcreExec(&pre, r, b, s, pos, ncap)
40 },
41 }
42 return r, nil
43 }
44 }
45
46 func pcreExec(pre *pcre.Regexp, r io.RuneReader, b []byte, s string, pos int, nc ap int) []int {
47 var pm *pcre.Matcher
48 if r != nil {
49 // Inefficient implementation; just repeatedly read a
50 // rune and call pcre Match until we find a match.
51 var buf [4]byte
52 for {
53 r, _, err := r.ReadRune()
54 if err != nil {
55 return nil
56 }
57 b = append(b, buf[:utf8.EncodeRune(buf[:], r)]...)
58 pm = pre.Matcher(b, 0)
59 if pm.Matches() {
60 break
61 }
62 }
63 } else if b != nil {
64 b = b[pos:]
65 pm = pre.Matcher(b, 0)
66 } else {
67 // Allocating here, so pm.Group returns this same byte
68 // slice we can do pointer math on matched groups vs b.
69 b = []byte(s[pos:])
70 pm = pre.Matcher(b, 0)
71 }
72 if !pm.Matches() {
73 return nil
74 }
75 if ncap == 0 {
76 return empty // empty but not nil
77 }
78 cap := make([]int, 0, 2*(ncap+1))
79 for i := 0; i <= ncap; i++ {
80 g := pm.Group(i)
81 off := int(uintptr(unsafe.Pointer(&g[0])) - uintptr(unsafe.Point er(&b[0])))
82 cap = append(cap, off+pos)
83 cap = append(cap, off+len(g)+pos)
84 }
85 return cap
86 }
OLDNEW
« no previous file with comments | « src/pkg/regexp/exec.go ('k') | src/pkg/regexp/find_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b