Anonymous avatar Anonymous committed ce400c5

almost working tree.decode

Comments (0)

Files changed (8)

pkg/groot/base_leaf.go

 package groot
 
+type ibaseLeaf interface {
+	toBaseLeaf() *baseLeaf
+}
+
 type baseLeaf struct {
 	name   string
 	title  string
 }
 
 func (base *baseLeaf) ROOTDecode(b *Buffer) (err error) {
+	spos := b.Pos()
 
 	vers, pos, bcnt := b.read_version()
 	dprintf("baseleaf-vers=%v pos=%v bcnt=%v\n", vers, pos, bcnt)
 	obj := b.read_object()
 	dprintf("baseleaf-nobjs: %v\n", obj)
 	if obj != nil {
-		base.leaf_count = obj.(*baseLeaf)
+		base.leaf_count = obj.(ibaseLeaf).toBaseLeaf()
 	}
-	if base.length != 0 {
+
+	b.check_byte_count(pos, bcnt, spos, "TLeaf")
+	if base.length == 0 {
 		//FIXME: ??? really ??? (check with Guy)
 		base.length = 1
 	}

pkg/groot/basket.go

 	if basket.key.objsz != 0 {
 		basket.key.objsz = uint32(basket.key.nbytes) - uint32(basket.key.keysz)
 	}
-	if flag != 0 {
+	if flag == 0 {
 		// fHeaderOnly
 		return
 	}

pkg/groot/branch.go

 	entryNumber uint32 // current entry number (last one filled in this branch)
 	readBasket uint32  // current basket number when reading
 	
-	//fBasketBytes
-	//fBasketEntry
-	//fBasketSeek
-
+	basketBytes []int32 // length of baskets on file
+	basketEntry []int32 // table of first entry of each basket
+	basketSeek  []int64 // addresses of baskets on file
 }
 
 func (branch *Branch) Class() Class {
 }
 
 func (branch *Branch) ROOTDecode(b *Buffer) (err error) {
-
+	spos := b.Pos()
 	vers, pos, bcnt := b.read_version()
-	dprintf("vers=%v pos=%v bcnt=%v\n", vers, pos, bcnt)
+	dprintf("vers=%v spos=%v pos=%v bcnt=%v\n", vers, spos, pos, bcnt)
 	branch.name, branch.title = b.read_tnamed()
 	dprintf("name='%v' title='%v'\n", branch.name, branch.title)
+	dprintf("spos=%v\n", b.Pos())
 
+	maxbaskets := uint32(0)
+	splitlvl := int32(0)
 	if vers <= 5 {
 		b.ntoi4() // fCompress
 		b.ntoi4() // fBasketSize
 		branch.entryOffsetLen = b.ntou4()
-		b.ntou4() // fMaxBaskets
+		maxbaskets = b.ntou4() // fMaxBaskets
 		branch.writeBasket = b.ntou4()
 		branch.entryNumber = b.ntou4()
 		b.ntod() // entries
 		branch.writeBasket = b.ntou4()
 		branch.entryNumber = b.ntou4()
 		b.ntoi4() // fOffset
-		b.ntou4() // fMaxBaskets
+		maxbaskets = b.ntou4() // fMaxBaskets
 		b.ntod() // entries
 		b.ntod() // tot_bytes
 		b.ntod() // zip_bytes
 		branch.writeBasket = b.ntou4()
 		branch.entryNumber = b.ntou4()
 		b.ntoi4() // fOffset
-		b.ntou4() // fMaxBaskets
-		b.ntoi4() // fSplitLevel
+		maxbaskets = b.ntou4() // fMaxBaskets
+		splitlvl = b.ntoi4() // fSplitLevel
 		b.ntod() // entries
 		b.ntod() // tot_bytes
 		b.ntod() // zip_bytes
 		branch.writeBasket = b.ntou4()
 		branch.entryNumber = b.ntou4()
 		b.ntoi4() // fOffset
-		b.ntou4() // fMaxBaskets
-		b.ntoi4() // fSplitLevel
+		maxbaskets = b.ntou4() // fMaxBaskets
+		splitlvl = b.ntoi4() // fSplitLevel
 		b.ntod() // entries
 		b.ntod() // tot_bytes
 		b.ntod() // zip_bytes
 		branch.writeBasket = b.ntou4()
 		branch.entryNumber = uint32(b.ntou8()) //fixme ?
 		b.ntoi4() // fOffset
-		b.ntou4() // fMaxBaskets
-		b.ntoi4() // fSplitLevel
+		maxbaskets = b.ntou4() // fMaxBaskets
+		splitlvl = b.ntoi4() // fSplitLevel
 		b.ntou8() // entries
 		b.ntou8() // tot_bytes
 		b.ntou8() // zip_bytes
 		branch.writeBasket = b.ntou4()
 		branch.entryNumber = uint32(b.ntou8()) //fixme ?
 		b.ntoi4() // fOffset
-		b.ntou4() // fMaxBaskets
-		b.ntoi4() // fSplitLevel
+		maxbaskets = b.ntou4() // fMaxBaskets
+		splitlvl = b.ntoi4() // fSplitLevel
 		b.ntou8() // entries
 		b.ntou8() // fFirstEntry
 		b.ntou8() // tot_bytes
 		b.ntou8() // zip_bytes
 	}
+	dprintf("::branch::stream : [%s] split-lvl= %v\n", branch.name, splitlvl)
+
+	dprintf("::branch::stream : branches : begin\n")
 	branches := b.read_obj_array()
+	dprintf("::branch::stream : branches : end\n")
 	dprintf("sub-branches: %v\n", len(branches))
 
+	dprintf("::branch::stream : leaves : begin\n")
 	leaves := b.read_obj_array()
+	dprintf("::branch::stream : leaves : end\n")
 	dprintf("sub-leaves: %v\n", len(leaves))
 
+	dprintf("::branch::stream : streamed_baskets : begin\n")
 	baskets := b.read_obj_array()
+	dprintf("::branch::stream : streamed_baskets : end\n")
 	dprintf("baskets: %v\n", len(baskets))
 
+	branch.basketEntry = make([]int32, 0, int(maxbaskets))
+	branch.basketBytes = make([]int32, 0, int(maxbaskets))
+	branch.basketSeek =  make([]int64, int(maxbaskets))
+
+	if vers < 6 {
+		copy(branch.basketEntry, b.read_array_I())
+		if vers <= 4 {
+			branch.basketBytes = make([]int32, int(maxbaskets))
+		} else {
+			copy(branch.basketBytes, b.read_array_I())
+		}
+		if vers < 2 {
+			panic("branch.ROOTDecode of vers<2 *NOT* handled")
+		} else {
+			nseeks := int(b.ntoi4())
+			for i := 0; i<nseeks; i++ {
+				branch.basketSeek[i] = int64(b.ntoi4())
+			}
+		}
+	} else if vers <= 9 {
+		// see TStreamerInfo::ReadBuffer::ReadBasicPointer
+		isarray := byte(0)
+		isarray = b.ntobyte()
+		if isarray != 0 {
+			copy(branch.basketBytes, b.read_fast_array_I(int(maxbaskets)))
+		}
+		isarray = b.ntobyte()
+		if isarray != 0 {
+			copy(branch.basketEntry, b.read_fast_array_I(int(maxbaskets)))
+		}
+		isbigfile := b.ntobyte()
+		if isbigfile == 2 {
+			copy(branch.basketSeek, b.read_fast_array_L(int(maxbaskets)))
+		} else {
+			for i := 0; i<int(maxbaskets); i++ {
+				branch.basketSeek[i] = int64(b.ntoi4())
+			}
+			
+		}
+	} else { // vers >= 10
+		// see TStreamerInfo::ReadBuffer::ReadBasicPointer
+		isarray := byte(0)
+
+		isarray = b.ntobyte()
+		if isarray != 0 {
+			copy(branch.basketBytes, b.read_fast_array_I(int(maxbaskets)))
+		}
+
+		isarray = b.ntobyte()
+		if isarray != 0 {
+			bentries := b.read_fast_array_UL(int(maxbaskets))
+			for _,v := range bentries {
+				branch.basketEntry = append(branch.basketEntry, int32(v))
+			}
+		}
+
+		isarray = b.ntobyte()
+		if isarray != 0 {
+			bentries := b.read_fast_array_UL(int(maxbaskets))
+			for i,v := range bentries {
+				branch.basketSeek[i] = int64(v)
+			}
+		}
+	}
+
+	if vers > 2 {
+		fname := b.read_tstring()
+		dprintf("fname=%s\n", fname)
+	}
+	dprintf("spos=%v\n", b.Pos())
+	b.check_byte_count(pos, bcnt, spos, "TBranch")
 	return
 }
 

pkg/groot/branch_element.go

+package groot
+
+import (
+	"reflect"
+)
+
+type BranchElement struct {
+	branch Branch
+	object Object
+	class  string // class name of referenced object
+	vers   int // version number of class
+	id     int // element serial number in fInfo
+	btype  int // branch type
+	stype  int // branch streamer type
+}
+
+func (be *BranchElement) Class() Class {
+	panic("not implemented")
+}
+
+func (be *BranchElement) Name() string {
+	return be.branch.name
+}
+
+func (be *BranchElement) Title() string {
+	return be.branch.title
+}
+
+func (be *BranchElement) ROOTDecode(b *Buffer) (err error) {
+
+	spos := b.Pos()
+	vers, pos, bcnt := b.read_version()
+	dprintf("vers=%v spos=%v pos=%v bcnt=%v\n", vers, spos, pos, bcnt)
+	err = be.branch.ROOTDecode(b)
+	if err != nil {
+		return err
+	}
+
+	if vers <= 7 {
+		be.class = b.read_tstring()
+		be.vers = int(b.ntoi4())
+		be.id = int(b.ntoi4())
+		be.btype = int(b.ntoi4())
+		be.stype = int(b.ntoi4())
+	} else { // vers >= 8
+		be.class = b.read_tstring()
+		b.read_tstring() // fParentName
+		b.read_tstring() // fCloneName
+		b.ntoi4() // fCheckSum
+		be.vers = int(b.ntoi4())
+		be.id = int(b.ntoi4())
+		be.btype = int(b.ntoi4())
+		be.stype = int(b.ntoi4())
+		b.ntoi4() // fMaximum
+
+		b.read_object() // fBranchCount  *TBranchElement
+		b.read_object() // fBranchCount2 *TBranchElement
+	}
+	b.check_byte_count(pos, bcnt, spos, "TBranchElement")
+	return
+}
+
+func (be *BranchElement) ROOTEncode(b *Buffer) (err error) {
+	panic("not implemented")
+	return
+}
+
+func init() {
+	f := func() reflect.Value {
+		o := &BranchElement{}
+		return reflect.ValueOf(o)
+	}
+	Factory.db["TBranchElement"] = f
+	Factory.db["*groot.BranchElement"] = f
+}
+
+// check interfaces
+var _ Object = (*BranchElement)(nil)
+var _ ROOTStreamer = (*BranchElement)(nil)
+

pkg/groot/buffer.go

 	"bytes"
 	"encoding/binary"
 	"fmt"
+	"unsafe"
 )
 
 type Buffer struct {
 	return NewBuffer(buf, k.file.order, uint32(k.keysz))
 }
 
+func (b *Buffer) Pos() int {
+	return len(b.data) - b.Len()
+}
+
 func (b *Buffer) Len() int {
 	return len(b.Bytes())
 }
 }
 
 func (b *Buffer) clone() *Buffer {
-	bb, err := NewBuffer(b.buf.Bytes(), b.order, b.klen)
+	bb, err := NewBuffer(b.data[:], b.order, b.klen)
 	if err != nil {
 		return nil
 	}
+	bb.read_nbytes(b.Pos())
 	return bb
 }
 
