Gwyfile Library
readgeneric.c

Example showing how to read a generic GWY file with arbitrary data types. It dumps the hierarchical file structure to the standard output.

/*
* $Id: readgeneric.c 343 2020-07-10 09:36:51Z yeti-dn $
*
* This example reads a general GWY file and prints its structure. It is
* similar to gwydump, albeit simpler.
*
* I, the copyright holder of this work, release this work into the public
* domain. This applies worldwide. In some countries this may not be legally
* possible; if so: I grant anyone the right to use this work for any purpose,
* without any conditions, unless such conditions are required by law.
*/
#include <stdlib.h>
#include <math.h>
#include <errno.h>
#include <string.h>
#include "gwyfile.h"
#define INDENT " "
#ifdef _WIN32
#define llformat "I64"
#else
#define llformat "ll"
#endif
static struct {
const char *name;
}
typenames[] = {
{ GWYFILE_ITEM_BOOL, "Bool", },
{ GWYFILE_ITEM_CHAR, "Char", },
{ GWYFILE_ITEM_INT32, "Int32", },
{ GWYFILE_ITEM_INT64, "Int64", },
{ GWYFILE_ITEM_DOUBLE, "Double", },
{ GWYFILE_ITEM_STRING, "String", },
{ GWYFILE_ITEM_OBJECT, "Object", },
{ GWYFILE_ITEM_CHAR_ARRAY, "CharArray", },
{ GWYFILE_ITEM_INT32_ARRAY, "Int32Array", },
{ GWYFILE_ITEM_INT64_ARRAY, "Int64Array", },
{ GWYFILE_ITEM_DOUBLE_ARRAY, "DoubleArray", },
{ GWYFILE_ITEM_STRING_ARRAY, "StringArray", },
{ GWYFILE_ITEM_OBJECT_ARRAY, "ObjectArray", },
};
static void dump_object_recursively(GwyfileObject *object,
int level);
static void dump_item_recursively (const GwyfileItem *item,
void *user_data);
int
main(int argc, char *argv[])
{
GwyfileObject *gwyf;
GwyfileError *error = NULL;
bool using_stdin = false;
if (argc != 2) {
printf("readgeneric FILE.gwy\n"
"Read a generic GWY file and print its structure.\n"
"Pass \"-\" as the filename to read the standard input.\n");
exit(argc == 1 ? EXIT_SUCCESS : EXIT_FAILURE);
}
/* Read a GWY file. */
if (strcmp(argv[1], "-") == 0) {
using_stdin = true;
gwyf = gwyfile_fread(stdin, SIZE_MAX, &error);
}
else
gwyf = gwyfile_read_file(argv[1], &error);
if (!gwyf) {
fprintf(stderr, "Cannot read %s: %s\n", using_stdin ? "the standard input" : argv[1], error->message);
exit(EXIT_FAILURE);
}
/* Dump its structure. */
dump_object_recursively(gwyf, 0);
/* Clean-up. This call recursively frees all the objects and items. */
return 0;
}
static void
dump_object_recursively(GwyfileObject *object, int level)
{
int i;
for (i = 0; i < level; i++)
printf(INDENT);
/* Object name. */
printf("Object \"%s\"\n", gwyfile_object_name(object));
/* Use gwyfile_object_foreach() to iterate over items. */
level++;
gwyfile_object_foreach(object, dump_item_recursively, &level);
}
static void
dump_item_recursively(const GwyfileItem *item,
void *user_data)
{
int *plevel = (int*)user_data;
int i, level = *plevel;
unsigned int k, array_length;
for (i = 0; i < level; i++)
printf(INDENT);
/* Item name. */
printf("Item \"%s\"", gwyfile_item_name(item));
/* Look up human-readable item type in typenames[]. */
for (k = 0; k < sizeof(typenames)/sizeof(typenames[0]); k++) {
if (typenames[k].type == type) {
printf(" type=%s", typenames[k].name);
break;
}
}
/* Array length for arrays. */
if ((array_length = gwyfile_item_array_length(item))) {
printf(" length=%u", array_length);
}
if (type == GWYFILE_ITEM_BOOL)
printf(" %s", gwyfile_item_get_bool(item) ? "true" : "false");
else if (type == GWYFILE_ITEM_CHAR)
printf(" 0x%02x", gwyfile_item_get_char(item));
else if (type == GWYFILE_ITEM_INT32)
printf(" %i", gwyfile_item_get_int32(item));
else if (type == GWYFILE_ITEM_INT64)
printf(" %" llformat "i", (long long int)gwyfile_item_get_int64(item));
else if (type == GWYFILE_ITEM_DOUBLE)
printf(" %g", gwyfile_item_get_double(item));
/* We could print other value types here but priting them properly would
* unnecessarily complicate this example. */
printf("\n");
if (type == GWYFILE_ITEM_OBJECT)
dump_object_recursively(gwyfile_item_get_object(item), level+1);
else if (type == GWYFILE_ITEM_OBJECT_ARRAY) {
GwyfileObject *const *objs = gwyfile_item_get_object_array(item);
for (k = 0; k < array_length; k++)
dump_object_recursively(objs[k], level+1);
}
}
/* vim: set cin et ts=4 sw=4 columns=120 tw=119 cino=>1s,e0,n0,f0,{0,}0,^0,\:1s,=0,g1s,h0,t0,+1s,c3,(0,u0 : */
GwyfileObject * gwyfile_read_file(const char *filename, GwyfileError **error)
Reads a GWY file from a named file and returns its top-level object.
Definition: gwyfile.c:405
GwyfileObject * gwyfile_fread(FILE *stream, size_t max_size, GwyfileError **error)
Reads a GWY file from a stdio stream and returns the top-level object.
Definition: gwyfile.c:565
void gwyfile_error_clear(GwyfileError **error)
Clears a GwyfileError.
Definition: gwyfile.c:8990
bool gwyfile_item_get_bool(const GwyfileItem *item)
Gets the boolean value contained in a GWY file data item.
Definition: gwyfile.c:5440
char gwyfile_item_get_char(const GwyfileItem *item)
Gets the character value contained in a GWY file data item.
Definition: gwyfile.c:5490
double gwyfile_item_get_double(const GwyfileItem *item)
Gets the double value contained in a GWY file data item.
Definition: gwyfile.c:5640
int32_t gwyfile_item_get_int32(const GwyfileItem *item)
Gets the 32bit integer value contained in a GWY file data item.
Definition: gwyfile.c:5540
int64_t gwyfile_item_get_int64(const GwyfileItem *item)
Gets the 64bit integer value contained in a GWY file data item.
Definition: gwyfile.c:5590
GwyfileObject *const * gwyfile_item_get_object_array(const GwyfileItem *item)
Gets the object array value contained in a GWY file data item.
Definition: gwyfile.c:8100
GwyfileObject * gwyfile_item_get_object(const GwyfileItem *item)
Gets the object value contained in a GWY file data item.
Definition: gwyfile.c:5903
uint32_t gwyfile_item_array_length(const GwyfileItem *item)
Obtains the array length of a GWY file data item.
Definition: gwyfile.c:7326
const char * gwyfile_item_name(const GwyfileItem *item)
Obtains the name of a GWY file data item.
Definition: gwyfile.c:7311
GwyfileItemType
Definition: gwyfile.h:87
GwyfileItemType gwyfile_item_type(const GwyfileItem *item)
Obtains the type of a GWY file data item.
Definition: gwyfile.c:7298
@ GWYFILE_ITEM_INT32
32bit integer.
Definition: gwyfile.h:90
@ GWYFILE_ITEM_DOUBLE_ARRAY
Array of IEEE double precision floating point numbers.
Definition: gwyfile.h:98
@ GWYFILE_ITEM_STRING
String of characters.
Definition: gwyfile.h:93
@ GWYFILE_ITEM_OBJECT_ARRAY
Array of objects, i.e. a nested data structures.
Definition: gwyfile.h:100
@ GWYFILE_ITEM_INT64_ARRAY
Array of 64bit integers.
Definition: gwyfile.h:97
@ GWYFILE_ITEM_STRING_ARRAY
Array of character strings.
Definition: gwyfile.h:99
@ GWYFILE_ITEM_CHAR_ARRAY
Array of characters.
Definition: gwyfile.h:95
@ GWYFILE_ITEM_BOOL
Boolean (true or false).
Definition: gwyfile.h:88
@ GWYFILE_ITEM_INT64
64bit integer.
Definition: gwyfile.h:91
@ GWYFILE_ITEM_INT32_ARRAY
Array of 32bit integers.
Definition: gwyfile.h:96
@ GWYFILE_ITEM_OBJECT
Object, i.e. a nested data structure.
Definition: gwyfile.h:94
@ GWYFILE_ITEM_DOUBLE
IEEE double precision floating point number.
Definition: gwyfile.h:92
@ GWYFILE_ITEM_CHAR
Single character.
Definition: gwyfile.h:89
void gwyfile_object_foreach(const GwyfileObject *object, GwyfileObjectForeachFunc function, void *user_data)
Calls a function for each item contained in a GWY file data object.
Definition: gwyfile.c:4894
const char * gwyfile_object_name(const GwyfileObject *object)
Obtains the name of a GWY file data object.
Definition: gwyfile.c:4599
void gwyfile_object_free(GwyfileObject *object)
Frees a GWY file data object.
Definition: gwyfile.c:4577
Gwyfile Library.
Detailed information about an error.
Definition: gwyfile.h:131
char * message
Text message describing the error. It is allocated when the error struct is created and freed with gw...
Definition: gwyfile.h:134