blob: 7ffbdc90b5815b443cef039fd63e60b32f2b6f35 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<h4 class="subsection">Advanced data layout specifications</h4> <p>Bindat type expressions are not limited to the types described earlier. They can also be arbitrary Lisp forms returning Bindat type expressions. For example, the type below describes data which can either contain a 24-bit error code or a vector of bytes: </p> <div class="example"> <pre class="example">(bindat-type
(len u8)
(payload . (if (zerop len) (uint 24) (vec (1- len)))))
</pre>
</div> <p>Furthermore, while composite types are normally unpacked to (and packed from) association lists, this can be changed via the use of the following special keyword arguments: </p> <dl compact> <dt><code>:unpack-val <var>exp</var></code></dt> <dd>
<p>When the list of fields ends with this keyword argument, then the value returned when unpacking is the value of <var>exp</var> instead of the standard alist. <var>exp</var> can refer to all the previous fields by their name. </p> </dd> <dt><code>:pack-val <var>exp</var></code></dt> <dd>
<p>If a field’s type is followed by this keyword argument, then the value packed into this field is returned by <var>exp</var> instead of being extracted from the alist. </p> </dd> <dt><code>:pack-var <var>name</var></code></dt> <dd><p>If the list of fields is preceded by this keyword argument, then all the subsequent <code>:pack-val</code> arguments can refer to the overall value to pack into this composite type via the variable named <var>name</var>. </p></dd> </dl> <p>For example, one could describe a 16-bit signed integer as follows: </p> <div class="example"> <pre class="example">(defconst sint16-bindat-spec
(let* ((max (ash 1 15))
(wrap (+ max max)))
(bindat-type :pack-var v
(n uint 16 :pack-val (if (< v 0) (+ v wrap) v))
:unpack-val (if (>= n max) (- n wrap) n))))
</pre>
</div> <p>Which would then behave as follows: </p>
<div class="example"> <pre class="example">(bindat-pack sint16-bindat-spec -8)
⇒ "\377\370"
(bindat-unpack sint16-bindat-spec "\300\100")
⇒ -16320
</pre>
</div> <p>Finally, you can define new Bindat type forms to use in Bindat type expressions with <code>bindat-defmacro</code>: </p> <dl> <dt id="bindat-defmacro">Macro: <strong>bindat-defmacro</strong> <em>name args &rest body</em>
</dt> <dd><p>Define a new Bindat type expression named <var>name</var> and taking arguments <var>args</var>. Its behavior follows that of <code>defmacro</code>, which the important difference that the new forms can only be used within Bindat type expressions. </p></dd>
</dl><div class="_attribution">
<p class="_attribution-p">
Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br>
<a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Bindat-Computed-Types.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Bindat-Computed-Types.html</a>
</p>
</div>
|