473,408 Members | 2,477 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,408 software developers and data experts.

"serializing" structs in C

I want to save a struct to disk.... as plain text.
At the moment I do it with a function that just
writes the data using fprintf. I mean like this:
fprintf(fp, "%d %d", my_struct.a, my_struct.b)
This way I have to write another "serializing"
function for every new kind of struct I want
to write, though. Is there a way to write
functions that can write/read any struct
to/from plain text format in a portable way?

copx

Nov 14 '05 #1
10 8231
Hello,

Since you don't want to write a serialization function, I would suggest
encoding (say base64) the struct into a string then writing that string into
the file.
For reading you would read the string, decode it to get the struct back
again.

If you add members however, you have to rewrite old files....unless you can
control it via 'version' field in your struct...

--
Elias
"copx" <in*****@invalid.com> wrote in message
news:3f***********************@newsread4.arcor-online.net...
I want to save a struct to disk.... as plain text.
At the moment I do it with a function that just
writes the data using fprintf. I mean like this:
fprintf(fp, "%d %d", my_struct.a, my_struct.b)
This way I have to write another "serializing"
function for every new kind of struct I want
to write, though. Is there a way to write
functions that can write/read any struct
to/from plain text format in a portable way?

copx

Nov 14 '05 #2
"copx" <in*****@invalid.com> writes:
I want to save a struct to disk.... as plain text.
At the moment I do it with a function that just
writes the data using fprintf. I mean like this:
fprintf(fp, "%d %d", my_struct.a, my_struct.b)
This way I have to write another "serializing"
function for every new kind of struct I want
to write, though. Is there a way to write
functions that can write/read any struct
to/from plain text format in a portable way?


Such a serializing function would need to know the type and location
of each structure member. If you store this information once for every
structure, you can pass it as an additional argument to a structure
serializing function. The program below should give you some ideas.

Martin

#include <stddef.h>
#include <stdio.h>

/* Structure that will be serialized. */
struct foo {
int a;
unsigned long b;
double c;
};

/* Information about a structure member. */
struct member_info {
enum {NIL, TYPE_INT, TYPE_UINT, TYPE_LONG, TYPE_ULONG, TYPE_DOUBLE} type;
size_t offset;
};

/* Information about the members of struct foo. */
const struct member_info foo_info [] = {
{TYPE_INT, offsetof (struct foo, a)},
{TYPE_ULONG, offsetof (struct foo, b)},
{TYPE_DOUBLE, offsetof (struct foo, c)},
{NIL, 0}
};

void serialize (const void *const data, const struct member_info *info)
{
while (1)
{
switch (info->type)
{
case TYPE_INT:
printf ("%d", *(int *)((char *)data + info->offset));
break;
case TYPE_UINT:
printf ("%u", *(unsigned int *)((char *)data + info->offset));
break;
case TYPE_LONG:
printf ("%ld", *(long *)((char *)data + info->offset));
break;
case TYPE_ULONG:
printf ("%lu", *(unsigned long *)((char *)data + info->offset));
break;
case TYPE_DOUBLE:
printf ("%f", *(double *)((char *)data + info->offset));
break;
}

if ((++info)->type == NIL)
{
putchar ('\n');
break;
}
else
putchar (' ');
}
}

int main (void)
{
struct foo myfoo = {42, 2004, 3.1415926536};
serialize (&myfoo, foo_info);
return 0;
}
Nov 14 '05 #3
Martin Dickopp wrote:
"copx" <in*****@invalid.com> writes:

I want to save a struct to disk.... as plain text.
At the moment I do it with a function that just
writes the data using fprintf. I mean like this:
fprintf(fp, "%d %d", my_struct.a, my_struct.b)
This way I have to write another "serializing"
function for every new kind of struct I want
to write, though. Is there a way to write
functions that can write/read any struct
to/from plain text format in a portable way?

Such a serializing function would need to know the type and location
of each structure member. If you store this information once for every
structure, you can pass it as an additional argument to a structure
serializing function. The program below should give you some ideas.

Martin


Two remarks:

(1) Although the need to write code for each and every structure member
can seem a PITA, it is a good investment. The same info can be used for
*other* serialization functions, such as printouts (consider the ease:
genericprintout(&myfoo, foo_info) et voila!), automatic garbage
collectors, ...

(2) If there are pointers in the structs, one must call the serializer
recursively; this requires 2 additional bookkeepings: a table of the
addresses of which structures have already been serialized, to avoid
duplications (one uses a tag instead); and easy access to the info table
from the address of a struct (the easiest is to have always an info
pointer as the first field of every struct).

Season greetings,
--
Michel Bardiaux
Peaktime Belgium S.A. Bd. du Souverain, 191 B-1160 Bruxelles
Tel : +32 2 790.29.41

