## GwySerializable

GwySerializable — Serialisable value-like object interface

## Functions

GwySerializable * | gwy_serializable_copy ()
void | gwy_serializable_assign ()
GwySerializableGroup * | gwy_serializable_itemize ()
GQuark | gwy_deserialize_error_quark ()
void | gwy_serializable_done ()
GwySerializableGroup * | gwy_serializable_group_new ()
void | gwy_serializable_group_alloc_size ()
void | gwy_serializable_group_free ()
const gchar * | gwy_serializable_group_name ()
void | gwy_serializable_group_rename ()
gsize | gwy_serializable_group_size ()
GwySerializableItem * | gwy_serializable_group_items ()
void | gwy_serializable_group_discard ()
void | gwy_serializable_group_itemize ()
void | gwy_serializable_group_done ()
void | gwy_serializable_group_append ()
void | gwy_serializable_group_append_int8 ()
void | gwy_serializable_group_append_int16 ()
void | gwy_serializable_group_append_int32 ()
void | gwy_serializable_group_append_int64 ()
void | gwy_serializable_group_append_boolean ()
void | gwy_serializable_group_append_float ()
void | gwy_serializable_group_append_double ()
void | gwy_serializable_group_append_object ()
void | gwy_serializable_group_append_unit ()
void | gwy_serializable_group_append_boxed ()
void | gwy_serializable_group_append_rgba ()
void | gwy_serializable_group_append_string ()
void | gwy_serializable_group_append_int8_array ()
void | gwy_serializable_group_append_int16_array ()
void | gwy_serializable_group_append_int32_array ()
void | gwy_serializable_group_append_int64_array ()
void | gwy_serializable_group_append_float_array ()
void | gwy_serializable_group_append_double_array ()
void | gwy_serializable_group_append_string_array ()
void | gwy_serializable_group_append_object_array ()
#define | GWY_SERIALIZABLE_GET_INTERFACE()

## Types and Values

enum | GwySerializableCType
enum | GwySerializeSizeType
enum | GwySerializableFlags
union | GwySerializableValue
| GwySerializableAux
struct | GwySerializableItem
#define | GWY_DESERIALIZE_ERROR
enum | GwyDeserializeError
| GwySerializableGroup
| GwySerializable
struct | GwySerializableInterface

## Object Hierarchy

        GInterface
        ╰── GwySerializable

## Prerequisites

GwySerializable requires GObject.

## Known Implementations

GwySerializable is implemented by GwyBrick, GwyDict, GwyField, GwyGLMaterial, GwyGradient, GwyLawn, GwyLine, GwyNield, GwyScatter, GwySelection, GwySelectionAxis, GwySelectionEllipse, GwySelectionLattice, GwySelectionLine, GwySelectionPath, GwySelectionPoint, GwySelectionQuad, GwySelectionRange, GwySelectionRectangle, GwySpectra, GwyStringList and GwyUnit.

## Includes

    #include <libgwyddion/gwyddion.h>

## Description

GwySerializable is an abstract interface for data-like objects that can be serialised and deserialised. You can serialise any object implementing this interface with functions such as `gwy_serialize_gio()` and the restore (deserialise) it with `gwy_deserialize_memory()`.

Gwyddion implements a simple serialisation model: only tree-like structures of objects, formed by ownership, can be serialised and restored. Any inter-object relations other than plain ownership must be stored in some weak form and there is no explicit support for this. Moreover, only object values are preserved, their identities are lost (in particular, signals, user data and similar attributes are not subject to serialisation and deserialisation). This, on the other hand, means that any saved object can be restored individually and independently and still be in a meaningful state.

Beside saving and restoration, all serialisable classes implement a copy-constructor that creates a duplicate of an existing object. This constructor is invoked with `gwy_serializable_copy()`. Furthermore, the value of one such object can be transferred to another object of the same class (or a superclass), similarly to overriden assignment operators in OO languages. This assignment is performed with `gwy_serializable_assign()`.

Most classes that implement GwySerializable define convenience macros for the copy-constructor and assignment operator, called `gwy_foo_copy()` and `gwy_foo_assign()`, respectively, where `foo` is the lowercase class name.

### Implementing GwySerializable

