go-hep.org/x/hep@v0.38.1/groot/gen.rcont.go (about)

     1  // Copyright ©2018 The go-hep Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build ignore
     6  
     7  package main
     8  
     9  import (
    10  	"fmt"
    11  	"log"
    12  	"os"
    13  	"text/template"
    14  
    15  	"go-hep.org/x/hep/groot/internal/genroot"
    16  	"go-hep.org/x/hep/groot/internal/rtests"
    17  )
    18  
    19  func main() {
    20  	genArrays()
    21  	genTClonesArrayData()
    22  }
    23  
    24  func genArrays() {
    25  	fname := "./rcont/array_gen.go"
    26  	year := genroot.ExtractYear(fname)
    27  	f, err := os.Create(fname)
    28  	if err != nil {
    29  		log.Fatal(err)
    30  	}
    31  	defer f.Close()
    32  
    33  	genroot.GenImports(year, "rcont", f,
    34  		"reflect",
    35  		"",
    36  		"go-hep.org/x/hep/groot/root",
    37  		"go-hep.org/x/hep/groot/rbytes",
    38  		"go-hep.org/x/hep/groot/rtypes",
    39  		"go-hep.org/x/hep/groot/rvers",
    40  	)
    41  
    42  	for i, typ := range []struct {
    43  		Name  string
    44  		Type  string
    45  		RFunc string
    46  		DType string
    47  		WFunc string
    48  	}{
    49  		{
    50  			Name:  "ArrayC",
    51  			Type:  "int8",
    52  			RFunc: "r.ReadArrayI8",
    53  			DType: "I8",
    54  			WFunc: "w.WriteArrayI8",
    55  		},
    56  		{
    57  			Name:  "ArrayS",
    58  			Type:  "int16",
    59  			RFunc: "r.ReadArrayI16",
    60  			DType: "I16",
    61  			WFunc: "w.WriteArrayI16",
    62  		},
    63  		{
    64  			Name:  "ArrayI",
    65  			Type:  "int32",
    66  			RFunc: "r.ReadArrayI32",
    67  			DType: "I32",
    68  			WFunc: "w.WriteArrayI32",
    69  		},
    70  		{
    71  			Name:  "ArrayL",
    72  			Type:  "int64",
    73  			RFunc: "r.ReadArrayI64",
    74  			DType: "I64",
    75  			WFunc: "w.WriteArrayI64",
    76  		},
    77  		{
    78  			Name:  "ArrayL64",
    79  			Type:  "int64",
    80  			RFunc: "r.ReadArrayI64",
    81  			DType: "I64",
    82  			WFunc: "w.WriteArrayI64",
    83  		},
    84  		{
    85  			Name:  "ArrayF",
    86  			Type:  "float32",
    87  			RFunc: "r.ReadArrayF32",
    88  			DType: "F32",
    89  			WFunc: "w.WriteArrayF32",
    90  		},
    91  		{
    92  			Name:  "ArrayD",
    93  			Type:  "float64",
    94  			RFunc: "r.ReadArrayF64",
    95  			DType: "F64",
    96  			WFunc: "w.WriteArrayF64",
    97  		},
    98  	} {
    99  		if i > 0 {
   100  			fmt.Fprintf(f, "\n")
   101  		}
   102  		tmpl := template.Must(template.New(typ.Name).Parse(arrayTmpl))
   103  		err = tmpl.Execute(f, typ)
   104  		if err != nil {
   105  			log.Fatalf("error executing template for %q: %v\n", typ.Name, err)
   106  		}
   107  	}
   108  
   109  	err = f.Close()
   110  	if err != nil {
   111  		log.Fatal(err)
   112  	}
   113  	genroot.GoFmt(f)
   114  }
   115  
   116  const arrayTmpl = `// {{.Name}} implements ROOT T{{.Name}}
   117  type {{.Name}} struct {
   118  	Data []{{.Type}}
   119  }
   120  
   121  func (*{{.Name}}) RVersion() int16 {
   122  	return rvers.{{.Name}}
   123  }
   124  
   125  // Class returns the ROOT class name.
   126  func (*{{.Name}}) Class() string {
   127  	return "T{{.Name}}"
   128  }
   129  
   130  func (arr *{{.Name}}) Len() int {
   131  	return len(arr.Data)
   132  }
   133  
   134  func (arr *{{.Name}}) At(i int) {{.Type}} {
   135  	return arr.Data[i]
   136  }
   137  
   138  func (arr *{{.Name}}) Get(i int) any {
   139  	return arr.Data[i]
   140  }
   141  
   142  func (arr *{{.Name}}) Set(i int, v any) {
   143  	arr.Data[i] = v.({{.Type}})
   144  }
   145  
   146  func (arr *{{.Name}}) MarshalROOT(w *rbytes.WBuffer) (int, error) {
   147  	if w.Err() != nil {
   148  		return 0, w.Err()
   149  	}
   150  
   151  	pos := w.Pos()
   152  	w.WriteI32(int32(len(arr.Data)))
   153  	{{.WFunc}}(arr.Data)
   154  
   155  	return int(w.Pos()-pos), w.Err()
   156  }
   157  
   158  func (arr *{{.Name}}) UnmarshalROOT(r *rbytes.RBuffer) error {
   159  	if r.Err() != nil {
   160  		return r.Err()
   161  	}
   162  
   163  	n := int(r.ReadI32())
   164  	arr.Data = rbytes.Resize{{.DType}}(arr.Data, n)
   165  	{{.RFunc}}(arr.Data)
   166  
   167  	return r.Err()
   168  }
   169  
   170  func init() {
   171  	f := func() reflect.Value {
   172  		o := &{{.Name}}{}
   173  		return reflect.ValueOf(o)
   174  	}
   175  	rtypes.Factory.Add("T{{.Name}}", f)
   176  }
   177  
   178  var (
   179  	_ root.Array         = (*{{.Name}})(nil)
   180  	_ rbytes.Marshaler   = (*{{.Name}})(nil)
   181  	_ rbytes.Unmarshaler = (*{{.Name}})(nil)
   182  )
   183  `
   184  
   185  func genTClonesArrayData() {
   186  	macro := `
   187  void gen_tclonesarray(const char *fname, bool bypass) {
   188  	auto f = TFile::Open(fname, "RECREATE");
   189  	auto c = new TClonesArray("TObjString", 3);
   190  	(*c)[0] = new TObjString("Elem-0");
   191  	(*c)[1] = new TObjString("elem-1");
   192  	(*c)[2] = new TObjString("Elem-20");
   193  
   194  	c->BypassStreamer(bypass);
   195  	f->WriteObjectAny(c, "TClonesArray", "clones");
   196  	f->Write();
   197  	f->Close();
   198  }
   199  `
   200  
   201  	for _, v := range []struct {
   202  		name   string
   203  		bypass bool
   204  	}{
   205  		{
   206  			name:   "testdata/tclonesarray-with-streamerbypass.root",
   207  			bypass: true,
   208  		},
   209  		{
   210  			name:   "testdata/tclonesarray-no-streamerbypass.root",
   211  			bypass: false,
   212  		},
   213  	} {
   214  		out, err := rtests.RunCxxROOT("gen_tclonesarray", []byte(macro), v.name, v.bypass)
   215  		if err != nil {
   216  			log.Fatalf("could not run gen-tclonesarray:\n%s\nerror: %+v", out, err)
   217  		}
   218  	}
   219  }