Buenas a todos!
Como les había mensioando en la Talk III, me encontraba desarrollando un librería genérica que nos permita serializar de manera facil, simple y transparente. Para ello hice la librería serializer.h que actualmente solo se encuentra para linux en las common-libs, esperamos que a la brevedad las portemos para Windows y para common-libs2.
typedef struct{
unsigned char age;
unsigned int dni;
char *name;
char *lastname;
}__attribute__ ((__packed__)) t_person;
t_person *person_create(unsigned char age, unsigned int dni, char *name, char *lastname);
void person_destroy(t_person*);
int main(int argc, char **argv) {
t_serializer *serializer = serializer_create("t_person", SFIELD_TYPE_CHAR /*Age*/,
SFIELD_TYPE_INT32 /*DNI*/,
SFIELD_TYPE_CHAR_POINTER /*Name*/,
SFIELD_TYPE_CHAR_POINTER /*Lastname*/,
SFIELD_TYPE_END);
t_person *person1,*person2;
t_stream *stream;
person1 = person_create(24, 3000000, "John", "Doe" );
stream = serializer_build(serializer, person1);
person2 = serializer_rebuild(serializer, stream);
assert( person1->age == person2->age);
assert( person1->dni == person2->dni);
assert( strcmp(person1->name, person2->name ) == 0 );
assert( strcmp(person1->lastname, person2->lastname ) == 0 );
serializer_delete(serializer, &stream);
serializer_destroy(serializer);
person_destroy(person1);
person_destroy(person2);
puts("Run Success!");
return EXIT_SUCCESS;
}
Como se puede ver en este ejemplo ( es el mismo que esta subido en el repositorio ), lo primero que hacemos es crear un serializador que tenga los mismo campos, con el mismo tipo y el mismo orden que la estructura que vamos a serializar finalizando siempre con un SFIELD_TYPE_END. La función serializer_build nos permite transformar una estructura en un stream y la función hace completamente lo inverso serializer_rebuild.
Desde el punto de vista de TADs, la recomendación seria; implementar una función person_serialize dentro del TAD person que internamente cree el t_serializer y asi el person_serialize sea el que devuelva el t_stream. La idea seria abstraer al usuario de nuestra lib de como se realiza la serializacion del tipo t_persona.
Si tuvieramos un campo que fuera un array estatic se puede usar el tipo SFIELD_TYPE_ARRAY seguido de la cantidad de elemento, seguido del tipo de dato del array. Ej:
t_serializer *serializer = serializer_create("t_person", SFIELD_TYPE_CHAR /*Age*/,
SFIELD_TYPE_INT32 /*DNI*/,
SFIELD_TYPE_CHAR_POINTER /*Name*/,
SFIELD_TYPE_CHAR_POINTER /*Lastname*/,
SFIELD_TYPE_ARRAY, 5, SFIELD_TYPE_INT32, /*telephones*/
SFIELD_TYPE_END);
Consideraciones: El tipo SFIELD_TYPE_VOID_POINTE aun no lo termine de implementar, por lo que no es recomendable usarlo ( Este tipo de dato esta pensado cuando tengamos una estructura dentro de otra y la idea seria encadenar serializadores). La otra consideración es de que aun no esta del todo pulida la lógica que transforma de estructura a stream por lo que el limite de tamaño de un stream es de 4kb. Por lo que no se puede serializar una estructura cuya suma de todos los campos sea mas grande que 4kb, aunque se puede re-definir la macro MAX_SERIALIZER_BUFFER para aumentar o achicar este limite.