17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2014 Intel Corporation 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 217ec681f3Smrg * IN THE SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#ifndef BLOB_H 257ec681f3Smrg#define BLOB_H 267ec681f3Smrg 277ec681f3Smrg#include <stdbool.h> 287ec681f3Smrg#include <stddef.h> 297ec681f3Smrg#include <stdint.h> 307ec681f3Smrg#include <stdlib.h> 317ec681f3Smrg 327ec681f3Smrg#ifdef __cplusplus 337ec681f3Smrgextern "C" { 347ec681f3Smrg#endif 357ec681f3Smrg 367ec681f3Smrg/* The blob functions implement a simple, low-level API for serializing and 377ec681f3Smrg * deserializing. 387ec681f3Smrg * 397ec681f3Smrg * All objects written to a blob will be serialized directly, (without any 407ec681f3Smrg * additional meta-data to describe the data written). Therefore, it is the 417ec681f3Smrg * caller's responsibility to ensure that any data can be read later, (either 427ec681f3Smrg * by knowing exactly what data is expected, or by writing to the blob 437ec681f3Smrg * sufficient meta-data to describe what has been written). 447ec681f3Smrg * 457ec681f3Smrg * A blob is efficient in that it dynamically grows by doubling in size, so 467ec681f3Smrg * allocation costs are logarithmic. 477ec681f3Smrg */ 487ec681f3Smrg 497ec681f3Smrgstruct blob { 507ec681f3Smrg /* The data actually written to the blob. */ 517ec681f3Smrg uint8_t *data; 527ec681f3Smrg 537ec681f3Smrg /** Number of bytes that have been allocated for \c data. */ 547ec681f3Smrg size_t allocated; 557ec681f3Smrg 567ec681f3Smrg /** The number of bytes that have actual data written to them. */ 577ec681f3Smrg size_t size; 587ec681f3Smrg 597ec681f3Smrg /** True if \c data a fixed allocation that we cannot resize 607ec681f3Smrg * 617ec681f3Smrg * \see blob_init_fixed 627ec681f3Smrg */ 637ec681f3Smrg bool fixed_allocation; 647ec681f3Smrg 657ec681f3Smrg /** 667ec681f3Smrg * True if we've ever failed to realloc or if we go pas the end of a fixed 677ec681f3Smrg * allocation blob. 687ec681f3Smrg */ 697ec681f3Smrg bool out_of_memory; 707ec681f3Smrg}; 717ec681f3Smrg 727ec681f3Smrg/* When done reading, the caller can ensure that everything was consumed by 737ec681f3Smrg * checking the following: 747ec681f3Smrg * 757ec681f3Smrg * 1. blob->current should be equal to blob->end, (if not, too little was 767ec681f3Smrg * read). 777ec681f3Smrg * 787ec681f3Smrg * 2. blob->overrun should be false, (otherwise, too much was read). 797ec681f3Smrg */ 807ec681f3Smrgstruct blob_reader { 817ec681f3Smrg const uint8_t *data; 827ec681f3Smrg const uint8_t *end; 837ec681f3Smrg const uint8_t *current; 847ec681f3Smrg bool overrun; 857ec681f3Smrg}; 867ec681f3Smrg 877ec681f3Smrg/** 887ec681f3Smrg * Init a new, empty blob. 897ec681f3Smrg */ 907ec681f3Smrgvoid 917ec681f3Smrgblob_init(struct blob *blob); 927ec681f3Smrg 937ec681f3Smrg/** 947ec681f3Smrg * Init a new, fixed-size blob. 957ec681f3Smrg * 967ec681f3Smrg * A fixed-size blob has a fixed block of data that will not be freed on 977ec681f3Smrg * blob_finish and will never be grown. If we hit the end, we simply start 987ec681f3Smrg * returning false from the write functions. 997ec681f3Smrg * 1007ec681f3Smrg * If a fixed-size blob has a NULL data pointer then the data is written but 1017ec681f3Smrg * it otherwise operates normally. This can be used to determine the size 1027ec681f3Smrg * that will be required to write a given data structure. 1037ec681f3Smrg */ 1047ec681f3Smrgvoid 1057ec681f3Smrgblob_init_fixed(struct blob *blob, void *data, size_t size); 1067ec681f3Smrg 1077ec681f3Smrg/** 1087ec681f3Smrg * Finish a blob and free its memory. 1097ec681f3Smrg * 1107ec681f3Smrg * If \blob was initialized with blob_init_fixed, the data pointer is 1117ec681f3Smrg * considered to be owned by the user and will not be freed. 1127ec681f3Smrg */ 1137ec681f3Smrgstatic inline void 1147ec681f3Smrgblob_finish(struct blob *blob) 1157ec681f3Smrg{ 1167ec681f3Smrg if (!blob->fixed_allocation) 1177ec681f3Smrg free(blob->data); 1187ec681f3Smrg} 1197ec681f3Smrg 1207ec681f3Smrgvoid 1217ec681f3Smrgblob_finish_get_buffer(struct blob *blob, void **buffer, size_t *size); 1227ec681f3Smrg 1237ec681f3Smrg/** 1247ec681f3Smrg * Add some unstructured, fixed-size data to a blob. 1257ec681f3Smrg * 1267ec681f3Smrg * \return True unless allocation failed. 1277ec681f3Smrg */ 1287ec681f3Smrgbool 1297ec681f3Smrgblob_write_bytes(struct blob *blob, const void *bytes, size_t to_write); 1307ec681f3Smrg 1317ec681f3Smrg/** 1327ec681f3Smrg * Reserve space in \blob for a number of bytes. 1337ec681f3Smrg * 1347ec681f3Smrg * Space will be allocated within the blob for these byes, but the bytes will 1357ec681f3Smrg * be left uninitialized. The caller is expected to use \sa 1367ec681f3Smrg * blob_overwrite_bytes to write to these bytes. 1377ec681f3Smrg * 1387ec681f3Smrg * \return An offset to space allocated within \blob to which \to_write bytes 1397ec681f3Smrg * can be written, (or -1 in case of any allocation error). 1407ec681f3Smrg */ 1417ec681f3Smrgintptr_t 1427ec681f3Smrgblob_reserve_bytes(struct blob *blob, size_t to_write); 1437ec681f3Smrg 1447ec681f3Smrg/** 1457ec681f3Smrg * Similar to \sa blob_reserve_bytes, but only reserves an uint32_t worth of 1467ec681f3Smrg * space. Note that this must be used if later reading with \sa 1477ec681f3Smrg * blob_read_uint32, since it aligns the offset correctly. 1487ec681f3Smrg */ 1497ec681f3Smrgintptr_t 1507ec681f3Smrgblob_reserve_uint32(struct blob *blob); 1517ec681f3Smrg 1527ec681f3Smrg/** 1537ec681f3Smrg * Similar to \sa blob_reserve_bytes, but only reserves an intptr_t worth of 1547ec681f3Smrg * space. Note that this must be used if later reading with \sa 1557ec681f3Smrg * blob_read_intptr, since it aligns the offset correctly. 1567ec681f3Smrg */ 1577ec681f3Smrgintptr_t 1587ec681f3Smrgblob_reserve_intptr(struct blob *blob); 1597ec681f3Smrg 1607ec681f3Smrg/** 1617ec681f3Smrg * Overwrite some data previously written to the blob. 1627ec681f3Smrg * 1637ec681f3Smrg * Writes data to an existing portion of the blob at an offset of \offset. 1647ec681f3Smrg * This data range must have previously been written to the blob by one of the 1657ec681f3Smrg * blob_write_* calls. 1667ec681f3Smrg * 1677ec681f3Smrg * For example usage, see blob_overwrite_uint32 1687ec681f3Smrg * 1697ec681f3Smrg * \return True unless the requested offset or offset+to_write lie outside 1707ec681f3Smrg * the current blob's size. 1717ec681f3Smrg */ 1727ec681f3Smrgbool 1737ec681f3Smrgblob_overwrite_bytes(struct blob *blob, 1747ec681f3Smrg size_t offset, 1757ec681f3Smrg const void *bytes, 1767ec681f3Smrg size_t to_write); 1777ec681f3Smrg 1787ec681f3Smrg/** 1797ec681f3Smrg * Add a uint8_t to a blob. 1807ec681f3Smrg * 1817ec681f3Smrg * \return True unless allocation failed. 1827ec681f3Smrg */ 1837ec681f3Smrgbool 1847ec681f3Smrgblob_write_uint8(struct blob *blob, uint8_t value); 1857ec681f3Smrg 1867ec681f3Smrg/** 1877ec681f3Smrg * Overwrite a uint8_t previously written to the blob. 1887ec681f3Smrg * 1897ec681f3Smrg * Writes a uint8_t value to an existing portion of the blob at an offset of 1907ec681f3Smrg * \offset. This data range must have previously been written to the blob by 1917ec681f3Smrg * one of the blob_write_* calls. 1927ec681f3Smrg * 1937ec681f3Smrg * \return True unless the requested position or position+to_write lie outside 1947ec681f3Smrg * the current blob's size. 1957ec681f3Smrg */ 1967ec681f3Smrgbool 1977ec681f3Smrgblob_overwrite_uint8(struct blob *blob, 1987ec681f3Smrg size_t offset, 1997ec681f3Smrg uint8_t value); 2007ec681f3Smrg 2017ec681f3Smrg/** 2027ec681f3Smrg * Add a uint16_t to a blob. 2037ec681f3Smrg * 2047ec681f3Smrg * \note This function will only write to a uint16_t-aligned offset from the 2057ec681f3Smrg * beginning of the blob's data, so some padding bytes may be added to the 2067ec681f3Smrg * blob if this write follows some unaligned write (such as 2077ec681f3Smrg * blob_write_string). 2087ec681f3Smrg * 2097ec681f3Smrg * \return True unless allocation failed. 2107ec681f3Smrg */ 2117ec681f3Smrgbool 2127ec681f3Smrgblob_write_uint16(struct blob *blob, uint16_t value); 2137ec681f3Smrg 2147ec681f3Smrg/** 2157ec681f3Smrg * Add a uint32_t to a blob. 2167ec681f3Smrg * 2177ec681f3Smrg * \note This function will only write to a uint32_t-aligned offset from the 2187ec681f3Smrg * beginning of the blob's data, so some padding bytes may be added to the 2197ec681f3Smrg * blob if this write follows some unaligned write (such as 2207ec681f3Smrg * blob_write_string). 2217ec681f3Smrg * 2227ec681f3Smrg * \return True unless allocation failed. 2237ec681f3Smrg */ 2247ec681f3Smrgbool 2257ec681f3Smrgblob_write_uint32(struct blob *blob, uint32_t value); 2267ec681f3Smrg 2277ec681f3Smrg/** 2287ec681f3Smrg * Overwrite a uint32_t previously written to the blob. 2297ec681f3Smrg * 2307ec681f3Smrg * Writes a uint32_t value to an existing portion of the blob at an offset of 2317ec681f3Smrg * \offset. This data range must have previously been written to the blob by 2327ec681f3Smrg * one of the blob_write_* calls. 2337ec681f3Smrg * 2347ec681f3Smrg * 2357ec681f3Smrg * The expected usage is something like the following pattern: 2367ec681f3Smrg * 2377ec681f3Smrg * size_t offset; 2387ec681f3Smrg * 2397ec681f3Smrg * offset = blob_reserve_uint32(blob); 2407ec681f3Smrg * ... various blob write calls, writing N items ... 2417ec681f3Smrg * blob_overwrite_uint32 (blob, offset, N); 2427ec681f3Smrg * 2437ec681f3Smrg * \return True unless the requested position or position+to_write lie outside 2447ec681f3Smrg * the current blob's size. 2457ec681f3Smrg */ 2467ec681f3Smrgbool 2477ec681f3Smrgblob_overwrite_uint32(struct blob *blob, 2487ec681f3Smrg size_t offset, 2497ec681f3Smrg uint32_t value); 2507ec681f3Smrg 2517ec681f3Smrg/** 2527ec681f3Smrg * Add a uint64_t to a blob. 2537ec681f3Smrg * 2547ec681f3Smrg * \note This function will only write to a uint64_t-aligned offset from the 2557ec681f3Smrg * beginning of the blob's data, so some padding bytes may be added to the 2567ec681f3Smrg * blob if this write follows some unaligned write (such as 2577ec681f3Smrg * blob_write_string). 2587ec681f3Smrg * 2597ec681f3Smrg * \return True unless allocation failed. 2607ec681f3Smrg */ 2617ec681f3Smrgbool 2627ec681f3Smrgblob_write_uint64(struct blob *blob, uint64_t value); 2637ec681f3Smrg 2647ec681f3Smrg/** 2657ec681f3Smrg * Add an intptr_t to a blob. 2667ec681f3Smrg * 2677ec681f3Smrg * \note This function will only write to an intptr_t-aligned offset from the 2687ec681f3Smrg * beginning of the blob's data, so some padding bytes may be added to the 2697ec681f3Smrg * blob if this write follows some unaligned write (such as 2707ec681f3Smrg * blob_write_string). 2717ec681f3Smrg * 2727ec681f3Smrg * \return True unless allocation failed. 2737ec681f3Smrg */ 2747ec681f3Smrgbool 2757ec681f3Smrgblob_write_intptr(struct blob *blob, intptr_t value); 2767ec681f3Smrg 2777ec681f3Smrg/** 2787ec681f3Smrg * Overwrite an intptr_t previously written to the blob. 2797ec681f3Smrg * 2807ec681f3Smrg * Writes a intptr_t value to an existing portion of the blob at an offset of 2817ec681f3Smrg * \offset. This data range must have previously been written to the blob by 2827ec681f3Smrg * one of the blob_write_* calls. 2837ec681f3Smrg * 2847ec681f3Smrg * For example usage, see blob_overwrite_uint32 2857ec681f3Smrg * 2867ec681f3Smrg * \return True unless the requested position or position+to_write lie outside 2877ec681f3Smrg * the current blob's size. 2887ec681f3Smrg */ 2897ec681f3Smrgbool 2907ec681f3Smrgblob_overwrite_intptr(struct blob *blob, 2917ec681f3Smrg size_t offset, 2927ec681f3Smrg intptr_t value); 2937ec681f3Smrg 2947ec681f3Smrg/** 2957ec681f3Smrg * Add a NULL-terminated string to a blob, (including the NULL terminator). 2967ec681f3Smrg * 2977ec681f3Smrg * \return True unless allocation failed. 2987ec681f3Smrg */ 2997ec681f3Smrgbool 3007ec681f3Smrgblob_write_string(struct blob *blob, const char *str); 3017ec681f3Smrg 3027ec681f3Smrg/** 3037ec681f3Smrg * Start reading a blob, (initializing the contents of \blob for reading). 3047ec681f3Smrg * 3057ec681f3Smrg * After this call, the caller can use the various blob_read_* functions to 3067ec681f3Smrg * read elements from the data array. 3077ec681f3Smrg * 3087ec681f3Smrg * For all of the blob_read_* functions, if there is insufficient data 3097ec681f3Smrg * remaining, the functions will do nothing, (perhaps returning default values 3107ec681f3Smrg * such as 0). The caller can detect this by noting that the blob_reader's 3117ec681f3Smrg * current value is unchanged before and after the call. 3127ec681f3Smrg */ 3137ec681f3Smrgvoid 3147ec681f3Smrgblob_reader_init(struct blob_reader *blob, const void *data, size_t size); 3157ec681f3Smrg 3167ec681f3Smrg/** 3177ec681f3Smrg * Read some unstructured, fixed-size data from the current location, (and 3187ec681f3Smrg * update the current location to just past this data). 3197ec681f3Smrg * 3207ec681f3Smrg * \note The memory returned belongs to the data underlying the blob reader. The 3217ec681f3Smrg * caller must copy the data in order to use it after the lifetime of the data 3227ec681f3Smrg * underlying the blob reader. 3237ec681f3Smrg * 3247ec681f3Smrg * \return The bytes read (see note above about memory lifetime). 3257ec681f3Smrg */ 3267ec681f3Smrgconst void * 3277ec681f3Smrgblob_read_bytes(struct blob_reader *blob, size_t size); 3287ec681f3Smrg 3297ec681f3Smrg/** 3307ec681f3Smrg * Read some unstructured, fixed-size data from the current location, copying 3317ec681f3Smrg * it to \dest (and update the current location to just past this data) 3327ec681f3Smrg */ 3337ec681f3Smrgvoid 3347ec681f3Smrgblob_copy_bytes(struct blob_reader *blob, void *dest, size_t size); 3357ec681f3Smrg 3367ec681f3Smrg/** 3377ec681f3Smrg * Skip \size bytes within the blob. 3387ec681f3Smrg */ 3397ec681f3Smrgvoid 3407ec681f3Smrgblob_skip_bytes(struct blob_reader *blob, size_t size); 3417ec681f3Smrg 3427ec681f3Smrg/** 3437ec681f3Smrg * Read a uint8_t from the current location, (and update the current location 3447ec681f3Smrg * to just past this uint8_t). 3457ec681f3Smrg * 3467ec681f3Smrg * \return The uint8_t read 3477ec681f3Smrg */ 3487ec681f3Smrguint8_t 3497ec681f3Smrgblob_read_uint8(struct blob_reader *blob); 3507ec681f3Smrg 3517ec681f3Smrg/** 3527ec681f3Smrg * Read a uint16_t from the current location, (and update the current location 3537ec681f3Smrg * to just past this uint16_t). 3547ec681f3Smrg * 3557ec681f3Smrg * \note This function will only read from a uint16_t-aligned offset from the 3567ec681f3Smrg * beginning of the blob's data, so some padding bytes may be skipped. 3577ec681f3Smrg * 3587ec681f3Smrg * \return The uint16_t read 3597ec681f3Smrg */ 3607ec681f3Smrguint16_t 3617ec681f3Smrgblob_read_uint16(struct blob_reader *blob); 3627ec681f3Smrg 3637ec681f3Smrg/** 3647ec681f3Smrg * Read a uint32_t from the current location, (and update the current location 3657ec681f3Smrg * to just past this uint32_t). 3667ec681f3Smrg * 3677ec681f3Smrg * \note This function will only read from a uint32_t-aligned offset from the 3687ec681f3Smrg * beginning of the blob's data, so some padding bytes may be skipped. 3697ec681f3Smrg * 3707ec681f3Smrg * \return The uint32_t read 3717ec681f3Smrg */ 3727ec681f3Smrguint32_t 3737ec681f3Smrgblob_read_uint32(struct blob_reader *blob); 3747ec681f3Smrg 3757ec681f3Smrg/** 3767ec681f3Smrg * Read a uint64_t from the current location, (and update the current location 3777ec681f3Smrg * to just past this uint64_t). 3787ec681f3Smrg * 3797ec681f3Smrg * \note This function will only read from a uint64_t-aligned offset from the 3807ec681f3Smrg * beginning of the blob's data, so some padding bytes may be skipped. 3817ec681f3Smrg * 3827ec681f3Smrg * \return The uint64_t read 3837ec681f3Smrg */ 3847ec681f3Smrguint64_t 3857ec681f3Smrgblob_read_uint64(struct blob_reader *blob); 3867ec681f3Smrg 3877ec681f3Smrg/** 3887ec681f3Smrg * Read an intptr_t value from the current location, (and update the 3897ec681f3Smrg * current location to just past this intptr_t). 3907ec681f3Smrg * 3917ec681f3Smrg * \note This function will only read from an intptr_t-aligned offset from the 3927ec681f3Smrg * beginning of the blob's data, so some padding bytes may be skipped. 3937ec681f3Smrg * 3947ec681f3Smrg * \return The intptr_t read 3957ec681f3Smrg */ 3967ec681f3Smrgintptr_t 3977ec681f3Smrgblob_read_intptr(struct blob_reader *blob); 3987ec681f3Smrg 3997ec681f3Smrg/** 4007ec681f3Smrg * Read a NULL-terminated string from the current location, (and update the 4017ec681f3Smrg * current location to just past this string). 4027ec681f3Smrg * 4037ec681f3Smrg * \note The memory returned belongs to the data underlying the blob reader. The 4047ec681f3Smrg * caller must copy the string in order to use the string after the lifetime 4057ec681f3Smrg * of the data underlying the blob reader. 4067ec681f3Smrg * 4077ec681f3Smrg * \return The string read (see note above about memory lifetime). However, if 4087ec681f3Smrg * there is no NULL byte remaining within the blob, this function returns 4097ec681f3Smrg * NULL. 4107ec681f3Smrg */ 4117ec681f3Smrgchar * 4127ec681f3Smrgblob_read_string(struct blob_reader *blob); 4137ec681f3Smrg 4147ec681f3Smrg#ifdef __cplusplus 4157ec681f3Smrg} 4167ec681f3Smrg#endif 4177ec681f3Smrg 4187ec681f3Smrg#endif /* BLOB_H */ 419