%% options copyright owner = Dirk Krause copyright year = 2015-xxxx license = bsd %% header /** @file Preferences as key/value pairs; the module contains functions to create and destroy a preference structure and to compare preference structures by name or against a given name. Typically preferences are stored in a dk4_sto_t structure. CRT on Windows: Optional. */ #ifndef DK4CONF_H_INCLUDED #include "dk4conf.h" #endif #ifndef DK4TYPES_H_INCLUDED #include "dk4types.h" #endif #ifndef DK4ERROR_H_INCLUDED #include "dk4error.h" #endif #ifndef DK4STR8_H_INCLUDED #include "dk4str8.h" #endif #ifndef DK4STRW_H_INCLUDED #include "dk4strw.h" #endif #ifndef DK4STRD_H_INCLUDED #include "dk4strd.h" #endif /** Preferences storage. */ typedef struct { dkChar *name; /**< Preference name. */ dkChar *value; /**< Value. */ } dk4_pref_t; #ifdef __cplusplus extern "C" { #endif /** Create preferences structure, allocate memory. @param name Preference name. @param value Preference value. @param erp Error report, may be NULL. @return Pointer to new preferences object on success, NULL on error. */ dk4_pref_t * dk4pref_open(dkChar const *name, dkChar const *value, dk4_er_t *erp); /** Destroy preference structure, release memory. @param ptr Preference structure to destroy. */ void dk4pref_close(dk4_pref_t *ptr); /** Comparison function. @param l Left pointer. @param r Right pointer. @param cr Comparison criteria: 0=structure/structure, 1=structure/name. @return Comparison result. */ int dk4pref_compare(const void *l, const void *r, int cr); #ifdef __cplusplus } #endif %% module #include "dk4pref.h" #include "dk4mem.h" $!trace-include dk4_pref_t * dk4pref_open(dkChar const *name, dkChar const *value, dk4_er_t *erp) { dk4_pref_t *back = NULL; $? "+ dk4pref_open \"%!ds\"=\"%!ds\"", TR_DKSTR(name), TR_DKSTR(value) if ((NULL != name) && (NULL != value)) { back = dk4mem_new(dk4_pref_t,1,erp); if (NULL != back) { back->name = NULL; back->value = NULL; back->name = dk4str_dup(name, erp); back->value = dk4str_dup(value, erp); if ((NULL == back->name) || (NULL == back->value)) { dk4pref_close(back); back = NULL; } } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } $? "- dk4pref_open PTR=%d", TR_IPTR(back) return back; } void dk4pref_close(dk4_pref_t *ptr) { $? "+ dk4pref_close" if (NULL != ptr) { $? ". \"%!ds\"=\"%!ds\"", TR_DKSTR(ptr->name), TR_DKSTR(ptr->value) #if 0 /* Original stuff. */ dk4mem_release(ptr->name); dk4mem_release(ptr->value); #endif /* 2016-12-10 Sanitize memory before releasing it. */ dk4str_release_sanitized(ptr->name); dk4str_release_sanitized(ptr->value); dk4mem_free(ptr); } $? "- dk4pref_close" } int dk4pref_compare(const void *l, const void *r, int cr) { const dk4_pref_t *pl; const dk4_pref_t *pr; int back = 0; $? "+ dk4pref_compare" if (NULL != l) { if (NULL != r) { pl = (const dk4_pref_t *)l; switch (cr) { case 1: { if (NULL != pl->name) { back = dk4str_cmp(pl->name, (const dkChar *)r); } else { back = -1; } } break; default: { pr = (const dk4_pref_t *)r; if (NULL != pl->name) { if (NULL != pr->name) { back = dk4str_cmp(pl->name, pr->name); } else { back = 1; } } else { if (NULL != pr->name) { back = -1; } } } break; } } else { back = 1; } } else { if (NULL != r) { back = -1; } } $? "- dk4pref_compare %d", back return back; }