%% options copyright owner = Dirk Krause copyright year = 2015-xxxx license = bsd %% header /** @file dk4dbitw.h Text (wchar_t) in database. */ #ifndef DK4DBI_H_INCLUDED #include #endif #if DK4_HAVE_WCHAR_H #ifndef WCHAR_H_INCLUDED #include #define WCHAR_H_INCLUDED 1 #endif #endif /** Function used when traversing a simple database. @param obj Object to modify during traversal. @param k Current key. @param v Current value. */ typedef int dk4dbi_wc_traverse_fct_t( void *obj, const wchar_t *k, const wchar_t *v ); #ifdef __cplusplus extern "C" { #endif /** Set text entry. @param db Database to modify. @param k Key text. @param v Value text. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if db, k or vis NULL, - DK4_E_SYNTAX
if the database was opened read-only or k or v is too long. - DK4_E_MATH_OVERFLOW
on numeric overflow in size calculation, - DK4_E_NOT_SUPPORTED
if db indicates an unsupported backend, - DK4_E_NOT_FOUND
if no record to delete was found, - DK4_E_MEMORY_ALLOCATION_FAILED
with mem.elsize and mem.nelem set if there is not enough memory available, - DK4_E_WRITE_FAILED
if modification of the database failed. */ int dk4dbi_wc_set( dk4_dbi_t *db, const wchar_t *k, const wchar_t *v, dk4_er_t *erp ); /** Retrieve text entry. @param db Database to query. @param k Key text. @param vbuf Result buffer address. @param vsz Pointer to size variable (in: size, out: used), number of wchar_t. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if db, k or vbufis NULL or vsz is 0, or the length of k exceeds the key size limit, - DK4_E_MATH_OVERFLOW
on numeric overflow in size calculation, - DK4_E_NOT_SUPPORTED
if db indicates an unsupported backend, - DK4_E_NOT_FOUND
if no record was found for the key, - DK4_E_BUFFER_TOO_SMALL
if the destination buffer is too small. */ int dk4dbi_wc_get( dk4_dbi_t *db, const wchar_t *k, wchar_t *vbuf, size_t vsz, dk4_er_t *erp ); /** Delete text entry. @param db Database to modify. @param k Key text. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if db or k is NULL, - DK4_E_SYNTAX
if the database is opened read-only or the length of k exceeds the key size limit, - DK4_E_MATH_OVERFLOW
on numeric overflow in size calculation, - DK4_E_NOT_SUPPORTED
if db indicates an unsupported backend, - DK4_E_WRITE_FAILED
if modification of the database failed, - DK4_E_NOT_FOUND
if no record for the specified key is in the database. */ int dk4dbi_wc_del( dk4_dbi_t *db, const wchar_t *k, dk4_er_t *erp ); /** Traverse database, apply function to all text entries. @param db Database to traverse. @param obj Object to modify during traversal. @param fct Function to apply to all text entries. @return 1 on success, 0 on error (database traversed), -1 on error (traversal aborted). */ int dk4dbi_wc_traverse( dk4_dbi_t *db, void *obj, dk4dbi_wc_traverse_fct_t *fct ); #ifdef __cplusplus } #endif %% module #include "dk4conf.h" #include "dk4strw.h" #include "dk4dbitw.h" #include "dk4maasz.h" $!trace-include /** Object for database traversal. */ typedef struct { void *obj; /**< Object for string traversal. */ dk4dbi_wc_traverse_fct_t *fct; /**< String traversal function. */ } dk4dbi_wc_traversal_object_t; int dk4dbi_wc_del( dk4_dbi_t *db, const wchar_t *k, dk4_er_t *erp ) { dk4_er_t er; size_t ks = 0; int back = 0; if ((NULL != db) && (NULL != k)) { dk4error_init(&er); ks = dk4ma_size_t_mul( sizeof(wchar_t), dk4ma_size_t_add(1, dk4strw_len(k), &er), &er ); if (DK4_E_NONE == er.ec) { back = dk4dbi_delete(db, k, ks, erp); } else { dk4error_copy(erp, &er); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } int dk4dbi_wc_set( dk4_dbi_t *db, const wchar_t *k, const wchar_t *v, dk4_er_t *erp ) { dk4_er_t er; size_t ks = 0; size_t vs = 0; int back = 0; if ((NULL != db) && (NULL != k)) { if (NULL != v) { dk4error_init(&er); ks = dk4ma_size_t_mul( sizeof(wchar_t), dk4ma_size_t_add(1, dk4strw_len(k), &er), &er ); vs = dk4ma_size_t_mul( sizeof(wchar_t), dk4ma_size_t_add(1, dk4strw_len(v), &er), &er ); if (DK4_E_NONE == er.ec) { back = dk4dbi_set(db, k, ks, v, vs, erp); } else { dk4error_copy(erp, &er); } } else { back = dk4dbi_wc_del(db, k, erp); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } int dk4dbi_wc_get( dk4_dbi_t *db, const wchar_t *k, wchar_t *vbuf, size_t vsz, dk4_er_t *erp ) { dk4_er_t er; size_t ks = 0; size_t ressz = 0; int back = 0; if ((NULL != vbuf) && (0 < vsz)) { *vbuf = L'\0'; } if ((NULL != db) && (NULL != k) && (NULL != vbuf) && (0 < vsz)) { dk4error_init(&er); ressz = dk4ma_size_t_mul(sizeof(wchar_t), vsz, &er); ks = dk4ma_size_t_mul( sizeof(wchar_t), dk4ma_size_t_add(1, dk4strw_len(k), &er), &er ); if (DK4_E_NONE == er.ec) { if (0 != dk4dbi_get(db, k, ks, vbuf, &ressz, erp)) { if (0 == (ressz % sizeof(wchar_t))) { ressz = ressz / sizeof(wchar_t); if (0 < ressz) { if (L'\0' == vbuf[ressz - 1]) { back = 1; } else { if (ressz < vsz) { vbuf[ressz] = L'\0'; back = 1; } else { *vbuf = L'\0'; dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } } } else { *vbuf = L'\0'; dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND); } } else { *vbuf = L'\0'; dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } } else { dk4error_copy(erp, &er); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } /** Function to traverse a simple database. The function must check the kb, ks, vb and vs arguments for validity, they are passed as found by the backend functions (this means pointers may be NULL, sizes may be 0). @param Object modified during traversal, may be NULL. @param kb Key data. @param ks Key size. @param vb Value data. @param vs Value size. @return 1 on success, 0 on error (can continue), -1 on error (abort). */ static int dk4dbi_wc_internal_traverse( void *obj, const void *kb, size_t ks, const void *vb, size_t vs ) { dk4dbi_wc_traversal_object_t *myobj; /* Passed from dk4dbi_traverse() */ const wchar_t *pk; /* Key pointer */ const wchar_t *pv; /* Value pointer */ int back = 0; if ((NULL != obj) && (NULL != kb) && (NULL != vb)) { if ((0 == (ks % sizeof(wchar_t))) && (0 == (vs % sizeof(wchar_t)))) { ks = ks / sizeof(wchar_t); vs = vs / sizeof(wchar_t); if ((0 < ks) && (0 < vs)) { pk = (const wchar_t *)kb; pv = (const wchar_t *)vb; if (('\0' == pk[ks - 1]) && ('\0' == pv[vs - 1])) { myobj = (dk4dbi_wc_traversal_object_t *)obj; back = (*(myobj->fct))(myobj->obj, pk, pv); } } } } return back; } int dk4dbi_wc_traverse( dk4_dbi_t *db, void *obj, dk4dbi_wc_traverse_fct_t *fct ) { dk4dbi_wc_traversal_object_t myobj; /* Passed to dk4dbi_traverse */ int back = -1; if ((NULL != db) && (NULL != fct)) { myobj.obj = obj; myobj.fct = fct; back = dk4dbi_traverse(db, &myobj, dk4dbi_wc_internal_traverse); } return back; }