You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

251 lines
8.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#ifndef ARRAY_INCLUDED
#include<assert.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
/*带有assert的安全分配内存*/
void *malloc_s(int _size){
assert(_size > 0);
void *malloc_ptr = malloc(_size);
assert(malloc_ptr != NULL);
return malloc_ptr;
}
/*字符串变量的创建与复制*/
char *malloc_s_strcpy(const char *const src){
//申请char[]时需要多分配几个位置用于存放'\0'结束符
char *dst = malloc_s(strlen(src)+2);
strcpy(dst, src);
return dst;
}
/*MARCO:根据类型安全分配内存*/
#define MALLOC_S(TypeName) (TypeName *)(malloc_s(sizeof(TypeName)))
/*链表单元*/
struct Array_{
void *p; /*内容数据*/
struct Array_ *next;
};
/*通过单向链表实现的动态数组,需要指定内置数据的类型*/
struct Array{
struct Array_ *front, *back; /*头尾节点*/
int TypeSize; /*内置类型的大小(不包含动态数据的纯大小)*/
int size; /*总体大小*/
};
/*链表初始化*/
void Array_create(struct Array *a, int ts)
{
assert("Array_create" && ts > 0);
a->TypeSize = ts;
a->size = 0;
a->back = a->front = NULL;
}
void Array_release_(struct Array_ *a, struct Array_ *back, void (*rel)(void *)){
if(a == back) return ;
Array_release_(a->next, back, rel);
rel(a->p);
free(a->p);
free(a);
}
/*释放动态分配的内存,需要指定释放内部动态成员的方法*/
void Array_release(struct Array *a, void (*rel)(void *)){
Array_release_(a->front, a->back, rel);
a->size = 0;
a->back = a->front = NULL;
}
/*返回指定位置的Array_*指针
配合PAT宏获取内部数据*/
struct Array_ *Array(struct Array *a, int pos){
assert("Array[pos]" && pos >= 0 && pos < a->size);
struct Array_ *node = a->front;
for(int i = 0; i < pos; i ++) node = node->next;
return node;
}
/*在pos前插入*/
void Array_insert(struct Array *a, void *p, int pos)
{
assert("Array_insert" && pos >= 0 && pos <= a->size);
struct Array_ *newNode, *node = a->front;
newNode = MALLOC_S(struct Array_);
newNode->p = malloc_s(a->TypeSize);
memcpy(newNode->p, p, a->TypeSize);
if(pos == 0){
newNode->next = a->front;
a->front = newNode;
}else{
for(int i = 0; i < pos-1; i ++) node = node->next;
newNode->next = node->next;
node->next = newNode;
}
a->size += 1;
}
/*删除pos位置的Array_节点*/
void Array_delete_pos(struct Array *a, int pos, void (*rel_)(void *)){
assert("Array_delete" && pos >= 0 && pos < a->size && a->size != 0);
struct Array_ *node = a->front, *freeNode;
if(pos == 0){
freeNode = a->front;
a->front = a->front->next;
rel_(freeNode->p);
free(freeNode);
}else{
for(int i = 0; i < pos-1; i ++) node = node->next;
freeNode = node->next;
node->next = node->next->next;
rel_(freeNode->p);
free(freeNode);
}
a->size--;
}
/*删除node所指向的Array节点*/
void Array_delete_p(struct Array *a, struct Array_ *node, void (*rel_)(void *)){
assert("Array_delete_p" && node != a->back);
struct Array_ *freeNode;
if(node == a->front){
freeNode = a->front;
a->front = a->front->next;
rel_(freeNode->p);
free(freeNode);
}else{
freeNode = node->next;
node->next = node->next->next;
rel_(freeNode->p);
free(freeNode);
}
a->size--;
}
/*交换内容即p指针*/
void Array__swap(struct Array_ *a, struct Array_ *b){
void *t = b->p;
b->p = a->p;
a->p = t;
}
/*
带有reverse选项的冒泡排序默认(reverse == 0)是升序
func(a,b)为排序所依据的比较函数
a>b:>0
a==b:0
a < b:<0
*/
void Array_sort(struct Array *a, int (*func)(void *, void *), int reverse){
reverse = reverse ? -1 : 1;
struct Array_ *sorted = a->back, *p;
while(a->front->next != sorted){
for(p = a->front; p->next != sorted; p = p->next)
if(reverse*func(p->p,p->next->p) > 0)
Array__swap(p, p->next);
sorted = p;
}
}
/*指定类型 转换(void)Array.p中的内容*/
#define PAT(TypeName, Array_Pointer) ((TypeName *)Array_Pointer->p)
/*链表的遍历*/
#define Range(arr) for(struct Array_ *p = arr.front; p != arr.back; p = p->next)
/*链表指定类型的初始化*/
#define DEF_ARRAY(Type, name)
void DoNothing(){}
/*记录每Array容器对象的信息*/
struct ArrayObjects{
void *p_obj; /*Array对象的地址*/
};
/*为每一个Array容器类实现释放管理*/
struct ArrayClass{
char *TypeName; /*容器内置类型的名称*/
void (*rel_)(void *);/*释放Array对象内部单个元素数据的方式*/
struct Array objects;/*该内置类型所有Array对象的信息*/
};
/*存储所有Array容器类*/
struct Array ArrayList;
/*以TypeName注册一个新的ArrayClass并且指定Rel__Func为释放单个元素的方式*/
void ArrayClass_Reg(char *TypeName, void (*Rel__Func)(void *p)){
struct ArrayClass ac;
ac.TypeName = malloc_s_strcpy(TypeName);
ac.rel_ = Rel__Func;
Array_create(&ac.objects, sizeof(struct ArrayObjects));
Array_insert(&ArrayList, &ac, 0);
}
/*向给定TypName的ArrayClass注册一个新的对象对象地址为p_obj*/
void ArrayObj_Reg(char *TypeName, void *p_obj){
struct Array_ *p;
for(p = ArrayList.front; p != ArrayList.back; p = p->next)
if(strcmp(((struct ArrayClass*)p->p)->TypeName, TypeName) == 0)
break;
Array_insert((&((struct ArrayClass*)p->p)->objects), &(struct ArrayObjects){p_obj}, 0);
}
/*释放ArrayList中单个元素占用的资源*/
void ArrayList_Rel_(void *p_class){
free(((struct ArrayClass *)p_class)->TypeName);
Array_release(&((struct ArrayClass *)p_class)->objects, DoNothing);
}
/*初始化Array_List*/
void ArrayList_Init(){
Array_create(&ArrayList, sizeof(struct ArrayClass));
}
/*释放ArrayList占用的资源*/
void ArrayList_Rel(){
Array_release(&ArrayList, ArrayList_Rel_);
}
/*主动提前释放资源,对于局部变量,需要在其被编译器释放前主动释放占用资源,防止内存泄漏*/
void Array_Obj_PreRelease(struct Array *unrel_obj){
for(struct Array_ *p = ArrayList.front; p != ArrayList.back; p = p->next)
for(struct Array_ *q = ((struct ArrayClass *)p->p)->objects.front; q != ((struct ArrayClass *)p->p)->objects.back; q = q->next)
if(unrel_obj == ((struct ArrayObjects*)q->p)->p_obj){
printf("%s\n", ((struct ArrayClass *)p->p)->TypeName);
Array_release(unrel_obj, ((struct ArrayClass *)p->p)->rel_);
Array_delete_p(&((struct ArrayClass *)p->p)->objects, q, DoNothing);
return ;
}
assert("Array_Obj_PreRelease:NotFound");
}
/*根据ArrayObj反查ArrayClass*/
struct ArrayClass *ArrayList_Find_Class_From_Obj(struct Array *a){
for(struct Array_ *p = ArrayList.front; p != ArrayList.back; p = p->next)
for(struct Array_ *q = ((struct ArrayClass *)p->p)->objects.front; q != ((struct ArrayClass *)p->p)->objects.back; q = q->next)
if(a == ((struct ArrayObjects*)q->p)->p_obj)
return (struct ArrayClass *)p->p;
assert("ArrayList_Find_Class_From_Obj:NotFound");
}
/*重写简化的Array_delete*/
void Array_deletepos(struct Array *a, int pos){
Array_delete_pos(a, pos, ArrayList_Find_Class_From_Obj(a)->rel_);
}
void Array_deletep(struct Array *a, struct Array_ *node){
Array_delete_p(a, node, ArrayList_Find_Class_From_Obj(a)->rel_);
}
/*MARCO:为Type注册一个新的ArrayClass并且指定Rel__Func为释放单个元素的方式*/
#define DECLARE_ARRAY(Type, RelFunc) ArrayClass_Reg(#Type, RelFunc);
/*
MARCO:为内置类型为Type的ArrayClass创建一个新的对象名称为ArrName
Example:
struct ARRAY(a, struct A);
^^^^^^___________________^
*/
#define ARRAY(ArrName, Type) \
Array ArrName; \
Array_create(&ArrName, sizeof(Type)); \
ArrayObj_Reg(#Type, &ArrName)
#define ARRAY_BIND(ArrName, Type) \
Array_create(&ArrName, sizeof(Type)); \
ArrayObj_Reg(#Type, &ArrName);
/*
Example:
struct A{
int a;
};
void rel_(void*p){}
int main(){
Array_Class_Init();
DECLARE_ARRAY(struct A, rel_)
struct ARRAY(a, struct A);
Array_Obj_PreRelease(&a);
Array_Class_Rel();
}
*/
#endif
#define ARRAY_INCLUDED