cutil/struct.c

90 lines
2.3 KiB
C

#include "struct.h"
#include "cutil.h"
union intvalue_u {
u8 int8;
u16 int16;
u32 int32;
u64 int64;
};
uint value_size(struct cu_struct_s* st, uint idx, const void* in)
{
struct cu_value_s* value = &st->members[idx];
switch (value->type)
{
case NoValue: return 0;
case Sequence: return value->sequence.size;
case Array: return value_array_size(st, idx, in);
case Int8: return VALUE_INT8_SIZE;
case Int16: return VALUE_INT16_SIZE;
case Int32: return VALUE_INT32_SIZE;
case Int64: return VALUE_INT64_SIZE;
default: return 0;
}
}
uint value_offset(struct cu_struct_s* st, uint idx, const void* in)
{
uint offset = 0;
while (idx--) offset += value_size(st, idx, in);
return offset;
}
void value_get(struct cu_struct_s* st, uint idx, const void* in, void* out)
{
uint size = value_size(st, idx, in);
uint offset = value_offset(st, idx, in);
struct cu_value_s* value = &st->members[idx];
union intvalue_u* data = (union intvalue_u*)out;
if (size) cu_memcpy(out, in + offset, size);
else return;
if (st->endian != cu_endian)
{
switch (value->type)
{
case Int8: break;
case Int16: data->int16 = cu_bswap16(data->int16); break;
case Int32: data->int32 = cu_bswap32(data->int32); break;
case Int64: data->int64 = cu_bswap64(data->int64); break;
}
}
}
uint value_array_size(struct cu_struct_s* st, uint idx, const void* in)
{
union intvalue_u count = {0};
struct cu_value_s* value = &st->members[idx];
if (value->array.index)
{
if (value->array.count != idx)
value_get(st, value->array.count, in, &count);
}
else if (value->array.count)
{
count.int32 = value->array.count;
}
else
{
const u8* items = (const u8*)in + value_offset(st, idx, in);
uint size = value->array.item;
while (cu_memtest(items, size))
{
items += size;
count.int32++;
}
}
return value->array.item * count.int32;
}
uint struct_size(struct cu_struct_s* st, const void* in)
{
uint idx = 0;
struct cu_value_s* value = st->members;
while ((value++)->type != NoValue) idx++;
return value_offset(st, idx, in);
}