~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/util/blob.h

  • Committer: mmach
  • Date: 2022-09-22 19:58:36 UTC
  • Revision ID: netbit73@gmail.com-20220922195836-9nl9joew85y8d25o
2022-07-04 12:44:28

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2014 Intel Corporation
 
3
 *
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the "Software"),
 
6
 * to deal in the Software without restriction, including without limitation
 
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
8
 * and/or sell copies of the Software, and to permit persons to whom the
 
9
 * Software is furnished to do so, subject to the following conditions:
 
10
 *
 
11
 * The above copyright notice and this permission notice (including the next
 
12
 * paragraph) shall be included in all copies or substantial portions of the
 
13
 * Software.
 
14
 *
 
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 
21
 * IN THE SOFTWARE.
 
22
 */
 
23
 
 
24
#ifndef BLOB_H
 
25
#define BLOB_H
 
26
 
 
27
#include <stdbool.h>
 
28
#include <stddef.h>
 
29
#include <stdint.h>
 
30
#include <stdlib.h>
 
31
 
 
32
#ifdef __cplusplus
 
33
extern "C" {
 
34
#endif
 
35
 
 
36
/* The blob functions implement a simple, low-level API for serializing and
 
37
 * deserializing.
 
38
 *
 
39
 * All objects written to a blob will be serialized directly, (without any
 
40
 * additional meta-data to describe the data written). Therefore, it is the
 
41
 * caller's responsibility to ensure that any data can be read later, (either
 
42
 * by knowing exactly what data is expected, or by writing to the blob
 
43
 * sufficient meta-data to describe what has been written).
 
44
 *
 
45
 * A blob is efficient in that it dynamically grows by doubling in size, so
 
46
 * allocation costs are logarithmic.
 
47
 */
 
48
 
 
49
struct blob {
 
50
   /* The data actually written to the blob. Never read or write this directly
 
51
    * when serializing, use blob_reserve_* and blob_overwrite_* instead which
 
52
    * check for out_of_memory and handle fixed-size blobs correctly.
 
53
    */
 
54
   uint8_t *data;
 
55
 
 
56
   /** Number of bytes that have been allocated for \c data. */
 
57
   size_t allocated;
 
58
 
 
59
   /** The number of bytes that have actual data written to them. */
 
60
   size_t size;
 
61
 
 
62
   /** True if \c data a fixed allocation that we cannot resize
 
63
    *
 
64
    * \see blob_init_fixed
 
65
    */
 
66
   bool fixed_allocation;
 
67
 
 
68
   /**
 
69
    * True if we've ever failed to realloc or if we go pas the end of a fixed
 
70
    * allocation blob.
 
71
    */
 
72
   bool out_of_memory;
 
73
};
 
74
 
 
75
/* When done reading, the caller can ensure that everything was consumed by
 
76
 * checking the following:
 
77
 *
 
78
 *   1. blob->current should be equal to blob->end, (if not, too little was
 
79
 *      read).
 
80
 *
 
81
 *   2. blob->overrun should be false, (otherwise, too much was read).
 
82
 */
 
83
struct blob_reader {
 
84
   const uint8_t *data;
 
85
   const uint8_t *end;
 
86
   const uint8_t *current;
 
87
   bool overrun;
 
88
};
 
89
 
 
90
/**
 
91
 * Init a new, empty blob.
 
92
 */
 
93
void
 
94
blob_init(struct blob *blob);
 
95
 
 
96
/**
 
97
 * Init a new, fixed-size blob.
 
98
 *
 
99
 * A fixed-size blob has a fixed block of data that will not be freed on
 
100
 * blob_finish and will never be grown.  If we hit the end, we simply start
 
101
 * returning false from the write functions.
 
102
 *
 
103
 * If a fixed-size blob has a NULL data pointer then the data is written but
 
104
 * it otherwise operates normally.  This can be used to determine the size
 
105
 * that will be required to write a given data structure.
 
106
 */
 
107
void
 
108
blob_init_fixed(struct blob *blob, void *data, size_t size);
 
109
 
 
110
/**
 
111
 * Finish a blob and free its memory.
 
112
 *
 
113
 * If \blob was initialized with blob_init_fixed, the data pointer is
 
114
 * considered to be owned by the user and will not be freed.
 
115
 */
 
116
static inline void
 
117
blob_finish(struct blob *blob)
 
118
{
 
119
   if (!blob->fixed_allocation)
 
120
      free(blob->data);
 
121
}
 
122
 
 
123
void
 
124
blob_finish_get_buffer(struct blob *blob, void **buffer, size_t *size);
 
125
 
 
126
/**
 
127
 * Add some unstructured, fixed-size data to a blob.
 
128
 *
 
129
 * \return True unless allocation failed.
 
130
 */
 
131
bool
 
132
blob_write_bytes(struct blob *blob, const void *bytes, size_t to_write);
 
133
 
 
134
/**
 
135
 * Reserve space in \blob for a number of bytes.
 
136
 *
 
137
 * Space will be allocated within the blob for these byes, but the bytes will
 
138
 * be left uninitialized. The caller is expected to use \sa
 
139
 * blob_overwrite_bytes to write to these bytes.
 
140
 *
 
141
 * \return An offset to space allocated within \blob to which \to_write bytes
 
142
 * can be written, (or -1 in case of any allocation error).
 
143
 */
 
144
intptr_t
 
145
blob_reserve_bytes(struct blob *blob, size_t to_write);
 
146
 
 
147
/**
 
148
 * Similar to \sa blob_reserve_bytes, but only reserves an uint32_t worth of
 
149
 * space. Note that this must be used if later reading with \sa
 
150
 * blob_read_uint32, since it aligns the offset correctly.
 
151
 */
 
152
intptr_t
 
153
blob_reserve_uint32(struct blob *blob);
 
154
 
 
155
/**
 
156
 * Similar to \sa blob_reserve_bytes, but only reserves an intptr_t worth of
 
157
 * space. Note that this must be used if later reading with \sa
 
158
 * blob_read_intptr, since it aligns the offset correctly.
 
159
 */
 
160
intptr_t
 
161
blob_reserve_intptr(struct blob *blob);
 
162
 
 
163
/**
 
164
 * Overwrite some data previously written to the blob.
 
165
 *
 
166
 * Writes data to an existing portion of the blob at an offset of \offset.
 
167
 * This data range must have previously been written to the blob by one of the
 
168
 * blob_write_* calls.
 
169
 *
 
170
 * For example usage, see blob_overwrite_uint32
 
171
 *
 
172
 * \return True unless the requested offset or offset+to_write lie outside
 
173
 * the current blob's size.
 
174
 */
 
175
bool
 
176
blob_overwrite_bytes(struct blob *blob,
 
177
                     size_t offset,
 
178
                     const void *bytes,
 
179
                     size_t to_write);
 
180
 
 
181
/**
 
182
 * Add a uint8_t to a blob.
 
183
 *
 
184
 * \return True unless allocation failed.
 
185
 */
 
186
bool
 
187
blob_write_uint8(struct blob *blob, uint8_t value);
 
188
 
 
189
/**
 
190
 * Overwrite a uint8_t previously written to the blob.
 
191
 *
 
192
 * Writes a uint8_t value to an existing portion of the blob at an offset of
 
193
 * \offset.  This data range must have previously been written to the blob by
 
194
 * one of the blob_write_* calls.
 
195
 *
 
196
 * \return True unless the requested position or position+to_write lie outside
 
197
 * the current blob's size.
 
198
 */
 
199
bool
 
200
blob_overwrite_uint8(struct blob *blob,
 
201
                     size_t offset,
 
202
                     uint8_t value);
 
203
 
 
204
/**
 
205
 * Add a uint16_t to a blob.
 
206
 *
 
207
 * \note This function will only write to a uint16_t-aligned offset from the
 
208
 * beginning of the blob's data, so some padding bytes may be added to the
 
209
 * blob if this write follows some unaligned write (such as
 
210
 * blob_write_string).
 
211
 *
 
212
 * \return True unless allocation failed.
 
213
 */
 
214
bool
 
215
blob_write_uint16(struct blob *blob, uint16_t value);
 
216
 
 
217
/**
 
218
 * Add a uint32_t to a blob.
 
219
 *
 
220
 * \note This function will only write to a uint32_t-aligned offset from the
 
221
 * beginning of the blob's data, so some padding bytes may be added to the
 
222
 * blob if this write follows some unaligned write (such as
 
223
 * blob_write_string).
 
224
 *
 
225
 * \return True unless allocation failed.
 
226
 */
 
227
bool
 
228
blob_write_uint32(struct blob *blob, uint32_t value);
 
229
 
 
230
/**
 
231
 * Overwrite a uint32_t previously written to the blob.
 
232
 *
 
233
 * Writes a uint32_t value to an existing portion of the blob at an offset of
 
234
 * \offset.  This data range must have previously been written to the blob by
 
235
 * one of the blob_write_* calls.
 
236
 *
 
237
 *
 
238
 * The expected usage is something like the following pattern:
 
239
 *
 
240
 *      size_t offset;
 
241
 *
 
242
 *      offset = blob_reserve_uint32(blob);
 
243
 *      ... various blob write calls, writing N items ...
 
244
 *      blob_overwrite_uint32 (blob, offset, N);
 
245
 *
 
246
 * \return True unless the requested position or position+to_write lie outside
 
247
 * the current blob's size.
 
248
 */
 
249
bool
 
250
blob_overwrite_uint32(struct blob *blob,
 
251
                      size_t offset,
 
252
                      uint32_t value);
 
253
 
 
254
/**
 
255
 * Add a uint64_t to a blob.
 
256
 *
 
257
 * \note This function will only write to a uint64_t-aligned offset from the
 
258
 * beginning of the blob's data, so some padding bytes may be added to the
 
259
 * blob if this write follows some unaligned write (such as
 
260
 * blob_write_string).
 
261
 *
 
262
 * \return True unless allocation failed.
 
263
 */
 
264
bool
 
265
blob_write_uint64(struct blob *blob, uint64_t value);
 
266
 
 
267
/**
 
268
 * Add an intptr_t to a blob.
 
269
 *
 
270
 * \note This function will only write to an intptr_t-aligned offset from the
 
271
 * beginning of the blob's data, so some padding bytes may be added to the
 
272
 * blob if this write follows some unaligned write (such as
 
273
 * blob_write_string).
 
274
 *
 
275
 * \return True unless allocation failed.
 
276
 */
 
277
bool
 
278
blob_write_intptr(struct blob *blob, intptr_t value);
 
279
 
 
280
/**
 
281
 * Overwrite an intptr_t previously written to the blob.
 
282
 *
 
283
 * Writes a intptr_t value to an existing portion of the blob at an offset of
 
284
 * \offset.  This data range must have previously been written to the blob by
 
285
 * one of the blob_write_* calls.
 
286
 *
 
287
 * For example usage, see blob_overwrite_uint32
 
288
 *
 
289
 * \return True unless the requested position or position+to_write lie outside
 
290
 * the current blob's size.
 
291
 */
 
292
bool
 
293
blob_overwrite_intptr(struct blob *blob,
 
294
                      size_t offset,
 
295
                      intptr_t value);
 
296
 
 
297
/**
 
298
 * Add a NULL-terminated string to a blob, (including the NULL terminator).
 
299
 *
 
300
 * \return True unless allocation failed.
 
301
 */
 
302
bool
 
303
blob_write_string(struct blob *blob, const char *str);
 
304
 
 
305
/**
 
306
 * Start reading a blob, (initializing the contents of \blob for reading).
 
307
 *
 
308
 * After this call, the caller can use the various blob_read_* functions to
 
309
 * read elements from the data array.
 
310
 *
 
311
 * For all of the blob_read_* functions, if there is insufficient data
 
312
 * remaining, the functions will do nothing, (perhaps returning default values
 
313
 * such as 0). The caller can detect this by noting that the blob_reader's
 
314
 * current value is unchanged before and after the call.
 
315
 */
 
316
void
 
317
blob_reader_init(struct blob_reader *blob, const void *data, size_t size);
 
318
 
 
319
/**
 
320
 * Read some unstructured, fixed-size data from the current location, (and
 
321
 * update the current location to just past this data).
 
322
 *
 
323
 * \note The memory returned belongs to the data underlying the blob reader. The
 
324
 * caller must copy the data in order to use it after the lifetime of the data
 
325
 * underlying the blob reader.
 
326
 *
 
327
 * \return The bytes read (see note above about memory lifetime).
 
328
 */
 
329
const void *
 
330
blob_read_bytes(struct blob_reader *blob, size_t size);
 
331
 
 
332
/**
 
333
 * Read some unstructured, fixed-size data from the current location, copying
 
334
 * it to \dest (and update the current location to just past this data)
 
335
 */
 
336
void
 
337
blob_copy_bytes(struct blob_reader *blob, void *dest, size_t size);
 
338
 
 
339
/**
 
340
 * Skip \size bytes within the blob.
 
341
 */
 
342
void
 
343
blob_skip_bytes(struct blob_reader *blob, size_t size);
 
344
 
 
345
/**
 
346
 * Read a uint8_t from the current location, (and update the current location
 
347
 * to just past this uint8_t).
 
348
 *
 
349
 * \return The uint8_t read
 
350
 */
 
351
uint8_t
 
352
blob_read_uint8(struct blob_reader *blob);
 
353
 
 
354
/**
 
355
 * Read a uint16_t from the current location, (and update the current location
 
356
 * to just past this uint16_t).
 
357
 *
 
358
 * \note This function will only read from a uint16_t-aligned offset from the
 
359
 * beginning of the blob's data, so some padding bytes may be skipped.
 
360
 *
 
361
 * \return The uint16_t read
 
362
 */
 
363
uint16_t
 
364
blob_read_uint16(struct blob_reader *blob);
 
365
 
 
366
/**
 
367
 * Read a uint32_t from the current location, (and update the current location
 
368
 * to just past this uint32_t).
 
369
 *
 
370
 * \note This function will only read from a uint32_t-aligned offset from the
 
371
 * beginning of the blob's data, so some padding bytes may be skipped.
 
372
 *
 
373
 * \return The uint32_t read
 
374
 */
 
375
uint32_t
 
376
blob_read_uint32(struct blob_reader *blob);
 
377
 
 
378
/**
 
379
 * Read a uint64_t from the current location, (and update the current location
 
380
 * to just past this uint64_t).
 
381
 *
 
382
 * \note This function will only read from a uint64_t-aligned offset from the
 
383
 * beginning of the blob's data, so some padding bytes may be skipped.
 
384
 *
 
385
 * \return The uint64_t read
 
386
 */
 
387
uint64_t
 
388
blob_read_uint64(struct blob_reader *blob);
 
389
 
 
390
/**
 
391
 * Read an intptr_t value from the current location, (and update the
 
392
 * current location to just past this intptr_t).
 
393
 *
 
394
 * \note This function will only read from an intptr_t-aligned offset from the
 
395
 * beginning of the blob's data, so some padding bytes may be skipped.
 
396
 *
 
397
 * \return The intptr_t read
 
398
 */
 
399
intptr_t
 
400
blob_read_intptr(struct blob_reader *blob);
 
401
 
 
402
/**
 
403
 * Read a NULL-terminated string from the current location, (and update the
 
404
 * current location to just past this string).
 
405
 *
 
406
 * \note The memory returned belongs to the data underlying the blob reader. The
 
407
 * caller must copy the string in order to use the string after the lifetime
 
408
 * of the data underlying the blob reader.
 
409
 *
 
410
 * \return The string read (see note above about memory lifetime). However, if
 
411
 * there is no NULL byte remaining within the blob, this function returns
 
412
 * NULL.
 
413
 */
 
414
char *
 
415
blob_read_string(struct blob_reader *blob);
 
416
 
 
417
#ifdef __cplusplus
 
418
}
 
419
#endif
 
420
 
 
421
#endif /* BLOB_H */