Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
Showing
3 changed files
with
352 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
} | ||
} |