Nicholas
Nicholas

Reputation: 628

How can I store C structures in human-readable files using the fewest lines of code?

I have a daemon for a scientific instrument that needs to persist about 100 unique variables. Currently, these settings are stored in binary form at explicit addresses, and each is accessed with a unique getter and setter. This is completely unmaintainable. I'd like to group settings together in sensible structures and persist those structures into files. I'll also have default values in case of incomplete files. What library or technique will allow me to save and restore these structures with as few lines of code as possible?

Upvotes: 2

Views: 649

Answers (3)

LogicG8
LogicG8

Reputation: 1757

The fastest/easiest way to serialize a C struct is to use X-macros. This lets you define related properties together and re-use elements. This example does not do any of the error checking that should be done but with an implementation less than 30 lines it will be hard to find a shorter one. More elaborate uses are possible like automatically creating getters and setters.

#include <stdio.h>

#define SETTINGS_TABLE \
    X(float,  "%f", foo, 2.71818) \
    X(float,  "%f", bar, 0.70711) \
    X(int,    "%i", baz, 42)

#define X(type, fmt, name, default) type name ;
struct Settings { SETTINGS_TABLE };
#undef X

#define X(type, fmt, name, default) default ,
struct Settings settings = { SETTINGS_TABLE };
#undef X

void dump(FILE *f)
{
#define X(type, fmt, name, default) fprintf(f, "%s=" fmt "\n", #name, settings.name);
    SETTINGS_TABLE
#undef X
}

void load(FILE *f)
{
#define X(type, fmt, name, default) fscanf(f, #name "=" fmt, &settings.name);
    SETTINGS_TABLE
#undef X
}

int main(int argc, char *argv[])
{
    FILE *cfg;

    cfg = fopen(argv[1], "r");
    load(cfg);
    fclose(cfg);
    dump(stdout);

    return 0;
}

Upvotes: 2

Mathuin
Mathuin

Reputation: 800

You can't simply serialize them using a library if you want human-readable files. You need to write a function which, given a filename and the structures, will write the contents of the structures in the file.I'd suggest you use a one line = one member basis, but write the name of the member too, so that you'll find which members are missing, this way: name:value.
Then, another function will need to retrieve a structure from the file. Instead of writing your own format, you could use JSON with the jansson library. **EDIT: As the comments said, libjson is another alternative, usable both in C and C++.

Upvotes: 2

"Shortest" have several meanings

  • fast to process
  • eating as little as memory as possible
  • easy and quick to code

I would suggest to use a simple textual format to serialize them, probably JSON (or maybe YAML or XML). The advantage of such formats is that they remain somehow human "readable" (at last for a programmer).

There exist a lot of JSON libraries (notably in C and C++): jansson in C, jsoncpp for C++, etc etc...

Does your scientific instrument runs only a tiny 8 bit controller? If yes, you might be constrained by code size...

And I suggest also to document the serialized format.

Upvotes: 1

Related Questions