go-hep.org/x/hep@v0.38.1/groot/riofs/fileplugin.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 package riofs 6 7 import ( 8 "fmt" 9 "net/url" 10 "os" 11 "sort" 12 "strings" 13 "sync" 14 15 "codeberg.org/go-mmap/mmap" 16 ) 17 18 var drivers = struct { 19 sync.RWMutex 20 db map[string]func(path string) (Reader, error) 21 }{ 22 db: make(map[string]func(path string) (Reader, error)), 23 } 24 25 // Register registers a plugin to open ROOT files. 26 // Register panics if it is called twice with the same name of if the plugin 27 // function is nil. 28 func Register(name string, f func(path string) (Reader, error)) { 29 drivers.Lock() 30 defer drivers.Unlock() 31 if f == nil { 32 panic("riofs: plugin function is nil") 33 } 34 if _, dup := drivers.db[name]; dup { 35 panic(fmt.Errorf("riofs: Register called twice for plugin %q", name)) 36 } 37 drivers.db[name] = f 38 } 39 40 // Drivers returns a sorted list of the names of the registered plugins 41 // to open ROOT files. 42 func Drivers() []string { 43 drivers.RLock() 44 defer drivers.RUnlock() 45 names := make([]string, 0, len(drivers.db)) 46 for name := range drivers.db { 47 names = append(names, name) 48 } 49 sort.Strings(names) 50 return names 51 } 52 53 func openFile(path string) (Reader, error) { 54 drivers.RLock() 55 defer drivers.RUnlock() 56 57 if f, err := openLocalFile(path); err == nil { 58 return f, nil 59 } 60 61 scheme := "file" 62 if u, err := url.Parse(path); err == nil { 63 scheme = u.Scheme 64 } 65 if open, ok := drivers.db[scheme]; ok { 66 return open(path) 67 } 68 69 return nil, fmt.Errorf("riofs: no ROOT plugin to open [%s] (scheme=%s)", path, scheme) 70 } 71 72 func openLocalFile(path string) (Reader, error) { 73 path = strings.TrimPrefix(path, "file://") 74 return os.Open(path) 75 } 76 77 func mmapLocalFile(path string) (Reader, error) { 78 path = strings.TrimPrefix(path, "file+mmap://") 79 return mmap.Open(path) 80 } 81 82 func init() { 83 Register("file", openLocalFile) 84 Register("file+mmap", mmapLocalFile) 85 }