## GwySerializable

GwySerializable — Abstract interface for serializable objects

## Functions

GByteArray * | (*GwySerializeFunc) ()
GObject * | (*GwyDeserializeFunc) ()
GByteArray * | gwy_serializable_serialize ()
GObject * | gwy_serializable_deserialize ()
GObject * | gwy_serializable_duplicate ()
void | gwy_serializable_clone ()
void | gwy_serializable_clone_with_type ()
gsize | gwy_serializable_get_size ()
gsize | gwy_serialize_get_struct_size ()
gsize | gwy_serialize_get_items_size ()
GByteArray * | gwy_serialize_pack_object_struct ()
gboolean | gwy_serialize_unpack_object_struct ()
gsize | gwy_serialize_check_string ()
GByteArray * | gwy_serialize_object_items ()
GwySerializeItem * | gwy_deserialize_object_hash ()
#define | GWY_SERIALIZABLE_GET_IFACE()

## Types and Values

| GwySerializeSpec
| GwySerializeValue
| GwySerializeItem
| GwySerializable
struct | GwySerializableIface

## Object Hierarchy

        GInterface
        ╰── GwySerializable

## Prerequisites

GwySerializable requires GObject.

## Known Implementations

GwySerializable is implemented by GwyContainer, GwySIUnit and GwyStringList.

## Includes

    #include <libgwyddion/gwyddion.h>

## Description

GwySerializable is an abstract interface for data-like object that can be serialized and deserialized. You can serialize any object implementing this interface with `gwy_serializable_serialize()` and the restore (deserialize) it with `gwy_serializable_deserialize()`. It is also posible it duplicate any such object with `gwy_serializable_duplicate()` and transform one object to copy of another with `gwy_serializable_clone()`.

