|
23 | 23 |
|
24 | 24 | (defuvfsfn fs_open [path flags mode] :result) |
25 | 25 | (defuvfsfn fs_read [file bufs nbufs offset] :result) |
| 26 | +(defuvfsfn fs_write [file bufs nbufs offset] :result) |
26 | 27 | (defuvfsfn fs_close [file] :result) |
27 | 28 |
|
28 | 29 |
|
|
59 | 60 | @result)) |
60 | 61 | acc)))))) |
61 | 62 |
|
| 63 | + |
62 | 64 | (defn open-read |
63 | 65 | {:doc "Open a file for reading, returning a IInputStream" |
64 | 66 | :added "0.1"} |
65 | 67 | [filename] |
66 | 68 | (assert (string? filename) "Filename must be a string") |
67 | 69 | (->FileStream (fs_open filename uv/O_RDONLY 0) 0 (uv/uv_buf_t))) |
68 | 70 |
|
| 71 | + |
69 | 72 | (defn read-line |
70 | 73 | "Read one line from input-stream for each invocation. |
71 | 74 | nil when all lines have been read" |
|
89 | 92 | (when-let [line (read-line input-stream)] |
90 | 93 | (cons line (lazy-seq (line-seq input-stream))))) |
91 | 94 |
|
92 | | -(deftype FileOutputStream [fp] |
| 95 | +(deftype FileOutputStream [fp offset uvbuf] |
93 | 96 | IOutputStream |
94 | 97 | (write-byte [this val] |
95 | | - (assert (integer? val) "Value must be a int") |
96 | | - (fputc val fp)) |
| 98 | + (assert false)) |
97 | 99 | (write [this buffer] |
98 | | - (fwrite buffer 1 (count buffer) fp)) |
| 100 | + (let [_ (pixie.ffi/set! uvbuf :base buffer) |
| 101 | + _ (pixie.ffi/set! uvbuf :len (count buffer)) |
| 102 | + write-count (fs_write fp uvbuf 1 offset)] |
| 103 | + (when (neg? write-count) |
| 104 | + (throw (uv/uv_err_name read-count))) |
| 105 | + (assert (= write-count (count buffer)) (str "Write error!" write-count " " (count buffer))) |
| 106 | + (set-field! this :offset (+ offset write-count)) |
| 107 | + (set-buffer-count! buffer write-count) |
| 108 | + write-count)) |
99 | 109 | IClosable |
100 | 110 | (close [this] |
101 | 111 | (fclose fp))) |
102 | 112 |
|
| 113 | +(deftype BufferedOutputStream [downstream idx buffer] |
| 114 | + IOutputStream |
| 115 | + (write-byte [this val] |
| 116 | + (pixie.ffi/pack! buffer idx CUInt8 val) |
| 117 | + (set-field! this :idx (inc idx)) |
| 118 | + (when (= idx (buffer-capacity buffer)) |
| 119 | + (write downstream buffer) |
| 120 | + (set-field this :idx 0))) |
| 121 | + IClosable |
| 122 | + (close [this] |
| 123 | + (set-buffer-count! buffer idx) |
| 124 | + (write downstream buffer))) |
| 125 | + |
| 126 | +(defn buffered-output-stream [downstream size] |
| 127 | + (->BufferedOutputStream downstream 0 (buffer size))) |
| 128 | + |
| 129 | + |
| 130 | +(defn throw-on-error [result] |
| 131 | + (when (neg? result) |
| 132 | + (throw (uv/uv_err_name result))) |
| 133 | + result) |
| 134 | + |
| 135 | +(defn open-write |
| 136 | + {:doc "Open a file for reading, returning a IInputStream" |
| 137 | + :added "0.1"} |
| 138 | + [filename] |
| 139 | + (assert (string? filename) "Filename must be a string") |
| 140 | + (->FileOutputStream (throw-on-error (fs_open filename uv/O_WRONLY 0)) |
| 141 | + 0 |
| 142 | + (uv/uv_buf_t))) |
| 143 | + |
| 144 | + |
103 | 145 | (defn file-output-rf [filename] |
104 | | - (let [fp (->FileOutputStream (fopen filename "w"))] |
| 146 | + (let [fp (buffered-output-stream (open-write filename) |
| 147 | + DEFAULT-BUFFER-SIZE)] |
105 | 148 | (fn ([] 0) |
106 | | - ([cnt] (close fp) cnt) |
107 | | - ([cnt chr] |
| 149 | + ([_] (close fp) nil) |
| 150 | + ([_ chr] |
108 | 151 | (assert (integer? chr)) |
109 | | - (let [written (write-byte fp chr)] |
110 | | - (if (= written 0) |
111 | | - (reduced cnt) |
112 | | - (+ cnt written))))))) |
| 152 | + (write-byte fp chr) |
| 153 | + nil)))) |
113 | 154 |
|
114 | 155 |
|
115 | 156 | (defn spit [filename val] |
|
0 commit comments