今天时候不早了,最后介绍一个,通过哈希表(参考今天写的另一篇文章《工具箱之哈希表》)所构建的原子类型。这种类型,我第一次听说,是在云风老大的博客《关于 getter 和 setter》上,这是好早之前的故事了。然而由于以前自己很不努力,也一直没有真正动手做些东西,拖延到今天,才算正式开始实践。唉!少壮不努力,今晚徒伤悲啊!目前来讲,但行好事,莫问前程吧。貌似跑题了。 =_=
这种类型的使用如下。
atom a1, a2, a3;
make_atom("property_name_foo", &a1);
make_atom("property_name_bar", &a2);
make_atom("property_name_bar", &a3);
assert(
a1 != a2 &&
a2 == a3
);
基本实现同云风老大的博客一样,就不罗嗦了。
如果用 GCC 编译器编译,并开启 -Werror 选项(将警告当作错误处理),那么任何给原子类型直接赋值 const char * 型字符串的企图,都会导致编译器报错(这,也正是我们要达到的目的啦)。这是我们利用了如下语句所达到的目的,尽管 _atom 结构体什么都不是,仅仅是符号表里的一个符号。
typedef struct _atom *atom;
另外,所谓原子类型,顾名思义,就是「不可分类型」,可以当作基本类型那样,做等于不等判定、大小比较、排序、构建数组等等。这是很方便的。不像字符串,为了比较两个字符串内容是否一致,还需要逐个字符遍历过去,相当繁琐。Python 相比而言,就方便许多,不过,那又是另外一番故事了。
最后,再提一下《工具箱之哈希表》博文,其中的 modifiable 参数,在今天最开始完成哈希表的时候,是没有的,是在下午写原子类型的时候,才考虑到这个需求,并增加上去。普通哈希表的生成(即 hash_str_install 接口)是可以被覆盖的,这和原子类型的「一一对应」独特性,存在冲突。如若没有此参数,则需要为原子类型(特殊的字符串类型)构建一个独立的缓存区。
最后,附上接口的测试程序。
#include <string.h>
#include "../lib/atom.h"
#include "../lib/hash_str.h"
#include "test_common.h"static int errorCount = 0;
int test_make_atom(void)
{
int error_orig = errorCount;atom a1, a2, a3;
make_atom("property_name_foo", &a1);
make_atom("property_name_bar", &a2);
make_atom("property_name_bar", &a3);
assertTrue(a1 != a2 && a2 == a3);return (error_orig == errorCount) ? True:False;
}/*
Atoms should not be modified.
*/
int test_atom_modifiable(void)
{
int error_orig = errorCount;
int _ret; struct hnode *np;atom a1;
make_atom("property_name_foobar", &a1);
// Should not be successfully installed.
_ret = hash_str_install("property_name_foobar", "",
(void * (*)(void *)) strdup, &np, False);assertEqual(_ret, -1);
return (error_orig == errorCount) ? True:False;
}void test_atom(void)
{
run(test_make_atom);
run(test_atom_modifiable);
TestResult();
}
- EOF -