Previous: , Up: Byte Packing   [Contents][Index]


38.20.3 バイトのunpackとpackの例

以下の2つはbindat.elを使用した完全な例です。1つ目は単純なバイトパッキングを示します:

(require 'bindat)

(defun rfc868-payload ()
  (bindat-pack
   '((now-hi u16)
     (now-lo u16))
   ;; EmacsはUnixエポックを使用する
   ;; RFC868エポックは1900-01-01 00:00:00なので
   ;; Unixエポックより2208988800秒(#x83aa7e80秒)大きい
   (let ((now (time-add nil '(#x83aa #x7e80))))
     `((now-hi . ,(car now))
       (now-lo . ,(cadr now))))))

(let ((s (rfc868-payload)))
  (list (multibyte-string-p s)
        (mapconcat (lambda (byte)
                     (format "%02x" byte))
                   s " ")
        (current-time-string)))
     ⇒ (nil "dc 6d 17 01" "Fri Mar 10 13:13:53 2017")

以下は複雑な構造体を定義してunpackする例です。以下のようなCの構造体があるものとします:

struct header {
    unsigned long    dest_ip;
    unsigned long    src_ip;
    unsigned short   dest_port;
    unsigned short   src_port;
};

struct data {
    unsigned char    type;
    unsigned char    opcode;
    unsigned short   length;  /* ネットワークバイトオーダー */
    unsigned char    id[8];   /* NUL終端文字列 */
    unsigned char    data[/* (length + 3) & ~3 */];
};

struct packet {
    struct header    header;
    unsigned long    counters[2];  /* リトルエンディアンオーダー */
    unsigned char    items;
    unsigned char    filler[3];
    struct data      item[/* items */];

};

対応するデータレイアウト仕様が以下です:

(setq header-spec
      '((dest-ip   ip)
        (src-ip    ip)
        (dest-port u16)
        (src-port  u16)))

(setq data-spec
      '((type      u8)
        (opcode    u8)
        (length    u16)  ; ネットワークバイトオーダー
        (id        strz 8)
        (data      vec (length))
        (align     4)))

(setq packet-spec
      '((header    struct header-spec)
        (counters  vec 2 u32r)   ; リトルエンディアンオーダー
        (items     u8)
        (fill      3)
        (item      repeat (items)
                   (struct data-spec))))

バイナリーデータによる表現は:

(setq binary-data
      [ 192 168 1 100 192 168 1 101 01 28 21 32
        160 134 1 0 5 1 0 0 2 0 0 0
        2 3 0 5 ?A ?B ?C ?D ?E ?F 0 0 1 2 3 4 5 0 0 0
        1 4 0 7 ?B ?C ?D ?E ?F ?G 0 0 6 7 8 9 10 11 12 0 ])

対応するデコードされた構造体は:

(setq decoded (bindat-unpack packet-spec binary-data))
     ⇒
((header
  (dest-ip   . [192 168 1 100])
  (src-ip    . [192 168 1 101])
  (dest-port . 284)
  (src-port  . 5408))
 (counters . [100000 261])
 (items . 2)
 (item ((data . [1 2 3 4 5])
        (id . "ABCDEF")
        (length . 5)
        (opcode . 3)
        (type . 2))
       ((data . [6 7 8 9 10 11 12])
        (id . "BCDEFG")
        (length . 7)
        (opcode . 4)
        (type . 1))))

以下はこの構造体からデータを取得する例です:

(bindat-get-field decoded 'item 1 'id)
     ⇒ "BCDEFG"

Previous: , Up: Byte Packing   [Contents][Index]