Created
December 26, 2010 13:28
-
-
Save zoka/755420 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; | |
(ns clojfix.simple) | |
(use 'gloss.core 'gloss.io) | |
(import | |
[java.nio | |
ByteBuffer]) | |
; | |
(defcodec simple-tuple | |
(header | |
(string-integer :ascii :delimiters ["="]) | |
(memoize | |
(fn [key] | |
(compile-frame | |
[key (string :ascii :delimiters [0x01])]))) | |
(fn [[key value]] | |
key))) | |
(defn print-bb [title b] | |
"Hex dump of ByteBuffer instance" | |
(let [cnt (.limit ^ByteBuffer b)] | |
(printf "bb:%s\n" title) | |
(loop [i 0] | |
(if (== i cnt) | |
(printf "\n") | |
(do | |
(printf "%d:%02x " i (.get ^ByteBuffer b i)) | |
(recur (inc i))))))) | |
(defn ascii-int-to-bb [b n width] | |
"ASCII representation of positive integer n is stored | |
at current byte buffer position. | |
Returns number of bytes filled." | |
(let [len (int width) | |
val (int n) | |
old-pos (int (.position ^ByteBuffer b)) | |
new-pos (int (+ len old-pos))] | |
(.position ^ByteBuffer b new-pos) | |
(loop [i new-pos acc val] | |
(if (== i old-pos) | |
len | |
(do | |
(.put ^ByteBuffer b (dec i) (+ (int (rem acc 10)) (int 0x30))) | |
(recur (dec i) (int (quot acc (int 10))))))))) | |
(defn encode-tuple [t] | |
(let [ | |
tag (int (first t)) | |
val (second t) | |
tlen (int (+ 1 (Math/log10 tag))) | |
vlen (int (count val)) | |
len (+ tlen vlen 2) | |
ret (ByteBuffer/allocate len)] | |
(ascii-int-to-bb ret tag tlen) | |
(. ret put (byte 0x21)) | |
(. ret put (.getBytes ^String val)) | |
(. ret put (byte 1)) | |
(. ret rewind) | |
ret)) | |
(defn bb-get-tag [b] | |
(if (== 0 (.remaining ^ByteBuffer b)) | |
0 | |
(do | |
(loop [ ret (int 0) | |
nextb (int (.get ^ByteBuffer b))] | |
(if (== 0 (.remaining ^ByteBuffer b)) | |
0 | |
(do | |
(if (or (< nextb (int 0x30)) | |
(> nextb (int 0x39))) | |
(if (== nextb (int 0x21)) | |
ret | |
0) | |
(recur | |
(+ (- nextb (int 0x30)) (* ret (int 10))) | |
(int (.get ^ByteBuffer b)))))))))) | |
(defn bb-get-val [b] | |
(if (== 0 (.remaining ^ByteBuffer b)) | |
nil | |
(do | |
(loop [sb (new StringBuilder) | |
nextb (int (.get ^ByteBuffer b))] | |
(if (== nextb (int 0x01)) | |
(.toString sb) | |
(do | |
(if (== 0 (.remaining ^ByteBuffer b)) | |
nil ; did not get SOH | |
(recur (. sb append (char nextb)) | |
(int (.get ^ByteBuffer b)))))))))) | |
(defn decode-tuple [b] | |
(let [tag (bb-get-tag b) | |
val (bb-get-val b)] | |
(if (or (== tag 0) (nil? val)) | |
nil | |
[tag val]))) | |
(defn tuple-bench [repeat] | |
(let [test-tuple [123 "The test"] | |
enc-bufs-gloss (encode simple-tuple test-tuple) | |
enc-buf (encode-tuple test-tuple) | |
dec-tuple-gloss (decode simple-tuple enc-bufs-gloss) | |
dec-tuple (decode-tuple enc-buf)] | |
(printf "Doing encode/decode %d times\n" repeat) | |
(print "encode(gloss): ") | |
(time (dotimes [i repeat] (encode simple-tuple dec-tuple-gloss))) | |
(print "encode-tuple: ") | |
(time (dotimes [_ repeat] (encode-tuple dec-tuple))) | |
(print "decode(gloss): ") | |
(time (dotimes [_ repeat] (decode simple-tuple enc-bufs-gloss))) | |
(print "decode-tuple: ") | |
(time (dotimes [_ repeat] (decode-tuple (.rewind ^ByteBuffer enc-buf)))) | |
)) | |
(defn enc-dec-test [] | |
(let [tuple [122 "abc-123"] | |
bb-gloss (encode simple-tuple tuple) | |
bb (encode-tuple tuple) | |
ee-gloss (decode simple-tuple bb-gloss) | |
ee (decode-tuple bb)] | |
(print-bb "bb" bb) | |
(println ee-gloss) | |
(println ee))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment