diff options
-rw-r--r-- | rt_struct.c | 49 | ||||
-rw-r--r-- | rt_struct.h | 123 |
2 files changed, 172 insertions, 0 deletions
diff --git a/rt_struct.c b/rt_struct.c new file mode 100644 index 0000000..314407c --- /dev/null +++ b/rt_struct.c @@ -0,0 +1,49 @@ +#include <stdlib.h> +#include <string.h> +#include "macros.h" +#include "rt_struct.h" + +static int is_root_type(rts_type_tag tag) { + return tag != TAG_STRUCT && tag != TAG_UNION; +} + +int create_rts(rts_type *type) { + if (type == NULL) { + return 1; + } + + if (is_root_type(type->tag)) { + return 0; + } + + if (type->members == NULL || type->members[0] == NULL) { + return 1; + } else { + size_t offset = 0; + size_t max_align = 0; + size_t remainder = 0; + size_t padding = 0; + rts_member **members = type->members; + for (int i = 0; members[i] != NULL; ++i) { + rts_type *member_type = members[i]->type; + if (create_rts(member_type)) { + return 1; + } else { + const size_t align = member_type->alignment; + max_align = max(max_align, align); + if (type->tag == TAG_STRUCT) { + remainder = offset % align; + padding = (remainder) ? align - remainder : 0; + offset += padding; + type->offsets[i] = offset; + offset += member_type->size; + } + } + } + type->alignment = max_align; + remainder = offset % max_align; + padding = (remainder) ? max_align - remainder : 0; + type->size = offset + padding; + return 0; + } +} diff --git a/rt_struct.h b/rt_struct.h new file mode 100644 index 0000000..b1ccd5f --- /dev/null +++ b/rt_struct.h @@ -0,0 +1,123 @@ +#ifndef RT_STRUCT_H +#define RT_STRUCT_H + +#include <stddef.h> +#include <stdint.h> +#include <time.h> + +typedef enum rts_type_tag rts_type_tag; +typedef struct rts_type rts_type; +typedef struct rts_member rts_member; + +enum rts_type_tag { + TAG_UINT, + TAG_SINT, + TAG_INT = TAG_SINT, + TAG_UCHAR, + TAG_SCHAR, + TAG_CHAR, + TAG_USHORT, + TAG_SSHORT, + TAG_SHORT = TAG_SSHORT, + TAG_ULONG, + TAG_SLONG, + TAG_LONG = TAG_SLONG, + TAG_ULONGLONG, + TAG_SLONGLONG, + TAG_LONGLONG = TAG_SLONGLONG, + TAG_FLOAT, + TAG_DOUBLE, + TAG_LONGDOUBLE, + TAG_TIME, + TAG_SIZE, + TAG_UINT8, + TAG_INT8, + TAG_UINT16, + TAG_INT16, + TAG_UINT32, + TAG_INT32, + TAG_UINT64, + TAG_INT64, + TAG_POINTER, + TAG_STRUCT, + TAG_UNION, + NUM_TAG +}; + +struct rts_type { + rts_type_tag tag; /* Type Tag. */ + char *name; /* Name of type. */ + int is_packed; /* Packed type flag. */ + size_t alignment; /* Alignment of type. */ + size_t size; /* Size of type. */ + rts_member **members; /* Member(s) of type. */ + size_t *offsets; /* Offset(s) of type. */ +}; + +struct rts_member { + char *name; /* Name of member. */ + int ptr_count; /* Pointer count of member. */ + int arr_count; /* Array dimension count of member. */ + rts_type *type; /* Type of member. */ +}; + +#define TYPEDEF_RTS(name, type) \ + struct _align_##name { \ + char c; \ + type x; \ + }; \ + static const rts_type RTS_TYPE_##name = { \ + TAG_##name, \ + NULL, \ + 0, \ + offsetof(struct _align_##name, x), \ + sizeof(type), \ + NULL, NULL \ + } \ + +TYPEDEF_RTS(UINT, unsigned int); +TYPEDEF_RTS(SINT, signed int); +TYPEDEF_RTS(INT, int); + +TYPEDEF_RTS(UCHAR, unsigned char); +TYPEDEF_RTS(SCHAR, signed char); +TYPEDEF_RTS(CHAR, char); + +TYPEDEF_RTS(USHORT, unsigned short); +TYPEDEF_RTS(SSHORT, signed short); +TYPEDEF_RTS(SHORT, short); + +TYPEDEF_RTS(ULONG, unsigned long); +TYPEDEF_RTS(SLONG, signed long); +TYPEDEF_RTS(LONG, long); + +TYPEDEF_RTS(ULONGLONG, unsigned long long); +TYPEDEF_RTS(SLONGLONG, signed long long); +TYPEDEF_RTS(LONGLONG, long long); + +TYPEDEF_RTS(FLOAT, float); +TYPEDEF_RTS(DOUBLE, double); +TYPEDEF_RTS(LONGDOUBLE, long double); + +TYPEDEF_RTS(TIME, time_t); +TYPEDEF_RTS(SIZE, size_t); + +TYPEDEF_RTS(UINT8, uint8_t); +TYPEDEF_RTS(INT8, int8_t); + +TYPEDEF_RTS(UINT16, uint16_t); +TYPEDEF_RTS(INT16, int16_t); + +TYPEDEF_RTS(UINT32, uint32_t); +TYPEDEF_RTS(INT32, int32_t); + +TYPEDEF_RTS(UINT64, uint64_t); +TYPEDEF_RTS(INT64, int64_t); + +TYPEDEF_RTS(POINTER, void *); + +#undef TYPEDEF_RTS + +extern int create_rts(rts_type *type); + +#endif |