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 ( ...@@ -76,6 +76,7 @@ import (
"time" "time"
"lab.nexedi.com/kirr/go123/exc" "lab.nexedi.com/kirr/go123/exc"
"lab.nexedi.com/kirr/go123/mem"
"lab.nexedi.com/kirr/go123/myname" "lab.nexedi.com/kirr/go123/myname"
"lab.nexedi.com/kirr/go123/xerr" "lab.nexedi.com/kirr/go123/xerr"
...@@ -131,7 +132,7 @@ func file_to_blob(g *git.Repository, path string) (Sha1, uint32) { ...@@ -131,7 +132,7 @@ func file_to_blob(g *git.Repository, path string) (Sha1, uint32) {
if st.Mode&syscall.S_IFMT == syscall.S_IFLNK { if st.Mode&syscall.S_IFMT == syscall.S_IFLNK {
__, err := os.Readlink(path) __, err := os.Readlink(path)
blob_content = Bytes(__) blob_content = mem.Bytes(__)
exc.Raiseif(err) exc.Raiseif(err)
} else { } else {
blob_content, err = ioutil.ReadFile(path) blob_content, err = ioutil.ReadFile(path)
...@@ -154,7 +155,7 @@ func blob_to_file(g *git.Repository, blob_sha1 Sha1, mode uint32, path string) { ...@@ -154,7 +155,7 @@ func blob_to_file(g *git.Repository, blob_sha1 Sha1, mode uint32, path string) {
exc.Raiseif(err) exc.Raiseif(err)
if mode&syscall.S_IFMT == syscall.S_IFLNK { 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) exc.Raiseif(err)
} else { } else {
// NOTE mode is native - we cannot use ioutil.WriteFile() directly // 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 ...@@ -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) tag, tag_obj := xload_tag(g, sha1)
tagged_type = tag.tagged_type tagged_type = tag.tagged_type
tagged_sha1 = tag.tagged_sha1 tagged_sha1 = tag.tagged_sha1
obj_encoded += String(tag_obj.Data()) obj_encoded += mem.String(tag_obj.Data())
} else { } else {
// for tree/blob we only care that object stays reachable // for tree/blob we only care that object stays reachable
tagged_type = obj_type tagged_type = obj_type
...@@ -276,7 +277,7 @@ func obj_recreate_from_commit(g *git.Repository, commit_sha1 Sha1) Sha1 { ...@@ -276,7 +277,7 @@ func obj_recreate_from_commit(g *git.Repository, commit_sha1 Sha1) Sha1 {
} }
// re-create tag object // 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) exc.Raiseif(err)
// the original tagged object should be already in repository, because we // the original tagged object should be already in repository, because we
......
...@@ -21,6 +21,7 @@ import ( ...@@ -21,6 +21,7 @@ import (
"strings" "strings"
"lab.nexedi.com/kirr/go123/exc" "lab.nexedi.com/kirr/go123/exc"
"lab.nexedi.com/kirr/go123/mem"
) )
// how/whether to redirect stdio of spawned process // how/whether to redirect stdio of spawned process
...@@ -78,8 +79,8 @@ func _git(argv []string, ctx RunWith) (err error, stdout, stderr string) { ...@@ -78,8 +79,8 @@ func _git(argv []string, ctx RunWith) (err error, stdout, stderr string) {
} }
err = cmd.Run() err = cmd.Run()
stdout = String(stdoutBuf.Bytes()) stdout = mem.String(stdoutBuf.Bytes())
stderr = String(stderrBuf.Bytes()) stderr = mem.String(stderrBuf.Bytes())
if !ctx.raw { if !ctx.raw {
// prettify stdout (e.g. so that 'sha1\n' becomes 'sha1' and can be used directly // prettify stdout (e.g. so that 'sha1\n' becomes 'sha1' and can be used directly
......
...@@ -22,6 +22,7 @@ import ( ...@@ -22,6 +22,7 @@ import (
"time" "time"
"lab.nexedi.com/kirr/go123/exc" "lab.nexedi.com/kirr/go123/exc"
"lab.nexedi.com/kirr/go123/mem"
git "github.com/libgit2/git2go" git "github.com/libgit2/git2go"
) )
...@@ -100,7 +101,7 @@ func xload_tag(g *git.Repository, tag_sha1 Sha1) (tag *Tag, tag_obj *git.OdbObje ...@@ -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) tag_obj, err := ReadObject(g, tag_sha1, git.ObjectTag)
exc.Raiseif(err) exc.Raiseif(err)
tag, err = tag_parse(String(tag_obj.Data())) tag, err = tag_parse(mem.String(tag_obj.Data()))
if err != nil { if err != nil {
exc.Raise(&TagLoadError{tag_sha1, err}) exc.Raise(&TagLoadError{tag_sha1, err})
} }
...@@ -226,7 +227,7 @@ func xcommit_tree2(g *git.Repository, tree Sha1, parents []Sha1, msg string, aut ...@@ -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("committer %s\n", &committer)
commit += fmt.Sprintf("\n%s", msg) 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) exc.Raiseif(err)
return sha1 return sha1
......
...@@ -18,6 +18,8 @@ import ( ...@@ -18,6 +18,8 @@ import (
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"lab.nexedi.com/kirr/go123/mem"
git "github.com/libgit2/git2go" git "github.com/libgit2/git2go"
) )
...@@ -45,7 +47,7 @@ func Sha1Parse(sha1str string) (Sha1, error) { ...@@ -45,7 +47,7 @@ func Sha1Parse(sha1str string) (Sha1, error) {
if hex.DecodedLen(len(sha1str)) != SHA1_RAWSIZE { if hex.DecodedLen(len(sha1str)) != SHA1_RAWSIZE {
return Sha1{}, fmt.Errorf("sha1parse: %q invalid", sha1str) 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 { if err != nil {
return Sha1{}, fmt.Errorf("sha1parse: %q invalid: %s", sha1str, err) return Sha1{}, fmt.Errorf("sha1parse: %q invalid: %s", sha1str, err)
} }
...@@ -68,7 +70,7 @@ func (sha1 *Sha1) Scan(s fmt.ScanState, ch rune) error { ...@@ -68,7 +70,7 @@ func (sha1 *Sha1) Scan(s fmt.ScanState, ch rune) error {
return err return err
} }
*sha1, err = Sha1Parse(String(tok)) *sha1, err = Sha1Parse(mem.String(tok))
return err return err
} }
......
...@@ -17,32 +17,13 @@ import ( ...@@ -17,32 +17,13 @@ import (
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"os" "os"
"reflect"
"strings" "strings"
"syscall" "syscall"
"unicode" "unicode"
"unicode/utf8" "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 "lab.nexedi.com/kirr/go123/mem"
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
}
// split string into lines. The last line, if it is empty, is omitted from the result // 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", ""]) // (rationale is: string.Split("hello\nworld\n", "\n") -> ["hello", "world", ""])
...@@ -212,7 +193,7 @@ func path_refunescape(s string) (string, error) { ...@@ -212,7 +193,7 @@ func path_refunescape(s string) (string, error) {
} }
out = append(out, c) out = append(out, c)
} }
return String(out), nil return mem.String(out), nil
} }
type EscapeError string type EscapeError string
......
...@@ -18,21 +18,6 @@ import ( ...@@ -18,21 +18,6 @@ import (
"testing" "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) { func TestSplitLines(t *testing.T) {
var tests = []struct { input, sep string; output []string } { var tests = []struct { input, sep string; output []string } {
{"", "\n", []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