= 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"]

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

    * B

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

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

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

    * h

      16ʸ(̥˥֥뤬)

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

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

    * H

      16ʸ(̥˥֥뤬)

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

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

    * c

      char

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

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

    * C

      unsigned char

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

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

    * s

      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

      ȥ륨ǥ:

        "\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
    * I

      unsigned int
    * l

      long
    * L

      unsigned long
    * q

      ruby 1.7 feature:
      long long (64 bit դ)
    * Q

      ruby 1.7 feature:
      unsigned long long (64 bit ʤ)
    * m

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

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

    * M

      quoted-printable encoding 줿ʸ
    * n

      ͥåȥХȥ(ӥåǥ)unsigned short
    * N

      ͥåȥХȥ(ӥåǥ)unsigned long
    * v

      "VAX"Хȥ(ȥ륨ǥ)unsigned short
    * V

      "VAX"Хȥ(ȥ륨ǥ)unsigned long
    * f

      ñư(¸)
    * d

      ư(¸)
    * e

      ȥ륨ǥñư(¸)
    * E

      ȥ륨ǥư(¸)
    * g

      ӥåǥñư(¸)
    * G

      ӥåǥư(¸)
    * p

      ʥ뽪üʸؤΥݥ
    * P

      ¤(Ĺʸ)ؤΥݥ
    * u

      uuencode줿ʸ
    * U

      utf-8
    * 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"

      ޤ