#
libsff

Home | Modules | Examples

# CCMIO Error Handling

Error handling in C APIs is fairly cumbersome if you need to check for errors frequently, as you either need to check return values (or parameters) or a global error after each function call to ensure that the next one does not go bad. However, most of the time you would like to call API routines if there has been no error, otherwise skip until the end. libsff has appropriated error handling ideas from dataflow programming in an attempt to make error handling less cumbersome for the API user. All functions return an error, in case it is convenient, but most functions also take an error pointer, the value of which will be set to the error returned. Should the value of this pointer be an error upon entrance to the function, the function will do nothing. Occasionally you will want to test whether an function call will succeed. In this case, `NULL`, which is always interpreted as `kCCMIONoErr`, should be passed to the function and the return value checked for success. If the error pointer were passed then an error would be recorded and no succeeding function would execute, even though they should.

Dataflow error handling allows the API user to write code that opens a file, does some reading or writing, and then closes it, without checking for errors until the end. The API guarantees that any return parameters of the function will be usable (i.e not crash), unless otherwise documented, and that, should an error occur early on, all memory will properly be deallocated.

There are several things to keep in mind when using errors:

- Because this is a C, not C++ API, it is of paramount importance to initialize the error when it is created. Thus, an error should always be declared:

                      CCMIOError err = kCCMIONoErr;

  unless it is being assigned as a result of an API call (e.g. `CCMIOOpenFile`).
- Although `kCCMIONoErr` should always have a value of 0 (zero), it is preferable to compare errors to `kCCMIONoErr` to avoid confusion, since while `!err` is a correct test for an error, `!CCMIOOpenFile` reads like it checks for the failure of the function, but in reality returns true only if there was not an error. Thus

                      if (CCMIOOpenFile(...) != kCCMIONoErr)

  should be the canonical test.
- Either pass NULL for the error when looping through nodes or reset the error afterwards, because the terminal condition is that there is an error (`kCCMIONoNodeErr`):
  `i = 0;
  while (CCMIONextEntity(NULL, parentID, kCCMIOField, &i, &child) == kCCMIONoErr)
  ... do stuff ...
  `