diff options
| author | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
| commit | 754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch) | |
| tree | f1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/elisp/bindat-types.html | |
new repository
Diffstat (limited to 'devdocs/elisp/bindat-types.html')
| -rw-r--r-- | devdocs/elisp/bindat-types.html | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/devdocs/elisp/bindat-types.html b/devdocs/elisp/bindat-types.html new file mode 100644 index 00000000..3e3ce8f8 --- /dev/null +++ b/devdocs/elisp/bindat-types.html @@ -0,0 +1,25 @@ + <h4 class="subsection">Describing Data Layout</h4> <p>To control unpacking and packing, you write a <em>data layout specification</em>, also called a <em>Bindat type expression</em>. This can be a <em>base type</em> or a <em>composite type</em> made of several fields, where the specification controls the length of each field to be processed, and how to pack or unpack it. We normally keep bindat type values in variables whose names end in <code>-bindat-spec</code>; that kind of name is automatically recognized as risky (see <a href="file-local-variables">File Local Variables</a>). </p> <dl> <dt id="bindat-type">Macro: <strong>bindat-type</strong> <em>&rest type</em> +</dt> <dd><p>Creates a Bindat type <em>value</em> object according to the Bindat type <em>expression</em> <var>type</var>. </p></dd> +</dl> <p>A field’s <em>type</em> describes the size (in bytes) of the object that the field represents and, in the case of multibyte fields, how the bytes are ordered within the field. The two possible orderings are <em>big endian</em> (also known as “network byte ordering”) and <em>little endian</em>. For instance, the number <code>#x23cd</code> (decimal 9165) in big endian would be the two bytes <code>#x23</code> <code>#xcd</code>; and in little endian, <code>#xcd</code> <code>#x23</code>. Here are the possible type values: </p> <dl compact> <dt><code>u8</code></dt> <dt><code>byte</code></dt> <dd> +<p>Unsigned byte, with length 1. </p> </dd> <dt><code>uint <var>bitlen</var></code></dt> <dd> +<p>Unsigned integer in network byte order, with <var>bitlen</var> bits. <var>bitlen</var> has to be a multiple of 8. </p> </dd> <dt><code>uintr <var>bitlen</var></code></dt> <dd> +<p>Unsigned integer in little endian order, with <var>bitlen</var> bits. <var>bitlen</var> has to be a multiple of 8. </p> </dd> <dt><code>str <var>len</var></code></dt> <dd> +<p>String of bytes of length <var>len</var>. </p> </dd> <dt><code>strz &optional <var>len</var></code></dt> <dd> +<p>Zero-terminated string of bytes, can be of arbitrary length or in a fixed-size field with length <var>len</var>. </p> </dd> <dt><code>vec <var>len</var> [<var>type</var>]</code></dt> <dd> +<p>Vector of <var>len</var> elements. The type of the elements is given by <var>type</var>, defaulting to bytes. The <var>type</var> can be any Bindat type expression. </p> </dd> <dt><code>repeat <var>len</var> [<var>type</var>]</code></dt> <dd> +<p>Like <code>vec</code>, but it unpacks to and packs from lists, whereas <code>vec</code> unpacks to vectors. </p> </dd> <dt><code>bits <var>len</var></code></dt> <dd> +<p>List of bits that are set to 1 in <var>len</var> bytes. The bytes are taken in big-endian order, and the bits are numbered starting with <code>8 * <var>len</var> - 1</code> and ending with zero. For example: <code>bits 2</code> unpacks <code>#x28</code> <code>#x1c</code> to <code>(2 3 4 11 13)</code> and <code>#x1c</code> <code>#x28</code> to <code>(3 5 10 11 12)</code>. </p> </dd> <dt><code>fill <var>len</var></code></dt> <dd> +<p><var>len</var> bytes used as a mere filler. In packing, these bytes are are left unchanged, which normally means they remain zero. When unpacking, this just returns nil. </p> </dd> <dt><code>align <var>len</var></code></dt> <dd> +<p>Same as <code>fill</code> except the number of bytes is that needed to skip to the next multiple of <var>len</var> bytes. </p> </dd> <dt><code>type <var>exp</var></code></dt> <dd> +<p>This lets you refer to a type indirectly: <var>exp</var> is a Lisp expression which should return a Bindat type <em>value</em>. </p> </dd> <dt><code>unit <var>exp</var></code></dt> <dd> +<p>This is a trivial type which uses up 0 bits of space. <var>exp</var> describes the value returned when we try to “unpack” such a field. </p> </dd> <dt><code>struct <var>fields</var>...</code></dt> <dd><p>Composite type made of several fields. Every field is of the form <code>(<var>name</var> <var>type</var>)</code> where <var>type</var> can be any Bindat type expression. <var>name</var> can be <code>_</code> when the field’s value does not deserve to be named, as is often the case for <code>align</code> and <code>fill</code> fields. When the context makes it clear that this is a Bindat type expression, the symbol <code>struct</code> can be omitted. </p></dd> </dl> <p>In the types above, <var>len</var> and <var>bitlen</var> are given as an integer specifying the number of bytes (or bits) in the field. When the length of a field is not fixed, it typically depends on the value of preceding fields. For this reason, the length <var>len</var> does not have to be a constant but can be any Lisp expression and it can refer to the value of previous fields via their name. </p> <p>For example, the specification of a data layout where a leading byte gives the size of a subsequent vector of 16 bit integers could be: </p> +<div class="example"> <pre class="example">(bindat-type + (len u8) + (payload vec (1+ len) uint 16)) +</pre> +</div><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-Types.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Bindat-Types.html</a> + </p> +</div> |
