1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2000-2016. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21-module(bs_match_misc_SUITE). 22 23-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, 24 init_per_testcase/2,end_per_testcase/2, 25 init_per_suite/1,end_per_suite/1, 26 bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1, 27 kenneth/1,encode_binary/1,native/1,happi/1, 28 size_var/1,wiger/1,x0_context/1,huge_float_field/1, 29 writable_binary_matched/1,otp_7198/1, 30 unordered_bindings/1,float_middle_endian/1]). 31 32-include_lib("common_test/include/ct.hrl"). 33 34suite() -> 35 [{ct_hooks,[ts_install_cth]}, 36 {timetrap,{minutes,15}}]. 37 38all() -> 39 [bound_var, bound_tail, t_float, little_float, sean, 40 kenneth, encode_binary, native, happi, size_var, wiger, 41 x0_context, huge_float_field, writable_binary_matched, 42 otp_7198, unordered_bindings, float_middle_endian]. 43 44groups() -> 45 []. 46 47init_per_group(_GroupName, Config) -> 48 Config. 49 50end_per_group(_GroupName, Config) -> 51 Config. 52 53init_per_suite(Config) when is_list(Config) -> 54 test_lib:interpret(?MODULE), 55 true = lists:member(?MODULE, int:interpreted()), 56 Config. 57 58end_per_suite(Config) when is_list(Config) -> 59 ok. 60 61init_per_testcase(_Case, Config) -> 62 test_lib:interpret(?MODULE), 63 Config. 64 65end_per_testcase(_Case, _Config) -> 66 ok. 67 68%% Test matching of bound variables. 69bound_var(Config) when is_list(Config) -> 70 ok = bound_var(42, 13, <<42,13>>), 71 nope = bound_var(42, 13, <<42,255>>), 72 nope = bound_var(42, 13, <<154,255>>), 73 ok. 74 75bound_var(A, B, <<A:8,B:8>>) -> ok; 76bound_var(_, _, _) -> nope. 77 78%% Test matching of a bound tail. 79bound_tail(Config) when is_list(Config) -> 80 ok = bound_tail(<<>>, <<13,14>>), 81 ok = bound_tail(<<2,3>>, <<1,1,2,3>>), 82 nope = bound_tail(<<2,3>>, <<1,1,2,7>>), 83 nope = bound_tail(<<2,3>>, <<1,1,2,3,4>>), 84 nope = bound_tail(<<2,3>>, <<>>), 85 ok. 86 87bound_tail(T, <<_:16,T/binary>>) -> ok; 88bound_tail(_, _) -> nope. 89 90t_float(Config) when is_list(Config) -> 91 F = f1(), 92 G = f_one(), 93 94 G = match_float(<<63,128,0,0>>, 32, 0), 95 G = match_float(<<63,240,0,0,0,0,0,0>>, 64, 0), 96 97 fcmp(F, match_float(<<F:32/float>>, 32, 0)), 98 fcmp(F, match_float(<<F:64/float>>, 64, 0)), 99 fcmp(F, match_float(<<1:1,F:32/float,127:7>>, 32, 1)), 100 fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)), 101 fcmp(F, match_float(<<1:13,F:32/float,127:3>>, 32, 13)), 102 fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)), 103 104 {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16, 0)), 105 {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16#7fffffff, 0)), 106 107 ok. 108 109float_middle_endian(Config) when is_list(Config) -> 110 F = 9007199254740990.0, % turns to -NaN when word-swapped 111 fcmp(F, match_float(<<F:64/float>>, 64, 0)), 112 fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)), 113 fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)), 114 ok. 115 116 117fcmp(F1, F2) when (F1 - F2) / F2 < 0.0000001 -> ok. 118 119match_float(Bin0, Fsz, I) -> 120 Bin = make_sub_bin(Bin0), 121 Bsz = size(Bin) * 8, 122 Tsz = Bsz - Fsz - I, 123 <<_:I,F:Fsz/float,_:Tsz>> = Bin, 124 F. 125 126little_float(Config) when is_list(Config) -> 127 F = f2(), 128 G = f_one(), 129 130 G = match_float_little(<<0,0,0,0,0,0,240,63>>, 64, 0), 131 G = match_float_little(<<0,0,128,63>>, 32, 0), 132 133 fcmp(F, match_float_little(<<F:32/float-little>>, 32, 0)), 134 fcmp(F, match_float_little(<<F:64/float-little>>, 64, 0)), 135 fcmp(F, match_float_little(<<1:1,F:32/float-little,127:7>>, 32, 1)), 136 fcmp(F, match_float_little(<<1:1,F:64/float-little,127:7>>, 64, 1)), 137 fcmp(F, match_float_little(<<1:13,F:32/float-little,127:3>>, 32, 13)), 138 fcmp(F, match_float_little(<<1:13,F:64/float-little,127:3>>, 64, 13)), 139 140 ok. 141 142match_float_little(Bin0, Fsz, I) -> 143 Bin = make_sub_bin(Bin0), 144 Bsz = size(Bin) * 8, 145 Tsz = Bsz - Fsz - I, 146 <<_:I,F:Fsz/float-little,_:Tsz>> = Bin, 147 F. 148 149 150make_sub_bin(Bin0) -> 151 Sz = size(Bin0), 152 Bin1 = <<37,Bin0/binary,38,39>>, 153 <<_:8,Bin:Sz/binary,_:8,_:8>> = Bin1, 154 Bin. 155 156f1() -> 157 3.1415. 158 159f2() -> 160 2.7133. 161 162f_one() -> 163 1.0. 164 165sean(Config) when is_list(Config) -> 166 small = sean1(<<>>), 167 small = sean1(<<1>>), 168 small = sean1(<<1,2>>), 169 small = sean1(<<1,2,3>>), 170 large = sean1(<<1,2,3,4>>), 171 172 small = sean1(<<4>>), 173 small = sean1(<<4,5>>), 174 small = sean1(<<4,5,6>>), 175 {'EXIT',{function_clause,_}} = (catch sean1(<<4,5,6,7>>)), 176 ok. 177 178sean1(<<B/binary>>) when byte_size(B) < 4 -> small; 179sean1(<<1, _B/binary>>) -> large. 180 181kenneth(Config) when is_list(Config) -> 182 {ok,[145,148,113,129,0,0,0,0]} = 183 msisdn_internal_storage(<<145,148,113,129,0,0,0,0>>, []). 184 185msisdn_internal_storage(<<>>,MSISDN) -> 186 {ok,lists:reverse(MSISDN)}; 187msisdn_internal_storage(<<2#11111111:8,_Rest/binary>>,MSISDN) -> 188 {ok,lists:reverse(MSISDN)}; 189msisdn_internal_storage(<<2#1111:4,DigitN:4,_Rest/binary>>,MSISDN) when 190 DigitN < 10 -> 191 {ok,lists:reverse([(DigitN bor 2#11110000)|MSISDN])}; 192msisdn_internal_storage(<<DigitNplus1:4,DigitN:4,Rest/binary>>,MSISDN) when 193 DigitNplus1 < 10, 194 DigitN < 10 -> 195 NewMSISDN=[((DigitNplus1 bsl 4) bor DigitN)|MSISDN], 196 msisdn_internal_storage(Rest,NewMSISDN); 197msisdn_internal_storage(_Rest,_MSISDN) -> 198 {fault}. %% Mandatory IE incorrect 199 200encode_binary(Config) when is_list(Config) -> 201 "C2J2QiSc" = encodeBinary(<<11,98,118,66,36,156>>, []), 202 ok. 203 204encodeBinary(<<>>, Output) -> 205 lists:reverse(Output); 206encodeBinary(<<Data:1/binary>>, Output) -> 207 <<DChar1:6, DChar2:2>> = Data, 208 Char1 = getBase64Char(DChar1), 209 Char2 = getBase64Char(DChar2), 210 Char3 = "=", 211 Char4 = "=", 212 NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output, 213 encodeBinary(<<>>, NewOutput); 214encodeBinary(<<Data:2/binary>>, Output) -> 215 <<DChar1:6, DChar2:6, DChar3:4>> = Data, 216 Char1 = getBase64Char(DChar1), 217 Char2 = getBase64Char(DChar2), 218 Char3 = getBase64Char(DChar3), 219 Char4 = "=", 220 NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output, 221 encodeBinary(<<>>, NewOutput); 222encodeBinary(<<Data:3/binary, Rest/binary>>, Output) -> 223 <<DChar1:6, DChar2:6, DChar3:6, DChar4:6>> = Data, 224 Char1 = getBase64Char(DChar1), 225 Char2 = getBase64Char(DChar2), 226 Char3 = getBase64Char(DChar3), 227 Char4 = getBase64Char(DChar4), 228 NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output, 229 encodeBinary(Rest, NewOutput); 230encodeBinary(_Data, _) -> 231 error. 232 233getBase64Char(0) -> "A"; 234getBase64Char(1) -> "B"; 235getBase64Char(2) -> "C"; 236getBase64Char(3) -> "D"; 237getBase64Char(4) -> "E"; 238getBase64Char(5) -> "F"; 239getBase64Char(6) -> "G"; 240getBase64Char(7) -> "H"; 241getBase64Char(8) -> "I"; 242getBase64Char(9) -> "J"; 243getBase64Char(10) -> "K"; 244getBase64Char(11) -> "L"; 245getBase64Char(12) -> "M"; 246getBase64Char(13) -> "N"; 247getBase64Char(14) -> "O"; 248getBase64Char(15) -> "P"; 249getBase64Char(16) -> "Q"; 250getBase64Char(17) -> "R"; 251getBase64Char(18) -> "S"; 252getBase64Char(19) -> "T"; 253getBase64Char(20) -> "U"; 254getBase64Char(21) -> "V"; 255getBase64Char(22) -> "W"; 256getBase64Char(23) -> "X"; 257getBase64Char(24) -> "Y"; 258getBase64Char(25) -> "Z"; 259getBase64Char(26) -> "a"; 260getBase64Char(27) -> "b"; 261getBase64Char(28) -> "c"; 262getBase64Char(29) -> "d"; 263getBase64Char(30) -> "e"; 264getBase64Char(31) -> "f"; 265getBase64Char(32) -> "g"; 266getBase64Char(33) -> "h"; 267getBase64Char(34) -> "i"; 268getBase64Char(35) -> "j"; 269getBase64Char(36) -> "k"; 270getBase64Char(37) -> "l"; 271getBase64Char(38) -> "m"; 272getBase64Char(39) -> "n"; 273getBase64Char(40) -> "o"; 274getBase64Char(41) -> "p"; 275getBase64Char(42) -> "q"; 276getBase64Char(43) -> "r"; 277getBase64Char(44) -> "s"; 278getBase64Char(45) -> "t"; 279getBase64Char(46) -> "u"; 280getBase64Char(47) -> "v"; 281getBase64Char(48) -> "w"; 282getBase64Char(49) -> "x"; 283getBase64Char(50) -> "y"; 284getBase64Char(51) -> "z"; 285getBase64Char(52) -> "0"; 286getBase64Char(53) -> "1"; 287getBase64Char(54) -> "2"; 288getBase64Char(55) -> "3"; 289getBase64Char(56) -> "4"; 290getBase64Char(57) -> "5"; 291getBase64Char(58) -> "6"; 292getBase64Char(59) -> "7"; 293getBase64Char(60) -> "8"; 294getBase64Char(61) -> "9"; 295getBase64Char(62) -> "+"; 296getBase64Char(63) -> "/"; 297getBase64Char(_Else) -> 298 %% This is an illegal input. 299 %% cgLogEM:log(error, ?MODULE, getBase64Char, [Else], 300 %% "illegal input", 301 %% ?LINE, version()), 302 "**". 303 304-define(M(F), <<F>> = <<F>>). 305 306native(Config) when is_list(Config) -> 307 ?M(3.14:64/native-float), 308 ?M(333:16/native), 309 ?M(38658345:32/native), 310 case <<1:16/native>> of 311 <<0,1>> -> native_big(); 312 <<1,0>> -> native_little() 313 end. 314 315native_big() -> 316 <<37.33:64/native-float>> = <<37.33:64/big-float>>, 317 <<3974:16/native-integer>> = <<3974:16/big-integer>>, 318 {comment,"Big endian"}. 319 320native_little() -> 321 <<37869.32343:64/native-float>> = <<37869.32343:64/little-float>>, 322 <<7974:16/native-integer>> = <<7974:16/little-integer>>, 323 {comment,"Little endian"}. 324 325happi(Config) when is_list(Config) -> 326 Bin = <<".123">>, 327 <<"123">> = lex_digits1(Bin, 1, []), 328 <<"123">> = lex_digits2(Bin, 1, []), 329 ok. 330 331lex_digits1(<<$., Rest/binary>>,_Val,_Acc) -> 332 Rest; 333lex_digits1(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 -> 334 lex_digits1(Rest,Val*10+dec(N),Acc); 335lex_digits1(_Other,_Val,_Acc) -> 336 not_ok. 337 338lex_digits2(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 -> 339 lex_digits2(Rest,Val*10+dec(N),Acc); 340lex_digits2(<<$., Rest/binary>>,_Val,_Acc) -> 341 Rest; 342lex_digits2(_Other,_Val,_Acc) -> 343 not_ok. 344 345dec(A) -> 346 A-$0. 347 348size_var(Config) when is_list(Config) -> 349 {<<45>>,<<>>} = split(<<1:16,45>>), 350 {<<45>>,<<46,47>>} = split(<<1:16,45,46,47>>), 351 {<<45,46>>,<<47>>} = split(<<2:16,45,46,47>>), 352 353 {<<45,46,47>>,<<48>>} = split_2(<<16:8,3:16,45,46,47,48>>), 354 355 {<<45,46>>,<<47>>} = split(2, <<2:16,45,46,47>>), 356 {'EXIT',{function_clause,_}} = (catch split(42, <<2:16,45,46,47>>)), 357 358 <<"cdef">> = skip(<<2:8,"abcdef">>), 359 360 ok. 361 362split(<<N:16,B:N/binary,T/binary>>) -> 363 {B,T}. 364 365split(N, <<N:16,B:N/binary,T/binary>>) -> 366 {B,T}. 367 368split_2(<<N0:8,N:N0,B:N/binary,T/binary>>) -> 369 {B,T}. 370 371skip(<<N:8,_:N/binary,T/binary>>) -> T. 372 373wiger(Config) when is_list(Config) -> 374 ok1 = wcheck(<<3>>), 375 ok2 = wcheck(<<1,2,3>>), 376 ok3 = wcheck(<<4>>), 377 {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>), 378 {error,<<>>} = wcheck(<<>>), 379 ok. 380 381wcheck(<<A>>) when A==3-> 382 ok1; 383wcheck(<<_,_:2/binary>>) -> 384 ok2; 385wcheck(<<_>>) -> 386 ok3; 387wcheck(Other) -> 388 {error,Other}. 389 390%% Test that having the match context in x(0) works. 391 392x0_context(Config) when is_list(Config) -> 393 x0_0([], <<3.0:64/float,42:16,123456:32>>). 394 395x0_0(_, Bin) -> 396 <<3.0:64/float,42:16,_/binary>> = Bin, 397 x0_1([], Bin, 64, 16, 2). 398 399x0_1(_, Bin, FloatSz, IntSz, BinSz) -> 400 <<_:FloatSz/float,42:IntSz,B:BinSz/binary,C:1/binary,D/binary>> = Bin, 401 id({B,C,D}), 402 <<_:FloatSz/float,42:IntSz,B:BinSz/binary,_/binary>> = Bin, 403 x0_2([], Bin). 404 405x0_2(_, Bin) -> 406 <<_:64,0:7,42:9,_/binary>> = Bin, 407 x0_3([], Bin). 408 409x0_3(_, Bin) -> 410 case Bin of 411 <<_:72,7:8,_/binary>> -> 412 ct:fail(failed); 413 <<_:64,0:16,_/binary>> -> 414 ct:fail(failed); 415 <<_:64,42:16,123456:32,_/binary>> -> 416 ok 417 end. 418 419 420huge_float_field(Config) when is_list(Config) -> 421 Sz = 1 bsl 27, 422 Bin = <<0:Sz>>, 423 424 nomatch = overflow_huge_float_skip_32(Bin), 425 nomatch = overflow_huge_float_32(Bin), 426 427 ok = overflow_huge_float(Bin, lists:seq(25, 32)++lists:seq(50, 64)), 428 ok = overflow_huge_float_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)), 429 ok. 430 431overflow_huge_float_skip_32(<<_:4294967296/float,0,_/binary>>) -> 1; % 1 bsl 32 432overflow_huge_float_skip_32(<<_:33554432/float-unit:128,0,_/binary>>) -> 2; % 1 bsl 25 433overflow_huge_float_skip_32(<<_:67108864/float-unit:64,0,_/binary>>) -> 3; % 1 bsl 26 434overflow_huge_float_skip_32(<<_:134217728/float-unit:32,0,_/binary>>) -> 4; % 1 bsl 27 435overflow_huge_float_skip_32(<<_:268435456/float-unit:16,0,_/binary>>) -> 5; % 1 bsl 28 436overflow_huge_float_skip_32(<<_:536870912/float-unit:8,0,_/binary>>) -> 6; % 1 bsl 29 437overflow_huge_float_skip_32(<<_:1073741824/float-unit:8,0,_/binary>>) -> 7; % 1 bsl 30 438overflow_huge_float_skip_32(<<_:2147483648/float-unit:8,0,_/binary>>) -> 8; % 1 bsl 31 439overflow_huge_float_skip_32(_) -> nomatch. 440 441overflow_huge_float_32(<<F:4294967296/float,_/binary>>) -> {1,F}; % 1 bsl 32 442overflow_huge_float_32(<<F:33554432/float-unit:128,0,_/binary>>) -> {2,F}; % 1 bsl 25 443overflow_huge_float_32(<<F:67108864/float-unit:128,0,_/binary>>) -> {3,F}; % 1 bsl 26 444overflow_huge_float_32(<<F:134217728/float-unit:128,0,_/binary>>) -> {4,F}; % 1 bsl 27 445overflow_huge_float_32(<<F:268435456/float-unit:128,0,_/binary>>) -> {5,F}; % 1 bsl 28 446overflow_huge_float_32(<<F:536870912/float-unit:128,0,_/binary>>) -> {6,F}; % 1 bsl 29 447overflow_huge_float_32(<<F:1073741824/float-unit:128,0,_/binary>>) -> {7,F}; % 1 bsl 30 448overflow_huge_float_32(<<F:2147483648/float-unit:128,0,_/binary>>) -> {8,F}; % 1 bsl 31 449overflow_huge_float_32(_) -> nomatch. 450 451 452overflow_huge_float(Bin, [Sz0|Sizes]) -> 453 Sz = id(1 bsl Sz0), 454 case Bin of 455 <<_:Sz/float-unit:8,0,_/binary>> -> 456 {error,Sz}; 457 _ -> 458 case Bin of 459 <<Var:Sz/float-unit:8,0,_/binary>> -> 460 {error,Sz,Var}; 461 _ -> 462 overflow_huge_float(Bin, Sizes) 463 end 464 end; 465overflow_huge_float(_, []) -> ok. 466 467overflow_huge_float_unit128(Bin, [Sz0|Sizes]) -> 468 Sz = id(1 bsl Sz0), 469 case Bin of 470 <<_:Sz/float-unit:128,0,_/binary>> -> 471 {error,Sz}; 472 _ -> 473 case Bin of 474 <<Var:Sz/float-unit:128,0,_/binary>> -> 475 {error,Sz,Var}; 476 _ -> 477 overflow_huge_float_unit128(Bin, Sizes) 478 end 479 end; 480overflow_huge_float_unit128(_, []) -> ok. 481 482 483%% 484%% Test that a writable binary can be safely matched. 485%% 486 487writable_binary_matched(Config) when is_list(Config) -> 488 WritableBin = create_writeable_binary(), 489 writable_binary_matched(WritableBin, WritableBin, 500). 490 491writable_binary_matched(<<0>>, _, N) -> 492 if 493 N =:= 0 -> ok; 494 true -> 495 put(grow_heap, [N|get(grow_heap)]), 496 WritableBin = create_writeable_binary(), 497 writable_binary_matched(WritableBin, WritableBin, N-1) 498 end; 499writable_binary_matched(<<B:8,T/binary>>, WritableBin0, N) -> 500 WritableBin = writable_binary(WritableBin0, B), 501 writable_binary_matched(T, WritableBin, N). 502 503writable_binary(WritableBin0, B) when is_binary(WritableBin0) -> 504 %% Heavy append to force the binary to move. 505 WritableBin = <<WritableBin0/binary,0:(size(WritableBin0))/unit:8,B>>, 506 id(<<(id(0)):128/unit:8>>), 507 WritableBin. 508 509create_writeable_binary() -> 510 <<(id(<<>>))/binary,1,2,3,4,5,6,0>>. 511 512otp_7198(Config) when is_list(Config) -> 513 %% When a match context was reused, and grown at the same time to 514 %% increase the number of saved positions, the thing word was not updated 515 %% to account for the new size. Therefore, if there was a garbage collection, 516 %% the new slots would be included in the garbage collection. 517 [do_otp_7198(FillerSize) || FillerSize <- lists:seq(0, 256)], 518 ok. 519 520do_otp_7198(FillerSize) -> 521 Filler = erlang:make_tuple(FillerSize, 42), 522 {Pid,Ref} = spawn_monitor(fun() -> do_otp_7198_test(Filler) end), 523 receive 524 {'DOWN',Ref,process,Pid,normal} -> 525 ok; 526 {'DOWN',Ref,process,Pid,Reason} -> 527 io:format("unexpected: ~p", [Reason]), 528 ct:fail(failed) 529 end. 530 531do_otp_7198_test(_) -> 532 [{'KEYWORD',114}, 533 {'KEYWORD',101}, 534 {'KEYWORD',103}, 535 {'KEYWORD',105}, 536 {'KEYWORD',111}, 537 {'FIELD',110}, 538 {'KEYWORD',119}, 539 {'KEYWORD',104}, 540 {'KEYWORD',97}, 541 {'KEYWORD',116}, 542 {'KEYWORD',101}, 543 {'KEYWORD',118}, 544 {'KEYWORD',101}, 545 {'KEYWORD',114}, 546 '$thats_all_folks$'] = otp_7198_scan(<<"region:whatever">>, []). 547 548 549otp_7198_scan(<<>>, TokAcc) -> 550 lists:reverse(['$thats_all_folks$' | TokAcc]); 551 552otp_7198_scan(<<D, Z, Rest/binary>>, TokAcc) when 553 (D =:= $D orelse D =:= $d) and 554 ((Z =:= $\s) or (Z =:= $() or (Z =:= $))) -> 555 otp_7198_scan(<<Z, Rest/binary>>, ['AND' | TokAcc]); 556 557otp_7198_scan(<<D>>, TokAcc) when 558 (D =:= $D) or (D =:= $d) -> 559 otp_7198_scan(<<>>, ['AND' | TokAcc]); 560 561otp_7198_scan(<<N, Z, Rest/binary>>, TokAcc) when 562 (N =:= $N orelse N =:= $n) and 563 ((Z =:= $\s) or (Z =:= $() or (Z =:= $))) -> 564 otp_7198_scan(<<Z, Rest/binary>>, ['NOT' | TokAcc]); 565 566otp_7198_scan(<<C, Rest/binary>>, TokAcc) when 567 (C >= $A) and (C =< $Z); 568 (C >= $a) and (C =< $z); 569 (C >= $0) and (C =< $9) -> 570 case Rest of 571 <<$:, R/binary>> -> 572 otp_7198_scan(R, [{'FIELD', C} | TokAcc]); 573 _ -> 574 otp_7198_scan(Rest, [{'KEYWORD', C} | TokAcc]) 575 end. 576 577unordered_bindings(Config) when is_list(Config) -> 578 {<<1,2,3,4>>,<<42,42>>,<<3,3,3>>} = 579 unordered_bindings(4, 2, 3, <<1,2,3,4, 42,42, 3,3,3, 3>>), 580 ok. 581 582unordered_bindings(CompressedLength, HashSize, PadLength, T) -> 583 <<Content:CompressedLength/binary,Mac:HashSize/binary, 584 Padding:PadLength/binary,PadLength>> = T, 585 {Content,Mac,Padding}. 586 587 588id(I) -> I. 589