Вопрос

I am writing a shared/dynamic library (https://github.com/zsawyer/mumble-LinkAPI).

For this I will provide some basic accessors (get, set and update) for the data in a shared memory struct (cannot be changed as it is externally defined). There are quite a number of accessors my library will provide. Getter and Setter methods are OK, imo, but my update functions give me trouble. They all pretty much will look the same - I smell a lot of code redundancy.

Note: I want to stick to C89! That is: I do not want to use C++ nor C99, C11.

Updating name is exemplary for almost all other update functions (arguments will vary):

ErrorCode updateName(wchar_t name[MAX_NAME_LENGTH]) {
    ErrorCode err = setName(name);
    if (err != ERROR_CODE_NO_ERROR) {
        return err;
    }
    return commit();
}

The error codes are defined in an enum:

/**
 * error codes hinting at the root cause of a failure
 */
typedef enum {
    /** no error */
    ERROR_CODE_NO_ERROR = 0,
    /** win32 specific: OpenFileMappingW failed to return a handle */
    ERROR_CODE_WIN32_NO_HANDLE = 1,
    /** win32 specific: MapViewOfFile failed to return a structure */
    ERROR_CODE_WIN32_NO_STRUCTURE = 2,
    /** unix specific: shm_open returned a negative integer */
    ERROR_CODE_UNIX_NO_HANDLE = 3,
    /** unix specific: mmap failed to return a structure */
    ERROR_CODE_UNIX_NO_STRUCTURE = 4,
    /** shared memory was not initialized */
    ERROR_CODE_NO_MEMORY_WAS_INITIALIZED = 5
} ErrorCode;

I want to pass the original error code all the way up to the caller of the library function while avoiding to write the same function x-times just with a different setXxx-function and parameter. I feel there should be an easier way.

Question: How can I rewrite the update functions to pass the ErrorCode and still reduce the code redundancy and make the function more readable/shorter?


Aside from that I caught myself at starting to copy a large part of the function documentation comments (i.e. that of set is 95% the same as of update methods), if you know any best practice to avoid that too, let me know.

Это было полезно?

Решение

How about defining a function

int commit_if_ok(int prev_error_code)
{
  if (prev_error_code != ERROR_CODE_NO_ERROR)
    return prev_error_code;
  else
    return commit();
}

and using it as:

ErrorCode updateName(wchar_t name[MAX_NAME_LENGTH])
{
  return commit_if_ok(setName(name));
}

Note that commit_if_ok may be an inline function if your particular compiler has directives to allow that (many older compilers don't, but some do), but it should not be a macro because it uses its argument twice.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top