leifericf
leifericf

Reputation: 2372

How to flip a single, specific bit in an Erlang bitstring?

I have the following module:

-module (bitutils).
-export ([get_bits/1, get_bit/2, set_bit/2]).

get_bits(B) ->
    << <<X>> || <<X:1>> <= B >>.

get_bit(Bin, N) ->
    << _:N/bitstring, Bit:1, _/bitstring >> = Bin,
    Bit.

set_bit(Bin, N) ->
    << A:N, _:1, B/bitstring >> = Bin,
    << A:N, 1:1, B >>.

Erlang REPL session (example):

Eshell V9.3  (abort with ^G)

1> c(bitutils).
{ok,bitutils}

2> B = <<0:3>>.
<<0:3>>

3> bitutils:get_bits(B).
<<0,0,0>>

4> bit_size(B).
3

5> byte_size(B).
1

6> bitutils:get_bit(B, 0).
0

7> bitutils:get_bit(B, 1).
0

8> bitutils:get_bit(B, 2).
0

9> bitutils:set_bit(B, 0).
** exception error: bad argument
     in function  bitutils:setBit/2 (bitutils.erl, line 12)

Question:

I can't figure out why the set_bit function is throwing an exception.

In the above example, when I call set_bit(B, 0), I want the function to return a new bitstring (e.g. NewB) where the first bit (at index 0) has been flipped from 0 to 1.

Such that, if I were to call get_bits(NewB), it would return: <<1,0,0>>

How can I flip a single, specific bit in an Erlang bitstring?

Upvotes: 1

Views: 437

Answers (2)

Hynek -Pichi- Vychodil
Hynek -Pichi- Vychodil

Reputation: 26121

Simpler

set_bit(Bin, N) ->
        << A:N/bits, _:1, B/bits >> = Bin,
        << A/bits, 1:1, B/bits >>.

Upvotes: 3

Peter Bagyinszki
Peter Bagyinszki

Reputation: 1080

You can do it this way:

set_bit(Bin, N) ->
        R = bit_size(Bin) - N - 1, 
        << A:N, _:1, B:R >> = Bin,
        << A:N, 1:1, B:R >>.

Upvotes: 1

Related Questions