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

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

Issue 247041: code review 247041: regexp: add ReplaceAllFunc and ReplaceAllStringFunc (Closed)
Patch Set: code review 247041: regexp: add ReplaceAllFunc and ReplaceAllStringFunc Created 14 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 | « no previous file | src/pkg/regexp/regexp.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package regexp 5 package regexp
6 6
7 import ( 7 import (
8 "bytes"
9 "io"
8 "os" 10 "os"
9 "strings" 11 "strings"
10 "testing" 12 "testing"
13 "utf8"
11 ) 14 )
12 15
13 var good_re = []string{ 16 var good_re = []string{
14 ``, 17 ``,
15 `.`, 18 `.`,
16 `^.$`, 19 `^.$`,
17 `a`, 20 `a`,
18 `a*`, 21 `a*`,
19 `a+`, 22 `a+`,
20 `a?`, 23 `a?`,
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 ReplaceTest{"abc", "", "abcdabc", "d"}, 298 ReplaceTest{"abc", "", "abcdabc", "d"},
296 ReplaceTest{"x", "xXx", "xxxXxxx", "xXxxXxxXxXxXxxXxxXx"}, 299 ReplaceTest{"x", "xXx", "xxxXxxx", "xXxxXxxXxXxXxxXxxXx"},
297 ReplaceTest{"abc", "d", "", ""}, 300 ReplaceTest{"abc", "d", "", ""},
298 ReplaceTest{"abc", "d", "abc", "d"}, 301 ReplaceTest{"abc", "d", "abc", "d"},
299 ReplaceTest{".+", "x", "abc", "x"}, 302 ReplaceTest{".+", "x", "abc", "x"},
300 ReplaceTest{"[a-c]*", "x", "def", "xdxexfx"}, 303 ReplaceTest{"[a-c]*", "x", "def", "xdxexfx"},
301 ReplaceTest{"[a-c]+", "x", "abcbcdcdedef", "xdxdedef"}, 304 ReplaceTest{"[a-c]+", "x", "abcbcdcdedef", "xdxdedef"},
302 ReplaceTest{"[a-c]*", "x", "abcbcdcdedef", "xdxdxexdxexfx"}, 305 ReplaceTest{"[a-c]*", "x", "abcbcdcdedef", "xdxdxexdxexfx"},
303 } 306 }
304 307
308 type ReplaceFuncTest struct {
309 pattern string
310 replacement func(string)string
311 input, output string
312 }
313
314 var replaceFuncTests = []ReplaceFuncTest{
315 ReplaceFuncTest{"[a-c]", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxayxbyxcydef"},
316 ReplaceFuncTest{"[a-c]+", func(s string) string { return "x" + s + "y" } , "defabcdef", "defxabcydef"},
317 ReplaceFuncTest{"[a-c]*", func(s string) string { return "x" + s + "y" } , "defabcdef", "xydxyexyfxabcydxyexyfxy"},
318 }
319
305 func TestReplaceAll(t *testing.T) { 320 func TestReplaceAll(t *testing.T) {
306 for _, tc := range replaceTests { 321 for _, tc := range replaceTests {
307 re, err := Compile(tc.pattern) 322 re, err := Compile(tc.pattern)
308 if err != nil { 323 if err != nil {
309 t.Errorf("Unexpected error compiling %q: %v", tc.pattern , err) 324 t.Errorf("Unexpected error compiling %q: %v", tc.pattern , err)
310 continue 325 continue
311 } 326 }
312 actual := re.ReplaceAllString(tc.input, tc.replacement) 327 actual := re.ReplaceAllString(tc.input, tc.replacement)
313 if actual != tc.output { 328 if actual != tc.output {
314 t.Errorf("%q.Replace(%q,%q) = %q; want %q", 329 t.Errorf("%q.Replace(%q,%q) = %q; want %q",
315 tc.pattern, tc.input, tc.replacement, actual, tc .output) 330 tc.pattern, tc.input, tc.replacement, actual, tc .output)
316 } 331 }
317 // now try bytes 332 // now try bytes
318 actual = string(re.ReplaceAll([]byte(tc.input), []byte(tc.replac ement))) 333 actual = string(re.ReplaceAll([]byte(tc.input), []byte(tc.replac ement)))
319 if actual != tc.output { 334 if actual != tc.output {
320 t.Errorf("%q.Replace(%q,%q) = %q; want %q", 335 t.Errorf("%q.Replace(%q,%q) = %q; want %q",
321 tc.pattern, tc.input, tc.replacement, actual, tc .output) 336 tc.pattern, tc.input, tc.replacement, actual, tc .output)
322 } 337 }
323 } 338 }
324 } 339 }
325 340
341 func TestReplaceAllFunc(t *testing.T) {
342 for _, tc := range replaceFuncTests {
343 re, err := Compile(tc.pattern)
344 if err != nil {
345 t.Errorf("Unexpected error compiling %q: %v", tc.pattern , err)
346 continue
347 }
348 actual := re.ReplaceAllStringFunc(tc.input, tc.replacement)
349 if actual != tc.output {
350 t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
351 tc.pattern, tc.input, tc.replacement, actual, tc .output)
352 }
353 // now try bytes
354 actual = string(re.ReplaceAllFunc([]byte(tc.input), func(s []byt e) []byte { return []byte(tc.replacement(string(s))) } ))
355 if actual != tc.output {
356 t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
357 tc.pattern, tc.input, tc.replacement, actual, tc .output)
358 }
359 }
360 }
361
326 type QuoteMetaTest struct { 362 type QuoteMetaTest struct {
327 pattern, output string 363 pattern, output string
328 } 364 }
329 365
330 var quoteMetaTests = []QuoteMetaTest{ 366 var quoteMetaTests = []QuoteMetaTest{
331 QuoteMetaTest{``, ``}, 367 QuoteMetaTest{``, ``},
332 QuoteMetaTest{`foo`, `foo`}, 368 QuoteMetaTest{`foo`, `foo`},
333 QuoteMetaTest{`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[{\]} \\\|,<\.>/\?~`}, 369 QuoteMetaTest{`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[{\]} \\\|,<\.>/\?~`},
334 } 370 }
335 371
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 b.StopTimer() 539 b.StopTimer()
504 re, _ := Compile("^" + x) 540 re, _ := Compile("^" + x)
505 b.StartTimer() 541 b.StartTimer()
506 for i := 0; i < b.N; i++ { 542 for i := 0; i < b.N; i++ {
507 if !re.MatchString(x) { 543 if !re.MatchString(x) {
508 println("no match!") 544 println("no match!")
509 break 545 break
510 } 546 }
511 } 547 }
512 } 548 }
549
550 func BenchmarkReplaceAll(b *testing.B) {
551 x := "abcdefghijklmnopqrstuvwxyz"
552 b.StopTimer()
553 re, _ := Compile("[cjrw]")
554 b.StartTimer()
555 for i := 0; i < b.N; i++ {
556 re.ReplaceAllString(x, "")
557 }
558 }
559
560 func BenchmarkOldReplaceAll(b *testing.B) {
r 2010/03/07 00:02:09 you can delete from here to the end.
561 x := "abcdefghijklmnopqrstuvwxyz"
562 b.StopTimer()
563 re, _ := Compile("[cjrw]")
564 b.StartTimer()
565 for i := 0; i < b.N; i++ {
566 re.oldReplaceAllString(x, "")
567 }
568 }
569
570 func (re *Regexp) oldReplaceAllString(src, repl string) string {
571 lastMatchEnd := 0 // end position of the most recent match
572 searchPos := 0 // position where we next look for a match
573 buf := new(bytes.Buffer)
574 for searchPos <= len(src) {
575 a := re.doExecute(src, nil, searchPos)
576 if len(a) == 0 {
577 break // no more matches
578 }
579
580 // Copy the unmatched characters before this match.
581 io.WriteString(buf, src[lastMatchEnd:a[0]])
582
583 // Now insert a copy of the replacement string, but not for a
584 // match of the empty string immediately after another match.
585 // (Otherwise, we get double replacement for patterns that
586 // match both empty and nonempty strings.)
587 if a[1] > lastMatchEnd || a[0] == 0 {
588 io.WriteString(buf, repl)
589 }
590 lastMatchEnd = a[1]
591
592 // Advance past this match; always advance at least one characte r.
593 _, width := utf8.DecodeRuneInString(src[searchPos:])
594 if searchPos+width > a[1] {
595 searchPos += width
596 } else if searchPos+1 > a[1] {
597 // This clause is only needed at the end of the input
598 // string. In that case, DecodeRuneInString returns wid th=0.
599 searchPos++
600 } else {
601 searchPos = a[1]
602 }
603 }
604
605 // Copy the unmatched characters after the last match.
606 io.WriteString(buf, src[lastMatchEnd:])
607
608 return buf.String()
609 }
610
OLDNEW
« no previous file with comments | « no previous file | src/pkg/regexp/regexp.go » ('j') | no next file with comments »

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