Serializing array of structs containing struct containing array of strings with tpl - c

I've got some code written in C with some fairly substantial structs used to hold data. I wanted to use tpl for serialization/deserialization of struct data for saving and loading the program's data instead of having to write a bunch of code to do it.
My problem is with the tpl_map() function: I can't seem to get it to parse a statement in which it would serialize an array of structs containing a struct containing an array of strings.
tpl's documentation doesn't necessarily say you can do this or that you can't do this. The thing I'd like to serialize would be described by A(S(i$(A(s)A(s)A(s)A(s)iiiiis)sssuussi)), but tpl_map() throws a parse error every time.
These are the relevant struct definitions:
typedef struct y {
char** a;
char** b;
char** c;
char** d;
int e;
int f;
int g;
int h;
int i;
char* j;
} y_t;
typedef struct x {
int a;
y_t y;
char* b;
char* c;
char* d;
unsigned int e;
unsigned int f;
char g[40];
char* h;
unsigned int i;
} x_t;
I'm attempting to serialize an array of x_t.
Chopping down the tpl format string to the minimal possible and working up, I find that it doesn't seem to like having an array inside an inner struct inside an outer struct. More specifically, the problem occurs with the A(i) in A(S($(A(i)))), for instance.
Any thoughts?

Related

Initiliazing int array with pointer type variable

I have the following code.
FlowNProcess f1[3];
int f1resources[2]={-1,0};
f1[1].resoures =f1resources;
typedef struct FlowNProcess
{
int id;
int tt;
int wt;
Requirement *requirement;
int *resoures;
char *state;
} FlowNProcess;
Here since the resources is an int* so, I am first creating an array of size 2 and then
assigning the pointer to it. Is there a better way to achieve the same, maybe a one-liner

How to copy the content of a structure​ in another structure in C

I have a C program where I have two structures
struct one{
int a;
int b;
char *s;
int c;
};
struct two{
int a;
int e;
char *s;
int d;
};
Is possible to write a function that copies the values of the variables with the same type and name from struct one to struct two?
For example, in this case the function should do this
two.a = one.a;
two.s = one.s;
There's no way to automatically grab fields of a given name from a struct. While you could do something like this in Java with reflection, it can't be done in C. You just need to manually copy the relevant members.
You may write function macro like this:
#define CAT(A, B) A ## B
#define ARGS_ASSIGN(N, L, R, ...) CAT(_ARGS_ASSIGN, N) (L, R, __VA_ARGS__)
#define _ARGS_ASSIGN1(L, R, M0) L.M0 = R.M0;
#define _ARGS_ASSIGN2(L, R, M0, M1) L.M0 = R.M0; L.M1 = R.M1;
/* ... define sufficiently more */
and use in such way:
ARGS_ASSIGN(2, two, one, a, s)
In theory you could do this with a simple block copy function for your example above using the code below if you are certain that your compiler sequences the structure as sequenced in its type definition. However, I don't think it's a great idea. Block copy would be safer with two data structures of the same type as defined in one of the answers proposed above.
Example using block copy function:
void main(void)
{
struct one{
int a;
int b;
char *s;
int c;
};
struct two{
int a;
int e;
char *s;
int d;
};
// Place code that assigns variable one here
memcpy(&two, &one, sizeof(one));
}

Pass a struct to pthread_create's startup routine

