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

     1  // Copyright ©2019 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  // Package rmeta provides tools to interoperate with ROOT Meta.
     6  package rmeta // import "go-hep.org/x/hep/groot/rmeta"
     7  
     8  import (
     9  	"fmt"
    10  	"strings"
    11  )
    12  
    13  // CxxTemplate represents a C++ template, such as 'vector<T>', 'map<K,V,Cmp>'.
    14  type CxxTemplate struct {
    15  	Name string   // Name is the name of the template type
    16  	Args []string // Args is the list of template arguments
    17  }
    18  
    19  // CxxTemplateOf extracts the typenames of a C++ templated typename.
    20  // Ex:
    21  //
    22  //	std::map<K,V> -> []string{"K", "V"}
    23  //	std::vector<T> -> []string{"T"}
    24  //	Foo<T1,T2,std::map<K,V>> -> []string{"T1", "T2", "std::map<K,V>"}
    25  func CxxTemplateFrom(typename string) CxxTemplate {
    26  	var (
    27  		name = strings.TrimSpace(typename)
    28  		lh   = strings.Index(name, "<")
    29  	)
    30  	if lh < 0 {
    31  		panic(fmt.Errorf("rmeta: missing '<' in %q", typename))
    32  	}
    33  	if !strings.HasSuffix(name, ">") {
    34  		panic(fmt.Errorf("rmeta: missing '>' in %q", typename))
    35  	}
    36  	cxx := CxxTemplate{
    37  		Name: name[:lh],
    38  	}
    39  	name = name[lh+1:]        // drop heading 'xxx<'
    40  	name = name[:len(name)-1] // drop trailing '>'
    41  	name = strings.TrimSpace(name)
    42  
    43  	if !strings.Contains(name, ",") {
    44  		if name != "" {
    45  			cxx.Args = []string{name}
    46  		}
    47  		return cxx
    48  	}
    49  
    50  	var (
    51  		bldr strings.Builder
    52  		tmpl int
    53  	)
    54  	for _, s := range name {
    55  		switch s {
    56  		case '<':
    57  			tmpl++
    58  			bldr.WriteRune(s)
    59  		case '>':
    60  			tmpl--
    61  			bldr.WriteRune(s)
    62  		case ',':
    63  			switch {
    64  			case tmpl > 0:
    65  				bldr.WriteRune(s)
    66  			default:
    67  				typ := strings.TrimSpace(bldr.String())
    68  				if typ == "" {
    69  					panic(fmt.Errorf("rmeta: invalid empty type argument %q", typename))
    70  				}
    71  				cxx.Args = append(cxx.Args, typ)
    72  				bldr.Reset()
    73  			}
    74  		default:
    75  			bldr.WriteRune(s)
    76  
    77  		}
    78  	}
    79  	typ := strings.TrimSpace(bldr.String())
    80  	if typ == "" {
    81  		panic(fmt.Errorf("rmeta: invalid empty type argument %q", typename))
    82  	}
    83  	cxx.Args = append(cxx.Args, typ)
    84  	return cxx
    85  }
    86  
    87  // TypeName2Enum returns the Enum corresponding to the provided C++ (or Go) typename.
    88  func TypeName2Enum(typename string) (Enum, bool) {
    89  	switch typename {
    90  	case "bool", "_Bool", "Bool_t":
    91  		return Bool, true
    92  	case "byte", "uint8", "uint8_t", "unsigned char", "UChar_t", "Byte_t":
    93  		return Uint8, true
    94  	case "uint16", "uint16_t", "unsigned short", "UShort_t":
    95  		return Uint16, true
    96  	case "uint32", "uint32_t", "unsigned", "unsigned int", "UInt_t":
    97  		return Uint32, true
    98  	case "uint64", "uint64_t", "unsigned long", "unsigned long int", "ULong_t", "ULong64_t":
    99  		return Uint64, true
   100  
   101  	case "char*":
   102  		return CharStar, true
   103  	case "Bits_t":
   104  		return Bits, true
   105  
   106  	case "int8", "int8_t", "char", "Char_t":
   107  		return Int8, true
   108  	case "int16", "int16_t", "short", "Short_t", "Version_t",
   109  		"Font_t", "Style_t", "Marker_t", "Width_t",
   110  		"Color_t",
   111  		"SCoord_t":
   112  		return Int16, true
   113  	case "int32", "int32_t", "int", "Int_t":
   114  		return Int32, true
   115  	case "int64", "int64_t", "long", "long int", "Long_t", "Long64_t",
   116  		"Seek_t":
   117  		return Int64, true
   118  
   119  	case "float32", "float", "Float_t", "float32_t",
   120  		"Angle_t", "Size_t":
   121  		return Float32, true
   122  	case "float64", "double", "Double_t", "float64_t",
   123  		"Coord_t":
   124  		return Float64, true
   125  	case "Float16_t", "Float16":
   126  		return Float16, true
   127  	case "Double32_t", "Double32":
   128  		return Double32, true
   129  
   130  	case "TString", "Option_t":
   131  		return TString, true
   132  	case "string", "std::string":
   133  		return STLstring, true
   134  	case "TObject":
   135  		return TObject, true
   136  	case "TNamed":
   137  		return TNamed, true
   138  	}
   139  
   140  	return -1, false
   141  }