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 }