/lss_parse_utils/src/lss_parse_utils.erl

https://github.com/ashneyderman/lss · Erlang · 73 lines · 26 code · 8 blank · 39 comment · 0 complexity · fa84d96c6643954bded26072060f6f00 MD5 · raw file

  1. % @author Alex Shneyderman <a.shneyderman@gmail.com>
  2. % @copyright (C) 2011, Alex Shneyderman
  3. % @since May 26, 2011
  4. %--------------------------------------------------------------------
  5. % @doc
  6. % Helper module that contains routines that parse a binary stream
  7. % and produce messages (tuples) to be consumed by LSS. The operation
  8. % can work in reverse as well - given a tuple a binary could be
  9. % produced.
  10. % @end
  11. %--------------------------------------------------------------------
  12. -module(lss_parse_utils).
  13. -export([parse_messages/1,create_messages/1]).
  14. -define(START_MSG_MARKER,<<16#FF,16#FF,16#FF,16#FF,16#FF,16#FF,16#FF,16#FF>>).
  15. %--------------------------------------------------------------------
  16. % @doc
  17. % Parsing messages out of the chunks of binaries that arrived on the socket.
  18. % The function returns a list of messages taht were parsed and left over binary
  19. % chunks.
  20. %
  21. % @spec parse_messages(Binaries) -> { Messages } |
  22. % { Messages, LeftOver }
  23. % Binaries = [binary()]
  24. % Messages = [term()]
  25. % LeftOver = binary()
  26. %
  27. % @end
  28. %--------------------------------------------------------------------
  29. parse_messages( Binaries ) ->
  30. consume_binary( list_to_binary( lists:reverse( Binaries ) ) ).
  31. %--------------------------------------------------------------------
  32. % @doc
  33. % Takes a term or a list of terms and converts them into a list
  34. % of binaries that can be sent out via the wire. Terms are separates
  35. % by the START_MSG_MARKER, which is appended to the end of each term.
  36. %
  37. % @spec create_messages(Term|Terms) -> { Messages }
  38. % Term = term()
  39. % Terms = [term()]
  40. % Messages = [binary()]
  41. % @end
  42. %--------------------------------------------------------------------
  43. create_messages([]) -> [];
  44. create_messages([Term|Terms]) -> lists:append( create_messages(Term), create_messages(Terms) );
  45. create_messages(Term) when is_tuple(Term)-> [term_to_binary(Term), ?START_MSG_MARKER].
  46. % module functions
  47. %--------------------------------------------------------------------
  48. consume_binary( <<>> ) -> { [] };
  49. consume_binary( Binary ) ->
  50. BinChunks = binary:split( Binary, ?START_MSG_MARKER, [ global ] ),
  51. Messages = produce_msgs( [], BinChunks ),
  52. case lists:last( BinChunks ) of
  53. <<>> ->
  54. { Messages };
  55. Other ->
  56. { Messages, Other }
  57. end.
  58. produce_msgs( SoFar, [] ) -> SoFar;
  59. produce_msgs( SoFar, [BinTerm,<<>> | Tail] ) -> % <<>> stands for the message separator, so BinTerm represents a full message
  60. case produce_msg( BinTerm ) of
  61. undefined -> produce_msgs( SoFar, Tail );
  62. Term -> produce_msgs( lists:append( SoFar, [Term] ), Tail )
  63. end.
  64. produce_msg( <<>> ) -> undefined;
  65. produce_msg( BinTerm ) -> binary_to_term( BinTerm ).