You can implement serialisation and deserialisation in your classes. Use the `G_IMPLEMENT_ITERFACE` macro to generate the boilerplate interface implementation code. The copy constructor and assignment operators are usually easy so we focus on serialisation and deserialisation (with public object data for simplicity). There are a number of helper functions, such as `gwy_deserialize_filter()` for getting only the interesting items in deserialisation or `gwy_serialize_item_double()` for handling the itemisation of a single value.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100

    // Standard object structure definitions
    typedef struct _MyObject      MyObject;
    typedef struct _MyObjectClass MyObjectClass;

    struct _MyObject {
        GObject g_object;
        gint32 data;
    };

    struct _MyObjectClass {
        GObjectClass g_object_class;
    };

    // Define the type
    G_DEFINE_TYPE_WITH_CODE(MyObject, my_object, G_TYPE_OBJECT,
                            G_IMPLEMENT_INTERFACE(GWY_TYPE_SERIALIZABLE, serializable_init));

    // Serialised data specification, used both in itemize() and construct()

    enum {
        ITEM_DATA,
        NUM_ITEMS
    };

    static const GwySerializableItem serializable_items[NUM_ITEMS] = {
        { .name = "data", .ctype = GWY_SERIALIZABLE_INT32, },
    };

    // Implement the interface
    static void
    serializable_init(GwySerializableInterface *iface)
    {
        iface->itemize   = serializable_itemize;
        iface->construct = serializable_construct;
        iface->copy      = serializable_copy;
        iface->assign    = serializable_assign;
    }

    // Duplication is easy, create a new object and set data
    static GwySerializable*
    serializable_copy(GwySerializable *serializable)
    {
        MyObject *myobject = GWY_MY_OBJECT(serializable);
        MyObject *copy = g_object_newv(MY_TYPE_OBJECT, 0, NULL);

        copy->data = myobject->data;
        return GWY_SERIALIZABLE(copy);
    }

    // Assigning is even easier, just set data
    static void
    serializable_assign(GwySerializable *destination,
                        GwySerializable *source)
    {
        MyObject *myobject = GWY_MY_OBJECT(serializable);
        MyObject *src = GWY_MY_OBJECT(source);

        src->data = myobject->data;
    }

    // Fill the item list with actual object data.  This is a bit
    // overcomplicated for such a simple object as MyObject, of course.
    static void
    serializable_itemize(GwySerializable *serializable,
                         GwySerializableGroup *group)
    {
        MyObject *myobject = GWY_MY_OBJECT(serializable);

        // Preallocate the group to avoid reallocations. Not really necessary in this case because we have just one
        // item.
        gwy_serializable_group_alloc_size(group, NUM_ITEMS);

        // Do not store the data if it has the default value.
        if (myobject->data)
            gwy_serializable_group_append_int32(group, serializable_items + ITEM_DATA, myobject->data);

        // If we had member objects, we would call gwy_serializable_group_itemize() here to itemise them.
    }

    // Construct the object from item list.  The data item does not need to be present, in this case the default zero
    // value is used.  Also, for more complicated objects the deserialisation can fail or resources need to be released;
    // see GwySerializableInterface for the clean-up rules.
    static gboolean
    serializable_construct(GwySerializable *serializable,
                           GwySerializableGroup *group,
                           GwyErrorList **error_list)
    {
        GwySerializableItem it[G_N_ELEMENTS(serializable_items)];

        memcpy(it, serializable_items, sizeof(serializable_items));
        gwy_deserialize_filter_items(it, G_N_ELEMENTS(it), group, "MyObject", error_list);

        MyObject *myobject = GWY_MY_OBJECT(serializable);
        myobject->data = it[0].value.v_int32;

        // The construction of more complex objects can fail due to a logical inconsitency. We would return FALSE
        // in such case and had to free anything in it[].

        return TRUE;
    }

## Functions

### gwy_serializable_copy()

    GwySerializable *
    gwy_serializable_copy (GwySerializable *serializable);

Creates an object with identical value.

This is a copy-constructor creating a deep copy.

You can duplicate a `NULL`, too, but you are discouraged from doing it.

GwySerializable implementations are encouraged to provide `my_object_copy()` convenience wrappers with argument and return value of the specific type and the corresponding type checking.

#### Parameters

serializable | A serializable object. |

#### Returns

The newly created object copy.

[transfer full]

### gwy_serializable_assign()

    void
    gwy_serializable_assign (GwySerializable *destination,
                             GwySerializable *source);

Copies the value of an object to another object.

If `destination` is the same object as `source` the function is no-op.

What constitutes ‘object value’ depends on the class. The general rule is that `destination` will look as the result of `gwy_serializable_copy()`. However, it will keep its identity (address, connected signal handlers, references, object data, etc.). The operation may be more efficient than constructing a new object but it may be not.

GwySerializable implementations are encouraged to provide `my_object_assign()` convenience wrappers with arguments of the specific type and the corresponding type checking.

#### Parameters

destination | An object of the same type as `source` . More precisely, `source` may be subclass of `destination` (the extra information is lost then). |
source | A serializable object. |

### gwy_serializable_itemize()

    GwySerializableGroup *
    gwy_serializable_itemize (GwySerializable *serializable);

Creates the itemised representation of a serializable object.

This function wraps the virtual table method `itemize()`. It deals with initialisation and filling the object type name. Method `itemize()` then only serialises the actual data of the object. It should use `gwy_serializable_group_alloc()` to allocate the `items` array.

#### Parameters

serializable | A serializable object. | [transfer none]

#### Returns

Newly allocated itemised representation of `serializable` object components.

[transfer full]

### gwy_deserialize_error_quark()

    GQuark
    gwy_deserialize_error_quark (void);

Gets the error domain for deserialisation.

See and use `GWY_DESERIALIZE_ERROR`.

