Several functions are provided for dealing with an arbitrary-width field of contiguous bits appearing anywhere in an integer. Such a contiguous set of bits is called a byte. Here the term byte does not imply some fixed number of bits (such as eight), rather a field of arbitrary and user-specifiable width.
The byte-manipulation functions use objects called byte specifiers to designate a specific byte position within an integer. The representation of a byte specifier is implementation-dependent; in particular, it may or may not be a number. It is sufficient to know that the function byte will construct one, and that the byte-manipulation functions will accept them. The function byte accepts two integers representing the position and size of the byte and returns a byte specifier. Such a specifier designates a byte whose width is size and whose bits have weights 2position+size−1 through 2position.
byte takes two integers representing the size and position of a byte and returns a byte specifier suitable for use as an argument to byte-manipulation functions.
Given a byte specifier, byte-size returns the size specified as an integer; byte-position similarly returns the position. For example:
bytespec
specifies a byte of integer to be extracted. The result is returned as a non-negative integer. For example:The name of the function ldb means “load byte.”
If the argument integer is specified by a form that is a place form acceptable to setf, then setf may be used with ldb to modify a byte within the integer that is stored in that place. The effect is to perform a dpb operation and then store the result back into the place.
ldb-test is a predicate that is true if any of the bits designated by the byte specifier bytespec are 1’s in integer; that is, it is true if the designated field is non-zero.
This is similar to ldb; however, the result contains the specified byte of integer in the position specified by bytespec, rather than in position 0 as with ldb. The result therefore agrees with integer in the byte specified but has zero-bits everywhere else. For example:
If the argument integer is specified by a form that is a place form acceptable to setf, then setf may be used with mask-field to modify a byte within the integer that is stored in that place. The effect is to perform a deposit-field operation and then store the result back into the place.
This returns a number that is the same as integer except in the bits specified by bytespec. Let s be the size specified by bytespec; then the low s bits of newbyte appear in the result in the byte specified by bytespec. The integer newbyte is therefore interpreted as being right-justified, as if it were the result of ldb. For example:
The name of the function dpb means “deposit byte.”
This function is to mask-field as dpb is to ldb. The result is an integer that contains the bits of newbyte within the byte specified by bytespec, and elsewhere contains the bits of integer. For example:
Implementation note: If the bytespec is a constant, one may of course construct, at compile time, an equivalent mask m, for example by computing (deposit-field -1 bytespec 0). Given this mask m, one may then compute
by computing
where the result of (lognot m) can of course also be computed at compile time. However, the following expression may also be used and may require fewer temporary registers in some situations:
A related, though possibly less useful, trick is that
interchanges those bits of x and y for which the mask m is 1, and leaves alone those bits of x and y for which m is 0.