mirror of
https://github.com/golang/go
synced 2024-11-18 08:44:43 -07:00
add a bytes package analogous to the strings package.
also has Equal and Compare R=rsc DELTA=348 (348 added, 0 deleted, 0 changed) OCL=29892 CL=29894
This commit is contained in:
parent
bd8495f973
commit
78933226f1
68
src/lib/bytes/Makefile
Normal file
68
src/lib/bytes/Makefile
Normal file
@ -0,0 +1,68 @@
|
||||
# Copyright 2009 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
# DO NOT EDIT. Automatically generated by gobuild.
|
||||
# gobuild -m >Makefile
|
||||
|
||||
D=
|
||||
|
||||
O_arm=5
|
||||
O_amd64=6
|
||||
O_386=8
|
||||
OS=568vq
|
||||
|
||||
O=$(O_$(GOARCH))
|
||||
GC=$(O)g -I_obj
|
||||
CC=$(O)c -FVw
|
||||
AS=$(O)a
|
||||
AR=6ar
|
||||
|
||||
default: packages
|
||||
|
||||
clean:
|
||||
rm -rf *.[$(OS)] *.a [$(OS)].out _obj
|
||||
|
||||
test: packages
|
||||
gotest
|
||||
|
||||
coverage: packages
|
||||
gotest
|
||||
6cov -g `pwd` | grep -v '_test\.go:'
|
||||
|
||||
%.$O: %.go
|
||||
$(GC) $*.go
|
||||
|
||||
%.$O: %.c
|
||||
$(CC) $*.c
|
||||
|
||||
%.$O: %.s
|
||||
$(AS) $*.s
|
||||
|
||||
O1=\
|
||||
bytes.$O\
|
||||
|
||||
|
||||
phases: a1
|
||||
_obj$D/bytes.a: phases
|
||||
|
||||
a1: $(O1)
|
||||
$(AR) grc _obj$D/bytes.a bytes.$O
|
||||
rm -f $(O1)
|
||||
|
||||
|
||||
newpkg: clean
|
||||
mkdir -p _obj$D
|
||||
$(AR) grc _obj$D/bytes.a
|
||||
|
||||
$(O1): newpkg
|
||||
$(O2): a1
|
||||
|
||||
nuke: clean
|
||||
rm -f $(GOROOT)/pkg$D/bytes.a
|
||||
|
||||
packages: _obj$D/bytes.a
|
||||
|
||||
install: packages
|
||||
test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg$D
|
||||
cp _obj$D/bytes.a $(GOROOT)/pkg$D/bytes.a
|
154
src/lib/bytes/bytes.go
Normal file
154
src/lib/bytes/bytes.go
Normal file
@ -0,0 +1,154 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// A package of simple functions to manipulate arrays of bytes.
|
||||
// Analagous to the facilities of the strings package.
|
||||
package bytes
|
||||
|
||||
import "utf8"
|
||||
|
||||
// Compare returns an integer comparing the two byte arrays lexicographically.
|
||||
// The result will be 0 if a==b, -1 if a < b, and +1 if a > b
|
||||
func Compare(a, b []byte) int {
|
||||
for i := 0; i < len(a) && i < len(b); i++ {
|
||||
switch {
|
||||
case a[i] > b[i]:
|
||||
return 1
|
||||
case a[i] < b[i]:
|
||||
return -1
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case len(a) < len(b):
|
||||
return -1
|
||||
case len(a) > len(b):
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Equal returns a boolean reporting whether a == b.
|
||||
func Equal(a, b []byte) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(a); i++ {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Explode splits s into an array of UTF-8 sequences, one per Unicode character (still arrays of bytes).
|
||||
// Invalid UTF-8 sequences become correct encodings of U+FFF8.
|
||||
func Explode(s []byte) [][]byte {
|
||||
a := make([][]byte, utf8.RuneCount(s));
|
||||
var size, rune int;
|
||||
i := 0;
|
||||
for len(s) > 0 {
|
||||
rune, size = utf8.DecodeRune(s);
|
||||
a[i] = s[0:size];
|
||||
s = s[size:len(s)];
|
||||
i++;
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// Count counts the number of non-overlapping instances of sep in s.
|
||||
func Count(s, sep []byte) int {
|
||||
if len(sep) == 0 {
|
||||
return utf8.RuneCount(s)+1
|
||||
}
|
||||
c := sep[0];
|
||||
n := 0;
|
||||
for i := 0; i+len(sep) <= len(s); i++ {
|
||||
if s[i] == c && (len(sep) == 1 || Equal(s[i:i+len(sep)], sep)) {
|
||||
n++;
|
||||
i += len(sep)-1
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
|
||||
func Index(s, sep []byte) int {
|
||||
n := len(sep);
|
||||
if n == 0 {
|
||||
return 0
|
||||
}
|
||||
c := sep[0];
|
||||
for i := 0; i+n <= len(s); i++ {
|
||||
if s[i] == c && (n == 1 || Equal(s[i:i+n], sep)) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// Split returns the array representing the subarrays of s separated by sep. Adjacent
|
||||
// occurrences of sep produce empty subarrays. If sep is empty, it is the same as Explode.
|
||||
func Split(s, sep []byte) [][]byte {
|
||||
if len(sep) == 0 {
|
||||
return Explode(s)
|
||||
}
|
||||
c := sep[0];
|
||||
start := 0;
|
||||
n := Count(s, sep)+1;
|
||||
a := make([][]byte, n);
|
||||
na := 0;
|
||||
for i := 0; i+len(sep) <= len(s); i++ {
|
||||
if s[i] == c && (len(sep) == 1 || Equal(s[i:i+len(sep)], sep)) {
|
||||
a[na] = s[start:i];
|
||||
na++;
|
||||
start = i+len(sep);
|
||||
i += len(sep)-1
|
||||
}
|
||||
}
|
||||
a[na] = s[start:len(s)];
|
||||
return a
|
||||
}
|
||||
|
||||
// Join concatenates the elements of a to create a single byte array. The separator
|
||||
// sep is placed between elements in the resulting array.
|
||||
func Join(a [][]byte, sep []byte) []byte {
|
||||
if len(a) == 0 {
|
||||
return []byte{}
|
||||
}
|
||||
if len(a) == 1 {
|
||||
return a[0]
|
||||
}
|
||||
n := len(sep) * (len(a)-1);
|
||||
for i := 0; i < len(a); i++ {
|
||||
n += len(a[i])
|
||||
}
|
||||
|
||||
b := make([]byte, n);
|
||||
bp := 0;
|
||||
for i := 0; i < len(a); i++ {
|
||||
s := a[i];
|
||||
for j := 0; j < len(s); j++ {
|
||||
b[bp] = s[j];
|
||||
bp++
|
||||
}
|
||||
if i + 1 < len(a) {
|
||||
s = sep;
|
||||
for j := 0; j < len(s); j++ {
|
||||
b[bp] = s[j];
|
||||
bp++
|
||||
}
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// HasPrefix tests whether the byte array s begins with prefix.
|
||||
func HasPrefix(s, prefix []byte) bool {
|
||||
return len(s) >= len(prefix) && Equal(s[0:len(prefix)], prefix)
|
||||
}
|
||||
|
||||
// HasSuffix tests whether the byte array s ends with suffix.
|
||||
func HasSuffix(s, suffix []byte) bool {
|
||||
return len(s) >= len(suffix) && Equal(s[len(s)-len(suffix):len(s)], suffix)
|
||||
}
|
130
src/lib/bytes/bytes_test.go
Normal file
130
src/lib/bytes/bytes_test.go
Normal file
@ -0,0 +1,130 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bytes
|
||||
|
||||
import (
|
||||
"bytes";
|
||||
"io";
|
||||
"testing";
|
||||
)
|
||||
|
||||
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 arrayOfString(a [][]byte) []string {
|
||||
result := make([]string, len(a));
|
||||
for j := 0; j < len(a); j++ {
|
||||
result[j] = string(a[j])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// For ease of reading, the test cases use strings that are converted to byte
|
||||
// arrays before invoking the functions.
|
||||
|
||||
var abcd = "abcd"
|
||||
var faces = "☺☻☹"
|
||||
var commas = "1,2,3,4"
|
||||
var dots = "1....2....3....4"
|
||||
|
||||
type CompareTest struct {
|
||||
a string;
|
||||
b string;
|
||||
cmp int;
|
||||
}
|
||||
var comparetests = []CompareTest {
|
||||
CompareTest{ "", "", 0 },
|
||||
CompareTest{ "a", "", 1 },
|
||||
CompareTest{ "", "a", -1 },
|
||||
CompareTest{ "abc", "abc", 0 },
|
||||
CompareTest{ "ab", "abc", -1 },
|
||||
CompareTest{ "abc", "ab", 1 },
|
||||
CompareTest{ "x", "ab", 1 },
|
||||
CompareTest{ "ab", "x", -1 },
|
||||
CompareTest{ "x", "a", 1 },
|
||||
CompareTest{ "b", "x", -1 },
|
||||
}
|
||||
|
||||
func TestCompare(t *testing.T) {
|
||||
for i := 0; i < len(comparetests); i++ {
|
||||
tt := comparetests[i];
|
||||
a := io.StringBytes(tt.a);
|
||||
b := io.StringBytes(tt.b);
|
||||
cmp := Compare(a, b);
|
||||
eql := Equal(a, b);
|
||||
if cmp != tt.cmp {
|
||||
t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp);
|
||||
}
|
||||
if eql != (tt.cmp==0) {
|
||||
t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type ExplodeTest struct {
|
||||
s string;
|
||||
a []string;
|
||||
}
|
||||
var explodetests = []ExplodeTest {
|
||||
ExplodeTest{ abcd, []string{"a", "b", "c", "d"} },
|
||||
ExplodeTest{ faces, []string{"☺", "☻", "☹" } },
|
||||
}
|
||||
func TestExplode(t *testing.T) {
|
||||
for i := 0; i < len(explodetests); i++ {
|
||||
tt := explodetests[i];
|
||||
a := Explode(io.StringBytes(tt.s));
|
||||
result := arrayOfString(a);
|
||||
if !eq(result, tt.a) {
|
||||
t.Errorf(`Explode("%s") = %v; want %v`, tt.s, result, tt.a);
|
||||
continue;
|
||||
}
|
||||
s := Join(a, []byte{});
|
||||
if string(s) != tt.s {
|
||||
t.Errorf(`Join(Explode("%s"), "") = "%s"`, tt.s, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type SplitTest struct {
|
||||
s string;
|
||||
sep string;
|
||||
a []string;
|
||||
}
|
||||
var splittests = []SplitTest {
|
||||
SplitTest{ abcd, "a", []string{"", "bcd"} },
|
||||
SplitTest{ abcd, "z", []string{"abcd"} },
|
||||
SplitTest{ abcd, "", []string{"a", "b", "c", "d"} },
|
||||
SplitTest{ commas, ",", []string{"1", "2", "3", "4"} },
|
||||
SplitTest{ dots, "...", []string{"1", ".2", ".3", ".4"} },
|
||||
SplitTest{ faces, "☹", []string{"☺☻", ""} },
|
||||
SplitTest{ faces, "~", []string{faces} },
|
||||
SplitTest{ faces, "", []string{"☺", "☻", "☹"} },
|
||||
}
|
||||
func TestSplit(t *testing.T) {
|
||||
for i := 0; i < len(splittests); i++ {
|
||||
tt := splittests[i];
|
||||
a := Split(io.StringBytes(tt.s), io.StringBytes(tt.sep));
|
||||
result := arrayOfString(a);
|
||||
if !eq(result, tt.a) {
|
||||
t.Errorf(`Split("%s", "%s") = %v; want %v`, tt.s, tt.sep, result, tt.a);
|
||||
continue;
|
||||
}
|
||||
s := Join(a, io.StringBytes(tt.sep));
|
||||
if string(s) != tt.s {
|
||||
t.Errorf(`Join(Split("%s", "%s"), "%s") = "%s"`, tt.s, tt.sep, tt.sep, s);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user