#### Returns

The error domain.

### gwy_serializable_done()

    void
    gwy_serializable_done (GwySerializable *serializable);

Frees temporary storage allocated by object itemization.

This function calls the virtual table method `done()`, if the class has any.

#### Parameters

serializable | A serializable object. |

### gwy_serializable_group_new()

    GwySerializableGroup *
    gwy_serializable_group_new (const gchar *name,
                                gsize nitems);

Creates a new group of serializable items.

Serialisable classes rarely need this function because their `itemize()` method already gets a GwySerializableGroup to fill.

#### Parameters

name | Group name, meanning object or boxed type name. Generally the type name of the GType. |
nitems | Minimum number of items to preallocate. |

#### Returns

A newly allocated group of serializable items.

[transfer full]

### gwy_serializable_group_alloc_size()

    void
    gwy_serializable_group_alloc_size (GwySerializableGroup *group,
                                       gsize nitems);

Ensures a minimum number of preallocated items in a itemised component list for serialisation.

The actual number of items preallocated can be larger than `nitems` . The new items are filled with zeros.

The function invalidates the pointer returned by `gwy_serializable_group_items()`.

#### Parameters

group | Itemised object components. |
nitems | Minimum size of `items` array to ensure. |

### gwy_serializable_group_free()

    void
    gwy_serializable_group_free (GwySerializableGroup *group,
                                 gboolean free_data,
                                 GwyErrorList **error_list);

Recursively frees lists of serialisation items.

Objects (and boxed types) can be either the actual objects or itemised into groups, provided that the `GWY_SERIALIZABLE_IS_GROUP` flags are set correctly. Recursive freeing descends into groups, not into objects. Hence, if there is an object-group split, it must have the natural form, where the top levels of the tree are groups and bottom levels are objects.

In serialisation, item data remain to be owned by the objects being serialised. They are not consumed. Therefore, one normally passes `free_data` =`FALSE` and `error_list` =`NULL` (otherwise every item would be reported as unconsumed).

In deserialisation, item data are normally consumed by the objects being constructed. If there any leftovers, they need to be freed. Therefore, one normally passes `free_data` =`TRUE` and non-`NULL` `error_list` (except after fatal errors when reporting all unconsumed items would be pointless clutter).

For convenience, `group` can be `NULL`. The function is no-op then.

The function does not call `gwy_serializable_group_done()`. A serialiser must call it beforehand if required.

#### Parameters

group | Itemised object components. | [nullable]
free_data | `TRUE` to free item data (deserialisation), `FALSE` to only free the groups (serialisation). |
error_list | Error list where to report unconsumed items (for deserialisation). | [nullable]

### gwy_serializable_group_name()

    const gchar *
    gwy_serializable_group_name (GwySerializableGroup *group);

Gets the name of a group of serialisable items.

The name name is the corresponding object or boxed type name. Generally the type name of the GType.

#### Parameters

group | Itemised object components. |

#### Returns

The group name.

[transfer none]

### gwy_serializable_group_rename()

    void
    gwy_serializable_group_rename (GwySerializableGroup *group,
                                   const gchar *name);

Renames a group of serializable items.

This function is rarely needed, except for cases like format translation.

#### Parameters

group | Itemised object components. |
name | New group name, meanning object or boxed type name. Generally the type name of the GType. It is not copied and must be a static, interned or other long-lived string. |

### gwy_serializable_group_size()

    gsize
    gwy_serializable_group_size (GwySerializableGroup *group);

Reports the data size of a list of serialisation items.

The size is only available in some context, in particular after `gwy_deserialize_group_memory()` or after calculating the sizes in serialisation.

#### Parameters

group | Shallowly itemised object components. |

#### Returns

Serialised data size, in bytes.

### gwy_serializable_group_items()

    GwySerializableItem *
    gwy_serializable_group_items (GwySerializableGroup *group,
                                  gsize *nitems);

Gets the entire array of items in a serialisable group.

#### Parameters

group | Itemised object components. |
nitems | Location where to store the number of items in the group. | [out][optional]

#### Returns

Array with all items in the group.

[transfer none][array length=nitems]

### gwy_serializable_group_discard()

    void
    gwy_serializable_group_discard (GwySerializableGroup *group,
                                    const gsize *indices,
                                    gsize nitems,
                                    gboolean free_data);

Discards items specified by indices from a serialisation group.

This is a low level functions useful only in format translation and similar tasks. See `gwy_deserialize_filter_items()` for a general helper filtering unwanted items during deserialisation. See `gwy_serializable_group_free()` for discussion of `free_data` .

#### Parameters

group | Itemised object components. |
indices | Indices of items to discard. |
nitems | The number of items to discard. | [array size=indices]
free_data | `TRUE` to free item data (deserialisation), `FALSE` to only remove items (serialisation). |

### gwy_serializable_group_itemize()

    void
    gwy_serializable_group_itemize (GwySerializableGroup *group);

Recursively itemises nested objects and boxed types for serialisation.

