File Index
Files and directories
Sign in
FILE

packing.h

File preview with syntax highlighting.

linux-6.19.14/include/linux/packing.h C
  1/* SPDX-License-Identifier: BSD-3-Clause
  2 * Copyright 2016-2018 NXP
  3 * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
  4 */
  5#ifndef _LINUX_PACKING_H
  6#define _LINUX_PACKING_H
  7
  8#include <linux/array_size.h>
  9#include <linux/bitops.h>
 10#include <linux/build_bug.h>
 11#include <linux/minmax.h>
 12#include <linux/stddef.h>
 13#include <linux/types.h>
 14
 15#define GEN_PACKED_FIELD_STRUCT(__type) \
 16	struct packed_field_ ## __type { \
 17		__type startbit; \
 18		__type endbit; \
 19		__type offset; \
 20		__type size; \
 21	}
 22
 23/* struct packed_field_u8. Use with bit offsets < 256, buffers < 32B and
 24 * unpacked structures < 256B.
 25 */
 26GEN_PACKED_FIELD_STRUCT(u8);
 27
 28/* struct packed_field_u16. Use with bit offsets < 65536, buffers < 8KB and
 29 * unpacked structures < 64KB.
 30 */
 31GEN_PACKED_FIELD_STRUCT(u16);
 32
 33#define PACKED_FIELD(start, end, struct_name, struct_field) \
 34{ \
 35	(start), \
 36	(end), \
 37	offsetof(struct_name, struct_field), \
 38	sizeof_field(struct_name, struct_field), \
 39}
 40
 41#define CHECK_PACKED_FIELD_OVERLAP(fields, index1, index2) ({ \
 42	typeof(&(fields)[0]) __f = (fields); \
 43	typeof(__f[0]) _f1 = __f[index1]; typeof(__f[0]) _f2 = __f[index2]; \
 44	const bool _ascending = __f[0].startbit < __f[1].startbit; \
 45	BUILD_BUG_ON_MSG(_ascending && _f1.startbit >= _f2.startbit, \
 46			 __stringify(fields) " field " __stringify(index2) \
 47			 " breaks ascending order"); \
 48	BUILD_BUG_ON_MSG(!_ascending && _f1.startbit <= _f2.startbit, \
 49			 __stringify(fields) " field " __stringify(index2) \
 50			 " breaks descending order"); \
 51	BUILD_BUG_ON_MSG(max(_f1.endbit, _f2.endbit) <= \
 52			 min(_f1.startbit, _f2.startbit), \
 53			 __stringify(fields) " field " __stringify(index2) \
 54			 " overlaps with previous field"); \
 55})
 56
 57#define CHECK_PACKED_FIELD(fields, index) ({ \
 58	typeof(&(fields)[0]) _f = (fields); \
 59	typeof(_f[0]) __f = _f[index]; \
 60	BUILD_BUG_ON_MSG(__f.startbit < __f.endbit, \
 61			 __stringify(fields) " field " __stringify(index) \
 62			 " start bit must not be smaller than end bit"); \
 63	BUILD_BUG_ON_MSG(__f.size != 1 && __f.size != 2 && \
 64			 __f.size != 4 && __f.size != 8, \
 65			 __stringify(fields) " field " __stringify(index) \
 66			" has unsupported unpacked storage size"); \
 67	BUILD_BUG_ON_MSG(__f.startbit - __f.endbit >= BITS_PER_BYTE * __f.size, \
 68			 __stringify(fields) " field " __stringify(index) \
 69			 " exceeds unpacked storage size"); \
 70	__builtin_choose_expr(index != 0, \
 71			      CHECK_PACKED_FIELD_OVERLAP(fields, index - 1, index), \
 72			      1); \
 73})
 74
 75/* Note that the packed fields may be either in ascending or descending order.
 76 * Thus, we must check that both the first and last field wit within the
 77 * packed buffer size.
 78 */
 79#define CHECK_PACKED_FIELDS_SIZE(fields, pbuflen) ({ \
 80	typeof(&(fields)[0]) _f = (fields); \
 81	typeof(pbuflen) _len = (pbuflen); \
 82	const size_t num_fields = ARRAY_SIZE(fields); \
 83	BUILD_BUG_ON_MSG(!__builtin_constant_p(_len), \
 84			 __stringify(fields) " pbuflen " __stringify(pbuflen) \
 85			 " must be a compile time constant"); \
 86	BUILD_BUG_ON_MSG(_f[0].startbit >= BITS_PER_BYTE * _len, \
 87			 __stringify(fields) " first field exceeds packed buffer size"); \
 88	BUILD_BUG_ON_MSG(_f[num_fields - 1].startbit >= BITS_PER_BYTE * _len, \
 89			 __stringify(fields) " last field exceeds packed buffer size"); \
 90})
 91
 92#define QUIRK_MSB_ON_THE_RIGHT	BIT(0)
 93#define QUIRK_LITTLE_ENDIAN	BIT(1)
 94#define QUIRK_LSW32_IS_FIRST	BIT(2)
 95
 96enum packing_op {
 97	PACK,
 98	UNPACK,
 99};
