Necrobious'

Tuesday, March 04, 2008

Binary to Hex String back to Binary in Erlang

A little project i'm working on in Erlang needs to take a byte sequence and write it out into a String to be save as an HTTP cookie. Then, on subsequent HTTP requests, read back in the hex string from the cookie, and convert it back into the byte sequence. I couldn't quite find a module for doing this in Erlang, so I hacked part of it, and cobbled the rest from examples I've found over the last few days.

Enjoy!



-module(hex).
-export([bin_to_hexstr/1,hexstr_to_bin/1]).

hex(N) when N < 10 ->
$0+N;
hex(N) when N >= 10, N < 16 ->
$a+(N-10).

int(C) when $0 =< C, C =< $9 ->
C - $0;
int(C) when $A =< C, C =< $F ->
C - $A + 10;
int(C) when $a =< C, C =< $f ->
C - $a + 10.

to_hex(N) when N < 256 ->
[hex(N div 16), hex(N rem 16)].

list_to_hexstr([]) ->
[];
list_to_hexstr([H|T]) ->
to_hex(H) ++ list_to_hexstr(T).

bin_to_hexstr(Bin) ->
list_to_hexstr(binary_to_list(Bin)).

hexstr_to_bin(S) ->
list_to_binary(hexstr_to_list(S)).

hexstr_to_list([X,Y|T]) ->
[int(X)*16 + int(Y) | hexstr_to_list(T)];
hexstr_to_list([]) ->
[].

6 Comments:

  • These are not tail recursive. Have a look at the implementation in scutil ( http://scutil.com/ ) for an alternative.

    By Blogger John Haugeland, at 3:55 PM  

  • The following is shorter and it avoids writing your own hex conversion functions.

    -module(hex).
    -export([bin_to_hexstr/1,hexstr_to_bin/1]).

    bin_to_hexstr(Bin) ->
      lists:flatten([io_lib:format("~2.16.0B", [X]) ||
        X <- binary_to_list(Bin)]).

    hexstr_to_bin(S) ->
      hexstr_to_bin(S, []).
    hexstr_to_bin([], Acc) ->
      list_to_binary(lists:reverse(Acc));
    hexstr_to_bin([X,Y|T], Acc) ->
      {ok, [V], []} = io_lib:fread("~16u", [X,Y]),
      hexstr_to_bin(T, [V | Acc]).

    By Blogger Unknown, at 9:04 AM  

  • less readable But shorter and undoubtedly tail recursion , great :)

    By Blogger Unknown, at 6:40 AM  

  • Shorter, faster (I suspect), more readable (IMO), and handles an odd number of nibbles:

    hexstr_to_bin(S) ->
    {ok, [N], []} = io_lib:fread("~16u", S),
    <>.

    By Blogger cartoon camels, at 7:25 PM  

  • Very cool, thanks!

    By Blogger necrobious, at 5:05 PM  

  • The shorter version is not correct. A hex string with leading zero byte will be incorrectly translated to binary:

    "004b9c6e92f7b0da890fa8c24f06a3fd"

    Steve's version works.

    By Blogger Seth, at 9:53 AM  

Post a Comment



<< Home