github.com/jgarto/itcv@v0.0.0-20180826224514-4eea09c1aa0d/_vendor/src/golang.org/x/tools/godoc/util/util.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 util contains utility types and functions for godoc.
     6  package util // import "golang.org/x/tools/godoc/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  // An RWValue wraps a value and permits mutually exclusive
    18  // access to it and records the time the value was last set.
    19  type RWValue struct {
    20  	mutex     sync.RWMutex
    21  	value     interface{}
    22  	timestamp time.Time // time of last set()
    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  // IsText reports whether a significant prefix of s looks like correct UTF-8;
    39  // that is, if it is likely that s is human-readable text.
    40  func IsText(s []byte) bool {
    41  	const max = 1024 // at least utf8.UTFMax
    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  			// last char may be incomplete - ignore
    48  			break
    49  		}
    50  		if c == 0xFFFD || c < ' ' && c != '\n' && c != '\t' && c != '\f' {
    51  			// decoding error or control character - not a text file
    52  			return false
    53  		}
    54  	}
    55  	return true
    56  }
    57  
    58  // textExt[x] is true if the extension x indicates a text file, and false otherwise.
    59  var textExt = map[string]bool{
    60  	".css": false, // must be served raw
    61  	".js":  false, // must be served raw
    62  }
    63  
    64  // IsTextFile reports whether the file has a known extension indicating
    65  // a text file, or if a significant chunk of the specified file looks like
    66  // correct UTF-8; that is, if it is likely that the file contains human-
    67  // readable text.
    68  func IsTextFile(fs vfs.Opener, filename string) bool {
    69  	// if the extension is known, use it for decision making
    70  	if isText, found := textExt[pathpkg.Ext(filename)]; found {
    71  		return isText
    72  	}
    73  
    74  	// the extension is not known; read an initial chunk
    75  	// of the file and check if it looks like text
    76  	f, err := fs.Open(filename)
    77  	if err != nil {
    78  		return false
    79  	}
    80  	defer f.Close()
    81  
    82  	var buf [1024]byte
    83  	n, err := f.Read(buf[0:])
    84  	if err != nil {
    85  		return false
    86  	}
    87  
    88  	return IsText(buf[0:n])
    89  }