deposit-field, dpbの使い方をいつも忘れる
ちゃんとメモしておきます。
まずはbytespec
から
1. bytespec
位置とサイズを保有するオブジェクトです。
次のようにして生成します。
(byte size pos)
下記の例は「3番目から7個」という意味。
(byte 7 3)
図であらわします。
098769876543210 --------------- 3... 3番目から 7654321... 7個 ******3 以降こうやって表します
2. deposit-field
(deposit-field left bytespec right)
例を示します。
(deposit-field #b1111000011110000 (byte 7 3) #b1010101010101010) -> #b1010100011110010 ******3 (byte 7 3) #b111100 0011110 000 left #b101010 1010101 010 right -------------------- #b101010 0011110 010
つまりはこんな感じ。
******3 (byte 7 3) #b...... 0011110 ... left #b101010 ....... 010 right -------------------- #b101010 0011110 010
3. dpb
(deposit-byte)
(deposit-field left bytespec right)
例を示します。
(dpb #b1111000011110000 (byte 7 3) #b1010101010101010) -> #b1010101110000010 ******3 (byte 7 3) #b111100001 1110000 left #b101010 1010101 010 right ----------------------- #b101010 1110000 010
つまり
******3 (byte 7 3) #b......... 1110000 left #b101010 ....... 010 right ----------------------- #b101010 1110000 010
deposit-field
は左辺右辺はどちらも同じ位置ですが、
dpb
(deposit-byte)は左辺と右辺で違った場所を取るようです。
4. ldb
(load-byte)
(ldb bytespec integer)
こちらはbytespec
の内容を取り出すだけ。
(ldb (byte 7 3) #b1111000011110000) -> #b11110
つまり
******3 (byte 7 3) #b111100 0011110 000 integer -------------------- #b...... 0011110 ...
5. mask-field
(ldb bytespec integer)
bytespec
の内容を取り出しますが右詰めしません。
(mask-field (byte 7 3) #b1100110011001100) -> #b11001000
つまり
******3 (byte 7 3) #b110011 0011001 100 integer -------------------- #b...... 0011001 000
mask-field
は引数と同じ位置ですが、
ldb
(load-byte)は右詰されます。
6. ldb-test
(ldb-test bytespec integer)
こちらはldb
で抜き出した内容が0ならnil
。
下記の実行と同じです。
(ldb-test bytespec n) == (not (zerop (ldb bytespec n)))
なんで上記のようにしないのかというと、
ldb
でいちいち値を作成してたら時間もメモリも
もったいないということで最適化されています。
logtest
なんかもそうです。
まとめ
★(deposit-field #b1111000011110000 (byte 7 3) #b1010101010101010) ******3 (byte 7 3) #b...... 0011110 ... left #b101010 ....... 010 right -------------------- #b101010 0011110 010
★(dpb #b1111000011110000 (byte 7 3) #b1010101010101010) ******3 (byte 7 3) #b......... 1110000 left #b101010 ....... 010 right ----------------------- #b101010 1110000 010
★(ldb (byte 7 3) #b1111000011110000) ******3 (byte 7 3) #b111100 0011110 000 integer -------------------- #b...... 0011110 ...
★(mask-field (byte 7 3) #b1100110011001100) ******3 (byte 7 3) #b110011 0011001 100 integer -------------------- #b...... 0011001 000