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