第六章 算法和容器¶
6.1 容器¶
1) typedef.h¶
/*
* File: typedef.h
*/
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#ifndef TYPEDEF_H
#define TYPEDEF_H
typedef enum _Ret
{
RET_OK,
RET_OOM,
RET_STOP,
RET_INVALID_PARAMS,
RET_FAIL
}Ret;
typedef void (*DataDestroyFunc)(void* ctx, void* data);
typedef int (*DataCompareFunc)(void* ctx, void* data);
typedef Ret (*DataVisitFunc)(void* ctx, void* data);
typedef int (*DataHashFunc)(void* data);
#ifdef __cplusplus
#define DECLS_BEGIN extern "C" {
#define DECLS_END }
#else
#define DECLS_BEGIN
#define DECLS_END
#endif/*__cplusplus*/
#define return_if_fail(p) if(!(p)) \
{printf("%s:%d Warning: "#p" failed.\n", \
__func__, __LINE__); return;}
#define return_val_if_fail(p, ret) if(!(p)) \
{printf("%s:%d Warning: "#p" failed.\n",\
__func__, __LINE__); return (ret);}
#define SAFE_FREE(p) if(p != NULL) {free(p); p = NULL;}
typedef Ret (*SortFunc)(void** array, size_t nr, DataCompareFunc cmp);
#endif/*TYPEDEF_H*/
2) darray¶
/*
* File: darray.h
*/
#include <stdio.h>
#include "typedef.h"
#ifndef DARRAY_H
#define DARRAY_H
DECLS_BEGIN
struct _DArray;
typedef struct _DArray DArray;
DArray* darray_create(DataDestroyFunc data_destroy, void* ctx);
Ret darray_insert(DArray* thiz, size_t index, void* data);
Ret darray_prepend(DArray* thiz, void* data);
Ret darray_append(DArray* thiz, void* data);
Ret darray_delete(DArray* thiz, size_t index);
Ret darray_get_by_index(DArray* thiz, size_t index, void** data);
Ret darray_set_by_index(DArray* thiz, size_t index, void* data);
size_t darray_length(DArray* thiz);
int darray_find(DArray* thiz, DataCompareFunc cmp, void* ctx);
Ret darray_foreach(DArray* thiz, DataVisitFunc visit, void* ctx);
Ret darray_sort(DArray* thiz, SortFunc sort, DataCompareFunc cmp);
void darray_destroy(DArray* thiz);
DECLS_END
#endif/*DARRAY_H*/
/*
* File: darray.c
*/
#include <stdlib.h>
#include "darray.h"
struct _DArray
{
void** data;
size_t size;
size_t alloc_size;
void* data_destroy_ctx;
DataDestroyFunc data_destroy;
};
static void darray_destroy_data(DArray* thiz, void* data)
{
if(thiz->data_destroy != NULL) {
thiz->data_destroy(thiz->data_destroy_ctx, data);
}
return;
}
DArray* darray_create(DataDestroyFunc data_destroy, void* ctx)
{
DArray* thiz = malloc(sizeof(DArray));
if(thiz != NULL) {
thiz->data = NULL;
thiz->size = 0;
thiz->alloc_size = 0;
thiz->data_destroy = data_destroy;
thiz->data_destroy_ctx = ctx;
}
return thiz;
}
#define MIN_PRE_ALLOCATE_NR 10
static Ret darray_expand(DArray* thiz, size_t need)
{
return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);
if((thiz->size + need) > thiz->alloc_size) {
size_t alloc_size = thiz->alloc_size + (thiz->alloc_size>>1) + MIN_PRE_ALLOCATE_NR;
void** data = (void**)realloc(thiz->data, sizeof(void*) * alloc_size);
if(data != NULL) {
thiz->data = data;
thiz->alloc_size = alloc_size;
}
}
return ((thiz->size + need) <= thiz->alloc_size) ? RET_OK : RET_FAIL;
}
static Ret darray_shrink(DArray* thiz)
{
return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);
if((thiz->size < (thiz->alloc_size >> 1)) && (thiz->alloc_size > MIN_PRE_ALLOCATE_NR)) {
size_t alloc_size = thiz->size + (thiz->size >> 1);
void** data = (void**)realloc(thiz->data, sizeof(void*) * alloc_size);
if(data != NULL) {
thiz->data = data;
thiz->alloc_size = alloc_size;
}
}
return RET_OK;
}
Ret darray_insert(DArray* thiz, size_t index, void* data)
{
Ret ret = RET_OOM;
size_t cursor = index;
return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);
cursor = cursor < thiz->size ? cursor : thiz->size;
if(darray_expand(thiz, 1) == RET_OK) {
size_t i = 0;
for(i = thiz->size; i > cursor; i--) {
thiz->data[i] = thiz->data[i-1];
}
thiz->data[cursor] = data;
thiz->size++;
ret = RET_OK;
}
return ret;
}
Ret darray_prepend(DArray* thiz, void* data)
{
return darray_insert(thiz, 0, data);
}
Ret darray_append(DArray* thiz, void* data)
{
return darray_insert(thiz, -1, data);
}
Ret darray_delete(DArray* thiz, size_t index)
{
size_t i = 0;
return_val_if_fail(thiz != NULL && thiz->size > index, RET_INVALID_PARAMS);
darray_destroy_data(thiz, thiz->data[index]);
for(i = index; (i+1) < thiz->size; i++) {
thiz->data[i] = thiz->data[i+1];
}
thiz->size--;
darray_shrink(thiz);
return RET_OK;
}
Ret darray_get_by_index(DArray* thiz, size_t index, void** data)
{
return_val_if_fail(thiz != NULL && data != NULL && index < thiz->size,
RET_INVALID_PARAMS);
*data = thiz->data[index];
return RET_OK;
}
Ret darray_set_by_index(DArray* thiz, size_t index, void* data)
{
return_val_if_fail(thiz != NULL && index < thiz->size,
RET_INVALID_PARAMS);
thiz->data[index] = data;
return RET_OK;
}
size_t darray_length(DArray* thiz)
{
return_val_if_fail(thiz != NULL, 0);
return thiz->size;
}
Ret darray_foreach(DArray* thiz, DataVisitFunc visit, void* ctx)
{
size_t i = 0;
Ret ret = RET_OK;
return_val_if_fail(thiz != NULL && visit != NULL, RET_INVALID_PARAMS);
for(i = 0; i < thiz->size; i++) {
ret = visit(ctx, thiz->data[i]);
}
return ret;
}
int darray_find(DArray* thiz, DataCompareFunc cmp, void* ctx)
{
size_t i = 0;
return_val_if_fail(thiz != NULL && cmp != NULL, -1);
for(i = 0; i < thiz->size; i++) {
if(cmp(ctx, thiz->data[i]) == 0) {
break;
}
}
return i;
}
void darray_destroy(DArray* thiz)
{
size_t i = 0;
if(thiz != NULL) {
for(i = 0; i < thiz->size; i++) {
darray_destroy_data(thiz, thiz->data[i]);
}
SAFE_FREE(thiz->data);
SAFE_FREE(thiz);
}
return;
}
Ret darray_sort(DArray* thiz, SortFunc sort, DataCompareFunc cmp)
{
return_val_if_fail(thiz != NULL && sort != NULL && cmp != NULL, RET_INVALID_PARAMS);
return sort(thiz->data, thiz->size, cmp);
}
#ifdef DARRAY_TEST
#include <assert.h>
#include "test_helper.c"
static void test_int_darray(void)
{
int i = 0;
int n = 100;
int data = 0;
DArray* darray = darray_create(NULL, NULL);
for(i = 0; i < n; i++) {
assert(darray_append(darray, (void*)i) == RET_OK);
assert(darray_length(darray) == (i + 1));
assert(darray_get_by_index(darray, i, (void**)&data) == RET_OK);
assert(data == i);
assert(darray_set_by_index(darray, i, (void*)(2*i)) == RET_OK);
assert(darray_get_by_index(darray, i, (void**)&data) == RET_OK);
assert(data == 2*i);
assert(darray_set_by_index(darray, i, (void*)i) == RET_OK);
assert(darray_find(darray, cmp_int, (void*)i) == i);
}
for(i = 0; i < n; i++) {
assert(darray_get_by_index(darray, 0, (void**)&data) == RET_OK);
assert(data == (i));
assert(darray_length(darray) == (n-i));
assert(darray_delete(darray, 0) == RET_OK);
assert(darray_length(darray) == (n-i-1));
if((i + 1) < n) {
assert(darray_get_by_index(darray, 0, (void**)&data) == RET_OK);
assert((int)data == (i+1));
}
}
assert(darray_length(darray) == 0);
for(i = 0; i < n; i++) {
assert(darray_prepend(darray, (void*)i) == RET_OK);
assert(darray_length(darray) == (i + 1));
assert(darray_get_by_index(darray, 0, (void**)&data) == RET_OK);
assert(data == i);
assert(darray_set_by_index(darray, 0, (void*)(2*i)) == RET_OK);
assert(darray_get_by_index(darray, 0, (void**)&data) == RET_OK);
assert(data == 2*i);
assert(darray_set_by_index(darray, 0, (void*)i) == RET_OK);
}
i = n - 1;
assert(darray_foreach(darray, check_and_dec_int, &i) == RET_OK);
darray_destroy(darray);
return;
}
static void test_invalid_params(void)
{
printf("===========Warning is normal begin==============\n");
assert(darray_length(NULL) == 0);
assert(darray_prepend(NULL, 0) == RET_INVALID_PARAMS);
assert(darray_append(NULL, 0) == RET_INVALID_PARAMS);
assert(darray_delete(NULL, 0) == RET_INVALID_PARAMS);
assert(darray_insert(NULL, 0, 0) == RET_INVALID_PARAMS);
assert(darray_set_by_index(NULL, 0, 0) == RET_INVALID_PARAMS);
assert(darray_get_by_index(NULL, 0, NULL) == RET_INVALID_PARAMS);
assert(darray_find(NULL, NULL, NULL) < 0);
assert(darray_foreach(NULL, NULL, NULL) == RET_INVALID_PARAMS);
printf("===========Warning is normal end==============\n");
return;
}
static void single_thread_test(void)
{
test_int_darray();
test_invalid_params();
return;
}
int main(int argc, char* argv[])
{
single_thread_test();
return 0;
}
#endif
gcc -Wall -Wno-unused-function -g -m32 -DDARRAY_TEST darray.c -o darray_test
3) dlist¶
/*
* File: dlist.h
*/
#include <stdio.h>
#include "typedef.h"
#ifndef DLIST_H
#define DLIST_H
DECLS_BEGIN
struct _DList;
typedef struct _DList DList;
DList* dlist_create(DataDestroyFunc data_destroy, void* ctx);
Ret dlist_insert(DList* thiz, size_t index, void* data);
Ret dlist_prepend(DList* thiz, void* data);
Ret dlist_append(DList* thiz, void* data);
Ret dlist_delete(DList* thiz, size_t index);
Ret dlist_get_by_index(DList* thiz, size_t index, void** data);
Ret dlist_set_by_index(DList* thiz, size_t index, void* data);
size_t dlist_length(DList* thiz);
int dlist_find(DList* thiz, DataCompareFunc cmp, void* ctx);
Ret dlist_foreach(DList* thiz, DataVisitFunc visit, void* ctx);
void dlist_destroy(DList* thiz);
DECLS_END
#endif/*DLIST*/
/*
* File: dlist.c
*/
#include <stdlib.h>
#include "dlist.h"
typedef struct _DListNode
{
struct _DListNode* prev;
struct _DListNode* next;
void* data;
}DListNode;
struct _DList
{
DListNode* first;
void* data_destroy_ctx;
DataDestroyFunc data_destroy;
};
static void dlist_destroy_data(DList* thiz, void* data)
{
if(thiz->data_destroy != NULL) {
thiz->data_destroy(thiz->data_destroy_ctx, data);
}
return;
}
static DListNode* dlist_create_node(DList* thiz, void* data)
{
DListNode* node = malloc(sizeof(DListNode));
if(node != NULL) {
node->prev = NULL;
node->next = NULL;
node->data = data;
}
return node;
}
static void dlist_destroy_node(DList* thiz, DListNode* node)
{
if(node != NULL) {
node->next = NULL;
node->prev = NULL;
dlist_destroy_data(thiz, node->data);
SAFE_FREE(node);
}
return;
}
DList* dlist_create(DataDestroyFunc data_destroy, void* ctx)
{
DList* thiz = malloc(sizeof(DList));
if(thiz != NULL) {
thiz->first = NULL;
thiz->data_destroy = data_destroy;
thiz->data_destroy_ctx = ctx;
}
return thiz;
}
static DListNode* dlist_get_node(DList* thiz, size_t index, int fail_return_last)
{
DListNode* iter = NULL;
return_val_if_fail(thiz != NULL, NULL);
iter = thiz->first;
while(iter != NULL && iter->next != NULL && index > 0) {
iter = iter->next;
index--;
}
if(!fail_return_last) {
iter = index > 0 ? NULL : iter;
}
return iter;
}
Ret dlist_insert(DList* thiz, size_t index, void* data)
{
Ret ret = RET_OK;
DListNode* node = NULL;
DListNode* cursor = NULL;
return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);
do
{
if((node = dlist_create_node(thiz, data)) == NULL) {
ret = RET_OOM;
break;
}
if(thiz->first == NULL) {
thiz->first = node;
break;
}
cursor = dlist_get_node(thiz, index, 1);
if(index < dlist_length(thiz)) {
node->next = cursor;
if(cursor->prev != NULL) {
cursor->prev->next = node;
}
cursor->prev = node;
if(thiz->first == cursor) {
thiz->first = node;
}
} else {
cursor->next = node;
node->prev = cursor;
}
}while(0);
return ret;
}
Ret dlist_prepend(DList* thiz, void* data)
{
return dlist_insert(thiz, 0, data);
}
Ret dlist_append(DList* thiz, void* data)
{
return dlist_insert(thiz, -1, data);
}
Ret dlist_delete(DList* thiz, size_t index)
{
Ret ret = RET_OK;
DListNode* cursor = NULL;
return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);
cursor = dlist_get_node(thiz, index, 0);
do
{
if(cursor == NULL) {
ret = RET_INVALID_PARAMS;
break;
}
if(cursor != NULL) {
if(cursor == thiz->first) {
thiz->first = cursor->next;
}
if(cursor->next != NULL) {
cursor->next->prev = cursor->prev;
}
if(cursor->prev != NULL) {
cursor->prev->next = cursor->next;
}
dlist_destroy_node(thiz, cursor);
}
}while(0);
return RET_OK;
}
Ret dlist_get_by_index(DList* thiz, size_t index, void** data)
{
DListNode* cursor = NULL;
return_val_if_fail(thiz != NULL && data != NULL, RET_INVALID_PARAMS);
cursor = dlist_get_node(thiz, index, 0);
if(cursor != NULL) {
*data = cursor->data;
}
return cursor != NULL ? RET_OK : RET_INVALID_PARAMS;
}
Ret dlist_set_by_index(DList* thiz, size_t index, void* data)
{
DListNode* cursor = NULL;
return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);
cursor = dlist_get_node(thiz, index, 0);
if(cursor != NULL) {
cursor->data = data;
}
return cursor != NULL ? RET_OK : RET_INVALID_PARAMS;
}
size_t dlist_length(DList* thiz)
{
size_t length = 0;
DListNode* iter = NULL;
return_val_if_fail(thiz != NULL, 0);
iter = thiz->first;
while(iter != NULL) {
length++;
iter = iter->next;
}
return length;
}
Ret dlist_foreach(DList* thiz, DataVisitFunc visit, void* ctx)
{
Ret ret = RET_OK;
DListNode* iter = NULL;
return_val_if_fail(thiz != NULL && visit != NULL, RET_INVALID_PARAMS);
iter = thiz->first;
while(iter != NULL && ret != RET_STOP) {
ret = visit(ctx, iter->data);
iter = iter->next;
}
return ret;
}
int dlist_find(DList* thiz, DataCompareFunc cmp, void* ctx)
{
int i = 0;
DListNode* iter = NULL;
return_val_if_fail(thiz != NULL && cmp != NULL, -1);
iter = thiz->first;
while(iter != NULL) {
if(cmp(ctx, iter->data) == 0) {
break;
}
i++;
iter = iter->next;
}
return i;
}
void dlist_destroy(DList* thiz)
{
DListNode* iter = NULL;
DListNode* next = NULL;
return_if_fail(thiz != NULL);
iter = thiz->first;
while(iter != NULL) {
next = iter->next;
dlist_destroy_node(thiz, iter);
iter = next;
}
thiz->first = NULL;
SAFE_FREE(thiz);
return;
}
#ifdef DLIST_TEST
#include <unistd.h>
#include <assert.h>
#include <pthread.h>
#include "test_helper.c"
static void test_int_dlist(void)
{
int i = 0;
int n = 100;
int data = 0;
DList* dlist = dlist_create(NULL, NULL);
for(i = 0; i < n; i++) {
assert(dlist_append(dlist, (void*)i) == RET_OK);
assert(dlist_length(dlist) == (i + 1));
assert(dlist_get_by_index(dlist, i, (void**)&data) == RET_OK);
assert(data == i);
assert(dlist_set_by_index(dlist, i, (void*)(2*i)) == RET_OK);
assert(dlist_get_by_index(dlist, i, (void**)&data) == RET_OK);
assert(data == 2*i);
assert(dlist_set_by_index(dlist, i, (void*)i) == RET_OK);
assert(dlist_find(dlist, cmp_int, (void*)i) == i);
}
for(i = 0; i < n; i++) {
assert(dlist_get_by_index(dlist, 0, (void**)&data) == RET_OK);
assert(data == (i));
assert(dlist_length(dlist) == (n-i));
assert(dlist_delete(dlist, 0) == RET_OK);
assert(dlist_length(dlist) == (n-i-1));
if((i + 1) < n)
{
assert(dlist_get_by_index(dlist, 0, (void**)&data) == RET_OK);
assert((int)data == (i+1));
}
}
assert(dlist_length(dlist) == 0);
for(i = 0; i < n; i++) {
assert(dlist_prepend(dlist, (void*)i) == RET_OK);
assert(dlist_length(dlist) == (i + 1));
assert(dlist_get_by_index(dlist, 0, (void**)&data) == RET_OK);
assert(data == i);
assert(dlist_set_by_index(dlist, 0, (void*)(2*i)) == RET_OK);
assert(dlist_get_by_index(dlist, 0, (void**)&data) == RET_OK);
assert(data == 2*i);
assert(dlist_set_by_index(dlist, 0, (void*)i) == RET_OK);
}
i = n - 1;
assert(dlist_foreach(dlist, check_and_dec_int, &i) == RET_OK);
dlist_destroy(dlist);
return;
}
static void test_invalid_params(void)
{
printf("===========Warning is normal begin==============\n");
assert(dlist_length(NULL) == 0);
assert(dlist_prepend(NULL, 0) == RET_INVALID_PARAMS);
assert(dlist_append(NULL, 0) == RET_INVALID_PARAMS);
assert(dlist_delete(NULL, 0) == RET_INVALID_PARAMS);
assert(dlist_insert(NULL, 0, 0) == RET_INVALID_PARAMS);
assert(dlist_set_by_index(NULL, 0, 0) == RET_INVALID_PARAMS);
assert(dlist_get_by_index(NULL, 0, NULL) == RET_INVALID_PARAMS);
assert(dlist_find(NULL, NULL, NULL) < 0);
assert(dlist_foreach(NULL, NULL, NULL) == RET_INVALID_PARAMS);
printf("===========Warning is normal end==============\n");
return;
}
static void single_thread_test(void)
{
test_int_dlist();
test_invalid_params();
return;
}
#define NR 1000
int main(int argc, char* argv[])
{
single_thread_test();
return 0;
}
#endif
gcc -Wall -Wno-unused-function -g -m32 -DDLIST_TEST dlist.c -o dlist_test
4) linear_container_dlist¶
/*
* File: linear_container.h
*/
#ifndef LINEAR_CONTAINER_H
#define LINEAR_CONTAINER_H
#include "typedef.h"
DECLS_BEGIN
struct _LinearContainer;
typedef struct _LinearContainer LinearContainer;
typedef Ret (*LinearContainerInsert)(LinearContainer* thiz, size_t index, void* data);
typedef Ret (*LinearContainerPrepend)(LinearContainer* thiz, void* data);
typedef Ret (*LinearContainerAppend)(LinearContainer* thiz, void* data);
typedef Ret (*LinearContainerDelete)(LinearContainer* thiz, size_t index);
typedef Ret (*LinearContainerGetByIndex)(LinearContainer* thiz, size_t index, void** data);
typedef Ret (*LinearContainerSetByIndex)(LinearContainer* thiz, size_t index, void* data);
typedef size_t (*LinearContainerLength)(LinearContainer* thiz);
typedef int (*LinearContainerFind)(LinearContainer* thiz, DataCompareFunc cmp, void* ctx);
typedef Ret (*LinearContainerForeach)(LinearContainer* thiz, DataVisitFunc visit, void* ctx);
typedef void (*LinearContainerDestroy)(LinearContainer* thiz);
struct _LinearContainer
{
LinearContainerInsert insert;
LinearContainerPrepend prepend;
LinearContainerAppend append;
LinearContainerDelete del;
LinearContainerGetByIndex get_by_index;
LinearContainerSetByIndex set_by_index;
LinearContainerLength length;
LinearContainerFind find;
LinearContainerForeach foreach;
LinearContainerDestroy destroy;
char priv[0];
};
static inline Ret linear_container_insert(LinearContainer* thiz, size_t index, void* data)
{
return_val_if_fail(thiz != NULL && thiz->insert != NULL, RET_INVALID_PARAMS);
return thiz->insert(thiz, index, data);
}
static inline Ret linear_container_prepend(LinearContainer* thiz, void* data)
{
return_val_if_fail(thiz != NULL && thiz->prepend != NULL, RET_INVALID_PARAMS);
return thiz->prepend(thiz, data);
}
static inline Ret linear_container_append(LinearContainer* thiz, void* data)
{
return_val_if_fail(thiz != NULL && thiz->append != NULL, RET_INVALID_PARAMS);
return thiz->append(thiz, data);
}
static inline Ret linear_container_delete(LinearContainer* thiz, size_t index)
{
return_val_if_fail(thiz != NULL && thiz->del != NULL, RET_INVALID_PARAMS);
return thiz->del(thiz, index);
}
static inline Ret linear_container_get_by_index(LinearContainer* thiz, size_t index, void** data)
{
return_val_if_fail(thiz != NULL && thiz->get_by_index != NULL, RET_INVALID_PARAMS);
return thiz->get_by_index(thiz, index, data);
}
static inline Ret linear_container_set_by_index(LinearContainer* thiz, size_t index, void* data)
{
return_val_if_fail(thiz != NULL && thiz->set_by_index != NULL, RET_INVALID_PARAMS);
return thiz->set_by_index(thiz, index, data);
}
static inline size_t linear_container_length(LinearContainer* thiz)
{
return_val_if_fail(thiz != NULL && thiz->length != NULL, 0);
return thiz->length(thiz);
}
static inline int linear_container_find(LinearContainer* thiz, DataCompareFunc cmp, void* ctx)
{
return_val_if_fail(thiz != NULL && thiz->find != NULL, -1);
return thiz->find(thiz, cmp, ctx);
}
static inline Ret linear_container_foreach(LinearContainer* thiz, DataVisitFunc visit, void* ctx)
{
return_val_if_fail(thiz != NULL && thiz->foreach != NULL, RET_INVALID_PARAMS);
return thiz->foreach(thiz, visit, ctx);
}
static inline void linear_container_destroy(LinearContainer* thiz)
{
return_if_fail(thiz!= NULL && thiz->destroy != NULL);
return thiz->destroy(thiz);
}
DECLS_END
#endif/*LINEAR_CONTAINER_H*/
/*
* File: linear_container_dlist.h
*/
#ifndef LINEAR_CONTAINER_DLIST_H
#define LINEAR_CONTAINER_DLIST_H
#include "linear_container.h"
DECLS_BEGIN
LinearContainer* linear_container_dlist_create(DataDestroyFunc data_destroy, void* ctx);
DECLS_END
#endif/*LINEAR_CONTAINER_DLIST_H*/
/*
* File: linear_container_dlist.c
*/
#include "dlist.h"
#include "linear_container.h"
typedef struct _PrivInfo
{
DList* dlist;
}PrivInfo;
static Ret linear_container_dlist_insert(LinearContainer* thiz, size_t index, void* data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return dlist_insert(priv->dlist, index, data);
}
static Ret linear_container_dlist_prepend(LinearContainer* thiz, void* data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return dlist_prepend(priv->dlist, data);
}
static Ret linear_container_dlist_append(LinearContainer* thiz, void* data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return dlist_append(priv->dlist, data);
}
static Ret linear_container_dlist_delete(LinearContainer* thiz, size_t index)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return dlist_delete(priv->dlist, index);
}
static Ret linear_container_dlist_get_by_index(LinearContainer* thiz, size_t index, void** data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return dlist_get_by_index(priv->dlist, index, data);
}
static Ret linear_container_dlist_set_by_index(LinearContainer* thiz, size_t index, void* data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return dlist_set_by_index(priv->dlist, index, data);
}
static size_t linear_container_dlist_length(LinearContainer* thiz)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return dlist_length(priv->dlist);
}
static int linear_container_dlist_find(LinearContainer* thiz, DataCompareFunc cmp, void* ctx)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return dlist_find(priv->dlist, cmp, ctx);
}
static Ret linear_container_dlist_foreach(LinearContainer* thiz, DataVisitFunc visit, void* ctx)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return dlist_foreach(priv->dlist, visit, ctx);
}
static void linear_container_dlist_destroy(LinearContainer* thiz)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
dlist_destroy(priv->dlist);
free(thiz);
return;
}
LinearContainer* linear_container_dlist_create(DataDestroyFunc data_destroy, void* ctx)
{
LinearContainer* thiz = (LinearContainer*)malloc(sizeof(LinearContainer) + sizeof(PrivInfo));
if(thiz != NULL) {
PrivInfo* priv = (PrivInfo*)thiz->priv;
priv->dlist = dlist_create(data_destroy, ctx);
thiz->insert = linear_container_dlist_insert;
thiz->prepend = linear_container_dlist_prepend;
thiz->append = linear_container_dlist_append;
thiz->del = linear_container_dlist_delete;
thiz->get_by_index = linear_container_dlist_get_by_index;
thiz->set_by_index = linear_container_dlist_set_by_index;
thiz->length = linear_container_dlist_length;
thiz->find = linear_container_dlist_find;
thiz->foreach = linear_container_dlist_foreach;
thiz->destroy = linear_container_dlist_destroy;
if(priv->dlist == NULL) {
free(thiz);
thiz = NULL;
}
}
return thiz;
}
5) queue¶
/*
* File: queue.h
*/
#include <stdio.h>
#include "typedef.h"
#include "linear_container.h"
#ifndef QUEUE_H
#define QUEUE_H
DECLS_BEGIN
struct _Queue;
typedef struct _Queue Queue;
Queue* queue_create(LinearContainer* container);
Ret queue_head(Queue* thiz, void** data);
Ret queue_push(Queue* thiz, void* data);
Ret queue_pop(Queue* thiz);
size_t queue_length(Queue* thiz);
Ret queue_foreach(Queue* thiz, DataVisitFunc visit, void* ctx);
void queue_destroy(Queue* thiz);
DECLS_END
#endif/*QUEUE_H*/
/*
* File: queue.c
*/
#include "queue.h"
#include "linear_container.h"
struct _Queue
{
LinearContainer* linear_container;
};
Queue* queue_create(LinearContainer* container)
{
Queue* thiz = NULL;
return_val_if_fail(container != NULL, NULL);
thiz = (Queue*)malloc(sizeof(Queue));
if(thiz != NULL) {
thiz->linear_container = container;
}
return thiz;
}
Ret queue_head(Queue* thiz, void** data)
{
return_val_if_fail(thiz != NULL && data != NULL, RET_INVALID_PARAMS);
return linear_container_get_by_index(thiz->linear_container, 0, data);
}
Ret queue_push(Queue* thiz, void* data)
{
return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);
return linear_container_append(thiz->linear_container, data);
}
Ret queue_pop(Queue* thiz)
{
return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);
return linear_container_delete(thiz->linear_container, 0);
}
size_t queue_length(Queue* thiz)
{
return_val_if_fail(thiz != NULL, 0);
return linear_container_length(thiz->linear_container);
}
Ret queue_foreach(Queue* thiz, DataVisitFunc visit, void* ctx)
{
return_val_if_fail(thiz != NULL && visit != NULL, RET_INVALID_PARAMS);
return linear_container_foreach(thiz->linear_container, visit, ctx);
}
void queue_destroy(Queue* thiz)
{
if(thiz != NULL) {
linear_container_destroy(thiz->linear_container);
thiz->linear_container = NULL;
free(thiz);
}
return;
}
#ifdef QUEUE_TEST
#include "test_helper.c"
#include "linear_container_dlist.h"
int main(int argc, char* argv[])
{
int i = 0;
int n = 1000;
int ret_data = 0;
Queue* queue = queue_create(linear_container_dlist_create(NULL, NULL));
for(i = 0; i < n; i++) {
assert(queue_push(queue, (void*)i) == RET_OK);
assert(queue_head(queue, (void**)&ret_data) == RET_OK);
assert(queue_length(queue) == (i+1));
}
queue_foreach(queue, print_int, NULL);
for(i = 0; i < n; i++) {
assert(queue_head(queue, (void**)&ret_data) == RET_OK);
assert(ret_data == i );
assert(queue_length(queue) == (n - i));
assert(queue_pop(queue) == RET_OK);
}
queue_destroy(queue);
return 0;
}
#endif/*QUEUE_TEST*/
gcc -Wall -Wno-unused-function -g -m32 -DQUEUE_TEST dlist.c linear_container_dlist.c queue.c -o queue_test
6) linear_container_darray¶
/*
* File: linear_container_darray.h
*/
#ifndef LINEAR_CONTAINER_DARRAY_H
#define LINEAR_CONTAINER_DARRAY_H
#include "linear_container.h"
DECLS_BEGIN
LinearContainer* linear_container_darray_create(DataDestroyFunc data_destroy, void* ctx);
DECLS_END
#endif/*LINEAR_CONTAINER_DARRAY_H*/
/*
* File: linear_container_darray.c
*/
#include "darray.h"
#include "linear_container.h"
typedef struct _PrivInfo
{
DArray* darray;
}PrivInfo;
static Ret linear_container_darray_insert(LinearContainer* thiz, size_t index, void* data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return darray_insert(priv->darray, index, data);
}
static Ret linear_container_darray_prepend(LinearContainer* thiz, void* data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return darray_prepend(priv->darray, data);
}
static Ret linear_container_darray_append(LinearContainer* thiz, void* data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return darray_append(priv->darray, data);
}
static Ret linear_container_darray_delete(LinearContainer* thiz, size_t index)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return darray_delete(priv->darray, index);
}
static Ret linear_container_darray_get_by_index(LinearContainer* thiz, size_t index, void** data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return darray_get_by_index(priv->darray, index, data);
}
static Ret linear_container_darray_set_by_index(LinearContainer* thiz, size_t index, void* data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return darray_set_by_index(priv->darray, index, data);
}
static size_t linear_container_darray_length(LinearContainer* thiz)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return darray_length(priv->darray);
}
static int linear_container_darray_find(LinearContainer* thiz, DataCompareFunc cmp, void* ctx)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return darray_find(priv->darray, cmp, ctx);
}
static Ret linear_container_darray_foreach(LinearContainer* thiz, DataVisitFunc visit, void* ctx)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return darray_foreach(priv->darray, visit, ctx);
}
static void linear_container_darray_destroy(LinearContainer* thiz)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
darray_destroy(priv->darray);
free(thiz);
return;
}
LinearContainer* linear_container_darray_create(DataDestroyFunc data_destroy, void* ctx)
{
LinearContainer* thiz = (LinearContainer*)malloc(sizeof(LinearContainer) + sizeof(PrivInfo));
if(thiz != NULL)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
priv->darray = darray_create(data_destroy, ctx);
thiz->insert = linear_container_darray_insert;
thiz->prepend = linear_container_darray_prepend;
thiz->append = linear_container_darray_append;
thiz->del = linear_container_darray_delete;
thiz->get_by_index = linear_container_darray_get_by_index;
thiz->set_by_index = linear_container_darray_set_by_index;
thiz->length = linear_container_darray_length;
thiz->find = linear_container_darray_find;
thiz->foreach = linear_container_darray_foreach;
thiz->destroy = linear_container_darray_destroy;
}
return thiz;
}
/*
* linear_container_test.c
*/
#include <assert.h>
#include "linear_container.h"
#include "test_helper.c"
#include "linear_container_dlist.h"
#include "linear_container_darray.h"
static void test_int_linear_container(LinearContainer* linear_container)
{
int i = 0;
int n = 100;
int data = 0;
for(i = 0; i < n; i++)
{
assert(linear_container_append(linear_container, (void*)i) == RET_OK);
assert(linear_container_length(linear_container) == (i + 1));
assert(linear_container_get_by_index(linear_container, i, (void**)&data) == RET_OK);
assert(data == i);
assert(linear_container_set_by_index(linear_container, i, (void*)(2*i)) == RET_OK);
assert(linear_container_get_by_index(linear_container, i, (void**)&data) == RET_OK);
assert(data == 2*i);
assert(linear_container_set_by_index(linear_container, i, (void*)i) == RET_OK);
assert(linear_container_find(linear_container, cmp_int, (void*)i) == i);
}
for(i = 0; i < n; i++)
{
assert(linear_container_get_by_index(linear_container, 0, (void**)&data) == RET_OK);
assert(data == (i));
assert(linear_container_length(linear_container) == (n-i));
assert(linear_container_delete(linear_container, 0) == RET_OK);
assert(linear_container_length(linear_container) == (n-i-1));
if((i + 1) < n)
{
assert(linear_container_get_by_index(linear_container, 0, (void**)&data) == RET_OK);
assert((int)data == (i+1));
}
}
assert(linear_container_length(linear_container) == 0);
for(i = 0; i < n; i++)
{
assert(linear_container_prepend(linear_container, (void*)i) == RET_OK);
assert(linear_container_length(linear_container) == (i + 1));
assert(linear_container_get_by_index(linear_container, 0, (void**)&data) == RET_OK);
assert(data == i);
assert(linear_container_set_by_index(linear_container, 0, (void*)(2*i)) == RET_OK);
assert(linear_container_get_by_index(linear_container, 0, (void**)&data) == RET_OK);
assert(data == 2*i);
assert(linear_container_set_by_index(linear_container, 0, (void*)i) == RET_OK);
}
i = n - 1;
assert(linear_container_foreach(linear_container, check_and_dec_int, &i) == RET_OK);
linear_container_destroy(linear_container);
return;
}
static void test_invalid_params(void)
{
printf("===========Warning is normal begin==============\n");
assert(linear_container_length(NULL) == 0);
assert(linear_container_prepend(NULL, 0) == RET_INVALID_PARAMS);
assert(linear_container_append(NULL, 0) == RET_INVALID_PARAMS);
assert(linear_container_delete(NULL, 0) == RET_INVALID_PARAMS);
assert(linear_container_insert(NULL, 0, 0) == RET_INVALID_PARAMS);
assert(linear_container_set_by_index(NULL, 0, 0) == RET_INVALID_PARAMS);
assert(linear_container_get_by_index(NULL, 0, NULL) == RET_INVALID_PARAMS);
assert(linear_container_find(NULL, NULL, NULL) < 0);
assert(linear_container_foreach(NULL, NULL, NULL) == RET_INVALID_PARAMS);
printf("===========Warning is normal end==============\n");
return;
}
static void single_thread_test(void)
{
LinearContainer* linear_container = linear_container_darray_create(NULL, NULL);
test_int_linear_container(linear_container);
linear_container = linear_container_dlist_create(NULL, NULL);
test_int_linear_container(linear_container);
test_invalid_params();
return;
}
int main(int argc, char* argv[])
{
single_thread_test();
return 0;
}
all:
# -Wno-unused-function 发现不使用的函数不警告
# darray_test
gcc -Wall -Wno-unused-function -g -m32 -DDARRAY_TEST darray.c -o darray_test
# dlist_test
gcc -Wall -Wno-unused-function -g -m32 -DDLIST_TEST dlist.c -o dlist_test
# queue_test
gcc -Wall -Wno-unused-function -g -m32 -DQUEUE_TEST dlist.c linear_container_dlist.c queue.c -o queue_test
# container_test
gcc -Wall -Wno-unused-function -g -m32 -shared darray.c dlist.c linear_container_darray.c linear_container_dlist.c queue.c -o libcontainer.so
gcc -Wall -Wno-unused-function -g -m32 linear_container_test.c -L./ -lcontainer -o container_test
clean:
rm *test *.so
6.2 迭代器¶
/*
* File : invert_ng.c
*/
#include "linear_container.h"
Ret invert(LinearContainer* linear_container)
{
int i = 0;
int j = 0;
void* data1 = NULL;
void* data2 = NULL;
return_val_if_fail(linear_container != NULL, RET_INVALID_PARAMS);
j = linear_container_length(linear_container) - 1;
for(; i < j; i++, j--)
{
linear_container_get_by_index(linear_container, i, &data1);
linear_container_get_by_index(linear_container, j, &data2);
linear_container_set_by_index(linear_container, i, data2);
linear_container_set_by_index(linear_container, j, data1);
}
return RET_OK;
}
#ifdef INVERT_TEST
#include "test_helper.c"
#include "linear_container_dlist.h"
int main(int argc, char* argv[])
{
int i = 0;
int n = 101;
LinearContainer* linear_container = linear_container_dlist_create(NULL, NULL);
for(i = 0; i < n; i++)
{
linear_container_append(linear_container, (void*)i);
}
invert(linear_container);
i--;
linear_container_foreach(linear_container, check_and_dec_int, &i);
linear_container_destroy(linear_container);
return 0;
}
#endif/*INVERT_TEST*/
#ifndef ITERATOR_H
#define ITERATOR_H
#include "typedef.h"
DECLS_BEGIN
struct _Iterator;
typedef struct _Iterator Iterator;
typedef Ret (*IteratorSetFunc)(Iterator* thiz, void* data);
typedef Ret (*IteratorGetFunc)(Iterator* thiz, void** data);
typedef Ret (*IteratorNextFunc)(Iterator* thiz);
typedef Ret (*IteratorPrevFunc)(Iterator* thiz);
typedef Ret (*IteratorAdvanceFunc)(Iterator* thiz, int offset);
typedef int (*IteratorOffsetFunc)(Iterator* thiz);
typedef Ret (*IteratorCloneFunc)(Iterator* thiz, Iterator** cloned);
typedef void (*IteratorDestroyFunc)(Iterator* thiz);
struct _Iterator
{
IteratorSetFunc set;
IteratorGetFunc get;
IteratorNextFunc next;
IteratorPrevFunc prev;
IteratorAdvanceFunc advance;
IteratorCloneFunc clone;
IteratorOffsetFunc offset;
IteratorDestroyFunc destroy;
char priv[0];
};
static inline Ret iterator_set(Iterator* thiz, void* data)
{
return_val_if_fail(thiz != NULL && thiz->set != NULL, RET_INVALID_PARAMS);
return thiz->set(thiz, data);
}
static inline Ret iterator_get(Iterator* thiz, void** data)
{
return_val_if_fail(thiz != NULL && thiz->get != NULL, RET_INVALID_PARAMS);
return thiz->get(thiz, data);
}
static inline Ret iterator_next(Iterator* thiz)
{
return_val_if_fail(thiz != NULL && thiz->next != NULL, RET_INVALID_PARAMS);
return thiz->next(thiz);
}
static inline Ret iterator_prev(Iterator* thiz)
{
return_val_if_fail(thiz != NULL && thiz->prev != NULL, RET_INVALID_PARAMS);
return thiz->prev(thiz);
}
static inline Ret iterator_advance(Iterator* thiz, int offset)
{
return_val_if_fail(thiz != NULL && thiz->advance != NULL, RET_INVALID_PARAMS);
return thiz->advance(thiz, offset);
}
static inline int iterator_offset(Iterator* thiz)
{
return_val_if_fail(thiz != NULL && thiz->offset != NULL, -1);
return thiz->offset(thiz);
}
static inline Ret iterator_clone(Iterator* thiz, Iterator** cloned)
{
return_val_if_fail(thiz != NULL && thiz->clone != NULL, RET_INVALID_PARAMS);
return thiz->clone(thiz, cloned);
}
static inline void iterator_destroy(Iterator* thiz)
{
return_if_fail(thiz != NULL && thiz->destroy != NULL);
return thiz->destroy(thiz);
}
DECLS_END
#endif/*ITERATOR_H*/
/*
* File : dlist_iterator.h
*/
#ifndef DLIST_ITERATOR_H
#define DLIST_ITERATOR_H
#include "dlist.h"
#include "iterator.h"
DECLS_BEGIN
Iterator* dlist_iterator_create(DList* dlist);
DECLS_END
#endif/*DLIST_ITERATOR_H*/
/*
* File : dlist_iterator.c
*/
#include <string.h>
#include "dlist_iterator.h"
typedef struct _PrivInfo
{
DList* dlist;
DListNode* cursor;
int offset;
}PrivInfo;
static Ret dlist_iterator_set(Iterator* thiz, void* data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->cursor != NULL && priv->dlist != NULL, RET_INVALID_PARAMS);
priv->cursor->data = data;
return RET_OK;
}
static Ret dlist_iterator_get(Iterator* thiz, void** data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->cursor != NULL && priv->dlist != NULL && data != NULL, RET_INVALID_PARAMS);
*data = priv->cursor->data;
return RET_OK;
}
static Ret dlist_iterator_next(Iterator* thiz)
{
Ret ret = RET_FAIL;
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->cursor != NULL && priv->dlist != NULL, RET_INVALID_PARAMS);
if(priv->cursor->next != NULL)
{
priv->cursor = priv->cursor->next;
priv->offset++;
ret = RET_OK;
}
return ret;
}
static Ret dlist_iterator_prev(Iterator* thiz)
{
Ret ret = RET_FAIL;
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->cursor != NULL && priv->dlist != NULL, RET_INVALID_PARAMS);
if(priv->cursor->prev != NULL)
{
priv->cursor = priv->cursor->prev;
priv->offset--;
ret = RET_OK;
}
return RET_OK;
}
static Ret dlist_iterator_advance(Iterator* thiz, int offset)
{
int n = offset;
Ret ret = RET_FAIL;
DListNode* iter = NULL;
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->cursor != NULL && priv->dlist != NULL, RET_INVALID_PARAMS);
iter = priv->cursor;
if(offset > 0)
{
for(n = offset; n > 0 && iter != NULL; n--)
{
iter = iter->next;
}
}
else
{
for(n = -offset; n > 0 && iter != NULL; n--)
{
iter = iter->prev;
}
}
if(iter != NULL)
{
priv->cursor = iter;
priv->offset += offset;
ret = RET_OK;
}
return ret;
}
static int dlist_iterator_offset(Iterator* thiz)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->cursor != NULL && priv->dlist != NULL, RET_INVALID_PARAMS);
return priv->offset;
}
static Ret dlist_iterator_clone(Iterator* thiz, Iterator** cloned)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->cursor != NULL && priv->dlist != NULL, RET_INVALID_PARAMS);
*cloned = (Iterator*)malloc(sizeof(Iterator) + sizeof(PrivInfo));
if(*cloned != NULL)
{
memcpy(*cloned, thiz, sizeof(Iterator) + sizeof(PrivInfo));
}
return *cloned != NULL ? RET_OK : RET_FAIL;
}
static void dlist_iterator_destroy(Iterator* thiz)
{
if(thiz != NULL)
{
free(thiz);
}
return;
}
Iterator* dlist_iterator_create(DList* dlist)
{
Iterator* thiz = NULL;
return_val_if_fail(dlist != NULL, NULL);
if((thiz = malloc(sizeof(Iterator) + sizeof(PrivInfo))) != NULL)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
thiz->set = dlist_iterator_set;
thiz->get = dlist_iterator_get;
thiz->next = dlist_iterator_next;
thiz->prev = dlist_iterator_prev;
thiz->advance = dlist_iterator_advance;
thiz->clone = dlist_iterator_clone;
thiz->offset = dlist_iterator_offset;
thiz->destroy = dlist_iterator_destroy;
priv->dlist = dlist;
priv->cursor = dlist->first;
priv->offset = 0;
}
return thiz;
}
/*
* File : darray_iterator.h
*/
#ifndef DARRAY_ITERATOR_H
#define DARRAY_ITERATOR_H
#include "darray.h"
#include "iterator.h"
DECLS_BEGIN
Iterator* darray_iterator_create(DArray* darray);
DECLS_END
#endif/*DARRAY_ITERATOR_H*/
/*
* File : darray_iterator.c
*/
#include <string.h>
#include "darray_iterator.h"
typedef struct _PrivInfo
{
DArray* darray;
int offset;
}PrivInfo;
static Ret darray_iterator_set(Iterator* thiz, void* data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->darray != NULL, RET_INVALID_PARAMS);
return darray_set_by_index(priv->darray, priv->offset, data);
}
static Ret darray_iterator_get(Iterator* thiz, void** data)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->darray != NULL && data != NULL, RET_INVALID_PARAMS);
return darray_get_by_index(priv->darray, priv->offset, data);
}
static Ret darray_iterator_next(Iterator* thiz)
{
Ret ret = RET_FAIL;
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->darray != NULL, RET_INVALID_PARAMS);
if((priv->offset + 1) < priv->darray->size)
{
priv->offset++;
ret = RET_OK;
}
return ret;
}
static Ret darray_iterator_prev(Iterator* thiz)
{
Ret ret = RET_FAIL;
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->darray != NULL, RET_INVALID_PARAMS);
if(priv->offset > 0)
{
priv->offset--;
ret = RET_OK;
}
return RET_OK;
}
static Ret darray_iterator_advance(Iterator* thiz, int offset)
{
int new_offset = 0;
Ret ret = RET_FAIL;
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->darray != NULL, RET_INVALID_PARAMS);
new_offset = priv->offset + offset;
if(new_offset >= 0 && new_offset < priv->darray->size)
{
priv->offset = new_offset;
}
return ret;
}
static int darray_iterator_offset(Iterator* thiz)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->darray != NULL, RET_INVALID_PARAMS);
return priv->offset;
}
static Ret darray_iterator_clone(Iterator* thiz, Iterator** cloned)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
return_val_if_fail(priv->darray != NULL, RET_INVALID_PARAMS);
*cloned = (Iterator*)malloc(sizeof(Iterator) + sizeof(PrivInfo));
if(*cloned != NULL)
{
memcpy(*cloned, thiz, sizeof(Iterator) + sizeof(PrivInfo));
}
return *cloned != NULL ? RET_OK : RET_FAIL;
}
static void darray_iterator_destroy(Iterator* thiz)
{
if(thiz != NULL)
{
free(thiz);
}
return;
}
Iterator* darray_iterator_create(DArray* darray)
{
Iterator* thiz = NULL;
return_val_if_fail(darray != NULL, NULL);
if((thiz = malloc(sizeof(Iterator) + sizeof(PrivInfo))) != NULL)
{
PrivInfo* priv = (PrivInfo*)thiz->priv;
thiz->set = darray_iterator_set;
thiz->get = darray_iterator_get;
thiz->next = darray_iterator_next;
thiz->prev = darray_iterator_prev;
thiz->advance = darray_iterator_advance;
thiz->clone = darray_iterator_clone;
thiz->offset = darray_iterator_offset;
thiz->destroy = darray_iterator_destroy;
priv->darray = darray;
priv->offset = 0;
}
return thiz;
}
/*
* File : invert.c
*/
#include "iterator.h"
Ret invert(Iterator* forward, Iterator* backward)
{
void* data1 = NULL;
void* data2 = NULL;
return_val_if_fail(forward != NULL && backward != NULL, RET_INVALID_PARAMS);
for(; iterator_offset(forward) < iterator_offset(backward); iterator_next(forward), iterator_prev(backward))
{
iterator_get(forward, &data1);
iterator_get(backward, &data2);
iterator_set(forward, data2);
iterator_set(backward, data1);
}
return RET_OK;
}
#ifdef INVERT_TEST
#include "dlist.h"
#include "dlist_iterator.h"
#include "test_helper.c"
int main(int argc, char* argv[])
{
int i = 0;
int n = 101;
int last = n - 1;
DList* dlist = dlist_create(NULL, NULL);
for(i = 0; i < n; i++)
{
dlist_append(dlist, (void*)i);
}
Iterator* forward = dlist_iterator_create(dlist);
Iterator* backward = dlist_iterator_create(dlist);
iterator_advance(backward, last);
invert(forward, backward);
dlist_foreach(dlist, check_and_dec_int, &last);
iterator_destroy(forward);
iterator_destroy(backward);
dlist_destroy(dlist);
return 0;
}
#endif/*INVERT_TEST*/
all:
gcc -Wall -m32 -g -DDARRAY_TEST darray.c -o darray_test
gcc -Wall -m32 -g -DDLIST_TEST dlist.c -o dlist_test
gcc -Wall -m32 -g -shared darray.c dlist.c linear_container_darray.c linear_container_dlist.c -o libcontainer.so
gcc -Wall -m32 -g linear_container_test.c -L./ -lcontainer -o container_test
gcc -Wall -m32 -g invert_ng.c -DINVERT_TEST -L./ -lcontainer -o invert_ng_test
gcc -Wall -m32 -g invert.c -DINVERT_TEST -L./ -lcontainer -o invert_test
clean:
rm *test *.so
6.3 动态绑定¶
/*
* File : call_cos.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main(int argc, char **argv)
{
void *handle = NULL;
double (*cosine)(double) = NULL;
/*加载共享库*/
handle = dlopen("libm.so", RTLD_LAZY);
/*通过函数名找到函数指针*/
*(void **) (&cosine) = dlsym(handle, "cos");
/*调用函数*/
printf("%f\n", (*cosine)(2.0));
/*卸载共享库*/
dlclose(handle);
return 0;
}
/*
* File: module.h
*/
#ifndef MODULE_H
#define MODULE_H
#include "typedef.h"
DECLS_BEGIN
struct _Module;
typedef struct _Module Module;
typedef enum _ModuleFlags
{
MODULE_FLAGS_NONE,
MODULE_FLAGS_DELAY = 1
}ModuleFlags;
Module* module_create(const char* file_name, ModuleFlags flags);
void* module_sym(Module* thiz, const char* func_name);
void module_destroy(Module* thiz);
DECLS_END
#endif/*MODULE_H*/
/*
* File: module_linux.h
*/
#include <dlfcn.h>
#include "module.h"
struct _Module
{
void* handle;
};
Module* module_create(const char* file_name, ModuleFlags flags)
{
Module* thiz = NULL;
return_val_if_fail(file_name != NULL, NULL);
if((thiz = malloc(sizeof(Module))) != NULL)
{
thiz->handle = dlopen(file_name, flags & MODULE_FLAGS_DELAY ? RTLD_LAZY : RTLD_NOW);
if(thiz->handle == NULL)
{
free(thiz);
thiz = NULL;
printf("%s\n", dlerror());
}
}
return thiz;
}
void* module_sym(Module* thiz, const char* func_name)
{
return_val_if_fail(thiz != NULL && thiz->handle != NULL && func_name != NULL, NULL);
dlerror();
return dlsym(thiz->handle, func_name);
}
void module_destroy(Module* thiz)
{
if(thiz != NULL)
{
if(thiz->handle != NULL)
{
dlclose(thiz->handle);
}
free(thiz);
}
return;
}
/*
* File : module_test.c
*/
#include <stdio.h>
#include "module.h"
int main(int argc, char* argv[])
{
if(argc != 3) {
printf("%s module function\n", argv[0]);
return 0;
}
Module* module = module_create(argv[1], 0);
if(module != NULL) {
void* func = module_sym(module, argv[2]);
printf("func=%p\n", func);
module_destroy(module);
} else {
printf("load %s failed\n", argv[1]);
}
return 0;
}
all:
gcc -Wall -m32 -g -DDARRAY_TEST darray.c -o darray_test
gcc -Wall -m32 -g -DDLIST_TEST dlist.c -o dlist_test
gcc -Wall -m32 -g -shared darray.c dlist.c linear_container_darray.c linear_container_dlist.c queue.c -o libcontainer.so
gcc -Wall -m32 -g linear_container_test.c -L./ -lcontainer -o container_test
gcc -Wall -m32 -g queue.c linear_container_dlist.c dlist.c -DQUEUE_TEST -o queue_test
gcc -Wall -m32 -g module_linux.c module_test.c -ldl -o module_test
gcc -Wall -m32 -g module_linux.c queue.c queue_test.c -ldl -o queue_dynamic_test
gcc -m32 -g call_cos.c -ldl -o call_cos
clean:
rm *test *.so call_cos