Decode a trail of <<Header, Length, Payload, ......, Header, Length, Payload,.......>> from Binary Input

Papa Tana papa.tana101@REDACTED
Tue Jul 14 23:44:12 CEST 2020


The Problem definition and Input Structure is Correct.
But the sample example Data was incorrect, sorry.

Here is the right sample Data:

Data =
<<
 1, 3:8, "a", "a", "a",
 2, 4:16, "a", "a", "a", "a",
 3, 6:24, "a", "a", "a", "a", "a", "a",
 4, 2:32, "a", "a"
>>

If Header == 1 Then LENGTH ==3 and occupies 8 bits,  THEN Payload is 3
Next Octets,
If Header == 2 Then LENGTH ==4 and occupies 16bits, THEN Payload is 4
Next Octets,
If Header == 3 Then LENGTH ==6 and occupies 24bits, THEN Payload is 6
Next Octets,
If Header == 4 Then LENGTH ==2 and occupies 32bits, THEN Payload is 2
Next Octets

And this is how I decode it, but I've got some error that I cannot see
where I am wrong:

decode(Data, [])
.

decode(<<>>, Acc) ->
    lists:reverse(Acc);

decode(Data, Acc) ->
		{ok, P, Rest} = use(Data),
    decode(Rest, [P | Acc]).

use(Data)->
	%% {ok, P, Rest}
	 << Header:8, _/binary >> = Data,
		case
			Header of
				1 ->
					<< _:8, Length1:8, Rest1/binary >> = Data,
					NumberOfOctets1 = Length1*8,					
					<< _:8, _:8, Content1:NumberOfOctets1, Rest11/binary>> = Rest1,
					{ok, <<Header:8,Length1:8,Content1:NumberOfOctets1>>, Rest11};
				2 ->
					<< _:8, Length2:16, Rest2/binary >> = Data,
					NumberOfOctets2 = Length2*8,					
					<< _:8, _:16, Content2:NumberOfOctets2, Rest22/binary>> = Rest2,
					{ok, <<Header:8,Length2:16,Content2:NumberOfOctets2>>, Rest22};
				3 ->
					<< _:8, Length3:24, Rest3/binary >> = Data,
					NumberOfOctets3 = Length3*8,					
					<< _:8, _:24, Content3:NumberOfOctets3, Rest33/binary>> = Rest3,
					{ok, <<Header:8,Length3:24,Content3:NumberOfOctets3>>, Rest33};
				4 ->
					<< _:8, Length4:32, Rest4/binary >> = Data,
					NumberOfOctets4 = Length4*8,
					<< _:8, _:32, Content4:NumberOfOctets4, Rest44/binary>> = Rest4,
					{ok, <<Header:8,Length4:32,Content4:NumberOfOctets4>>, Rest44}
		end
.
Best Regards,

