Home | History | Annotate | Download | only in glsl
      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 #pragma once
     25 #ifndef BLOB_H
     26 #define BLOB_H
     27 
     28 #ifdef __cplusplus
     29 extern "C" {
     30 #endif
     31 
     32 #include <stdbool.h>
     33 #include <stddef.h>
     34 #include <stdint.h>
     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. */
     51    uint8_t *data;
     52 
     53    /** Number of bytes that have been allocated for \c data. */
     54    size_t allocated;
     55 
     56    /** The number of bytes that have actual data written to them. */
     57    size_t size;
     58 };
     59 
     60 /* When done reading, the caller can ensure that everything was consumed by
     61  * checking the following:
     62  *
     63  *   1. blob->current should be equal to blob->end, (if not, too little was
     64  *      read).
     65  *
     66  *   2. blob->overrun should be false, (otherwise, too much was read).
     67  */
     68 struct blob_reader {
     69    uint8_t *data;
     70    uint8_t *end;
     71    uint8_t *current;
     72    bool overrun;
     73 };
     74 
     75 /**
     76  * Create a new, empty blob, belonging to \mem_ctx.
     77  *
     78  * \return The new blob, (or NULL in case of allocation failure).
     79  */
     80 struct blob *
     81 blob_create (void *mem_ctx);
     82 
     83 /**
     84  * Add some unstructured, fixed-size data to a blob.
     85  *
     86  * \return True unless allocation failed.
     87  */
     88 bool
     89 blob_write_bytes (struct blob *blob, const void *bytes, size_t to_write);
     90 
     91 /**
     92  * Reserve space in \blob for a number of bytes.
     93  *
     94  * Space will be allocated within the blob for these byes, but the bytes will
     95  * be left uninitialized. The caller is expected to use the return value to
     96  * write directly (and immediately) to these bytes.
     97  *
     98  * \note The return value is valid immediately upon return, but can be
     99  * invalidated by any other call to a blob function. So the caller should call
    100  * blob_reserve_byes immediately before writing through the returned pointer.
    101  *
    102  * This function is intended to be used when interfacing with an existing API
    103  * that is not aware of the blob API, (so that blob_write_bytes cannot be
    104  * called).
    105  *
    106  * \return A pointer to space allocated within \blob to which \to_write bytes
    107  * can be written, (or NULL in case of any allocation error).
    108  */
    109 uint8_t *
    110 blob_reserve_bytes (struct blob *blob, size_t to_write);
    111 
    112 /**
    113  * Overwrite some data previously written to the blob.
    114  *
    115  * Writes data to an existing portion of the blob at an offset of \offset.
    116  * This data range must have previously been written to the blob by one of the
    117  * blob_write_* calls.
    118  *
    119  * For example usage, see blob_overwrite_uint32
    120  *
    121  * \return True unless the requested offset or offset+to_write lie outside
    122  * the current blob's size.
    123  */
    124 bool
    125 blob_overwrite_bytes (struct blob *blob,
    126                       size_t offset,
    127                       const void *bytes,
    128                       size_t to_write);
    129 
    130 /**
    131  * Add a uint32_t to a blob.
    132  *
    133  * \note This function will only write to a uint32_t-aligned offset from the
    134  * beginning of the blob's data, so some padding bytes may be added to the
    135  * blob if this write follows some unaligned write (such as
    136  * blob_write_string).
    137  *
    138  * \return True unless allocation failed.
    139  */
    140 bool
    141 blob_write_uint32 (struct blob *blob, uint32_t value);
    142 
    143 /**
    144  * Overwrite a uint32_t previously written to the blob.
    145  *
    146  * Writes a uint32_t value to an existing portion of the blob at an offset of
    147  * \offset.  This data range must have previously been written to the blob by
    148  * one of the blob_write_* calls.
    149  *
    150  *
    151  * The expected usage is something like the following pattern:
    152  *
    153  *	size_t offset;
    154  *
    155  *	offset = blob->size;
    156  *	blob_write_uint32 (blob, 0); // placeholder
    157  *	... various blob write calls, writing N items ...
    158  *	blob_overwrite_uint32 (blob, offset, N);
    159  *
    160  * \return True unless the requested position or position+to_write lie outside
    161  * the current blob's size.
    162  */
    163 bool
    164 blob_overwrite_uint32 (struct blob *blob,
    165                        size_t offset,
    166                        uint32_t value);
    167 
    168 /**
    169  * Add a uint64_t to a blob.
    170  *
    171  * \note This function will only write to a uint64_t-aligned offset from the
    172  * beginning of the blob's data, so some padding bytes may be added to the
    173  * blob if this write follows some unaligned write (such as
    174  * blob_write_string).
    175  *
    176  * \return True unless allocation failed.
    177  */
    178 bool
    179 blob_write_uint64 (struct blob *blob, uint64_t value);
    180 
    181 /**
    182  * Add an intptr_t to a blob.
    183  *
    184  * \note This function will only write to an intptr_t-aligned offset from the
    185  * beginning of the blob's data, so some padding bytes may be added to the
    186  * blob if this write follows some unaligned write (such as
    187  * blob_write_string).
    188  *
    189  * \return True unless allocation failed.
    190  */
    191 bool
    192 blob_write_intptr (struct blob *blob, intptr_t value);
    193 
    194 /**
    195  * Add a NULL-terminated string to a blob, (including the NULL terminator).
    196  *
    197  * \return True unless allocation failed.
    198  */
    199 bool
    200 blob_write_string (struct blob *blob, const char *str);
    201 
    202 /**
    203  * Start reading a blob, (initializing the contents of \blob for reading).
    204  *
    205  * After this call, the caller can use the various blob_read_* functions to
    206  * read elements from the data array.
    207  *
    208  * For all of the blob_read_* functions, if there is insufficient data
    209  * remaining, the functions will do nothing, (perhaps returning default values
    210  * such as 0). The caller can detect this by noting that the blob_reader's
    211  * current value is unchanged before and after the call.
    212  */
    213 void
    214 blob_reader_init (struct blob_reader *blob, uint8_t *data, size_t size);
    215 
    216 /**
    217  * Read some unstructured, fixed-size data from the current location, (and
    218  * update the current location to just past this data).
    219  *
    220  * \note The memory returned belongs to the data underlying the blob reader. The
    221  * caller must copy the data in order to use it after the lifetime of the data
    222  * underlying the blob reader.
    223  *
    224  * \return The bytes read (see note above about memory lifetime).
    225  */
    226 void *
    227 blob_read_bytes (struct blob_reader *blob, size_t size);
    228 
    229 /**
    230  * Read some unstructured, fixed-size data from the current location, copying
    231  * it to \dest (and update the current location to just past this data)
    232  */
    233 void
    234 blob_copy_bytes (struct blob_reader *blob, uint8_t *dest, size_t size);
    235 
    236 /**
    237  * Read a uint32_t from the current location, (and update the current location
    238  * to just past this uint32_t).
    239  *
    240  * \note This function will only read from a uint32_t-aligned offset from the
    241  * beginning of the blob's data, so some padding bytes may be skipped.
    242  *
    243  * \return The uint32_t read
    244  */
    245 uint32_t
    246 blob_read_uint32 (struct blob_reader *blob);
    247 
    248 /**
    249  * Read a uint64_t from the current location, (and update the current location
    250  * to just past this uint64_t).
    251  *
    252  * \note This function will only read from a uint64_t-aligned offset from the
    253  * beginning of the blob's data, so some padding bytes may be skipped.
    254  *
    255  * \return The uint64_t read
    256  */
    257 uint64_t
    258 blob_read_uint64 (struct blob_reader *blob);
    259 
    260 /**
    261  * Read an intptr_t value from the current location, (and update the
    262  * current location to just past this intptr_t).
    263  *
    264  * \note This function will only read from an intptr_t-aligned offset from the
    265  * beginning of the blob's data, so some padding bytes may be skipped.
    266  *
    267  * \return The intptr_t read
    268  */
    269 intptr_t
    270 blob_read_intptr (struct blob_reader *blob);
    271 
    272 /**
    273  * Read a NULL-terminated string from the current location, (and update the
    274  * current location to just past this string).
    275  *
    276  * \note The memory returned belongs to the data underlying the blob reader. The
    277  * caller must copy the string in order to use the string after the lifetime
    278  * of the data underlying the blob reader.
    279  *
    280  * \return The string read (see note above about memory lifetime). However, if
    281  * there is no NULL byte remaining within the blob, this function returns
    282  * NULL.
    283  */
    284 char *
    285 blob_read_string (struct blob_reader *blob);
    286 
    287 #ifdef __cplusplus
    288 }
    289 #endif
    290 
    291 #endif /* BLOB_H */
    292