So I've got an assignment that I'm having trouble with. I'm trying use pthreads to sum the elements of a matrix with 3 different processors. I have a struct
typedef struct{
int rows;
int cols;
pid;
int localsum;
}ThreadData;
some global variabls
int processors=3;
int rows=4;
int cols=4;
int matrix[10][10];
and a sum function
void *matrixSum(void *p){
//cast *a to struct ThreadData?
int sum=0;
int i=p->pid;
int size=p->rows*p->cols;
//to sequentially add a processor's 'owned' cells
int row=p-pid/p-cols;
int col=p-pid%p->cols;
int max_partition_size = ((size/processors)+1);
for(i;i<max_partition_size*processors;i+=processors){
col=i%p->cols;
row=i/p->cols;
if(i<=size-1){
sum+=matrix[row][col]+1;
}
}
p->localsum=sum;
}
so my main method looks like this:
int main(){
int totalsum=0;
ThreadData *a;
a=malloc(processors*(sizeof(ThreadData));
int i;
for(i=0;i<processors;i++){
a[i].rows=rows;
a[i].cols=cols;
a[i].pid=i;
a[i].localsum=0;
}
//just a function that iterates over the matrix to assign it some contents
fillmatrix(rows, cols);
pthread_t tid[processors];
for(i=0;i<processors;i++){
pthread_create(tid,NULL,matrixSum,(void *)&a);
totalsum+=a[i].localsum;
}
pthread_join();
}
My ultimate goal is to pass my matrixSum() with a ThreadData struct as the argument.
So I think I have to cast the void pointer given in matrixSum() to a struct, but I'm having trouble doing so.
I tried doing so like this
ThreadData *a=malloc(sizeof(ThreadData));
a=(struct ThreadData*)p;
But I get a warning: assignment from incompatible pointer type error.
So what's the proper way to do this - that is to cast the void pointer taken from the parameters, and operate on it like the struct it is meant to be?
Try using a=(ThreadData*)p;.
In C language, struct ThreadData is differ to ThreadData.
In this case, you used typedef and defined no tag to the struct, so you mustn't use struct to use the struct.

How to declare similar structure with different number of fields?

I have 2 headers that need to define 2 similar structures. One structure should be aligned to 32bytes and other is similar but doesn't need to align to 32bytes so I can save some memory here. One is included in the other. Here is main_header.h
struct mainStruct
{
int a;
int b;
int c;
char pad[20];
};
Following is sub_header.h
#include "main_header.h"
struct subStruct
{
int a;
int b;
int c;
};
Now what I wish to do is define subStruct in a way that, whenever i change mainStruct other than pad[20] all other fields should be updated in subStruct. That is, if tomorrow, I make mainStruct like this:
struct mainStruct
{
int a;
int b;
int c;
int d;
char pad[16];
};
then, automatically it should be reflected in sub_header.h as
struct subStruct
{
int a;
int b;
int c;
int d;
};
Is there an efficient way of doing it using some kind of Macros or other preprocessor directives??
And subStruct should always be derived from mainStruct and not other way around, this is very important.
Thanks in advance.
Did you consider the other way around; including subStruct as an element in mainStruct? Like this:
struct sub {
int a, b, c;
};
struct main {
struct sub head;
char dummy[16];
};
True, it does take an extra layer of syntax to get at a, b or c, but the memory layout and performance should be the same.
Otherwise, there's nothing preventing you from using a macro, as you suggest yourself:
#define SUB_FIELDS int a; int b; int c;
struct main {
SUB_FIELDS
char dummy[16];
};
struct sub {
SUB_FIELDS
};
Well, that's why C++ was initially invented. But if you wish to stay with plain C (there could be reasons for such decision) you may check GLib / GObject type system implemented as a set of macros over plain C.

array to structure casting

I have these three structures,
typedef struct serial_header {
int zigbeeMsgType;
int seqNumber;
int commandIdentifier;
int dest;
int src;
}serial_header_t;
typedef struct serial_packet {
serial_header_t header;
int data[];
} serial_packet_t;
and last one is
typedef struct readAttributePacket
{
int u8SourceEndPointId;
int u8DestinationEndPointId;
int u16ClusterId;
int bDirectionIsServerToClient;
int u8NumberOfAttributesInRequest;
int bIsManufacturerSpecific;
int u16ManufacturerCode;
int pu16AttributeRequestList[];
}readAttributePacket_t;
I am troubling with this code, i just want to cast the data[] array which reside in serial_packet_t into readAttributePacket_t structure.
I think the data[] should be
data[]={0x01,0x01,0x04,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
I need to cast those data to readAttributePacket_t structure. But this below code showing wrong.
void main()
{
int a[]= {0x32,0x00,0x31,0x69,0x69,0x00,0x00,0x01,0x01,0x04,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
int i;
readAttributePacket_t *p;
serial_packet_t *data;
data = (serial_packet_t*)&a;
for(i=0;i<20;i++){
printf(" %02x \n",a[i]);
}
p = (readAttributePacket_t *)&data->data;
printf("\nu8SourceEndPointId:%x \nu8DestinationEndPointId:%x \nu16ClusterId:%04x \nbDirectionIsServerToClient:%x \nu8NumberOfAttributesInRequest:%x \nbIsManufacturerSpecific:%x \nu16ManufacturerCode:%04x",p->u8SourceEndPointId,
p->u8DestinationEndPointId,
p->u16ClusterId,
p->bDirectionIsServerToClient,
p->u8NumberOfAttributesInRequest,
p->bIsManufacturerSpecific,
p->u16ManufacturerCode);
getch();
}
the output should be like
u8SourceEndPointId=01
u8DestinationEndPointId=01
u16ClusterId=0402
bDirectionIsServerToClient=00
u8NumberOfAttributesInRequest=02
bIsManufacturerSpecific=00
u16ManufacturerCode=0000
How could I get the pu16AttributeRequestList[] array into readAttributePacket_t structure, should like that,
pu16AttributeRequestList[0]=0000
pu16AttributeRequestList[1]=0001
You can't just cast an array to a structure because they're simply incompatible types. Due to memory alignment constraints, the compiler needs to insert padding between the fields of a structure, so the members are not located at the memory addresses you may expect. Solutions:
Portable but slower/harder to do manually (preferred): copy manually the fields of the structure to the array.
Shorter to write but GCC-specific: use the __attribute__((packed)) keyword to make GCC not introduce padding between struct fields.
Construct a union of 3 structs. all on equal memory space. then you dont even need to cast.
I think the only thing that you need to do in to remove the address operator from the casting statement.
data = (serial_packet_t*)a;
instead of
data = (serial_packet_t*)&a;
as far as I know, everything should work fine from here.

Resources