m2014_c:C 工具库1:list
转自: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的更多相关文章
- 细说Java主流日志工具库
概述 在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息. 在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子. 我们先来逐一了解一下主流日志工具. java.util ...
- JHChart 1.1.0 iOS图表工具库中文ReadMe
JHChart(最新版本1.1.0) 好吧,的确当前的github上已经存有不少的iOS图表工具库,然而,当公司的项目需要图表时,几乎没有哪个第三方能够完全满足我的项目需求.无奈之下,本人不得不花费一 ...
- JHChart iOS图表工具库1.0.3新版本详解
前言. 从2016年4月14日开始,本人着手开发了JHChart图表工具库.经过断断续续的开发,截止到现在,已经实现了折线图.柱状图.饼状图.环形图和表格样式的图表功能.为了方便使用,我已经将一个简单 ...
- [转]Android开源项目第二篇——工具库篇
本文为那些不错的Android开源项目第二篇--开发工具库篇,主要介绍常用的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容.多 ...
- CSV.js – 用于 CSV 解析和编码的 JS 工具库
逗号分隔值(CSV )文件用于以以纯文本的形式存储表格化数据(数字和文本). CSV 文件包含任意数量的记录,通过某种换行符分隔,每条记录由字段,其他一些字符或字符串分隔,最常用的是文字逗号或制表符. ...
- Lo-Dash – 替代 Underscore 的优秀 JS 工具库
前端开发人员大都喜欢 Underscore,它的工具函数很实用,用法简单.这里给大家推荐另外一个功能更全面的 JavaScript 工具——Lo-Dash,帮助你更好的开发网站和 Web 应用程序. ...
- Java主流日志工具库
在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息.在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子.我们先来逐一了解一下主流日志工具. 1.java.util.lo ...
- Android开源项目第二篇——工具库篇
本文为那些不错的Android开源项目第二篇——开发工具库篇,**主要介绍常用的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容 ...
- javaScript常用工具库
对应于百度前端技术学院2015年春季的课程2相关内容 https://github.com/baidu-ife/ife/tree/master/2015_spring/task/task0002 ht ...
- Android 绘图工具库AChartEngine
From: http://www.oschina.net/p/achartengine AChartEngine是为android应用而设计的绘图工具库.目前该库的最新稳定版本是0.7,支持绘制以下类 ...
随机推荐
- Redis总结(六)Redis配置文件全解(转载)
前面已经写了一些关于redis 的介绍,redis 的基本功能和用法,基本上都说了,有问题的可以去看看 http://www.cnblogs.com/zhangweizhong/category/77 ...
- CSC时无法找到C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib
偶然用到CSC编译c#程序,出现如下问题: warning CS1668: “LIB 环境变量”中指定的搜索路径“C:\Program Files\Microsoft SDKs\Wind ...
- Python2.X和Python3.X中的urllib区别
Urllib是Python提供的一个用于操作URL的模块,在Python2.X中,有Urllib库,也有Urllib2库,在Python3.X中Urllib2合并到了Urllib中,我们爬取网页的时候 ...
- 产生sql语句的vba
//清除空列 Sub ClearNullMacro1() Dim j As Integer Dim colCount As Integer colCount = Cells(2, Columns.Co ...
- SpringCloud-服务注册与发现
这里我们会用到Spring Cloud Netflix,该项目是Spring Cloud的子项目之一,主要内容是对Netflix公司一系列开源产品的包装,它为Spring Boot应用提供了自配置的N ...
- 【Android】14.2 外部文件存储和读取
分类:C#.Android.VS2015: 创建日期:2016-02-27 一.简介 1.基本概念 内部存储的私有可用存储空间一般都不会很大,对于容量比较大的文件,例如视频等,应该将其存储在外部存储设 ...
- vue2.0实现图片加载失败默认显示图片
<div class="bg"> <img :src="goods.phoneFloorAd.resUrl" :onerror="e ...
- vue2 vue-router2 webpack1
转自:http://www.qinshenxue.com/article/20161106163608.html: 项目地址:https://github.com/qinshenxue/vue2-vu ...
- 偏于SQL语句的 sqlAlchemy 增删改查操作
ORM 江湖 曾几何时,程序员因为惧怕SQL而在开发的时候小心翼翼的写着sql,心中总是少不了恐慌,万一不小心sql语句出错,搞坏了数据库怎么办?又或者为了获取一些数据,什么内外左右连接,函数存储过程 ...
- ASP.NET 5 将于2016年一季度公布
简单介绍:微软ASP.NET团队在GitHub宣布ASP.NET 5的公布时间表和发展蓝图. 该团队宣布在2015年还将公布三个Beta版.一个ASP.NET 5的抢先版(RC 1).到2016年一季 ...