An object with nested object and boxed members can fill `v_object` and `v_boxed` fields in GwySerializableItem and call this function to replace all such fields with the corresponding GwySerializableGroup. The function also ensures `gwy_serializable_done()` is called on all objecst that need it after the serialisation is done.

Object arrays are also handled. Pay attention to memory management in such case. The function does not modify the elements of `v_object_array` . It replaces the entire array with a newly allocated array of groups. So you can have static or otherwise valuable arrays as `v_object_array` and it will be kept intact. On the other hand, if you allocated `v_object_array` dynamically on heap, you will need to free it. This can be done immediately after calling this function. The new array of groups is freed by `gwy_serializable_group_free()` and you do not normally need to concern yourself with freeing it.

Using this function is not necessary. An object can also directly invoke the nested itemisation during its serialisation. In such case the object must set the `GWY_SERIALIZABLE_IS_GROUP` flags and ensure that `gwy_serializable_done()` is called on object members as needed. The two approaches cannot be mixed.

#### Parameters

group | Shallowly itemised object components. |

### gwy_serializable_group_done()

    void
    gwy_serializable_group_done (GwySerializableGroup *group);

Recursively frees temporary object data for a list of serialisation items.

The functions is useful for serialisers, not individual classes implementing serialisation. It calls `gwy_serializable_done()` on all objects in `group` that need it, in the correct (i.e. backwards) order. This is normally done at the end of serialisation.

Keep in mind that it only releases whatever is inside the top-level serialised object. You also need to finally call `gwy_serializable_done()` on the top-level object itself to release its temporary data.

#### Parameters

group | Itemised object components. |

### gwy_serializable_group_append()

    void
    gwy_serializable_group_append (GwySerializableGroup *group,
                                   const GwySerializableItem *items,
                                   gsize nitems);

Appends pre-filled serialisable items to a group.

This is a low-level function. Objects should usually use functions such as `gwy_serializable_group_append_int32()` for serialisation.

#### Parameters

group | Itemised object components. |
items | Items to append. They will be shallow-copied to the group. | [array size=nitems][transfer none]
nitems | The number of items in `items` . |

### gwy_serializable_group_append_int8()

    void
    gwy_serializable_group_append_int8 (GwySerializableGroup *group,
                                        const GwySerializableItem *model,
                                        gint8 value);

Appends a serialisable item of type 8bit integer to a group.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_INT8` type). |
value | A 8bit integer member. |

### gwy_serializable_group_append_int16()

    void
    gwy_serializable_group_append_int16 (GwySerializableGroup *group,
                                         const GwySerializableItem *model,
                                         gint16 value);

Appends a serialisable item of type 16bit integer to a group.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_INT16` type). |
value | A 16bit integer member. |

### gwy_serializable_group_append_int32()

    void
    gwy_serializable_group_append_int32 (GwySerializableGroup *group,
                                         const GwySerializableItem *model,
                                         gint32 value);

Appends a serialisable item of type 32bit integer to a group.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_INT32` type). |
value | A 32bit integer member. |

### gwy_serializable_group_append_int64()

    void
    gwy_serializable_group_append_int64 (GwySerializableGroup *group,
                                         const GwySerializableItem *model,
                                         gint64 value);

Appends a serialisable item of type 64bit integer to a group.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_INT64` type). |
value | A 64bit integer member. |

### gwy_serializable_group_append_boolean()

    void
    gwy_serializable_group_append_boolean (GwySerializableGroup *group,
                                           const GwySerializableItem *model,
                                           gboolean value);

Appends a serialisable item of type boolean to a group.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_BOOLEAN` type). |
value | A boolean member. |

### gwy_serializable_group_append_float()

    void
    gwy_serializable_group_append_float (GwySerializableGroup *group,
                                         const GwySerializableItem *model,
                                         gfloat value);

Appends a serialisable item of type float to a group.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_FLOAT` type). |
value | A float member. |

### gwy_serializable_group_append_double()

    void
    gwy_serializable_group_append_double (GwySerializableGroup *group,
                                          const GwySerializableItem *model,
                                          gdouble value);

Appends a serialisable item of type double to a group.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_DOUBLE` type). |
value | A double member. |

### gwy_serializable_group_append_object()

    void
    gwy_serializable_group_append_object (GwySerializableGroup *group,
                                          const GwySerializableItem *model,
                                          GObject *object);

Appends a serialisable item of an object type to a group.

It is not an error to pass a `NULL` as `object` . A `NULL` member object is not serialised and no item is appended.

The object must continue to exist until serialisation is done.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_OBJECT` type). |
object | A member object. It must be serialisable. | [nullable]

### gwy_serializable_group_append_unit()

    void
    gwy_serializable_group_append_unit (GwySerializableGroup *group,
                                        const GwySerializableItem *model,
                                        GwyUnit *unit);

Appends a serialisable item of an unit type to a group.

This is a convenience function for the common case where the member object is a unit. It almost identical to `gwy_serializable_group_append_object()` except the argument type.

