github.com/jgarto/itcv@v0.0.0-20180826224514-4eea09c1aa0d/_vendor/src/golang.org/x/tools/godoc/vfs/mapfs/mapfs.go (about) 1 // Copyright 2013 The Go 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 mapfs file provides an implementation of the FileSystem 6 // interface based on the contents of a map[string]string. 7 package mapfs // import "golang.org/x/tools/godoc/vfs/mapfs" 8 9 import ( 10 "io" 11 "os" 12 pathpkg "path" 13 "sort" 14 "strings" 15 "time" 16 17 "golang.org/x/tools/godoc/vfs" 18 ) 19 20 // New returns a new FileSystem from the provided map. 21 // Map keys should be forward slash-separated pathnames 22 // and not contain a leading slash. 23 func New(m map[string]string) vfs.FileSystem { 24 return mapFS(m) 25 } 26 27 // mapFS is the map based implementation of FileSystem 28 type mapFS map[string]string 29 30 func (fs mapFS) String() string { return "mapfs" } 31 32 func (fs mapFS) RootType(p string) vfs.RootType { 33 return "" 34 } 35 36 func (fs mapFS) Close() error { return nil } 37 38 func filename(p string) string { 39 return strings.TrimPrefix(p, "/") 40 } 41 42 func (fs mapFS) Open(p string) (vfs.ReadSeekCloser, error) { 43 b, ok := fs[filename(p)] 44 if !ok { 45 return nil, os.ErrNotExist 46 } 47 return nopCloser{strings.NewReader(b)}, nil 48 } 49 50 func fileInfo(name, contents string) os.FileInfo { 51 return mapFI{name: pathpkg.Base(name), size: len(contents)} 52 } 53 54 func dirInfo(name string) os.FileInfo { 55 return mapFI{name: pathpkg.Base(name), dir: true} 56 } 57 58 func (fs mapFS) Lstat(p string) (os.FileInfo, error) { 59 b, ok := fs[filename(p)] 60 if ok { 61 return fileInfo(p, b), nil 62 } 63 ents, _ := fs.ReadDir(p) 64 if len(ents) > 0 { 65 return dirInfo(p), nil 66 } 67 return nil, os.ErrNotExist 68 } 69 70 func (fs mapFS) Stat(p string) (os.FileInfo, error) { 71 return fs.Lstat(p) 72 } 73 74 // slashdir returns path.Dir(p), but special-cases paths not beginning 75 // with a slash to be in the root. 76 func slashdir(p string) string { 77 d := pathpkg.Dir(p) 78 if d == "." { 79 return "/" 80 } 81 if strings.HasPrefix(p, "/") { 82 return d 83 } 84 return "/" + d 85 } 86 87 func (fs mapFS) ReadDir(p string) ([]os.FileInfo, error) { 88 p = pathpkg.Clean(p) 89 var ents []string 90 fim := make(map[string]os.FileInfo) // base -> fi 91 for fn, b := range fs { 92 dir := slashdir(fn) 93 isFile := true 94 var lastBase string 95 for { 96 if dir == p { 97 base := lastBase 98 if isFile { 99 base = pathpkg.Base(fn) 100 } 101 if fim[base] == nil { 102 var fi os.FileInfo 103 if isFile { 104 fi = fileInfo(fn, b) 105 } else { 106 fi = dirInfo(base) 107 } 108 ents = append(ents, base) 109 fim[base] = fi 110 } 111 } 112 if dir == "/" { 113 break 114 } else { 115 isFile = false 116 lastBase = pathpkg.Base(dir) 117 dir = pathpkg.Dir(dir) 118 } 119 } 120 } 121 if len(ents) == 0 { 122 return nil, os.ErrNotExist 123 } 124 125 sort.Strings(ents) 126 var list []os.FileInfo 127 for _, dir := range ents { 128 list = append(list, fim[dir]) 129 } 130 return list, nil 131 } 132 133 // mapFI is the map-based implementation of FileInfo. 134 type mapFI struct { 135 name string 136 size int 137 dir bool 138 } 139 140 func (fi mapFI) IsDir() bool { return fi.dir } 141 func (fi mapFI) ModTime() time.Time { return time.Time{} } 142 func (fi mapFI) Mode() os.FileMode { 143 if fi.IsDir() { 144 return 0755 | os.ModeDir 145 } 146 return 0444 147 } 148 func (fi mapFI) Name() string { return pathpkg.Base(fi.name) } 149 func (fi mapFI) Size() int64 { return int64(fi.size) } 150 func (fi mapFI) Sys() interface{} { return nil } 151 152 type nopCloser struct { 153 io.ReadSeeker 154 } 155 156 func (nc nopCloser) Close() error { return nil }