...
1
2
3
4
5
6 package util
7
8 import (
9 pathpkg "path"
10 "sync"
11 "time"
12 "unicode/utf8"
13
14 "golang.org/x/tools/godoc/vfs"
15 )
16
17
18
19 type RWValue struct {
20 mutex sync.RWMutex
21 value interface{}
22 timestamp time.Time
23 }
24
25 func (v *RWValue) Set(value interface{}) {
26 v.mutex.Lock()
27 v.value = value
28 v.timestamp = time.Now()
29 v.mutex.Unlock()
30 }
31
32 func (v *RWValue) Get() (interface{}, time.Time) {
33 v.mutex.RLock()
34 defer v.mutex.RUnlock()
35 return v.value, v.timestamp
36 }
37
38
39
40 func IsText(s []byte) bool {
41 const max = 1024
42 if len(s) > max {
43 s = s[0:max]
44 }
45 for i, c := range string(s) {
46 if i+utf8.UTFMax > len(s) {
47
48 break
49 }
50 if c == 0xFFFD || c < ' ' && c != '\n' && c != '\t' && c != '\f' {
51
52 return false
53 }
54 }
55 return true
56 }
57
58
59 var textExt = map[string]bool{
60 ".css": false,
61 ".js": false,
62 ".svg": false,
63 }
64
65
66
67
68
69 func IsTextFile(fs vfs.Opener, filename string) bool {
70
71 if isText, found := textExt[pathpkg.Ext(filename)]; found {
72 return isText
73 }
74
75
76
77 f, err := fs.Open(filename)
78 if err != nil {
79 return false
80 }
81 defer f.Close()
82
83 var buf [1024]byte
84 n, err := f.Read(buf[0:])
85 if err != nil {
86 return false
87 }
88
89 return IsText(buf[0:n])
90 }
91
View as plain text