Tuesday, September 22, 2009

erlang: Parsing binary data dynamically

Hi,
here's a quick tip for parsing binary data which format is unknown at compile time...

Let's say that you have a binary string and that later you receive its structure. Take for
example the code below:
-module(binm).

-export([test/0, test/2]).

test() ->
        test(<<4,0,0,0,5,0,0,0,7,0,8,0,33,1>>, [ 4, 4, 2, 2]).

test(Bin, List) ->
        {Final, End} = lists:foldl( fun(Len, {Res, Rest}) ->
                case Rest of 
                        <<M:Len/binary, NewRest/binary>> ->
                                {[ M | Res ], NewRest};
                        <<_:1/binary, NewRest/binary>> ->
                                { Res, NewRest}
                end
                end, {[], Bin}, List),
        {lists:reverse(Final), End}.

Precisely, we want to slice the binary part into 4 parts described as '[4, 4, 2, 2]' where each element is the size.
test() ->
        test(<<4,0,0,0,5,0,0,0,7,0,8,0,33,1>>, [ 4, 4, 2, 2]).

Let's compile and run:
2> c(binm).    
{ok,binm}
3> binm:test().
{[<<4,0,0,0>>,<<5,0,0,0>>,<<7,0>>,<<8,0>>],<<33,1>>}
4> 
Isn't this nice ? :p

Sticky