1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 2000-2012. 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_misc_SUITE). 21: 22: -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, 23: init_per_testcase/2,end_per_testcase/2, 24: init_per_suite/1,end_per_suite/1, 25: bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1, 26: kenneth/1,encode_binary/1,native/1,happi/1, 27: size_var/1,wiger/1,x0_context/1,huge_float_field/1, 28: writable_binary_matched/1,otp_7198/1, 29: unordered_bindings/1,float_middle_endian/1]). 30: 31: -include_lib("test_server/include/test_server.hrl"). 32: 33: suite() -> [{ct_hooks,[ts_install_cth]}]. 34: 35: all() -> 36: [bound_var, bound_tail, t_float, little_float, sean, 37: kenneth, encode_binary, native, happi, size_var, wiger, 38: x0_context, huge_float_field, writable_binary_matched, 39: otp_7198, unordered_bindings, float_middle_endian]. 40: 41: groups() -> 42: []. 43: 44: init_per_group(_GroupName, Config) -> 45: Config. 46: 47: end_per_group(_GroupName, Config) -> 48: Config. 49: 50: init_per_suite(Config) when is_list(Config) -> 51: ?line test_lib:interpret(?MODULE), 52: ?line true = lists:member(?MODULE, int:interpreted()), 53: Config. 54: 55: end_per_suite(Config) when is_list(Config) -> 56: ok. 57: 58: init_per_testcase(_Case, Config) -> 59: test_lib:interpret(?MODULE), 60: Dog = test_server:timetrap(?t:minutes(15)), 61: [{watchdog,Dog}|Config]. 62: 63: end_per_testcase(_Case, Config) -> 64: Dog = ?config(watchdog, Config), 65: ?t:timetrap_cancel(Dog), 66: ok. 67: 68: bound_var(doc) -> "Test matching of bound variables."; 69: bound_var(Config) when is_list(Config) -> 70: ?line ok = bound_var(42, 13, <<42,13>>), 71: ?line nope = bound_var(42, 13, <<42,255>>), 72: ?line nope = bound_var(42, 13, <<154,255>>), 73: ok. 74: 75: bound_var(A, B, <<A:8,B:8>>) -> ok; 76: bound_var(_, _, _) -> nope. 77: 78: bound_tail(doc) -> "Test matching of a bound tail."; 79: bound_tail(Config) when is_list(Config) -> 80: ?line ok = bound_tail(<<>>, <<13,14>>), 81: ?line ok = bound_tail(<<2,3>>, <<1,1,2,3>>), 82: ?line nope = bound_tail(<<2,3>>, <<1,1,2,7>>), 83: ?line nope = bound_tail(<<2,3>>, <<1,1,2,3,4>>), 84: ?line nope = bound_tail(<<2,3>>, <<>>), 85: ok. 86: 87: bound_tail(T, <<_:16,T/binary>>) -> ok; 88: bound_tail(_, _) -> nope. 89: 90: t_float(Config) when is_list(Config) -> 91: F = f1(), 92: G = f_one(), 93: 94: ?line G = match_float(<<63,128,0,0>>, 32, 0), 95: ?line G = match_float(<<63,240,0,0,0,0,0,0>>, 64, 0), 96: 97: ?line fcmp(F, match_float(<<F:32/float>>, 32, 0)), 98: ?line fcmp(F, match_float(<<F:64/float>>, 64, 0)), 99: ?line fcmp(F, match_float(<<1:1,F:32/float,127:7>>, 32, 1)), 100: ?line fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)), 101: ?line fcmp(F, match_float(<<1:13,F:32/float,127:3>>, 32, 13)), 102: ?line fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)), 103: 104: ?line {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16, 0)), 105: ?line {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16#7fffffff, 0)), 106: 107: ok. 108: 109: float_middle_endian(Config) when is_list(Config) -> 110: F = 9007199254740990.0, % turns to -NaN when word-swapped 111: ?line fcmp(F, match_float(<<F:64/float>>, 64, 0)), 112: ?line fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)), 113: ?line fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)), 114: ok. 115: 116: 117: fcmp(F1, F2) when (F1 - F2) / F2 < 0.0000001 -> ok. 118: 119: match_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: 126: little_float(Config) when is_list(Config) -> 127: F = f2(), 128: G = f_one(), 129: 130: ?line G = match_float_little(<<0,0,0,0,0,0,240,63>>, 64, 0), 131: ?line G = match_float_little(<<0,0,128,63>>, 32, 0), 132: 133: ?line fcmp(F, match_float_little(<<F:32/float-little>>, 32, 0)), 134: ?line fcmp(F, match_float_little(<<F:64/float-little>>, 64, 0)), 135: ?line fcmp(F, match_float_little(<<1:1,F:32/float-little,127:7>>, 32, 1)), 136: ?line fcmp(F, match_float_little(<<1:1,F:64/float-little,127:7>>, 64, 1)), 137: ?line fcmp(F, match_float_little(<<1:13,F:32/float-little,127:3>>, 32, 13)), 138: ?line fcmp(F, match_float_little(<<1:13,F:64/float-little,127:3>>, 64, 13)), 139: 140: ok. 141: 142: match_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: 150: make_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: 156: f1() -> 157: 3.1415. 158: 159: f2() -> 160: 2.7133. 161: 162: f_one() -> 163: 1.0. 164: 165: sean(Config) when is_list(Config) -> 166: ?line small = sean1(<<>>), 167: ?line small = sean1(<<1>>), 168: ?line small = sean1(<<1,2>>), 169: ?line small = sean1(<<1,2,3>>), 170: ?line large = sean1(<<1,2,3,4>>), 171: 172: ?line small = sean1(<<4>>), 173: ?line small = sean1(<<4,5>>), 174: ?line small = sean1(<<4,5,6>>), 175: ?line {'EXIT',{function_clause,_}} = (catch sean1(<<4,5,6,7>>)), 176: ok. 177: 178: sean1(<<B/binary>>) when byte_size(B) < 4 -> small; 179: sean1(<<1, _B/binary>>) -> large. 180: 181: kenneth(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: 185: msisdn_internal_storage(<<>>,MSISDN) -> 186: {ok,lists:reverse(MSISDN)}; 187: msisdn_internal_storage(<<2#11111111:8,_Rest/binary>>,MSISDN) -> 188: {ok,lists:reverse(MSISDN)}; 189: msisdn_internal_storage(<<2#1111:4,DigitN:4,_Rest/binary>>,MSISDN) when 190: DigitN < 10 -> 191: {ok,lists:reverse([(DigitN bor 2#11110000)|MSISDN])}; 192: msisdn_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); 197: msisdn_internal_storage(_Rest,_MSISDN) -> 198: {fault}. %% Mandatory IE incorrect 199: 200: encode_binary(Config) when is_list(Config) -> 201: "C2J2QiSc" = encodeBinary(<<11,98,118,66,36,156>>, []), 202: ok. 203: 204: encodeBinary(<<>>, Output) -> 205: lists:reverse(Output); 206: encodeBinary(<<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); 214: encodeBinary(<<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); 222: encodeBinary(<<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); 230: encodeBinary(_Data, _) -> 231: error. 232: 233: getBase64Char(0) -> "A"; 234: getBase64Char(1) -> "B"; 235: getBase64Char(2) -> "C"; 236: getBase64Char(3) -> "D"; 237: getBase64Char(4) -> "E"; 238: getBase64Char(5) -> "F"; 239: getBase64Char(6) -> "G"; 240: getBase64Char(7) -> "H"; 241: getBase64Char(8) -> "I"; 242: getBase64Char(9) -> "J"; 243: getBase64Char(10) -> "K"; 244: getBase64Char(11) -> "L"; 245: getBase64Char(12) -> "M"; 246: getBase64Char(13) -> "N"; 247: getBase64Char(14) -> "O"; 248: getBase64Char(15) -> "P"; 249: getBase64Char(16) -> "Q"; 250: getBase64Char(17) -> "R"; 251: getBase64Char(18) -> "S"; 252: getBase64Char(19) -> "T"; 253: getBase64Char(20) -> "U"; 254: getBase64Char(21) -> "V"; 255: getBase64Char(22) -> "W"; 256: getBase64Char(23) -> "X"; 257: getBase64Char(24) -> "Y"; 258: getBase64Char(25) -> "Z"; 259: getBase64Char(26) -> "a"; 260: getBase64Char(27) -> "b"; 261: getBase64Char(28) -> "c"; 262: getBase64Char(29) -> "d"; 263: getBase64Char(30) -> "e"; 264: getBase64Char(31) -> "f"; 265: getBase64Char(32) -> "g"; 266: getBase64Char(33) -> "h"; 267: getBase64Char(34) -> "i"; 268: getBase64Char(35) -> "j"; 269: getBase64Char(36) -> "k"; 270: getBase64Char(37) -> "l"; 271: getBase64Char(38) -> "m"; 272: getBase64Char(39) -> "n"; 273: getBase64Char(40) -> "o"; 274: getBase64Char(41) -> "p"; 275: getBase64Char(42) -> "q"; 276: getBase64Char(43) -> "r"; 277: getBase64Char(44) -> "s"; 278: getBase64Char(45) -> "t"; 279: getBase64Char(46) -> "u"; 280: getBase64Char(47) -> "v"; 281: getBase64Char(48) -> "w"; 282: getBase64Char(49) -> "x"; 283: getBase64Char(50) -> "y"; 284: getBase64Char(51) -> "z"; 285: getBase64Char(52) -> "0"; 286: getBase64Char(53) -> "1"; 287: getBase64Char(54) -> "2"; 288: getBase64Char(55) -> "3"; 289: getBase64Char(56) -> "4"; 290: getBase64Char(57) -> "5"; 291: getBase64Char(58) -> "6"; 292: getBase64Char(59) -> "7"; 293: getBase64Char(60) -> "8"; 294: getBase64Char(61) -> "9"; 295: getBase64Char(62) -> "+"; 296: getBase64Char(63) -> "/"; 297: getBase64Char(_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: 306: native(Config) when is_list(Config) -> 307: ?line ?M(3.14:64/native-float), 308: ?line ?M(333:16/native), 309: ?line ?M(38658345:32/native), 310: case <<1:16/native>> of 311: <<0,1>> -> native_big(); 312: <<1,0>> -> native_little() 313: end. 314: 315: native_big() -> 316: ?line <<37.33:64/native-float>> = <<37.33:64/big-float>>, 317: ?line <<3974:16/native-integer>> = <<3974:16/big-integer>>, 318: {comment,"Big endian"}. 319: 320: native_little() -> 321: ?line <<37869.32343:64/native-float>> = <<37869.32343:64/little-float>>, 322: ?line <<7974:16/native-integer>> = <<7974:16/little-integer>>, 323: {comment,"Little endian"}. 324: 325: happi(Config) when is_list(Config) -> 326: Bin = <<".123">>, 327: ?line <<"123">> = lex_digits1(Bin, 1, []), 328: ?line <<"123">> = lex_digits2(Bin, 1, []), 329: ok. 330: 331: lex_digits1(<<$., Rest/binary>>,_Val,_Acc) -> 332: Rest; 333: lex_digits1(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 -> 334: lex_digits1(Rest,Val*10+dec(N),Acc); 335: lex_digits1(_Other,_Val,_Acc) -> 336: not_ok. 337: 338: lex_digits2(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 -> 339: lex_digits2(Rest,Val*10+dec(N),Acc); 340: lex_digits2(<<$., Rest/binary>>,_Val,_Acc) -> 341: Rest; 342: lex_digits2(_Other,_Val,_Acc) -> 343: not_ok. 344: 345: dec(A) -> 346: A-$0. 347: 348: size_var(Config) when is_list(Config) -> 349: ?line {<<45>>,<<>>} = split(<<1:16,45>>), 350: ?line {<<45>>,<<46,47>>} = split(<<1:16,45,46,47>>), 351: ?line {<<45,46>>,<<47>>} = split(<<2:16,45,46,47>>), 352: 353: ?line {<<45,46,47>>,<<48>>} = split_2(<<16:8,3:16,45,46,47,48>>), 354: 355: ?line {<<45,46>>,<<47>>} = split(2, <<2:16,45,46,47>>), 356: ?line {'EXIT',{function_clause,_}} = (catch split(42, <<2:16,45,46,47>>)), 357: 358: ?line <<"cdef">> = skip(<<2:8,"abcdef">>), 359: 360: ok. 361: 362: split(<<N:16,B:N/binary,T/binary>>) -> 363: {B,T}. 364: 365: split(N, <<N:16,B:N/binary,T/binary>>) -> 366: {B,T}. 367: 368: split_2(<<N0:8,N:N0,B:N/binary,T/binary>>) -> 369: {B,T}. 370: 371: skip(<<N:8,_:N/binary,T/binary>>) -> T. 372: 373: wiger(Config) when is_list(Config) -> 374: ?line ok1 = wcheck(<<3>>), 375: ?line ok2 = wcheck(<<1,2,3>>), 376: ?line ok3 = wcheck(<<4>>), 377: ?line {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>), 378: ?line {error,<<>>} = wcheck(<<>>), 379: ok. 380: 381: wcheck(<<A>>) when A==3-> 382: ok1; 383: wcheck(<<_,_:2/binary>>) -> 384: ok2; 385: wcheck(<<_>>) -> 386: ok3; 387: wcheck(Other) -> 388: {error,Other}. 389: 390: %% Test that having the match context in x(0) works. 391: 392: x0_context(Config) when is_list(Config) -> 393: x0_0([], <<3.0:64/float,42:16,123456:32>>). 394: 395: x0_0(_, Bin) -> 396: <<3.0:64/float,42:16,_/binary>> = Bin, 397: x0_1([], Bin, 64, 16, 2). 398: 399: x0_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: 405: x0_2(_, Bin) -> 406: <<_:64,0:7,42:9,_/binary>> = Bin, 407: x0_3([], Bin). 408: 409: x0_3(_, Bin) -> 410: case Bin of 411: <<_:72,7:8,_/binary>> -> 412: ?line ?t:fail(); 413: <<_:64,0:16,_/binary>> -> 414: ?line ?t:fail(); 415: <<_:64,42:16,123456:32,_/binary>> -> 416: ok 417: end. 418: 419: 420: huge_float_field(Config) when is_list(Config) -> 421: Sz = 1 bsl 27, 422: ?line Bin = <<0:Sz>>, 423: 424: ?line nomatch = overflow_huge_float_skip_32(Bin), 425: ?line nomatch = overflow_huge_float_32(Bin), 426: 427: ?line ok = overflow_huge_float(Bin, lists:seq(25, 32)++lists:seq(50, 64)), 428: ?line ok = overflow_huge_float_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)), 429: ok. 430: 431: overflow_huge_float_skip_32(<<_:4294967296/float,0,_/binary>>) -> 1; % 1 bsl 32 432: overflow_huge_float_skip_32(<<_:33554432/float-unit:128,0,_/binary>>) -> 2; % 1 bsl 25 433: overflow_huge_float_skip_32(<<_:67108864/float-unit:64,0,_/binary>>) -> 3; % 1 bsl 26 434: overflow_huge_float_skip_32(<<_:134217728/float-unit:32,0,_/binary>>) -> 4; % 1 bsl 27 435: overflow_huge_float_skip_32(<<_:268435456/float-unit:16,0,_/binary>>) -> 5; % 1 bsl 28 436: overflow_huge_float_skip_32(<<_:536870912/float-unit:8,0,_/binary>>) -> 6; % 1 bsl 29 437: overflow_huge_float_skip_32(<<_:1073741824/float-unit:8,0,_/binary>>) -> 7; % 1 bsl 30 438: overflow_huge_float_skip_32(<<_:2147483648/float-unit:8,0,_/binary>>) -> 8; % 1 bsl 31 439: overflow_huge_float_skip_32(_) -> nomatch. 440: 441: overflow_huge_float_32(<<F:4294967296/float,_/binary>>) -> {1,F}; % 1 bsl 32 442: overflow_huge_float_32(<<F:33554432/float-unit:128,0,_/binary>>) -> {2,F}; % 1 bsl 25 443: overflow_huge_float_32(<<F:67108864/float-unit:128,0,_/binary>>) -> {3,F}; % 1 bsl 26 444: overflow_huge_float_32(<<F:134217728/float-unit:128,0,_/binary>>) -> {4,F}; % 1 bsl 27 445: overflow_huge_float_32(<<F:268435456/float-unit:128,0,_/binary>>) -> {5,F}; % 1 bsl 28 446: overflow_huge_float_32(<<F:536870912/float-unit:128,0,_/binary>>) -> {6,F}; % 1 bsl 29 447: overflow_huge_float_32(<<F:1073741824/float-unit:128,0,_/binary>>) -> {7,F}; % 1 bsl 30 448: overflow_huge_float_32(<<F:2147483648/float-unit:128,0,_/binary>>) -> {8,F}; % 1 bsl 31 449: overflow_huge_float_32(_) -> nomatch. 450: 451: 452: overflow_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; 465: overflow_huge_float(_, []) -> ok. 466: 467: overflow_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; 480: overflow_huge_float_unit128(_, []) -> ok. 481: 482: 483: %% 484: %% Test that a writable binary can be safely matched. 485: %% 486: 487: writable_binary_matched(Config) when is_list(Config) -> 488: ?line WritableBin = create_writeable_binary(), 489: ?line writable_binary_matched(WritableBin, WritableBin, 500). 490: 491: writable_binary_matched(<<0>>, _, N) -> 492: if 493: N =:= 0 -> ok; 494: true -> 495: put(grow_heap, [N|get(grow_heap)]), 496: ?line WritableBin = create_writeable_binary(), 497: ?line writable_binary_matched(WritableBin, WritableBin, N-1) 498: end; 499: writable_binary_matched(<<B:8,T/binary>>, WritableBin0, N) -> 500: ?line WritableBin = writable_binary(WritableBin0, B), 501: writable_binary_matched(T, WritableBin, N). 502: 503: writable_binary(WritableBin0, B) when is_binary(WritableBin0) -> 504: %% Heavy append to force the binary to move. 505: ?line WritableBin = <<WritableBin0/binary,0:(size(WritableBin0))/unit:8,B>>, 506: ?line id(<<(id(0)):128/unit:8>>), 507: WritableBin. 508: 509: create_writeable_binary() -> 510: <<(id(<<>>))/binary,1,2,3,4,5,6,0>>. 511: 512: otp_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: ?line [do_otp_7198(FillerSize) || FillerSize <- lists:seq(0, 256)], 518: ok. 519: 520: do_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: ?line ?t:fail() 529: end. 530: 531: do_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: 549: otp_7198_scan(<<>>, TokAcc) -> 550: lists:reverse(['$thats_all_folks$' | TokAcc]); 551: 552: otp_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: 557: otp_7198_scan(<<D>>, TokAcc) when 558: (D =:= $D) or (D =:= $d) -> 559: otp_7198_scan(<<>>, ['AND' | TokAcc]); 560: 561: otp_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: 566: otp_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: 577: unordered_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: 582: unordered_bindings(CompressedLength, HashSize, PadLength, T) -> 583: <<Content:CompressedLength/binary,Mac:HashSize/binary, 584: Padding:PadLength/binary,PadLength>> = T, 585: {Content,Mac,Padding}. 586: 587: 588: id(I) -> I.