227 lines
6.3 KiB
C
227 lines
6.3 KiB
C
/**
|
|
* Copyright (C) 2015 Happy Fish / YuQing
|
|
*
|
|
* libfastcommon may be copied only under the terms of the GNU General
|
|
* Public License V3, which may be found in the FastDFS source kit.
|
|
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
|
|
**/
|
|
|
|
//skiplist.h, support stable sort :)
|
|
#ifndef _SKIPLIST_H
|
|
#define _SKIPLIST_H
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "common_define.h"
|
|
#include "skiplist_common.h"
|
|
#include "flat_skiplist.h"
|
|
#include "multi_skiplist.h"
|
|
#include "skiplist_set.h"
|
|
|
|
#define SKIPLIST_TYPE_FLAT 0
|
|
#define SKIPLIST_TYPE_MULTI 1
|
|
#define SKIPLIST_TYPE_SET 2
|
|
|
|
typedef struct skiplist
|
|
{
|
|
int type;
|
|
union {
|
|
FlatSkiplist flat;
|
|
MultiSkiplist multi;
|
|
SkiplistSet set;
|
|
} u;
|
|
} Skiplist;
|
|
|
|
typedef struct skiplist_iterator {
|
|
int type;
|
|
union {
|
|
FlatSkiplistIterator flat;
|
|
MultiSkiplistIterator multi;
|
|
SkiplistSetIterator set;
|
|
} u;
|
|
} SkiplistIterator;
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define skiplist_init(sl, level_count, compare_func, free_func) \
|
|
skiplist_init_ex(sl, level_count, compare_func, free_func, \
|
|
SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE, SKIPLIST_TYPE_FLAT)
|
|
|
|
static inline int skiplist_init_ex(Skiplist *sl, const int level_count,
|
|
skiplist_compare_func compare_func, skiplist_free_func free_func,
|
|
const int min_alloc_elements_once, const int type)
|
|
{
|
|
sl->type = type;
|
|
switch (type) {
|
|
case SKIPLIST_TYPE_FLAT:
|
|
return flat_skiplist_init_ex(&sl->u.flat, level_count,
|
|
compare_func, free_func, min_alloc_elements_once);
|
|
case SKIPLIST_TYPE_MULTI:
|
|
return multi_skiplist_init_ex(&sl->u.multi, level_count,
|
|
compare_func, free_func, min_alloc_elements_once);
|
|
case SKIPLIST_TYPE_SET:
|
|
return skiplist_set_init_ex(&sl->u.set, level_count,
|
|
compare_func, free_func, min_alloc_elements_once);
|
|
default:
|
|
return EINVAL;
|
|
}
|
|
}
|
|
|
|
static inline void skiplist_destroy(Skiplist *sl)
|
|
{
|
|
switch (sl->type) {
|
|
case SKIPLIST_TYPE_FLAT:
|
|
flat_skiplist_destroy(&sl->u.flat);
|
|
break;
|
|
case SKIPLIST_TYPE_MULTI:
|
|
multi_skiplist_destroy(&sl->u.multi);
|
|
break;
|
|
case SKIPLIST_TYPE_SET:
|
|
skiplist_set_destroy(&sl->u.set);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static inline int skiplist_insert(Skiplist *sl, void *data)
|
|
{
|
|
switch (sl->type) {
|
|
case SKIPLIST_TYPE_FLAT:
|
|
return flat_skiplist_insert(&sl->u.flat, data);
|
|
case SKIPLIST_TYPE_MULTI:
|
|
return multi_skiplist_insert(&sl->u.multi, data);
|
|
case SKIPLIST_TYPE_SET:
|
|
return skiplist_set_insert(&sl->u.set, data);
|
|
default:
|
|
return EINVAL;
|
|
}
|
|
}
|
|
|
|
static inline int skiplist_delete(Skiplist *sl, void *data)
|
|
{
|
|
switch (sl->type) {
|
|
case SKIPLIST_TYPE_FLAT:
|
|
return flat_skiplist_delete(&sl->u.flat, data);
|
|
case SKIPLIST_TYPE_MULTI:
|
|
return multi_skiplist_delete(&sl->u.multi, data);
|
|
case SKIPLIST_TYPE_SET:
|
|
return skiplist_set_delete(&sl->u.set, data);
|
|
default:
|
|
return EINVAL;
|
|
}
|
|
}
|
|
|
|
static inline int skiplist_delete_all(Skiplist *sl, void *data, int *delete_count)
|
|
{
|
|
int result;
|
|
switch (sl->type) {
|
|
case SKIPLIST_TYPE_FLAT:
|
|
return flat_skiplist_delete_all(&sl->u.flat, data, delete_count);
|
|
case SKIPLIST_TYPE_MULTI:
|
|
return multi_skiplist_delete_all(&sl->u.multi, data, delete_count);
|
|
case SKIPLIST_TYPE_SET:
|
|
result = skiplist_set_delete(&sl->u.set, data);
|
|
*delete_count = (result == 0) ? 1 : 0;
|
|
return result;
|
|
default:
|
|
return EINVAL;
|
|
}
|
|
}
|
|
|
|
static inline void *skiplist_find(Skiplist *sl, void *data)
|
|
{
|
|
switch (sl->type) {
|
|
case SKIPLIST_TYPE_FLAT:
|
|
return flat_skiplist_find(&sl->u.flat, data);
|
|
case SKIPLIST_TYPE_MULTI:
|
|
return multi_skiplist_find(&sl->u.multi, data);
|
|
case SKIPLIST_TYPE_SET:
|
|
return skiplist_set_find(&sl->u.set, data);
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static inline int skiplist_find_all(Skiplist *sl, void *data, SkiplistIterator *iterator)
|
|
{
|
|
iterator->type = sl->type;
|
|
switch (sl->type) {
|
|
case SKIPLIST_TYPE_FLAT:
|
|
return flat_skiplist_find_all(&sl->u.flat, data, &iterator->u.flat);
|
|
case SKIPLIST_TYPE_MULTI:
|
|
return multi_skiplist_find_all(&sl->u.multi, data, &iterator->u.multi);
|
|
case SKIPLIST_TYPE_SET:
|
|
return EOPNOTSUPP;
|
|
default:
|
|
return EINVAL;
|
|
}
|
|
}
|
|
|
|
static inline void skiplist_iterator(Skiplist *sl, SkiplistIterator *iterator)
|
|
{
|
|
iterator->type = sl->type;
|
|
switch (sl->type) {
|
|
case SKIPLIST_TYPE_FLAT:
|
|
return flat_skiplist_iterator(&sl->u.flat, &iterator->u.flat);
|
|
case SKIPLIST_TYPE_MULTI:
|
|
return multi_skiplist_iterator(&sl->u.multi, &iterator->u.multi);
|
|
case SKIPLIST_TYPE_SET:
|
|
return skiplist_set_iterator(&sl->u.set, &iterator->u.set);
|
|
default:
|
|
return EINVAL;
|
|
}
|
|
}
|
|
|
|
static inline void *skiplist_next(SkiplistIterator *iterator)
|
|
{
|
|
switch (iterator->type) {
|
|
case SKIPLIST_TYPE_FLAT:
|
|
return flat_skiplist_next(&iterator->u.flat);
|
|
case SKIPLIST_TYPE_MULTI:
|
|
return multi_skiplist_next(&iterator->u.multi);
|
|
case SKIPLIST_TYPE_SET:
|
|
return skiplist_set_next(&iterator->u.set);
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static inline bool skiplist_empty(Skiplist *sl)
|
|
{
|
|
switch (sl->type) {
|
|
case SKIPLIST_TYPE_FLAT:
|
|
return flat_skiplist_empty(&sl->u.flat);
|
|
case SKIPLIST_TYPE_MULTI:
|
|
return multi_skiplist_empty(&sl->u.multi);
|
|
case SKIPLIST_TYPE_SET:
|
|
return skiplist_set_empty(&sl->u.set);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static inline const char* skiplist_get_type_caption(Skiplist *sl)
|
|
{
|
|
switch (sl->type) {
|
|
case SKIPLIST_TYPE_FLAT:
|
|
return "flat";
|
|
case SKIPLIST_TYPE_MULTI:
|
|
return "multi";
|
|
case SKIPLIST_TYPE_SET:
|
|
return "set";
|
|
default:
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|