📄 gdk_atoms.mx
字号:
The routine @%put@ takes a pointer to a memory resident copy and preparesa persistent copy in the BAT passed. The inverse operation is @%get@. A new value can be directly included into the BAT using @%new@, which shouldprepare a null-value representation.A value is removed from the BATstore using @%del@, which can take care of garbage collection and BAT administration. The pair @%tostr@ and @%fromstr@ should convert a reference to a persistentvalue to a memory resident string equivalent. @%FromStr@ takes a string and applies a @%put@ to store it within a BAT. They are used to prepare for readable output/input and to support coercion.The routines @%cmp@ and @%eq@ are comparison routines used to build access structures. The @%null@ returns a reference to a null value representation.@- The incremental atom construction uses hardwired properties.This should be improved later on.@{@cvoidATOMdelete(int id){ memset(BATatoms + id, 0, sizeof(atomDesc)); if (id == GDKatomcnt - 1) GDKatomcnt--;}static intalign(int n){ if (n == 0) return 0; /* successively check bits from the bottom to see if one is set */ if (n & 1) return 1; if (n & 2) return 2; if (n & 4) return 4; return 8;}voidATOMproperty(str id, str property, GDKfcn arg){ int t; gdk_set_lock(GDKthreadLock, "ATOMproperty"); t = ATOMindex(id); if (t < 0) { t = -t; if (t == GDKatomcnt) { GDKatomcnt++; } FATALcheck(GDKatomcnt == MAXATOMS, "ATOMproperty:too many types"); FATALcheck(strlen(id) >= IDLENGTH, "ATOMproperty:name too long"); memset(BATatoms + t, 0, sizeof(atomDesc)); strcpy(BATatoms[t].name, id); BATatoms[t].size = sizeof(int); /* default */ BATatoms[t].align = sizeof(int); /* default */ BATatoms[t].linear = 1; /* default */ BATatoms[t].storage = t; /* default */ BATatoms[t].deleting = 1; /* not yet usable */ } if (strcmp("size", property) == 0) { if ((int) (ssize_t) arg) { BATatoms[t].size = (int) (ssize_t) arg; BATatoms[t].varsized = 0; BATatoms[t].align = align((int) (ssize_t) arg); } else { BATatoms[t].size = sizeof(var_t); BATatoms[t].varsized = 1; BATatoms[t].align = sizeof(var_t); } } else if (strcmp("linear", property) == 0) { BATatoms[t].linear = (int) (ssize_t) arg; } else if (strcmp("align", property) == 0) { BATatoms[t].align = (int) (ssize_t) arg; } else if (strcmp("storage", property) == 0) { int tpe = (int) (ssize_t) arg; BATatoms[t] = BATatoms[tpe]; /* copy from example */ strcpy(BATatoms[t].name, id); /* restore name */ } else if (strcmp("fromstr", property) == 0) { BATatoms[t].atomFromStr = (int (*)(char *, int *, void **)) arg; } else if (strcmp("tostr", property) == 0) { BATatoms[t].atomToStr = (int (*)(char **, int *, void *)) arg; } else if (strcmp("read", property) == 0) { BATatoms[t].atomRead = (void *(*)(void *, stream *, size_t)) arg; } else if (strcmp("write", property) == 0) { BATatoms[t].atomWrite = (int (*)(void *, stream *, size_t)) arg; } else if (strcmp("fix", property) == 0) { BATatoms[t].atomFix = (int (*)(void *)) arg; } else if (strcmp("unfix", property) == 0) { BATatoms[t].atomUnfix = (int (*)(void *)) arg; } else {#define atomset(dst,val) oldval = (ptr) dst; if (val == NULL || dst == val) goto out; dst = val; ptr oldval = NULL; if (strcmp("heap", property) == 0) { BATatoms[t].size = sizeof(var_t); BATatoms[t].varsized = 1; BATatoms[t].align = sizeof(var_t); atomset(BATatoms[t].atomHeap, (void (*)(Heap *, size_t)) arg); } else if (strcmp("heapconvert", property) == 0) { atomset(BATatoms[t].atomHeapConvert, (void (*)(Heap *, int)) arg); } else if (strcmp("check", property) == 0) { atomset(BATatoms[t].atomHeapCheck, (int (*)(Heap *, HeapRepair *)) arg); } else if (strcmp("del", property) == 0) { atomset(BATatoms[t].atomDel, (void (*)(Heap *, var_t *)) arg); } else if (strcmp("convert", property) == 0) { atomset(BATatoms[t].atomConvert, (void (*)(void *, int)) arg); } else if (strcmp("put", property) == 0) { atomset(BATatoms[t].atomPut, (var_t (*)(Heap *, var_t *, void *)) arg); } else if (strcmp("null", property) == 0) { ptr atmnull = ((ptr (*)(void)) arg) (); atomset(BATatoms[t].atomNull, atmnull); } if (oldval) goto out; /* these ADT functions *must* be equal for overloaded types */ if (strcmp("cmp", property) == 0) { atomset(BATatoms[t].atomCmp, (int (*)(void *, void *)) arg); } else if (strcmp("hash", property) == 0) { atomset(BATatoms[t].atomHash, (hash_t (*)(void *)) arg); } else if (strcmp("length", property) == 0) { atomset(BATatoms[t].atomLen, (int (*)(void *)) arg); } if (BATatoms[t].storage != t) GDKerror("ATOMproperty: %s overload of %s violates inheritance from %s.\n", ATOMname(t), property, ATOMname(BATatoms[t].storage));/**/ BATatoms[t].storage = t; /* critical redefine: undo remapping */ } out: gdk_unset_lock(GDKthreadLock, "ATOMproperty");}intATOMindex(str nme){ int t, j = GDKatomcnt; for (t = 0; t < GDKatomcnt; t++) { if (!BATatoms[t].name[0]) { if (j == GDKatomcnt) j = t; } else if (strcmp(nme, BATatoms[t].name) == 0) { return t; } } if (strcmp(nme, "bat") == 0) { return TYPE_bat; } return -j;}char *ATOMname(int t){ return (t >= 0 && t < GDKatomcnt && BATatoms[t].name) ? BATatoms[t].name : "null";}intATOMisdescendant(int tpe, int parent){ int cur = -1; while (cur != tpe) { cur = tpe; if (cur == parent) return TRUE; tpe = BATatoms[tpe].storage; } return FALSE;}intATOMdump(void){ int t; for (t = 0; t < GDKatomcnt; t++) { stream_printf(GDKout, "%2d '%9s' (%3d) ", t, BATatoms[t].name, BATatoms[t].size); if (BATatoms[t].atomFromStr) { stream_printf(GDKout, "\"FromStr\" "); } if (BATatoms[t].atomToStr) { stream_printf(GDKout, "\"ToStr\" "); } if (BATatoms[t].atomCmp) { stream_printf(GDKout, "\"Cmp\" "); } if (BATatoms[t].atomNull) { stream_printf(GDKout, "\"Null\" "); } if (BATatoms[t].atomHash) { stream_printf(GDKout, "\"Hash\" "); } if (BATatoms[t].atomPut) { stream_printf(GDKout, "\"Put\" "); } if (BATatoms[t].atomDel) { stream_printf(GDKout, "\"Del\" "); } if (BATatoms[t].atomLen) { stream_printf(GDKout, "\"Len\" "); } if (BATatoms[t].atomConvert) { stream_printf(GDKout, "\"Convert\" "); } if (BATatoms[t].atomHeap) { stream_printf(GDKout, "\"NewHeap\" "); } stream_printf(GDKout, "\n"); } return 0;}@}@- nil valuesAll types have a single value designated as a NIL value. It designatesa missing value and it is ignored (forbidden) in several primitives.The current policy is to use the smallest value in any ordered domain.The routine atomnil returns a pointer to the nil value representation.@{@h#include <limits.h> /* for *_MIN and *_MAX */#include <float.h> /* for FLT_MAX and DBL_MAX */#ifndef LLONG_MAX#ifdef LONGLONG_MAX#define LLONG_MAX LONGLONG_MAX#define LLONG_MIN LONGLONG_MIN#else#define LLONG_MAX LL_CONSTANT(9223372036854775807)#define LLONG_MIN (-LL_CONSTANT(9223372036854775807) - LL_CONSTANT(1))#endif#endif#define GDK_bit_max ((bit) 1)#define GDK_bit_min ((bit) 0)#define GDK_chr_max ((chr) SCHAR_MAX)#define GDK_chr_min ((chr) SCHAR_MIN)#define GDK_bte_max ((bte) SCHAR_MAX)#define GDK_bte_min ((bte) SCHAR_MIN)#define GDK_sht_max ((sht) SHRT_MAX)#define GDK_sht_min ((sht) SHRT_MIN)#define GDK_int_max INT_MAX#define GDK_int_min INT_MIN#define GDK_flt_max ((flt) FLT_MAX)#define GDK_flt_min (-GDK_flt_max)#define GDK_lng_max ((lng) LLONG_MAX)#define GDK_lng_min ((lng) LLONG_MIN)#define GDK_dbl_max ((dbl) DBL_MAX)#define GDK_dbl_min (-GDK_dbl_max)/* GDK_oid_max see below */#define GDK_oid_min ((oid) 0)/* representation of the nil */ gdk_export const chr chr_nil;gdk_export const bte bte_nil;gdk_export const sht sht_nil;gdk_export const int int_nil;gdk_export const flt flt_nil;gdk_export const dbl dbl_nil;gdk_export const lng lng_nil;gdk_export const char str_nil[2];/* derived NIL values - OIDDEPEND */#define bit_nil ((bit) chr_nil)#if SIZEOF_VOID_P == SIZEOF_INT#define ptr_nil ((ptr) int_nil)#else /* SIZEOF_VOID_P == SIZEOF_LNG */#define ptr_nil ((ptr) lng_nil)#endif#define bat_nil ((bat) int_nil)#if SIZEOF_WRD == SIZEOF_INT#define wrd_nil ((wrd) int_nil)#define GDK_wrd_max ((wrd) GDK_int_max)#define GDK_wrd_min ((wrd) GDK_int_min)#else#define wrd_nil ((wrd) lng_nil)#define GDK_wrd_max ((wrd) GDK_lng_max)#define GDK_wrd_min ((wrd) GDK_lng_min)#endif#if SIZEOF_OID == SIZEOF_INT#define oid_nil ((oid) GDK_int_min)#define GDK_oid_max ((oid) GDK_int_max)#else#define oid_nil ((oid) GDK_lng_min)#define GDK_oid_max ((oid) GDK_lng_max)#endif#define void_nil oid_nil@cconst chr chr_nil = (chr) '\200';const bte bte_nil = GDK_bte_min;const sht sht_nil = GDK_sht_min;const int int_nil = GDK_int_min;const flt flt_nil = GDK_flt_min;const dbl dbl_nil = GDK_dbl_min;const lng lng_nil = GDK_lng_min;const char str_nil[2] = { GDK_chr_min, 0 };ptrATOMnil(int t){ ptr src = ATOMnilptr(t); int len = ATOMlen(ATOMtype(t), src); ptr dst = GDKmalloc(len); memcpy(dst, src, len); return dst;}@}@- Derived typesIn all algorithms across GDK, you will find switches on the types( chr, bte, sht, int, wrd, flt, dbl, lng, str). They respectively represent an octet, a 16-bit int, a 32-bit int, a 32-bit float, a 64-bit double,a 64-bit int, and a pointer-sized location of a char-buffer (ended by a zero char).In contrast, the types (bit, ptr, bat, oid) are derived types. They do not occur in the switches. The @%ATOMstorage@ macro maps them respectivelyonto a @code{ chr}, @code{ int} (pointers are 32-bit), @code{ int}, and@code{ int}. OIDs are 32-bit.This approach makes it tractable to switch to 64-bits OIDs,or to a fully 64-bits OS easily. One only has to map the @code{ oid}and @code{ ptr} types to @code{ lng} instead of @code{ int}. Derived types mimic their fathers in many ways. They inherit the @code{ size},@code{ varsized}, @code{ linear}, @code{ null} and @code{ align} properties of their father. The same goes for the ADT functions HASH, CMP, PUT, NULL,DEL, LEN, and HEAP. So, a derived type differs in only two waysfrom its father:@table @code@item [string representation]the only two ADT operations specific for a derived type are FROMSTRand TOSTR.@item [identity](a @code{ bit} is really of a different type than @code{ chr}). The set ofoperations on derived type values or BATs of such types may differfrom the sets of operations on the father type. @end table@{@h/* use "do ... while(0)" so that lhs can safely be used in if statements */#define ATOMstorage(t) BATatoms[t].storage#define ATOMsize(t) BATatoms[t].size#define ATOMalign(t) BATatoms[t].align#define ATOMfromstr(t,s,l,src) BATatoms[t].atomFromStr(src,l,s)#define ATOMnilptr(t) BATatoms[t].atomNull#define ATOMhash(t,src) BATatoms[t].atomHash(src)#define ATOMdel(t,hp,src) do if (BATatoms[t].atomDel) BATatoms[t].atomDel(hp,src); while (0)#define ATOMvarsized(t) ((t != TYPE_void) && BATatoms[t].varsized)#define ATOMlinear(t) BATatoms[t].linear#define ATOMtype(t) ((t == TYPE_void)?TYPE_oid:t)#define ATOMfix(t,v) do if (BATatoms[t].atomFix) BATatoms[t].atomFix(v); while (0)#define ATOMunfix(t,v) do if (BATatoms[t].atomUnfix) BATatoms[t].atomUnfix(v); while (0)#define ATOMconvert(t,v,d) do if (BATatoms[t].atomConvert) BATatoms[t].atomConvert(v,d); while (0)#define ATOMheapConvert(t,hp,d) do if (BATatoms[t].atomHeapConvert) BATatoms[t].atomHeapConvert(hp,d); while (0)#define CONV_HTON 1#define CONV_NTOH 0@- In case that atoms are added to a bat, their logical reference countshould be incremented (and decremented if deleted). Notice that BATs with atomic types that have logical references (e.g. BATs of BATs but also BATs of ODMG odSet) can never be persistent, as this would makethe commit tremendously complicated.@h#define ATOMput(P1, P2, p3, p4) \{ \ int t_ = (P1); \ ptr P3 = (ptr) (p3); \ ptr P4 = (ptr) (p4); \ \ if (t_ == TYPE_oid || t_ == TYPE_wrd || t_ == TYPE_ptr || t_ > TYPE_str) \ t_ = ATOMstorage(t_); \ if (t_ <= TYPE_bat) { \ if (t_ <= TYPE_bte) { \ if (t_ != TYPE_void) \ *(bte *) (P3) = *(bte *) (P4); \ } else if (t_ == TYPE_sht) { \ *(sht *) (P3) = *(sht *) (P4); \ } else if (t_ == TYPE_bat) { \ BBPincref(*(bat *) (P4), TRUE); \ *(bat *) (P3) = *(bat *) (P4); \ } \ } else { \ if (t_ <= TYPE_flt) { \ *(int *) (P3) = *(int *) (P4); \ } else if (t_ <= TYPE_lng) { \ *(lng *) (P3) = *(lng *) (P4); \ } else if (t_ == TYPE_str) { \ if (strPut(P2, (var_t *) (P3), (str) (P4)) == 0)\ goto bunins_failed; \ } else if (t_) { \ if (BATatoms[t_].atomPut) { \ if ((*BATatoms[t_].atomPut) (P2, (var_t *) P3, P4) == 0) \ goto bunins_failed; \ } else { \ memcpy(P3, P4, (size_t) ATOMsize(P1)); \ } \ ATOMfix(t_, P4); \ } \ } \}#define ATOMreplace(P1, P2, P3, P4) \{ \ int t_ = (P1); \ \ if (t_ == TYPE_oid || t_ == TYPE_wrd || t_ == TYPE_ptr || t_ > TYPE_str) \ t_ = ATOMstorage(t_); \ if (t_ <= TYPE_bat) { \ if (t_ <= TYPE_bte) { \ if (t_ != TYPE_void) \ *(bte *) (P3) = *(bte *) (P4); \ } else if (t_ == TYPE_sht) { \ *(sht *) (P3) = *(sht *) (P4); \ } else if (t_ == TYPE_bat) { \ BBPincref(*(bat *) (P4), TRUE); \ BBPdecref(*(bat *) (P3), TRUE); \ *(bat *) (P3) = *(bat *) (P4); \ } \ } else { \ if (t_ <= TYPE_flt) { \ *(int *) (P3) = *(int *) (P4); \ } else if (t_ <= TYPE_lng) { \ *(lng *) (P3) = *(lng *) (P4); \ } else if (t_ == TYPE_str) { \ if (strPut(P2, (var_t *) (P3), (str) (P4)) == 0) \ goto bunins_failed; \ } else if (BATatoms[t_].atomPut) { \ var_t loc_ = *(var_t *) (P3); \ \ if ((*BATatoms[t_].atomPut) (P2, &loc_, P4) == 0) \ goto bunins_failed; \ ATOMunfix(t_, P3); \ if (BATatoms[t_].atomDel) { \ ATOMdel(t_, P2, (var_t *) P3); \ } \ *(var_t *) (P3) = loc_; \ ATOMfix(t_, P4); \ } else { \ ATOMunfix(t_, P3); \ memcpy(P3, P4, (size_t) ATOMsize(P1)); \ ATOMfix(t_, P4); \ } \ } \}#define GDK_STRHASHTABLE (1<<10)#define GDK_STRHASHMASK (GDK_STRHASHTABLE-1)#define GDK_STRHASHSIZE (GDK_STRHASHTABLE * sizeof(var_t))#define GDK_STRHASHCREDIT(h) (((var_t*) (h)->base)[GDK_STRHASHTABLE])#define GDK_ELIMDOUBLES(h) ((h)->free < GDK_ELIMLIMIT)#define GDK_ELIMLIMIT (1<<GDK_ELIMPOWER)#define GDK_ELIMBASE(x) (((x) >> GDK_ELIMPOWER) << GDK_ELIMPOWER)#if SIZEOF_SIZE_T == SIZEOF_INT#define GDK_ELIMPOWER 16 /* makes for a max 64KB hash table * ie 256 string bytes per hash bucket * ~ 4 strings of UP4(8<=len<=11)=12 + 4 bytes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -