I'm reading a binary file where one of the bytes defines a type of data.
Typically:
0x13 => FOO
0x14 => BAR
But, as it is, there can be multiple definitions of same type, then real type is defined elsewhere, but it is not always accessible. Therefore I would like to print all possibilities if no sub specification is defined.
E.g.:
0x13 => FOO
0x14 => BAR
0x14 => BAZ <-- also "type" 0x14
0x15 => XEN
To store the type definitions and descriptions I have a struct in the format of:
struct data_def {
char id;
char *name;
char *desc;
...
};
If it was possible I would have had an array as in:
static const struct data_def data_db[][] = {
...
} /* index 0x13 */
{0x13, "FOO", "This is foo", ...}
}, /* index 0x14 */
{0x14, "BAR", "This is bar", ...},
{0x14, "BAZ", "This is baz", ...}
}, /* index 0x15 */
{0x15, "XEN", "This is xen", ...}
}
}
In order so that data_db[0x14][1].name == BAZ, etc.
But AFAIK this is not possible. Or is it? (C89).
I am looking for another way to do it. Was thinking of something like this:
static const struct data_def data_db[] = {
...
{0x13, "FOO", "This is foo", ...},
{0x14, "BAR", "This is bar", ...},
{0x14, "BAZ", "This is baz", ...},
{0x15, "XEN", "This is xen", ...}
}
And then have a lookup table as in where each first entry starts. This could
off course also be dynamically created by looping data_db, but would rather
have it statically defined (I think – I haven't decided):
static const char data_index[] {
...
0x20, /* at index 0x13 of data_index */
0x21, /* at index 0x14 of data_index */
0x23, /* at index 0x15 of data_index */
}
Giving that one could print, (or other), by doing e.g.:
while (data_db[data_index[0x14 + i]].id == 0x14) {
print data_db[data_index[0x14 + i]].name
++i
}
Is there a better way to solve this? I imagine this is something that has been done a billion times before with similar scenarios. I would rather not use any libraries outside of the standard library as this eventually is only a small part of the program and the rest of the code is "free" of that as well.
This is just a shot in the dark, but if the number of types within an identifier group has an upper bound and if you can utilize a value that you know will not be one of your types, you could do something like this:
#define MAX_NUM_TYPES 3
#define INVALID_TYPE 0xff
struct Data_Def{
unsigned char id;
char * name;
char * desc;
};
static const struct Data_Def data_db[][MAX_NUM_TYPES] = {
.
.
.
{ /* Index 0x13 */
/* id name desc */
{ 0x13, "FOO", "This is foo" },
{ 0x13, "BAR", "This is bar" },
{ INVALID_TYPE, NULL, NULL },
},
{ /* Index 0x14 */
/* id name desc */
{ 0x14, "BAZ", "This is baz" },
{ INVALID_TYPE, NULL, NULL },
{ INVALID_TYPE, NULL, NULL },
},
};
And if you want to print...
unsigned char index = 0;
/* Print all types within a group with id 0x13. */
while ((data_db[0x13][index].id != INVALID_TYPE) && (index < MAX_NUM_TYPES))
{
printf("%s", data_db[0x13][index].name);
index++;
}
This may not work at all for what you're trying to accomplish and depending on the number of types per group, it may be a complete waste of code space. However, it is one way of attacking the problem.
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With