Split out field handling from pa_bitmatch into a common library, in preparation for...
[ocaml-bitstring.git] / bitmatch_persistent.mli
1 (** Bitmatch persistent patterns. *)
2 (* Copyright (C) 2008 Red Hat Inc., Richard W.M. Jones
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  * $Id$
19  *)
20
21 (**
22    {{:#reference}Jump straight to the reference section for
23    documentation on types and functions}.
24
25    {2 Introduction}
26
27    Bitmatch allows you to name sets of fields and reuse them
28    elsewhere.  For example if you frequently need to parse
29    Pascal-style strings in the form [length byte + string], then you
30    could name the [{ strlen : 8 : int; str : strlen*8 : string}]
31    pattern and reuse it everywhere by name.
32
33    These are called {b persistent patterns}.
34
35    The basic usage is:
36
37 {v
38 (* Create a persistent pattern called 'pascal' which
39  * matches Pascal-style strings (length byte + string).
40  *)
41 bitmatch pascal =
42   { strlen : 8 : int;
43     str : strlen*8 : string }
44
45 let is_pascal_string bits =
46   bitmatch bits with
47   | { pascal } ->
48     printf "matches a Pascal string %s, len %d bytes\n"
49       str strlen
50 v}
51
52    {3 Important notes}
53
54    There are some important things you should know about
55    persistent patterns before you decide to use them:
56
57    'Persistent' refers to the fact that they can be saved into binary
58    files.  However these binary files use OCaml [Marshal] module and
59    depend (sometimes) on the version of OCaml used to generate them
60    and (sometimes) the version of bitmatch used.  So your build system
61    should rebuild these files from source when your code is rebuilt.
62
63    Persistent patterns are syntactic.  They work in the same way
64    as cutting and pasting (or [#include]-ing) code.  For example
65    if a persistent pattern binds a field named [len], then any
66    uses of [len] following in the surrounding pattern could
67    be affected.
68
69    Programs which generate and manipulate persistent patterns have to
70    link to camlp4.  Since camlp4 in OCaml >= 3.10 is rather large, we
71    have placed this code into this separate submodule, so that
72    programs which just use bitmatch don't need to pull in the whole of
73    camlp4.  This restriction does not apply to generated code which
74    only uses persistent patterns.  If the distinction isn't clear,
75    use [ocamlobjinfo] to look at the dependencies of your [*.cmo]
76    files.
77
78    Persistent patterns can be generated in several ways, but they
79    can only be {i used} by the [pa_bitmatch] syntax extension.
80    This means they are purely compile-time constructs.  You
81    cannot use them to make arbitrary patterns and run those
82    patterns (not unless your program runs [ocamlc] to make a [*.cmo]
83    file then dynamically links to the [*.cmo] file).
84
85
86
87
88
89
90
91
92
93
94    {2:reference Reference}
95
96    {3 Internal}
97 *)
98
99 type patt = Camlp4.PreCast.Syntax.Ast.patt
100 type expr = Camlp4.PreCast.Syntax.Ast.expr
101 type loc_t = Camlp4.PreCast.Syntax.Ast.Loc.t
102
103 (** {3 Types} *)
104
105 type 'a field
106 (** A field in a persistent pattern or persistent constructor. *)
107
108 type pattern = patt field list
109 (** A persistent pattern (used in [bitmatch] operator), is just a list
110     of pattern fields. *)
111
112 type constructor = expr field list
113 (** A persistent constructor (used in [BITSTRING] operator), is just a
114     list of constructor fields. *)
115
116 (** {3 Printers} *)
117
118 val string_of_pattern : pattern -> string
119 val string_of_constructor : constructor -> string
120 val string_of_field : 'a field -> string
121 (** Convert patterns, constructors, or individual fields
122     into printable strings for debugging purposes.
123
124     The strings look similar to the syntax used by bitmatch, but
125     some things cannot be printed fully, eg. length expressions. *)
126
127 (** {3 Persistence} *)
128
129 val pattern_to_channel : out_channel -> pattern -> unit
130 val constructor_to_channel : out_channel -> constructor -> unit
131 (** Save a pattern/constructor to an output channel. *)
132
133 val pattern_to_string : pattern -> string
134 val constructor_to_string : constructor -> string
135 (** Serialize a pattern/constructor to a string. *)
136
137 val pattern_to_buffer : string -> int -> int -> pattern -> int
138 val constructor_to_buffer : string -> int -> int -> constructor -> int
139 (** Serialize a pattern/constructor to part of a string, return the length. *)
140
141 val pattern_from_channel : in_channel -> pattern
142 val constructor_from_channel : in_channel -> constructor
143 (** Load a pattern/constructor from an output channel.
144
145     Note: This is not type safe.  The pattern/constructor must
146     have been written out under the same version of OCaml and
147     the same version of bitmatch. *)
148
149 val pattern_from_string : string -> int -> pattern
150 val constructor_from_string : string -> int -> constructor
151 (** Load a pattern/constructor from a string at offset within the string.
152
153     Note: This is not type safe.  The pattern/constructor must
154     have been written out under the same version of OCaml and
155     the same version of bitmatch. *)
156
157 (** {3 Create pattern fields}
158
159     These fields are used in pattern matches ([bitmatch]). *)
160
161 val create_pattern_field : loc_t -> patt field
162 (** Create a pattern field.
163
164     The pattern is unbound, the type is set to [int], bit length to [32],
165     endianness to [BigEndian], signedness to unsigned ([false]),
166     and source code location to the [_loc] parameter.
167
168     To create a complete field you need to call the [set_*]
169     functions.  For example, to create [{ len : 8 : int }]
170     you would do:
171
172 {v
173     let field = create_pattern_field _loc in
174     let field = set_lident_patt field "len" in
175     let field = set_length_int field 8 in
176 v}
177 *)
178
179 val set_lident_patt : patt field -> string -> patt field
180 (** Sets the pattern to the pattern binding an identifier
181     given in the string.
182
183     The effect is that the field [{ len : 8 : int }] could
184     be created by calling [set_lident_patt field "len"]. *)
185
186 val set_int_patt : patt field -> int -> patt field
187 (** Sets the pattern field to the pattern which matches an integer.
188
189     The effect is that the field [{ 2 : 8 : int }] could
190     be created by calling [set_int_patt field 2]. *)
191
192 val set_string_patt : patt field -> string -> patt field
193 (** Sets the pattern field to the pattern which matches a string.
194
195     The effect is that the field [{ "MAGIC" : 8*5 : string }] could
196     be created by calling [set_int_patt field "MAGIC"]. *)
197
198 val set_unbound_patt : patt field -> patt field
199 (** Sets the pattern field to the unbound pattern (usually written [_]).
200
201     The effect is that the field [{ _ : 8 : int }] could
202     be created by calling [set_unbound_patt field]. *)
203
204 val set_patt : patt field -> patt -> patt field
205 (** Sets the pattern field to an arbitrary OCaml pattern match. *)
206
207 val set_length_int : 'a field -> int -> 'a field
208 (** Sets the length in bits of a field to a constant integer.
209
210     The effect is that the field [{ len : 8 : string }] could
211     be created by calling [set_length field 8]. *)
212
213 val set_length : 'a field -> expr -> 'a field
214 (** Sets the length in bits of a field to an OCaml expression.
215
216     The effect is that the field [{ len : 2*i : string }] could
217     be created by calling [set_length field <:expr< 2*i >>]. *)
218
219 val set_endian : 'a field -> Bitmatch.endian -> 'a field
220 (** Sets the endianness of a field to the constant endianness.
221
222     The effect is that the field [{ _ : 16 : bigendian }] could
223     be created by calling [set_endian field Bitmatch.BigEndian]. *)
224
225 val set_endian_expr : 'a field -> expr -> 'a field
226 (** Sets the endianness of a field to an endianness expression.
227
228     The effect is that the field [{ _ : 16 : endian(e) }] could
229     be created by calling [set_endian_expr field e]. *)
230
231 val set_signed : 'a field -> bool -> 'a field
232 (** Sets the signedness of a field to a constant signedness.
233
234     The effect is that the field [{ _ : 16 : signed }] could
235     be created by calling [set_signed field true]. *)
236
237 val set_type_int : 'a field -> 'a field
238 (** Sets the type of a field to [int].
239
240     The effect is that the field [{ _ : 16 : int }] could
241     be created by calling [set_type_int field]. *)
242
243 val set_type_string : 'a field -> 'a field
244 (** Sets the type of a field to [string].
245
246     The effect is that the field [{ str : 16 : string }] could
247     be created by calling [set_type_string field]. *)
248
249 val set_type_bitstring : 'a field -> 'a field
250 (** Sets the type of a field to [bitstring].
251
252     The effect is that the field [{ _ : 768 : bitstring }] could
253     be created by calling [set_type_bitstring field]. *)
254
255 val set_location : 'a field -> loc_t -> 'a field
256 (** Sets the source code location of a field.  This is used when
257     pa_bitmatch displays error messages. *)
258
259 (** {3 Create constructor fields}
260
261     These fields are used in constructors ([BITSTRING]). *)
262
263 val create_constructor_field : loc_t -> expr field
264 (** Create a constructor field.
265
266     The defaults are the same as for {!create_pattern_field}
267     except that the expression is initialized to [0].
268 *)
269
270 val set_lident_expr : expr field -> string -> expr field
271 (** Sets the expression in a constructor field to an expression
272     which uses the identifier.
273
274     The effect is that the field [{ len : 8 : int }] could
275     be created by calling [set_lident_expr field "len"]. *)
276
277 val set_int_expr : expr field -> int -> expr field
278 (** Sets the expression to the value of the integer.
279
280     The effect is that the field [{ 2 : 8 : int }] could
281     be created by calling [set_int_expr field 2]. *)
282
283 val set_string_expr : expr field -> string -> expr field
284 (** Sets the expression to the value of the string.
285
286     The effect is that the field [{ "MAGIC" : 8*5 : string }] could
287     be created by calling [set_int_expr field "MAGIC"]. *)
288
289 val set_expr : expr field -> expr -> expr field
290 (** Sets the expression field to an arbitrary OCaml expression. *)
291
292 (** {3 Accessors} *)
293
294 val get_patt : patt field -> patt
295 (** Get the pattern from a pattern field. *)
296
297 val get_expr : expr field -> expr
298 (** Get the expression from an expression field. *)
299
300 val get_length : 'a field -> expr
301 (** Get the length in bits from a field.  Note that what is returned
302     is an OCaml expression, since lengths can be non-constant. *)
303
304 type endian_expr =
305   | ConstantEndian of Bitmatch.endian
306   | EndianExpr of expr
307
308 val get_endian : 'a field -> endian_expr
309 (** Get the endianness of a field.  This is an {!endian_expr} which
310     could be a constant or an OCaml expression. *)
311
312 val get_signed : 'a field -> bool
313 (** Get the signedness of a field. *)
314
315 type field_type = Int | String | Bitstring
316
317 val get_type : 'a field -> field_type
318 (** Get the type of a field, [Int], [String] or [Bitstring]. *)
319
320 val get_location : 'a field -> loc_t
321 (** Get the source code location of a field. *)