转自:http://www.cnblogs.com/sniperHW/archive/2012/04/02/2429607.html

近来考虑将项目基础框架的开发语言从C++换成C,免不了要编写一大堆的基础工具。

本篇为第一篇,list,提供的接口和操作方式与std::list相似.后续将会陆续贴出map,vector,memory pool,

hash_table等工具。

list.h

#ifndef _LIST_H
#define _LIST_H struct list;
struct node;
struct fix_obj_pool; struct list_iter
{
struct node **next;
struct node *n;
}; struct fix_obj_pool *list_create_obj_pool(unsigned int val_size,int default_size,int align4); struct list* list_create(unsigned int val_size,struct fix_obj_pool*);
void list_destroy(struct list**); struct list_iter list_begin(struct list*);
struct list_iter list_end(struct list*);
struct list_iter list_rbegin(struct list*);
struct list_iter list_rend(struct list*); unsigned int list_size(struct list*);
void list_insert_before(struct list*,struct list_iter,void*);
void list_insert_after(struct list*,struct list_iter,void*);
void list_push_back(struct list*,void*);
void list_push_front(struct list*,void*);
void list_pop_back(struct list*,void*);
void list_pop_front(struct list*,void*);
int list_is_empty(struct list*); #ifndef LIST_INSERT_BEFORE
#define LIST_INSERT_BEFORE(TYPE,LIST,IT,VAL)\
{TYPE val = VAL;list_insert_before(LIST,IT,&val);}
#endif #ifndef LIST_INSERT_AFTER
#define LIST_INSERT_AFTER(TYPE,LIST,IT,VAL)\
{TYPE val = VAL;list_insert_after(LIST,IT,&val);}
#endif #ifndef LIST_PUSH_BACK
#define LIST_PUSH_BACK(TYPE,LIST,VAL)\
{TYPE val = VAL;list_push_back(LIST,&val);}
#endif #ifndef LIST_PUSH_FRONT
#define LIST_PUSH_FRONT(TYPE,LIST,VAL)\
{TYPE val = VAL;list_push_front(LIST,&val);}
#endif #ifndef LIST_POP_FRONT
#define LIST_POP_FRONT(TYPE,LIST)\
({ TYPE __result;\
do list_pop_front(LIST,&__result);\
while(0);\
__result;})
#endif #ifndef LIST_POP_BACK
#define LIST_POP_BACK(TYPE,LIST)\
({ TYPE __result;\
do list_pop_back(LIST,&__result);\
while(0);\
__result;})
#endif struct list_iter list_find(struct list*,void*); #ifndef LIST_FIND
#define LIST_FIND(TYPE,L,VAL)\
({ TYPE val = VAL;struct list_iter it;\
do it = list_find(L,&val);\
while(0);\
it;})
#endif int list_remove(struct list*,void*); #ifndef LIST_REMOVE
#define LIST_REMOVE(TYPE,L,VAL)\
({ TYPE val = VAL;int ret;\
do ret = list_remove(L,&val);\
while(0);\
ret;})
#endif struct list_iter list_erase(struct list*,struct list_iter); struct list_iter iter_next(struct list_iter);
void *iter_get_val(struct list_iter,void*);
void iter_set_val(struct list_iter,void*);
int iter_is_equal(struct list_iter a,struct list_iter b); #ifndef ITER_GET_VAL
#define ITER_GET_VAL(TYPE,NODE)\
({ TYPE __result;\
do iter_get_val(NODE,&__result);\
while(0);\
__result;})
#endif #ifndef ITER_SET_VAL
#define ITER_SET_VAL(TYPE,NODE,VAL)\
{TYPE val=VAL;iter_set_val(NODE,&val);}
#endif #endif

