go-hep.org/x/hep@v0.38.1/groot/rtypes/factory.go (about) 1 // Copyright ©2017 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 rtypes 6 7 import ( 8 "errors" 9 "reflect" 10 "sync" 11 ) 12 13 var ( 14 errInvalidType = errors.New("rtypes: invalid classname") 15 ) 16 17 // FactoryFct creates new values of a given type. 18 type FactoryFct func() reflect.Value 19 20 type factory struct { 21 mu sync.RWMutex 22 db map[string]FactoryFct // a registry of all factory functions by type name 23 } 24 25 func (f *factory) Len() int { 26 f.mu.RLock() 27 n := len(f.db) 28 f.mu.RUnlock() 29 return n 30 } 31 32 func (f *factory) Keys() []string { 33 f.mu.RLock() 34 keys := make([]string, 0, len(f.db)) 35 for k := range f.db { 36 keys = append(keys, k) 37 } 38 f.mu.RUnlock() 39 return keys 40 } 41 42 func (f *factory) HasKey(n string) bool { 43 f.mu.RLock() 44 _, ok := f.db[n] 45 f.mu.RUnlock() 46 return ok 47 } 48 49 func (f *factory) Get(n string) FactoryFct { 50 if n == "" { 51 panic(errInvalidType) 52 } 53 54 f.mu.RLock() 55 fct, ok := f.db[n] 56 f.mu.RUnlock() 57 if ok { 58 return fct 59 } 60 61 // if we are here, nobody registered a streamer+factory for 'string'. 62 // try our streamer-less rbase.String version. 63 if n == "string" { 64 f.mu.RLock() 65 fct, ok := f.db["*rbase.String"] 66 f.mu.RUnlock() 67 if ok { 68 return fct 69 } 70 } 71 72 f.mu.RLock() 73 obj := f.db["*rdict.Object"] 74 f.mu.RUnlock() 75 76 fct = func() reflect.Value { 77 v := obj() 78 v.Interface().(setClasser).SetClass(n) 79 return v 80 } 81 82 return fct 83 } 84 85 func (f *factory) Add(n string, fct FactoryFct) { 86 f.mu.Lock() 87 f.db[n] = fct 88 f.mu.Unlock() 89 } 90 91 type setClasser interface { 92 SetClass(name string) 93 } 94 95 var Factory = &factory{ 96 db: make(map[string]FactoryFct), 97 }