= packƥץ졼ʸ

ʲˤΤϡArray#pack [Array]String#unpack [String]
Υƥץ졼ʸΰǤƥץ졼ʸϸˡĹפɽ
³뤳ȤǤޤĹפ`*'Ȥ뤳ȤǡֻĤơ
ɽȤǤޤ

Ĺΰ̣ϥƥץ졼ʸˤۤʤޤ
  "iiii"
Τ褦Ϣ³ƥץ졼ʸ
  "i4"
Ƚ񤭴뤳ȤǤޤ

 short  long ϥƥˤ餺줾 2, 4Хȥ
ο(32ӥåȥޥǰŪshort, longΥ)̣Ƥ
`s', `S', `l', `L' ФƤľ `_'ޤ`!'("s!"Τ褦)
³뤳Ȥǥƥ¸short, long Υˤ뤳ȤǤޤ
`i', `I' (int)ΥϾ˥ƥ¸Ǥꡢ`n', `N', `v', `V'
ΥϾ˥ƥ¸ǤϤʤ(`!'Ĥʤ)ȤդƤ

ƥץ졼ʸζ̵뤵ޤ
ruby 1.7 feature:
ޤ`#' Ԥ뤤ϥƥץ졼ʸκǸޤǤϥȤȤߤ
̵뤵ޤ

桢Array#packString#unpackǰ㤤ΤΤ/Ƕڤä
Array#pack/String#unpackפȤƤޤ

    * a

      ASCIIʸ(nullʸͤ/³nullʸ䥹ڡĤ)

        ["abc"].pack("a") => "a"
        ["abc"].pack("a*") => "abc"
        ["abc"].pack("a4") => "abc\0"

        "abc\0".unpack("a4") => ["abc\0"]
        "abc ".unpack("a4") => ["abc "]

    * A

      ASCIIʸ(ڡͤ/³nullʸ䥹ڡ)

        ["abc"].pack("A") => "a"
        ["abc"].pack("A*") => "abc"
        ["abc"].pack("A4") => "abc "

        "abc ".unpack("A4") => ["abc"]
        "abc\0".unpack("A4") => ["abc"]

    * Z

      nullüʸ(aƱ / ³nullʸ)

        ["abc"].pack("Z") => "a"
        ["abc"].pack("Z*") => "abc"
        ["abc"].pack("Z4") => "abc\0"

        "abc\0".unpack("Z4") => ["abc"]
        "abc ".unpack("Z4") => ["abc "]

    * b

      ӥåȥȥ(̥ӥåȤ̥ӥå)

        "\001\002".unpack("b*") => ["1000000001000000"]
        "\001\002".unpack("b3") => ["100"]


        ["1000000001000000"].pack("b*") => "\001\002"

    * B

      ӥåȥȥ(̥ӥåȤ鲼̥ӥå)

        "\001\002".unpack("B*") => ["0000000100000010"]
        "\001\002".unpack("B9") => ["000000010"]

        ["0000000100000010"].pack("B*") => "\001\002"

    * h

      16ʸ(̥˥֥뤬)

        "\x01\xfe".unpack("h*") => ["10ef"]
        "\x01\xfe".unpack("h3") => ["10e"]

        ["10ef"].pack("h*") => "\001\376"

    * H

      16ʸ(̥˥֥뤬)

        "\x01\xfe".unpack("H*") => ["01fe"]
        "\x01\xfe".unpack("H3") => ["01f"]

        ["01fe"].pack("H*") => "\001\376"

    * c

      char (8bit Ĥ)

        "\001\376".unpack("c*") => [1, -2]

        [1, -2].pack("c*") => "\001\376"
        [1, 254].pack("c*") => "\001\376"

    * C

      unsigned char (8bit ʤ)

        "\001\376".unpack("C*") => [1, 254]

        [1, -2].pack("C*") => "\001\376"
        [1, 254].pack("C*") => "\001\376"

    * s

      short (16bit Ĥ, ǥ˰¸)
      (s!  16bit Ǥʤshort Υ˰¸)

      ȥ륨ǥ:

        "\001\002\376\375".unpack("s*") => [513, -514]

        [513, 65022].pack("s*") => "\001\002\376\375"
        [513, -514].pack("s*") => "\001\002\376\375"

      ӥåǥ:

        "\001\002\376\375".unpack("s*") => [258, -259]

        [258, 65277].pack("s*") => "\001\002\376\375"
        [258, -259].pack("s*") => "\001\002\376\375"

    * S

      unsigned short (16bit ʤ, ǥ˰¸)
      (S!  16bit Ǥʤshort Υ˰¸)

      ȥ륨ǥ:

        "\001\002\376\375".unpack("S*") => [513, 65022]

        [513, 65022].pack("s*") => "\001\002\376\375"
        [513, -514].pack("s*") => "\001\002\376\375"

      ӥåǥ:

        "\001\002\376\375".unpack("S*") => [258, 65277]

        [258, 65277].pack("S*") => "\001\002\376\375"
        [258, -259].pack("S*") => "\001\002\376\375"

    * i

      int (Ĥ, ǥ int Υ˰¸)

      ȥ륨ǥ, 32bit int:

        "\001\002\003\004\377\376\375\374".unpack("i*") => [67305985, -50462977]

        [67305985, 4244504319].pack("i*") => "\001\002\003\004\377\376\375\374"
        [67305985, -50462977].pack("i*") => "\001\002\003\004\377\376\375\374"

      ӥåǥ, 32bit int:

        "\001\002\003\004\377\376\375\374".unpack("i*") => [16909060, -66052]

        [16909060, 4294901244].pack("i*") => "\001\002\003\004\377\376\375\374"
        [16909060, -66052].pack("i*") => "\001\002\003\004\377\376\375\374"

    * I

      unsigned int (ʤ, ǥ int Υ˰¸)

      ȥ륨ǥ, 32bit int:

        "\001\002\003\004\377\376\375\374".unpack("I*") => [67305985, 4244504319]

        [67305985, 4244504319].pack("I*") => "\001\002\003\004\377\376\375\374"
        [67305985, -50462977].pack("I*") => "\001\002\003\004\377\376\375\374"

      ӥåǥ, 32bit int:

        "\001\002\003\004\377\376\375\374".unpack("I*") => [16909060, 4294901244]

        [16909060, 4294901244].pack("I*") => "\001\002\003\004\377\376\375\374"
        [16909060, -66052].pack("I*") => "\001\002\003\004\377\376\375\374"

    * l

      long (32bit Ĥ, ǥ˰¸)
      (l!  32bit Ǥʤlong Υ˰¸)

      ȥ륨ǥ, 32bit long:

        "\001\002\003\004\377\376\375\374".unpack("l*") => [67305985, -50462977]

    * L

      unsigned long (32bit ʤ, ǥ˰¸)
      (L!  32bit Ǥʤlong Υ˰¸)

      ȥ륨ǥ, 32bit long:

        "\001\002\003\004\377\376\375\374".unpack("L*") => [67305985, 4244504319]

    * q

      ruby 1.7 feature:
      long long (դ, ǥ long long Υ˰¸)
      (C  long long ʤˤ 64bit)

      ȥ륨ǥ, 64bit long long:

        "\001\002\003\004\005\006\007\010\377\376\375\374\373\372\371\370".unpack("q*")
        => [578437695752307201, -506097522914230529]

    * Q

      ruby 1.7 feature:
      unsigned long long (ʤ, ǥ long long Υ˰¸)
      (C  long long ʤˤ 64bit)

      ȥ륨ǥ, 64bit long long:

        "\001\002\003\004\005\006\007\010\377\376\375\374\373\372\371\370".unpack("Q*")
        => [578437695752307201, 17940646550795321087]

    * m

      base64줿ʸ60 ƥåȤ(ȺǸ)˲ԥɤղäޤ

      Base64ϡ3ƥå(8bits * 3 = 24bits)ΥХʥꥳɤASCIIʸ
      65ʸ ([A-Za-z0-9+/]64ʸpaddingΤ'=')Ѥ
      4ƥå(6bits * 4 = 24bits)ΰǽʸѴ륨󥳡ǥ
      ˡǤRFC2045Ƥޤ

        [""].pack("m") => ""
        ["\0"].pack("m") => "AA==\n"
        ["\0\0"].pack("m") => "AAA=\n"
        ["\0\0\0"].pack("m") => "AAAA\n"
        ["\377"].pack("m") => "/w==\n"
        ["\377\377"].pack("m") => "//8=\n"
        ["\377\377\377"].pack("m") => "////\n"

        ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"].pack("m")
        => "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJT\nVFVWV1hZWg==\n"
        ["abcdefghijklmnopqrstuvwxyz"].pack("m3")
        => "YWJj\nZGVm\nZ2hp\namts\nbW5v\ncHFy\nc3R1\ndnd4\neXo=\n"

        "".unpack("m") => [""]
        "AA==\n".unpack("m") => ["\000"]
        "AA==".unpack("m") => ["\000"]

        "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJT\nVFVWV1hZWg==\n".unpack("m")
        => ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]
        "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWg==\n".unpack("m")
        => ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]

    * M

      quoted-printable encoding 줿ʸ

        ["a b c\td \ne"].pack("M") => "a b c\td =\n\ne=\n"

        "a b c\td =\n\ne=\n".unpack("M") => ["a b c\td \ne"]

    * n

      ͥåȥХȥ(ӥåǥ)unsigned short (16bit ʤ)

        [0,1,-1,32767,-32768,65535].pack("n*")
        => "\000\000\000\001\377\377\177\377\200\000\377\377"

        "\000\000\000\001\377\377\177\377\200\000\377\377".unpack("n*")
        => [0, 1, 65535, 32767, 32768, 65535]

    * N

      ͥåȥХȥ(ӥåǥ)unsigned long (32bit ʤ)

        [0,1,-1].pack("N*") => "\000\000\000\000\000\000\000\001\377\377\377\377"

        "\000\000\000\000\000\000\000\001\377\377\377\377".unpack("N*") => [0, 1, 4294967295]

    * v

      "VAX"Хȥ(ȥ륨ǥ)unsigned short (16bit ʤ)

        [0,1,-1,32767,-32768,65535].pack("v*")
        => "\000\000\001\000\377\377\377\177\000\200\377\377"

        "\000\000\001\000\377\377\377\177\000\200\377\377".unpack("v*")
        => [0, 1, 65535, 32767, 32768, 65535]

    * V

      "VAX"Хȥ(ȥ륨ǥ)unsigned long (32bit ʤ)

        [0,1,-1].pack("V*") => "\000\000\000\000\001\000\000\000\377\377\377\377"

        "\000\000\000\000\001\000\000\000\377\377\377\377".unpack("V*") => [0, 1, 4294967295]

    * f

      ñư(¸)

      IA-32 (x86):
        [1.0].pack("f") => "\000\000\200?"

      sparc:
        [1.0].pack("f") => "?\200\000\000"

    * d

      ư(¸)

      IA-32:
        [1.0].pack("d") => "\000\000\000\000\000\000\360?"

      sparc:
        [1.0].pack("d") => "?\360\000\000\000\000\000\000"

    * e

      ȥ륨ǥñư(¸)

      IA-32:
        [1.0].pack("e") => "\000\000\200?"

      sparc:
        [1.0].pack("e") => "\000\000\200?"

    * E

      ȥ륨ǥư(¸)

      IA-32:
        [1.0].pack("E") => "\000\000\000\000\000\000\360?"

      sparc:
        [1.0].pack("E") => "\000\000\000\000\000\000\360?"

    * g

      ӥåǥñư(¸)

      IA-32:
        [1.0].pack("g") => "?\200\000\000"

      sparc:
        [1.0].pack("g") => "?\200\000\000"

    * G

      ӥåǥư(¸)

      IA-32:
        [1.0].pack("G") => "?\360\000\000\000\000\000\000"

      sparc:
        [1.0].pack("G") => "?\360\000\000\000\000\000\000"

    * p

      ʥ뽪üʸؤΥݥ

        [""].pack("p") => "\310\037\034\010"
        ["a", "b", "c"].pack("p3") => " =\030\010\340^\030\010\360^\030\010"
        [nil].pack("p") => "\000\000\000\000"

    * P

      ¤(Ĺʸ)ؤΥݥ

        [nil].pack("P") => "\000\000\000\000"
        ["abc"].pack("P3") => "x*\024\010"

        ["abc"].pack("P4") => ArgumentError: too short buffer for P(3 for 4)
        [""].pack("P") => ArgumentError: too short buffer for P(0 for 1)

    * u

      uuencode줿ʸ

        [""].pack("u") => ""
        ["a"].pack("u") => "!80``\n"
        ["abc"].pack("u") => "#86)C\n"
        ["abcd"].pack("u") => "$86)C9```\n"
        ["a"*45].pack("u") => "M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A\n"
        ["a"*46].pack("u") => "M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A\n!80``\n"
        ["abcdefghi"].pack("u6") => "&86)C9&5F\n#9VAI\n"
        
    * U

      utf-8

        [0].pack("U") => "\000"
        [1].pack("U") => "\001"
        [0x7f].pack("U") => "\177"
        [0x80].pack("U") => "\302\200"
        [0x7fffffff].pack("U") => "\375\277\277\277\277\277"
        [0x80000000].pack("U") => ArgumentError
        [0,256,65536].pack("U3") => "\000\304\200\360\220\200\200"

        "\000\304\200\360\220\200\200".unpack("U3") => [0, 256, 65536]

    * w

      BER

      1ХȤ7ӥåȤѤɬ׺Ǿ¤ΥХȿǤե
      0ʾɽɽƥХȤκǾ̥ӥåȤϥǡκǸ
      ɬ1ΩäƤ(ĤޤǾ̥ӥåȤϤɤޤǥǡ
      뤫򼨤Ƥ)

      BER  Basic Encoding Rules ά(BER Υ󥳡ǥ󥰤
      ɽ櫓ǤϤʤASN.1 Υ󥳡ǥ󥰤ǻѤ)

      

    * x

      ʥХ/1ХɤФ
    * X

      1Хȸ
    * @

      а֤ؤΰư

