[erlang-questions] Binary matching problem

Tomas Stejskal <>
Sat Feb 23 14:58:13 CET 2008


Hello,

as a newbie I've played with the module id3_v1.erl from Joe's book and 
I've found some strange behavior regarding binary matching. The module's 
purpose is reading an id3 version 1 or version 1.1 tag from a mp3 file.

Here is modified version of the module:

---
-module(id3_v1).
-export([read_v1_or_v11_tag/1, read_only_v1_tag/1]).
-import(lists, [reverse/1]).

read_v1_or_v11_tag(File) ->
    read_id3_tag(File, fun parse_v1_or_v11_tag/1).

read_only_v1_tag(File) ->
    read_id3_tag(File, fun parse_only_v1_tag/1).

read_id3_tag(File, Parse) ->
    case file:open(File, [read, binary, raw]) of
    {ok, S} ->
        Size = filelib:file_size(File),
        {ok, Bin} = file:pread(S, Size - 128, 128),
        Result = Parse(Bin),
        file:close(S),
        Result;
    Error ->
        {File, Error}
    end.

parse_only_v1_tag(<<"TAG", Title:30/binary,
           Artist:30/binary, Album:30/binary,
           _Year:4/binary, _Comment:30/binary,
           _Genre:8>>) ->
    {ok,
     {"ID3v1",
      [{title, trim(Title)},
       {artist, trim(Artist)},
       {album, trim(Album)}]}};
parse_only_v1_tag(_) ->
    error.

parse_v1_or_v11_tag(<<"TAG", Title:30/binary,
       Artist:30/binary, Album:30/binary,
       _Year:4/binary, _Comment:28/binary,
       0:8, Track:8, _Genre:8>>) ->
    {ok,
     {"ID3v1.1",
      [{track, Track}, {title, trim(Title)},
       {artist, trim(Artist)}, {album, trim(Album)}]}};
parse_v1_or_v11_tag(<<"TAG", Title:30/binary,
          Artist:30/binary, Album:30/binary,
          _Year:4/binary, _Comment:30/binary,
          _Genre:8>>) ->
    {ok,
     {"ID3v1",
      [{title, trim(Title)},
       {artist, trim(Artist)},
       {album, trim(Album)}]}};
parse_v1_or_v11_tag(_) ->
    error.
   
trim(Bin) ->
    list_to_binary(trim_blanks(binary_to_list(Bin))).

trim_blanks(L) ->
    reverse(skip_blanks_and_zero(reverse(L))).

skip_blanks_and_zero([$\s|T]) ->
    skip_blanks_and_zero(T);
skip_blanks_and_zero([0|T]) ->
    skip_blanks_and_zero(T);
skip_blanks_and_zero(L) ->
    L.
---

When I use the function read_v1_or_v11_tag on a mp3 file containing 
version 1 tag, it returns an error. However, when the function 
read_only_v1_tag is applied on the same file, it reads the tag data 
correctly. The only difference between these two functions is that the 
former has an extra branch to read version 1.1 tag.

Is this a bug or have I missed something?

I've included an example file which contains only the id3 v1 tag data 
(last 128 bytes of the mp3 file).

Thanks in advance

/Tom

-------------- next part --------------
A non-text attachment was scrubbed...
Name: id3_v1.mp3
Type: audio/mpeg
Size: 128 bytes
Desc: not available
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080223/ea6a3e11/attachment.mp3>


More information about the erlang-questions mailing list