Functions for reading/writing little-endian data using InputStream/OutputStream.

NOTE: This namespace is intended to be used only from within cljam, and should not be used outside cljam.

(ns cljam.io.util.lsb.io-stream
  (:refer-clojure :exclude [read-string])
  (:require [cljam.io.util.byte-buffer :as bb]
            [cljam.util :refer [string->bytes]])
  (:import [java.io
            ByteArrayOutputStream
            EOFException
            InputStream
            OutputStream]))
(declare read-bytes)

Skips over 'length' bytes of data, discarding the skipped bytes.

(defn skip
  [^InputStream stream ^long length]
  (.skip stream length))

Reads 1 byte. Returns a byte value.

(defn read-byte
  [^InputStream stream]
  (unchecked-byte (.read stream)))

Reads 1 byte. Returns an unsigned byte value as long.

(defn read-ubyte
  [^InputStream stream]
  (bit-and (.read stream) 0xFF))

Reads 2 bytes. Returns a short value.

(defn read-short
  [^InputStream stream]
  (let [bb (bb/allocate-lsb-byte-buffer 2)]
    (read-bytes stream (.array bb) 0 2)
    (.getShort bb)))

Reads 2 bytes. Returns an unsigned short value as long.

(defn read-ushort
  [^InputStream stream]
  (bit-and (short (read-short stream)) 0xFFFF))

Reads 4 bytes. Returns an int value.

(defn read-int
  [^InputStream stream]
  (let [bb (bb/allocate-lsb-byte-buffer 4)]
    (read-bytes stream (.array bb) 0 4)
    (.getInt bb)))

Reads 4 bytes. Returns an unsigned int value as long.

(defn read-uint
  [^InputStream stream]
  (bit-and (int (read-int stream)) 0xFFFFFFFF))

Reads 8 bytes. Returns a long value.

(defn read-long
  [^InputStream stream]
  (let [bb (bb/allocate-lsb-byte-buffer 8)]
    (read-bytes stream (.array bb) 0 8)
    (.getLong bb)))

Reads 4 bytes. Returns a float value.

(defn read-float
  [^InputStream stream]
  (Float/intBitsToFloat (read-int stream)))

Reads 8 bytes. Returns a double value.

(defn read-double
  [^InputStream stream]
  (Double/longBitsToDouble (read-long stream)))

Reads 'length' bytes to buffer starting from offset bytes. Returns a new byte-array if called without buffer.

(defn read-bytes
  ([^InputStream stream ^long length]
   (let [ba (byte-array length)]
     (read-bytes stream ba 0 length)))
  ([^InputStream stream buffer ^long offset ^long length]
   (loop [total-read 0]
     (when (< total-read length)
       (let [n (.read stream buffer (+ offset total-read) (- length total-read))]
         (if (neg? n)
           (throw (EOFException. "Premature EOF"))
           (recur (+ total-read n))))))
   buffer))

Reads 'length' bytes. Returns a String.

(defn read-string
  [^InputStream stream ^long length]
  (String. ^bytes (read-bytes stream length)))

Reads until next null character. Returns a String without the null.

(defn read-null-terminated-string
  [^InputStream stream]
  (with-open [baos (ByteArrayOutputStream. 32)]
    (loop []
      (let [b (.read stream)]
        (when-not (zero? b)
          (.write baos b)
          (recur))))
    (.toString baos)))

Writes 1 byte.

(defn write-ubyte
  [^OutputStream stream b]
  (let [bb (bb/allocate-lsb-byte-buffer)]
    (.putShort bb b)
    (.write stream (.array bb) 0 1)))

Writes a 1-byte ascii character.

(defn write-char
  [^OutputStream stream b]
  (let [bb (bb/allocate-lsb-byte-buffer)]
    (.putChar bb b)
    (.write stream (.array bb) 0 1)))

Writes a 2-byte short value.

(defn write-short
  [^OutputStream stream n]
  (let [bb (bb/allocate-lsb-byte-buffer)]
    (.putShort bb n)
    (.write stream (.array bb) 0 2)))

Writes a 2-byte unsigned short value.

(defn write-ushort
  [^OutputStream stream n]
  (let [bb (bb/allocate-lsb-byte-buffer)]
    (.putInt bb n)
    (.write stream (.array bb) 0 2)))

Writes a 4-byte integer value.

(defn write-int
  [^OutputStream stream n]
  (let [bb (bb/allocate-lsb-byte-buffer)]
    (.putInt bb n)
    (.write stream (.array bb) 0 4)))

Writes a 4-byte unsigned integer value.

(defn write-uint
  [^OutputStream stream n]
  (let [bb (bb/allocate-lsb-byte-buffer)]
    (.putInt bb (unchecked-int n))
    (.write stream (.array bb) 0 4)))

Writes an 8-byte long value.

(defn write-long
  [^OutputStream stream n]
  (let [bb (bb/allocate-lsb-byte-buffer)]
    (.putLong bb n)
    (.write stream (.array bb) 0 8)))

Writes a 4-byte float value.

(defn write-float
  [^OutputStream stream n]
  (let [bb (bb/allocate-lsb-byte-buffer)]
    (.putFloat bb n)
    (.write stream (.array bb) 0 4)))

Writes a 8-byte double value.

(defn write-double
  [^OutputStream stream n]
  (let [bb (bb/allocate-lsb-byte-buffer)]
    (.putDouble bb n)
    (.write stream (.array bb) 0 8)))

Writes a byte-array.

(defn write-bytes
  [^OutputStream stream ^bytes b]
  (.write stream b 0 (alength b)))

Writes a string as a sequence of ascii characters.

(defn write-string
  [^OutputStream stream s]
  (let [data-bytes (string->bytes s)]
    (.write stream data-bytes 0 (alength data-bytes))))