Carp/core/Binary.carp

110 lines
4.6 KiB
Plaintext
Raw Normal View History

(system-include "carp_binary.h")
(defmodule Binary
(doc Order
"The type of byte orders.
LittleEndian designates the little endian ordering, and indicates the least
significant byte appears first in a given byte sequence.
BigEndian designates the big endian ordering, and indicates the most
significant byte occurs first in a given byte sequence.")
(deftype Order LittleEndian BigEndian)
(register to-int16 (λ [Byte Byte] Int))
(register to-int32 (λ [Byte Byte Byte Byte] Int))
(register to-int64 (λ [Byte Byte Byte Byte Byte Byte Byte Byte] Int))
(register system-endianness-internal (λ [] Int))
(doc system-endianness "Returns the endianness of the host system.")
(sig system-endianness (λ [] Order))
(defn system-endianness []
(if (= (system-endianness-internal) 1)
(Order.LittleEndian)
(Order.BigEndian)))
(doc bytes->int16-unsafe
"Interprets the first two bytes in a byte sequence as an int16 value.
**This operation is unsafe.**")
(sig bytes->int16-unsafe (Fn [Order (Ref (Array Byte) a)] Int))
(defn bytes->int16-unsafe [order bs]
(match order
(Order.LittleEndian)
(to-int16 @(Array.unsafe-nth bs 0) @(Array.unsafe-nth bs 1))
(Order.BigEndian)
(to-int16 @(Array.unsafe-nth bs 1) @(Array.unsafe-nth bs 0))))
(doc bytes->int32-unsafe
"Interprets the first four bytes in a byte sequence as an int32 value.
**This operation is unsafe.**")
(sig bytes->int32-unsafe (Fn [Order (Ref (Array Byte))] Int))
(defn bytes->int32-unsafe [order bs]
(match order
(Order.LittleEndian)
(to-int32 @(Array.unsafe-nth bs 0) @(Array.unsafe-nth bs 1)
@(Array.unsafe-nth bs 2) @(Array.unsafe-nth bs 3))
(Order.BigEndian)
(to-int32 @(Array.unsafe-nth bs 3) @(Array.unsafe-nth bs 2)
@(Array.unsafe-nth bs 1) @(Array.unsafe-nth bs 0))))
(doc bytes->int64-unsafe
"Interprets the first eight bytes in a byte sequence as an int64 value.
**This operation is unsafe.**")
(sig bytes->int64-unsafe (Fn [Order (Ref (Array Byte) a)] Int))
(defn bytes->int64-unsafe [order bs]
(match order
(Order.LittleEndian)
(to-int64 @(Array.unsafe-nth bs 0) @(Array.unsafe-nth bs 1)
@(Array.unsafe-nth bs 2) @(Array.unsafe-nth bs 3)
@(Array.unsafe-nth bs 4) @(Array.unsafe-nth bs 5)
@(Array.unsafe-nth bs 6) @(Array.unsafe-nth bs 7))
(Order.BigEndian)
(to-int64 @(Array.unsafe-nth bs 7) @(Array.unsafe-nth bs 6)
@(Array.unsafe-nth bs 5) @(Array.unsafe-nth bs 4)
@(Array.unsafe-nth bs 3) @(Array.unsafe-nth bs 2)
@(Array.unsafe-nth bs 1) @(Array.unsafe-nth bs 0))))
(doc byte-seq->int8-seq-unsafe
"Interprets a sequence of bytes as a sequence of int8 values.
**This operation is unsafe.**")
(sig byte-seq->int8-seq (Fn [(Ref (Array Byte) a)] (Array Int)))
(defn byte-seq->int8-seq [bs]
(let [f (fn [b] (Byte.to-int @b))]
(Array.copy-map &f bs)))
(doc byte-seq->int16-seq-unsafe
"Interprets a sequence of bytes as a sequence of int16 values.
**This operation is unsafe.**")
(sig byte-seq->int16-seq (Fn [Order (Ref (Array Byte) a)] (Array Int)))
(defn byte-seq->int16-seq [order bs]
;; This is way less efficient than it could be.
;; Instead of allocating about 4 extra arrays, we can express this
;; as a fold.
(let [enum (Array.enumerated bs)]
(let [evens (Array.copy-filter &(fn [p] (Int.even? @(Pair.a p))) &enum)
odds (Array.copy-filter &(fn [p] (Int.odd? @(Pair.a p))) &enum)
intf (fn [r1 r2] (to-int16 @(Pair.b r1) @(Pair.b r2)))]
(match order
(Order.LittleEndian) (Array.zip &intf &evens &odds)
(Order.BigEndian) (Array.zip &intf &odds &evens)))))
(doc byte-seq->int32-seq-unsafe
"Interprets a sequence of bytes as a sequence of int32 values.
**This operation is unsafe.**")
(sig byte-seq->int32-seq (Fn [Order (Ref (Array Byte) a)] (Array Int)))
(defn byte-seq->int32-seq [order bs]
(let [partitions (Array.partition bs 4)
f (fn [b] (bytes->int32-unsafe order b))]
(Array.copy-map &f &partitions)))
(doc byte-seq->int64-seq-unsafe
"Interprets a sequence of bytes as a sequence of int32 values.
**This operation is unsafe.**")
(sig byte-seq->int64-seq (Fn [Order (Ref (Array Byte) a)] (Array Int)))
(defn byte-seq->int64-seq [order bs]
(let [partitions (Array.partition bs 8)
f (fn [b] (bytes->int64-unsafe order b))]
(Array.copy-map &f &partitions)))
)