list.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "list.h"
#include "../mem/fix_obj_pool/fix_obj_pool.h"
struct node
{
struct node *next;
struct node *pre;
unsigned int val_size;
union{
char value[1];
unsigned int pad;
};
}; struct list
{
unsigned int size;
struct node head;
struct node end;
struct fix_obj_pool *obj_pool;//产生node使用的内存池
}; struct fix_obj_pool *list_create_obj_pool(unsigned int val_size,int default_size,int align4)
{
struct node dummmy;
unsigned int node_size = sizeof(dummmy) + val_size - sizeof(dummmy.pad);
struct fix_obj_pool *pool = create_pool(node_size,default_size,align4);
return pool;
} struct list* list_create(unsigned int val_size,struct fix_obj_pool *obj_pool)
{
struct list *_list = malloc(sizeof(*_list));
if(_list)
{
_list->size = 0;
_list->head.val_size = _list->end.val_size = val_size;
_list->head.next = &_list->end;
_list->end.pre = &_list->head;
_list->head.pre = _list->end.next = 0;
_list->obj_pool = obj_pool;
}
return _list;
} void list_destroy(struct list **_list)
{
assert(_list);
assert(*_list);
if((*_list)->size > 0)
{
struct node *cur = (*_list)->head.next;
while(cur != &(*_list)->end)
{
struct node *next = cur->next;
if((*_list)->obj_pool)
pool_dealloc((*_list)->obj_pool,cur);
else
free(cur);
cur = next;
}
}
free(*_list);
*_list = 0;
} inline struct list_iter list_begin(struct list *_list)
{
assert(_list);
struct list_iter it;
it.n = _list->head.next;
it.next = &(it.n->next);
return it;
} inline struct list_iter list_end(struct list *_list)
{
assert(_list);
struct list_iter it;
it.n = &_list->end;
it.next = 0;
return it;
} inline struct list_iter list_rbegin(struct list *_list)
{
assert(_list);
struct list_iter it;
it.n = _list->end.pre;
it.next = &(it.n->pre);
return it;
} inline struct list_iter list_rend(struct list *_list)
{
assert(_list);
struct list_iter it;
it.n = &_list->head;
it.next = 0;
return it;
} inline unsigned int list_size(struct list *_list)
{
assert(_list);
return _list->size;
} void list_insert_after(struct list *l,struct list_iter it,void *val)
{
assert(l);
struct node *new_node;
if(l->obj_pool)
new_node = pool_alloc(l->obj_pool);
else
new_node = malloc(sizeof(*new_node) + l->head.val_size - sizeof(new_node->pad));
if(new_node)
{
new_node->val_size = l->head.val_size;
memcpy(new_node->value,val,l->head.val_size);
struct node *n = it.n;
struct node *N = n->next;
n->next = N->pre = new_node;
new_node->next = N;
new_node->pre = n;
++l->size;
}
} void list_insert_before(struct list *l, struct list_iter it,void *val)
{
assert(l);
struct node *new_node;
if(l->obj_pool)
new_node = pool_alloc(l->obj_pool);
else
new_node = malloc(sizeof(*new_node) + l->head.val_size - sizeof(new_node->pad));
if(new_node)
{
new_node->val_size = l->head.val_size;
memcpy(new_node->value,val,l->head.val_size);
struct node *n = it.n;
struct node *P = n->pre;
n->pre = P->next = new_node;
new_node->next = n;
new_node->pre = P;
++l->size;
}
} void list_push_back(struct list *_list,void *val)
{
assert(_list);
struct list_iter end = list_end(_list);
list_insert_before(_list,end,val);
} void list_push_front(struct list *_list,void *val)
{
assert(_list);
struct list_iter begin = list_begin(_list);
list_insert_before(_list,begin,val);
} void list_pop_back(struct list *_list,void *out)
{
assert(_list);
if(_list->size > 0)
{
struct node *_node = _list->end.pre;
memcpy(out,_node->value,_node->val_size);
struct node *pre = _node->pre;
struct node *next = _node->next;
pre->next = next;
next->pre = pre;
if(_list->obj_pool)
pool_dealloc(_list->obj_pool,_node);
else
free(_node);
//free(_node);
--_list->size;
}
} void list_pop_front(struct list *_list,void *out)
{
assert(_list);
if(_list->size > 0)
{
struct node *_node = _list->head.next;
memcpy(out,_node->value,_node->val_size);
struct node *pre = _node->pre;
struct node *next = _node->next;
pre->next = next;
next->pre = pre;
if(_list->obj_pool)
pool_dealloc(_list->obj_pool,_node);
else
free(_node);
--_list->size;
}
} inline int list_is_empty(struct list *_list)
{
assert(_list);
return _list->size == 0;
} struct list_iter list_find(struct list *l,void *v)
{
assert(l);
struct list_iter it;
it.n = 0;
struct node *cur = l->head.next;
while(cur != &l->end)
{ if(memcmp(cur->value,v,l->head.val_size) == 0)
//找到目标
break;
cur = cur->next;
} if(cur != &l->end)
{
it.n = cur;
it.next = &cur->next;
}
else
{
it.n = &l->end;
it.next = 0;
}
return it;
} int list_remove(struct list *l,void *v)
{
assert(l);
struct list_iter it = list_find(l,v);
if(it.n == 0)
return 0;
list_erase(l,it);
return 1;
} struct list_iter list_erase(struct list *l,struct list_iter it)
{
assert(l);
struct list_iter it_next = iter_next(it);
struct node *n = it.n;
struct node *P = n->pre;
struct node *N = n->next;
P->next = N;
N->pre = P;
if(l->obj_pool)
pool_dealloc(l->obj_pool,n);
else
free(n);
--l->size;
return it_next;
} inline struct list_iter iter_next(struct list_iter it)
{
if(it.next == 0)
return it;
struct list_iter it_next;
it_next.n = (*it.next);
if(it.next == &it.n->next)
it_next.next = &(it_next.n->next);
else if(it.next == &it.n->pre)
it_next.next = &(it_next.n->pre);
else
{
assert(0);
}
return it_next;
} inline int iter_is_equal(struct list_iter a,struct list_iter b)
{
return a.n == b.n;
} void *iter_get_val(struct list_iter iter,void *v)
{
struct node *n = iter.n;
memcpy(v,n->value,n->val_size);
} void iter_set_val(struct list_iter iter,void *v)
{
struct node *n = iter.n;
memcpy(n->value,v,n->val_size);
}

