FS-10167: Refactored simclist for ks-ification, and adjusted it for pool-based allocations and cleanup
This commit is contained in:
parent
8957953741
commit
075cd0d179
|
@ -43,7 +43,7 @@ struct blade_module_chat_s {
|
|||
blade_module_callbacks_t *module_callbacks;
|
||||
|
||||
const char *session_state_callback_id;
|
||||
list_t participants;
|
||||
ks_list_t *participants;
|
||||
};
|
||||
|
||||
|
||||
|
@ -87,7 +87,9 @@ ks_status_t blade_module_chat_create(blade_module_chat_t **bm_chatP, blade_handl
|
|||
bm_chat->pool = pool;
|
||||
bm_chat->tpool = blade_handle_tpool_get(bh);
|
||||
bm_chat->session_state_callback_id = NULL;
|
||||
list_init(&bm_chat->participants);
|
||||
|
||||
ks_list_create(&bm_chat->participants, pool);
|
||||
ks_assert(bm_chat->participants);
|
||||
|
||||
blade_module_create(&bm_chat->module, bh, bm_chat, &g_module_chat_callbacks);
|
||||
bm_chat->module_callbacks = &g_module_chat_callbacks;
|
||||
|
@ -110,7 +112,7 @@ ks_status_t blade_module_chat_destroy(blade_module_chat_t **bm_chatP)
|
|||
|
||||
blade_module_chat_on_shutdown(bm_chat->module);
|
||||
|
||||
list_destroy(&bm_chat->participants);
|
||||
ks_list_destroy(&bm_chat->participants);
|
||||
|
||||
blade_module_destroy(&bm_chat->module);
|
||||
|
||||
|
@ -257,7 +259,7 @@ void blade_module_chat_on_session_state(blade_session_t *bs, blade_session_state
|
|||
|
||||
cJSON_DeleteItemFromObject(props, "blade.chat.participant");
|
||||
|
||||
list_delete(&bm_chat->participants, blade_session_id_get(bs)); // @todo make copy of session id instead and search manually, also free the id
|
||||
ks_list_delete(bm_chat->participants, blade_session_id_get(bs)); // @todo make copy of session id instead and search manually, also free the id
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,7 +298,7 @@ ks_bool_t blade_chat_join_request_handler(blade_module_t *bm, blade_request_t *b
|
|||
if (props_participant) props_participant->type = cJSON_True;
|
||||
else cJSON_AddTrueToObject(props, "blade.chat.participant");
|
||||
|
||||
list_append(&bm_chat->participants, blade_session_id_get(bs)); // @todo make copy of session id instead and cleanup when removed
|
||||
ks_list_append(bm_chat->participants, blade_session_id_get(bs)); // @todo make copy of session id instead and cleanup when removed
|
||||
|
||||
blade_rpc_response_create(breq->pool, &res, NULL, breq->message_id);
|
||||
|
||||
|
@ -347,7 +349,7 @@ ks_bool_t blade_chat_leave_request_handler(blade_module_t *bm, blade_request_t *
|
|||
|
||||
cJSON_DeleteItemFromObject(props, "blade.chat.participant");
|
||||
|
||||
list_delete(&bm_chat->participants, blade_session_id_get(bs)); // @todo make copy of session id instead and search manually, also free the id
|
||||
ks_list_delete(bm_chat->participants, blade_session_id_get(bs)); // @todo make copy of session id instead and search manually, also free the id
|
||||
|
||||
blade_rpc_response_create(breq->pool, &res, NULL, breq->message_id);
|
||||
|
||||
|
@ -411,7 +413,7 @@ ks_bool_t blade_chat_send_request_handler(blade_module_t *bm, blade_request_t *b
|
|||
cJSON_AddStringToObject(res, "from", breq->session_id); // @todo should really be the identity, but we don't have that in place yet
|
||||
cJSON_AddStringToObject(res, "message", message);
|
||||
|
||||
blade_handle_sessions_send(breq->handle, &bm_chat->participants, NULL, event);
|
||||
blade_handle_sessions_send(breq->handle, bm_chat->participants, NULL, event);
|
||||
|
||||
cJSON_Delete(event);
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ struct blade_module_wss_s {
|
|||
struct pollfd *listeners_poll;
|
||||
int32_t listeners_count;
|
||||
|
||||
list_t connected; // @todo consider keeping this only as the list of connection id's, since the handle retains the pointer lookup
|
||||
ks_list_t *connected; // @todo consider keeping this only as the list of connection id's, since the handle retains the pointer lookup
|
||||
};
|
||||
|
||||
struct blade_transport_wss_s {
|
||||
|
@ -176,7 +176,8 @@ ks_status_t blade_module_wss_create(blade_module_wss_t **bm_wssP, blade_handle_t
|
|||
bm_wss->module_callbacks = &g_module_wss_callbacks;
|
||||
bm_wss->transport_callbacks = &g_transport_wss_callbacks;
|
||||
|
||||
list_init(&bm_wss->connected);
|
||||
ks_list_create(&bm_wss->connected, pool);
|
||||
ks_assert(bm_wss->connected);
|
||||
|
||||
*bm_wssP = bm_wss;
|
||||
|
||||
|
@ -198,7 +199,7 @@ ks_status_t blade_module_wss_destroy(blade_module_wss_t **bm_wssP)
|
|||
|
||||
blade_module_destroy(&bm_wss->module);
|
||||
|
||||
list_destroy(&bm_wss->connected);
|
||||
ks_list_destroy(&bm_wss->connected);
|
||||
|
||||
ks_pool_free(bm_wss->pool, bm_wssP);
|
||||
|
||||
|
@ -470,15 +471,15 @@ KS_DECLARE(ks_status_t) blade_module_wss_on_shutdown(blade_module_t *bm)
|
|||
bm_wss->listeners_count = 0;
|
||||
if (bm_wss->listeners_poll) ks_pool_free(bm_wss->pool, &bm_wss->listeners_poll);
|
||||
|
||||
if (list_size(&bm_wss->connected) > 0) {
|
||||
if (ks_list_size(bm_wss->connected) > 0) {
|
||||
// this approach to shutdown is cleaner, ensures connections will detach from sessions and be destroyed all in the same places
|
||||
list_iterator_start(&bm_wss->connected);
|
||||
while (list_iterator_hasnext(&bm_wss->connected)) {
|
||||
bc = (blade_connection_t *)list_iterator_next(&bm_wss->connected);
|
||||
ks_list_iterator_start(bm_wss->connected);
|
||||
while (ks_list_iterator_hasnext(bm_wss->connected)) {
|
||||
bc = (blade_connection_t *)ks_list_iterator_next(bm_wss->connected);
|
||||
blade_connection_disconnect(bc);
|
||||
}
|
||||
list_iterator_stop(&bm_wss->connected);
|
||||
while (list_size(&bm_wss->connected) > 0) ks_sleep_ms(100);
|
||||
ks_list_iterator_stop(bm_wss->connected);
|
||||
while (ks_list_size(bm_wss->connected) > 0) ks_sleep_ms(100);
|
||||
}
|
||||
|
||||
if (stopped) ks_log(KS_LOG_DEBUG, "Stopped\n");
|
||||
|
@ -590,7 +591,7 @@ void *blade_module_wss_listeners_thread(ks_thread_t *thread, void *data)
|
|||
ks_log(KS_LOG_DEBUG, "Connection (%s) started\n", blade_connection_id_get(bc));
|
||||
|
||||
blade_handle_connections_add(bc);
|
||||
list_append(&bm_wss->connected, bc);
|
||||
ks_list_append(bm_wss->connected, bc);
|
||||
blade_connection_state_set(bc, BLADE_CONNECTION_STATE_NEW);
|
||||
|
||||
blade_connection_read_unlock(bc);
|
||||
|
@ -726,7 +727,7 @@ ks_status_t blade_transport_wss_on_connect(blade_connection_t **bcP, blade_modul
|
|||
// @todo make sure it's sensible to be mixing outbound and inbound connections in the same list, but this allows entering the destruction pipeline
|
||||
// for module shutdown, disconnects and errors without special considerations
|
||||
blade_handle_connections_add(bc);
|
||||
list_append(&bm_wss->connected, bc);
|
||||
ks_list_append(bm_wss->connected, bc);
|
||||
|
||||
blade_connection_state_set(bc, BLADE_CONNECTION_STATE_NEW);
|
||||
|
||||
|
@ -866,7 +867,7 @@ blade_connection_state_hook_t blade_transport_wss_on_state_disconnect(blade_conn
|
|||
bt_wss = (blade_transport_wss_t *)blade_connection_transport_get(bc);
|
||||
bt_wss_init = (blade_transport_wss_init_t *)blade_connection_transport_init_get(bc);
|
||||
|
||||
list_delete(&bt_wss->module->connected, bc);
|
||||
ks_list_delete(bt_wss->module->connected, bc);
|
||||
|
||||
if (bt_wss_init) blade_transport_wss_init_destroy(&bt_wss_init);
|
||||
if (bt_wss) blade_transport_wss_destroy(&bt_wss); // @TODO: Scream at this very loudly until I feel better for it wasting 2 days to track down, and then fix the issue it's causing
|
||||
|
|
|
@ -45,7 +45,7 @@ struct blade_session_s {
|
|||
ks_mutex_t *mutex;
|
||||
ks_cond_t *cond;
|
||||
|
||||
list_t connections;
|
||||
ks_list_t *connections;
|
||||
ks_time_t ttl;
|
||||
|
||||
ks_q_t *sending;
|
||||
|
@ -94,11 +94,11 @@ static void blade_session_cleanup(ks_pool_t *pool, void *ptr, void *arg, ks_pool
|
|||
//}
|
||||
//list_iterator_stop(&bs->connections);
|
||||
|
||||
// called by list_destroy()
|
||||
//list_clear(&bs->connections);
|
||||
// called by ks_list_destroy()
|
||||
//ks_list_clear(&bs->connections);
|
||||
|
||||
// @todo change bs->connections to a pointer, allocate the memory in the pool, and set a cleanup callback for it to call list_destroy() automatically
|
||||
list_destroy(&bs->connections);
|
||||
// @todo change bs->connections to a pointer, allocate the memory in the pool, and set a cleanup callback for it to call ks_list_destroy() automatically
|
||||
ks_list_destroy(&bs->connections);
|
||||
// q has auto cleanup
|
||||
//ks_q_destroy(&bs->receiving);
|
||||
//ks_q_destroy(&bs->sending);
|
||||
|
@ -151,7 +151,9 @@ KS_DECLARE(ks_status_t) blade_session_create(blade_session_t **bsP, blade_handle
|
|||
ks_cond_create_ex(&bs->cond, pool, bs->mutex);
|
||||
ks_assert(bs->cond);
|
||||
|
||||
list_init(&bs->connections);
|
||||
ks_list_create(&bs->connections, pool);
|
||||
ks_assert(bs->connections);
|
||||
|
||||
ks_q_create(&bs->sending, pool, 0);
|
||||
ks_assert(bs->sending);
|
||||
ks_q_create(&bs->receiving, pool, 0);
|
||||
|
@ -375,7 +377,7 @@ KS_DECLARE(ks_status_t) blade_session_connections_add(blade_session_t *bs, const
|
|||
|
||||
ks_mutex_lock(bs->mutex);
|
||||
|
||||
list_append(&bs->connections, cid);
|
||||
ks_list_append(bs->connections, cid);
|
||||
|
||||
bs->ttl = 0;
|
||||
|
||||
|
@ -396,18 +398,18 @@ KS_DECLARE(ks_status_t) blade_session_connections_remove(blade_session_t *bs, co
|
|||
|
||||
ks_mutex_lock(bs->mutex);
|
||||
|
||||
size = list_size(&bs->connections);
|
||||
size = ks_list_size(bs->connections);
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
const char *cid = (const char *)list_get_at(&bs->connections, i);
|
||||
const char *cid = (const char *)ks_list_get_at(bs->connections, i);
|
||||
if (!strcasecmp(cid, id)) {
|
||||
ks_log(KS_LOG_DEBUG, "Session (%s) connection removed (%s)\n", bs->id, id);
|
||||
list_delete_at(&bs->connections, i);
|
||||
ks_list_delete_at(bs->connections, i);
|
||||
ks_pool_free(bs->pool, &cid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (list_size(&bs->connections) == 0) bs->ttl = ks_time_now() + (5 * KS_USEC_PER_SEC);
|
||||
if (ks_list_size(bs->connections) == 0) bs->ttl = ks_time_now() + (5 * KS_USEC_PER_SEC);
|
||||
|
||||
ks_mutex_unlock(bs->mutex);
|
||||
|
||||
|
@ -428,7 +430,7 @@ ks_status_t blade_session_connections_choose(blade_session_t *bs, cJSON *json, b
|
|||
|
||||
// @todo may be multiple connections, for now let's just assume there will be only one
|
||||
// later there will need to be a way to pick which connection to use
|
||||
cid = list_get_at(&bs->connections, 0);
|
||||
cid = ks_list_get_at(bs->connections, 0);
|
||||
if (!cid) {
|
||||
// no connections available
|
||||
ret = KS_STATUS_FAIL;
|
||||
|
@ -515,7 +517,7 @@ void *blade_session_state_thread(ks_thread_t *thread, void *data)
|
|||
|
||||
state = bs->state;
|
||||
|
||||
if (!list_empty(&bs->connections)) {
|
||||
if (!ks_list_empty(bs->connections)) {
|
||||
while (blade_session_sending_pop(bs, &json) == KS_STATUS_SUCCESS && json) {
|
||||
blade_connection_t *bc = NULL;
|
||||
if (blade_session_connections_choose(bs, json, &bc) == KS_STATUS_SUCCESS) {
|
||||
|
@ -554,7 +556,7 @@ void *blade_session_state_thread(ks_thread_t *thread, void *data)
|
|||
default: break;
|
||||
}
|
||||
|
||||
if (list_empty(&bs->connections) &&
|
||||
if (ks_list_empty(bs->connections) &&
|
||||
bs->ttl > 0 &&
|
||||
!blade_session_terminating(bs) &&
|
||||
ks_time_now() >= bs->ttl) {
|
||||
|
@ -587,20 +589,20 @@ ks_status_t blade_session_state_on_hangup(blade_session_t *bs)
|
|||
|
||||
ks_log(KS_LOG_DEBUG, "Session (%s) state hangup\n", bs->id);
|
||||
|
||||
list_iterator_start(&bs->connections);
|
||||
while (list_iterator_hasnext(&bs->connections)) {
|
||||
const char *cid = (const char *)list_iterator_next(&bs->connections);
|
||||
ks_list_iterator_start(bs->connections);
|
||||
while (ks_list_iterator_hasnext(bs->connections)) {
|
||||
const char *cid = (const char *)ks_list_iterator_next(bs->connections);
|
||||
blade_connection_t *bc = blade_handle_connections_get(bs->handle, cid);
|
||||
ks_assert(bc);
|
||||
|
||||
blade_connection_disconnect(bc);
|
||||
blade_connection_read_unlock(bc);
|
||||
}
|
||||
list_iterator_stop(&bs->connections);
|
||||
ks_list_iterator_stop(bs->connections);
|
||||
|
||||
// @todo review this code, it may end up blocking forever as the mutex for the session is locked and the connection thread will not be able to lock to remove the connection...
|
||||
// isolate another mutex for the connection list, simclist is not intrinsicly thread safe like other containers
|
||||
while (!list_empty(&bs->connections)) ks_sleep(100);
|
||||
while (!ks_list_empty(bs->connections)) ks_sleep(100);
|
||||
|
||||
blade_session_state_set(bs, BLADE_SESSION_STATE_DESTROY);
|
||||
|
||||
|
@ -616,7 +618,7 @@ ks_status_t blade_session_state_on_ready(blade_session_t *bs)
|
|||
//ks_log(KS_LOG_DEBUG, "Session (%s) state ready\n", bs->id);
|
||||
|
||||
// @todo for now only process messages if there is a connection available
|
||||
if (list_size(&bs->connections) > 0) {
|
||||
if (ks_list_size(bs->connections) > 0) {
|
||||
// @todo may only want to pop once per call to give sending a chance to keep up
|
||||
while (blade_session_receiving_pop(bs, &json) == KS_STATUS_SUCCESS && json) {
|
||||
blade_session_process(bs, json);
|
||||
|
@ -664,7 +666,7 @@ KS_DECLARE(ks_status_t) blade_session_send(blade_session_t *bs, cJSON *json, bla
|
|||
ks_log(KS_LOG_DEBUG, "Session (%s) sending response (%s)\n", bs->id, id);
|
||||
}
|
||||
|
||||
if (list_empty(&bs->connections)) {
|
||||
if (ks_list_empty(bs->connections)) {
|
||||
blade_session_sending_push(bs, json);
|
||||
} else {
|
||||
blade_connection_t *bc = NULL;
|
||||
|
|
|
@ -711,7 +711,7 @@ KS_DECLARE(ks_status_t) blade_handle_sessions_remove(blade_session_t *bs)
|
|||
return ret;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) blade_handle_sessions_send(blade_handle_t *bh, list_t *sessions, const char *exclude, cJSON *json)
|
||||
KS_DECLARE(void) blade_handle_sessions_send(blade_handle_t *bh, ks_list_t *sessions, const char *exclude, cJSON *json)
|
||||
{
|
||||
blade_session_t *bs = NULL;
|
||||
|
||||
|
@ -719,9 +719,9 @@ KS_DECLARE(void) blade_handle_sessions_send(blade_handle_t *bh, list_t *sessions
|
|||
ks_assert(sessions);
|
||||
ks_assert(json);
|
||||
|
||||
list_iterator_start(sessions);
|
||||
while (list_iterator_hasnext(sessions)) {
|
||||
const char *sessionid = list_iterator_next(sessions);
|
||||
ks_list_iterator_start(sessions);
|
||||
while (ks_list_iterator_hasnext(sessions)) {
|
||||
const char *sessionid = ks_list_iterator_next(sessions);
|
||||
if (exclude && !strcmp(exclude, sessionid)) continue;
|
||||
bs = blade_handle_sessions_get(bh, sessionid);
|
||||
if (!bs) {
|
||||
|
@ -731,7 +731,7 @@ KS_DECLARE(void) blade_handle_sessions_send(blade_handle_t *bh, list_t *sessions
|
|||
blade_session_send(bs, json, NULL);
|
||||
blade_session_read_unlock(bs);
|
||||
}
|
||||
list_iterator_stop(sessions);
|
||||
ks_list_iterator_stop(sessions);
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) blade_handle_session_state_callback_register(blade_handle_t *bh, void *data, blade_session_state_callback_t callback, const char **id)
|
||||
|
|
|
@ -68,7 +68,7 @@ KS_DECLARE(ks_status_t) blade_handle_connections_remove(blade_connection_t *bc);
|
|||
KS_DECLARE(blade_session_t *) blade_handle_sessions_get(blade_handle_t *bh, const char *sid);
|
||||
KS_DECLARE(ks_status_t) blade_handle_sessions_add(blade_session_t *bs);
|
||||
KS_DECLARE(ks_status_t) blade_handle_sessions_remove(blade_session_t *bs);
|
||||
KS_DECLARE(void) blade_handle_sessions_send(blade_handle_t *bh, list_t *sessions, const char *exclude, cJSON *json);
|
||||
KS_DECLARE(void) blade_handle_sessions_send(blade_handle_t *bh, ks_list_t *sessions, const char *exclude, cJSON *json);
|
||||
KS_DECLARE(ks_status_t) blade_handle_session_state_callback_register(blade_handle_t *bh, void *data, blade_session_state_callback_t callback, const char **id);
|
||||
KS_DECLARE(ks_status_t) blade_handle_session_state_callback_unregister(blade_handle_t *bh, const char *id);
|
||||
KS_DECLARE(void) blade_handle_session_state_callbacks_execute(blade_session_t *bs, blade_session_state_condition_t condition);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
|
||||
/*
|
||||
* SimCList library. See http://mij.oltrelinux.com/devel/simclist
|
||||
* Original SimCList library. See http://mij.oltrelinux.com/devel/simclist
|
||||
*/
|
||||
|
||||
|
||||
|
@ -59,7 +59,7 @@ extern "C" {
|
|||
*
|
||||
* This is a signed integer value.
|
||||
*/
|
||||
typedef int32_t list_hash_t;
|
||||
typedef int32_t ks_list_hash_t;
|
||||
|
||||
#ifndef SIMCLIST_NO_DUMPRESTORE
|
||||
typedef struct {
|
||||
|
@ -67,10 +67,10 @@ extern "C" {
|
|||
struct timeval timestamp; /* when the list has been dumped, seconds since UNIX epoch */
|
||||
uint32_t list_size;
|
||||
uint32_t list_numels;
|
||||
list_hash_t list_hash; /* hash of the list when dumped, or 0 if invalid */
|
||||
ks_list_hash_t list_hash; /* hash of the list when dumped, or 0 if invalid */
|
||||
uint32_t dumpsize;
|
||||
int consistent; /* 1 if the dump is verified complete/consistent; 0 otherwise */
|
||||
} list_dump_info_t;
|
||||
} ks_list_dump_info_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -106,7 +106,7 @@ extern "C" {
|
|||
*
|
||||
* It is responsability of the function to handle possible NULL values.
|
||||
*/
|
||||
typedef size_t(*element_meter)(const void *el);
|
||||
typedef ks_size_t(*element_meter)(const void *el);
|
||||
|
||||
/**
|
||||
* a function computing the hash of elements.
|
||||
|
@ -117,7 +117,7 @@ extern "C" {
|
|||
*
|
||||
* It is responsability of the function to handle possible NULL values.
|
||||
*/
|
||||
typedef list_hash_t(*element_hash_computer)(const void *el);
|
||||
typedef ks_list_hash_t(*element_hash_computer)(const void *el);
|
||||
|
||||
/**
|
||||
* a function for serializing an element.
|
||||
|
@ -157,16 +157,16 @@ extern "C" {
|
|||
typedef void *(*element_unserializer)(const void *restrict data, uint32_t *restrict data_len);
|
||||
|
||||
/* [private-use] list entry -- olds actual user datum */
|
||||
struct list_entry_s {
|
||||
struct ks_list_entry_s {
|
||||
void *data;
|
||||
|
||||
/* doubly-linked list service references */
|
||||
struct list_entry_s *next;
|
||||
struct list_entry_s *prev;
|
||||
struct ks_list_entry_s *next;
|
||||
struct ks_list_entry_s *prev;
|
||||
};
|
||||
|
||||
/* [private-use] list attributes */
|
||||
struct list_attributes_s {
|
||||
struct ks_list_attributes_s {
|
||||
/* user-set routine for comparing list elements */
|
||||
element_comparator comparator;
|
||||
/* user-set routing for seeking elements */
|
||||
|
@ -184,14 +184,15 @@ extern "C" {
|
|||
|
||||
/** list object */
|
||||
typedef struct {
|
||||
struct list_entry_s *head_sentinel;
|
||||
struct list_entry_s *tail_sentinel;
|
||||
struct list_entry_s *mid;
|
||||
ks_pool_t *pool;
|
||||
struct ks_list_entry_s *head_sentinel;
|
||||
struct ks_list_entry_s *tail_sentinel;
|
||||
struct ks_list_entry_s *mid;
|
||||
|
||||
unsigned int numels;
|
||||
|
||||
/* array of spare elements */
|
||||
struct list_entry_s **spareels;
|
||||
struct ks_list_entry_s **spareels;
|
||||
unsigned int spareelsnum;
|
||||
|
||||
#ifdef SIMCLIST_WITH_THREADS
|
||||
|
@ -202,30 +203,32 @@ extern "C" {
|
|||
/* service variables for list iteration */
|
||||
int iter_active;
|
||||
unsigned int iter_pos;
|
||||
struct list_entry_s *iter_curentry;
|
||||
struct ks_list_entry_s *iter_curentry;
|
||||
|
||||
/* list attributes */
|
||||
struct list_attributes_s attrs;
|
||||
} list_t;
|
||||
struct ks_list_attributes_s attrs;
|
||||
} ks_list_t;
|
||||
|
||||
/**
|
||||
* initialize a list object for use.
|
||||
*
|
||||
* @param l must point to a user-provided memory location
|
||||
* @return 0 for success. -1 for failure
|
||||
* @param list must point to a user-provided memory location for a pointer to allocate
|
||||
* @param pool pool for lifecycle and auto cleanup
|
||||
* @return KS_STATUS_SUCCESS for success.
|
||||
*/
|
||||
KS_DECLARE(int) list_init(list_t *restrict l);
|
||||
KS_DECLARE(ks_status_t) ks_list_create(ks_list_t **list, ks_pool_t *pool);
|
||||
|
||||
/**
|
||||
* completely remove the list from memory.
|
||||
*
|
||||
* This function is the inverse of list_init(). It is meant to be called when
|
||||
* This function is the inverse of ks_list_create(). It is meant to be called when
|
||||
* the list is no longer going to be used. Elements and possible memory taken
|
||||
* for internal use are freed.
|
||||
*
|
||||
* @param l list to destroy
|
||||
* @param list pointer to pointer of list to destroy
|
||||
* @return KS_STATUS_SUCCESS for success.
|
||||
*/
|
||||
KS_DECLARE(void) list_destroy(list_t *restrict l);
|
||||
KS_DECLARE(ks_status_t) ks_list_destroy(ks_list_t **list);
|
||||
|
||||
/**
|
||||
* set the comparator function for list elements.
|
||||
|
@ -239,7 +242,7 @@ extern "C" {
|
|||
*
|
||||
* @see element_comparator()
|
||||
*/
|
||||
int list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun);
|
||||
int ks_list_attributes_comparator(ks_list_t *restrict l, element_comparator comparator_fun);
|
||||
|
||||
/**
|
||||
* set a seeker function for list elements.
|
||||
|
@ -253,7 +256,7 @@ extern "C" {
|
|||
*
|
||||
* @see element_seeker()
|
||||
*/
|
||||
int list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun);
|
||||
int ks_list_attributes_seeker(ks_list_t *restrict l, element_seeker seeker_fun);
|
||||
|
||||
/**
|
||||
* require to free element data when list entry is removed (default: don't free).
|
||||
|
@ -273,19 +276,19 @@ extern "C" {
|
|||
* @return 0 if the attribute was successfully set; -1 otherwise
|
||||
*
|
||||
* @see element_meter()
|
||||
* @see list_meter_int8_t()
|
||||
* @see list_meter_int16_t()
|
||||
* @see list_meter_int32_t()
|
||||
* @see list_meter_int64_t()
|
||||
* @see list_meter_uint8_t()
|
||||
* @see list_meter_uint16_t()
|
||||
* @see list_meter_uint32_t()
|
||||
* @see list_meter_uint64_t()
|
||||
* @see list_meter_float()
|
||||
* @see list_meter_double()
|
||||
* @see list_meter_string()
|
||||
* @see ks_list_meter_int8_t()
|
||||
* @see ks_list_meter_int16_t()
|
||||
* @see ks_list_meter_int32_t()
|
||||
* @see ks_list_meter_int64_t()
|
||||
* @see ks_list_meter_uint8_t()
|
||||
* @see ks_list_meter_uint16_t()
|
||||
* @see ks_list_meter_uint32_t()
|
||||
* @see ks_list_meter_uint64_t()
|
||||
* @see ks_list_meter_float()
|
||||
* @see ks_list_meter_double()
|
||||
* @see ks_list_meter_string()
|
||||
*/
|
||||
int list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data);
|
||||
int ks_list_attributes_copy(ks_list_t *restrict l, element_meter metric_fun, int copy_data);
|
||||
|
||||
/**
|
||||
* set the element hash computing function for the list elements.
|
||||
|
@ -305,7 +308,7 @@ extern "C" {
|
|||
*
|
||||
* @see element_hash_computer()
|
||||
*/
|
||||
int list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun);
|
||||
int ks_list_attributes_hash_computer(ks_list_t *restrict l, element_hash_computer hash_computer_fun);
|
||||
|
||||
/**
|
||||
* set the element serializer function for the list elements.
|
||||
|
@ -314,19 +317,19 @@ extern "C" {
|
|||
*
|
||||
* Serialize functions are used for dumping the list to some persistent
|
||||
* storage. The serializer function is called for each element; it is passed
|
||||
* a reference to the element and a reference to a size_t object. It will
|
||||
* a reference to the element and a reference to a ks_size_t object. It will
|
||||
* provide (and return) the buffer with the serialization of the element and
|
||||
* fill the size_t object with the length of this serialization data.
|
||||
* fill the ks_size_t object with the length of this serialization data.
|
||||
*
|
||||
* @param l list to operate
|
||||
* @param serializer_fun pointer to the actual serializer function
|
||||
* @return 0 if the attribute was successfully set; -1 otherwise
|
||||
*
|
||||
* @see element_serializer()
|
||||
* @see list_dump_filedescriptor()
|
||||
* @see list_restore_filedescriptor()
|
||||
* @see ks_list_dump_filedescriptor()
|
||||
* @see ks_list_restore_filedescriptor()
|
||||
*/
|
||||
int list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun);
|
||||
int ks_list_attributes_serializer(ks_list_t *restrict l, element_serializer serializer_fun);
|
||||
|
||||
/**
|
||||
* set the element unserializer function for the list elements.
|
||||
|
@ -345,10 +348,10 @@ extern "C" {
|
|||
* @return 0 if the attribute was successfully set; -1 otherwise
|
||||
*
|
||||
* @see element_unserializer()
|
||||
* @see list_dump_filedescriptor()
|
||||
* @see list_restore_filedescriptor()
|
||||
* @see ks_list_dump_filedescriptor()
|
||||
* @see ks_list_restore_filedescriptor()
|
||||
*/
|
||||
int list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun);
|
||||
int ks_list_attributes_unserializer(ks_list_t *restrict l, element_unserializer unserializer_fun);
|
||||
|
||||
/**
|
||||
* append data at the end of the list.
|
||||
|
@ -360,7 +363,7 @@ extern "C" {
|
|||
*
|
||||
* @return 1 for success. < 0 for failure
|
||||
*/
|
||||
KS_DECLARE(int) list_append(list_t *restrict l, const void *data);
|
||||
KS_DECLARE(int) ks_list_append(ks_list_t *restrict l, const void *data);
|
||||
|
||||
/**
|
||||
* insert data in the head of the list.
|
||||
|
@ -372,7 +375,7 @@ extern "C" {
|
|||
*
|
||||
* @return 1 for success. < 0 for failure
|
||||
*/
|
||||
KS_DECLARE(int) list_prepend(list_t *restrict l, const void *restrict data);
|
||||
KS_DECLARE(int) ks_list_prepend(ks_list_t *restrict l, const void * data);
|
||||
|
||||
/**
|
||||
* extract the element in the top of the list.
|
||||
|
@ -382,7 +385,7 @@ extern "C" {
|
|||
* @param l list to operate
|
||||
* @return reference to user datum, or NULL on errors
|
||||
*/
|
||||
KS_DECLARE(void *) list_fetch(list_t *restrict l);
|
||||
KS_DECLARE(void *) ks_list_fetch(ks_list_t *restrict l);
|
||||
|
||||
/**
|
||||
* retrieve an element at a given position.
|
||||
|
@ -391,7 +394,7 @@ extern "C" {
|
|||
* @param pos [0,size-1] position index of the element wanted
|
||||
* @return reference to user datum, or NULL on errors
|
||||
*/
|
||||
KS_DECLARE(void *) list_get_at(const list_t *restrict l, unsigned int pos);
|
||||
KS_DECLARE(void *) ks_list_get_at(const ks_list_t *restrict l, unsigned int pos);
|
||||
|
||||
/**
|
||||
* return the maximum element of the list.
|
||||
|
@ -400,12 +403,12 @@ extern "C" {
|
|||
*
|
||||
* Returns the maximum element with respect to the comparator function output.
|
||||
*
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*
|
||||
* @param l list to operate
|
||||
* @return the reference to the element, or NULL
|
||||
*/
|
||||
KS_DECLARE(void *) list_get_max(const list_t *restrict l);
|
||||
KS_DECLARE(void *) ks_list_get_max(const ks_list_t *restrict l);
|
||||
|
||||
/**
|
||||
* return the minimum element of the list.
|
||||
|
@ -414,12 +417,12 @@ extern "C" {
|
|||
*
|
||||
* Returns the minimum element with respect to the comparator function output.
|
||||
*
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*
|
||||
* @param l list to operate
|
||||
* @return the reference to the element, or NULL
|
||||
*/
|
||||
KS_DECLARE(void *) list_get_min(const list_t *restrict l);
|
||||
KS_DECLARE(void *) ks_list_get_min(const ks_list_t *restrict l);
|
||||
|
||||
/**
|
||||
* retrieve and remove from list an element at a given position.
|
||||
|
@ -428,7 +431,7 @@ extern "C" {
|
|||
* @param pos [0,size-1] position index of the element wanted
|
||||
* @return reference to user datum, or NULL on errors
|
||||
*/
|
||||
KS_DECLARE(void *) list_extract_at(list_t *restrict l, unsigned int pos);
|
||||
KS_DECLARE(void *) ks_list_extract_at(ks_list_t *restrict l, unsigned int pos);
|
||||
|
||||
/**
|
||||
* insert an element at a given position.
|
||||
|
@ -438,7 +441,7 @@ extern "C" {
|
|||
* @param pos [0,size-1] position index to insert the element at
|
||||
* @return positive value on success. Negative on failure
|
||||
*/
|
||||
KS_DECLARE(int) list_insert_at(list_t *restrict l, const void *data, unsigned int pos);
|
||||
KS_DECLARE(int) ks_list_insert_at(ks_list_t *restrict l, const void *data, unsigned int pos);
|
||||
|
||||
/**
|
||||
* expunge the first found given element from the list.
|
||||
|
@ -452,10 +455,10 @@ extern "C" {
|
|||
* @param data reference of the element to search for
|
||||
* @return 0 on success. Negative value on failure
|
||||
*
|
||||
* @see list_attributes_comparator()
|
||||
* @see list_delete_at()
|
||||
* @see ks_list_attributes_comparator()
|
||||
* @see ks_list_delete_at()
|
||||
*/
|
||||
KS_DECLARE(int) list_delete(list_t *restrict l, const void *data);
|
||||
KS_DECLARE(int) ks_list_delete(ks_list_t *restrict l, const void *data);
|
||||
|
||||
/**
|
||||
* expunge an element at a given position from the list.
|
||||
|
@ -464,7 +467,7 @@ extern "C" {
|
|||
* @param pos [0,size-1] position index of the element to be deleted
|
||||
* @return 0 on success. Negative value on failure
|
||||
*/
|
||||
KS_DECLARE(int) list_delete_at(list_t *restrict l, unsigned int pos);
|
||||
KS_DECLARE(int) ks_list_delete_at(ks_list_t *restrict l, unsigned int pos);
|
||||
|
||||
/**
|
||||
* expunge an array of elements from the list, given their position range.
|
||||
|
@ -474,20 +477,20 @@ extern "C" {
|
|||
* @param posend [posstart,size-1] position of the last element to be deleted
|
||||
* @return the number of elements successfully removed on success, <0 on error
|
||||
*/
|
||||
KS_DECLARE(int) list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend);
|
||||
KS_DECLARE(int) ks_list_delete_range(ks_list_t *restrict l, unsigned int posstart, unsigned int posend);
|
||||
|
||||
/**
|
||||
* clear all the elements off of the list.
|
||||
*
|
||||
* The element datums will not be freed.
|
||||
*
|
||||
* @see list_delete_range()
|
||||
* @see list_size()
|
||||
* @see ks_list_delete_range()
|
||||
* @see ks_list_size()
|
||||
*
|
||||
* @param l list to operate
|
||||
* @return the number of elements removed on success, <0 on error
|
||||
*/
|
||||
KS_DECLARE(int) list_clear(list_t *restrict l);
|
||||
KS_DECLARE(int) ks_list_clear(ks_list_t *restrict l);
|
||||
|
||||
/**
|
||||
* inspect the number of elements in the list.
|
||||
|
@ -495,7 +498,7 @@ extern "C" {
|
|||
* @param l list to operate
|
||||
* @return number of elements currently held by the list
|
||||
*/
|
||||
KS_DECLARE(unsigned int) list_size(const list_t *restrict l);
|
||||
KS_DECLARE(unsigned int) ks_list_size(const ks_list_t *restrict l);
|
||||
|
||||
/**
|
||||
* inspect whether the list is empty.
|
||||
|
@ -503,9 +506,9 @@ extern "C" {
|
|||
* @param l list to operate
|
||||
* @return 0 iff the list is not empty
|
||||
*
|
||||
* @see list_size()
|
||||
* @see ks_list_size()
|
||||
*/
|
||||
KS_DECLARE(int) list_empty(const list_t *restrict l);
|
||||
KS_DECLARE(int) ks_list_empty(const ks_list_t *restrict l);
|
||||
|
||||
/**
|
||||
* find the position of an element in a list.
|
||||
|
@ -521,10 +524,10 @@ extern "C" {
|
|||
* @param data reference of the element to search for
|
||||
* @return position of element in the list, or <0 if not found
|
||||
*
|
||||
* @see list_attributes_comparator()
|
||||
* @see list_get_at()
|
||||
* @see ks_list_attributes_comparator()
|
||||
* @see ks_list_get_at()
|
||||
*/
|
||||
KS_DECLARE(int) list_locate(const list_t *restrict l, const void *data);
|
||||
KS_DECLARE(int) ks_list_locate(const ks_list_t *restrict l, const void *data);
|
||||
|
||||
/**
|
||||
* returns an element given an indicator.
|
||||
|
@ -539,7 +542,7 @@ extern "C" {
|
|||
* @param indicator indicator data to pass to the seeker along with elements
|
||||
* @return reference to the element accepted by the seeker, or NULL if none found
|
||||
*/
|
||||
KS_DECLARE(void *) list_seek(list_t *restrict l, const void *indicator);
|
||||
KS_DECLARE(void *) ks_list_seek(ks_list_t *restrict l, const void *indicator);
|
||||
|
||||
/**
|
||||
* inspect whether some data is member of the list.
|
||||
|
@ -550,7 +553,7 @@ extern "C" {
|
|||
* the data is in list if any element of the list points to the same
|
||||
* location of data.
|
||||
* A "semantic" comparison is accomplished, otherwise, if a comparator
|
||||
* function has been set previously, with list_attributes_comparator();
|
||||
* function has been set previously, with ks_list_attributes_comparator();
|
||||
* in which case, the given data reference is believed to be in list iff
|
||||
* comparator_fun(elementdata, userdata) == 0 for any element in the list.
|
||||
*
|
||||
|
@ -558,9 +561,9 @@ extern "C" {
|
|||
* @param data reference to the data to search
|
||||
* @return 0 iff the list does not contain data as an element
|
||||
*
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*/
|
||||
KS_DECLARE(int) list_contains(const list_t *restrict l, const void *data);
|
||||
KS_DECLARE(int) ks_list_contains(const ks_list_t *restrict l, const void *data);
|
||||
|
||||
/**
|
||||
* concatenate two lists
|
||||
|
@ -579,7 +582,7 @@ extern "C" {
|
|||
* @param dest reference to the destination list
|
||||
* @return 0 for success, -1 for errors
|
||||
*/
|
||||
KS_DECLARE(int) list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest);
|
||||
KS_DECLARE(int) ks_list_concat(const ks_list_t *l1, const ks_list_t *l2, ks_list_t *restrict dest);
|
||||
|
||||
/**
|
||||
* sort list elements.
|
||||
|
@ -594,9 +597,9 @@ extern "C" {
|
|||
* @param versus positive: order small to big; negative: order big to small
|
||||
* @return 0 iff sorting was successful
|
||||
*
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*/
|
||||
KS_DECLARE(int) list_sort(list_t *restrict l, int versus);
|
||||
KS_DECLARE(int) ks_list_sort(ks_list_t *restrict l, int versus);
|
||||
|
||||
/**
|
||||
* start an iteration session.
|
||||
|
@ -606,9 +609,9 @@ extern "C" {
|
|||
* @param l list to operate
|
||||
* @return 0 if the list cannot be currently iterated. >0 otherwise
|
||||
*
|
||||
* @see list_iterator_stop()
|
||||
* @see ks_list_iterator_stop()
|
||||
*/
|
||||
KS_DECLARE(int) list_iterator_start(list_t *restrict l);
|
||||
KS_DECLARE(int) ks_list_iterator_start(ks_list_t *restrict l);
|
||||
|
||||
/**
|
||||
* return the next element in the iteration session.
|
||||
|
@ -616,7 +619,7 @@ extern "C" {
|
|||
* @param l list to operate
|
||||
* @return element datum, or NULL on errors
|
||||
*/
|
||||
KS_DECLARE(void *) list_iterator_next(list_t *restrict l);
|
||||
KS_DECLARE(void *) ks_list_iterator_next(ks_list_t *restrict l);
|
||||
|
||||
/**
|
||||
* inspect whether more elements are available in the iteration session.
|
||||
|
@ -624,7 +627,7 @@ extern "C" {
|
|||
* @param l list to operate
|
||||
* @return 0 iff no more elements are available.
|
||||
*/
|
||||
KS_DECLARE(int) list_iterator_hasnext(const list_t *restrict l);
|
||||
KS_DECLARE(int) ks_list_iterator_hasnext(const ks_list_t *restrict l);
|
||||
|
||||
/**
|
||||
* end an iteration session.
|
||||
|
@ -632,7 +635,7 @@ extern "C" {
|
|||
* @param l list to operate
|
||||
* @return 0 iff the iteration session cannot be stopped
|
||||
*/
|
||||
KS_DECLARE(int) list_iterator_stop(list_t *restrict l);
|
||||
KS_DECLARE(int) ks_list_iterator_stop(ks_list_t *restrict l);
|
||||
|
||||
/**
|
||||
* return the hash of the current status of the list.
|
||||
|
@ -642,7 +645,7 @@ extern "C" {
|
|||
*
|
||||
* @return 0 for success; <0 for failure
|
||||
*/
|
||||
KS_DECLARE(int) list_hash(const list_t *restrict l, list_hash_t *restrict hash);
|
||||
KS_DECLARE(int) ks_list_hash(const ks_list_t *restrict l, ks_list_hash_t *restrict hash);
|
||||
|
||||
#ifndef SIMCLIST_NO_DUMPRESTORE
|
||||
/**
|
||||
|
@ -658,9 +661,9 @@ extern "C" {
|
|||
* @param info reference to a dump metainformation structure to fill
|
||||
* @return 0 for success; <0 for failure
|
||||
*
|
||||
* @see list_dump_filedescriptor()
|
||||
* @see ks_list_dump_filedescriptor()
|
||||
*/
|
||||
int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info);
|
||||
int ks_list_dump_getinfo_filedescriptor(int fd, ks_list_dump_info_t *restrict info);
|
||||
|
||||
/**
|
||||
* get meta informations on a list dump on file.
|
||||
|
@ -673,9 +676,9 @@ extern "C" {
|
|||
* @param info reference to a dump metainformation structure to fill
|
||||
* @return 0 for success; <0 for failure
|
||||
*
|
||||
* @see list_dump_filedescriptor()
|
||||
* @see ks_list_dump_filedescriptor()
|
||||
*/
|
||||
int list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info);
|
||||
int ks_list_dump_getinfo_file(const char *restrict filename, ks_list_dump_info_t *restrict info);
|
||||
|
||||
/**
|
||||
* dump the list into an open, writable file descriptor.
|
||||
|
@ -689,8 +692,8 @@ extern "C" {
|
|||
* descriptor is not closed at the end of the operations.
|
||||
*
|
||||
* To use dump functions, either of these conditions must be satisfied:
|
||||
* -# a metric function has been specified with list_attributes_copy()
|
||||
* -# a serializer function has been specified with list_attributes_serializer()
|
||||
* -# a metric function has been specified with ks_list_attributes_copy()
|
||||
* -# a serializer function has been specified with ks_list_attributes_serializer()
|
||||
*
|
||||
* If a metric function has been specified, each element of the list is dumped
|
||||
* as-is from memory, copying it from its pointer for its length down to the
|
||||
|
@ -708,10 +711,10 @@ extern "C" {
|
|||
* @return 0 if successful; -1 otherwise
|
||||
*
|
||||
* @see element_serializer()
|
||||
* @see list_attributes_copy()
|
||||
* @see list_attributes_serializer()
|
||||
* @see ks_list_attributes_copy()
|
||||
* @see ks_list_attributes_serializer()
|
||||
*/
|
||||
int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len);
|
||||
int ks_list_dump_filedescriptor(const ks_list_t *restrict l, int fd, ks_size_t *restrict len);
|
||||
|
||||
/**
|
||||
* dump the list to a file name.
|
||||
|
@ -726,256 +729,256 @@ extern "C" {
|
|||
*
|
||||
* @return 0 if successful; -1 otherwise
|
||||
*
|
||||
* @see list_attributes_copy()
|
||||
* @see ks_list_attributes_copy()
|
||||
* @see element_serializer()
|
||||
* @see list_attributes_serializer()
|
||||
* @see list_dump_filedescriptor()
|
||||
* @see list_restore_file()
|
||||
* @see ks_list_attributes_serializer()
|
||||
* @see ks_list_dump_filedescriptor()
|
||||
* @see ks_list_restore_file()
|
||||
*
|
||||
* This function stores a representation of the list
|
||||
*/
|
||||
int list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len);
|
||||
int ks_list_dump_file(const ks_list_t *restrict l, const char *restrict filename, ks_size_t *restrict len);
|
||||
|
||||
/**
|
||||
* restore the list from an open, readable file descriptor to memory.
|
||||
*
|
||||
* This function is the "inverse" of list_dump_filedescriptor(). It restores
|
||||
* This function is the "inverse" of ks_list_dump_filedescriptor(). It restores
|
||||
* the list content from a (open, read-ready) file descriptor to memory. An
|
||||
* unserializer might be needed to restore elements from the persistent
|
||||
* representation back into memory-consistent format. List attributes can not
|
||||
* be restored and must be set manually.
|
||||
*
|
||||
* @see list_dump_filedescriptor()
|
||||
* @see list_attributes_serializer()
|
||||
* @see list_attributes_unserializer()
|
||||
* @see ks_list_dump_filedescriptor()
|
||||
* @see ks_list_attributes_serializer()
|
||||
* @see ks_list_attributes_unserializer()
|
||||
*
|
||||
* @param l list to restore to
|
||||
* @param fd file descriptor to read from.
|
||||
* @param len location to store the length of the dump read (bytes), or NULL
|
||||
* @return 0 if successful; -1 otherwise
|
||||
*/
|
||||
int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len);
|
||||
int ks_list_restore_filedescriptor(ks_list_t *restrict l, int fd, ks_size_t *restrict len);
|
||||
|
||||
/**
|
||||
* restore the list from a file name.
|
||||
*
|
||||
* This function restores the content of a list from a file into memory. It is
|
||||
* the inverse of list_dump_file().
|
||||
* the inverse of ks_list_dump_file().
|
||||
*
|
||||
* @see element_unserializer()
|
||||
* @see list_attributes_unserializer()
|
||||
* @see list_dump_file()
|
||||
* @see list_restore_filedescriptor()
|
||||
* @see ks_list_attributes_unserializer()
|
||||
* @see ks_list_dump_file()
|
||||
* @see ks_list_restore_filedescriptor()
|
||||
*
|
||||
* @param l list to restore to
|
||||
* @param filename filename to read data from
|
||||
* @param len location to store the length of the dump read (bytes), or NULL
|
||||
* @return 0 if successful; -1 otherwise
|
||||
*/
|
||||
int list_restore_file(list_t *restrict l, const char *restrict filename, size_t *len);
|
||||
int ks_list_restore_file(ks_list_t *restrict l, const char *restrict filename, ks_size_t *len);
|
||||
#endif
|
||||
|
||||
/* ready-made comparators, meters and hash computers */
|
||||
/* comparator functions */
|
||||
/**
|
||||
* ready-made comparator for int8_t elements.
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*/
|
||||
int list_comparator_int8_t(const void *a, const void *b);
|
||||
int ks_list_comparator_int8_t(const void *a, const void *b);
|
||||
|
||||
/**
|
||||
* ready-made comparator for int16_t elements.
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*/
|
||||
int list_comparator_int16_t(const void *a, const void *b);
|
||||
int ks_list_comparator_int16_t(const void *a, const void *b);
|
||||
|
||||
/**
|
||||
* ready-made comparator for int32_t elements.
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*/
|
||||
int list_comparator_int32_t(const void *a, const void *b);
|
||||
int ks_list_comparator_int32_t(const void *a, const void *b);
|
||||
|
||||
/**
|
||||
* ready-made comparator for int64_t elements.
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*/
|
||||
int list_comparator_int64_t(const void *a, const void *b);
|
||||
int ks_list_comparator_int64_t(const void *a, const void *b);
|
||||
|
||||
/**
|
||||
* ready-made comparator for uint8_t elements.
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*/
|
||||
int list_comparator_uint8_t(const void *a, const void *b);
|
||||
int ks_list_comparator_uint8_t(const void *a, const void *b);
|
||||
|
||||
/**
|
||||
* ready-made comparator for uint16_t elements.
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*/
|
||||
int list_comparator_uint16_t(const void *a, const void *b);
|
||||
int ks_list_comparator_uint16_t(const void *a, const void *b);
|
||||
|
||||
/**
|
||||
* ready-made comparator for uint32_t elements.
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*/
|
||||
int list_comparator_uint32_t(const void *a, const void *b);
|
||||
int ks_list_comparator_uint32_t(const void *a, const void *b);
|
||||
|
||||
/**
|
||||
* ready-made comparator for uint64_t elements.
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*/
|
||||
int list_comparator_uint64_t(const void *a, const void *b);
|
||||
int ks_list_comparator_uint64_t(const void *a, const void *b);
|
||||
|
||||
/**
|
||||
* ready-made comparator for float elements.
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*/
|
||||
int list_comparator_float(const void *a, const void *b);
|
||||
int ks_list_comparator_float(const void *a, const void *b);
|
||||
|
||||
/**
|
||||
* ready-made comparator for double elements.
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*/
|
||||
int list_comparator_double(const void *a, const void *b);
|
||||
int ks_list_comparator_double(const void *a, const void *b);
|
||||
|
||||
/**
|
||||
* ready-made comparator for string elements.
|
||||
* @see list_attributes_comparator()
|
||||
* @see ks_list_attributes_comparator()
|
||||
*/
|
||||
int list_comparator_string(const void *a, const void *b);
|
||||
int ks_list_comparator_string(const void *a, const void *b);
|
||||
|
||||
/* metric functions */
|
||||
/**
|
||||
* ready-made metric function for int8_t elements.
|
||||
* @see list_attributes_copy()
|
||||
* @see ks_list_attributes_copy()
|
||||
*/
|
||||
size_t list_meter_int8_t(const void *el);
|
||||
ks_size_t ks_list_meter_int8_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made metric function for int16_t elements.
|
||||
* @see list_attributes_copy()
|
||||
* @see ks_list_attributes_copy()
|
||||
*/
|
||||
size_t list_meter_int16_t(const void *el);
|
||||
ks_size_t ks_list_meter_int16_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made metric function for int32_t elements.
|
||||
* @see list_attributes_copy()
|
||||
* @see ks_list_attributes_copy()
|
||||
*/
|
||||
size_t list_meter_int32_t(const void *el);
|
||||
ks_size_t ks_list_meter_int32_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made metric function for int64_t elements.
|
||||
* @see list_attributes_copy()
|
||||
* @see ks_list_attributes_copy()
|
||||
*/
|
||||
size_t list_meter_int64_t(const void *el);
|
||||
ks_size_t ks_list_meter_int64_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made metric function for uint8_t elements.
|
||||
* @see list_attributes_copy()
|
||||
* @see ks_list_attributes_copy()
|
||||
*/
|
||||
size_t list_meter_uint8_t(const void *el);
|
||||
ks_size_t ks_list_meter_uint8_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made metric function for uint16_t elements.
|
||||
* @see list_attributes_copy()
|
||||
* @see ks_list_attributes_copy()
|
||||
*/
|
||||
size_t list_meter_uint16_t(const void *el);
|
||||
ks_size_t ks_list_meter_uint16_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made metric function for uint32_t elements.
|
||||
* @see list_attributes_copy()
|
||||
* @see ks_list_attributes_copy()
|
||||
*/
|
||||
size_t list_meter_uint32_t(const void *el);
|
||||
ks_size_t ks_list_meter_uint32_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made metric function for uint64_t elements.
|
||||
* @see list_attributes_copy()
|
||||
* @see ks_list_attributes_copy()
|
||||
*/
|
||||
size_t list_meter_uint64_t(const void *el);
|
||||
ks_size_t ks_list_meter_uint64_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made metric function for float elements.
|
||||
* @see list_attributes_copy()
|
||||
* @see ks_list_attributes_copy()
|
||||
*/
|
||||
size_t list_meter_float(const void *el);
|
||||
ks_size_t ks_list_meter_float(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made metric function for double elements.
|
||||
* @see list_attributes_copy()
|
||||
* @see ks_list_attributes_copy()
|
||||
*/
|
||||
size_t list_meter_double(const void *el);
|
||||
ks_size_t ks_list_meter_double(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made metric function for string elements.
|
||||
* @see list_attributes_copy()
|
||||
* @see ks_list_attributes_copy()
|
||||
*/
|
||||
size_t list_meter_string(const void *el);
|
||||
ks_size_t ks_list_meter_string(const void *el);
|
||||
|
||||
/* hash functions */
|
||||
/**
|
||||
* ready-made hash function for int8_t elements.
|
||||
* @see list_attributes_hash_computer()
|
||||
* @see ks_list_attributes_hash_computer()
|
||||
*/
|
||||
list_hash_t list_hashcomputer_int8_t(const void *el);
|
||||
ks_list_hash_t ks_list_hashcomputer_int8_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made hash function for int16_t elements.
|
||||
* @see list_attributes_hash_computer()
|
||||
* @see ks_list_attributes_hash_computer()
|
||||
*/
|
||||
list_hash_t list_hashcomputer_int16_t(const void *el);
|
||||
ks_list_hash_t ks_list_hashcomputer_int16_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made hash function for int32_t elements.
|
||||
* @see list_attributes_hash_computer()
|
||||
* @see ks_list_attributes_hash_computer()
|
||||
*/
|
||||
list_hash_t list_hashcomputer_int32_t(const void *el);
|
||||
ks_list_hash_t ks_list_hashcomputer_int32_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made hash function for int64_t elements.
|
||||
* @see list_attributes_hash_computer()
|
||||
* @see ks_list_attributes_hash_computer()
|
||||
*/
|
||||
list_hash_t list_hashcomputer_int64_t(const void *el);
|
||||
ks_list_hash_t ks_list_hashcomputer_int64_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made hash function for uint8_t elements.
|
||||
* @see list_attributes_hash_computer()
|
||||
* @see ks_list_attributes_hash_computer()
|
||||
*/
|
||||
list_hash_t list_hashcomputer_uint8_t(const void *el);
|
||||
ks_list_hash_t ks_list_hashcomputer_uint8_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made hash function for uint16_t elements.
|
||||
* @see list_attributes_hash_computer()
|
||||
* @see ks_list_attributes_hash_computer()
|
||||
*/
|
||||
list_hash_t list_hashcomputer_uint16_t(const void *el);
|
||||
ks_list_hash_t ks_list_hashcomputer_uint16_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made hash function for uint32_t elements.
|
||||
* @see list_attributes_hash_computer()
|
||||
* @see ks_list_attributes_hash_computer()
|
||||
*/
|
||||
list_hash_t list_hashcomputer_uint32_t(const void *el);
|
||||
ks_list_hash_t ks_list_hashcomputer_uint32_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made hash function for uint64_t elements.
|
||||
* @see list_attributes_hash_computer()
|
||||
* @see ks_list_attributes_hash_computer()
|
||||
*/
|
||||
list_hash_t list_hashcomputer_uint64_t(const void *el);
|
||||
ks_list_hash_t ks_list_hashcomputer_uint64_t(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made hash function for float elements.
|
||||
* @see list_attributes_hash_computer()
|
||||
* @see ks_list_attributes_hash_computer()
|
||||
*/
|
||||
list_hash_t list_hashcomputer_float(const void *el);
|
||||
ks_list_hash_t ks_list_hashcomputer_float(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made hash function for double elements.
|
||||
* @see list_attributes_hash_computer()
|
||||
* @see ks_list_attributes_hash_computer()
|
||||
*/
|
||||
list_hash_t list_hashcomputer_double(const void *el);
|
||||
ks_list_hash_t ks_list_hashcomputer_double(const void *el);
|
||||
|
||||
/**
|
||||
* ready-made hash function for string elements.
|
||||
* @see list_attributes_hash_computer()
|
||||
* @see ks_list_attributes_hash_computer()
|
||||
*/
|
||||
list_hash_t list_hashcomputer_string(const void *el);
|
||||
ks_list_hash_t ks_list_hashcomputer_string(const void *el);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -179,10 +179,11 @@ typedef INT64 int64_t;
|
|||
/* list dump declarations */
|
||||
#define SIMCLIST_DUMPFORMAT_VERSION 1 /* (short integer) version of fileformat managed by _dump* and _restore* functions */
|
||||
|
||||
// @todo this is not correct, the header would be padded by default on version for 2 more bytes, and treating the structure as 30 bytes would cut the last 2 bytes off the listhash at the end
|
||||
#define SIMCLIST_DUMPFORMAT_HEADERLEN 30 /* length of the header */
|
||||
|
||||
/* header for a list dump */
|
||||
struct list_dump_header_s {
|
||||
struct ks_list_dump_header_s {
|
||||
uint16_t ver; /* version */
|
||||
int32_t timestamp_sec; /* dump timestamp, seconds since UNIX Epoch */
|
||||
int32_t timestamp_usec; /* dump timestamp, microseconds since timestamp_sec */
|
||||
|
@ -197,31 +198,31 @@ struct list_dump_header_s {
|
|||
|
||||
|
||||
/* deletes tmp from list, with care wrt its position (head, tail, middle) */
|
||||
static int list_drop_elem(list_t *restrict l, struct list_entry_s *tmp, unsigned int pos);
|
||||
static int ks_list_drop_elem(ks_list_t *restrict l, struct ks_list_entry_s *tmp, unsigned int pos);
|
||||
|
||||
/* set default values for initialized lists */
|
||||
static int list_attributes_setdefaults(list_t *restrict l);
|
||||
static int ks_list_attributes_setdefaults(ks_list_t *restrict l);
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* check whether the list internal REPresentation is valid -- Costs O(n) */
|
||||
static int list_repOk(const list_t *restrict l);
|
||||
static int ks_list_repOk(const ks_list_t *restrict l);
|
||||
|
||||
/* check whether the list attribute set is valid -- Costs O(1) */
|
||||
static int list_attrOk(const list_t *restrict l);
|
||||
static int ks_list_attrOk(const ks_list_t *restrict l);
|
||||
#endif
|
||||
|
||||
/* do not inline, this is recursive */
|
||||
static void list_sort_quicksort(list_t *restrict l, int versus,
|
||||
unsigned int first, struct list_entry_s *fel,
|
||||
unsigned int last, struct list_entry_s *lel);
|
||||
static void ks_list_sort_quicksort(ks_list_t *restrict l, int versus,
|
||||
unsigned int first, struct ks_list_entry_s *fel,
|
||||
unsigned int last, struct ks_list_entry_s *lel);
|
||||
|
||||
static inline void list_sort_selectionsort(list_t *restrict l, int versus,
|
||||
unsigned int first, struct list_entry_s *fel,
|
||||
unsigned int last, struct list_entry_s *lel);
|
||||
static inline void ks_list_sort_selectionsort(ks_list_t *restrict l, int versus,
|
||||
unsigned int first, struct ks_list_entry_s *fel,
|
||||
unsigned int last, struct ks_list_entry_s *lel);
|
||||
|
||||
static void *list_get_minmax(const list_t *restrict l, int versus);
|
||||
static void *ks_list_get_minmax(const ks_list_t *restrict l, int versus);
|
||||
|
||||
static inline struct list_entry_s *list_findpos(const list_t *restrict l, int posstart);
|
||||
static inline struct ks_list_entry_s *ks_list_findpos(const ks_list_t *restrict l, int posstart);
|
||||
|
||||
/*
|
||||
* Random Number Generator
|
||||
|
@ -266,17 +267,43 @@ static inline long get_random(void) {
|
|||
#endif
|
||||
|
||||
|
||||
static void ks_list_cleanup(ks_pool_t *pool, void *ptr, void *arg, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t type)
|
||||
{
|
||||
ks_list_t *l = (ks_list_t *)ptr;
|
||||
|
||||
switch (action) {
|
||||
case KS_MPCL_ANNOUNCE:
|
||||
break;
|
||||
case KS_MPCL_TEARDOWN:
|
||||
ks_list_clear(l);
|
||||
break;
|
||||
case KS_MPCL_DESTROY:
|
||||
for (unsigned int i = 0; i < l->spareelsnum; i++) ks_pool_free(l->pool, &l->spareels[i]);
|
||||
ks_pool_free(l->pool, &l->spareels);
|
||||
ks_pool_free(l->pool, &l->head_sentinel);
|
||||
ks_pool_free(l->pool, &l->tail_sentinel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* list initialization */
|
||||
KS_DECLARE(int) list_init(list_t *restrict l) {
|
||||
if (l == NULL) return -1;
|
||||
KS_DECLARE(ks_status_t) ks_list_create(ks_list_t ** list, ks_pool_t *pool) {
|
||||
ks_list_t *l = NULL;
|
||||
|
||||
ks_assert(l);
|
||||
ks_assert(pool);
|
||||
|
||||
seed_random();
|
||||
|
||||
l = ks_pool_alloc(pool, sizeof(ks_list_t));
|
||||
ks_assert(l);
|
||||
|
||||
l->pool = pool;
|
||||
l->numels = 0;
|
||||
|
||||
/* head/tail sentinels and mid pointer */
|
||||
l->head_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
|
||||
l->tail_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
|
||||
l->head_sentinel = (struct ks_list_entry_s *)ks_pool_alloc(pool, sizeof(struct ks_list_entry_s));
|
||||
l->tail_sentinel = (struct ks_list_entry_s *)ks_pool_alloc(pool, sizeof(struct ks_list_entry_s));
|
||||
l->head_sentinel->next = l->tail_sentinel;
|
||||
l->tail_sentinel->prev = l->head_sentinel;
|
||||
l->head_sentinel->prev = l->tail_sentinel->next = l->mid = NULL;
|
||||
|
@ -288,34 +315,39 @@ KS_DECLARE(int) list_init(list_t *restrict l) {
|
|||
l->iter_curentry = NULL;
|
||||
|
||||
/* free-list attributes */
|
||||
l->spareels = (struct list_entry_s **)malloc(SIMCLIST_MAX_SPARE_ELEMS * sizeof(struct list_entry_s *));
|
||||
l->spareels = (struct ks_list_entry_s **)ks_pool_alloc(pool, SIMCLIST_MAX_SPARE_ELEMS * sizeof(struct ks_list_entry_s *));
|
||||
l->spareelsnum = 0;
|
||||
|
||||
#ifdef SIMCLIST_WITH_THREADS
|
||||
l->threadcount = 0;
|
||||
#endif
|
||||
|
||||
list_attributes_setdefaults(l);
|
||||
ks_list_attributes_setdefaults(l);
|
||||
|
||||
assert(list_repOk(l));
|
||||
assert(list_attrOk(l));
|
||||
assert(ks_list_repOk(l));
|
||||
assert(ks_list_attrOk(l));
|
||||
|
||||
return 0;
|
||||
ks_assert(ks_pool_set_cleanup(pool, l, NULL, ks_list_cleanup) == KS_STATUS_SUCCESS);
|
||||
|
||||
*list = l;
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) list_destroy(list_t *restrict l) {
|
||||
unsigned int i;
|
||||
KS_DECLARE(ks_status_t) ks_list_destroy(ks_list_t ** list) {
|
||||
ks_list_t *l = NULL;
|
||||
|
||||
list_clear(l);
|
||||
for (i = 0; i < l->spareelsnum; i++) {
|
||||
free(l->spareels[i]);
|
||||
}
|
||||
free(l->spareels);
|
||||
free(l->head_sentinel);
|
||||
free(l->tail_sentinel);
|
||||
ks_assert(list);
|
||||
|
||||
l = *list;
|
||||
*list = NULL;
|
||||
if (!l) return KS_STATUS_FAIL;
|
||||
|
||||
ks_pool_free(l->pool, &l);
|
||||
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int list_attributes_setdefaults(list_t *restrict l) {
|
||||
int ks_list_attributes_setdefaults(ks_list_t *restrict l) {
|
||||
l->attrs.comparator = NULL;
|
||||
l->attrs.seeker = NULL;
|
||||
|
||||
|
@ -329,99 +361,99 @@ int list_attributes_setdefaults(list_t *restrict l) {
|
|||
l->attrs.serializer = NULL;
|
||||
l->attrs.unserializer = NULL;
|
||||
|
||||
assert(list_attrOk(l));
|
||||
assert(ks_list_attrOk(l));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* setting list properties */
|
||||
int list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun) {
|
||||
int ks_list_attributes_comparator(ks_list_t *restrict l, element_comparator comparator_fun) {
|
||||
if (l == NULL) return -1;
|
||||
|
||||
l->attrs.comparator = comparator_fun;
|
||||
|
||||
assert(list_attrOk(l));
|
||||
assert(ks_list_attrOk(l));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun) {
|
||||
int ks_list_attributes_seeker(ks_list_t *restrict l, element_seeker seeker_fun) {
|
||||
if (l == NULL) return -1;
|
||||
|
||||
l->attrs.seeker = seeker_fun;
|
||||
assert(list_attrOk(l));
|
||||
assert(ks_list_attrOk(l));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data) {
|
||||
int ks_list_attributes_copy(ks_list_t *restrict l, element_meter metric_fun, int copy_data) {
|
||||
if (l == NULL || (metric_fun == NULL && copy_data != 0)) return -1;
|
||||
|
||||
l->attrs.meter = metric_fun;
|
||||
l->attrs.copy_data = copy_data;
|
||||
|
||||
assert(list_attrOk(l));
|
||||
assert(ks_list_attrOk(l));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun) {
|
||||
int ks_list_attributes_hash_computer(ks_list_t *restrict l, element_hash_computer hash_computer_fun) {
|
||||
if (l == NULL) return -1;
|
||||
|
||||
l->attrs.hasher = hash_computer_fun;
|
||||
assert(list_attrOk(l));
|
||||
assert(ks_list_attrOk(l));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun) {
|
||||
int ks_list_attributes_serializer(ks_list_t *restrict l, element_serializer serializer_fun) {
|
||||
if (l == NULL) return -1;
|
||||
|
||||
l->attrs.serializer = serializer_fun;
|
||||
assert(list_attrOk(l));
|
||||
assert(ks_list_attrOk(l));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun) {
|
||||
int ks_list_attributes_unserializer(ks_list_t *restrict l, element_unserializer unserializer_fun) {
|
||||
if (l == NULL) return -1;
|
||||
|
||||
l->attrs.unserializer = unserializer_fun;
|
||||
assert(list_attrOk(l));
|
||||
assert(ks_list_attrOk(l));
|
||||
return 0;
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_append(list_t *restrict l, const void *data) {
|
||||
return list_insert_at(l, data, l->numels);
|
||||
KS_DECLARE(int) ks_list_append(ks_list_t *restrict l, const void *data) {
|
||||
return ks_list_insert_at(l, data, l->numels);
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_prepend(list_t *restrict l, const void *data) {
|
||||
return list_insert_at(l, data, 0);
|
||||
KS_DECLARE(int) ks_list_prepend(ks_list_t *restrict l, const void *data) {
|
||||
return ks_list_insert_at(l, data, 0);
|
||||
}
|
||||
|
||||
KS_DECLARE(void *) list_fetch(list_t *restrict l) {
|
||||
return list_extract_at(l, 0);
|
||||
KS_DECLARE(void *) ks_list_fetch(ks_list_t *restrict l) {
|
||||
return ks_list_extract_at(l, 0);
|
||||
}
|
||||
|
||||
KS_DECLARE(void *) list_get_at(const list_t *restrict l, unsigned int pos) {
|
||||
struct list_entry_s *tmp;
|
||||
KS_DECLARE(void *) ks_list_get_at(const ks_list_t *restrict l, unsigned int pos) {
|
||||
struct ks_list_entry_s *tmp;
|
||||
|
||||
tmp = list_findpos(l, pos);
|
||||
tmp = ks_list_findpos(l, pos);
|
||||
|
||||
return (tmp != NULL ? tmp->data : NULL);
|
||||
}
|
||||
|
||||
KS_DECLARE(void *) list_get_max(const list_t *restrict l) {
|
||||
return list_get_minmax(l, +1);
|
||||
KS_DECLARE(void *) ks_list_get_max(const ks_list_t *restrict l) {
|
||||
return ks_list_get_minmax(l, +1);
|
||||
}
|
||||
|
||||
KS_DECLARE(void *) list_get_min(const list_t *restrict l) {
|
||||
return list_get_minmax(l, -1);
|
||||
KS_DECLARE(void *) ks_list_get_min(const ks_list_t *restrict l) {
|
||||
return ks_list_get_minmax(l, -1);
|
||||
}
|
||||
|
||||
/* REQUIRES {list->numels >= 1}
|
||||
* return the min (versus < 0) or max value (v > 0) in l */
|
||||
static void *list_get_minmax(const list_t *restrict l, int versus) {
|
||||
static void *ks_list_get_minmax(const ks_list_t *restrict l, int versus) {
|
||||
void *curminmax;
|
||||
struct list_entry_s *s;
|
||||
struct ks_list_entry_s *s;
|
||||
|
||||
if (l->attrs.comparator == NULL || l->numels == 0)
|
||||
return NULL;
|
||||
|
@ -436,8 +468,8 @@ static void *list_get_minmax(const list_t *restrict l, int versus) {
|
|||
}
|
||||
|
||||
/* set tmp to point to element at index posstart in l */
|
||||
static inline struct list_entry_s *list_findpos(const list_t *restrict l, int posstart) {
|
||||
struct list_entry_s *ptr;
|
||||
static inline struct ks_list_entry_s *ks_list_findpos(const ks_list_t *restrict l, int posstart) {
|
||||
struct ks_list_entry_s *ptr;
|
||||
float x;
|
||||
int i;
|
||||
|
||||
|
@ -465,26 +497,26 @@ static inline struct list_entry_s *list_findpos(const list_t *restrict l, int po
|
|||
return ptr;
|
||||
}
|
||||
|
||||
KS_DECLARE(void *) list_extract_at(list_t *restrict l, unsigned int pos) {
|
||||
struct list_entry_s *tmp;
|
||||
KS_DECLARE(void *) ks_list_extract_at(ks_list_t *restrict l, unsigned int pos) {
|
||||
struct ks_list_entry_s *tmp;
|
||||
void *data;
|
||||
|
||||
if (l->iter_active || pos >= l->numels) return NULL;
|
||||
|
||||
tmp = list_findpos(l, pos);
|
||||
tmp = ks_list_findpos(l, pos);
|
||||
data = tmp->data;
|
||||
|
||||
tmp->data = NULL; /* save data from list_drop_elem() free() */
|
||||
list_drop_elem(l, tmp, pos);
|
||||
tmp->data = NULL; /* save data from ks_list_drop_elem() free() */
|
||||
ks_list_drop_elem(l, tmp, pos);
|
||||
l->numels--;
|
||||
|
||||
assert(list_repOk(l));
|
||||
assert(ks_list_repOk(l));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_insert_at(list_t *restrict l, const void *data, unsigned int pos) {
|
||||
struct list_entry_s *lent, *succ, *prec;
|
||||
KS_DECLARE(int) ks_list_insert_at(ks_list_t *restrict l, const void *data, unsigned int pos) {
|
||||
struct ks_list_entry_s *lent, *succ, *prec;
|
||||
|
||||
if (l->iter_active || pos > l->numels) return -1;
|
||||
|
||||
|
@ -494,15 +526,15 @@ KS_DECLARE(int) list_insert_at(list_t *restrict l, const void *data, unsigned in
|
|||
l->spareelsnum--;
|
||||
}
|
||||
else {
|
||||
lent = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
|
||||
lent = (struct ks_list_entry_s *)ks_pool_alloc(l->pool, sizeof(struct ks_list_entry_s));
|
||||
if (lent == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (l->attrs.copy_data) {
|
||||
/* make room for user' data (has to be copied) */
|
||||
size_t datalen = l->attrs.meter(data);
|
||||
lent->data = (struct list_entry_s *)malloc(datalen);
|
||||
ks_size_t datalen = l->attrs.meter(data);
|
||||
lent->data = (struct ks_list_entry_s *)ks_pool_alloc(l->pool, datalen);
|
||||
memcpy(lent->data, data, datalen);
|
||||
}
|
||||
else {
|
||||
|
@ -510,7 +542,7 @@ KS_DECLARE(int) list_insert_at(list_t *restrict l, const void *data, unsigned in
|
|||
}
|
||||
|
||||
/* actually append element */
|
||||
prec = list_findpos(l, pos - 1);
|
||||
prec = ks_list_findpos(l, pos - 1);
|
||||
succ = prec->next;
|
||||
|
||||
prec->next = lent;
|
||||
|
@ -531,56 +563,56 @@ KS_DECLARE(int) list_insert_at(list_t *restrict l, const void *data, unsigned in
|
|||
if (pos <= (l->numels - 1) / 2) l->mid = l->mid->prev;
|
||||
}
|
||||
|
||||
assert(list_repOk(l));
|
||||
assert(ks_list_repOk(l));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_delete(list_t *restrict l, const void *data) {
|
||||
KS_DECLARE(int) ks_list_delete(ks_list_t *restrict l, const void *data) {
|
||||
int pos, r;
|
||||
|
||||
pos = list_locate(l, data);
|
||||
pos = ks_list_locate(l, data);
|
||||
if (pos < 0)
|
||||
return -1;
|
||||
|
||||
r = list_delete_at(l, pos);
|
||||
r = ks_list_delete_at(l, pos);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
|
||||
assert(list_repOk(l));
|
||||
assert(ks_list_repOk(l));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_delete_at(list_t *restrict l, unsigned int pos) {
|
||||
struct list_entry_s *delendo;
|
||||
KS_DECLARE(int) ks_list_delete_at(ks_list_t *restrict l, unsigned int pos) {
|
||||
struct ks_list_entry_s *delendo;
|
||||
|
||||
|
||||
if (l->iter_active || pos >= l->numels) return -1;
|
||||
|
||||
delendo = list_findpos(l, pos);
|
||||
delendo = ks_list_findpos(l, pos);
|
||||
|
||||
list_drop_elem(l, delendo, pos);
|
||||
ks_list_drop_elem(l, delendo, pos);
|
||||
|
||||
l->numels--;
|
||||
|
||||
|
||||
assert(list_repOk(l));
|
||||
assert(ks_list_repOk(l));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend) {
|
||||
struct list_entry_s *lastvalid, *tmp, *tmp2;
|
||||
KS_DECLARE(int) ks_list_delete_range(ks_list_t *restrict l, unsigned int posstart, unsigned int posend) {
|
||||
struct ks_list_entry_s *lastvalid, *tmp, *tmp2;
|
||||
unsigned int numdel, midposafter, i;
|
||||
int movedx;
|
||||
|
||||
if (l->iter_active || posend < posstart || posend >= l->numels) return -1;
|
||||
|
||||
numdel = posend - posstart + 1;
|
||||
if (numdel == l->numels) return list_clear(l);
|
||||
if (numdel == l->numels) return ks_list_clear(l);
|
||||
|
||||
tmp = list_findpos(l, posstart); /* first el to be deleted */
|
||||
tmp = ks_list_findpos(l, posstart); /* first el to be deleted */
|
||||
lastvalid = tmp->prev; /* last valid element */
|
||||
|
||||
midposafter = (l->numels - 1 - numdel) / 2;
|
||||
|
@ -603,12 +635,12 @@ KS_DECLARE(int) list_delete_range(list_t *restrict l, unsigned int posstart, uns
|
|||
for (; i <= posend; i++) {
|
||||
tmp2 = tmp;
|
||||
tmp = tmp->next;
|
||||
if (tmp2->data != NULL) free(tmp2->data);
|
||||
if (tmp2->data != NULL) ks_pool_free(l->pool, &tmp2->data);
|
||||
if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) {
|
||||
l->spareels[l->spareelsnum++] = tmp2;
|
||||
}
|
||||
else {
|
||||
free(tmp2);
|
||||
ks_pool_free(l->pool, &tmp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -621,7 +653,7 @@ KS_DECLARE(int) list_delete_range(list_t *restrict l, unsigned int posstart, uns
|
|||
l->spareels[l->spareelsnum++] = tmp2;
|
||||
}
|
||||
else {
|
||||
free(tmp2);
|
||||
ks_pool_free(l->pool, &tmp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -632,13 +664,13 @@ KS_DECLARE(int) list_delete_range(list_t *restrict l, unsigned int posstart, uns
|
|||
|
||||
l->numels -= posend - posstart + 1;
|
||||
|
||||
assert(list_repOk(l));
|
||||
assert(ks_list_repOk(l));
|
||||
|
||||
return numdel;
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_clear(list_t *restrict l) {
|
||||
struct list_entry_s *s;
|
||||
KS_DECLARE(int) ks_list_clear(ks_list_t *restrict l) {
|
||||
struct ks_list_entry_s *s;
|
||||
unsigned int numels;
|
||||
|
||||
/* will be returned */
|
||||
|
@ -650,14 +682,14 @@ KS_DECLARE(int) list_clear(list_t *restrict l) {
|
|||
/* spare a loop conditional with two loops: spareing elems and freeing elems */
|
||||
for (s = l->head_sentinel->next; l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS && s != l->tail_sentinel; s = s->next) {
|
||||
/* move elements as spares as long as there is room */
|
||||
if (s->data != NULL) free(s->data);
|
||||
if (s->data != NULL) ks_pool_free(l->pool, &s->data);
|
||||
l->spareels[l->spareelsnum++] = s;
|
||||
}
|
||||
while (s != l->tail_sentinel) {
|
||||
/* free the remaining elems */
|
||||
if (s->data != NULL) free(s->data);
|
||||
if (s->data != NULL) ks_pool_free(l->pool, &s->data);
|
||||
s = s->next;
|
||||
free(s->prev);
|
||||
ks_pool_free(l->pool, &s->prev);
|
||||
}
|
||||
l->head_sentinel->next = l->tail_sentinel;
|
||||
l->tail_sentinel->prev = l->head_sentinel;
|
||||
|
@ -671,7 +703,7 @@ KS_DECLARE(int) list_clear(list_t *restrict l) {
|
|||
while (s != l->tail_sentinel) {
|
||||
/* free the remaining elems */
|
||||
s = s->next;
|
||||
free(s->prev);
|
||||
ks_pool_free(l->pool, &s->prev);
|
||||
}
|
||||
l->head_sentinel->next = l->tail_sentinel;
|
||||
l->tail_sentinel->prev = l->head_sentinel;
|
||||
|
@ -679,21 +711,21 @@ KS_DECLARE(int) list_clear(list_t *restrict l) {
|
|||
l->numels = 0;
|
||||
l->mid = NULL;
|
||||
|
||||
assert(list_repOk(l));
|
||||
assert(ks_list_repOk(l));
|
||||
|
||||
return numels;
|
||||
}
|
||||
|
||||
KS_DECLARE(unsigned int) list_size(const list_t *restrict l) {
|
||||
KS_DECLARE(unsigned int) ks_list_size(const ks_list_t *restrict l) {
|
||||
return l->numels;
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_empty(const list_t *restrict l) {
|
||||
KS_DECLARE(int) ks_list_empty(const ks_list_t *restrict l) {
|
||||
return (l->numels == 0);
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_locate(const list_t *restrict l, const void *data) {
|
||||
struct list_entry_s *el;
|
||||
KS_DECLARE(int) ks_list_locate(const ks_list_t *restrict l, const void *data) {
|
||||
struct ks_list_entry_s *el;
|
||||
int pos = 0;
|
||||
|
||||
if (l->attrs.comparator != NULL) {
|
||||
|
@ -713,8 +745,8 @@ KS_DECLARE(int) list_locate(const list_t *restrict l, const void *data) {
|
|||
return pos;
|
||||
}
|
||||
|
||||
KS_DECLARE(void *) list_seek(list_t *restrict l, const void *indicator) {
|
||||
const struct list_entry_s *iter;
|
||||
KS_DECLARE(void *) ks_list_seek(ks_list_t *restrict l, const void *indicator) {
|
||||
const struct ks_list_entry_s *iter;
|
||||
|
||||
if (l->attrs.seeker == NULL) return NULL;
|
||||
|
||||
|
@ -725,12 +757,12 @@ KS_DECLARE(void *) list_seek(list_t *restrict l, const void *indicator) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_contains(const list_t *restrict l, const void *data) {
|
||||
return (list_locate(l, data) >= 0);
|
||||
KS_DECLARE(int) ks_list_contains(const ks_list_t *restrict l, const void *data) {
|
||||
return (ks_list_locate(l, data) >= 0);
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest) {
|
||||
struct list_entry_s *el, *srcel;
|
||||
KS_DECLARE(int) ks_list_concat(const ks_list_t *l1, const ks_list_t *l2, ks_list_t *restrict dest) {
|
||||
struct ks_list_entry_s *el, *srcel;
|
||||
unsigned int cnt;
|
||||
int err;
|
||||
|
||||
|
@ -738,7 +770,7 @@ KS_DECLARE(int) list_concat(const list_t *l1, const list_t *l2, list_t *restrict
|
|||
if (l1 == NULL || l2 == NULL || dest == NULL || l1 == dest || l2 == dest)
|
||||
return -1;
|
||||
|
||||
list_init(dest);
|
||||
//ks_list_init(dest);
|
||||
|
||||
dest->numels = l1->numels + l2->numels;
|
||||
if (dest->numels == 0)
|
||||
|
@ -748,7 +780,7 @@ KS_DECLARE(int) list_concat(const list_t *l1, const list_t *l2, list_t *restrict
|
|||
srcel = l1->head_sentinel->next;
|
||||
el = dest->head_sentinel;
|
||||
while (srcel != l1->tail_sentinel) {
|
||||
el->next = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
|
||||
el->next = (struct ks_list_entry_s *)ks_pool_alloc(dest->pool, sizeof(struct ks_list_entry_s));
|
||||
el->next->prev = el;
|
||||
el = el->next;
|
||||
el->data = srcel->data;
|
||||
|
@ -758,7 +790,7 @@ KS_DECLARE(int) list_concat(const list_t *l1, const list_t *l2, list_t *restrict
|
|||
/* copy list 2 */
|
||||
srcel = l2->head_sentinel->next;
|
||||
while (srcel != l2->tail_sentinel) {
|
||||
el->next = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
|
||||
el->next = (struct ks_list_entry_s *)ks_pool_alloc(dest->pool, sizeof(struct ks_list_entry_s));
|
||||
el->next->prev = el;
|
||||
el = el->next;
|
||||
el->data = srcel->data;
|
||||
|
@ -778,43 +810,43 @@ KS_DECLARE(int) list_concat(const list_t *l1, const list_t *l2, list_t *restrict
|
|||
for (cnt = 0; cnt < (unsigned int)err; cnt++) dest->mid = dest->mid->prev;
|
||||
}
|
||||
|
||||
assert(!(list_repOk(l1) && list_repOk(l2)) || list_repOk(dest));
|
||||
assert(!(ks_list_repOk(l1) && ks_list_repOk(l2)) || ks_list_repOk(dest));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_sort(list_t *restrict l, int versus) {
|
||||
KS_DECLARE(int) ks_list_sort(ks_list_t *restrict l, int versus) {
|
||||
if (l->iter_active || l->attrs.comparator == NULL) /* cannot modify list in the middle of an iteration */
|
||||
return -1;
|
||||
|
||||
if (l->numels <= 1)
|
||||
return 0;
|
||||
list_sort_quicksort(l, versus, 0, l->head_sentinel->next, l->numels - 1, l->tail_sentinel->prev);
|
||||
assert(list_repOk(l));
|
||||
ks_list_sort_quicksort(l, versus, 0, l->head_sentinel->next, l->numels - 1, l->tail_sentinel->prev);
|
||||
assert(ks_list_repOk(l));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SIMCLIST_WITH_THREADS
|
||||
struct list_sort_wrappedparams {
|
||||
list_t *restrict l;
|
||||
struct ks_list_sort_wrappedparams {
|
||||
ks_list_t *restrict l;
|
||||
int versus;
|
||||
unsigned int first, last;
|
||||
struct list_entry_s *fel, *lel;
|
||||
struct ks_list_entry_s *fel, *lel;
|
||||
};
|
||||
|
||||
static void *list_sort_quicksort_threadwrapper(void *wrapped_params) {
|
||||
struct list_sort_wrappedparams *wp = (struct list_sort_wrappedparams *)wrapped_params;
|
||||
list_sort_quicksort(wp->l, wp->versus, wp->first, wp->fel, wp->last, wp->lel);
|
||||
free(wp);
|
||||
static void *ks_list_sort_quicksort_threadwrapper(void *wrapped_params) {
|
||||
struct ks_list_sort_wrappedparams *wp = (struct ks_list_sort_wrappedparams *)wrapped_params;
|
||||
ks_list_sort_quicksort(wp->l, wp->versus, wp->first, wp->fel, wp->last, wp->lel);
|
||||
ks_pool_free(wp->l->pool, &wp);
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void list_sort_selectionsort(list_t *restrict l, int versus,
|
||||
unsigned int first, struct list_entry_s *fel,
|
||||
unsigned int last, struct list_entry_s *lel) {
|
||||
struct list_entry_s *cursor, *toswap, *firstunsorted;
|
||||
static inline void ks_list_sort_selectionsort(ks_list_t *restrict l, int versus,
|
||||
unsigned int first, struct ks_list_entry_s *fel,
|
||||
unsigned int last, struct ks_list_entry_s *lel) {
|
||||
struct ks_list_entry_s *cursor, *toswap, *firstunsorted;
|
||||
void *tmpdata;
|
||||
|
||||
if (last <= first) /* <= 1-element lists are always sorted */
|
||||
|
@ -832,13 +864,13 @@ static inline void list_sort_selectionsort(list_t *restrict l, int versus,
|
|||
}
|
||||
}
|
||||
|
||||
static void list_sort_quicksort(list_t *restrict l, int versus,
|
||||
unsigned int first, struct list_entry_s *fel,
|
||||
unsigned int last, struct list_entry_s *lel) {
|
||||
static void ks_list_sort_quicksort(ks_list_t *restrict l, int versus,
|
||||
unsigned int first, struct ks_list_entry_s *fel,
|
||||
unsigned int last, struct ks_list_entry_s *lel) {
|
||||
unsigned int pivotid;
|
||||
unsigned int i;
|
||||
register struct list_entry_s *pivot;
|
||||
struct list_entry_s *left, *right;
|
||||
register struct ks_list_entry_s *pivot;
|
||||
struct ks_list_entry_s *left, *right;
|
||||
void *tmpdata;
|
||||
#ifdef SIMCLIST_WITH_THREADS
|
||||
pthread_t tid;
|
||||
|
@ -850,7 +882,7 @@ static void list_sort_quicksort(list_t *restrict l, int versus,
|
|||
return;
|
||||
|
||||
if (last - first + 1 <= SIMCLIST_MINQUICKSORTELS) {
|
||||
list_sort_selectionsort(l, versus, first, fel, last, lel);
|
||||
ks_list_sort_selectionsort(l, versus, first, fel, last, lel);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -930,7 +962,7 @@ static void list_sort_quicksort(list_t *restrict l, int versus,
|
|||
if (pivotid > 0) {
|
||||
/* prepare wrapped args, then start thread */
|
||||
if (l->threadcount < SIMCLIST_MAXTHREADS - 1) {
|
||||
struct list_sort_wrappedparams *wp = (struct list_sort_wrappedparams *)malloc(sizeof(struct list_sort_wrappedparams));
|
||||
struct ks_list_sort_wrappedparams *wp = (struct ks_list_sort_wrappedparams *)ks_pool_alloc(l->pool, sizeof(struct ks_list_sort_wrappedparams));
|
||||
l->threadcount++;
|
||||
traised = 1;
|
||||
wp->l = l;
|
||||
|
@ -939,28 +971,28 @@ static void list_sort_quicksort(list_t *restrict l, int versus,
|
|||
wp->fel = fel;
|
||||
wp->last = first + pivotid - 1;
|
||||
wp->lel = pivot->prev;
|
||||
if (pthread_create(&tid, NULL, list_sort_quicksort_threadwrapper, wp) != 0) {
|
||||
free(wp);
|
||||
if (pthread_create(&tid, NULL, ks_list_sort_quicksort_threadwrapper, wp) != 0) {
|
||||
ks_pool_free(l->pool, &wp);
|
||||
traised = 0;
|
||||
list_sort_quicksort(l, versus, first, fel, first + pivotid - 1, pivot->prev);
|
||||
ks_list_sort_quicksort(l, versus, first, fel, first + pivotid - 1, pivot->prev);
|
||||
}
|
||||
}
|
||||
else {
|
||||
list_sort_quicksort(l, versus, first, fel, first + pivotid - 1, pivot->prev);
|
||||
ks_list_sort_quicksort(l, versus, first, fel, first + pivotid - 1, pivot->prev);
|
||||
}
|
||||
}
|
||||
if (first + pivotid < last) list_sort_quicksort(l, versus, first + pivotid + 1, pivot->next, last, lel);
|
||||
if (first + pivotid < last) ks_list_sort_quicksort(l, versus, first + pivotid + 1, pivot->next, last, lel);
|
||||
if (traised) {
|
||||
pthread_join(tid, (void **)NULL);
|
||||
l->threadcount--;
|
||||
}
|
||||
#else
|
||||
if (pivotid > 0) list_sort_quicksort(l, versus, first, fel, first + pivotid - 1, pivot->prev);
|
||||
if (first + pivotid < last) list_sort_quicksort(l, versus, first + pivotid + 1, pivot->next, last, lel);
|
||||
if (pivotid > 0) ks_list_sort_quicksort(l, versus, first, fel, first + pivotid - 1, pivot->prev);
|
||||
if (first + pivotid < last) ks_list_sort_quicksort(l, versus, first + pivotid + 1, pivot->next, last, lel);
|
||||
#endif
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_iterator_start(list_t *restrict l) {
|
||||
KS_DECLARE(int) ks_list_iterator_start(ks_list_t *restrict l) {
|
||||
if (l->iter_active) return 0;
|
||||
l->iter_pos = 0;
|
||||
l->iter_active = 1;
|
||||
|
@ -968,7 +1000,7 @@ KS_DECLARE(int) list_iterator_start(list_t *restrict l) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
KS_DECLARE(void *) list_iterator_next(list_t *restrict l) {
|
||||
KS_DECLARE(void *) ks_list_iterator_next(ks_list_t *restrict l) {
|
||||
void *toret;
|
||||
|
||||
if (!l->iter_active) return NULL;
|
||||
|
@ -980,21 +1012,21 @@ KS_DECLARE(void *) list_iterator_next(list_t *restrict l) {
|
|||
return toret;
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_iterator_hasnext(const list_t *restrict l) {
|
||||
KS_DECLARE(int) ks_list_iterator_hasnext(const ks_list_t *restrict l) {
|
||||
if (!l->iter_active) return 0;
|
||||
return (l->iter_pos < l->numels);
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_iterator_stop(list_t *restrict l) {
|
||||
KS_DECLARE(int) ks_list_iterator_stop(ks_list_t *restrict l) {
|
||||
if (!l->iter_active) return 0;
|
||||
l->iter_pos = 0;
|
||||
l->iter_active = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
KS_DECLARE(int) list_hash(const list_t *restrict l, list_hash_t *restrict hash) {
|
||||
struct list_entry_s *x;
|
||||
list_hash_t tmphash;
|
||||
KS_DECLARE(int) ks_list_hash(const ks_list_t *restrict l, ks_list_hash_t *restrict hash) {
|
||||
struct ks_list_entry_s *x;
|
||||
ks_list_hash_t tmphash;
|
||||
|
||||
assert(hash != NULL);
|
||||
|
||||
|
@ -1030,7 +1062,7 @@ KS_DECLARE(int) list_hash(const list_t *restrict l, list_hash_t *restrict hash)
|
|||
}
|
||||
|
||||
#ifndef SIMCLIST_NO_DUMPRESTORE
|
||||
int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info) {
|
||||
int ks_list_dump_getinfo_filedescriptor(int fd, ks_list_dump_info_t *restrict info) {
|
||||
int32_t terminator_head, terminator_tail;
|
||||
uint32_t elemlen;
|
||||
off_t hop;
|
||||
|
@ -1095,24 +1127,24 @@ int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info) {
|
||||
int ks_list_dump_getinfo_file(const char *restrict filename, ks_list_dump_info_t *restrict info) {
|
||||
int fd, ret;
|
||||
|
||||
fd = open(filename, O_RDONLY, 0);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
ret = list_dump_getinfo_filedescriptor(fd, info);
|
||||
ret = ks_list_dump_getinfo_filedescriptor(fd, info);
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len) {
|
||||
struct list_entry_s *x;
|
||||
int ks_list_dump_filedescriptor(const ks_list_t *restrict l, int fd, ks_size_t *restrict len) {
|
||||
struct ks_list_entry_s *x;
|
||||
void *ser_buf;
|
||||
uint32_t bufsize;
|
||||
struct timeval timeofday;
|
||||
struct list_dump_header_s header;
|
||||
struct ks_list_dump_header_s header;
|
||||
|
||||
if (l->attrs.meter == NULL && l->attrs.serializer == NULL) {
|
||||
errno = ENOTTY;
|
||||
|
@ -1175,14 +1207,14 @@ int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict
|
|||
if (l->attrs.serializer != NULL) { /* user user-specified serializer */
|
||||
/* get preliminary length of serialized element in header.elemlen */
|
||||
ser_buf = l->attrs.serializer(l->head_sentinel->next->data, &header.elemlen);
|
||||
free(ser_buf);
|
||||
ks_pool_free(l->pool, &ser_buf);
|
||||
/* request custom serialization of each element */
|
||||
for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) {
|
||||
ser_buf = l->attrs.serializer(x->data, &bufsize);
|
||||
header.totlistlen += bufsize;
|
||||
if (header.elemlen != 0) { /* continue on speculation */
|
||||
if (header.elemlen != bufsize) {
|
||||
free(ser_buf);
|
||||
ks_pool_free(l->pool, &ser_buf);
|
||||
/* constant element length speculation broken! */
|
||||
header.elemlen = 0;
|
||||
header.totlistlen = 0;
|
||||
|
@ -1198,10 +1230,10 @@ int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict
|
|||
WRITE_ERRCHECK(fd, ser_buf, bufsize);
|
||||
}
|
||||
else { /* speculation found broken */
|
||||
WRITE_ERRCHECK(fd, &bufsize, sizeof(size_t));
|
||||
WRITE_ERRCHECK(fd, &bufsize, sizeof(ks_size_t));
|
||||
WRITE_ERRCHECK(fd, ser_buf, bufsize);
|
||||
}
|
||||
free(ser_buf);
|
||||
ks_pool_free(l->pool, &ser_buf);
|
||||
}
|
||||
}
|
||||
else if (l->attrs.meter != NULL) {
|
||||
|
@ -1223,7 +1255,7 @@ int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict
|
|||
WRITE_ERRCHECK(fd, x->data, bufsize);
|
||||
}
|
||||
else {
|
||||
WRITE_ERRCHECK(fd, &bufsize, sizeof(size_t));
|
||||
WRITE_ERRCHECK(fd, &bufsize, sizeof(ks_size_t));
|
||||
WRITE_ERRCHECK(fd, x->data, bufsize);
|
||||
}
|
||||
}
|
||||
|
@ -1259,8 +1291,8 @@ int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict
|
|||
return 0;
|
||||
}
|
||||
|
||||
int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len) {
|
||||
struct list_dump_header_s header;
|
||||
int ks_list_restore_filedescriptor(ks_list_t *restrict l, int fd, ks_size_t *restrict len) {
|
||||
struct ks_list_dump_header_s header;
|
||||
unsigned long cnt;
|
||||
void *buf;
|
||||
uint32_t elsize, totreadlen, totmemorylen;
|
||||
|
@ -1311,7 +1343,7 @@ int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len
|
|||
/* elements have constant size = header.elemlen */
|
||||
if (l->attrs.unserializer != NULL) {
|
||||
/* use unserializer */
|
||||
buf = malloc(header.elemlen);
|
||||
buf = ks_pool_alloc(l->pool, header.elemlen);
|
||||
for (cnt = 0; cnt < header.numels; cnt++) {
|
||||
READ_ERRCHECK(fd, buf, header.elemlen);
|
||||
list_append(l, l->attrs.unserializer(buf, &elsize));
|
||||
|
@ -1321,7 +1353,7 @@ int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len
|
|||
else {
|
||||
/* copy verbatim into memory */
|
||||
for (cnt = 0; cnt < header.numels; cnt++) {
|
||||
buf = malloc(header.elemlen);
|
||||
buf = ks_pool_alloc(l->pool, header.elemlen);
|
||||
READ_ERRCHECK(fd, buf, header.elemlen);
|
||||
list_append(l, buf);
|
||||
}
|
||||
|
@ -1335,7 +1367,7 @@ int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len
|
|||
/* use unserializer */
|
||||
for (cnt = 0; cnt < header.numels; cnt++) {
|
||||
READ_ERRCHECK(fd, &elsize, sizeof(elsize));
|
||||
buf = malloc((size_t)elsize);
|
||||
buf = ks_pool_alloc(l->pool, (ks_size_t)elsize);
|
||||
READ_ERRCHECK(fd, buf, elsize);
|
||||
totreadlen += elsize;
|
||||
list_append(l, l->attrs.unserializer(buf, &elsize));
|
||||
|
@ -1346,7 +1378,7 @@ int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len
|
|||
/* copy verbatim into memory */
|
||||
for (cnt = 0; cnt < header.numels; cnt++) {
|
||||
READ_ERRCHECK(fd, &elsize, sizeof(elsize));
|
||||
buf = malloc(elsize);
|
||||
buf = ks_pool_alloc(l->pool, elsize);
|
||||
READ_ERRCHECK(fd, buf, elsize);
|
||||
totreadlen += elsize;
|
||||
list_append(l, buf);
|
||||
|
@ -1386,7 +1418,7 @@ int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len
|
|||
return 0;
|
||||
}
|
||||
|
||||
int list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len) {
|
||||
int ks_list_dump_file(const ks_list_t *restrict l, const char *restrict filename, ks_size_t *restrict len) {
|
||||
int fd, oflag, mode;
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -1399,19 +1431,19 @@ int list_dump_file(const list_t *restrict l, const char *restrict filename, size
|
|||
fd = open(filename, oflag, mode);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
list_dump_filedescriptor(l, fd, len);
|
||||
ks_list_dump_filedescriptor(l, fd, len);
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int list_restore_file(list_t *restrict l, const char *restrict filename, size_t *restrict len) {
|
||||
int ks_list_restore_file(ks_list_t *restrict l, const char *restrict filename, ks_size_t *restrict len) {
|
||||
int fd;
|
||||
|
||||
fd = open(filename, O_RDONLY, 0);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
list_restore_filedescriptor(l, fd, len);
|
||||
ks_list_restore_filedescriptor(l, fd, len);
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
|
@ -1419,7 +1451,7 @@ int list_restore_file(list_t *restrict l, const char *restrict filename, size_t
|
|||
#endif /* ifndef SIMCLIST_NO_DUMPRESTORE */
|
||||
|
||||
|
||||
static int list_drop_elem(list_t *restrict l, struct list_entry_s *tmp, unsigned int pos) {
|
||||
static int ks_list_drop_elem(ks_list_t *restrict l, struct ks_list_entry_s *tmp, unsigned int pos) {
|
||||
if (tmp == NULL) return -1;
|
||||
|
||||
/* fix mid pointer. This is wrt the PRE situation */
|
||||
|
@ -1437,20 +1469,20 @@ static int list_drop_elem(list_t *restrict l, struct list_entry_s *tmp, unsigned
|
|||
|
||||
/* free what's to be freed */
|
||||
if (l->attrs.copy_data && tmp->data != NULL)
|
||||
free(tmp->data);
|
||||
ks_pool_free(l->pool, &tmp->data);
|
||||
|
||||
if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) {
|
||||
l->spareels[l->spareelsnum++] = tmp;
|
||||
}
|
||||
else {
|
||||
free(tmp);
|
||||
ks_pool_free(l->pool, &tmp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ready-made comparators and meters */
|
||||
#define SIMCLIST_NUMBER_COMPARATOR(type) int list_comparator_##type(const void *a, const void *b) { return( *(type *)a < *(type *)b) - (*(type *)a > *(type *)b); }
|
||||
#define SIMCLIST_NUMBER_COMPARATOR(type) int ks_list_comparator_##type(const void *a, const void *b) { return( *(type *)a < *(type *)b) - (*(type *)a > *(type *)b); }
|
||||
|
||||
SIMCLIST_NUMBER_COMPARATOR(int8_t)
|
||||
SIMCLIST_NUMBER_COMPARATOR(int16_t)
|
||||
|
@ -1465,10 +1497,10 @@ SIMCLIST_NUMBER_COMPARATOR(uint64_t)
|
|||
SIMCLIST_NUMBER_COMPARATOR(float)
|
||||
SIMCLIST_NUMBER_COMPARATOR(double)
|
||||
|
||||
int list_comparator_string(const void *a, const void *b) { return strcmp((const char *)b, (const char *)a); }
|
||||
int ks_list_comparator_string(const void *a, const void *b) { return strcmp((const char *)b, (const char *)a); }
|
||||
|
||||
/* ready-made metric functions */
|
||||
#define SIMCLIST_METER(type) size_t list_meter_##type(const void *el) { if (el) { /* kill compiler whinge */ } return sizeof(type); }
|
||||
#define SIMCLIST_METER(type) ks_size_t ks_list_meter_##type(const void *el) { if (el) { /* kill compiler whinge */ } return sizeof(type); }
|
||||
|
||||
SIMCLIST_METER(int8_t)
|
||||
SIMCLIST_METER(int16_t)
|
||||
|
@ -1483,10 +1515,10 @@ SIMCLIST_METER(uint64_t)
|
|||
SIMCLIST_METER(float)
|
||||
SIMCLIST_METER(double)
|
||||
|
||||
size_t list_meter_string(const void *el) { return strlen((const char *)el) + 1; }
|
||||
ks_size_t ks_list_meter_string(const void *el) { return strlen((const char *)el) + 1; }
|
||||
|
||||
/* ready-made hashing functions */
|
||||
#define SIMCLIST_HASHCOMPUTER(type) list_hash_t list_hashcomputer_##type(const void *el) { return (list_hash_t)(*(type *)el); }
|
||||
#define SIMCLIST_HASHCOMPUTER(type) ks_list_hash_t ks_list_hashcomputer_##type(const void *el) { return (ks_list_hash_t)(*(type *)el); }
|
||||
|
||||
SIMCLIST_HASHCOMPUTER(int8_t)
|
||||
SIMCLIST_HASHCOMPUTER(int16_t)
|
||||
|
@ -1501,16 +1533,16 @@ SIMCLIST_HASHCOMPUTER(uint64_t)
|
|||
SIMCLIST_HASHCOMPUTER(float)
|
||||
SIMCLIST_HASHCOMPUTER(double)
|
||||
|
||||
list_hash_t list_hashcomputer_string(const void *el) {
|
||||
size_t l;
|
||||
list_hash_t hash = 123;
|
||||
ks_list_hash_t ks_list_hashcomputer_string(const void *el) {
|
||||
ks_size_t l;
|
||||
ks_list_hash_t hash = 123;
|
||||
const char *str = (const char *)el;
|
||||
char plus;
|
||||
|
||||
for (l = 0; str[l] != '\0'; l++) {
|
||||
if (l) plus = (char)(hash ^ str[l]);
|
||||
else plus = (char)(hash ^ (str[l] - str[0]));
|
||||
hash += (plus << (CHAR_BIT * (l % sizeof(list_hash_t))));
|
||||
hash += (plus << (CHAR_BIT * (l % sizeof(ks_list_hash_t))));
|
||||
}
|
||||
|
||||
return hash;
|
||||
|
@ -1518,9 +1550,9 @@ list_hash_t list_hashcomputer_string(const void *el) {
|
|||
|
||||
|
||||
#ifndef NDEBUG
|
||||
static int list_repOk(const list_t *restrict l) {
|
||||
static int ks_list_repOk(const ks_list_t *restrict l) {
|
||||
int ok, i;
|
||||
struct list_entry_s *s;
|
||||
struct ks_list_entry_s *s;
|
||||
|
||||
ok = (l != NULL) && (
|
||||
/* head/tail checks */
|
||||
|
@ -1550,7 +1582,7 @@ static int list_repOk(const list_t *restrict l) {
|
|||
return ok;
|
||||
}
|
||||
|
||||
static int list_attrOk(const list_t *restrict l) {
|
||||
static int ks_list_attrOk(const ks_list_t *restrict l) {
|
||||
int ok;
|
||||
|
||||
ok = (l->attrs.copy_data == 0 || l->attrs.meter != NULL);
|
||||
|
|
Loading…
Reference in New Issue