Left: | ||
Right: |
OLD | NEW |
---|---|
(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 } | |
OLD | NEW |