2020-07-14 23:57 UTC+03:00, Oliver Korpilla <Oliver.Korpilla@REDACTED>:
> Hi,
>
> I'm not sure the example data was correct. I see Leornard also changed that
> one:
>
> start() ->
>     Data = << 1,2,"a","b", 3,0,0,1,"x", 4,0,0,0,1,"y", 4,0,0,0,2,"m", "n"
>>>,
>     io:format("~p~n", [ extract(Data) ]).
>
> extract(<< >>) -> [];
> extract(<< Header:8, X/binary>>) ->
>   Bits    = Header * 8,
>   << Length:Bits, Y/binary >> = X,
>   Payload = binary:part(Y, 0, Length),
>   Rest    = binary:part(Y, Length, byte_size(Y) - Length),
>   Result  = { Header, Length, Payload },
>   [ Result | extract(Rest) ].
>
> Regards,
> Oliver
>
> Gesendet: Dienstag, 14. Juli 2020 um 22:24 Uhr
> Von: "Leonard B" <leonard.boyce@REDACTED>
> An: "Papa Tana" <papa.tana101@REDACTED>
> Cc: "erlang-questions" <erlang-questions@REDACTED>
> Betreff: Re: Decode a trail of <<Header,Length,Payload,......,Header,Length,
> Payload,.......>> from Binary Input
> rough and there's probably a better way but should work:
>
> %% Data =
> <<1,2:(1*8),"a","b",2,3:(2*8),"a","b","c",3,1:(3*8),"x",4,1:(4*8),"y",8,2:(8*8),"m","n">>.
>
> d(Data) ->
> d(Data, []).
>
> d(<<X:8, Rest0/binary>>, Acc) ->
> Len = X * 8,
> <<LenVal:Len, Rest/binary>> = Rest0,
> <<D:LenVal/binary, Tl/binary>> = Rest,
> io:format("Len: ~p LenVal: ~p D: ~p~n", [Len, LenVal, D]),
> io:format("Tl: ~p~n", [Tl]),
> d(Tl, [{X, D} | Acc]);
> d(<<>>, Acc) ->
> lists:reverse(Acc).
>
> 56> bt:d(Data).
> Len: 8 LenVal: 2 D: <<"ab">>
> Tl: <<2,0,3,97,98,99,3,0,0,1,120,4,0,0,0,1,121,8,0,0,0,0,0,0,0,2,109,110>>
> Len: 16 LenVal: 3 D: <<"abc">>
> Tl: <<3,0,0,1,120,4,0,0,0,1,121,8,0,0,0,0,0,0,0,2,109,110>>
> Len: 24 LenVal: 1 D: <<"x">>
> Tl: <<4,0,0,0,1,121,8,0,0,0,0,0,0,0,2,109,110>>
> Len: 32 LenVal: 1 D: <<"y">>
> Tl: <<8,0,0,0,0,0,0,0,2,109,110>>
> Len: 64 LenVal: 2 D: <<"mn">>
> Tl: <<>>
> [{1,<<"ab">>},
> {2,<<"abc">>},
> {3,<<"x">>},
> {4,<<"y">>},
> {8,<<"mn">>}]
>
>
>
> Leonard
>
> On Tue, Jul 14, 2020 at 3:48 PM Papa Tana <papa.tana101@REDACTED> wrote:
>>
>> Dear All,
>>
>> I am working with some Binary Input as below, which complete format is:
>>
>> Data =
>> <<
>>
>> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>> |Header | LENGTH(8bits) | Payload |
>> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>> |Header | LENGTH(16bits) | Payload|
>> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>> |Header | LENGTH(32bits) | Payload|
>> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>> |Header | LENGTH(8bits) | Payload |
>> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>> |Header | LENGTH(32bits) | Payload|
>> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>> |Header | LENGTH(16bits) | Payload|
>> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>> |Header | LENGTH(8bits) | Payload |
>> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>> |Header | LENGTH(16bits) | Payload|
>> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>>
>> >>
>>
>> - Header is always 8 bits,
>> - LENGTH has a dynamic size(can be 8 "if Header=1", 16 "if Header=2",
>> 24 "if Header=3" or 32 "if Header=4")
>> - Payload is deducted from LENGTH
>>
>> I am doing something like this in my Code(repetitive check), because I
>> have to test Data for every possible value of Header (impossible to
>> maintain such a code):
>>
>> [ {Header, LENGTH, Payload} || <<Header:8, LENGTH:8 if Header = 1,
>> Payload:LENGTH*8>> <= Data ]
>> [ {Header, LENGTH, Payload} || <<Header:8, LENGTH:16 if Header = 2,
>> Payload:LENGTH*8>> <= Data ]
>> [ {Header, LENGTH, Payload} || <<Header:8, LENGTH:24 if Header = 3,
>> Payload:LENGTH*8>> <= Data ]
>> [ {Header, LENGTH, Payload} || <<Header:8, LENGTH:32 if Header = 4,
>> Payload:LENGTH*8>> <= Data ]
>>
>> Is there any way to extract all {Header, LENGTH, Payload} in this Data
>> Binary Input in a more efficient way please?
>>
>> An example of Data:
>>
>> Data =
>> <<
>> 1,2,"a","b",
>> 3,1,"x",
>> 4,1,"y",
>> 8,2,"m", "n"
>> >>.
>>
>> Thanks in advance,
>>
>> Best Regards,
>


More information about the erlang-questions mailing list