Refactoring; added some utility functions to navigate the type definitions

This commit is contained in:
Alexandre Paillier
2022-03-16 11:59:33 +01:00
parent 3b6c32d707
commit c3dc0c18ff

View File

@@ -51,9 +51,242 @@ typedef enum
uint8_t mem_buffer[SIZE_MEM_BUFFER];
uint16_t mem_idx;
uint8_t *typename_matcher_array;
uint8_t *typenames_array;
uint8_t *structs_array;
uint8_t *current_struct_fields_array;
// Typename matcher masks
#define TYPENAME_MATCHER_ENUM(m) ((m >> 4) & 0xF)
#define TYPENAME_MATCHER_IDX(m) (m & 0xF)
// lib functions
const uint8_t *get_array_in_mem(const uint8_t *ptr, uint8_t *const array_size)
{
*array_size = *ptr;
return (ptr + 1);
}
static inline const uint8_t *get_string_in_mem(const uint8_t *ptr, uint8_t *const string_length)
{
return get_array_in_mem(ptr, string_length);
}
// ptr must point to the beginning of a struct field
uint8_t get_struct_field_typedesc(const uint8_t *ptr)
{
return *ptr;
}
// ptr must point to the beginning of a struct field
bool struct_field_is_array(const uint8_t *ptr)
{
return (get_struct_field_typedesc(ptr) & ARRAY_MASK);
}
// ptr must point to the beginning of a struct field
bool struct_field_has_typesize(const uint8_t *ptr)
{
return (get_struct_field_typedesc(ptr) & TYPESIZE_MASK);
}
// ptr must point to the beginning of a struct field
e_type struct_field_type(const uint8_t *ptr)
{
return (get_struct_field_typedesc(ptr) & TYPE_MASK);
}
// ptr must point to the beginning of a struct field
// TODO: Extra check inside or not
uint8_t get_struct_field_typesize(const uint8_t *ptr)
{
return *(ptr + 1);
}
// ptr must point to the beginning of a struct field
const uint8_t *get_struct_field_custom_typename(const uint8_t *ptr,
uint8_t *const length)
{
ptr += 1; // skip TypeDesc
return get_string_in_mem(ptr, length);
}
// ptr must point to the beginning of a struct field
const uint8_t *get_struct_field_sol_typename(const uint8_t *ptr,
uint8_t *const length)
{
e_type field_type;
uint8_t matcher_count;
const uint8_t *matcher;
uint8_t matcher_idx;
uint8_t typenames_count;
const uint8_t *typename_ptr;
field_type = struct_field_type(ptr);
matcher = get_array_in_mem(typename_matcher_array, &matcher_count);
while (matcher_count-- > 0)
{
if (TYPENAME_MATCHER_ENUM(*matcher) == field_type)
{
matcher_idx = TYPENAME_MATCHER_IDX(*matcher);
typename_ptr = get_array_in_mem(typenames_array, &typenames_count);
// if the index, somehow, can't fit in the typenames array
if ((matcher_idx + 1) > typenames_count) return NULL;
while (typenames_count-- > 0)
{
typename_ptr = get_string_in_mem(typename_ptr, length);
if (matcher_idx-- == 0)
{
return typename_ptr;
}
typename_ptr += *length; // skip this typename, get next one
}
return NULL; // Not found
}
matcher += 1; // get next one
}
return NULL; // Not found
}
// ptr must point to the beginning of a struct field
const uint8_t *get_struct_field_typename(const uint8_t *ptr,
uint8_t *const length)
{
if (struct_field_type(ptr) == TYPE_CUSTOM)
{
return get_struct_field_custom_typename(ptr, length);
}
return get_struct_field_sol_typename(ptr, length);
}
// ptr must point to the beginning of a depth level
e_array_type struct_field_array_depth(const uint8_t *ptr,
uint8_t *const array_size)
{
if (*ptr == ARRAY_FIXED_SIZE)
{
*array_size = *(ptr + 1);
}
return *ptr;
}
// ptr must point to the beginning of a struct field level
const uint8_t *get_next_struct_field_array_lvl(const uint8_t *ptr)
{
switch (*ptr)
{
case ARRAY_DYNAMIC:
break;
case ARRAY_FIXED_SIZE:
ptr += 1;
break;
default:
// should not be in here :^)
break;
}
return ptr + 1;
}
// Skips TypeDesc and TypeSize/Length+TypeName
// Came to be since it is used in multiple functions
// TODO: Find better name
const uint8_t *struct_field_half_skip(const uint8_t *ptr)
{
const uint8_t *field_ptr;
uint8_t size;
field_ptr = ptr;
ptr += 1; // skip TypeDesc
if (struct_field_type(field_ptr) == TYPE_CUSTOM)
{
get_string_in_mem(ptr, &size);
ptr += (1 + size); // skip typename
}
else if (struct_field_has_typesize(field_ptr))
{
ptr += 1; // skip TypeSize
}
return ptr;
}
// ptr must point to the beginning of a struct field
const uint8_t *get_struct_field_array_lvls_array(const uint8_t *ptr,
uint8_t *const length)
{
ptr = struct_field_half_skip(ptr);
return get_array_in_mem(ptr, length);
}
// ptr must point to the beginning of a struct field
const uint8_t *get_struct_field_keyname(const uint8_t *ptr,
uint8_t *const length)
{
const uint8_t *field_ptr;
uint8_t size;
field_ptr = ptr;
ptr = struct_field_half_skip(ptr);
if (struct_field_is_array(field_ptr))
{
ptr = get_array_in_mem(ptr, &size);
while (size-- > 0)
{
ptr = get_next_struct_field_array_lvl(ptr);
}
}
return get_string_in_mem(ptr, length);
}
// ptr must point to the beginning of a struct field
const uint8_t *get_next_struct_field(const uint8_t *ptr)
{
uint8_t length;
ptr = get_struct_field_keyname(ptr, &length);
return (ptr + length);
}
// ptr must point to the beginning of a struct
const uint8_t *get_struct_name(const uint8_t *ptr, uint8_t *const length)
{
return get_string_in_mem(ptr, length);
}
// ptr must point to the beginning of a struct
const uint8_t *get_struct_fields_array(const uint8_t *ptr,
uint8_t *const length)
{
uint8_t name_length;
get_struct_name(ptr, &name_length);
ptr += (1 + name_length); // skip length
return get_array_in_mem(ptr, length);
}
// ptr must point to the beginning of a struct
const uint8_t *get_next_struct(const uint8_t *ptr)
{
uint8_t fields_count;
ptr = get_struct_fields_array(ptr, &fields_count);
while (fields_count-- > 0)
{
ptr = get_next_struct_field(ptr);
}
return ptr;
}
// ptr must point to the size of the structs array
const uint8_t *get_structs_array(const uint8_t *ptr, uint8_t *const length)
{
return get_array_in_mem(ptr, length);
}
//
bool set_struct_name(uint8_t *data)
@@ -133,99 +366,85 @@ bool set_struct_field(uint8_t *data)
return true;
}
void dump_mem(void)
{
uint8_t *mem = structs_array + 1;
uint8_t type_desc;
uint8_t structs_count;
const uint8_t *struct_ptr;
//
uint8_t fields_count;
uint8_t array_depth;
const uint8_t *field_ptr;
//
uint8_t lvls_count;
const uint8_t *lvl_ptr;
for (int i = 0; i < *structs_array; ++i)
const uint8_t *name;
uint8_t name_length;
//
uint8_t array_size;
uint8_t byte_size;
struct_ptr = get_structs_array(structs_array, &structs_count);
while (structs_count-- > 0)
{
fwrite(mem + 1, *mem, sizeof(*mem), stdout);
name = get_struct_name(struct_ptr, &name_length);
fwrite(name, sizeof(*name), name_length, stdout);
printf("(");
mem += (1 + *mem);
fields_count = *mem;
mem += 1;
for (int y = 0; y < fields_count; ++y)
field_ptr = get_struct_fields_array(struct_ptr, &fields_count);
for (int idx = 0; idx < fields_count; ++idx)
{
if (y > 0) printf(",");
type_desc = *mem;
mem += 1;
switch (type_desc & TYPE_MASK)
if (idx > 0) printf(",");
name = get_struct_field_typename(field_ptr, &name_length);
fwrite(name, sizeof(*name), name_length, stdout);
if (struct_field_has_typesize(field_ptr))
{
case TYPE_CUSTOM:
fwrite(mem + 1, *mem, sizeof(*mem), stdout);
mem += (1 + *mem);
if (type_desc & TYPESIZE_MASK) mem += 1;
break;
case TYPE_SOL_UINT:
printf("u");
case TYPE_SOL_INT:
printf("int");
if (type_desc & TYPESIZE_MASK)
{
printf("%d", (*mem * 8));
mem += 1;
}
break;
case TYPE_SOL_ADDRESS:
printf("address");
if (type_desc & TYPESIZE_MASK) mem += 1;
break;
case TYPE_SOL_BOOL:
printf("bool");
if (type_desc & TYPESIZE_MASK) mem += 1;
break;
case TYPE_SOL_STRING:
printf("string");
if (type_desc & TYPESIZE_MASK) mem += 1;
break;
case TYPE_SOL_BYTE:
printf("byte");
if (type_desc & TYPESIZE_MASK) mem += 1;
break;
case TYPE_SOL_BYTES_FIX:
printf("bytes");
if (type_desc & TYPESIZE_MASK)
{
printf("%d", *mem);
mem += 1;
}
break;
case TYPE_SOL_BYTES_DYN:
printf("bytes");
if (type_desc & TYPESIZE_MASK) mem += 1;
break;
default:
// should not be in here :^)
break;
}
if (type_desc & ARRAY_MASK)
{
array_depth = *mem++;
while (array_depth-- > 0)
byte_size = get_struct_field_typesize(field_ptr);
switch(struct_field_type(field_ptr))
{
switch (*mem++)
case TYPE_SOL_INT:
case TYPE_SOL_UINT:
printf("%u", (byte_size * 8));
break;
case TYPE_SOL_BYTES_FIX:
printf("%u", byte_size);
break;
default:
// should not be in here :^)
break;
}
}
if (struct_field_is_array(field_ptr))
{
lvl_ptr = get_struct_field_array_lvls_array(field_ptr, &lvls_count);
while (lvls_count-- > 0)
{
printf("[");
switch (struct_field_array_depth(lvl_ptr, &array_size))
{
case ARRAY_DYNAMIC:
printf("[]");
break;
case ARRAY_FIXED_SIZE:
printf("[%u]", *mem++);
printf("%u", array_size);
break;
default:
// should not be in here :^)
break;
}
printf("]");
lvl_ptr = get_next_struct_field_array_lvl(lvl_ptr);
}
}
printf(" ");
fwrite(mem + 1, *mem, sizeof(*mem), stdout);
mem += (1 + *mem);
name = get_struct_field_keyname(field_ptr, &name_length);
fwrite(name, sizeof(*name), name_length, stdout);
field_ptr = get_next_struct_field(field_ptr);
}
printf(")\n");
struct_ptr = get_next_struct(struct_ptr);
}
return;
}
bool handle_apdu(uint8_t *data)
@@ -255,11 +474,62 @@ bool handle_apdu(uint8_t *data)
return true;
}
bool init_typenames(void)
{
char *typenames_str[] = {
"int",
"uint",
"address",
"bool",
"string",
"byte",
"bytes"
};
// table to match type enums to indexes in the typenames string array
int enum_to_str[][2] = {
{ TYPE_SOL_INT, 0 },
{ TYPE_SOL_UINT, 1},
{ TYPE_SOL_ADDRESS, 2 },
{ TYPE_SOL_BOOL, 3 },
{ TYPE_SOL_STRING, 4 },
{ TYPE_SOL_BYTE, 5 },
{ TYPE_SOL_BYTES_FIX, 6 },
{ TYPE_SOL_BYTES_DYN, 6 }
};
typename_matcher_array = &mem_buffer[mem_idx++];
*typename_matcher_array = 0;
// set matchers
for (size_t i = 0; i < (sizeof(enum_to_str) / sizeof(enum_to_str[0])); ++i)
{
mem_buffer[mem_idx++] = ((enum_to_str[i][0] << 4) | (enum_to_str[i][1]));
// increment array size
*typename_matcher_array += 1;
}
typenames_array = &mem_buffer[mem_idx++];
*typenames_array = 0;
// set typenames
for (size_t i = 0; i < (sizeof(typenames_str) / sizeof(typenames_str[0])); ++i)
{
mem_buffer[mem_idx++] = strlen(typenames_str[i]); // length
// copy typename
memcpy(&mem_buffer[mem_idx], typenames_str[i], mem_buffer[mem_idx - 1]);
// increment mem idx by typename length
mem_idx += mem_buffer[mem_idx - 1];
// increment array size
*typenames_array += 1;
}
return true;
}
void init_heap(void)
{
// init global variables
mem_idx = 0;
init_typenames();
// set types pointer
structs_array = &mem_buffer[mem_idx];