It is not an error to pass a `NULL` as `unit` . A `NULL` member unit is not serialised and no item is appended.

The unit must continue to exist until serialisation is done.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_OBJECT` type). |
unit | A member unit. | [nullable]

### gwy_serializable_group_append_boxed()

    void
    gwy_serializable_group_append_boxed (GwySerializableGroup *group,
                                         const GwySerializableItem *model,
                                         gconstpointer boxed);

Appends a serialisable item of type boxed to a group.

The `aux.boxed_type` field of `model` must be set to the specific boxed type.

The boxed pointer must continue to exist until serialisation is done.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_BOXED` type). |
boxed | A boxed member struct. |

### gwy_serializable_group_append_rgba()

    void
    gwy_serializable_group_append_rgba (GwySerializableGroup *group,
                                        const GwySerializableItem *model,
                                        const GwyRGBA *rgba);

Appends a serialisable item of type RGBA colour to a group.

The `aux.boxed_type` field of `model` must be `GWY_TYPE_RGBA` or zero. The latter is not useful if the template is also used for deserialisation and is thus not recommended.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_BOXED` type). |
rgba | An RGBA colour member struct. |

### gwy_serializable_group_append_string()

    void
    gwy_serializable_group_append_string (GwySerializableGroup *group,
                                          const GwySerializableItem *model,
                                          const gchar *string);

Appends a serialisable item of type string to a group.

It is not an error to pass a `NULL` as `string` . A `NULL` string is not serialised and no item is appended.

The string must continue to exist until serialisation is done.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_STRING` type). |
string | A string member. | [nullable]

### gwy_serializable_group_append_int8_array()

    void
    gwy_serializable_group_append_int8_array
                                   (GwySerializableGroup *group,
                                    const GwySerializableItem *model,
                                    const gint8 *values,
                                    gsize len);

Appends a serialisable item of type 8bit integer array to a group.

It is not an error to pass an empty array as `values` . If `len` is zero or `values` is `NULL`, the member is not serialised. It is valid to pass non-zero `len` with `NULL` `values` and vice versa.

The array must continue to exist until serialisation is done.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_INT8_ARRAY` type). |
values | An array of 8bit integers member. | [array length=len][nullable]
len | Number of elements in `values` . |

### gwy_serializable_group_append_int16_array()

    void
    gwy_serializable_group_append_int16_array
                                   (GwySerializableGroup *group,
                                    const GwySerializableItem *model,
                                    const gint16 *values,
                                    gsize len);

Appends a serialisable item of type 16bit integer array to a group.

It is not an error to pass an empty array as `values` . If `len` is zero or `values` is `NULL`, the member is not serialised. It is valid to pass non-zero `len` with `NULL` `values` and vice versa.

The array must continue to exist until serialisation is done.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_INT16_ARRAY` type). |
values | An array of 16bit integers member. | [array length=len][nullable]
len | Number of elements in `values` . |

### gwy_serializable_group_append_int32_array()

    void
    gwy_serializable_group_append_int32_array
                                   (GwySerializableGroup *group,
                                    const GwySerializableItem *model,
                                    const gint32 *values,
                                    gsize len);

Appends a serialisable item of type 32bit integer array to a group.

It is not an error to pass an empty array as `values` . If `len` is zero or `values` is `NULL`, the member is not serialised. It is valid to pass non-zero `len` with `NULL` `values` and vice versa.

The array must continue to exist until serialisation is done.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_INT32_ARRAY` type). |
values | An array of 32bit integers member. | [array length=len][nullable]
len | Number of elements in `values` . |

### gwy_serializable_group_append_int64_array()

    void
    gwy_serializable_group_append_int64_array
                                   (GwySerializableGroup *group,
                                    const GwySerializableItem *model,
                                    const gint64 *values,
                                    gsize len);

Appends a serialisable item of type 64bit integer array to a group.

It is not an error to pass an empty array as `values` . If `len` is zero or `values` is `NULL`, the member is not serialised. It is valid to pass non-zero `len` with `NULL` `values` and vice versa.

The array contents is never modified by this function.

#### Parameters

values | An array of 64bit integers member. | [array length=len][nullable]
len | Number of elements in `values` . |
model | Item template (of `GWY_SERIALIZABLE_INT64_ARRAY` type). |
group | Itemised object components to append to. |

### gwy_serializable_group_append_float_array()

    void
    gwy_serializable_group_append_float_array
                                   (GwySerializableGroup *group,
                                    const GwySerializableItem *model,
                                    const gfloat *values,
                                    gsize len);

Appends a serialisable item of type float array to a group.

It is not an error to pass an empty array as `values` . If `len` is zero or `values` is `NULL`, the member is not serialised. It is valid to pass non-zero `len` with `NULL` `values` and vice versa.

The array contents is never modified by this function.

#### Parameters

values | An array of floats member. | [array length=len][nullable]
len | Number of elements in `values` . |
model | Item template (of `GWY_SERIALIZABLE_FLOAT_ARRAY` type). |
group | Itemised object components to append to. |

### gwy_serializable_group_append_double_array()

    void
    gwy_serializable_group_append_double_array
                                   (GwySerializableGroup *group,
                                    const GwySerializableItem *model,
                                    const gdouble *values,
                                    gsize len);

Appends a serialisable item of type double array to a group.

It is not an error to pass an empty array as `values` . If `len` is zero or `values` is `NULL`, the member is not serialised. It is valid to pass non-zero `len` with `NULL` `values` and vice versa.

The array contents is never modified by this function.

#### Parameters

values | An array of doubles member. | [array length=len][nullable]
len | Number of elements in `values` . |
model | Item template (of `GWY_SERIALIZABLE_DOUBLE_ARRAY` type). |
group | Itemised object components to append to. |

### gwy_serializable_group_append_string_array()

    void
    gwy_serializable_group_append_string_array
                                   (GwySerializableGroup *group,
                                    const GwySerializableItem *model,
                                    gchar **strings,
                                    gsize len);

Appends a serialisable item of type string array to a group.

It is not an error to pass an empty array as `strings` . If `len` is zero, `strings` is `NULL` or `strings` is an array containing only `NULL` elements, the member is not serialised. Otherwise it is serialised and all the strings must exist. It is an error to pass `strings` array with some elements `NULL` and some non-`NULL`.

The array and the strings in it must continue to exist until serialisation is done.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_STRING_ARRAY` type). |
strings | A string array member. | [array length=len][nullable]
len | Number of elements in `strings` . |

