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