Skip to content

Commit

Permalink
Implement ITF8/LTF8 encoder
Browse files Browse the repository at this point in the history
  • Loading branch information
athos committed May 17, 2024
1 parent 11d39b0 commit 904592c
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 8 deletions.
117 changes: 116 additions & 1 deletion src/cljam/io/cram/itf8.clj
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
(ns cljam.io.cram.itf8
(:require [cljam.io.util.byte-buffer :as bb]))
(:require [cljam.io.util.byte-buffer :as bb])
(:import [java.nio ByteBuffer]))

(defn decode-itf8
"Decodes ITF-8 integer from ByteBuffer."
Expand Down Expand Up @@ -95,3 +96,117 @@
(bit-shift-left (long (bb/read-ubyte bb)) 16)
(bit-shift-left (long (bb/read-ubyte bb)) 8)
(long (bb/read-ubyte bb))))))

(defn- ensure-buffer-room! [^ByteBuffer bb ^long n flush-fn]
(when (< (.remaining bb) n)
(flush-fn)))

(defn encode-itf8
"Encodes ITF-8 integer to ByteBuffer."
[^long v bb flush-fn]
(cond (zero? (unsigned-bit-shift-right v 7))
(do (ensure-buffer-room! bb 1 flush-fn)
(bb/write-ubyte bb v))

(zero? (unsigned-bit-shift-right v 14))
(do (ensure-buffer-room! bb 2 flush-fn)
(bb/write-ubyte bb (bit-or (unsigned-bit-shift-right v 8) 0x80))
(bb/write-ubyte bb (bit-and v 0xff)))

(zero? (unsigned-bit-shift-right v 21))
(do (ensure-buffer-room! bb 3 flush-fn)
(bb/write-ubyte bb (bit-or (unsigned-bit-shift-right v 16) 0xc0))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 8) 0xff))
(bb/write-ubyte bb (bit-and v 0xff)))

(zero? (unsigned-bit-shift-right v 28))
(do (ensure-buffer-room! bb 4 flush-fn)
(bb/write-ubyte bb (bit-or (unsigned-bit-shift-right v 24) 0xe0))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 16) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 8) 0xff))
(bb/write-ubyte bb (bit-and v 0xff)))

:else
(do (ensure-buffer-room! bb 5 flush-fn)
(bb/write-ubyte bb (bit-or (unsigned-bit-shift-right v 28) 0xf0))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 20) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 12) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 4) 0xff))
(bb/write-ubyte bb (bit-and v 0x0f))))
nil)

(defn encode-ltf8
"Encodes LTF-8 integer to ByteBuffer."
[^long v bb flush-fn]
(cond (zero? (unsigned-bit-shift-right v 7))
(do (ensure-buffer-room! bb 1 flush-fn)
(bb/write-ubyte bb v))

(zero? (unsigned-bit-shift-right v 14))
(do (ensure-buffer-room! bb 2 flush-fn)
(bb/write-ubyte bb (bit-or (unsigned-bit-shift-right v 8) 0x80))
(bb/write-ubyte bb (bit-and v 0xff)))

(zero? (unsigned-bit-shift-right v 21))
(do (ensure-buffer-room! bb 3 flush-fn)
(bb/write-ubyte bb (bit-or (unsigned-bit-shift-right v 16) 0xc0))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 8) 0xff))
(bb/write-ubyte bb (bit-and v 0xff)))

(zero? (unsigned-bit-shift-right v 28))
(do (ensure-buffer-room! bb 4 flush-fn)
(bb/write-ubyte bb (bit-or (unsigned-bit-shift-right v 24) 0xe0))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 16) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 8) 0xff))
(bb/write-ubyte bb (bit-and v 0xff)))

(zero? (unsigned-bit-shift-right v 35))
(do (ensure-buffer-room! bb 5 flush-fn)
(bb/write-ubyte bb (bit-or (unsigned-bit-shift-right v 32) 0xf0))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 24) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 16) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 8) 0xff))
(bb/write-ubyte bb (bit-and v 0xff)))

(zero? (unsigned-bit-shift-right v 42))
(do (ensure-buffer-room! bb 6 flush-fn)
(bb/write-ubyte bb (bit-or (unsigned-bit-shift-right v 40) 0xf8))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 32) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 24) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 16) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 8) 0xff))
(bb/write-ubyte bb (bit-and v 0xff)))

(zero? (unsigned-bit-shift-right v 49))
(do (ensure-buffer-room! bb 7 flush-fn)
(bb/write-ubyte bb (bit-or (unsigned-bit-shift-right v 48) 0xfc))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 40) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 32) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 24) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 16) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 8) 0xff))
(bb/write-ubyte bb (bit-and v 0xff)))

(zero? (unsigned-bit-shift-right v 56))
(do (ensure-buffer-room! bb 8 flush-fn)
(bb/write-ubyte bb (bit-or (unsigned-bit-shift-right v 56) 0xfe))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 48) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 40) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 32) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 24) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 16) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 8) 0xff))
(bb/write-ubyte bb (bit-and v 0xff)))

