可扩展数组位于YHan.Helper中。 可扩展数组与C数组区别较大,具有以下特点 1.动态扩容,这一点与std::vector比较像 2.支持添加、删除、读值、写值时,触发对应的事件回调 3.带排序功能,支持自定义元素比较函数 4.合法性验证(IsBadReadPtr验证array对象的合法性,IsBadCodePtr验证callback的合法性)
在重写的过程中,发现作者很喜欢防御式编程,第4点就是很好体现,但是我认为对于非法输入应该使用assert,因为这是代码写错了,强行让代码继续运行本就是逻辑错误,直接让程序崩掉才是正确选择。
明白了作者的设计意图后,我们很好给出C语言的对于可扩展数组的定义。因为可扩展数组并不是Ex_DirectUI导出的功能,所以我们也没必要保证abi与原作者的实现相同,只需要包含所需功能即可,另外原作者的实现可以禁用事件,但是Ex_DirectUI中没有用到,我就不去实现了。
#ifndef _EX_DIRECTUI_ARRAY_H_
#define _EX_DIRECTUI_ARRAY_H_
#include <stddef.h>
#define EX_DIRECTUI_ARRAY_DEFAULT_GROWTH 1.1f
typedef struct tag_array_t array_t;
enum array_event_t
{
array_event_add,
array_event_del,
array_event_get,
array_event_set,
array_event_cmp
};
enum array_reason_t
{
array_reason_find,
array_reason_sort
};
typedef void * array_element_t;
typedef void *(*array_add_cb_t)(
array_t * arr,
size_t idx,
array_element_t ele,
void * param);
typedef void(*array_del_cb_t)(
array_t * arr,
size_t idx,
array_element_t ele,
void * event_data);
typedef void *(*array_get_cb_t)(
array_t * arr,
size_t idx,
array_element_t ele,
void * event_data);
typedef void *(*array_set_cb_t)(
array_t * arr,
size_t idx,
array_element_t ele,
void * event_data);
typedef int(*array_cmp_cb_t)(
array_t * arr,
size_t idx_x,
array_element_t ele_x,
size_t idx_y,
array_element_t ele_y,
void * event_data,
array_reason_t reason);
typedef struct tag_array_t
{
array_element_t * data;
size_t size;
size_t capacity;
float growth;
void * user_data;
void * event_data;
array_add_cb_t add_cb;
array_del_cb_t del_cb;
array_get_cb_t get_cb;
array_set_cb_t set_cb;
array_cmp_cb_t cmp_cb;
}array_t;
#endif
总的来说,我认为原作者的可扩展数组有点设计错误的地方,例如:数组_创建 函数中,传递参数初始成员数,但又无法触发添加成员的事件回调,数组重定义时,若缩小容量,会调用数组事件_删除成员,凭什么扩容时,不调用数组事件_添加成员呢?但我也只能读懂原作者的代码,才能重新设计数组容器。
|