1// Copyright 2009 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 ioutil implements some I/O utility functions.
6package ioutil
7
8import (
9	"bytes"
10	"io"
11	"os"
12	"sort"
13	"sync"
14)
15
16// readAll reads from r until an error or EOF and returns the data it read
17// from the internal buffer allocated with a specified capacity.
18func readAll(r io.Reader, capacity int64) (b []byte, err error) {
19	var buf bytes.Buffer
20	// If the buffer overflows, we will get bytes.ErrTooLarge.
21	// Return that as an error. Any other panic remains.
22	defer func() {
23		e := recover()
24		if e == nil {
25			return
26		}
27		if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
28			err = panicErr
29		} else {
30			panic(e)
31		}
32	}()
33	if int64(int(capacity)) == capacity {
34		buf.Grow(int(capacity))
35	}
36	_, err = buf.ReadFrom(r)
37	return buf.Bytes(), err
38}
39
40// ReadAll reads from r until an error or EOF and returns the data it read.
41// A successful call returns err == nil, not err == EOF. Because ReadAll is
42// defined to read from src until EOF, it does not treat an EOF from Read
43// as an error to be reported.
44func ReadAll(r io.Reader) ([]byte, error) {
45	return readAll(r, bytes.MinRead)
46}
47
48// ReadFile reads the file named by filename and returns the contents.
49// A successful call returns err == nil, not err == EOF. Because ReadFile
50// reads the whole file, it does not treat an EOF from Read as an error
51// to be reported.
52func ReadFile(filename string) ([]byte, error) {
53	f, err := os.Open(filename)
54	if err != nil {
55		return nil, err
56	}
57	defer f.Close()
58	// It's a good but not certain bet that FileInfo will tell us exactly how much to
59	// read, so let's try it but be prepared for the answer to be wrong.
60	var n int64 = bytes.MinRead
61
62	if fi, err := f.Stat(); err == nil {
63		// As initial capacity for readAll, use Size + a little extra in case Size
64		// is zero, and to avoid another allocation after Read has filled the
65		// buffer. The readAll call will read into its allocated internal buffer
66		// cheaply. If the size was wrong, we'll either waste some space off the end
67		// or reallocate as needed, but in the overwhelmingly common case we'll get
68		// it just right.
69		if size := fi.Size() + bytes.MinRead; size > n {
70			n = size
71		}
72	}
73	return readAll(f, n)
74}
75
76// WriteFile writes data to a file named by filename.
77// If the file does not exist, WriteFile creates it with permissions perm;
78// otherwise WriteFile truncates it before writing.
79func WriteFile(filename string, data []byte, perm os.FileMode) error {
80	f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
81	if err != nil {
82		return err
83	}
84	n, err := f.Write(data)
85	if err == nil && n < len(data) {
86		err = io.ErrShortWrite
87	}
88	if err1 := f.Close(); err == nil {
89		err = err1
90	}
91	return err
92}
93
94// ReadDir reads the directory named by dirname and returns
95// a list of directory entries sorted by filename.
96func ReadDir(dirname string) ([]os.FileInfo, error) {
97	f, err := os.Open(dirname)
98	if err != nil {
99		return nil, err
100	}
101	list, err := f.Readdir(-1)
102	f.Close()
103	if err != nil {
104		return nil, err
105	}
106	sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() })
107	return list, nil
108}
109
110type nopCloser struct {
111	io.Reader
112}
113
114func (nopCloser) Close() error { return nil }
115
116// NopCloser returns a ReadCloser with a no-op Close method wrapping
117// the provided Reader r.
118func NopCloser(r io.Reader) io.ReadCloser {
119	return nopCloser{r}
120}
121
122type devNull int
123
124// devNull implements ReaderFrom as an optimization so io.Copy to
125// ioutil.Discard can avoid doing unnecessary work.
126var _ io.ReaderFrom = devNull(0)
127
128func (devNull) Write(p []byte) (int, error) {
129	return len(p), nil
130}
131
132func (devNull) WriteString(s string) (int, error) {
133	return len(s), nil
134}
135
136var blackHolePool = sync.Pool{
137	New: func() interface{} {
138		b := make([]byte, 8192)
139		return &b
140	},
141}
142
143func (devNull) ReadFrom(r io.Reader) (n int64, err error) {
144	bufp := blackHolePool.Get().(*[]byte)
145	readSize := 0
146	for {
147		readSize, err = r.Read(*bufp)
148		n += int64(readSize)
149		if err != nil {
150			blackHolePool.Put(bufp)
151			if err == io.EOF {
152				return n, nil
153			}
154			return
155		}
156	}
157}
158
159// Discard is an io.Writer on which all Write calls succeed
160// without doing anything.
161var Discard io.Writer = devNull(0)
162