1 package dos2unix 2 3 import "io" 4 5 // WriteFlusher combines the io.Writer interface with a buffer Flush method 6 type WriteFlusher interface { 7 io.Writer 8 Flush() error 9 } 10 11 var cr = []byte{'\r'} 12 13 type dos2unixWriter struct { 14 io.Writer 15 lastCR bool 16 } 17 18 func (d *dos2unixWriter) Write(p []byte) (int, error) { 19 var n int 20 if d.lastCR && len(p) > 0 { 21 if p[0] != '\n' { 22 _, err := d.Writer.Write(cr) 23 if err != nil { 24 return 0, err 25 } 26 } 27 d.lastCR = false 28 } 29 for pos := 0; pos < len(p); pos++ { 30 if d.lastCR { 31 if p[pos] == '\n' { 32 if pos > 1 { // more than just \r\n 33 m, err := d.Writer.Write(p[:pos-1]) 34 n += m 35 if err != nil { 36 return n, err 37 } 38 } 39 n++ 40 p = p[pos:] 41 pos = 0 42 } 43 } 44 d.lastCR = p[pos] == '\r' 45 } 46 if len(p) > 0 { 47 if d.lastCR { 48 p = p[:len(p)-1] 49 n++ 50 } 51 if len(p) > 0 { 52 m, err := d.Writer.Write(p) 53 n += m 54 if err != nil { 55 return n, err 56 } 57 } 58 } 59 return n, nil 60 } 61 62 func (d *dos2unixWriter) Flush() error { 63 if !d.lastCR { 64 return nil 65 } 66 d.lastCR = false 67 _, err := d.Writer.Write(cr) 68 return err 69 } 70 71 // DOS2UnixWriter wraps a writer to convert \r\n into \n. It is advisable to 72 // call the Flush method upon completion as a final \r may be buffered 73 func DOS2UnixWriter(w io.Writer) WriteFlusher { 74 return &dos2unixWriter{ 75 Writer: w, 76 } 77 } 78 79 type unix2dosWriter struct { 80 io.Writer 81 } 82 83 func (u unix2dosWriter) Write(p []byte) (int, error) { 84 var n int 85 for pos := 0; pos < len(p); pos++ { 86 if p[pos] == '\n' { 87 if pos > 0 { 88 m, err := u.Writer.Write(p[:pos]) 89 n += m 90 if err != nil { 91 return n, err 92 } 93 p = p[pos:] 94 pos = 0 95 } 96 if _, err := u.Writer.Write(cr); err != nil { 97 return n, err 98 } 99 } 100 } 101 if len(p) > 0 { 102 m, err := u.Writer.Write(p) 103 n += m 104 if err != nil { 105 return n, err 106 } 107 } 108 return n, nil 109 } 110 111 // Unix2DOSWriter wraps a io.Writer to convert \n into \r\n 112 func Unix2DOSWriter(w io.Writer) io.Writer { 113 return unix2dosWriter{ 114 Writer: w, 115 } 116 } 117