Nov 14 '05 #4
copx wrote:

I want to save a struct to disk.... as plain text.
At the moment I do it with a function that just
writes the data using fprintf. I mean like this:
fprintf(fp, "%d %d", my_struct.a, my_struct.b)
This way I have to write another "serializing"
function for every new kind of struct I want
to write, though. Is there a way to write
functions that can write/read any struct
to/from plain text format in a portable way?


No, but you can write code to serialize some classes of
structures. For example:

typedef struct para {
size_t linecount;
char **lines;
} para, paraptr;

(you can use some tricks to make the lines field a variable length
array in C90, but making it a pointer to an array of char *
pointers, which need to be allocated, and in turn need to be
allocated space to hold the individual strings, is cleaner)

Now the serializing routine might be:

void writepara(paraptr pp)
{
size_t count;

count = pp->linecount;
printf("%ud\n", (unsigned int)count);
while (count--) puts((pp->lines)[count], stdout);
}

If I have not goofed excessively, the resultant text file will
consist of an integer specifying the number of following lines,
followed by the lines in reversed order. This pattern will be
repeated as needed, and can be read back into entirely different
structures if desired. The lines proper cannot contain embedded
'\n's nor '\0's without confusion.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #5

"Martin Dickopp" <ex****************@zero-based.org> schrieb im Newsbeitrag
news:bs*************@news.t-online.com...
[snip]
/* Information about the members of struct foo. */
const struct member_info foo_info [] = {
{TYPE_INT, offsetof (struct foo, a)},
{TYPE_ULONG, offsetof (struct foo, b)},
{TYPE_DOUBLE, offsetof (struct foo, c)},
{NIL, 0}
};

[snip]

Is offsetof() really part of ANSI/ISO C?
I don't claim to know every ANSI keyword
but I've never seen it before and it looks
a lot like typeof() which is a non-standard GNU
extension IIRC.

Otherwise this looks like a pretty good
solution for my problem.

copx

Nov 14 '05 #6
lallous wrote:
Hello,

Please don't top-post. It's rude.
Since you don't want to write a serialization function, I would suggest
encoding (say base64) the struct into a string then writing that string into
the file.


This is very bad advice, in my opinion. Depending on what exactly you
mean, it's either more complicated than the original proposal or
completely non-portable.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #7
On Tue, 30 Dec 2003 22:04:52 +0100, "copx" <in*****@invalid.com> wrote
in comp.lang.c:

"Martin Dickopp" <ex****************@zero-based.org> schrieb im Newsbeitrag
news:bs*************@news.t-online.com...
[snip]
/* Information about the members of struct foo. */
const struct member_info foo_info [] = {
{TYPE_INT, offsetof (struct foo, a)},
{TYPE_ULONG, offsetof (struct foo, b)},
{TYPE_DOUBLE, offsetof (struct foo, c)},
{NIL, 0}
}; [snip]

Is offsetof() really part of ANSI/ISO C?


Has been since the first ANSI 1989 standard, still is in the latest
C99 standard. Here's the relevant text from the current standard:

========
7.17 Common definitions <stddef.h>

1 The following types and macros are defined in the standard header
<stddef.h>. Some are also defined in other headers, as noted in their
respective subclauses.

[snip]

3 The macros are

NULL
which expands to an implementation-defined null pointer constant; and

offsetof(type, member-designator)
which expands to an integer constant expression that has type size_t,
the value of which is the offset in bytes, to the structure member
(designated by member-designator), from the beginning of its structure
(designated by type). The type and member designator shall be such
that given

static type t;

then the expression &(t.member-designator) evaluates to an address
constant. (If the specified member is a bit-field, the behavior is
undefined.)
========
I don't claim to know every ANSI keyword
but I've never seen it before and it looks
a lot like typeof() which is a non-standard GNU
extension IIRC.

Otherwise this looks like a pretty good
solution for my problem.

copx


--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
Nov 14 '05 #8
"copx" <in*****@invalid.com> writes:
I want to save a struct to disk.... as plain text.
At the moment I do it with a function that just
writes the data using fprintf. I mean like this:
fprintf(fp, "%d %d", my_struct.a, my_struct.b)
This way I have to write another "serializing"
function for every new kind of struct I want
to write, though. Is there a way to write
functions that can write/read any struct
to/from plain text format in a portable way?


Not easily without having to do some manual work for each struct type
(e.g., setting up an array of offsets and types).