### gwy_serializable_group_append_object_array()

    void
    gwy_serializable_group_append_object_array
                                   (GwySerializableGroup *group,
                                    const GwySerializableItem *model,
                                    GObject **objects,
                                    gsize len);

Appends a serialisable item of type object array to a group.

It is not an error to pass an empty array as `objects` . If `len` is zero, `objects` is `NULL` or `objects` is an array containing only `NULL` elements, the member is not serialised. Otherwise it is serialised and all the objects must exist. It is an error to pass `objects` array with some elements `NULL` and some non-`NULL`.

The array and the objects in it must continue to exist until serialisation is done.

#### Parameters

group | Itemised object components to append to. |
model | Item template (of `GWY_SERIALIZABLE_OBJECT_ARRAY` type). |
objects | An object array member. | [array length=len][nullable]
len | Number of elements in `objects` . |

### GWY_SERIALIZABLE_GET_INTERFACE()

    #define GWY_SERIALIZABLE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), GWY_TYPE_SERIALIZABLE, GwySerializableInterface))

## Types and Values

### enum GwySerializableCType

Type of serialisable value.

The type is a single byte, i.e. a value smaller than 256. It is equal to the character used in GWY files to denote the corresponding type.

Signed and usinged types are not distinguished here as their byte order is handled the same way.

#### Members

GWY_SERIALIZABLE_CONSUMED | Reserved type value which does not appear in files and denotes already consumed items internally. |
GWY_SERIALIZABLE_INT8 | Denotes a character (8bit integer). |
GWY_SERIALIZABLE_INT8_ARRAY | Denotes a character (8bit integer) array. |
GWY_SERIALIZABLE_BOOLEAN | Denotes a one-byte boolean. |
GWY_SERIALIZABLE_INT16 | Denotes a 16bit integer. |
GWY_SERIALIZABLE_INT16_ARRAY | Denotes an array of 16bit integers. |
GWY_SERIALIZABLE_INT32 | Denotes a 32bit integer. |
GWY_SERIALIZABLE_INT32_ARRAY | Denotes an array of 32bit integers. |
GWY_SERIALIZABLE_INT64 | Denotes a 64bit integer. |
GWY_SERIALIZABLE_INT64_ARRAY | Denotes an array of 64bit integers. |
GWY_SERIALIZABLE_FLOAT | Denotes a IEEE single (float). |
GWY_SERIALIZABLE_FLOAT_ARRAY | Denotes an array of IEEE singles (floats). |
GWY_SERIALIZABLE_DOUBLE | Denotes a IEEE double. |
GWY_SERIALIZABLE_DOUBLE_ARRAY | Denotes an array of IEEE doubles. |
GWY_SERIALIZABLE_STRING | Denotes a UTF-8-encoded C string. If you need a raw sequence of bytes, use `GWY_SERIALIZABLE_INT8_ARRAY` instead. |
GWY_SERIALIZABLE_STRING_ARRAY | Denotes an array of UTF-8 encoded C strings. |
GWY_SERIALIZABLE_OBJECT | Denotes an object. |
GWY_SERIALIZABLE_OBJECT_ARRAY | Denotes an array of objects. |
GWY_SERIALIZABLE_BOXED | Denotes a serialisable boxed type. |

### enum GwySerializeSizeType

Type of size representation in GWY files.

#### Members

GWY_SERIALIZE_SIZE_32BIT | The 32bit Gwyddion 2 format. |
GWY_SERIALIZE_SIZE_64BIT | The 64bit Gwyddion 3 format. |

