I have a Destination pointer stored in void* DestPointer
and a source pointer stored in void* SrcPointer
. Assume the destination pointer, points to starting adress of the free and safe memory and source pointer points to the starting adress of memory containing data it's type may be int16_t or int32_t) but can be interfered with counter i
. Now I want to fill the memory by :
*(uint16_t*)DestPointer=*(uint16_t*) SrcPointer
I want this uint8_t change according to i, it could be a bounus if the stated problem generalizer to something like.
i==-1 -> int8_t
i==-2 -> int16_t
i==-4 -> int32_t
i==1 -> uint8_t
i==2 -> uint16_t
i==4 -> uint32_t
How to implement it? I just know enumeration can't work maybe some macro or magical c expression help.
It seems I need to implement memcpy() in a specific way!
Those strange indices aren't very helpful - it would have been much easier with adjacent numbers 0,1,2... So the best thing to do is to get rid of those negative numbers. Another good option would be to pick the copy size based on type with _Generic
.
Otherwise assuming you can't change those index numbers... When dealing with bad interfaces that you are stuck with and can't change, X-macros might often be an ok solution. Something like this:
#define INT_TYPES(X) \
/* type val */ \
X(int8_t, -1) \
X(int16_t, -2) \
X(int32_t, -4) \
X(uint8_t, 1) \
X(uint16_t, 2) \
X(uint32_t, 4) \
Then create an enum eint8_t = -1
, eint16_t = -2
and so on:
typedef enum
{
#define INT_TYPE_ENUM(type, val) e##type = (val),
INT_TYPES(INT_TYPE_ENUM)
} int_t;
Then a look-up table to compensate for the negative indices. This is using designated initializers so we get for example index [4 + -4] = sizeof(int32_t)
:
#define lookup_offset 4
const size_t int_type_lookup[] =
{
#define INT_TYPE_SIZE(type, val) [lookup_offset+(val)] = sizeof(type),
INT_TYPES(INT_TYPE_SIZE)
};
(Similarly you could make a function pointer look-up table which might be handy in some cases.)
The copy function which is a wrapper around memcpy
:
void intcpy (void* restrict dst,
const void* restrict src,
size_t n,
int_t type)
{
memcpy(dst,src, n*int_type_lookup[lookup_offset + type]);
}
Complete example:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define INT_TYPES(X) \
/* type val */ \
X(int8_t, -1) \
X(int16_t, -2) \
X(int32_t, -4) \
X(uint8_t, 1) \
X(uint16_t, 2) \
X(uint32_t, 4) \
typedef enum
{
#define INT_TYPE_ENUM(type, val) e##type = (val),
INT_TYPES(INT_TYPE_ENUM)
} int_t;
void intcpy (void* restrict dst,
const void* restrict src,
size_t n,
int_t type)
{
#define lookup_offset 4
const size_t int_type_lookup[] =
{
#define INT_TYPE_SIZE(type, val) [lookup_offset+(val)] = sizeof(type),
INT_TYPES(INT_TYPE_SIZE)
};
memcpy(dst,src, n*int_type_lookup[lookup_offset + type]);
}
int main (void)
{
int16_t some_data [50]={1,2,3,4,5};
int16_t dst[50];
intcpy(dst, some_data, 50, eint16_t);
for(size_t i=0; i<5; i++)
{
printf("%d ", (int)dst[i]);
}
return 0;
}