github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/internal/file/wofile.go (about) 1 package file 2 3 import ( 4 "bufio" 5 "bytes" 6 "errors" 7 "os" 8 "strings" 9 ) 10 11 type wofile struct { 12 *os.File 13 bw *bufio.Writer 14 mode int 15 closed bool 16 std bool 17 probe [1]byte // workaround for https://github.com/golang/go/issues/19122 18 } 19 20 func (wo *wofile) IsClosed() bool { 21 return wo.closed 22 } 23 24 func (wo *wofile) Close() error { 25 if wo.std { 26 return errors.New("cannot close standard file") 27 } 28 29 if err := wo.bw.Flush(); err != nil { 30 return err 31 } 32 33 if err := wo.File.Close(); err != nil { 34 return err 35 } 36 37 wo.closed = true 38 39 return nil 40 } 41 42 func (wo *wofile) Write(p []byte) (nn int, err error) { 43 switch wo.mode { 44 case IONBF: 45 nn, err = wo.File.Write(p) 46 case IOFBF: 47 nn, err = wo.bw.Write(p) 48 case IOLBF: 49 i := bytes.LastIndexByte(p, '\n') 50 if i == -1 { 51 nn, err = wo.bw.Write(p) 52 } else { 53 nn, err = wo.bw.Write(p[:i+1]) 54 if err != nil { 55 return 56 } 57 err = wo.bw.Flush() 58 if err != nil { 59 return 60 } 61 62 nn, err = wo.bw.Write(p[i+1:]) 63 } 64 } 65 66 return 67 } 68 69 func (wo *wofile) WriteString(s string) (nn int, err error) { 70 switch wo.mode { 71 case IONBF: 72 nn, err = wo.File.WriteString(s) 73 case IOFBF: 74 nn, err = wo.bw.WriteString(s) 75 case IOLBF: 76 i := strings.LastIndexByte(s, '\n') 77 if i == -1 { 78 nn, err = wo.bw.WriteString(s) 79 } else { 80 nn, err = wo.bw.WriteString(s[:i+1]) 81 if err != nil { 82 return 83 } 84 err = wo.bw.Flush() 85 if err != nil { 86 return 87 } 88 89 nn, err = wo.bw.WriteString(s[i+1:]) 90 } 91 } 92 93 return 94 } 95 96 func (wo *wofile) Flush() error { 97 return wo.bw.Flush() 98 } 99 100 func (wo *wofile) UnreadByte() error { 101 return os.ErrInvalid 102 } 103 104 func (wo *wofile) ReadByte() (c byte, err error) { 105 _, err = wo.Read(wo.probe[:]) 106 107 return 0, err 108 } 109 110 func (wo *wofile) ReadBytes(delim byte) (line []byte, err error) { 111 _, err = wo.Read(wo.probe[:]) 112 113 return nil, err 114 } 115 116 func (wo *wofile) Seek(offset int64, whence int) (n int64, err error) { 117 if err := wo.bw.Flush(); err != nil { 118 return 0, err 119 } 120 121 return wo.File.Seek(offset, whence) 122 } 123 124 func (wo *wofile) Setvbuf(mode int, size int) (err error) { 125 err = wo.bw.Flush() 126 if err != nil { 127 return 128 } 129 130 wo.mode = mode 131 132 if size > 0 { 133 wo.bw = bufio.NewWriterSize(wo.File, size) 134 } 135 136 return 137 }