### enum GwySerializableFlags

Flags denoting extra properties of items in intermediate serialisation representation.

#### Members

GWY_SERIALIZABLE_BIG_DATA |  |
GWY_SERIALIZABLE_TRANSFORMED |  |
GWY_SERIALIZABLE_IS_GROUP |  |

### union GwySerializableValue

Representation of individual values of object serialisable data.

See GwySerializableCType for corresponding type specifiers.

All string values must be valid UTF-8. If you need raw byte sequences use arrays of guint8.

Signed and unsigned integer members are provided for convenience, the serialisation does not distinguish between signed and unsigned integers.

Value type `v_size` has currently no use in implementations.

Value types `v_group` and `v_group_array` are used for the intermediate representation during serialisation and deserialisation. In serialisation, objects and boxed types are initially represented as `v_object` or `v_boxed` . Subsequently, they are transformed to GwySerializableGroup starting from the top-level object in the tree and going down. In deserialisation, the transformations go in the reverse order. Classes implementing GwySerializable do not need to deal with the representation of contained objects as groups (aside from calling `gwy_serializable_group_itemize()` at the end of their `itemize()`). They should only see objects, boxed types and objects arrays represented as the actual types, not GwySerializableGroup. The flag `GWY_SERIALIZABLE_IS_GROUP` is set when contained objects are itemised to groups.

#### Members

gboolean `v_boolean`; | The value as a gboolean. |
gint8 `v_int8`; | The value as a gint8. |
guint8 `v_uint8`; | The value as a guint8. |
gint16 `v_int16`; | The value as a gint16. |
guint16 `v_uint16`; | The value as a guint16. |
gint32 `v_int32`; | The value as a gint32. |
guint32 `v_uint32`; | The value as a guint32. |
gint64 `v_int64`; | The value as a gint64. |
guint64 `v_uint64`; | The value as a guint64. |
gfloat `v_float`; | The value as a gfloat. |
gdouble `v_double`; | The value as a gdouble. |
gchar *`v_string`; | The value as a gchar pointer. |
guchar *`v_ustring`; | The value as a guchar pointer. |
GObject *`v_object`; | The value as an object. |
gpointer `v_boxed`; | The value as a boxed type. |
gsize `v_size`; | The value as a gsize. |
GType `v_type`; | The value as a GType. |
gint8 *`v_int8_array`; | The value as an array of gint8s. |
guint8 *`v_uint8_array`; | The value as an array of guint8s. |
gint16 *`v_int16_array`; | The value as an array of gint16s. |
guint16 *`v_uint16_array`; | The value as an array of guint16s. |
gint32 *`v_int32_array`; | The value as an array of gint32s. |
guint32 *`v_uint32_array`; | The value as an array of guint32s. |
gint64 *`v_int64_array`; | The value as an array of gint64s. |
guint64 *`v_uint64_array`; | The value as an array of guint64s. |
gfloat *`v_float_array`; | The value as an array of gfloats. |
gdouble *`v_double_array`; | The value as an array of gdoubles. |
gchar **`v_string_array`; | The value as an array of gchar pointers. |
guchar **`v_ustring_array`; | The value as an array of guchar pointers. |
GObject **`v_object_array`; | The value as an array of objects. |
GwySerializableGroup *`v_group`; | The value of an object or boxed component as its own item group. |
GwySerializableGroup **`v_group_array`; | The value of an object or boxed component array as their own item groups. |

### GwySerializableAux

Auxiliary information about a serialised component.

It should be kept zero-filled when not used. Values `object_type` and `pspec` are optional and allow to delegate some type and range checking to the deserialiser, which will reject object or values not conforming to the expected type or range, and `serializable_construct()` can assume they have already been checked.

Value `boxed_type` is mandatory for boxed type components.

#### Members

GType `object_type`; | Expected object type for object-valued components. |
GType `boxed_type`; | Boxed type for boxed-valued components (mandatory). |
GParamSpec *`pspec`; | Parameter specification used for atomic value range validation. |

### struct GwySerializableItem

    struct GwySerializableItem {
        GwySerializableValue value;
        const gchar *name;
        gsize array_size;
        GwySerializableAux aux;
        GwySerializableFlags flags : 24;
        guchar ctype;
    };

Information about one object component that is subject to serialisation or deserialisation.

An item corresponds to ‘item’ in libgwyfile.

#### Members

GwySerializableValue `value`; | Item value, the interpreration depends on the `ctype` member. |
const gchar *`name`; | Component name. |
gsize `array_size`; | Array size of the component if of an array type. Unused otherwise but should be kept zero when not applicable. |
GwySerializableAux `aux`; | Auxiliary information about the item type and valid values, mostly optional. |
GwySerializableFlags `flags` : 24; | Auxiliary information about arrays and serialisation state. |
guchar `ctype`; | Item type, one of the GwySerializableCType enum. |

### GWY_DESERIALIZE_ERROR

    #define GWY_DESERIALIZE_ERROR gwy_deserialize_error_quark()