== 

ʲpack/unpack λΰǤ

pack ѤʤƤƱȤǤϤܤƤޤ
pack ϰŹˤʤ䤹̤뤳Ȥθpack Ȥʤ
̲򼨤Ǥ

    * (ʸ)ʸѴ

        p [82, 117, 98, 121].pack("cccc")
        => "Ruby"

        p [82, 117, 98, 121].pack("c4")
        => "Ruby"

        p [82, 117, 98, 121].pack("c*")
        => "Ruby"

        s = ""
        [82, 117, 98, 121].each {|c| s << c}
        p s
        => "Ruby"

        p [82, 117, 98, 121].collect {|c| sprintf "%c", c}.join
        => "Ruby"

        p [82, 117, 98, 121].inject("") {|s, c| s << c}
        => "Ruby"

    * ʸ(ʸ)Ѵ
        p "Ruby".unpack('C*')
        => [82, 117, 98, 121]

        a = []
        "Ruby".each_byte {|c| a << c}
        p a
        => [82, 117, 98, 121]

    * "x" ǥʥХȤ뤳ȤǤ
        p [82, 117, 98, 121].pack("ccxxcc")
        => "Ru\000\000by"

    * "x" ʸɤФ
        p "Ru\0\0by".unpack('ccxxcc')
        => [82, 117, 98, 121]

    * HexפͤѴ
        p "61 62 63 64 65 66".delete(' ').to_a.pack('H*').unpack('C*')
        => [97, 98, 99, 100, 101, 102]

        p "61 62 63 64 65 66".split.collect {|c| c.hex}
        => [97, 98, 99, 100, 101, 102]

    * Хʥ16ʿpackǤĹХȿǤϤʤ
      ӥåȤ˥֥θĿɽ

        p [0b01010010, 0b01110101, 0b01100010, 0b01111001].pack("C4")
        => "Ruby"
        p ["01010010011101010110001001111001"].pack("B32") # 8 bits * 4
        => "Ruby"

        p [0x52, 0x75, 0x62, 0x79].pack("C4")
        => "Ruby"
        p ["52756279"].pack("H8")  # 2 nybbles * 4
        => "Ruby"

    * ƥץ졼ʸ'a'Ĺ1ĤʸŬѤ
        p  ["RUBY", "u", "b", "y"].pack("a4")
        => "RUBY"

        p ["RUBY", "u", "b", "y"].pack("aaaa")
        => "Ruby"

        p ["RUBY", "u", "b", "y"].pack("a*aaa")
        => "RUBYuby"

    * ƥץ졼ʸ"a"ϡĹ­ʤʬ̥ʸ䤦
        p ["Ruby"].pack("a8")
        => "Ruby\000\000\000\000"

    * ȥ륨ǥȥӥåǥ

        p [1,2].pack("s2")
        => "\000\001\000\002" # ӥåǥΥƥǤν
        => "\001\000\002\000" # ȥ륨ǥΥƥǤν

        p [1,2].pack("n2")
        => "\000\001\000\002" # ƥˤ餺ӥåǥ

        p [1,2].pack("v2")
        => "\001\000\002\000" # ƥˤ餺ȥ륨ǥ

    * ͥåȥХȥ signed long
          s = "\xff\xff\xff\xfe"
          n = s.unpack("N")[0]
          if n[31] == 1
            n = -((n ^ 0xffff_ffff) + 1)
          end
          p n
          => -2

    * ͥåȥХȥ signed long(2)

          s = "\xff\xff\xff\xfe"
          p n = s.unpack("N").pack("l").unpack("l")[0]
          => -2

    * IPɥ쥹
          require 'socket'
          p Socket.gethostbyname("localhost")[3].unpack("C4").join(".")
          => "127.0.0.1"

          p "127.0.0.1".split(".").collect {|c| c.to_i}.pack("C4")
          => "\177\000\000\001"

    * sockaddr_in ¤
          require 'socket'
          p [Socket::AF_INET,
             Socket.getservbyname('echo'),
             127, 0, 0, 1].pack("s n C4 x8")
          => "\002\000\000\a\177\000\000\001\000\000\000\000\000\000\000\000"

      ruby 1.7 feature: pack/unpack Ȥ
      Socket.pack_sockaddr_in [Socket],
      Socket.unpack_sockaddr_in [Socket] ᥽åɤޤ

    * '\0'üʸΥɥ쥹

      ƥץ졼ʸ "p"  "P" ϡC ٥Υ󥿥եΤ
      ˤޤ(㤨 ioctl)

        p ["foo"].pack("p")
        => "8\266\021\010"

      ̤ʸϥߤ˸ޤºݤʸ"foo\0"ؤɥ
      (ΥХʥɽ)ǤʲΤ褦ˤи줿ɽǸ뤳
      ޤ

        printf "%#010x\n", "8\266\021\010".unpack("L")[0]
        => 0x0811b638

      ɥ쥹ؤΥ֥( "foo\0") ϡpack η
      ̤ GC ޤǤGCʤȤݾڤƤޤ

      unpack("p"), unpack("P") ϡpack η̤餷 unpack Ǥޤ

        p ["foo"].pack("p").unpack("p")
        => ["foo"]
        p "8\266\021\010".unpack("p")
        => -:1:in `unpack': no associated pointer (ArgumentError)
                from -:1

      ruby 1.7 feature: "p"  "P" ϡnil ̤˰ NULL
      ݥ󥿤ȤƲᤷޤ(ʲϡ32bitޥǰŪʷ)

          p [nil].pack("p")        #=> "\000\000\000\000"
          p "\0\0\0\0".unpack("p") #=> [nil]

    * ¤ΤΥɥ쥹

      㤨С
          struct {
            int   a;
            short b;
            long  c;
          } v = {1,2,3};
      ɽʸ

          v = [1,2,3].pack("i!s!l!")

      Ǥ(byte alignment ꤫ºݤŬ padding ɬפ
      ʤ뤫⤷ޤ)

      ι¤Τؤɥ쥹

          p [v].pack("P")
          => "\300\265\021\010"

      ޤ