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  }