Error domain for deserialisation.

Errors in this domain will be from the GwyDeserializeError enumeration. See GError for information on error domains.

### enum GwyDeserializeError

Error codes returned by deserialisation.

In the error code descriptions, fatal error means aborting of deserialisation of the object that is just being unpacked. Non-fatal errors are competely recoverable. If the deserialisation of a contained object is aborted, the unpacking of the container object still continues. Therefore, fatal errors are truly fatal only if they occur for the top-level object.

#### Members

GWY_DESERIALIZE_ERROR_PADDING | There is too much data to represent given object. This error is non-fatal: the extra data is just ignored. |
GWY_DESERIALIZE_ERROR_ITEM | Unexpected item was encountered. This error is non-fatal: such item is just ignored. |
GWY_DESERIALIZE_ERROR_REPLACED | Invalid information (for instance an out-of-bounds value) was encountered and replaced (for instance by a default value). This error is non-fatal. Implementations should use it when they encounter invalid information but are able to proceed. |
GWY_DESERIALIZE_ERROR_FATAL_MASK | Distinguishes fatal and non-fatal errors (fatal give non-zero value when masked with this mask). |
GWY_DESERIALIZE_ERROR_TRUNCATED | Data ends in the middle of some item or there is not enough data to represent given object. This error is fatal. |
GWY_DESERIALIZE_ERROR_SIZE_T | Size is not representable on this system. This can occur on legacy 32bit systems, however, they are incapable of holding such large data in core anyway. This error is fatal. |
GWY_DESERIALIZE_ERROR_OBJECT | Representation of an object of unknown or deserialisation-incapable type was found. This error is fatal. |
GWY_DESERIALIZE_ERROR_DATA | Uknown data type (GwySerializableCType) was encountered or the object representation is internally inconsistent. This error is fatal. |
GWY_DESERIALIZE_ERROR_UTF8 | Serialised string is not valid UTF-8. This error is fatal. |
GWY_DESERIALIZE_ERROR_INVALID | Object representation is logicaly inconsistent or otherwise invalid. Reserved for classes to indicate data errors on levels higher than physical representation. This error is fatal. |

### GwySerializableGroup

    typedef struct _GwySerializableGroup GwySerializableGroup;

Representation of one object or boxed type during serialisation and deserialisation.

The groups reflect the tree-like structure of object members. They can contain nested groups inside for nested object and boxed type components. A group corresponds to ‘object’ in libgwyfile.

The structure has no public fields. Use functions such as `gwy_serializable_group_append_double()` to add more items during serialisation. Use `gwy_deserialize_filter_items()` to sort out items during deserialisation.

### GwySerializable

    typedef struct _GwySerializable GwySerializable;

Formal type of serialisable objects.

### struct GwySerializableInterface

    struct GwySerializableInterface {
        void             (*itemize)  (GwySerializable *serializable,
                                      GwySerializableGroup *group);
        void             (*done)     (GwySerializable *serializable);

        gboolean         (*construct)(GwySerializable *serializable,
                                      GwySerializableGroup *group,
                                      GwyErrorList **error_list);

        GwySerializable* (*copy)     (GwySerializable *serializable);
        void             (*assign)   (GwySerializable *destination,
                                      GwySerializable *source);
    };

Interface implemented by serialisable objects.

The object class must implement all the methods, except `GwySerializableInterface.done()` which is optional.

#### Members

`itemize`()

Creates itemised representation of the object data. It can employ many helper functions like `gwy_serializable_group_alloc_size()`, `gwy_serializable_group_itemize()` and functions for adding items of various types. If the object possibly contains member objects it must either call `gwy_serializable_group_itemize()` at the end (recommended) or ensure the contained objects are itemised too.

`done`() | Frees all temporary data created by `GwySerializableInterface.itemize()`. This method is optional but if it is defined it is guaranteed to be called after each `GwySerializableInterface.itemize()`. |

`construct`()

Deserialises an object from array of flattened data items. The first argument is the object of the final class (i.e. it may be a derived class), constructed with the default parameterless constructor.

All strings, objects and arrays in the item list are newly allocated. The method can (and, generally, should) take ownership by filling corresponding item values with `NULL`, setting their `array_size` to zero and setting the type to `GWY_SERIALIZABLE_CONSUMED`. The caller takes care of freeing them if they are not consumed by `construct()`.

This method must make any assumptions about the contents of `items`. Commonly, however, only items from a small predefined set are expected and then `gwy_deserialize_filter_items()` can be used to simplify the processing of the item list.

It is possible to chain this method to the parent class and pass it the the item list or a part of it, if you are careful.

`copy`() | Creates a new object with all data identical to this object. This method is expected to create a deep copy. Classes may provide other methods for shallow copies. |
`assign`() | Makes all data of this object identical to the data of another object of the same class. Implementations may assume that the is-a relation is satisfied for the source object. This method is expected to perform a deep copy. Classes may provide other methods for shallow copies. |