Gwyfile Library
Gwyfile Library Documentation

The libgwyfile library contains fundamental functions for reading and writing Gwyddion GWY files as foreign data, i.e. without adopting the Gwyddion object system.

The latest libgwyfile source code and documentation can be found on the project web page at SourceForge.

Namespace

All macros, declarations and exported symbols bear the gwyfile prefix to avoid clash with other names. Specifically:

  • Macro names and constants such as enumerated values are all UPPER_CASE and prefixed with GWYFILE_.
  • Function names are all lower_case and prefixed with gwyfile_.
  • Type names are PascalCase and prefixed with Gwyfile.

Names of this form are to be treated as reserved and avoided for your own symbols. This is recommended even if you are embedding the library as it makes updating to its future versions easier.

Ownership rules

Since the GWY file data structures always form a forest of trees, object and items are either roots (including standalone objects and items) or owned by the parent object or item. When you add an item into an object or put an object to an object-holding item, you always transfer the ownership. Only the roots are owned by you.

Specific non-atomic data, such as arrays and strings, are also typically owned by the data item containing them and the item takes care of freeing them when destroyed itself. Specifically, this is always the case when they are created by reading a file. However, the ownership can be transferred between the item and you.

For creation of non-atomic data, there are three types of functions:

  • Plain, such as gwyfile_item_new_string(). They consume the data passed to them, i.e. ownership is passed from you to the item and, generally, you should not touch the data at all afterwards. The item will free the data with free() upon its own destruction.
  • Copying, such as gwyfile_item_new_string_copy(). They make a copy of the data passed to them. No ownership is transferred but, of course, it incurs some memory overhead.
  • Constant, such as gwyfile_item_new_string_const(). No copy is made and no ownership transferred. However, the data passed to such function must not cease to exists and must not change during the item lifetime. These functions are often the most efficient but they are also most prone to incorrect usage.

Each item construction function has also an item data-setting counterpart. For instance gwyfile_item_set_string(), gwyfile_item_set_string_copy() and gwyfile_item_set_string_const() correspond to the three string item construction functions mentioned above.

For obtaining of non-atomic data, two different types of functions exist:

  • Plain, such as gwyfile_item_get_string(). They return the data but keep the ownership hence the item will free the data when destroyed itself.
  • Taking, such as gwyfile_item_take_string(). Such function transfers the ownership from the item to the caller. Therefore, it can only be used if the item actually owns the data. Again, using these functions incurs the smallest overhead but requires more care.

Error handling

Roughly, libgwyfile distinguishes three severities of errors

  • Business as usual. These problems are expected to occur during normal operation and include I/O errors, data format errors or passing names of non-existent items to gwyfile_object_get() or gwyfile_object_remove(). They are reported by the return value. In the case of file-related operations, more details can be obtained via GwyfileError.
  • Trouble. This includes primarily failures to allocate large memory chunks in direct function calls such as gwyfile_item_new_double_array_copy(). They are reported by an abnormal function return value (usually NULL) and setting errno to ENOMEM. Note too large data encountered during the loading of a GWY file still belong to the previous category and are reported with error domain GWYFILE_ERROR_DOMAIN_SYSTEM and code ENOMEM.
  • Panic. The library panics and aborts via assert() if an invalid argument is passed to a function. This means the function cannot proceed without breaking invariants and likely causing heap or stack corruption down the road. Examples include trying to insert one item to multiple objects (breaking the forest of trees invariant), passing NULL as item or object arguments (where not permitted) or trying to take ownership of data that was already taken. The failure to allocate a small fixed-size chunk of memory (e.g. a _GwyfileObject struct) leads to the same reaction, as total heap exhaustion is a non-recoverable error for essentially all programs.

Version

This documentation was generated from the following source code revision:

$Id: gwyfile.c 399 2023-04-18 09:03:52Z yeti-dn $