diff --git a/src/cljam/io/cram/itf8.clj b/src/cljam/io/cram/itf8.clj index cfaf45c6..e336ce9e 100644 --- a/src/cljam/io/cram/itf8.clj +++ b/src/cljam/io/cram/itf8.clj @@ -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." @@ -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) diff --git a/test/cljam/io/cram/itf8_test.clj b/test/cljam/io/cram/itf8_test.clj index 83f803a7..909423fd 100644 --- a/test/cljam/io/cram/itf8_test.clj +++ b/test/cljam/io/cram/itf8_test.clj @@ -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 @@ -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 @@ -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 @@ -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]))