test.c

#include <stdio.h>
#include "list.h"
#include "../mem/fix_obj_pool/fix_obj_pool.h" int main()
{
struct fix_obj_pool *obj_pool = list_create_obj_pool(sizeof(int),4096,0);
struct list *l = list_create(sizeof(int),obj_pool);
LIST_PUSH_BACK(int,l,1);
LIST_PUSH_BACK(int,l,2);
LIST_PUSH_BACK(int,l,3);
LIST_PUSH_BACK(int,l,4);
struct list_iter it = LIST_FIND(int,l,2);
LIST_INSERT_BEFORE(int,l,it,5);
LIST_INSERT_AFTER(int,l,it,6);
it = list_begin(l);
struct list_iter end = list_end(l); for( ; !iter_is_equal(it,end); )
{
if(ITER_GET_VAL(int,it) == 3)
it = list_erase(l,it);
else
it = iter_next(it);
} it = list_begin(l);
while(!iter_is_equal(it,end))
{
printf("%d\n",ITER_GET_VAL(int,it));
it = iter_next(it);
} printf("free size:%d\n",get_free_size(obj_pool)); list_destroy(&l);
printf("free size:%d\n",get_free_size(obj_pool));
destroy_pool(&obj_pool); return 0;
}

m2014_c:C 工具库1:list的更多相关文章

  1. 细说Java主流日志工具库

    概述 在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息. 在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子. 我们先来逐一了解一下主流日志工具. java.util ...

  2. JHChart 1.1.0 iOS图表工具库中文ReadMe

    JHChart(最新版本1.1.0) 好吧,的确当前的github上已经存有不少的iOS图表工具库,然而,当公司的项目需要图表时,几乎没有哪个第三方能够完全满足我的项目需求.无奈之下,本人不得不花费一 ...

  3. JHChart iOS图表工具库1.0.3新版本详解

    前言. 从2016年4月14日开始,本人着手开发了JHChart图表工具库.经过断断续续的开发,截止到现在,已经实现了折线图.柱状图.饼状图.环形图和表格样式的图表功能.为了方便使用,我已经将一个简单 ...

  4. [转]Android开源项目第二篇——工具库篇

    本文为那些不错的Android开源项目第二篇--开发工具库篇,主要介绍常用的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容.多 ...

  5. CSV.js – 用于 CSV 解析和编码的 JS 工具库

    逗号分隔值(CSV )文件用于以以纯文本的形式存储表格化数据(数字和文本). CSV 文件包含任意数量的记录,通过某种换行符分隔,每条记录由字段,其他一些字符或字符串分隔,最常用的是文字逗号或制表符. ...

  6. Lo-Dash – 替代 Underscore 的优秀 JS 工具库

    前端开发人员大都喜欢 Underscore,它的工具函数很实用,用法简单.这里给大家推荐另外一个功能更全面的 JavaScript 工具——Lo-Dash,帮助你更好的开发网站和 Web 应用程序. ...

  7. Java主流日志工具库

    在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息.在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子.我们先来逐一了解一下主流日志工具. 1.java.util.lo ...

  8. Android开源项目第二篇——工具库篇

    本文为那些不错的Android开源项目第二篇——开发工具库篇,**主要介绍常用的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容 ...

  9. javaScript常用工具库

    对应于百度前端技术学院2015年春季的课程2相关内容 https://github.com/baidu-ife/ife/tree/master/2015_spring/task/task0002 ht ...

  10. Android 绘图工具库AChartEngine

    From: http://www.oschina.net/p/achartengine AChartEngine是为android应用而设计的绘图工具库.目前该库的最新稳定版本是0.7,支持绘制以下类 ...

