Commits

Sebastien Binet  committed 745dc66

fold breader into Buffer

  • Participants
  • Parent commits e4811f3

Comments (0)

Files changed (8)

File pkg/groot/buffer.go

 )
 
 type Buffer struct {
-	order  binary.ByteOrder
-	buffer []byte
-	pos    int
-	klen   uint32 // to compute refs (used in read_class, read_object)
+	order binary.ByteOrder // byte order of underlying data source
+	data  []byte           // data source
+	buf   *bytes.Buffer    // buffer for more efficient i/o from r
+	klen  uint32           // to compute refs (used in read_class, read_object)
 }
 
-func NewBuffer(buf []byte, order binary.ByteOrder, klen uint32) (b *Buffer, err error) {
+func NewBuffer(data []byte, order binary.ByteOrder, klen uint32) (b *Buffer, err error) {
 	b = &Buffer{
-		order:  order,
-		buffer: buf[:],
-		pos:    0,
-		klen:   klen,
+		order: order,
+		data:  data,
+		klen:  klen,
 	}
-	return b, err
+	b.buf = bytes.NewBuffer(b.data[:])
+	return
 }
 
-func NewBufferFromKey(k Key) (b *Buffer, err error) {
+func NewBufferFromKey(k *Key) (b *Buffer, err error) {
 	buf, err := k.Buffer()
 	if err != nil {
 		return
 	}
-	b = &Buffer{
-		order: k.file.order,
-		buffer: buf,
-		pos: 0,
-		klen: uint32(k.keysz),
+	return NewBuffer(buf, k.file.order, uint32(k.keysz))
+}
+
+func (b *Buffer) Bytes() []byte {
+	return b.buf.Bytes()
+}
+
+func (b *Buffer) clone() *Buffer {
+	bb, err := NewBuffer(b.buf.Bytes(), b.order, b.klen)
+	if err != nil {
+		return nil
+	}
+	return bb
+}
+
+func (b *Buffer) read_nbytes(nbytes int) (o []byte) {
+	o = make([]byte, nbytes)
+	err := binary.Read(b.buf, b.order, o)
+	if err != nil {
+		panic(err)
 	}
 	return
 }
 
-func (b *Buffer) Buffer() []byte {
-	return b.buffer[:]
-}
-
-func (b *Buffer) breader() breader {
-	return breader{b.order}
-}
-
-func (b *Buffer) read_class_tag() (class string, err error) {
-	br := b.breader()
-	buf := bytes.NewBuffer(b.buffer[b.pos:])
-	tag := br.ntou4(buf)
-	println("tag:",tag)
-
-	if tag == kNewClassTag {
-		
-	} else if (tag & kClassMask) != 0 {
-		
-	} else {
-		println("**err** tag unknown case:", tag)
-		err = fmt.Errorf("groot.Buffer: unknown tag case (%v)", tag)
-		return
+func (b *Buffer) ntoi2() (o int16) {
+	err := binary.Read(b.buf, b.order, &o)
+	if err != nil {
+		panic(err)
 	}
 	return
 }
 
+func (b *Buffer) ntoi4() (o int32) {
+	err := binary.Read(b.buf, b.order, &o)
+	if err != nil {
+		panic(err)
+	}
+	return
+}
+
+func (b *Buffer) ntoi8() (o int64) {
+	err := binary.Read(b.buf, b.order, &o)
+	if err != nil {
+		panic(err)
+	}
+	return
+}
+
+func (b *Buffer) ntobyte() (o byte) {
+	err := binary.Read(b.buf, b.order, &o)
+	if err != nil {
+		panic(err)
+	}
+	return
+}
+
+func (b *Buffer) ntou2() (o uint16) {
+	err := binary.Read(b.buf, b.order, &o)
+	if err != nil {
+		panic(err)
+	}
+	return
+}
+
+func (b *Buffer) ntou4() (o uint32) {
+	err := binary.Read(b.buf, b.order, &o)
+	if err != nil {
+		panic(err)
+	}
+	return
+}
+
+func (b *Buffer) ntou8() (o uint64) {
+	err := binary.Read(b.buf, b.order, &o)
+	if err != nil {
+		panic(err)
+	}
+	return
+}
+
+func (b *Buffer) ntof() (o float32) {
+	err := binary.Read(b.buf, b.order, &o)
+	if err != nil {
+		panic(err)
+	}
+	return
+}
+
+func (b *Buffer) ntod() (o float64) {
+	err := binary.Read(b.buf, b.order, &o)
+	if err != nil {
+		panic(err)
+	}
+	return
+}
+
+func (b *Buffer) readArrayF() (o []float32) {
+	n := int(b.ntou4())
+	o = make([]float32, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntof()
+	}
+	return
+}
+
+func (b *Buffer) readArrayD() (o []float64) {
+	n := int(b.ntou4())
+	o = make([]float64, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntod()
+	}
+	return
+}
+
+func (b *Buffer) readArrayS() (o []int16) {
+	n := int(b.ntou4())
+	o = make([]int16, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntoi2()
+	}
+	return
+}
+
+func (b *Buffer) readArrayI() (o []int32) {
+	n := int(b.ntou4())
+	o = make([]int32, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntoi4()
+	}
+	return
+}
+
+func (b *Buffer) readArrayL() (o []int64) {
+	n := int(b.ntou4())
+	o = make([]int64, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntoi8()
+	}
+	return
+}
+
+func (b *Buffer) readArrayC() (o []byte) {
+	n := int(b.ntou4())
+	o = make([]byte, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntobyte()
+	}
+	return
+}
+
+func (b *Buffer) readStaticArray() (o []uint32) {
+	n := int(b.ntou4())
+	o = make([]uint32, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntou4()
+	}
+	return
+}
+
+func (b *Buffer) readFastArrayF(n int) (o []float32) {
+	o = make([]float32, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntof()
+	}
+	return
+}
+
+func (b *Buffer) readFastArrayD(n int) (o []float64) {
+	o = make([]float64, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntod()
+	}
+	return
+}
+
+func (b *Buffer) readFastArrayS(n int) (o []int16) {
+	o = make([]int16, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntoi2()
+	}
+	return
+}
+
+func (b *Buffer) readFastArrayI(n int) (o []int32) {
+	o = make([]int32, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntoi4()
+	}
+	return
+}
+
+func (b *Buffer) readFastArrayL(n int) (o []int64) {
+	o = make([]int64, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntoi8()
+	}
+	return
+}
+
+func (b *Buffer) readFastArrayC(n int) (o []byte) {
+	o = make([]byte, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntobyte()
+	}
+	return
+}
+
+func (b *Buffer) readFastArrayTString(n int) (o []string) {
+	o = make([]string, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.readTString()
+	}
+	return
+}
+
+func (b *Buffer) readFastArray(n int) (o []uint32) {
+	o = make([]uint32, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntou4()
+	}
+	return
+}
+
+func (b *Buffer) readTString() string {
+	n := int(b.ntobyte())
+	if n == 255 {
+		// large string
+		n = int(b.ntou4())
+	}
+	if n == 0 {
+		return ""
+	}
+	v := b.ntobyte()
+	if v == 0 {
+		return ""
+	}
+	o := make([]byte, n)
+	o[0] = v
+	err := binary.Read(b.buf, b.order, o[1:])
+	if err != nil {
+		panic(err)
+	}
+	return string(o)
+}
+
+//FIXME
+// readBasicPointerElem
+// readBasicPointer
+
+func (b *Buffer) readString(max int) string {
+	o := []byte{}
+	n := 0
+	var v byte
+	for {
+		v = b.ntobyte()
+		if v == 0 {
+			break
+		}
+		n += 1
+		if max > 0 && n >= max {
+			break
+		}
+		o = append(o, v)
+	}
+	return string(o)
+}
+
+func (b *Buffer) readStdString() string {
+	nwh := b.ntobyte()
+	nchars := int32(nwh)
+	if nwh == 255 {
+		nchars = b.ntoi4()
+	}
+	if nchars < 0 {
+		panic("groot.readStdString: negative char number")
+	}
+	return b.readString(int(nchars))
+}
+
+func (b *Buffer) readVersion() (vers uint16, pos, bcnt uint32) {
+
+	bcnt = b.ntou4()
+	if (int64(bcnt) & ^kByteCountMask) != 0 {
+		bcnt = uint32(int64(bcnt) & ^kByteCountMask)
+	} else {
+		panic("groot.breader.readVersion: too old file")
+	}
+	vers = b.ntou2()
+	return
+}
+
+func (b *Buffer) readObject() (o Object) {
+	clsname, bcnt, isref := b.readClass()
+	dprintf(">>[%s] [%v] [%v]\n", clsname, bcnt, isref)
+	if isref {
+
+	} else {
+		if clsname == "" {
+			o = nil
+		} else {
+
+			factory := Factory.Get(clsname)
+			if factory == nil {
+				dprintf("**err** no factory for class [%s]\n", clsname)
+				return
+			}
+
+			vv := factory()
+			o = vv.Interface().(Object)
+			// if vv,ok := vv.Interface().(FileSetter); ok {
+			// 	err := vv.SetFile(k.file)
+			// 	if err != nil {
+			// 		return v
+			// 	}
+			// }
+			if vv, ok := vv.Interface().(ROOTStreamer); ok {
+				err := vv.ROOTDecode(b.clone())
+				if err != nil {
+					panic(err)
+				}
+			} else {
+				dprintf("**err** class [%s] does not satisfy the ROOTStreamer interface\n", clsname)
+			}
+		}
+	}
+	return o
+}
+
+func (b *Buffer) readClass() (name string, bcnt uint32, isref bool) {
+
+	//var bufvers = 0
+	i := b.ntou4()
+
+	if i == kNullTag {
+		/*empty*/
+	} else if (i & kByteCountMask) != 0 {
+		//bufvers = 1
+		clstag := b.readClassTag()
+		if clstag == "" {
+			panic("groot.breader.readClass: empty class tag")
+		}
+		name = clstag
+		bcnt = uint32(int64(i) & ^kByteCountMask)
+	} else {
+		bcnt = uint32(i)
+		isref = true
+	}
+	dprintf("--[%s] [%v] [%v]\n", name, bcnt, isref)
+	return
+}
+
+func (b *Buffer) readClassTag() (clstag string) {
+	tag := b.ntou4()
+
+	if tag == kNewClassTag {
+		clstag = b.readString(80)
+		dprintf("--class+tag: [%v]\n", clstag)
+	} else if (tag & kClassMask) != 0 {
+		clstag = b.clone().readClassTag()
+		dprintf("--class-tag: [%v]\n", clstag)
+	} else {
+		panic(fmt.Errorf("groot.readClassTag: unknown class-tag [%v]", tag))
+	}
+	return
+}
+
+// func (b *Buffer) readObject(r io.Reader) (id, bits uint32) {
+// 	/*v,pos,bcnt := */ br.readVersion(r)
+// 	id = br.ntou8(r)
+// 	bits = br.ntou8(r)
+// 	return
+// }
+
+//FIXME
+// readObjectAny
+// readTList
+// readTObjArray
+// readTClonesArray
+// readTCollection
+// readTHashList
+// readTNamed
+// readTCanvas
+
 // EOF

File pkg/groot/consts.go

 	kClassMask = 0x80000000
 	kMapOffset = 2
 	kByteCountVMask = 0x4000
+
+	kIsReferenced = 1 << 4
+	kIsOnHeap = 0x01000000
 )
 
 

File pkg/groot/core.go

 	}
 }
 
+func dprintf(format string, args ...interface{}) {
+	fmt.Printf(format, args...)
+}
+
 const (
 	sz_int16  = 2
 	sz_int32  = 4
 	g_START_BIG_FILE = 2000000000
 )
 
-
 // EOF

File pkg/groot/directory.go

 package groot
 
 import (
-	"bytes"
 	"fmt"
-	"io"
 	"os"
 	"reflect"
 	"time"
 
 func NewDirectory(f *File, buf []byte) (d *Directory, err error) {
 	d = &Directory{file:f}
-	err = d.from_buffer(bytes.NewBuffer(buf))
+	b, err := NewBuffer(buf, f.order, 0)
+	err = d.from_buffer(b)
 	if err != nil {
 		return
 	}
 	return nbytes
 }
 
-func (d *Directory) from_buffer(buf io.Reader) (err error) {
-	br := d.file.breader()
-	version := br.ntou2(buf)
-	d.ctime = datime2time(br.ntou4(buf))
-	d.mtime = datime2time(br.ntou4(buf))
-	d.nbytes_keys = br.ntou4(buf)
-	d.nbytes_name = br.ntou4(buf)
+func (d *Directory) from_buffer(b *Buffer) (err error) {
+	version := b.ntou2()
+	d.ctime = datime2time(b.ntou4())
+	d.mtime = datime2time(b.ntou4())
+	d.nbytes_keys = b.ntou4()
+	d.nbytes_name = b.ntou4()
 	if version > 1000 {
-		d.seek_dir = br.ntoi8(buf)
-		d.seek_parent = br.ntoi8(buf)
-		d.seek_keys = br.ntoi8(buf)
+		d.seek_dir = b.ntoi8()
+		d.seek_parent = b.ntoi8()
+		d.seek_keys = b.ntoi8()
 	} else {
-		d.seek_dir = int64(br.ntoi4(buf))
-		d.seek_parent = int64(br.ntoi4(buf))
-		d.seek_keys = int64(br.ntoi4(buf))
+		d.seek_dir = int64(b.ntoi4())
+		d.seek_parent = int64(b.ntoi4())
+		d.seek_keys = int64(b.ntoi4())
 	}
 	printf("dir-version: %v\n", version)
 	printf("dir-ctime: %v\n", d.ctime.String())
 	return err
 }
 
-func (d *Directory) ROOTDecode(buf []byte) (err error) {
-	iobuf := bytes.NewBuffer(buf)
-	err = d.from_buffer(iobuf)
+func (d *Directory) ROOTDecode(b *Buffer) (err error) {
+	version := b.ntou2()
+	d.ctime = datime2time(b.ntou4())
+	d.mtime = datime2time(b.ntou4())
+	d.nbytes_keys = b.ntou4()
+	d.nbytes_name = b.ntou4()
+	if version > 1000 {
+		d.seek_dir = b.ntoi8()
+		d.seek_parent = b.ntoi8()
+		d.seek_keys = b.ntoi8()
+	} else {
+		d.seek_dir = int64(b.ntoi4())
+		d.seek_parent = int64(b.ntoi4())
+		d.seek_keys = int64(b.ntoi4())
+	}
+	printf("dir-version: %v\n", version)
+	printf("dir-ctime: %v\n", d.ctime.String())
+	printf("dir-mtime: %v\n", d.mtime.String())
+	printf("dir-nbytes-keys: %v\n", d.nbytes_keys)
+	printf("dir-nbytes-name: %v\n", d.nbytes_name)
+	printf("dir-seek-dir: %v\n", d.seek_dir)
+	printf("dir-seek-parent: %v\n", d.seek_parent)
+	printf("dir-seek-keys: %v\n", d.seek_keys)
+
 	if err != nil {
 		return err
 	}
 	return err
 }
 
-func (d *Directory) ROOTEncode(buf []byte) error {
+func (d *Directory) ROOTEncode(buffer *Buffer) error {
 	panic("groot.Directory.ROOTEncode: sorry, not implemented")
 }
 
 		return -1, err
 	}
 
-	f := bytes.NewReader(buf)
-	if f == nil {
-		return -1, fmt.Errorf("groot: could not create a bytes.Reader")
-	}
-
-	err = hdr.init_from_buffer(f)
+	b,err := NewBuffer(buf, d.file.order, 0)
 	if err != nil {
 		return -1, err
 	}
 
-	br := d.file.breader()
-	nkeys = int(br.ntoi4(f))
+	err = hdr.init_from_buffer(b)
+	if err != nil {
+		return -1, err
+	}
+
+	nkeys = int(b.ntoi4())
 	printf("dir-nkeys: %v\n", nkeys)
 
 	d.keys = make([]Key, nkeys)
 		if err != nil {
 			return -1, err
 		}
-		err = key.init_from_buffer(f)
+		err = key.init_from_buffer(b)
 		if err != nil {
 			return -1, err
 		}

File pkg/groot/ifaces.go

 	// GetComment returns the comment associated with this member
 	Comment() string
 
-	// GetName returns the name of this member
+	// Name returns the name of this member
 	Name() string
 
 	// Type returns the class of this member
 type Object interface {
 	// Class returns the ROOT class of this object
 	Class() Class
+
+	// Name returns the name of this ROOT object
+	Name() string
+
+	// Title returns the title of this ROOT object
+	Title() string
 }
 
 // ClassFactory creates ROOT classes
 // routine for encoding and decoding transmitted values sent to a ROOT file.
 type ROOTStreamer interface {
 	// de-serialize into the current value using 'buf' as input
-	ROOTDecode(buf []byte) error
+	ROOTDecode(buf *Buffer) error
 	// serialize the current value using 'buf' as output
-	ROOTEncode(buf []byte) error
+	ROOTEncode(buf *Buffer) error
 }
 
 // FileSetter is the interface allowing to reset the ownership of a ROOT object

File pkg/groot/key.go

 package groot
 
 import (
-	"io"
 	"time"
 )
 
 	return k, err
 }
 
-func (k *Key) init_from_buffer(f io.Reader) (err error) {
-
-	br := k.file.breader()
+func (k *Key) init_from_buffer(b *Buffer) (err error) {
 
 	// read the key structure from the buffer
-	k.nbytes = br.ntou4(f)
+	k.nbytes = b.ntou4()
 	printf("key-nbytes: %v\n", k.nbytes)
 
 	printf("key-version: %v\n", k.version)
 
-	k.version = uint32(br.ntou2(f))
+	k.version = uint32(b.ntou2())
 	printf("key-version: %v\n", k.version)
-	k.objsz = uint32(br.ntoi4(f))
+	k.objsz = uint32(b.ntoi4())
 	printf("key-objsz: %v\n", k.objsz)
 
-	k.date = datime2time(br.ntou4(f))
+	k.date = datime2time(b.ntou4())
 	printf("key-cdate: %v\n", k.date.String())
 
-	k.keysz = br.ntou2(f)
+	k.keysz = b.ntou2()
 	printf("key-keysz: %v\n", k.keysz)
 
-	k.cycle = br.ntou2(f)
+	k.cycle = b.ntou2()
 	printf("key-cycle: %v\n", k.cycle)
 
 	if k.version > 1000 {
-		k.seek_key = br.ntoi8(f)
-		k.seek_parent_dir = br.ntoi8(f)
+		k.seek_key = b.ntoi8()
+		k.seek_parent_dir = b.ntoi8()
 	} else {
-		k.seek_key = int64(br.ntoi4(f))
-		k.seek_parent_dir = int64(br.ntoi4(f))
+		k.seek_key = int64(b.ntoi4())
+		k.seek_parent_dir = int64(b.ntoi4())
 	}
 	printf("key-seek-key: %v\n", k.seek_key)
 	printf("key-seek-pdir: %v\n", k.seek_parent_dir)
 
-	k.class = br.readTString(f)
+	k.class = b.readTString()
 	printf("key-class [%v]\n", k.class)
 
-	k.name = br.readTString(f)
+	k.name = b.readTString()
 	printf("key-name  [%v]\n", k.name)
 
-	k.title = br.readTString(f)
+	k.title = b.readTString()
 	printf("key-title [%v]\n", k.title)
 
 	return err
 func (k *Key) Value() (v interface{}) {
 	factory := Factory.Get(k.Class())
 	if factory == nil {
+		printf("**err** no factory for class [%s]\n", k.Class())
 		return v
 	}
 
 		}
 	}
 	if vv,ok := vv.Interface().(ROOTStreamer); ok {
-		buf, err := k.Buffer()
+		buf, err := NewBufferFromKey(k)
 		if err != nil {
 			return v
 		}
 		if err != nil {
 			return v
 		}
+	} else {
+		dprintf("**err** class [%s] does not satisfy the ROOTStreamer interface\n", k.Class())
 	}
 	v = vv.Interface()
 	return v

File pkg/groot/reader.go

 	return f, err
 }
 
-func (f *File) breader() breader {
-	return breader{f.order}
-}
-
 func (f *File) seek(offset int64, pos int) (ret int64, err error) {
 	switch pos {
 	case os.SEEK_SET:
 	nbytes := f.nbytes_name + f.root_dir.record_size(f.version)
 	printf("nbytes: %v\n", nbytes)
 
+	buf := make([]byte, int(nbytes))
+
 	// read directory info
-	_, err = f.f.Seek(f.beg+int64(f.nbytes_name), os.SEEK_SET)
+	_, err = f.f.ReadAt(buf, f.beg)
 	if err != nil {
 		return err
 	}
-	err = f.root_dir.from_buffer(f.f)
+
+	b, err := NewBuffer(buf[f.nbytes_name:], f.order, 0)
+	if err != nil {
+		return err
+	}
+
+	err = f.root_dir.from_buffer(b)
 	if err != nil {
 		return err
 	}
 	nk += 2 * sz_int32 // Key::fObjectSize, Date
 	nk += 2 * sz_int16 // Key::fKeyLength, fCycle
 	nk += 2 * sz_int32 // Key::fSeekKey, fSeekParentDirectory
-	// WARNING: the above is sz_int32 since we are at beginning of file...
+	// WARNING: the above is sz_int32 since we are at beginning of file
 
-	_, err = f.f.Seek(f.beg+int64(nk), os.SEEK_SET)
+	b, err = NewBuffer(buf[nk:], f.order, 0)
 	if err != nil {
 		return err
 	}
 
-	br := f.breader()
-
-	var cname string
-	cname = br.readTString(f.f)
+	printf("nk: %v\n", nk)
+	printf("buf: %v\n", buf[:])
+	printf("rst: %v\n", buf[nk:])
+	printf("TFile: %v\n", []byte{'T', 'F', 'i', 'l', 'e'})
+	cname := b.readTString()
 	if cname != "TFile" {
 		return fmt.Errorf("groot: expected [TFile]. got [%v]", cname)
 	}
 	printf("f-clsname [%v]\n", cname)
 
-	cname = br.readTString(f.f)
+	cname = b.readTString()
 	printf("f-cname   [%v]\n", cname)
 
-	f.title = br.readTString(f.f)
+	f.title = b.readTString()
 	printf("f-title   [%v]\n", f.title)
 
 	if f.root_dir.nbytes_name < 10 || f.root_dir.nbytes_name > 1000 {
 }
 
 func (f *File) read_header() (err error) {
-	cur, err := f.f.Seek(0, os.SEEK_CUR)
-	if err != nil {
-		return err
-	}
-	defer f.f.Seek(cur, os.SEEK_SET)
-
-	_, err = f.f.Seek(0, os.SEEK_SET)
+	buf := make([]byte, 64)
+	_, err = f.f.ReadAt(buf, 0)
 	if err != nil {
 		return err
 	}
 
-	br := f.breader()
+	b, err := NewBuffer(buf, f.order, 0)
 	{
-		hdr := make([]byte, 4)
-		err = binary.Read(f.f, f.order, &hdr)
-		if err != nil {
-			return err
-		}
+		hdr := b.read_nbytes(4)
 		printf("hdr: %v\n", string(hdr))
 		if string(hdr) != "root" {
 			return fmt.Errorf(
 				f.name, string(hdr))
 		}
 	}
-	f.version = br.ntou4(f.f)
-	f.beg = int64(br.ntou4(f.f))
+	f.version = b.ntou4()
+	f.beg = int64(b.ntou4())
 	printf("beg: %v\n", f.beg)
 	if f.version >= 1000000 {
-		f.end = int64(br.ntou8(f.f))
-		f.seek_free = int64(br.ntou8(f.f))
+		f.end = int64(b.ntou8())
+		f.seek_free = int64(b.ntou8())
 	} else {
-		f.end = int64(br.ntou4(f.f))
-		f.seek_free = int64(br.ntou4(f.f))
+		f.end = int64(b.ntou4())
+		f.seek_free = int64(b.ntou4())
 	}
 	printf("end: %v\n", f.end)
 	printf("seek-free: %v\n", f.seek_free)
-	f.nbytes_free = br.ntou4(f.f)
-	/*nfree*/ br.ntoi4(f.f)
-	f.nbytes_name = br.ntou4(f.f)
+	f.nbytes_free = b.ntou4()
+	/*nfree*/ b.ntoi4()
+	f.nbytes_name = b.ntou4()
 	printf("nbytes-free: %v\n", f.nbytes_free)
 	printf("nbytes-name: %v\n", f.nbytes_name)
-	/*units*/ br.ntobyte(f.f)
-	/*compress*/ br.ntou4(f.f)
+	/*units*/ b.ntobyte()
+	/*compress*/ b.ntou4()
 	if f.version >= 1000000 {
-		f.seek_info = int64(br.ntou8(f.f))
+		f.seek_info = int64(b.ntou8())
 	} else {
-		f.seek_info = int64(br.ntou4(f.f))
+		f.seek_info = int64(b.ntou4())
 	}
-	f.nbytes_info = br.ntou4(f.f)
+	f.nbytes_info = b.ntou4()
 	printf("seek-info: %v\n", f.seek_info)
 	printf("nbytes-info: %v\n", f.nbytes_info)
 
 }
 
 func (f *File) read_streamer_infos() (err error) {
-	buf := make([]byte, int(f.nbytes_info))
-	_, err = f.f.ReadAt(buf, f.seek_info)
-	if err != nil {
-		return err
+
+	if true {
+		return
 	}
-	printf("buf: %v\n", len(buf))
+	lst := make(List, 0)
+	dprintf("lst: %v\n", lst)
+
+	var buf []byte
+
+	if f.seek_info > 0 && f.seek_info < f.end {
+		buf = make([]byte, int(f.nbytes_info))
+
+		_, err = f.f.ReadAt(buf, f.seek_info)
+		if err != nil {
+			return err
+		}
+		key, err := NewKey(f, 0, 0)
+		if err != nil {
+			return err
+		}
+		b, err := NewBuffer(buf, f.order, 0)
+		err = key.init_from_buffer(b)
+		if err != nil {
+			return err
+		}
+		obj, ok := key.Value().(List)
+		if ok {
+			lst = obj
+		}
+	}
+	dprintf("buf: %v\n", len(buf))
+	
 	return err
 }
 
+/*
+void TFile::ReadStreamerInfo()
+{
+// Read the list of StreamerInfo from this file
+// The key with name holding the list of TStreamerInfo objects is read.
+// The corresponding TClass objects are updated.
+
+   TList *list = 0;
+   if (fSeekInfo > 0 && fSeekInfo < fEND) {
+      TKey *key = new TKey();
+      char *buffer = new char[fNbytesInfo+1];
+      char *buf    = buffer;
+      Seek(fSeekInfo);
+      ReadBuffer(buf,fNbytesInfo);
+      key->ReadBuffer(buf);
+      TFile *filesave = gFile;
+      gFile = this; // used in ReadObj
+      list = (TList*)key->ReadObj();
+      if (!list) {
+         gDirectory->GetListOfKeys()->Remove(key);
+         MakeZombie();
+      }
+      gFile = filesave;
+      delete [] buffer;
+      delete key;
+   } else {
+      list = (TList*)Get("StreamerInfo"); //for versions 2.26 (never released)
+   }
+
+   if (list == 0) return;
+   if (gDebug > 0) Info("ReadStreamerInfo", "called for file %s",GetName());
+
+   // loop on all TStreamerInfo classes
+   TStreamerInfo *info;
+   TIter next(list);
+   while ((info = (TStreamerInfo*)next())) {
+      if (info->IsA() != TStreamerInfo::Class()) {
+         Warning("ReadStreamerInfo","%s: not a TStreamerInfo object", GetName());
+         continue;
+      }
+      info->BuildCheck();
+      Int_t uid = info->GetNumber();
+      Int_t asize = fClassIndex->GetSize();
+      if (uid >= asize && uid <100000) fClassIndex->Set(2*asize);
+      if (uid >= 0 && uid < fClassIndex->GetSize()) fClassIndex->fArray[uid] = 1;
+      else {
+         printf("ReadStreamerInfo, class:%s, illegal uid=%d\n",info->GetName(),uid);
+      }
+      if (gDebug > 0) printf(" -class: %s version: %d info read at slot %d\n",info->GetName(), info->GetClassVersion(),uid);
+   }
+   fClassIndex->fArray[0] = 0;
+   list->Clear();  //this will delete all TStreamerInfo objects with kCanDelete bit set
+   delete list;
+}
+
+*/
+
 func (f *File) Name() string {
 	return f.name
 }

File pkg/groot/utils.go

 import (
 	"bytes"
 	"compress/zlib"
-	"encoding/binary"
 	"fmt"
-	"io"
 	"io/ioutil"
-	"os"
 	"time"
 )
 
-type breader struct {
-	order binary.ByteOrder
-}
-
-func (b breader) skip(r io.Seeker, nbytes int64) {
-	_, err := r.Seek(nbytes, os.SEEK_CUR)
-	if err != nil {
-		panic(err)
-	}
-}
-
-func (b breader) ntoi2(r io.Reader) (o int16) {
-	err := binary.Read(r, b.order, &o)
-	if err != nil {
-		panic(err)
-	}
-	return
-}
-
-func (b breader) ntoi4(r io.Reader) (o int32) {
-	err := binary.Read(r, b.order, &o)
-	if err != nil {
-		panic(err)
-	}
-	return
-}
-
-func (b breader) ntoi8(r io.Reader) (o int64) {
-	err := binary.Read(r, b.order, &o)
-	if err != nil {
-		panic(err)
-	}
-	return
-}
-
-func (b breader) ntobyte(r io.Reader) (o byte) {
-	err := binary.Read(r, b.order, &o)
-	if err != nil {
-		panic(err)
-	}
-	return
-}
-
-func (b breader) ntou2(r io.Reader) (o uint16) {
-	err := binary.Read(r, b.order, &o)
-	if err != nil {
-		panic(err)
-	}
-	return
-}
-
-func (b breader) ntou4(r io.Reader) (o uint32) {
-	err := binary.Read(r, b.order, &o)
-	if err != nil {
-		panic(err)
-	}
-	return
-}
-
-func (b breader) ntou8(r io.Reader) (o uint64) {
-	err := binary.Read(r, b.order, &o)
-	if err != nil {
-		panic(err)
-	}
-	return
-}
-
-func (b breader) ntof(r io.Reader) (o float32) {
-	err := binary.Read(r, b.order, &o)
-	if err != nil {
-		panic(err)
-	}
-	return
-}
-
-func (b breader) ntod(r io.Reader) (o float64) {
-	err := binary.Read(r, b.order, &o)
-	if err != nil {
-		panic(err)
-	}
-	return
-}
-
-func (b breader) readArrayF(r io.Reader) (o []float32) {
-	n := int(b.ntou4(r))
-	o = make([]float32, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntof(r)
-	}
-	return
-}
-
-func (b breader) readArrayD(r io.Reader) (o []float64) {
-	n := int(b.ntou4(r))
-	o = make([]float64, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntod(r)
-	}
-	return
-}
-
-func (b breader) readArrayS(r io.Reader) (o []int16) {
-	n := int(b.ntou4(r))
-	o = make([]int16, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntoi2(r)
-	}
-	return
-}
-
-func (b breader) readArrayI(r io.Reader) (o []int32) {
-	n := int(b.ntou4(r))
-	o = make([]int32, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntoi4(r)
-	}
-	return
-}
-
-func (b breader) readArrayL(r io.Reader) (o []int64) {
-	n := int(b.ntou4(r))
-	o = make([]int64, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntoi8(r)
-	}
-	return
-}
-
-func (b breader) readArrayC(r io.Reader) (o []byte) {
-	n := int(b.ntou4(r))
-	o = make([]byte, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntobyte(r)
-	}
-	return
-}
-
-func (b breader) readStaticArray(r io.Reader) (o []uint32) {
-	n := int(b.ntou4(r))
-	o = make([]uint32, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntou4(r)
-	}
-	return
-}
-
-func (b breader) readFastArrayF(r io.Reader, n int) (o []float32) {
-	o = make([]float32, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntof(r)
-	}
-	return
-}
-
-func (b breader) readFastArrayD(r io.Reader, n int) (o []float64) {
-	o = make([]float64, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntod(r)
-	}
-	return
-}
-
-func (b breader) readFastArrayS(r io.Reader, n int) (o []int16) {
-	o = make([]int16, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntoi2(r)
-	}
-	return
-}
-
-func (b breader) readFastArrayI(r io.Reader, n int) (o []int32) {
-	o = make([]int32, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntoi4(r)
-	}
-	return
-}
-
-func (b breader) readFastArrayL(r io.Reader, n int) (o []int64) {
-	o = make([]int64, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntoi8(r)
-	}
-	return
-}
-
-func (b breader) readFastArrayC(r io.Reader, n int) (o []byte) {
-	o = make([]byte, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntobyte(r)
-	}
-	return
-}
-
-func (b breader) readFastArrayTString(r io.Reader, n int) (o []string) {
-	o = make([]string, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.readTString(r)
-	}
-	return
-}
-
-func (b breader) readFastArray(r io.Reader, n int) (o []uint32) {
-	o = make([]uint32, n)
-	for i := 0; i < n; i++ {
-		o[i] = b.ntou4(r)
-	}
-	return
-}
-
-func (b breader) readTString(r io.Reader) string {
-	n := int(b.ntobyte(r))
-	if n == 255 {
-		// large string
-		n = int(b.ntou4(r))
-	}
-	if n == 0 {
-		return ""
-	}
-	v := b.ntobyte(r)
-	if v == 0 {
-		return ""
-	}
-	o := make([]byte, n)
-	o[0] = v
-	err := binary.Read(r, b.order, o[1:])
-	if err != nil {
-		panic(err)
-	}
-	return string(o)
-}
-
-//FIXME
-// readBasicPointerElem
-// readBasicPointer
-
-func (b breader) readString(r io.Reader, max int) string {
-	o := []byte{}
-	n := 0
-	var v byte
-	for {
-		v = b.ntobyte(r)
-		if v == 0 {
-			break
-		}
-		n += 1
-		if max > 0 && n >= max {
-			break
-		}
-		o = append(o, v)
-	}
-	return string(o)
-}
-
-//FIXME
-// readObjectAny
-// readTList
-// readTObjArray
-// readTClonesArray
-// readTCollection
-// readTHashList
-// readTNamed
-// readTCanvas
-
-//FIXME
-// getStreamer(f TFile, name string) Streamer
-
 // datime2time converts a uint32 holding a ROOT's TDatime into a time.Time
 func datime2time(d uint32) time.Time {