]> Cypherpunks repositories - gostls13.git/commitdiff
bytes, strings: add LastIndexByte
authorDmitry Vyukov <dvyukov@google.com>
Wed, 29 Apr 2015 17:45:55 +0000 (20:45 +0300)
committerDmitry Vyukov <dvyukov@google.com>
Thu, 30 Apr 2015 07:13:18 +0000 (07:13 +0000)
Currently the packages have the following index functions:

func Index(s, sep []byte) int
func IndexAny(s []byte, chars string) int
func IndexByte(s []byte, c byte) int
func IndexFunc(s []byte, f func(r rune) bool) int
func IndexRune(s []byte, r rune) int

func LastIndex(s, sep []byte) int
func LastIndexAny(s []byte, chars string) int
func LastIndexFunc(s []byte, f func(r rune) bool) int

Searching for the last occurrence of a byte is quite common
for string parsing algorithms (e.g. find the last paren on a line).
Also addition of LastIndexByte makes the set more orthogonal.

Change-Id: Ida168849acacf8e78dd70c1354bef9eac5effafe
Reviewed-on: https://go-review.googlesource.com/9500
Reviewed-by: Rob Pike <r@golang.org>
src/bytes/bytes.go
src/bytes/bytes_test.go
src/strings/strings.go
src/strings/strings_test.go

index 60de451504038875da0466a6b600b00f3d97af85..b86824087e5356405855d4581aeb728fa50f8ae1 100644 (file)
@@ -138,6 +138,16 @@ func LastIndex(s, sep []byte) int {
        return -1
 }
 
+// LastIndexByte returns the index of the last instance of c in s, or -1 if c is not present in s.
+func LastIndexByte(s []byte, c byte) int {
+       for i := len(s) - 1; i >= 0; i-- {
+               if s[i] == c {
+                       return i
+               }
+       }
+       return -1
+}
+
 // IndexRune interprets s as a sequence of UTF-8-encoded Unicode code points.
 // It returns the byte index of the first occurrence in s of the given rune.
 // It returns -1 if rune is not present in s.
index 980c41d754ddfbcbb135daa0adf98bb940848bc1..6245e481805779e8665965053bde7cae4ce31e78 100644 (file)
@@ -265,6 +265,23 @@ func TestIndexByte(t *testing.T) {
        }
 }
 
+func TestLastIndexByte(t *testing.T) {
+       testCases := []BinOpTest{
+               {"", "q", -1},
+               {"abcdef", "q", -1},
+               {"abcdefabcdef", "a", len("abcdef")},      // something in the middle
+               {"abcdefabcdef", "f", len("abcdefabcde")}, // last byte
+               {"zabcdefabcdef", "z", 0},                 // first byte
+               {"a☺b☻c☹d", "b", len("a☺")},               // non-ascii
+       }
+       for _, test := range testCases {
+               actual := LastIndexByte([]byte(test.a), test.b[0])
+               if actual != test.i {
+                       t.Errorf("LastIndexByte(%q,%c) = %v; want %v", test.a, test.b[0], actual, test.i)
+               }
+       }
+}
+
 // test a larger buffer with different sizes and alignments
 func TestIndexByteBig(t *testing.T) {
        var n = 1024
index c6085f51d590640f147b84b447e55211efee19cb..7b8a6b536b5d85f060f48433bd68b416ac15da39 100644 (file)
@@ -271,6 +271,16 @@ func LastIndexAny(s, chars string) int {
        return -1
 }
 
+// LastIndexByte returns the index of the last instance of c in s, or -1 if c is not present in s.
+func LastIndexByte(s string, c byte) int {
+       for i := len(s) - 1; i >= 0; i-- {
+               if s[i] == c {
+                       return i
+               }
+       }
+       return -1
+}
+
 // Generic split: splits after each instance of sep,
 // including sepSave bytes of sep in the subarrays.
 func genSplit(s, sep string, sepSave, n int) []string {
index ee0c260753198fe99dfee6a30e8e76551afdeee3..4e21deaecde12078605f72f02fee3b0517df6989 100644 (file)
@@ -120,6 +120,23 @@ func TestLastIndex(t *testing.T)    { runIndexTests(t, LastIndex, "LastIndex", l
 func TestIndexAny(t *testing.T)     { runIndexTests(t, IndexAny, "IndexAny", indexAnyTests) }
 func TestLastIndexAny(t *testing.T) { runIndexTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests) }
 
+func TestLastIndexByte(t *testing.T) {
+       testCases := []IndexTest{
+               {"", "q", -1},
+               {"abcdef", "q", -1},
+               {"abcdefabcdef", "a", len("abcdef")},      // something in the middle
+               {"abcdefabcdef", "f", len("abcdefabcde")}, // last byte
+               {"zabcdefabcdef", "z", 0},                 // first byte
+               {"a☺b☻c☹d", "b", len("a☺")},               // non-ascii
+       }
+       for _, test := range testCases {
+               actual := LastIndexByte(test.s, test.sep[0])
+               if actual != test.out {
+                       t.Errorf("LastIndexByte(%q,%c) = %v; want %v", test.s, test.sep[0], actual, test.out)
+               }
+       }
+}
+
 var indexRuneTests = []struct {
        s    string
        rune rune