:else
(do (ensure-buffer-room! bb 9 flush-fn)
(bb/write-ubyte bb 0xff)
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 56) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 48) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 40) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 32) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 24) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 16) 0xff))
(bb/write-ubyte bb (bit-and (unsigned-bit-shift-right v 8) 0xff))
(bb/write-ubyte bb (bit-and v 0xff))))
nil)
59 changes: 52 additions & 7 deletions test/cljam/io/cram/itf8_test.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
(ns cljam.io.cram.itf8-test
(:require [cljam.io.cram.itf8 :as itf8]
[cljam.io.util.byte-buffer :as bb]
[clojure.test :refer [deftest are]]))
[clojure.test :refer [are deftest]])
(:import [java.util Arrays]))

(deftest decode-itf8-test
(are [bs expected] (= expected
Expand All @@ -12,12 +13,12 @@
[0x7f] 0x7f
[0x80 0xff] 0xff
[0xbc 0xab] 0x3cab
[0xc0 0x12 0x34] 0x1234
[0xc0 0x56 0x78] 0x5678
[0xda 0xbc 0x23] 0x1abc23
[0xe0 0x12 0x34 0x56] 0x123456
[0xe0 0x23 0x45 0x67] 0x234567
[0xea 0xbc 0xde 0xf0] 0xabcdef0
[0xfc 0xaf 0xeb 0xab 0x0e] (unchecked-int 0xcafebabe)
[0xff 0xff 0xff 0xff 0xff] -1))
[0xf1 0x23 0x45 0x67 0x08] 0x12345678
[0xff 0xff 0xff 0xff 0x0f] -1))

(deftest decode-ltf8-test
(are [bs expected] (= expected
Expand All @@ -28,9 +29,9 @@
[0x7f] 0x7f
[0x80 0xff] 0xff
[0xbc 0xab] 0x3cab
[0xc0 0x12 0x34] 0x1234
[0xc0 0x56 0x78] 0x5678
[0xda 0xbc 0x23] 0x1abc23
[0xe0 0x12 0x34 0x56] 0x123456
[0xe0 0x23 0x45 0x67] 0x234567
[0xea 0xbc 0xde 0xf0] 0xabcdef0
[0xf0 0xde 0xad 0xbe 0xef] 0xdeadbeef
[0xf7 0xff 0xff 0xff 0xff] 0x7ffffffff
Expand All @@ -42,3 +43,47 @@
[0xfe 0xff 0xff 0xff 0xff 0xff 0xff 0xff] 0xffffffffffffff
[0xff 0x12 0x34 0x56 0x78 0x9a 0xbc 0xde 0xf0] 0x123456789abcdef0
[0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff] -1))

(deftest encode-itf8-test
(are [v expected] (= expected
(let [bb (bb/allocate-lsb-byte-buffer 5)]
(itf8/encode-itf8 v bb nil)
(->> (.position bb)
(Arrays/copyOfRange (.array bb) 0)
(map #(bit-and % 0xff)))))
0 [0x00]
0x7f [0x7f]
0xff [0x80 0xff]
0x3cab [0xbc 0xab]
0x5678 [0xc0 0x56 0x78]
0x1abc23 [0xda 0xbc 0x23]
0x234567 [0xe0 0x23 0x45 0x67]
0xabcdef0 [0xea 0xbc 0xde 0xf0]
0x12345678 [0xf1 0x23 0x45 0x67 0x08]
-1 [0xff 0xff 0xff 0xff 0x0f]))

(deftest encode-ltf8-test
(are [v expected] (let [bb (bb/allocate-lsb-byte-buffer 9)]
(itf8/encode-ltf8 v bb nil)
(= expected
(->> (.position bb)
(Arrays/copyOfRange (.array bb) 0)
(map #(bit-and % 0xff)))))
0 [0x00]
0x7f [0x7f]
0xff [0x80 0xff]
0x3cab [0xbc 0xab]
0x5678 [0xc0 0x56 0x78]
0x1abc23 [0xda 0xbc 0x23]
0x234567 [0xe0 0x23 0x45 0x67]
0xabcdef0 [0xea 0xbc 0xde 0xf0]
0xdeadbeef [0xf0 0xde 0xad 0xbe 0xef]
0x7ffffffff [0xf7 0xff 0xff 0xff 0xff]
0x123456789a [0xf8 0x12 0x34 0x56 0x78 0x9a]
0x3ffffffffff [0xfb 0xff 0xff 0xff 0xff 0xff]
0xbadbadbadbad [0xfc 0xba 0xdb 0xad 0xba 0xdb 0xad]
0x123456789abcd [0xfd 0x23 0x45 0x67 0x89 0xab 0xcd]
0x123456789abcde [0xfe 0x12 0x34 0x56 0x78 0x9a 0xbc 0xde]
0xffffffffffffff [0xfe 0xff 0xff 0xff 0xff 0xff 0xff 0xff]
0x123456789abcdef0 [0xff 0x12 0x34 0x56 0x78 0x9a 0xbc 0xde 0xf0]
-1 [0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff]))

0 comments on commit 904592c

Please sign in to comment.