原子是一个指向唯一的、不可改变的0个或任意多个字节序列的指针。
大多数原子都是指向以空字符结束的字符串,但是任何一个指向任意字节序列的指针都可以是原子。任何原子只可以出现一次。
原子通常被当作数据结构中的关键字使用。
Atom接口:(atom.h)
#ifndef ATOM_INCLUDEED #define ATOM_INCLUDEED extern int Atom_length(const char *str); extern const char *Atom_new(const char *str,int len); extern const char *Atom_string(const char *str); extern const char *Atom_int(long n); #endif
实现:(atom.c)
#include "atom.h" #include "limits.h" #include "mem.h" #define NELEMS(x) ((sizeof(x))/(sizeof((x)[0]))) static struct atom{ struct atom *link; int len; char *str; }*buckets[2048]; const char *Atom_string(const char *str){ assert(str); return Atom_new(str,strlen(str)); } const char *Atom_int(long n){ char str[43]; char *s=str+sizeof(str); unsigned long m; if(n==LONG_MIN) m=LONG_MAX+1UL; else if(n<0) m=-n; else m=n; do{ *--s=m%10+'0'; }while((m/=10)>0); if(n<0) *--s='-'; return Atom_new(s,(str+sizeof(str)-s)); } const char *Atom_new(const char *str,int len){ unsigned long h; int i; struct atom *p; assert(str); assert(len>=0); for(h=0,i=0; i<len; i++) h=(h<<1)+scatter[(unsigned char)str[i]]; h&=NELEMS(buckets)-1; for(p=buckets[h];p;p=p->link){ if(len==p->len){ for(i=0;i<len&&p->str[i]==str[i];) i++; if(i==len) return p->str; } p=ALLOC(sizeof(*p)+len+1); p->len=len; p->str=(char*)(p+1); if(len>0) memcpy(p->str,str,len); p->str[len]='\0'; p->link=buckets[h]; buckets[h]=p; } } int Atom_length(const char *str){ struct atom *p; int i; assert(str); for(i=0; i<NELEMS(buckets); i++) for(p=buckets[i]; p; p=p->link) if(p->str==str) return p->len; assert(0); return 0; }