Hi,

I think you don't handle the switching of streams correctly. You have to 
keep track with atoms. But then you run into thread-safety issues.

(defn concat-input-stream
  "Gets one or many input streams and returns a new input stream that
  concatenates the given streams."
  [is & streams]
  (let [is      (atom is)
        streams (atom streams)
        switch! (fn []
                  (locking is
                    (.close @is)
                    (reset! is (first streams))
                    (swap! streams rest)))
        do-read (fn
                  ([is]             (if is (.read is) -1))
                  ([is arr]         (if is (.read is arr) -1))
                  ([is arr off len] (if is (.read is arr off len) -1)))]
    (proxy [java.io.InputStream] []
      (close
        []
        (when @is
          (.close @is)
          (doseq [s @streams] (.close s))))
      (read
        ([]
         (let [ch (do-read @is)]
           (if (neg? ch)
             (do
               (switch!)
               (if @is
                 (.read this)
                 -1))
             ch)))
        ([arr]
         (let [n (do-read @is arr)]
           (if (neg? n)
             (do
               (switch!)
               (if @is
                 (.read this arr)
                 -1))
             n)))
        ([arr off len]
         (let [n (do-read @is arr off len)]
           (if (neg? n)
             (do
               (switch!)
               (if @is
                 (.read this arr off len)
                 -1))
             n)))))))

You could also use java.io.SequenceInputStream with a small helper.

(defn coll->enumeration
  [coll]
  (let [s (atom coll)]
    (reify [java.util.Enumeration] []
      (hasMoreElements [this]
        (boolean (swap! s seq)))
      (nextElement [this]
        (locking this
          (if-let [sq (seq @s)]
            (let [e (first sq)]
              (reset! s (rest sq))
              e)
            (throw (java.util.NoSuchElementException.))))))))

(defn concat-input-stream
  "Gets one or many input streams and returns a new input stream that
  concatenates the given streams."
  [is & streams]
  (java.io.SequenceInputStream. (coll->enumeration (cons is streams))))

All code untested.

Kind regards
Meikel

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to