+func (b *Buffer) rewind_nbytes(nbytes int) {
+	idx := b.Pos()
+	b.buf = bytes.NewBuffer(b.data[idx-nbytes:])
+}
+
 func (b *Buffer) read_nbytes(nbytes int) (o []byte) {
 	o = make([]byte, nbytes)
 	err := binary.Read(b.buf, b.order, o)
 	return
 }
 
+func (b *Buffer) read_fast_array_UL(n int) (o []uint64) {
+	o = make([]uint64, n)
+	for i := 0; i < n; i++ {
+		o[i] = b.ntou8()
+	}
+	return
+}
+
 func (b *Buffer) read_fast_array_C(n int) (o []byte) {
 	o = make([]byte, n)
 	for i := 0; i < n; i++ {
 }
 
 func (b *Buffer) read_object() (o Object) {
+	spos := b.Pos()
 	// before reading object, save start position
 	startbuf := b.clone()
 
 	clsname, bcnt, isref := b.read_class()
-	dprintf(">>[%s] [%v] [%v]\n", clsname, bcnt, isref)
+	dprintf(">>[class=%s] [bcnt=%v] [isref=%v]\n", clsname, bcnt, isref)
 	if isref {
-		obj_offset := bcnt - kMapOffset - b.klen
 		bb := b.clone()
-		bb.read_nbytes(int(obj_offset))
+		dprintf("obj_offset: [%v] -> [%v] -> [%v]\n",
+			bcnt, bcnt-kMapOffset, bcnt-kMapOffset-bb.klen)
+		bb.rewind_nbytes(b.Pos() - int(bcnt - kMapOffset - bb.klen))
 		ii := bb.ntou4()
 		if (ii & kByteCountMask) != 0 {
 			scls := bb.read_class_tag()
 			if scls == "" {
 				panic("groot.Buffer.read_object: read_class_tag did not find a class name")
 			}
-			factory := Factory.Get(scls)
-			if factory == nil {
-				dprintf("**err** no factory for class [%s]\n", clsname)
-				return
-			}
-
-			vv := factory()
-			o = vv.Interface().(Object)
-			panic("chasing refs isnt implemented")
 		} else {
 			/* boo */
 		}
 			} else {
 				dprintf("**err** class [%s] does not satisfy the ROOTStreamer interface\n", clsname)
 			}
+			b.check_byte_count(0,bcnt, spos, clsname)
 		}
 	}
 	return o
 
 	//var bufvers = 0
 	i := b.ntou4()
