Skip to content

Adding c-string (null terminated strings) #29

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ pom.xml.asc
.\#*
/out
/*-init.clj
/doc/dist/
/doc/dist/
.lsp
2 changes: 1 addition & 1 deletion project.clj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(defproject funcool/octet "1.1.2"
(defproject funcool/octet "1.1.3"
:description "A clojure(script) library for work with binary data."
:url "https://github.com/funcool/octet"
:license {:name "Public Domain"
Expand Down
1 change: 1 addition & 0 deletions src/octet/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
(util/defalias spec spec/spec)
(util/defalias size spec/size)
(util/defalias repeat spec/repeat)
(util/defalias cstring string-spec/cstring)
(util/defalias string string-spec/string)
(util/defalias string* string-spec/string*)
(util/defalias vector* coll-spec/vector*)
Expand Down
29 changes: 29 additions & 0 deletions src/octet/spec/string.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,32 @@
(buffer/write-int buff pos length)
(buffer/write-bytes buff (+ pos 4) length input)
(+ length 4)))))

(def ^{:doc "Arbitrary length cstring (null-terminated string) type spec."}
cstring
(reify
#?@(:clj
[clojure.lang.IFn
(invoke [s] s)]
:cljs
[cljs.core/IFn
(-invoke [s] s)])

spec/ISpecDynamicSize
(size* [_ data]
(let [data (string->bytes data)]
(+ 1 (count data))))

spec/ISpec
(read [_ buff pos]
(loop [index pos acc []]
(let [b (buffer/read-byte buff index)]
(if (zero? b)
[(inc (count acc)) (bytes->string (byte-array acc) (count acc))]
(recur (inc index) (conj acc b))))))

(write [_ buff pos value]
(let [input (string->bytes (str value "\0"))
length (count input)]
(buffer/write-bytes buff pos length input)
length))))
40 changes: 40 additions & 0 deletions test/octet/tests/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,14 @@
:else
(t/is (= data data')))))))))))

(t/deftest spec-data-with-cstring-single
(let [spec (buf/spec (buf/cstring))
buffer (buf/allocate 11)]
(buf/write! buffer ["1234567890"] spec)
(let [[readed data] (buf/read* buffer spec)]
(t/is (= readed 11))
(t/is (= data ["1234567890"])))))

(t/deftest spec-data-with-dynamic-types-single
(let [spec (buf/spec (buf/string*))
buffer (buf/allocate 20)]
Expand All @@ -264,6 +272,38 @@
(t/is (= readed 18))
(t/is (= data ["1234567890" 1000])))))

(t/deftest spec-data-with-cstring-and-other-types-combined
(let [spec (buf/spec (buf/cstring) (buf/int32))
buffer (buf/allocate 40)]
(buf/write! buffer ["1234567890" 1000] spec)
(let [[readed data] (buf/read* buffer spec)]
(t/is (= readed 15))
(t/is (= data ["1234567890" 1000])))))

(t/deftest spec-data-with-multi-cstring
(let [spec (buf/spec buf/cstring buf/cstring)
buffer (buf/allocate 40)]
(buf/write! buffer ["1234567890" "1234567890"] spec)
(let [[readed data] (buf/read* buffer spec)]
(t/is (= readed 22))
(t/is (= data ["1234567890" "1234567890"])))))

(t/deftest spec-data-with-types-and-cstring-combined
(let [spec (buf/spec buf/cstring buf/int32 buf/byte buf/cstring)
buffer (buf/allocate 40)]
(buf/write! buffer ["1234567890" 1000 1 "1234567890"] spec)
(let [[readed data] (buf/read* buffer spec)]
(t/is (= readed 27))
(t/is (= data ["1234567890" 1000 1 "1234567890"])))))

(t/deftest spec-data-with-multi-cstring-and-dynamic-types-combined
(let [spec (buf/spec (buf/int32) (buf/cstring) (buf/cstring) (buf/int32))
buffer (buf/allocate 40)]
(buf/write! buffer [9999 "12345" "67890" 1000] spec)
(let [[readed data] (buf/read* buffer spec)]
(t/is (= readed 20))
(t/is (= data [9999 "12345" "67890" 1000])))))

(t/deftest spec-data-with-indexed-ref-string-single
(let [spec (buf/spec (buf/int32)
(buf/int32)
Expand Down