How the @,x,X directives work with Ruby pack()/unpack() method?

穿精又带淫゛_ 提交于 2019-12-06 00:12:16

I will give you few example and will be learning together with you:

[1,2,3,4].pack("CCCC")
=> "\x01\x02\x03\x04"

So serializes in unsigned chars. Every letter in new byte.

[1,2,3,4].pack("CCXCC")
=> "\x01\x03\x04"
[1,2,3,4].pack("CCXXC")
=> "\x03"

Think of the 'X' as backspace directive

[1,2,3,4].pack("CCxC")
=> "\x01\x02\x00\x03"
[1,2,3,4].pack("CCxxC")
=> "\x01\x02\x00\x00\x03"

'x' places zero valued byte.

[1,2,3,4].pack("CC@C")
=> "\x01\x03"
[1,2,3,4].pack("CC@@C")
=> "\x01\x03"
[1,2,3,4].pack("CC@@CC")
=> "\x01\x03\x04"
[1,2,3,4].pack("CC@CC")
=> "\x01\x03\x04"
[1,2,3,4].pack("CC@C@C")
=> "\x01\x04"
[1,2,3,4].pack("CC@C@@C")
=> "\x01\x04"

'@' seems to be a single backspace, but will not support multiple operations at one time. The last one as explanation does not relate at all with the text from the documentation:

@ Moves to absolute position

But is what it seems to be doing.

EDIT BTW @ seems a lot more logical when looked in the context of unpack:

[1,2,3,4,5].pack("CCCCC").unpack("CCC@CCCCC@CC")
=> [1, 2, 3, 1, 2, 3, 4, 5, 1, 2]

Starts unpacking from the very beginning once more.

EDIT2 And here goes the explanation of the other two directives in the context of unpacking:

[1,2,3,4,5].pack("CCCCC").unpack("CCCXC")
=> [1, 2, 3, 3]
[1,2,3,4,5].pack("CCCCC").unpack("CCCXXC")
=> [1, 2, 3, 2]
[1,2,3,4,5].pack("CCCCC").unpack("CCCxC")
=> [1, 2, 3, 5]

So 'x' ignores the next to decode byte and 'X' will make the previous byte the next to read once more. 'X' can stack.

Here goes my first attempt of summarizing the results:

pack:

  • 'x' places zero byte
  • 'X' works like backspace directive, meaning the previous byte is not going to be packed actually
  • '@' has unexplainable behaviour for me

unpack:

  • 'x' Skips the next byte that was for unpacking
  • 'X' moves the reader backwards, meaning the last read byte will be read once more.
  • '@' moves the reader to the very beginning. That means that all the bytes will be unpacked once more.

NOTE Reader is a word I made up for ease of explanation and is, by no means, formal.

EDIT3 Here goes the explanation of "\x01" notation too:

a = [17, 22, 31]
=> [17, 22, 31]
a.pack("CCC")
=> "\x11\x16\x1F"

It seems like this stands for hexadecimal representation. And all the site I have linked to use decimal representation apparently. Otherwise, as it can be seen those are the hexadecimal representations of the given numbers.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!