Commit 0be1f647 authored by Kirill Smelkov's avatar Kirill Smelkov

Move string <-> []byte zero-copy conversion routines to https://lab.nexedi.com/kirr/go123/mem/

It is now

	mem.String(),	and
	mem.Bytes()
parent 3aedc246
......@@ -76,6 +76,7 @@ import (
"time"
"lab.nexedi.com/kirr/go123/exc"
"lab.nexedi.com/kirr/go123/mem"
"lab.nexedi.com/kirr/go123/myname"
"lab.nexedi.com/kirr/go123/xerr"
......@@ -131,7 +132,7 @@ func file_to_blob(g *git.Repository, path string) (Sha1, uint32) {
if st.Mode&syscall.S_IFMT == syscall.S_IFLNK {
__, err := os.Readlink(path)
blob_content = Bytes(__)
blob_content = mem.Bytes(__)
exc.Raiseif(err)
} else {
blob_content, err = ioutil.ReadFile(path)
......@@ -154,7 +155,7 @@ func blob_to_file(g *git.Repository, blob_sha1 Sha1, mode uint32, path string) {
exc.Raiseif(err)
if mode&syscall.S_IFMT == syscall.S_IFLNK {
err = os.Symlink(String(blob_content), path)
err = os.Symlink(mem.String(blob_content), path)
exc.Raiseif(err)
} else {
// NOTE mode is native - we cannot use ioutil.WriteFile() directly
......@@ -192,7 +193,7 @@ func obj_represent_as_commit(g *git.Repository, sha1 Sha1, obj_type string) Sha1
tag, tag_obj := xload_tag(g, sha1)
tagged_type = tag.tagged_type
tagged_sha1 = tag.tagged_sha1
obj_encoded += String(tag_obj.Data())
obj_encoded += mem.String(tag_obj.Data())
} else {
// for tree/blob we only care that object stays reachable
tagged_type = obj_type
......@@ -276,7 +277,7 @@ func obj_recreate_from_commit(g *git.Repository, commit_sha1 Sha1) Sha1 {
}
// re-create tag object
tag_sha1, err := WriteObject(g, Bytes(obj_raw), git.ObjectTag)
tag_sha1, err := WriteObject(g, mem.Bytes(obj_raw), git.ObjectTag)
exc.Raiseif(err)
// the original tagged object should be already in repository, because we
......
......@@ -21,6 +21,7 @@ import (
"strings"
"lab.nexedi.com/kirr/go123/exc"
"lab.nexedi.com/kirr/go123/mem"
)
// how/whether to redirect stdio of spawned process
......@@ -78,8 +79,8 @@ func _git(argv []string, ctx RunWith) (err error, stdout, stderr string) {
}
err = cmd.Run()
stdout = String(stdoutBuf.Bytes())
stderr = String(stderrBuf.Bytes())
stdout = mem.String(stdoutBuf.Bytes())
stderr = mem.String(stderrBuf.Bytes())
if !ctx.raw {
// prettify stdout (e.g. so that 'sha1\n' becomes 'sha1' and can be used directly
......
......@@ -22,6 +22,7 @@ import (
"time"
"lab.nexedi.com/kirr/go123/exc"
"lab.nexedi.com/kirr/go123/mem"
git "github.com/libgit2/git2go"
)
......@@ -100,7 +101,7 @@ func xload_tag(g *git.Repository, tag_sha1 Sha1) (tag *Tag, tag_obj *git.OdbObje
tag_obj, err := ReadObject(g, tag_sha1, git.ObjectTag)
exc.Raiseif(err)
tag, err = tag_parse(String(tag_obj.Data()))
tag, err = tag_parse(mem.String(tag_obj.Data()))
if err != nil {
exc.Raise(&TagLoadError{tag_sha1, err})
}
......@@ -226,7 +227,7 @@ func xcommit_tree2(g *git.Repository, tree Sha1, parents []Sha1, msg string, aut
commit += fmt.Sprintf("committer %s\n", &committer)
commit += fmt.Sprintf("\n%s", msg)
sha1, err := WriteObject(g, Bytes(commit), git.ObjectCommit)
sha1, err := WriteObject(g, mem.Bytes(commit), git.ObjectCommit)
exc.Raiseif(err)
return sha1
......
......@@ -18,6 +18,8 @@ import (
"encoding/hex"
"fmt"
"lab.nexedi.com/kirr/go123/mem"
git "github.com/libgit2/git2go"
)
......@@ -45,7 +47,7 @@ func Sha1Parse(sha1str string) (Sha1, error) {
if hex.DecodedLen(len(sha1str)) != SHA1_RAWSIZE {
return Sha1{}, fmt.Errorf("sha1parse: %q invalid", sha1str)
}
_, err := hex.Decode(sha1.sha1[:], Bytes(sha1str))
_, err := hex.Decode(sha1.sha1[:], mem.Bytes(sha1str))
if err != nil {
return Sha1{}, fmt.Errorf("sha1parse: %q invalid: %s", sha1str, err)
}
......@@ -68,7 +70,7 @@ func (sha1 *Sha1) Scan(s fmt.ScanState, ch rune) error {
return err
}
*sha1, err = Sha1Parse(String(tok))
*sha1, err = Sha1Parse(mem.String(tok))
return err
}
......
......@@ -17,32 +17,13 @@ import (
"encoding/hex"
"fmt"
"os"
"reflect"
"strings"
"syscall"
"unicode"
"unicode/utf8"
"unsafe"
)
// string -> []byte without copying
func Bytes(s string) []byte {
var b []byte
bp := (*reflect.SliceHeader)(unsafe.Pointer(&b))
bp.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
bp.Cap = len(s)
bp.Len = len(s)
return b
}
// []byte -> string without copying
func String(b []byte) string {
var s string
sp := (*reflect.StringHeader)(unsafe.Pointer(&s))
sp.Data = (*reflect.SliceHeader)(unsafe.Pointer(&b)).Data
sp.Len = len(b)
return s
}
"lab.nexedi.com/kirr/go123/mem"
)
// split string into lines. The last line, if it is empty, is omitted from the result
// (rationale is: string.Split("hello\nworld\n", "\n") -> ["hello", "world", ""])
......@@ -212,7 +193,7 @@ func path_refunescape(s string) (string, error) {
}
out = append(out, c)
}
return String(out), nil
return mem.String(out), nil
}
type EscapeError string
......
......@@ -18,21 +18,6 @@ import (
"testing"
)
// check that String() and Bytes() create correct objects which alias original object memory
func TestStringBytes(t *testing.T) {
s := "Hello"
b := []byte(s)
s1 := String(b)
b1 := Bytes(s1)
if s1 != s { t.Error("string -> []byte -> String != Identity") }
if !reflect.DeepEqual(b1, b) { t.Error("[]byte -> String -> Bytes != Identity") }
b[0] = 'I'
if s != "Hello" { t.Error("string -> []byte not copied") }
if s1 != "Iello" { t.Error("[]byte -> String not aliased") }
if !reflect.DeepEqual(b1, b) { t.Error("string -> Bytes not aliased") }
}
func TestSplitLines(t *testing.T) {
var tests = []struct { input, sep string; output []string } {
{"", "\n", []string{}},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment