mirror of
https://github.com/golang/go
synced 2024-11-13 19:00:25 -07:00
regexp: change Expr() to String(); add HasOperator method to Regexp.
It reports whether a regular expression has operators as opposed to matching literal text. R=rsc, gri CC=golang-dev https://golang.org/cl/3731041
This commit is contained in:
parent
8ec6f7cd11
commit
a9e7c9381e
@ -229,18 +229,21 @@ func TestReplaceAllFunc(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type QuoteMetaTest struct {
|
type MetaTest struct {
|
||||||
pattern, output string
|
pattern, output, literal string
|
||||||
|
isLiteral bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var quoteMetaTests = []QuoteMetaTest{
|
var metaTests = []MetaTest{
|
||||||
{``, ``},
|
{``, ``, ``, true},
|
||||||
{`foo`, `foo`},
|
{`foo`, `foo`, `foo`, true},
|
||||||
{`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[{\]}\\\|,<\.>/\?~`},
|
{`foo\.\$`, `foo\\\.\\\$`, `foo.$`, true}, // has meta but no operator
|
||||||
|
{`foo.\$`, `foo\.\\\$`, `foo`, false}, // has escaped operators and real operators
|
||||||
|
{`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[{\]}\\\|,<\.>/\?~`, `!@#`, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQuoteMeta(t *testing.T) {
|
func TestQuoteMeta(t *testing.T) {
|
||||||
for _, tc := range quoteMetaTests {
|
for _, tc := range metaTests {
|
||||||
// Verify that QuoteMeta returns the expected string.
|
// Verify that QuoteMeta returns the expected string.
|
||||||
quoted := QuoteMeta(tc.pattern)
|
quoted := QuoteMeta(tc.pattern)
|
||||||
if quoted != tc.output {
|
if quoted != tc.output {
|
||||||
@ -269,14 +272,16 @@ func TestQuoteMeta(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasMeta(t *testing.T) {
|
func TestLiteralPrefix(t *testing.T) {
|
||||||
for _, tc := range quoteMetaTests {
|
for _, tc := range metaTests {
|
||||||
// HasMeta should be false if QuoteMeta returns the original string;
|
// Literal method needs to scan the pattern.
|
||||||
// true otherwise.
|
re := MustCompile(tc.pattern)
|
||||||
quoted := QuoteMeta(tc.pattern)
|
str, complete := re.LiteralPrefix()
|
||||||
if HasMeta(tc.pattern) != (quoted != tc.pattern) {
|
if complete != tc.isLiteral {
|
||||||
t.Errorf("HasMeta(`%s`) = %t; want %t",
|
t.Errorf("LiteralPrefix(`%s`) = %t; want %t", tc.pattern, complete, tc.isLiteral)
|
||||||
tc.pattern, HasMeta(tc.pattern), quoted != tc.pattern)
|
}
|
||||||
|
if str != tc.literal {
|
||||||
|
t.Errorf("LiteralPrefix(`%s`) = `%s`; want `%s`", tc.pattern, str, tc.literal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,8 +120,8 @@ func build(n int, x ...int) [][]int {
|
|||||||
func TestFind(t *testing.T) {
|
func TestFind(t *testing.T) {
|
||||||
for _, test := range findTests {
|
for _, test := range findTests {
|
||||||
re := MustCompile(test.pat)
|
re := MustCompile(test.pat)
|
||||||
if re.Expr() != test.pat {
|
if re.String() != test.pat {
|
||||||
t.Errorf("Expr() = `%s`; should be `%s`", re.Expr(), test.pat)
|
t.Errorf("String() = `%s`; should be `%s`", re.String(), test.pat)
|
||||||
}
|
}
|
||||||
result := re.Find([]byte(test.text))
|
result := re.Find([]byte(test.text))
|
||||||
switch {
|
switch {
|
||||||
|
@ -599,8 +599,8 @@ Loop:
|
|||||||
re.prefix = string(b)
|
re.prefix = string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expr returns the source text used to compile the regular expression.
|
// String returns the source text used to compile the regular expression.
|
||||||
func (re *Regexp) Expr() string {
|
func (re *Regexp) String() string {
|
||||||
return re.expr
|
return re.expr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -849,6 +849,24 @@ func (re *Regexp) doExecute(str string, bytestr []byte, pos int) []int {
|
|||||||
return final.match.m
|
return final.match.m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LiteralPrefix returns a literal string that must begin any match
|
||||||
|
// of the regular expression re. It returns the boolean true if the
|
||||||
|
// literal string comprises the entire regular expression.
|
||||||
|
func (re *Regexp) LiteralPrefix() (prefix string, complete bool) {
|
||||||
|
c := make([]int, len(re.inst)-2) // minus start and end.
|
||||||
|
// First instruction is start; skip that.
|
||||||
|
i := 0
|
||||||
|
for inst := re.inst[0].next; inst.kind != iEnd; inst = inst.next {
|
||||||
|
// stop if this is not a char
|
||||||
|
if inst.kind != iChar {
|
||||||
|
return string(c[:i]), false
|
||||||
|
}
|
||||||
|
c[i] = inst.char
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return string(c[:i]), true
|
||||||
|
}
|
||||||
|
|
||||||
// MatchString returns whether the Regexp matches the string s.
|
// MatchString returns whether the Regexp matches the string s.
|
||||||
// The return value is a boolean: true for match, false for no match.
|
// The return value is a boolean: true for match, false for no match.
|
||||||
func (re *Regexp) MatchString(s string) bool { return len(re.doExecute(s, nil, 0)) > 0 }
|
func (re *Regexp) MatchString(s string) bool { return len(re.doExecute(s, nil, 0)) > 0 }
|
||||||
@ -1003,18 +1021,6 @@ func QuoteMeta(s string) string {
|
|||||||
return string(b[0:j])
|
return string(b[0:j])
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasMeta returns a boolean indicating whether the string contains
|
|
||||||
// any regular expression metacharacters.
|
|
||||||
func HasMeta(s string) bool {
|
|
||||||
// A byte loop is correct because all metacharacters are ASCII.
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
if special(int(s[i])) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find matches in slice b if b is non-nil, otherwise find matches in string s.
|
// Find matches in slice b if b is non-nil, otherwise find matches in string s.
|
||||||
func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
|
func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
|
||||||
var end int
|
var end int
|
||||||
|
Loading…
Reference in New Issue
Block a user