100
101int packing(void *pbuf, u64 *uval, int startbit, int endbit, size_t pbuflen,
102	    enum packing_op op, u8 quirks);
103
104int pack(void *pbuf, u64 uval, size_t startbit, size_t endbit, size_t pbuflen,
105	 u8 quirks);
106
107int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
108	   size_t pbuflen, u8 quirks);
109
110void pack_fields_u8(void *pbuf, size_t pbuflen, const void *ustruct,
111		    const struct packed_field_u8 *fields, size_t num_fields,
112		    u8 quirks);
113
114void pack_fields_u16(void *pbuf, size_t pbuflen, const void *ustruct,
115		     const struct packed_field_u16 *fields, size_t num_fields,
116		     u8 quirks);
117
118void unpack_fields_u8(const void *pbuf, size_t pbuflen, void *ustruct,
119		      const struct packed_field_u8 *fields, size_t num_fields,
120		      u8 quirks);
121
122void unpack_fields_u16(const void *pbuf, size_t pbuflen, void *ustruct,
123		       const struct packed_field_u16 *fields, size_t num_fields,
124		       u8 quirks);
125
126/* Do not hand-edit the following packed field check macros!
127 *
128 * They are generated using scripts/gen_packed_field_checks.c, which may be
129 * built via "make scripts_gen_packed_field_checks". If larger macro sizes are
130 * needed in the future, please use this program to re-generate the macros and
131 * insert them here.
132 */
133
134#define CHECK_PACKED_FIELDS_1(fields) \
135	CHECK_PACKED_FIELD(fields, 0)
136
137#define CHECK_PACKED_FIELDS_2(fields) do { \
138	CHECK_PACKED_FIELDS_1(fields); \
139	CHECK_PACKED_FIELD(fields, 1); \
140} while (0)
141
142#define CHECK_PACKED_FIELDS_3(fields) do { \
143	CHECK_PACKED_FIELDS_2(fields); \
144	CHECK_PACKED_FIELD(fields, 2); \
145} while (0)
146
147#define CHECK_PACKED_FIELDS_4(fields) do { \
148	CHECK_PACKED_FIELDS_3(fields); \
149	CHECK_PACKED_FIELD(fields, 3); \
150} while (0)
151
152#define CHECK_PACKED_FIELDS_5(fields) do { \
153	CHECK_PACKED_FIELDS_4(fields); \
154	CHECK_PACKED_FIELD(fields, 4); \
155} while (0)
156
157#define CHECK_PACKED_FIELDS_6(fields) do { \
158	CHECK_PACKED_FIELDS_5(fields); \
159	CHECK_PACKED_FIELD(fields, 5); \
160} while (0)
161
162#define CHECK_PACKED_FIELDS_7(fields) do { \
163	CHECK_PACKED_FIELDS_6(fields); \
164	CHECK_PACKED_FIELD(fields, 6); \
165} while (0)
166
167#define CHECK_PACKED_FIELDS_8(fields) do { \
168	CHECK_PACKED_FIELDS_7(fields); \
169	CHECK_PACKED_FIELD(fields, 7); \
170} while (0)
171
172#define CHECK_PACKED_FIELDS_9(fields) do { \
173	CHECK_PACKED_FIELDS_8(fields); \
174	CHECK_PACKED_FIELD(fields, 8); \
175} while (0)
176
177#define CHECK_PACKED_FIELDS_10(fields) do { \
178	CHECK_PACKED_FIELDS_9(fields); \
179	CHECK_PACKED_FIELD(fields, 9); \
180} while (0)
181
182#define CHECK_PACKED_FIELDS_11(fields) do { \
183	CHECK_PACKED_FIELDS_10(fields); \
184	CHECK_PACKED_FIELD(fields, 10); \
185} while (0)
186
187#define CHECK_PACKED_FIELDS_12(fields) do { \
188	CHECK_PACKED_FIELDS_11(fields); \
189	CHECK_PACKED_FIELD(fields, 11); \
190} while (0)
191
192#define CHECK_PACKED_FIELDS_13(fields) do { \
193	CHECK_PACKED_FIELDS_12(fields); \
194	CHECK_PACKED_FIELD(fields, 12); \
195} while (0)
196
197#define CHECK_PACKED_FIELDS_14(fields) do { \
198	CHECK_PACKED_FIELDS_13(fields); \
199	CHECK_PACKED_FIELD(fields, 13); \
200} while (0)
201
202#define CHECK_PACKED_FIELDS_15(fields) do { \
203	CHECK_PACKED_FIELDS_14(fields); \
204	CHECK_PACKED_FIELD(fields, 14); \
205} while (0)
206
207#define CHECK_PACKED_FIELDS_16(fields) do { \
208	CHECK_PACKED_FIELDS_15(fields); \
209	CHECK_PACKED_FIELD(fields, 15); \
210} while (0)
211
212#define CHECK_PACKED_FIELDS_17(fields) do { \
213	CHECK_PACKED_FIELDS_16(fields); \
214	CHECK_PACKED_FIELD(fields, 16); \
215} while (0)
216
217#define CHECK_PACKED_FIELDS_18(fields) do { \
218	CHECK_PACKED_FIELDS_17(fields); \
219	CHECK_PACKED_FIELD(fields, 17); \
220} while (0)
221
222#define CHECK_PACKED_FIELDS_19(fields) do { \
223	CHECK_PACKED_FIELDS_18(fields); \
224	CHECK_PACKED_FIELD(fields, 18); \
225} while (0)
226
227#define CHECK_PACKED_FIELDS_20(fields) do { \
228	CHECK_PACKED_FIELDS_19(fields); \
229	CHECK_PACKED_FIELD(fields, 19); \
230} while (0)
231
232#define CHECK_PACKED_FIELDS_21(fields) do { \
233	CHECK_PACKED_FIELDS_20(fields); \
234	CHECK_PACKED_FIELD(fields, 20); \
235} while (0)
236
237#define CHECK_PACKED_FIELDS_22(fields) do { \
238	CHECK_PACKED_FIELDS_21(fields); \
239	CHECK_PACKED_FIELD(fields, 21); \
240} while (0)
241
242#define CHECK_PACKED_FIELDS_23(fields) do { \
243	CHECK_PACKED_FIELDS_22(fields); \
244	CHECK_PACKED_FIELD(fields, 22); \
245} while (0)
246
247#define CHECK_PACKED_FIELDS_24(fields) do { \
248	CHECK_PACKED_FIELDS_23(fields); \
249	CHECK_PACKED_FIELD(fields, 23); \
250} while (0)
251
252#define CHECK_PACKED_FIELDS_25(fields) do { \
253	CHECK_PACKED_FIELDS_24(fields); \
254	CHECK_PACKED_FIELD(fields, 24); \
255} while (0)
256
257#define CHECK_PACKED_FIELDS_26(fields) do { \
258	CHECK_PACKED_FIELDS_25(fields); \
259	CHECK_PACKED_FIELD(fields, 25); \
260} while (0)
261
262#define CHECK_PACKED_FIELDS_27(fields) do { \
263	CHECK_PACKED_FIELDS_26(fields); \
264	CHECK_PACKED_FIELD(fields, 26); \
265} while (0)
266
267#define CHECK_PACKED_FIELDS_28(fields) do { \
268	CHECK_PACKED_FIELDS_27(fields); \
269	CHECK_PACKED_FIELD(fields, 27); \
270} while (0)
271
272#define CHECK_PACKED_FIELDS_29(fields) do { \
273	CHECK_PACKED_FIELDS_28(fields); \
274	CHECK_PACKED_FIELD(fields, 28); \
275} while (0)
276
277#define CHECK_PACKED_FIELDS_30(fields) do { \
278	CHECK_PACKED_FIELDS_29(fields); \
279	CHECK_PACKED_FIELD(fields, 29); \
280} while (0)
281
282#define CHECK_PACKED_FIELDS_31(fields) do { \
283	CHECK_PACKED_FIELDS_30(fields); \
284	CHECK_PACKED_FIELD(fields, 30); \
285} while (0)
286
287#define CHECK_PACKED_FIELDS_32(fields) do { \
288	CHECK_PACKED_FIELDS_31(fields); \
289	CHECK_PACKED_FIELD(fields, 31); \
290} while (0)
291
292#define CHECK_PACKED_FIELDS_33(fields) do { \
293	CHECK_PACKED_FIELDS_32(fields); \
294	CHECK_PACKED_FIELD(fields, 32); \
295} while (0)
296
297#define CHECK_PACKED_FIELDS_34(fields) do { \
298	CHECK_PACKED_FIELDS_33(fields); \
299	CHECK_PACKED_FIELD(fields, 33); \
300} while (0)
301
302#define CHECK_PACKED_FIELDS_35(fields) do { \
303	CHECK_PACKED_FIELDS_34(fields); \
304	CHECK_PACKED_FIELD(fields, 34); \
305} while (0)
306
307#define CHECK_PACKED_FIELDS_36(fields) do { \
308	CHECK_PACKED_FIELDS_35(fields); \
309	CHECK_PACKED_FIELD(fields, 35); \
310} while (0)
311
312#define CHECK_PACKED_FIELDS_37(fields) do { \
313	CHECK_PACKED_FIELDS_36(fields); \
314	CHECK_PACKED_FIELD(fields, 36); \
315} while (0)
316
317#define CHECK_PACKED_FIELDS_38(fields) do { \
318	CHECK_PACKED_FIELDS_37(fields); \
319	CHECK_PACKED_FIELD(fields, 37); \
320} while (0)
321
322#define CHECK_PACKED_FIELDS_39(fields) do { \
323	CHECK_PACKED_FIELDS_38(fields); \
324	CHECK_PACKED_FIELD(fields, 38); \
325} while (0)
326
327#define CHECK_PACKED_FIELDS_40(fields) do { \
328	CHECK_PACKED_FIELDS_39(fields); \
329	CHECK_PACKED_FIELD(fields, 39); \
330} while (0)
331
332#define CHECK_PACKED_FIELDS_41(fields) do { \
333	CHECK_PACKED_FIELDS_40(fields); \
334	CHECK_PACKED_FIELD(fields, 40); \
335} while (0)
336
337#define CHECK_PACKED_FIELDS_42(fields) do { \
338	CHECK_PACKED_FIELDS_41(fields); \
339	CHECK_PACKED_FIELD(fields, 41); \
340} while (0)
341
342#define CHECK_PACKED_FIELDS_43(fields) do { \
343	CHECK_PACKED_FIELDS_42(fields); \
344	CHECK_PACKED_FIELD(fields, 42); \
345} while (0)
346
347#define CHECK_PACKED_FIELDS_44(fields) do { \
348	CHECK_PACKED_FIELDS_43(fields); \
349	CHECK_PACKED_FIELD(fields, 43); \
350} while (0)
351
352#define CHECK_PACKED_FIELDS_45(fields) do { \
353	CHECK_PACKED_FIELDS_44(fields); \
354	CHECK_PACKED_FIELD(fields, 44); \
355} while (0)
356
357#define CHECK_PACKED_FIELDS_46(fields) do { \
358	CHECK_PACKED_FIELDS_45(fields); \
359	CHECK_PACKED_FIELD(fields, 45); \
360} while (0)
361
362#define CHECK_PACKED_FIELDS_47(fields) do { \
363	CHECK_PACKED_FIELDS_46(fields); \
364	CHECK_PACKED_FIELD(fields, 46); \
365} while (0)
366
367#define CHECK_PACKED_FIELDS_48(fields) do { \
368	CHECK_PACKED_FIELDS_47(fields); \
369	CHECK_PACKED_FIELD(fields, 47); \
370} while (0)
371
372#define CHECK_PACKED_FIELDS_49(fields) do { \
373	CHECK_PACKED_FIELDS_48(fields); \
374	CHECK_PACKED_FIELD(fields, 48); \
375} while (0)
376
377#define CHECK_PACKED_FIELDS_50(fields) do { \
378	CHECK_PACKED_FIELDS_49(fields); \
379	CHECK_PACKED_FIELD(fields, 49); \
380} while (0)
381
382#define CHECK_PACKED_FIELDS(fields) \
383	__builtin_choose_expr(ARRAY_SIZE(fields) == 1, ({ CHECK_PACKED_FIELDS_1(fields); }), \
384	__builtin_choose_expr(ARRAY_SIZE(fields) == 2, ({ CHECK_PACKED_FIELDS_2(fields); }), \
385	__builtin_choose_expr(ARRAY_SIZE(fields) == 3, ({ CHECK_PACKED_FIELDS_3(fields); }), \
386	__builtin_choose_expr(ARRAY_SIZE(fields) == 4, ({ CHECK_PACKED_FIELDS_4(fields); }), \
387	__builtin_choose_expr(ARRAY_SIZE(fields) == 5, ({ CHECK_PACKED_FIELDS_5(fields); }), \
388	__builtin_choose_expr(ARRAY_SIZE(fields) == 6, ({ CHECK_PACKED_FIELDS_6(fields); }), \
389	__builtin_choose_expr(ARRAY_SIZE(fields) == 7, ({ CHECK_PACKED_FIELDS_7(fields); }), \
390	__builtin_choose_expr(ARRAY_SIZE(fields) == 8, ({ CHECK_PACKED_FIELDS_8(fields); }), \
391	__builtin_choose_expr(ARRAY_SIZE(fields) == 9, ({ CHECK_PACKED_FIELDS_9(fields); }), \
392	__builtin_choose_expr(ARRAY_SIZE(fields) == 10, ({ CHECK_PACKED_FIELDS_10(fields); }), \
393	__builtin_choose_expr(ARRAY_SIZE(fields) == 11, ({ CHECK_PACKED_FIELDS_11(fields); }), \
394	__builtin_choose_expr(ARRAY_SIZE(fields) == 12, ({ CHECK_PACKED_FIELDS_12(fields); }), \
395	__builtin_choose_expr(ARRAY_SIZE(fields) == 13, ({ CHECK_PACKED_FIELDS_13(fields); }), \
396	__builtin_choose_expr(ARRAY_SIZE(fields) == 14, ({ CHECK_PACKED_FIELDS_14(fields); }), \
397	__builtin_choose_expr(ARRAY_SIZE(fields) == 15, ({ CHECK_PACKED_FIELDS_15(fields); }), \
398	__builtin_choose_expr(ARRAY_SIZE(fields) == 16, ({ CHECK_PACKED_FIELDS_16(fields); }), \
399	__builtin_choose_expr(ARRAY_SIZE(fields) == 17, ({ CHECK_PACKED_FIELDS_17(fields); }), \
400	__builtin_choose_expr(ARRAY_SIZE(fields) == 18, ({ CHECK_PACKED_FIELDS_18(fields); }), \
401	__builtin_choose_expr(ARRAY_SIZE(fields) == 19, ({ CHECK_PACKED_FIELDS_19(fields); }), \
402	__builtin_choose_expr(ARRAY_SIZE(fields) == 20, ({ CHECK_PACKED_FIELDS_20(fields); }), \
403	__builtin_choose_expr(ARRAY_SIZE(fields) == 21, ({ CHECK_PACKED_FIELDS_21(fields); }), \
404	__builtin_choose_expr(ARRAY_SIZE(fields) == 22, ({ CHECK_PACKED_FIELDS_22(fields); }), \
405	__builtin_choose_expr(ARRAY_SIZE(fields) == 23, ({ CHECK_PACKED_FIELDS_23(fields); }), \
406	__builtin_choose_expr(ARRAY_SIZE(fields) == 24, ({ CHECK_PACKED_FIELDS_24(fields); }), \
407	__builtin_choose_expr(ARRAY_SIZE(fields) == 25, ({ CHECK_PACKED_FIELDS_25(fields); }), \
408	__builtin_choose_expr(ARRAY_SIZE(fields) == 26, ({ CHECK_PACKED_FIELDS_26(fields); }), \
409	__builtin_choose_expr(ARRAY_SIZE(fields) == 27, ({ CHECK_PACKED_FIELDS_27(fields); }), \
410	__builtin_choose_expr(ARRAY_SIZE(fields) == 28, ({ CHECK_PACKED_FIELDS_28(fields); }), \
411	__builtin_choose_expr(ARRAY_SIZE(fields) == 29, ({ CHECK_PACKED_FIELDS_29(fields); }), \
412	__builtin_choose_expr(ARRAY_SIZE(fields) == 30, ({ CHECK_PACKED_FIELDS_30(fields); }), \
413	__builtin_choose_expr(ARRAY_SIZE(fields) == 31, ({ CHECK_PACKED_FIELDS_31(fields); }), \
414	__builtin_choose_expr(ARRAY_SIZE(fields) == 32, ({ CHECK_PACKED_FIELDS_32(fields); }), \
415	__builtin_choose_expr(ARRAY_SIZE(fields) == 33, ({ CHECK_PACKED_FIELDS_33(fields); }), \
416	__builtin_choose_expr(ARRAY_SIZE(fields) == 34, ({ CHECK_PACKED_FIELDS_34(fields); }), \
417	__builtin_choose_expr(ARRAY_SIZE(fields) == 35, ({ CHECK_PACKED_FIELDS_35(fields); }), \
418	__builtin_choose_expr(ARRAY_SIZE(fields) == 36, ({ CHECK_PACKED_FIELDS_36(fields); }), \
419	__builtin_choose_expr(ARRAY_SIZE(fields) == 37, ({ CHECK_PACKED_FIELDS_37(fields); }), \
420	__builtin_choose_expr(ARRAY_SIZE(fields) == 38, ({ CHECK_PACKED_FIELDS_38(fields); }), \
421	__builtin_choose_expr(ARRAY_SIZE(fields) == 39, ({ CHECK_PACKED_FIELDS_39(fields); }), \
422	__builtin_choose_expr(ARRAY_SIZE(fields) == 40, ({ CHECK_PACKED_FIELDS_40(fields); }), \
423	__builtin_choose_expr(ARRAY_SIZE(fields) == 41, ({ CHECK_PACKED_FIELDS_41(fields); }), \
424	__builtin_choose_expr(ARRAY_SIZE(fields) == 42, ({ CHECK_PACKED_FIELDS_42(fields); }), \
425	__builtin_choose_expr(ARRAY_SIZE(fields) == 43, ({ CHECK_PACKED_FIELDS_43(fields); }), \
426	__builtin_choose_expr(ARRAY_SIZE(fields) == 44, ({ CHECK_PACKED_FIELDS_44(fields); }), \
427	__builtin_choose_expr(ARRAY_SIZE(fields) == 45, ({ CHECK_PACKED_FIELDS_45(fields); }), \
428	__builtin_choose_expr(ARRAY_SIZE(fields) == 46, ({ CHECK_PACKED_FIELDS_46(fields); }), \
429	__builtin_choose_expr(ARRAY_SIZE(fields) == 47, ({ CHECK_PACKED_FIELDS_47(fields); }), \
430	__builtin_choose_expr(ARRAY_SIZE(fields) == 48, ({ CHECK_PACKED_FIELDS_48(fields); }), \
431	__builtin_choose_expr(ARRAY_SIZE(fields) == 49, ({ CHECK_PACKED_FIELDS_49(fields); }), \
432	__builtin_choose_expr(ARRAY_SIZE(fields) == 50, ({ CHECK_PACKED_FIELDS_50(fields); }), \
433	({ BUILD_BUG_ON_MSG(1, "CHECK_PACKED_FIELDS() must be regenerated to support array sizes larger than 50."); }) \
434))))))))))))))))))))))))))))))))))))))))))))))))))
435
436/* End of generated content */
437
438#define pack_fields(pbuf, pbuflen, ustruct, fields, quirks) \
439	({ \
440		CHECK_PACKED_FIELDS(fields); \
441		CHECK_PACKED_FIELDS_SIZE((fields), (pbuflen)); \
442		_Generic((fields), \
443			 const struct packed_field_u8 * : pack_fields_u8, \
444			 const struct packed_field_u16 * : pack_fields_u16 \
445			)((pbuf), (pbuflen), (ustruct), (fields), ARRAY_SIZE(fields), (quirks)); \
446	})
447
448#define unpack_fields(pbuf, pbuflen, ustruct, fields, quirks) \
449	({ \
450		CHECK_PACKED_FIELDS(fields); \
451		CHECK_PACKED_FIELDS_SIZE((fields), (pbuflen)); \
452		_Generic((fields), \
453			 const struct packed_field_u8 * : unpack_fields_u8, \
454			 const struct packed_field_u16 * : unpack_fields_u16 \
455			)((pbuf), (pbuflen), (ustruct), (fields), ARRAY_SIZE(fields), (quirks)); \
456	})
457
458#endif
~/ Read-only file preview.