#ifndef ARRAY_INCLUDED #include #include #include #include /*带有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; 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){ 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