Note all GwySerializable methods work with object `value', whatever it means for a particular type. Beside that, objects also have their identity which is unique and can't be subject of cloning. It consists of properties like memory address or references held by object users. Two important properties related to identity (and thus NOT retained) are: signals connected to a particular object and user data set with `g_object_set_data()` or `g_object_set_qdata()`.

You can implement serialization and deserialization in your classes with `gwy_serialize_pack_object_struct()` and `gwy_serialize_unpack_object_struct()` or with `gwy_serialize_object_items()` and `gwy_deserialize_object_hash()`. The former two are useful for struct-like objects (most objects are of this kind), the latter two for hash-like objects, i.e., objects that can contain components of arbitrary name and type. Serialized size calculations can be in most cases performed by `gwy_serialize_get_struct_size()` and `gwy_serialize_get_items_size()` helper functions.

## Functions

### GwySerializeFunc ()

    GByteArray *
    (*GwySerializeFunc) (GObject *serializable,
                         GByteArray *buffer);

The type of serialization method, see `gwy_serializable_serialize()` for description.

#### Parameters

serializable | An object to serialize. |
buffer | A buffer to append the representation to, may be `NULL` indicating a new one should be allocated. |

#### Returns

`buffer` with serialized object appended.

### GwyDeserializeFunc ()

    GObject *
    (*GwyDeserializeFunc) (const guchar *buffer,
                           gsize size,
                           gsize *position);

The type of deserialization method, see `gwy_serializable_deserialize()` for description.

#### Parameters

buffer | A buffer containing a serialized object. |
size | The size of `buffer` . |
position | The current position in `buffer` . |

#### Returns

A newly created (restored) object.

### gwy_serializable_serialize ()

    GByteArray *
    gwy_serializable_serialize (GObject *serializable,
                                GByteArray *buffer);

Serializes an object to byte buffer.

This is a high-level method. Do not use it for implementation of child object serialization (should you ever need to do it manually), it would lead to repeated required buffer size calculations.

#### Parameters

serializable | A GObject that implements GwySerializable interface. |
buffer | A buffer to which the serialized object should be appended, or `NULL` to allocate and return a new GByteArray. |

#### Returns

`buffer` or a newly allocated GByteArray with serialized object appended.

### gwy_serializable_deserialize ()

    GObject *
    gwy_serializable_deserialize (const guchar *buffer,
                                  gsize size,
                                  gsize *position);

Restores a serialized object from byte buffer.

The newly created object has reference count according to its nature, thus a GtkObject will have a floating reference, a GObject will have a refcount of 1, etc.

#### Parameters

buffer | A block of memory of size `size` contaning object representation. |
size | The size of `buffer` . |
position | The position of the object in `buffer` , it's updated to point after it. |

#### Returns

A newly created object.

### gwy_serializable_duplicate ()

    GObject *
    gwy_serializable_duplicate (GObject *object);

Creates a copy of an object.

If the object doesn't support duplication natively, it's brute-force serialized and then deserialized, this may be quite inefficient, namely for large objects.

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

#### Parameters

object | An object implementing GwySerializable interface. |

#### Returns

The newly created object copy. However if the object is a singleton, `object` itself (with incremented reference count) can be returned, too.

### gwy_serializable_clone ()

    void
    gwy_serializable_clone (GObject *source,
                            GObject *copy);

Makes an object identical to another object of the same type.

More precisely, `source` may be subclass of `copy` (the extra information is lost then).

#### Parameters

source | An object implementing GwySerializable interface. |
copy | An object of the same type as `source` to modify after it. |

### gwy_serializable_clone_with_type ()

    void
    gwy_serializable_clone_with_type (GObject *source,
                                      GObject *copy,
                                      GType type);

Makes an object identical to another object of the same type, with explicit type checking.

This function is the same as `gwy_serializable_clone()`, except it asserts the object type, which must be `type` .

Since 2.52

#### Parameters

source | An object implementing GwySerializable interface. |
copy | An object of the same type as `source` to modify after it. |
type | The type the objects are asserted to be. |

### gwy_serializable_get_size ()

    gsize
    gwy_serializable_get_size (GObject *serializable);

Calculates the expected size of serialized object.

#### Parameters

serializable | A GObject that implements GwySerializable interface. |

#### Returns

The expected size of serialized `serializable` .

### gwy_serialize_get_struct_size ()

    gsize
    gwy_serialize_get_struct_size (const guchar *object_name,
                                   gsize nspec,
                                   const GwySerializeSpec *spec);

Calculates serialized object size for struct-like objects.

The component specification is the same as in `gwy_serialize_pack_object_struct()`.

#### Parameters

object_name | The type name of the object. |
nspec | The number of items in `spec` . |
spec | The components to serialize. |

#### Returns

Serialized object size, it included space for object name and size. The value is exact unless some components are objects that do not return exact size estimate themselves.

### gwy_serialize_get_items_size ()

    gsize
    gwy_serialize_get_items_size (const guchar *object_name,
                                  gsize nitems,
                                  const GwySerializeItem *items);

Calculates serialized object size for hash-like objects.

The component specification is the same as in `gwy_serialize_object_items()`.

#### Parameters

object_name | The type name of the object. |
nitems | The number of `items` items. |
items | The components to serialize. |

#### Returns

Serialized object size, it included space for object name and size. The value is exact unless some components are objects that do not return exact size estimate themselves.

### gwy_serialize_pack_object_struct ()

    GByteArray *
    gwy_serialize_pack_object_struct (GByteArray *buffer,
                                      const guchar *object_name,
                                      gsize nspec,
                                      const GwySerializeSpec *spec);

Appends serialization of object with `g_type_name()` `object_name` and components described by `spec` to `buffer` in gwy-file format.

Here's how a serialization method of a simple object whose state is described by a single real number foo could look (without error checking):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    static guchar*
    my_object_serialize(GObject *obj,
                        guchar *buffer,
                        gsize *size)
    {
        MyObject *my_object = MY_OBJECT(obj);
        GwySerializeSpec spec[] = {
            { 'd', "foo", &my_object->foo, NULL, },
        };

        return gwy_serialize_pack_object_struct(buffer, size,
                                                "MyObject",
                                                G_N_ELEMENTS(spec), spec);
    }

#### Parameters

buffer | A buffer to which the serialized components should be appended. |
object_name | The type name of the object. |
nspec | The number of items in `spec` . |
spec | The components to serialize. |

#### Returns

The buffer with serialization of `spec` components appended.

### gwy_serialize_unpack_object_struct ()

    gboolean
    gwy_serialize_unpack_object_struct (const guchar *buffer,
                                        gsize size,
                                        gsize *position,
                                        const guchar *object_name,
                                        gsize nspec,
                                        GwySerializeSpec *spec);

Deserializes an object with named components packed into gwy-file format by `gwy_serialize_pack_object_struct()`.

Extra components are ignored (but cause a warning), components of different type than expected cause failure, missing components are not detected.

It is safe to pass pointers to existing non-atomic objects (strings, arrays, objects) in `spec` values, they will be dereferenced and freed as necessary when an unpacked value is about to replace them. For the same reason it is an error to pass pointers to unintialized memory there, always initialize non-atomic `spec` values to `NULL` pointers, at least.

Caller is responsible for use/clean-up of these values if deserialization succeeds or not.

Here's how a deserialization method of a simple object whose state is described by a single real number `foo` could look (without error checking):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    static GObject*
    my_object_deserialize(const guchar *buffer,
                          gsize size,
                          gsize *position)
    {
        double foo = 1.0;
        GwySerializeSpec spec[] = {
            { 'd', "foo", &foo, NULL, },
        };
        MyObject *my_object;

        gwy_serialize_unpack_object_struct(buffer, size, position,
                                           "MyObject",
                                           G_N_ELEMENTS(spec), spec);
        return my_object_new(foo);
    }

#### Parameters

buffer | A memory location containing a serialized object at position `position` . |
size | Current size of `buffer` , new size is returned here. |
position | The position of the object in `buffer` , it's updated to point after it. |
object_name | The type name of the object. |
nspec | The number of items in `spec` . |
spec | The components to deserialize. |

#### Returns

Whether the unpacking succeeded (see description body for definition of success and failure).

### gwy_serialize_check_string ()

    gsize
    gwy_serialize_check_string (const guchar *buffer,
                                gsize size,
                                gsize position,
                                const guchar *compare_to);

Check whether `size` bytes of memory in `buffer` can be interpreted as a NUL-terminated string, and eventually whether it's equal to `compare_to` .

When `compare_to` is `NULL`, the comparsion is not performed.

#### Parameters

buffer | A memory location containing a NUL-terminated string at position `position` . |
size | The size of `buffer` . |
position | The position of the string in `buffer` . |
compare_to | String to compare `buffer` to, or `NULL`. |

#### Returns

The length of the NUL-terminated string including the NUL character; zero otherwise.

### gwy_serialize_object_items ()

    GByteArray *
    gwy_serialize_object_items (GByteArray *buffer,
                                const guchar *object_name,
                                gsize nitems,
                                const GwySerializeItem *items);

Serializes an object to buffer in gwy-file format.

More precisely, it appends serialization of object with `g_type_name()` `object_name` with components described by `items` to `buffer` .

#### Parameters

buffer | A buffer to which the serialized components should be appended, or `NULL`. |
object_name | The type of the object. |
nitems | The number of `items` items. |
items | The components to serialize. |

#### Returns

`buffer` or a newly allocated GByteArray with serialization of `items` components appended.

### gwy_deserialize_object_hash ()

    GwySerializeItem *
    gwy_deserialize_object_hash (const guchar *buffer,
                                 gsize size,
                                 gsize *position,
                                 const guchar *object_name,
                                 gsize *nitems);

Deserializes an object with arbitrary components from gwy-file format.

This function works like `gwy_serialize_unpack_object_struct()`, except that it does not use any a priori knowledge of what the object contains. So instead of filling values in supplied GwySerializeSpec's, it constructs GwySerializeItem's completely from what is found in `buffer` . It does considerably less sanity checks and even allows several components of the same name.

#### Parameters

buffer | A block of memory of size `size` contaning object representation. |
size | The size of `buffer` . |
position | Current position in buffer, will be updated to point after object. |
object_name | The type name of the object. |
nitems | Where the number of deserialized components should be stored. |

#### Returns

A newly allocated array of deserialized components. Note the `name` fields of GwySerializeSpec's point to `buffer` and thus are valid only as long as `buffer` is; any arrays or strings are newly allocated and must be reused or freed by caller.

### GWY_SERIALIZABLE_GET_IFACE()

    #define GWY_SERIALIZABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), GWY_TYPE_SERIALIZABLE, GwySerializableIface))

## Types and Values

### GwySerializeSpec

    typedef struct {
        guchar ctype;
        const guchar *name;
        gpointer value;
        guint32 *array_size;
    } GwySerializeSpec;

A structure containing information for one object/struct component serialization or deserialization.

This component information is used in `gwy_serialize_pack_object_struct()` and `gwy_serialize_unpack_object_struct()` suitable for (de)serialization of struct-like objects.

Following atomic component types (`ctype` 's) exist: `'b'` for a boolean, `'c'` for a character, `'i'` for a 32bit integer, `'q'` for a 64bit integer, `'d'` for a gdouble, `'s'` for a NUL-terminated string, `'o'` for a serializable object.

And array component types: `'C'` for a character array, `'I'` for a 32bit integer array, `'Q'` for a 64bit integer array, `'D'` for a gdouble array, `'S'` for an array of NUL-terminated strings, `'O'` for an array of objects.

#### Members

guchar `ctype`; | Component type, see description body for possible values. |
const guchar *`name`; | Component name as a NUL-terminated string. |
gpointer `value`; | Pointer to component (always add one level of indirection; for an object, a GObject** pointer should be stored). If it is `NULL`, the component is ignored. For serialization it means it is not serialized, for deserialization it means its existence is acknowledged (no unknown component warning) but it's skipped instead of unpacking. |
guint32 *`array_size`; | Pointer to array size if component is an array, `NULL` otherwise. |

### GwySerializeValue

Helper serialization type that can hold any atomic value or pointer to non-atomic value.

#### Members

gboolean `v_boolean`; | Boolean. |
guchar `v_char`; | Character. |
guint32 `v_int32`; | 32bit integer. |
guint64 `v_int64`; | 64bit integer. |
gdouble `v_double`; | Double-precision float. |
guchar *`v_string`; | NUL-terminated string. |
GObject *`v_object`; | Object (serializable). |
gboolean *`v_boolean_array`; | Array of booleans. Not to be used. |
guchar *`v_char_array`; | Array of characters. |
guint32 *`v_int32_array`; | Array of 32bit integers. |
guint64 *`v_int64_array`; | Array of 64bit integers. |
gdouble *`v_double_array`; | Array of double-precision floats. |
guchar **`v_string_array`; | Array of NUL-terminated strings. |
GObject **`v_object_array`; | Array of objects (serializable). |

### GwySerializeItem

    typedef struct {
        guchar ctype;
        const guchar *name;
        GwySerializeValue value;
        guint32 array_size;
    } GwySerializeItem;

A structure containing information for one object/struct component serialization or deserialization.

This component information is used in `gwy_serialize_object_items()` and `gwy_deserialize_object_hash()` suitable for (de)serialization of hash-like objects.

#### Members

guchar `ctype`; | Component type, see GwySerializeSpec for details. |
const guchar *`name`; | Component name as a NUL-terminated string. |
GwySerializeValue `value`; | Component value. |
guint32 `array_size`; | Array size if component is an array, unused otherwise. |

### GwySerializable

    typedef struct _GwySerializable GwySerializable;

### struct GwySerializableIface

    struct GwySerializableIface {
        GwySerializeFunc serialize;
        GwyDeserializeFunc deserialize;
        void (*clone)(GObject *source, GObject *copy);
        GObject* (*duplicate)(GObject *object);
        gsize (*get_size)(GObject *object);
    };

The methods a serializable objects has to implement.

#### Members

GwySerializeFunc `serialize`; | Serialization method (obligatory), see GwySerializeFunc for description. |
GwyDeserializeFunc `deserialize`; | Restore method (obligatory), see GwyDeserializeFunc for description. |
`clone` () | Clone method (obligatory). Copies complete object `value' to an existing object of the same type. This method is called from copy's class if source and copy classes differ. |
`duplicate` () | Duplication method (optional). Creates a duplicate of an object. When it is absent, duplication is performed by a rather inefficient serialize-and-deserialize fallback. |
`get_size` () | Serialized size calculation method (optional). Calculates expected serialized object size (including object name and size header). Its purpose is to avoid frequent memory reallocations during serialization of large objects. The returned value may be inexact, a reasonable upper bound is sufficient. When it is absent, serialization is less efficient. |