I once worked on a project to do something similar, with the intent of
allowin access to a struct member given a pointer to the struct and
the name of the member, as a string. It involved a multi-stage
process, starting with feeding the relevant header files to a C parser
that generated C code that printed out information about each struct
and member. (It was at a previous job, and I don't have the code.)

Unless you have a *lot* of structs you want to serialize, it's
probably easier to do some manual work.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
(Note new e-mail address)
Nov 14 '05 #9

"Jack Klein" <ja*******@spamcop.net> schrieb im Newsbeitrag
news:vj********************************@4ax.com...
On Tue, 30 Dec 2003 22:04:52 +0100, "copx" <in*****@invalid.com> wrote
in comp.lang.c:

"Martin Dickopp" <ex****************@zero-based.org> schrieb im Newsbeitrag news:bs*************@news.t-online.com...
[snip]
/* Information about the members of struct foo. */
const struct member_info foo_info [] = {
{TYPE_INT, offsetof (struct foo, a)},
{TYPE_ULONG, offsetof (struct foo, b)},
{TYPE_DOUBLE, offsetof (struct foo, c)},
{NIL, 0}
};

[snip]

Is offsetof() really part of ANSI/ISO C?


Has been since the first ANSI 1989 standard, still is in the latest
C99 standard. Here's the relevant text from the current standard:

[snip]

I see. Thanks.

copx

Nov 14 '05 #10
On Tue, 30 Dec 2003 12:40:00 +0200
"lallous" <la*****@lgwm.org> wrote:

Please don't top post. It is considered rude since it makes it harder to
read. It is also in contravention of the appropriate RFC, use your
favourite search engine for more information, terms such as netiquette,
top-posting, bottom-posting may help. Instead, after appropriate
snipage, post you reply under the parts of the post you are doing, as I
have done.

Top-posting fixed.
"copx" <in*****@invalid.com> wrote in message
news:3f***********************@newsread4.arcor-online.net...
I want to save a struct to disk.... as plain text. ^^^^^^^^^^^^^ At the moment I do it with a function that just
writes the data using fprintf. I mean like this:
fprintf(fp, "%d %d", my_struct.a, my_struct.b)
This is correct.
This way I have to write another "serializing"
function for every new kind of struct I want
to write, though.
Unfortunately true.
Is there a way to write
functions that can write/read any struct
to/from plain text format in a portable way?

You can use pre-processor magic to automate a lot (if not all) of the
generation of such functions.
Since you don't want to write a serialization function, I would
suggest encoding (say base64) the struct into a string then writing
that string into the file.
For reading you would read the string, decode it to get the struct
back again.
Unfortunately this does not help for a number of reasons.

1) The OP wants plain text, base64 (or any other encoding) does not
normally count as plain text.

2) The file produced will not be portable since the representation of
the data may vary between systems, e.g. different padding, different
endianness, 1s-complements vs 2s-complement etc.
If you add members however, you have to rewrite old files....unless
you can control it via 'version' field in your struct...


Not much help in dealing with all of the above. Also not much help if
the OP wants to be able to read the files with a text editor.
--
Flash Gordon
Paid to be a Geek & a Senior Software Developer
Although my email address says spam, it is real and I read it.
Nov 14 '05 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Maersa | last post by:
Hi All, Was anybody able to serialize the "Type" class properly using XmlSerializer().... Want to serialize and deserialze the Type in a string form, but can this be done ? myobj.Type =...
3
by: Amy L. | last post by:
I am using the xml serializer to serialize the objects out of a collection into a file. The object that is being serialized is a class in my application. When I serialize my class it produces the...
388
by: maniac | last post by:
Hey guys, I'm new here, just a simple question. I'm learning to Program in C, and I was recommended a book called, "Mastering C Pointers", just asking if any of you have read it, and if it's...
0
by: Kenneth Baltrinic | last post by:
Is the following code correct for serializing a quasi-single class, that is a class that has a descreet (though more than one, so not a true singleton) number of static instances and no dynamically...
2
by: Mike Fiedler | last post by:
On a client web services request, I have a SoapExtension that is adding a header to the message in the BeforeSerialize stage. If the Web Service request is for an operation with...
6
by: geoffrobinson | last post by:
Hi, I'm serializing an object using XmlSerializer. It is serializing, but we are getting errors upon deserialization. We use the following code to serialize: FileStream fs = new...
2
by: Rick Francis | last post by:
I need help serializing an array without including the array "name". I am writing in C# and using the XmlSerializer to serial classes. I am trying to serialize a class with an array in it like...
5
by: Nirdesh | last post by:
Hi, I am serializing a custom class holding some data for my project. This data internally contains a class which contains an event public delegate void MemberModifiedEventHandler(object...
18
by: Stephan Beal | last post by:
Hi, all! Before i ask my question, i want to clarify that my question is not about the code i will show, but about what the C Standard says should happen. A week or so ago it occurred to me...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.