Bitfields access in Clojure

24 views
Skip to first unread message

Daniel Janus

unread,
Jul 21, 2009, 5:36:54 PM7/21/09
to Clojure
Dear list,

Having a free day on my hands, I finally got around to writing some
nontrivial code in Clojure. The result happens to be a library that I
hope might be useful to someone else besides me. It's called clj-
bitfields and consists of one macro, with-bitfields, that allow you to
say things like:

(with-bitfields arr 0 {last 1, term 1, dest 22, char 8}
[last term dest char])

where `arr' is a Java array of bytes, and the map denotes names of
symbols that will be
bound to bitfields of a packed structure with given length.

The code of clj-bitfields can be found at

http://github.com/nathell/clj-bitfields/tree/master

It's MIT-licensed, so I would be happy to see it mentioned on
clojure.org/libraries.

Since this is my first Clojure library and I'm not fully accustomed
yet to doing things The Clojure Way, I'm pretty certain that some
things might have been done better. I would be extremely grateful if
someone had a look at this code and comments on how to make it more
Clojurish.

Thanks!
Daniel Janus

Daniel Janus

unread,
Jul 21, 2009, 6:09:24 PM7/21/09
to Clojure
Dear list,

[I apologize in advance if this gets posted twice.]

Timothy Pratley

unread,
Jul 22, 2009, 3:52:01 AM7/22/09
to Clojure
Could you give a more detailed example to illustrate what this means?

Daniel Janus

unread,
Jul 22, 2009, 7:15:31 AM7/22/09
to Clojure
Perhaps a good illustration will be what it macroexpands to:

(let [last (+ (bit-and (aget arr (unchecked-add 0 0)) 1))
term (+ (bit-shift-right (bit-and (aget arr (unchecked-add 0 0))
3) 1))
dest (+ (bit-shift-right (bit-and (aget arr (unchecked-add 0 0))
255) 2)
(bit-shift-left (bit-and (aget arr (unchecked-add 0 1))
255) 6)
(bit-shift-left (bit-and (aget arr (unchecked-add 0 2))
255) 14))
char (+ (bit-and (aget arr (unchecked-add 0 3)) 255))]
[last term dest char])

The background is that in C99, you can declare structures like:

struct foo {
uint32_t last:1;
uint32_t term:1;
uint32_t dest:22;
uint32_t char:8;
};

which means that each of the fields is only that many bits long (e.g.
last can only hold values 0 and 1, while dest can range from 0 to
4194303). Such a structure takes up 1+1+22+8 = 32 bits = 4 bytes in
memory. It can also be written to disk, and clj-bitfields gives you a
way to read it back and access the individual fields.

Best regards,
Daniel Janus

Paul Mooser

unread,
Jul 22, 2009, 12:42:27 PM7/22/09
to Clojure
Is it safe to assume that you can extract the key ordering from the
literal map the user specified ? Or am I misunderstanding ?

Meikel Brandmeyer

unread,
Jul 22, 2009, 3:17:02 PM7/22/09
to clo...@googlegroups.com
Hi,

Am 22.07.2009 um 18:42 schrieb Paul Mooser:

> Is it safe to assume that you can extract the key ordering from the
> literal map the user specified ? Or am I misunderstanding ?

Up to eight elements in a literal map are stored
as array-map. An array-map keeps the key ordering.
For more elements the map becomes a hash-map,
which does not keep the key ordering.

Sincerely
Meikel

Michael Wood

unread,
Jul 24, 2009, 4:11:39 AM7/24/09
to clo...@googlegroups.com
2009/7/22 Meikel Brandmeyer <m...@kotka.de>:

I assume that's an implementation detail that one could not rely on,
though, right?

--
Michael Wood <esio...@gmail.com>

Daniel Janus

unread,
Jul 24, 2009, 5:53:39 AM7/24/09
to Clojure

> > Up to eight elements in a literal map are stored
> > as array-map. An array-map keeps the key ordering.
> > For more elements the map becomes a hash-map,
> > which does not keep the key ordering.
>
> I assume that's an implementation detail that one could not rely on,
> though, right?

Yeah, I guess so, and thanks to Paul and Meikel for pointing that out
--
I made the obvious mistake of assuming this is always going to work...

I'm going to change the API to replace the maps with vectors of
alternating
symbols and integers, which will make the ordering explicit.

Thanks once again!
Daniel Janus
Reply all
Reply to author
Forward
0 new messages