packages feed

data-layout-0.1.0.0: cbits/layout.c

#include <stdint.h>

#define id(n) (n)

#define bswap32 __builtin_bswap32
#define bswap64 __builtin_bswap64

/*
 * Unfortunately GCC does not have a __builtin_bswap16, but
 * this should compile to pretty good assembly.
 */
inline static uint16_t bswap16(uint16_t n)
{
    return (n >> 8) | (n << 8);
}

/*
 * Defines an encode/decode case for the specified type
 * and byte order.
 *
 * enc    The memory area (src or dst) which contains or will
 *        contain the encoded data. During encoding this will
 *        be 'dst' and during decoding this will be 'src'.
 *
 * type   The type of the values to copy.
 *
 * bswap  The function to use to swap the byte order. Pass
 *        the identity function if no byte swapping is
 *        required.
 */
#define CASE(_enc,_type,_bswap)                            \
case sizeof (_type):                                       \
    /* repeat 'num_reps' times */                          \
    for (r = 0; r < num_reps; ++r) {                       \
        /* skip 'offsets[0]' bytes */                      \
        _enc += offsets[0];                                \
        for (o = 1; o < num_offsets; ++o) {                \
            /* copy 'num_values * sizeof (_type)' bytes */ \
            for (v = 0; v < num_values; v++) {             \
                *(_type *)dst = _bswap(*(_type *)src);     \
                dst += sizeof (_type);                     \
                src += sizeof (_type);                     \
            }                                              \
            /* skip 'offsets[o]' bytes */                  \
            _enc += offsets[o];                            \
        }                                                  \
    }                                                      \
break;

#define OK    0
#define ERROR 1

/*
 * data_layout_encode / data_layout_decode
 *
 * Copies data from the second memory area (source) into the first
 * memory area (destination) using the specified operations.
 *
 * dst          destination memory area
 * src          source memory area
 * num_reps     number of times to repeat the decode
 * num_offsets  number of skip operations in 'offsets'
 * offsets      list with number of bytes to skip in between each copy
 * num_values   number of values to copy in between each skip
 * value_size   size of a single value in bytes
 * swap_bytes   non-zero to swap the byte order of values
 *
 * Returns zero on success, non-zero otherwise.
 */

#define CODEC_FN(_name,_enc)                               \
int data_layout_##_name                                    \
    ( char *dst                                            \
    , char *src                                            \
    , int num_reps                                         \
    , int num_offsets                                      \
    , int *offsets                                         \
    , int num_values                                       \
    , int value_size                                       \
    , int swap_bytes                                       \
    )                                                      \
{                                                          \
    int r, o, v;                                           \
                                                           \
    if (swap_bytes) {                                      \
        switch (value_size) {                              \
            CASE (_enc, uint64_t, bswap64);                \
            CASE (_enc, uint32_t, bswap32);                \
            CASE (_enc, uint16_t, bswap16);                \
            CASE (_enc, uint8_t,  id);                     \
            default: return ERROR;                         \
        }                                                  \
    } else {                                               \
        switch (value_size) {                              \
            CASE (_enc, uint64_t, id);                     \
            CASE (_enc, uint32_t, id);                     \
            CASE (_enc, uint16_t, id);                     \
            CASE (_enc, uint8_t,  id);                     \
            default: return ERROR;                         \
        }                                                  \
    }                                                      \
                                                           \
    return OK;                                             \
}

CODEC_FN (encode, dst)
CODEC_FN (decode, src)