Skip to content

Commit 2c4012a

Browse files
committed
Merge pull request #256 from thomasmulvaney/seekable-streams
add ISeekableStream protocol
2 parents 5b194c8 + 1838d80 commit 2c4012a

File tree

4 files changed

+54
-20
lines changed

4 files changed

+54
-20
lines changed

pixie/io-blocking.pxi

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44

55
(def fopen (ffi-fn libc "fopen" [CCharP CCharP] CVoidP))
6+
(def fseek (ffi-fn libc "fseek" [CVoidP CInt CInt] CInt))
7+
(def ftell (ffi-fn libc "ftell" [CVoidP] CInt))
8+
(def -rewind (ffi-fn libc "rewind" [CVoidP] CVoidP))
69
(def fread (ffi-fn libc "fread" [CVoidP CInt CInt CVoidP] CInt))
710
(def fgetc (ffi-fn libc "fgetc" [CVoidP] CInt))
811
(def fputc (ffi-fn libc "fputc" [CInt CVoidP] CInt))
@@ -15,6 +18,18 @@
1518

1619
(def DEFAULT-BUFFER-SIZE 1024)
1720

21+
(defn default-stream-reducer [this f init]
22+
(let [buf (buffer DEFAULT-BUFFER-SIZE)
23+
rrf (preserving-reduced f)]
24+
(loop [acc init]
25+
(let [read-count (read this buf DEFAULT-BUFFER-SIZE)]
26+
(if (> read-count 0)
27+
(let [result (reduce rrf acc buf)]
28+
(if (not (reduced? result))
29+
(recur result)
30+
@result))
31+
acc)))))
32+
1833
(deftype FileStream [fp]
1934
IInputStream
2035
(read [this buffer len]
@@ -25,21 +40,17 @@
2540
read-count))
2641
(read-byte [this]
2742
(fgetc buffer))
43+
ISeekableStream
44+
(seek [this pos]
45+
(fseek fp pos 0))
46+
(rewind [this]
47+
(-rewind fp))
2848
IDisposable
2949
(-dispose! [this]
3050
(fclose fp))
3151
IReduce
3252
(-reduce [this f init]
33-
(let [buf (buffer DEFAULT-BUFFER-SIZE)
34-
rrf (preserving-reduced f)]
35-
(loop [acc init]
36-
(let [read-count (read this buf DEFAULT-BUFFER-SIZE)]
37-
(if (> read-count 0)
38-
(let [result (reduce rrf acc buf)]
39-
(if (not (reduced? result))
40-
(recur result)
41-
@result))
42-
acc))))))
53+
(default-stream-reducer this f init)))
4354

4455
(defn open-read
4556
{:doc "Open a file for reading, returning a IInputStream"
@@ -109,6 +120,15 @@
109120
(dispose! c)
110121
result))
111122

123+
(defn slurp-stream [stream]
124+
(let [c stream
125+
result (transduce
126+
(map char)
127+
string-builder
128+
c)]
129+
(dispose! c)
130+
result))
131+
112132
(deftype ProcessInputStream [fp]
113133
IInputStream
114134
(read [this buffer len]
@@ -124,16 +144,7 @@
124144
(pclose fp))
125145
IReduce
126146
(-reduce [this f init]
127-
(let [buf (buffer DEFAULT-BUFFER-SIZE)
128-
rrf (preserving-reduced f)]
129-
(loop [acc init]
130-
(let [read-count (read this buf DEFAULT-BUFFER-SIZE)]
131-
(if (> read-count 0)
132-
(let [result (reduce rrf acc buf)]
133-
(if (not (reduced? result))
134-
(recur result)
135-
@result))
136-
acc))))))
147+
(default-stream-reducer this f init)))
137148

138149

139150
(defn popen-read

pixie/io.pxi

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@
4444
(set-field! this :offset (+ offset read-count))
4545
(set-buffer-count! buffer read-count)
4646
read-count))
47+
ISeekableStream
48+
(position [this]
49+
offset)
50+
(rewind [this]
51+
(set-field! this :offset 0))
52+
(seek [this pos]
53+
(set-field! this :offset pos))
4754
IDisposable
4855
(-dispose! [this]
4956
(dispose! uvbuf)

pixie/streams.pxi

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,8 @@
1111

1212
(defprotocol IByteOutputStream
1313
(write-byte [this byte]))
14+
15+
(defprotocol ISeekableStream
16+
(position [this])
17+
(seek [this position])
18+
(rewind [this]))

tests/pixie/tests/test-io.pxi

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(ns pixie.tests.test-io
22
(require pixie.test :as t)
3+
(require pixie.streams :as st :refer :all)
34
(require pixie.io :as io))
45

56
(t/deftest test-file-reduction
@@ -24,6 +25,16 @@
2425
s (io/line-seq f)]
2526
(t/assert= (last s) "Second line.")))
2627

28+
(t/deftest test-seek
29+
(let [f (io/open-read "tests/pixie/tests/test-io.txt")]
30+
(io/read-line f)
31+
(t/assert= (io/read-line f) "Second line.")
32+
(io/rewind f)
33+
(io/read-line f)
34+
(t/assert= (io/read-line f) "Second line.")
35+
(io/seek f (- (position f) 6))
36+
(t/assert= (io/read-line f) "line.")))
37+
2738
(t/deftest test-slurp-spit
2839
(let [val (vec (range 1280))]
2940
(io/spit "test.tmp" val)

0 commit comments

Comments
 (0)