erlang bit syntax에 대하여
erlang에서는 <<
와 >>
로 감싸서 바이너리 데이터를 다루는데, <<"Hello World!">>
처럼 쓰면 C 언어에서의 char *
문자열과 같은 자료구조로 쓸 수 있고, 비트 단위로 쪼갤 수 있기 때문에 <<H, Rest/binary>>
처럼 bit syntax를 써서 바이너리 데이터를 쉽게 파싱할 수도 있다. 앞의 'Hello World!'
문자열에 적용하면 첫 한 바이트를 얻을 수 있을 것이다.
1> <<H, Rest/binary>> = <<"Hello World!">>.
<<"Hello World!">>
2> H.
72
3> Rest.
<<"ello World!">>
만약 어떤 방법으로 IP 패킷을 받았다면 (예를 들면 Packet
변수에), 다음과 같이 한 번 실행에 손쉽게 IP 헤더를 분석할 수 있다.
<<IpVer:4, HLen:4, SvcType:8, TotLen:16,
Id:16, Flags:3, FragOff:13, TTL:8, Proto:8, HdrChkSum:16,
SrcIP:32, DstIP:32, IpPayload/binary>> = Packet.
bit syntax를 보면 변수 명 뒤에 :
다음에는 얻어낼 바이너리 데이터의 비트 단위의 크기를 표시한다. 그래서 IpVer
변수에는 IP 헤더의 첫 4비트 필드의 값이 들어간다. 정상적인 IPv4 헤더라면 '4' 값이 들어갈 것이다.
변수 명 뒤의 /
다음에는 해당 변수에 넣는 바이너리 데이터의 type을 나타낸다. erlang reference manual을 참고하면 여기에는 다음 중 하나의 값을 사용할 수 있다. 생략할 경우 integer
가 기본값이 된다.
Type = integer | float | binary | bytes | bitstring | bits |
utf8 | utf16 | utf32
이외에도 signed/unsigned이나 endian 등을 더 명시할 수 있지만 다음에 다루기로 한다.
Type 중 binary, bytes, bitstring, bits에 대해 좀더 구분해보자면, 먼저 bytes는 binary와 같고, bits와 bitstring은 같은 것이다. 보다 짧게 표기하기 위한 것이다. binary와 bitstring은 데이터를 byte (즉 8 bit) 단위로 구분하느냐 bit 단위로 구분하느냐 차이이다. 아래 예의 경우 X
에는 1이, Y
에는 <<2,3,4>>
가 매치된다.
1> <<X, Y/binary>> = <<1, 2, 3, 4>>.
<<1,2,3,4>>
그러나 아래처럼 X
에 바이너리 데이터의 첫 7 bit를 매치시켜놓으면 나머지는 byte 단위로 딱 떨어지지 않고 25 bit가 되기 때문에 예외 에러가 발생한다.
1> <<X:7, Y/binary>> = <<1, 2, 3, 4>>.
** exception error: no match of right hand side value <<1,2,3,4>>
이 경우에는 X에 매치되는 데이터의 길이를 byte로 바로 잡든가, 아니면 아래와 같이 Y에 25 bit 데이터를 매치시키도록 type을 바꿔야 한다.
1> <<X:7, Y/bitstring>> = <<1, 2, 3, 4>>.
<<1,2,3,4>>
2> X.
0
3> Y.
<<129,1,130,0:1>>
X
는 첫 7 bit만 읽었기 때문에 0이 매치됐고, Y
의 경우 <<2, 3, 4>>
가 1 bit 씩 오른쪽으로 쉬프트되는 꼴이 되어서 이진수로는 10000001, 00000001, 10000010, 0
가 되어 위에서 표기된 것처럼 <<129, 1, 130, 0:1>>
이 매치되었다.