1: %%
    2: %% %CopyrightBegin%
    3: %% 
    4: %% Copyright Ericsson AB 1999-2011. All Rights Reserved.
    5: %% 
    6: %% The contents of this file are subject to the Erlang Public License,
    7: %% Version 1.1, (the "License"); you may not use this file except in
    8: %% compliance with the License. You should have received a copy of the
    9: %% Erlang Public License along with this software. If not, it can be
   10: %% retrieved online at http://www.erlang.org/.
   11: %% 
   12: %% Software distributed under the License is distributed on an "AS IS"
   13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   14: %% the License for the specific language governing rights and limitations
   15: %% under the License.
   16: %% 
   17: %% %CopyrightEnd%
   18: %%
   19: 
   20: -module(bs_match_bin_no_opt_SUITE).
   21: 
   22: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   23: 	 init_per_group/2,end_per_group/2,
   24: 	 byte_split_binary/1,bit_split_binary/1,match_huge_bin/1]).
   25: 
   26: -include_lib("test_server/include/test_server.hrl").
   27: 
   28: suite() -> [{ct_hooks,[ts_install_cth]}].
   29: 
   30: all() -> 
   31:     [byte_split_binary, bit_split_binary, match_huge_bin].
   32: 
   33: groups() -> 
   34:     [].
   35: 
   36: init_per_suite(Config) ->
   37:     Config.
   38: 
   39: end_per_suite(_Config) ->
   40:     ok.
   41: 
   42: init_per_group(_GroupName, Config) ->
   43:     Config.
   44: 
   45: end_per_group(_GroupName, Config) ->
   46:     Config.
   47: 
   48: 
   49: byte_split_binary(doc) -> "Tries to split a binary at all byte-aligned positions.";
   50: byte_split_binary(Config) when is_list(Config) ->
   51:     ?line L = lists:seq(0, 57),
   52:     ?line B = mkbin(L),
   53:     ?line byte_split(L, B, size(B)),
   54:     ?line Unaligned = make_unaligned_sub_binary(B),
   55:     ?line byte_split(L, Unaligned, size(Unaligned)).
   56: 
   57: byte_split(L, B, Pos) when Pos >= 0 ->
   58:     ?line Sz1 = Pos,
   59:     ?line Sz2 = size(B) - Pos,
   60:     ?line <<B1:Sz1/binary,B2:Sz2/binary>> = B,
   61:     ?line B1 = list_to_binary(lists:sublist(L, 1, Pos)),
   62:     ?line B2 = list_to_binary(lists:nthtail(Pos, L)),
   63:     ?line byte_split(L, B, Pos-1);
   64: byte_split(_, _, _) -> ok.
   65: 
   66: bit_split_binary(doc) -> "Tries to split a binary at all positions.";
   67: bit_split_binary(Config) when is_list(Config) ->
   68:     Fun = fun(Bin, List, SkipBef, N) ->
   69: 		  ?line SkipAft = 8*size(Bin) - N - SkipBef,
   70: 		  %%io:format("~p, ~p, ~p", [SkipBef,N,SkipAft]),
   71: 		  ?line <<_:SkipBef,OutBin:N/binary-unit:1,_:SkipAft>> = Bin,
   72: 		  ?line OutBin = make_bin_from_list(List, N)
   73: 	  end,
   74:     ?line bit_split_binary1(Fun, erlang:md5(<<1,2,3>>)),
   75:     ?line bit_split_binary1(Fun,
   76: 			    make_unaligned_sub_binary(erlang:md5(<<1,2,3>>))),
   77:     ok.
   78: 
   79: bit_split_binary1(Action, Bin) ->
   80:     BitList = bits_to_list(binary_to_list(Bin), 16#80),
   81:     bit_split_binary2(Action, Bin, BitList, 0).
   82: 
   83: bit_split_binary2(Action, Bin, [_|T]=List, Bef) ->
   84:     bit_split_binary3(Action, Bin, List, Bef, size(Bin)*8),
   85:     bit_split_binary2(Action, Bin, T, Bef+1);
   86: bit_split_binary2(_, _, [], _) -> ok.
   87: 
   88: bit_split_binary3(Action, Bin, List, Bef, Aft) when Bef =< Aft ->
   89:     Action(Bin, List, Bef, (Aft-Bef) div 8 * 8),
   90:     bit_split_binary3(Action, Bin, List, Bef, Aft-8);
   91: bit_split_binary3(_, _, _, _, _) -> ok.
   92: 
   93: make_bin_from_list(_, 0) -> mkbin([]);
   94: make_bin_from_list(List, N) ->
   95:     list_to_binary([make_int(List, 8, 0),
   96: 		    make_bin_from_list(lists:nthtail(8, List), N-8)]).
   97: 
   98: 
   99: make_int(_, 0, Acc) -> Acc;
  100: make_int([H|T], N, Acc) -> make_int(T, N-1, Acc bsl 1 bor H).
  101:     
  102: bits_to_list([_|T], 0) -> bits_to_list(T, 16#80);
  103: bits_to_list([H|_]=List, Mask) ->
  104:     [case H band Mask of
  105: 	 0 -> 0;
  106: 	 _ -> 1
  107:      end|bits_to_list(List, Mask bsr 1)];
  108: bits_to_list([], _) -> [].
  109: 
  110: mkbin(L) when is_list(L) -> list_to_binary(L).
  111: 
  112: make_unaligned_sub_binary(Bin0) ->
  113:     Bin1 = <<0:3,Bin0/binary,31:5>>,
  114:     Sz = size(Bin0),
  115:     <<0:3,Bin:Sz/binary,31:5>> = id(Bin1),
  116:     Bin.
  117: 
  118: id(I) -> I.
  119: 
  120: match_huge_bin(Config) when is_list(Config) ->
  121:     ?line Bin = <<0:(1 bsl 27),13:8>>,
  122:     ?line skip_huge_bin_1(1 bsl 27, Bin),
  123:     ?line 16777216 = match_huge_bin_1(1 bsl 27, Bin),
  124:     
  125:     %% Test overflowing the size of a binary field.
  126:     ?line nomatch = overflow_huge_bin_skip_32(Bin),
  127:     ?line nomatch = overflow_huge_bin_32(Bin),
  128:     ?line nomatch = overflow_huge_bin_skip_64(Bin),
  129:     ?line nomatch = overflow_huge_bin_64(Bin),
  130: 
  131:     %% Size in variable
  132:     ?line ok = overflow_huge_bin(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
  133:     ?line ok = overflow_huge_bin_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
  134: 
  135:     ok.
  136: 
  137: overflow_huge_bin(Bin, [Sz0|Sizes]) ->
  138:     Sz = id(1 bsl Sz0),
  139:     case Bin of
  140: 	<<_:Sz/binary-unit:8,0,_/binary>> ->
  141: 	    {error,Sz};
  142: 	_ ->
  143: 	    case Bin of
  144: 		<<NewBin:Sz/binary-unit:8,0,_/binary>> ->
  145: 		    {error,Sz,size(NewBin)};
  146: 		_ ->
  147: 		    overflow_huge_bin(Bin, Sizes)
  148: 	    end
  149:     end;
  150: overflow_huge_bin(_, []) -> ok.
  151: 
  152: overflow_huge_bin_unit128(Bin, [Sz0|Sizes]) ->
  153:     Sz = id(1 bsl Sz0),
  154:     case Bin of
  155: 	<<_:Sz/binary-unit:128,0,_/binary>> ->
  156: 	    {error,Sz};
  157: 	_ ->
  158: 	    case Bin of
  159: 		<<NewBin:Sz/binary-unit:128,0,_/binary>> ->
  160: 		    {error,Sz,size(NewBin)};
  161: 		_ ->
  162: 		    overflow_huge_bin_unit128(Bin, Sizes)
  163: 	    end
  164:     end;
  165: overflow_huge_bin_unit128(_, []) -> ok.
  166: 
  167: skip_huge_bin_1(I, Bin) ->
  168:     <<_:I/binary-unit:1,13>> = Bin,
  169:     ok.
  170: 
  171: match_huge_bin_1(I, Bin) ->
  172:     case Bin of
  173: 	<<Val:I/binary-unit:1,13>> -> size(Val);
  174: 	_ -> nomatch
  175:     end.
  176: 
  177: overflow_huge_bin_skip_32(<<_:4294967296/binary,0,_/binary>>) -> 1; % 1 bsl 32
  178: overflow_huge_bin_skip_32(<<_:33554432/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 25
  179: overflow_huge_bin_skip_32(<<_:67108864/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 26
  180: overflow_huge_bin_skip_32(<<_:134217728/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 27
  181: overflow_huge_bin_skip_32(<<_:268435456/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 28
  182: overflow_huge_bin_skip_32(<<_:536870912/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 29
  183: overflow_huge_bin_skip_32(<<_:1073741824/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 30
  184: overflow_huge_bin_skip_32(<<_:2147483648/binary-unit:8,0,_/binary>>) -> 8; % 1 bsl 31
  185: overflow_huge_bin_skip_32(_) -> nomatch.
  186: 
  187: overflow_huge_bin_32(<<Bin:4294967296/binary,_/binary>>) -> {1,Bin}; % 1 bsl 32
  188: overflow_huge_bin_32(<<Bin:33554432/binary-unit:128,0,_/binary>>) -> {2,Bin}; % 1 bsl 25
  189: overflow_huge_bin_32(<<Bin:67108864/binary-unit:128,0,_/binary>>) -> {3,Bin}; % 1 bsl 26
  190: overflow_huge_bin_32(<<Bin:134217728/binary-unit:128,0,_/binary>>) -> {4,Bin}; % 1 bsl 27
  191: overflow_huge_bin_32(<<Bin:268435456/binary-unit:128,0,_/binary>>) -> {5,Bin}; % 1 bsl 28
  192: overflow_huge_bin_32(<<Bin:536870912/binary-unit:128,0,_/binary>>) -> {6,Bin}; % 1 bsl 29
  193: overflow_huge_bin_32(<<Bin:1073741824/binary-unit:128,0,_/binary>>) -> {7,Bin}; % 1 bsl 30
  194: overflow_huge_bin_32(<<Bin:2147483648/binary-unit:128,0,_/binary>>) -> {8,Bin}; % 1 bsl 31
  195: overflow_huge_bin_32(_) -> nomatch.
  196: 
  197: overflow_huge_bin_skip_64(<<_:18446744073709551616/binary,0,_/binary>>) -> 1; % 1 bsl 64
  198: overflow_huge_bin_skip_64(<<_:144115188075855872/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 57
  199: overflow_huge_bin_skip_64(<<_:288230376151711744/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 58
  200: overflow_huge_bin_skip_64(<<_:576460752303423488/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 59
  201: overflow_huge_bin_skip_64(<<_:1152921504606846976/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 60
  202: overflow_huge_bin_skip_64(<<_:2305843009213693952/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 61
  203: overflow_huge_bin_skip_64(<<_:4611686018427387904/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 62
  204: overflow_huge_bin_skip_64(<<_:9223372036854775808/binary-unit:8,_/binary>>) -> 8; % 1 bsl 63
  205: overflow_huge_bin_skip_64(_) -> nomatch.
  206: 
  207: overflow_huge_bin_64(<<Bin:18446744073709551616/binary,_/binary>>) -> {1,Bin}; % 1 bsl 64
  208: overflow_huge_bin_64(<<Bin:144115188075855872/binary-unit:128,0,_/binary>>) -> {2,Bin}; % 1 bsl 57
  209: overflow_huge_bin_64(<<Bin:288230376151711744/binary-unit:128,0,_/binary>>) -> {3,Bin}; % 1 bsl 58
  210: overflow_huge_bin_64(<<Bin:576460752303423488/binary-unit:128,0,_/binary>>) -> {4,Bin}; % 1 bsl 59
  211: overflow_huge_bin_64(<<Bin:1152921504606846976/binary-unit:128,0,_/binary>>) -> {5,Bin}; % 1 bsl 60
  212: overflow_huge_bin_64(<<Bin:2305843009213693952/binary-unit:128,0,_/binary>>) -> {6,Bin}; % 1 bsl 61
  213: overflow_huge_bin_64(<<Bin:4611686018427387904/binary-unit:128,0,_/binary>>) -> {7,Bin}; % 1 bsl 62
  214: overflow_huge_bin_64(<<Bin:9223372036854775808/binary-unit:128,0,_/binary>>) -> {8,Bin}; % 1 bsl 63
  215: overflow_huge_bin_64(_) -> nomatch.