提交 14a0ac06 编写于 作者: chai2010's avatar chai2010

bytes 包更多函数和测试

上级 431facd2
......@@ -32,4 +32,24 @@ func bytealg_IndexString(a, b: string) => int {
// See the bytes.Index implementation for details.
func bytealg_Cutover(n: int) => int {
panic("unimplemented")
}
\ No newline at end of file
}
func bytealg_Count(b: []byte, c: byte) => int {
n := 0
for _, x := range b {
if x == c {
n++
}
}
return n
}
func bytealg_CountString(s: string, c: byte) => int {
n := 0
for i := 0; i < len(s); i++ {
if s[i] == c {
n++
}
}
return n
}
......@@ -261,3 +261,113 @@ func IndexRune(s: []byte, r: rune) => int {
return Index(s, b[:n])
}
}
// Count counts the number of non-overlapping instances of sep in s.
// If sep is an empty slice, Count returns 1 + the number of UTF-8-encoded code points in s.
func Count(s, sep: []byte) => int {
// special case
if len(sep) == 0 {
return utf8.RuneCount(s) + 1
}
if len(sep) == 1 {
return bytealg_Count(s, sep[0])
}
n := 0
for {
i := Index(s, sep)
if i == -1 {
return n
}
n++
s = s[i+len(sep):]
}
}
// SplitN slices s into subslices separated by sep and returns a slice of
// the subslices between those separators.
// If sep is empty, SplitN splits after each UTF-8 sequence.
// The count determines the number of subslices to return:
// n > 0: at most n subslices; the last subslice will be the unsplit remainder.
// n == 0: the result is nil (zero subslices)
// n < 0: all subslices
func SplitN(s, sep: []byte, n: int) => [][]byte {
return genSplit(s, sep, 0, n)
}
// Generic split: splits after each instance of sep,
// including sepSave bytes of sep in the subslices.
func genSplit(s, sep: []byte, sepSave, n: int) => [][]byte {
if n == 0 {
return nil
}
if len(sep) == 0 {
return explode(s, n)
}
if n < 0 {
n = Count(s, sep) + 1
}
a := make([][]byte, n)
n--
i := 0
for i < n {
m := Index(s, sep)
if m < 0 {
break
}
a[i] = s[: m+sepSave : m+sepSave]
s = s[m+len(sep):]
i++
}
a[i] = s
return a[:i+1]
}
// explode splits s into a slice of UTF-8 sequences, one per Unicode code point (still slices of bytes),
// up to a maximum of n byte slices. Invalid UTF-8 sequences are chopped into individual bytes.
func explode(s: []byte, n: int) => [][]byte {
if n <= 0 {
n = len(s)
}
a := make([][]byte, n)
size: int
na := 0
for len(s) > 0 {
if na+1 >= n {
a[na] = s
na++
break
}
_, size = utf8.DecodeRune(s)
a[na] = s[0:size:size]
s = s[size:]
na++
}
return a[0:na]
}
// Join concatenates the elements of s to create a new byte slice. The separator
// sep is placed between elements in the resulting slice.
func Join(s: [][]byte, sep: []byte) => []byte {
if len(s) == 0 {
return []byte{}
}
if len(s) == 1 {
// Just return a copy.
return append([]byte(nil), s[0]...)
}
n := len(sep) * (len(s) - 1)
for _, v := range s {
n += len(v)
}
b := make([]byte, n)
bp := copy(b, s[0])
for _, v := range s[1:] {
bp += copy(b[bp:], sep)
bp += copy(b[bp:], v)
}
return b
}
......@@ -321,6 +321,170 @@ func TestIndexRune {
}
}
// test count of a single byte across page offsets
func TestCountByte {
b := make([]byte, 5015) // bigger than a page
windows := []int{1, 2, 3, 4, 15, 16, 17, 31, 32, 33, 63, 64, 65, 128}
testCountWindow := func(i, window: int) {
for j := 0; j < window; j++ {
b[i+j] = byte(100)
p := Count(b[i:i+window], []byte{100})
if p != j+1 {
assert(false)
//t.Errorf("TestCountByte.Count(%q, 100) = %d", b[i:i+window], p)
}
}
}
maxWnd := windows[len(windows)-1]
for i := 0; i <= 2*maxWnd; i++ {
for _, window := range windows {
if window > len(b[i:]) {
window = len(b[i:])
}
testCountWindow(i, window)
for j := 0; j < window; j++ {
b[i+j] = byte(0)
}
}
}
for i := 4096 - (maxWnd + 1); i < len(b); i++ {
for _, window := range windows {
if window > len(b[i:]) {
window = len(b[i:])
}
testCountWindow(i, window)
for j := 0; j < window; j++ {
b[i+j] = byte(0)
}
}
}
}
// Make sure we don't count bytes outside our window
func TestCountByteNoMatch {
b := make([]byte, 5015)
windows := []int{1, 2, 3, 4, 15, 16, 17, 31, 32, 33, 63, 64, 65, 128}
for i := 0; i <= len(b); i++ {
for _, window := range windows {
if window > len(b[i:]) {
window = len(b[i:])
}
// Fill the window with non-match
for j := 0; j < window; j++ {
b[i+j] = byte(100)
}
// Try to find something that doesn't exist
p := Count(b[i:i+window], []byte{0})
if p != 0 {
assert(false)
//t.Errorf("TestCountByteNoMatch(%q, 0) = %d", b[i:i+window], p)
}
for j := 0; j < window; j++ {
b[i+j] = byte(0)
}
}
}
}
type SplitTest struct {
s: string
sep: string
n: int
a: []string
}
const abcd = "abcd"
const faces = "☺☻☹"
const commas = "1,2,3,4"
const dots = "1....2....3....4"
global splittests = []SplitTest{
{"", "", -1, []string{}},
{abcd, "a", 0, nil},
{abcd, "", 2, []string{"a", "bcd"}},
{abcd, "a", -1, []string{"", "bcd"}},
{abcd, "z", -1, []string{"abcd"}},
{abcd, "", -1, []string{"a", "b", "c", "d"}},
{commas, ",", -1, []string{"1", "2", "3", "4"}},
{dots, "...", -1, []string{"1", ".2", ".3", ".4"}},
{faces, "☹", -1, []string{"☺☻", ""}},
{faces, "~", -1, []string{faces}},
{faces, "", -1, []string{"☺", "☻", "☹"}},
{"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}},
{"1 2", " ", 3, []string{"1", "2"}},
{"123", "", 2, []string{"1", "23"}},
{"123", "", 17, []string{"1", "2", "3"}},
}
func TestSplit {
for _, tt := range splittests {
a := SplitN([]byte(tt.s), []byte(tt.sep), tt.n)
// Appending to the results should not change future results.
x: []byte
for _, v := range a {
x = append(v, 'z')
}
result := sliceOfString(a)
if !eq(result, tt.a) {
print("result:[")
for i, x := range result {
if i > 0 {
print(", ")
}
print(x)
}
println("]")
print("tt.a:[")
for i, x := range tt.a {
if i > 0 {
print(", ")
}
print(x)
}
println("]")
assert(false)
//t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a)
continue
}
if tt.n == 0 || len(a) == 0 {
continue
}
if want := tt.a[len(tt.a)-1] + "z"; string(x) != want {
println("x:", string(x))
println("want:", want)
assert(false)
//t.Errorf("last appended result was %s; want %s", x, want)
}
s := Join(a, []byte(tt.sep))
if string(s) != tt.s {
assert(false)
//t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
}
if tt.n < 0 {
//b := Split([]byte(tt.s), []byte(tt.sep))
//if !reflect.DeepEqual(a, b) {
assert(false)
//t.Errorf("Split disagrees withSplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a)
//}
}
if len(a) > 0 {
in, out := a[0], s
if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] {
assert(false)
//t.Errorf("Join(%#v, %q) didn't copy", a, tt.sep)
}
}
}
}
func TestEqualFold {
for _, tt := range EqualFoldTests {
if out := EqualFold([]byte(tt.s), []byte(tt.t)); out != tt.out {
......@@ -345,3 +509,22 @@ global EqualFoldTests = []struct {
{"abc", "XYZ", false},
{"abcdefghijk", "abcdefghijX", false},
}
func eq(a, b: []string) => bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
func sliceOfString(s: [][]byte) => []string {
result := make([]string, len(s))
for i, v := range s {
result[i] = string(v)
}
return result
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册