八発白中

はてなブログに引越しました。

Common Lispの循環ストリームライブラリ「Circular-Streams」を公開しました

Clackではライブラリ内で使うユーティリティをsrc/util以下に置いているのですが、その1つであるreplay-input-streamを独立ライブラリの「Circular-Streams」として公開しました。

通常、ストリームは一度読み終わると再度読むことはできませんが、このライブラリを使うと何度もreadできる"循環ストリーム"を作ることができます。

;; 元のストリーム
(defparameter *stream*
              (flex:make-in-memory-input-stream
               #(72 101 108 108 111)))

;; 循環ストリーム
(defparameter *circular-stream*
              (make-circular-input-stream *stream*))

(read-char *circular-stream*)          ;=> #\H
(read-char *circular-stream*)          ;=> #\e
(read-char *circular-stream*)          ;=> #\l
(read-char *circular-stream*)          ;=> #\l
(read-char *circular-stream*)          ;=> #\o
(read-char *circular-stream* nil :eof) ;=> :eof
(read-char *circular-stream*)          ;=> #\H ← また読める!!

(let ((buf (make-array 4 :adjustable t :fill-pointer 4)))
  (read-sequence buf *circular-stream*)
  (flex:octets-to-string buf))
;=> "ello"

Octet stream (read-byteできるストリーム) しか扱えないので注意してください。

利用シーンがなかなか思い浮かばないかもしれないですが、たとえばClackではClack.RequestでのPOSTリクエストのパースに使っています。Clack.Requestではインスタンスを何回作っても同じbodyが返ってくることを期待しているので、何度もreadできるストリームは便利なわけです。

小さなリリースですが、興味があればお使いください。

追記: Quicklispに申請中です。2012年3月のアップデートで取り込まれる予定です。