Skip to content

Instantly share code, notes, and snippets.

@zoka
Created December 26, 2010 13:28
Show Gist options
  • Save zoka/755420 to your computer and use it in GitHub Desktop.
Save zoka/755420 to your computer and use it in GitHub Desktop.
;;
(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