-	dprintf("..first_int: %x\n", i)
+	dprintf("..first_int: %x (len=%d)\n", i, b.Len()/8)
 	if i == kNullTag {
 		/*empty*/
+		dprintf("read_class: first_int is kNullTag\n")
 	} else if (i & kByteCountMask) != 0 {
 		//bufvers = 1
+		dprintf("read_class: first_int & kByteCountMask\n")
 		clstag := b.read_class_tag()
 		if clstag == "" {
 			panic("groot.Buffer.read_class: empty class tag")
 		}
 		name = clstag
 		bcnt = uint32(int64(i) & ^kByteCountMask)
+		dprintf("read_class: kNewClassTag: read class name='%s' bcnt=%d\n",
+			name, bcnt)
 	} else {
+		dprintf("read_class: first_int %x ==> position toward object.\n", i)
 		bcnt = uint32(i)
 		isref = true
 	}
-	dprintf("--[%s] [%v] [%v]\n", name, bcnt, isref)
+	dprintf("--[cls=%s] [bcnt=%v] [isref=%v]\n", name, bcnt, isref)
 	return
 }
 
 func (b *Buffer) read_class_tag() (clstag string) {
 	tag := b.ntou4()
-	dprintf("--tag:%v %x\n", tag, tag)
-	if tag == kNewClassTag {
+
+	tag_new_class := tag == kNewClassTag
+	tag_class_mask := (int64(tag) & (^int64(kClassMask))) != 0
+
+	dprintf("--tag:%v %x -> new_class=%v class_mask=%v\n", 
+		tag, tag, 
+		tag_new_class,
+		tag_class_mask)
+
+	if tag_new_class {
 		clstag = b.read_string(80)
-		printf("--class+tag: [%v]\n", clstag)
-	} else if (tag & kClassMask) != 0 {
-		clstag = b.clone().read_class_tag()
-		printf("--class-tag: [%v]\n", clstag)
+		dprintf("--class+tag: [%v] - kNewClassTag\n", clstag)
+	} else if tag_class_mask {
+		ref := uint32(int64(tag) & (^int64(kClassMask)))
+		dprintf("--class-tag: [%v] & kClassMask -- ref=%d -- recurse\n", 
+			clstag, ref)
+		bb := b.clone()
+		dprintf("cl_offset: [%v] -> [%v] -> [%v]\n",
+			ref, ref-kMapOffset, ref-kMapOffset-bb.klen)
+		bb.rewind_nbytes(b.Pos() - int(ref - kMapOffset - bb.klen))
+		clstag = bb.read_class_tag()
+		//printf("--class-tag: [%v] & kClassMask\n", clstag)
 	} else {
 		panic(fmt.Errorf("groot.read_class_tag: unknown class-tag [%v]", tag))
 	}
 }
 
 func (b *Buffer) read_tnamed() (name, title string) {
-
+	spos := b.Pos()
 	vers, pos, bcnt := b.read_version()
 	id := b.ntou4()
 	bits := b.ntou4()
 	title = b.read_tstring()
 	printf("read_tnamed: vers=%v pos=%v bcnt=%v id=%v bits=%v name='%v' title='%v'\n",
 		vers, pos, bcnt, id, bits, name, title)
-	//FIXME: buffer.check_byte_count(pos,bcnt,"TNamed")
+
+	b.check_byte_count(pos,bcnt,spos,"TNamed")
 
 	return
 }
 }
 
 func (b *Buffer) read_obj_array() (elmts []Object) {
-
+	spos := b.Pos()
 	vers, pos, bcnt := b.read_version()
 	if vers > 2 {
 		// skip version
 
 	elmts = make([]Object, nobjs)
 	for i := 0; i < nobjs; i++ {
-		dprintf("--[%d]...\n", i)
+		dprintf("read_obj_array: %d/%d...\n", i, nobjs)
 		obj := b.read_object()
-		dprintf("--[%d]... [done]\n", i)
+		dprintf("read_obj_array: %d/%d...[done]\n", i, nobjs)
 		elmts[i] = obj
 	}
-	//FIXME: buffer.check_byte_count(s,c,"TObjArray")
+
+	b.check_byte_count(pos, bcnt, spos, "TObjArray")
 	return elmts
 }
 
-/*
-    short v;
-    unsigned int s, c;
-    if(!a_buffer.read_version(v,s,c)) return false;
-
-    //::printf("debug : ObjArray::stream : version %d count %d\n",v,c);
-
-   {uint32 id,bits;
-    if(!Object_stream(a_buffer,id,bits)) return false;}
-    std::string name;
-    if(!a_buffer.read(name)) return false;
-    int nobjects;
-    if(!a_buffer.read(nobjects)) return false;
-    int lowerBound;
-    if(!a_buffer.read(lowerBound)) return false;
-
-    //::printf("debug : ObjArray : nobject \"%s\" %d %d\n",
-    //  name.c_str(),nobjects,lowerBound);
-
-    for (int i=0;i<nobjects;i++) {
-      //::printf("debug : ObjArray :    n=%d i=%d ...\n",nobjects,i);
-      iro* obj;
-      if(!a_buffer.read_object(a_fac,a_args,obj)){
-        a_buffer.out() << "inlib::rroot::ObjArray::stream :"
-                       << " can't read object."
-                       << std::endl;
-        return false;
-      }
-      //::printf("debug : ObjArray :    n=%d i=%d : ok\n",nobjects,i);
-      if(obj) {
-        T* to = inlib::cast<iro,T>(*obj);
-        if(!to) {
-          a_buffer.out() << "inlib::rroot::ObjArray::stream :"
-                         << " inlib::cast failed."
-                         << std::endl;
-        } else {
-          push_back(to);
-        }
-      } else {
-        //a_accept_null for branch::stream m_baskets.
-        if(a_accept_null) this->push_back(0);
-      }
-    }
-
-    return a_buffer.check_byte_count(s,c,"TObjArray");
-  }
-*/
-
 func (b *Buffer) read_attline() (color, style, width uint16) {
-	/*vers, pos, bcnt := */ b.read_version()
+	spos := b.Pos()
+	/*vers*/_, pos, bcnt := b.read_version()
 	color = b.ntou2()
 	style = b.ntou2()
 	width = b.ntou2()
-	//FIXME: check_byte_count(s,c,"TAttLine")
+	b.check_byte_count(pos,bcnt, spos, "TAttLine")
 	return
 }
 
 func (b *Buffer) read_attfill() (color, style uint16) {
-	/*vers, pos, bcnt := */ b.read_version()
+	spos := b.Pos()
+	/*vers*/_, pos, bcnt := b.read_version()
 	color = b.ntou2()
 	style = b.ntou2()
-	//FIXME: check_byte_count(s,c,"TAttFill")
+	b.check_byte_count(pos,bcnt, spos, "TAttFill")
 	return
 }
 
 func (b *Buffer) read_attmarker() (color, style uint16, width float32) {
-	/*vers, pos, bcnt := */ b.read_version()
+	spos := b.Pos()
+	/*vers*/_, pos, bcnt := b.read_version()
 	color = b.ntou2()
 	style = b.ntou2()
 	width = b.ntof()
-	//FIXME: check_byte_count(s,c,"TAttMarker")
+	b.check_byte_count(pos,bcnt, spos,"TAttMarker")
 	return
 }
 
 // readTNamed
 // readTCanvas
 
+func (b *Buffer) check_byte_count(start, count uint32, spos int, cls string) bool {
+	if count == 0 {
+		return true
+	}
+
+	lenbuf := uint64(start) + uint64(count) + uint64(unsafe.Sizeof(uint(0)))
+	diff := uint64(b.Pos() - spos)
+
+	if diff == lenbuf {
+		return true
+	}
+	
+	if diff < lenbuf {
+		err := fmt.Errorf(
+			"buffer.check_count: object of class [%s] read too few bytes (%d missing)",
+			cls, lenbuf-diff)
+		fmt.Printf("**error** %s\n", err.Error())
+		//panic(err)
+
+		dprintf("-->pos= %v\n", b.Pos())
+		b.read_nbytes(int(lenbuf-diff))
+		dprintf("-->pos= %v\n", b.Pos())
+		return true
+	}
+	if diff > lenbuf {
+		err := fmt.Errorf(
+			"buffer.check_count: object of class [%s] read too many bytes (%d in excess)",
+			cls, diff-lenbuf)
+		fmt.Printf("**error** %s\n", err.Error())
+
+		//panic(err)
+		dprintf("-->pos= %v\n", b.Pos())
+		b.rewind_nbytes(int(diff -lenbuf))
+		dprintf("-->pos= %v\n", b.Pos())
+		return true
+	}
+	return false
+}
 // EOF

pkg/groot/leaf.go

 	"reflect"
 )
 
+// leaf of ints
+
 type LeafI struct {
 	base baseLeaf
 	min int32
 	data []int
 }
 
+func (leaf *LeafI) toBaseLeaf() *baseLeaf {
+	return &leaf.base
+}
+
 func (leaf *LeafI) Class() Class {
 	panic("not implemented")
 }
 	panic("not implemented")
 }
 
+// leaf of ints-64
+
+type LeafL struct {
+	base baseLeaf
+	min int32
+	max int32
+	data []int64
+}
+
+func (leaf *LeafL) toBaseLeaf() *baseLeaf {
+	return &leaf.base
+}
+
+func (leaf *LeafL) Class() Class {
+	panic("not implemented")
+}
+
+func (leaf *LeafL) Name() string {
+	return leaf.base.name
+}
+
+func (leaf *LeafL) Title() string {
+	return leaf.base.title
+}
+
+func (leaf *LeafL) ROOTDecode(b *Buffer) (err error) {
+
+	vers, pos, bcnt := b.read_version()
+	dprintf("leafL-vers=%v pos=%v bcnt=%v\n", vers, pos, bcnt)
+	err = leaf.base.ROOTDecode(b)
+	if err != nil {
+		return err
+	}
+	leaf.min = b.ntoi4()
+	leaf.max = b.ntoi4()
+	leaf.data = make([]int64, int(leaf.base.length))
+	dprintf("leafL min=%v max=%v len=%d\n", leaf.min, leaf.max, len(leaf.data))
+	return
+}
+
+func (leaf *LeafL) ROOTEncode(b *Buffer) (err error) {
+	//FIXME
+	panic("not implemented")
+}
+
+// leaf of floats
+
+type LeafF struct {
+	base baseLeaf
+	min int32
+	max int32
+	data []float32
+}
+
+func (leaf *LeafF) toBaseLeaf() *baseLeaf {
+	return &leaf.base
+}
+
+func (leaf *LeafF) Class() Class {
+	panic("not implemented")
+}
+
+func (leaf *LeafF) Name() string {
+	return leaf.base.name
+}
+
+func (leaf *LeafF) Title() string {
+	return leaf.base.title
+}
+
+func (leaf *LeafF) ROOTDecode(b *Buffer) (err error) {
+
+	vers, pos, bcnt := b.read_version()
+	dprintf("leafF-vers=%v pos=%v bcnt=%v\n", vers, pos, bcnt)
+	err = leaf.base.ROOTDecode(b)
+	if err != nil {
+		return err
+	}
+	leaf.min = b.ntoi4()
+	leaf.max = b.ntoi4()
+	leaf.data = make([]float32, int(leaf.base.length))
+	dprintf("leafF min=%v max=%v len=%d\n", leaf.min, leaf.max, len(leaf.data))
+	return
+}
+
+func (leaf *LeafF) ROOTEncode(b *Buffer) (err error) {
+	//FIXME
+	panic("not implemented")
+}
+
+// leaf of doubles
+
+type LeafD struct {
+	base baseLeaf
+	min int32
+	max int32
+	data []float64
+}
+
+func (leaf *LeafD) toBaseLeaf() *baseLeaf {
+	return &leaf.base
+}
+
+func (leaf *LeafD) Class() Class {
+	panic("not implemented")
+}
+
+func (leaf *LeafD) Name() string {
+	return leaf.base.name
+}
+
+func (leaf *LeafD) Title() string {
+	return leaf.base.title
+}
+
+func (leaf *LeafD) ROOTDecode(b *Buffer) (err error) {
+
+	vers, pos, bcnt := b.read_version()
+	dprintf("leafD-vers=%v pos=%v bcnt=%v\n", vers, pos, bcnt)
+	err = leaf.base.ROOTDecode(b)
+	if err != nil {
+		return err
+	}
+	leaf.min = b.ntoi4()
+	leaf.max = b.ntoi4()
+	leaf.data = make([]float64, int(leaf.base.length))
+	dprintf("leafD min=%v max=%v len=%d\n", leaf.min, leaf.max, len(leaf.data))
+	return
+}
+
+func (leaf *LeafD) ROOTEncode(b *Buffer) (err error) {
+	//FIXME
+	panic("not implemented")
+}
+
 func init() {
-	f := func() reflect.Value {
-		o := &LeafI{}
-		return reflect.ValueOf(o)
+	{
+		f := func() reflect.Value {
+			o := &LeafI{}
+			return reflect.ValueOf(o)
+		}
+		Factory.db["TLeafI"] = f
+		Factory.db["*groot.LeafI"] = f
 	}
-	Factory.db["TLeafI"] = f
-	Factory.db["*groot.LeafI"] = f
+
+	{
+		f := func() reflect.Value {
+			o := &LeafL{}
+			return reflect.ValueOf(o)
+		}
+		Factory.db["TLeafL"] = f
+		Factory.db["*groot.LeafL"] = f
+	}
+
+	{
+		f := func() reflect.Value {
+			o := &LeafF{}
+			return reflect.ValueOf(o)
+		}
+		Factory.db["TLeafF"] = f
+		Factory.db["*groot.LeafF"] = f
+	}
+
+	{
+		f := func() reflect.Value {
+			o := &LeafD{}
+			return reflect.ValueOf(o)
+		}
+		Factory.db["TLeafD"] = f
+		Factory.db["*groot.LeafD"] = f
+	}
 }
 
 // EOF

pkg/groot/leaf_element.go

+package groot
+
+import (
+	"reflect"
+)
+
+type LeafElement struct {
+	base   baseLeaf
+	id     int // element serial number in fInfo
+	ltype  int // leaf type
+}
+
+func (le *LeafElement) toBaseLeaf() *baseLeaf {
+	return &le.base
+}
+
+func (le *LeafElement) Class() Class {
+	panic("not implemented")
+}
+
+func (le *LeafElement) Name() string {
+	return le.base.name
+}
+
+func (le *LeafElement) Title() string {
+	return le.base.title
+}
+
+func (le *LeafElement) ROOTDecode(b *Buffer) (err error) {
+
+	spos := b.Pos()
+	vers, pos, bcnt := b.read_version()
+	dprintf("vers=%v spos=%v pos=%v bcnt=%v\n", vers, spos, pos, bcnt)
+	err = le.base.ROOTDecode(b)
+	if err != nil {
+		return err
+	}
+
+	le.id = int(b.ntoi4())
+	le.ltype = int(b.ntoi4())
+
+	b.check_byte_count(pos, bcnt, spos, "TLeafElement")
+	return
+}
+
+func (le *LeafElement) ROOTEncode(b *Buffer) (err error) {
+	panic("not implemented")
+	return
+}
+
+func init() {
+	f := func() reflect.Value {
+		o := &LeafElement{}
+		return reflect.ValueOf(o)
+	}
+	Factory.db["TLeafElement"] = f
+	Factory.db["*groot.LeafElement"] = f
+}
+
+// check interfaces
+var _ Object = (*LeafElement)(nil)
+var _ ROOTStreamer = (*LeafElement)(nil)
+

pkg/groot/tree.go

 func (tree *Tree) ROOTDecode(b *Buffer) (err error) {
 
 	vers, pos, bcnt := b.read_version()
-	printf("vers=%v pos=%v bcnt=%v\n", vers, pos, bcnt)
+	dprintf("vers=%v pos=%v bcnt=%v\n", vers, pos, bcnt)
 	tree.name, tree.title = b.read_tnamed()
-	printf("name='%v' title='%v'\n", tree.name, tree.title)
+	dprintf("name='%v' title='%v'\n", tree.name, tree.title)
 	b.read_attline()
 	b.read_attfill()
 	b.read_attmarker()
 
 	branches := b.read_obj_array()
 	dprintf("-- #nbranches: %v\n", len(branches))
+
+	leaves := b.read_obj_array()
+	dprintf("-- #nleaves: %v\n", len(leaves))
+
 	return
 }
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.