随机推荐

  1. HTTP管线化技术--ajax请求

    1.管线化技术——客户端可以发送多次请求到服务端,而不需要等待上一次请求得到响应的时候才能进行下一次请求.实现并行发送请求 2.ajax——实现网页异步刷新 问题:当用户进行多次ajax请求的时候,并 ...

  2. 详解php的安装模式---CGI,FASTCGI,php-fpm,mod_php,mod_cgi,mod_fcgid

    1. CGI CGI是通用网关接口,HTTP服务器使用这样的接口程序来和“其他程序”(比如PHP的解释器程序)通讯,这个“其他程序”可以使用任何计算机语言来编写,它通过CGI这个接口从HTTP服务器取 ...

  3. 判断是否是IE浏览器和是否是IE11

    判断是否是IE浏览器用下面这个函数, function isIE() { //ie? 是ie返回true,否则返回false if (!!window.ActiveXObject || "A ...

  4. Struts2源码阅读(一)_Struts2框架流程概述

    1. Struts2架构图  当外部的httpservletrequest到来时 ,初始到了servlet容器(所以虽然Servlet和Action是解耦合的,但是Action依旧能够通过httpse ...

  5. shell脚本之函数的使用

    把代码封装成函数,相当于造了一个“轮子”,之后就直接重复使用即可. 函数的创建 shell中函数的创建有2种方式 1.使用function关键字 语法 function test { ... } 2. ...

  6. 如何利用dex2jar反编译APK

    工具/原料 电脑 dex2jar JD-GUI 方法/步骤 1 下载dex2jar和JD-GUI,在参考资料中添加了这两个工具的百度网盘下载地址供读者下载使用(笔者亲测) 2 找到我们准备测试用的ap ...

  7. python3.5读取kafka中的数据

    安装包 pykafka 代码如下: from pykafka import KafkaClient client = KafkaClient(hosts="test43:9092" ...

  8. CentOS6.5+nginx+mysql+php(laravel)服务器环境搭建

    公司准备迭代会员中心项目,要上laravel框架,替代以前的Ecshop框架,PHP工程师将部分功能页面代码提交,自己也准备着手搭建一个测试环境将项目跑起来: 一. 环境依赖安装设置 关闭防火墙 [r ...

  9. Python操作Word【批量生成文章】

    http://www.cnblogs.com/codex/p/4668396.html 需要做一些会议记录.总共有多少呢?五个地点x7个月份x每月4篇=140篇.虽然不很重要,但是140篇记录完全雷同 ...

  10. 一款基于jQuery的带Tooltip表单验证的注册表单

    今天给大家分享一款基于jQuery的注册表单,这款注册表单的特点是确认提交注册信息时,表单会自动验证所填写的信息,如果信息填写有误,即会在相应的字段内以Tooltip提示框的形式显示错误信息.这款jQ ...