📄 gdk_atoms.mx
字号:
*/#else#define GDK_ELIMPOWER 17 /* makes for a max 128KB hash table * ie 512 string bytes per hash bucket * ~ 5 strings of UP8(8<=len<=15)=16 + 8 bytes */#endif@- Atomic ADT functions@cintATOMlen(int t, ptr src){ int (*l)(ptr) = BATatoms[t].atomLen; return l ? (*l)(src) : ATOMsize(t);}intATOMheap(int t, Heap *hp, size_t cap){ void (*h) (Heap *, size_t) = BATatoms[t].atomHeap; if (h) { (*h) (hp, cap); if (hp->base == NULL) return -1; } return 0;}intATOMcmp(int t, ptr l, ptr r){ switch (ATOMstorage(t)) {#ifndef NOEXPAND_CHR case TYPE_chr: return simple_CMP(l, r, chr);#endif#ifndef NOEXPAND_BTE case TYPE_bte: return simple_CMP(l, r, bte);#endif#ifndef NOEXPAND_SHT case TYPE_sht: return simple_CMP(l, r, sht);#endif#ifndef NOEXPAND_INT case TYPE_int: return simple_CMP(l, r, int);#endif#ifndef NOEXPAND_FLT case TYPE_flt: return simple_CMP(l, r, flt);#endif#ifndef NOEXPAND_LNG case TYPE_lng: return simple_CMP(l, r, lng);#endif#ifndef NOEXPAND_DBL case TYPE_dbl: return simple_CMP(l, r, dbl);#endif default: return (l == r) ? 0 : atom_CMP(l, r, t); }}@Atom print avoids coercion to strings for built-in types.The comparison against the NULL value is hard coded for speed.@c#define LINE_LEN 60intATOMprint(int t, ptr p, stream *s){ int (*tostr) (str *, int *, ptr); if (p && (t >= 0) && (t < GDKatomcnt) && (tostr = BATatoms[t].atomToStr)) { if (t != TYPE_bat && t < TYPE_str) { char buf[dblStrlen], *addr = buf; /* use memory from stack */ int sz = dblStrlen, l = (*tostr) (&addr, &sz, p); stream_write(s, buf, l, 1); return l; } else { str buf = 0; int sz = 0, l = (*tostr) (&buf, &sz, p); l = (int) stream_write(s, buf, l, 1); GDKfree(buf); return l; } } return (int) stream_write(s, "nil", 1, 3);}intATOMformat(int t, ptr p, char **buf){ int (*tostr) (str *, int *, ptr); if (p && (t >= 0) && (t < GDKatomcnt) && (tostr = BATatoms[t].atomToStr)) { int sz = 0, l = (*tostr) (buf, &sz, p); return l; } strcpy(*buf = GDKmalloc(4), "nil"); return 3;}ptrATOMdup(int t, ptr p){ int len = ATOMlen(t, p); ptr n = GDKmalloc(len); memcpy(n, p, len); return n;}@* Builtin Atomic Operator Implementations@+ Atom-from-String Conversions These routines convert from string to atom. They are used during conversion and BAT import. In order to avoid unnecessary malloc()/free()sequences, the conversion functions have a meta 'dst' pointer to adestination region, and an integer* 'len' parameter, that denotes the length of that region (a char region for ToStr functions, an atom regionfrom FromStr conversions). Only if necessary will the conversionroutine do a GDKfree()/GDKmalloc() sequence, and increment the 'len'.Passing a pointer to a nil-ptr as 'dst' and/or a *len==0 is valid; the conversion function will then alloc some region for you.@= atommem if (!*dst) { *dst = (@1 *) GDKmalloc(*len = @2); } else if (*len < (int) @2) { GDKfree(*dst); *dst = (@1 *) GDKmalloc(*len = @2); }@= atomtostrint@1ToStr(char ** dst, int *len, @1 *src){ @:atommem(char,@1Strlen)@ if (*src == @1_nil) { strcpy(*dst, "nil"); return 3; } snprintf(*dst, *len, @2, (@3) *src); return (int) strlen(*dst);}@c#define num08(x) ((x) >= '0' && (x) <= '7')#define num10(x) GDKisdigit(x)#define num16(x) (GDKisdigit(x) || ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F'))#define base10(x) ((x) - '0')#define base08(x) ((x) - '0')#define base16(x) (((x) >= 'a' && (x) <= 'f') ? ((x) - 'a' + 10) : ((x) >= 'A' && (x) <= 'F') ? ((x) - 'A' + 10) : (x) - '0')#define mult08(x) ((x) << 3)#define mult16(x) ((x) << 4)#define mult10(x) ((x) + (x) + ((x) << 3))#define mult7(x) (((x) << 3) - (x))intvoidFromStr(str src, int *len, void **dst){ (void) src; (void) len; (void) dst; return 0;}intvoidToStr(str *dst, int *len, void *src){ (void) src; @:atommem(char,3)@ strcpy(*dst, "nil"); return 3;}void *voidRead(void *a, stream *s, size_t cnt){ (void) s; (void) cnt; return a;}intvoidWrite(void *a, stream *s, size_t cnt){ (void) a; (void) s; (void) cnt; return GDK_SUCCEED;}intchrFromStr(char *src, int *len, chr **dst){ unsigned char *p = (unsigned char *) src; unsigned int base = 0; int error = 0; @:atommem(chr,sizeof(chr))@ while (GDKisspace(*p)) p++; if (p[0] == 'n' && p[1] == 'i' && p[2] == 'l') { base = chr_nil; p += 3; } else { int q = p[0] == '\'' && p[1] != 0; if (q) p++; error = 1; /* until proved otherwise */ if ((*p & 0x80) == 0) { if (q && *p == '\\' && p[1] != 0) { /* interpret backslash escape but only in a single-quoted string*/ p++; switch (*p) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': /* \ with up to three octal digits */ base = base08(*p); if (num08(p[1])) { p++; base = mult08(base) + base08(*p); if (num08(p[1])) { p++; base = mult08(base) + base08(*p); } } error = 0; break; case 'x': /* \x with one or two hexadecimal digits */ if (num16(p[1])) { p++; base = base16(*p); if (num16(p[1])) { p++; base = mult16(base) + base16(*p); } error = 0; } break; case 'a': base = '\a'; error = 0; break; case 'b': base = '\b'; error = 0; break; case 'f': base = '\f'; error = 0; break; case 'n': base = '\n'; error = 0; break; case 'r': base = '\r'; error = 0; break; case 't': base = '\t'; error = 0; break; case '\0': /* cannot happen */ break; case '\'': case '\\': /* \' and \\ can be handled by the default case */ default: /* unrecognized \ escape, just copy the backslashed character */ base = *p; error = 0; break; } p++; } else { base = *p++; error = 0; }#ifndef ASCII_CHR } else if ((*p & 0xC0) == 0x80) { /* illegal UTF-8 sequence */ } else if ((*p & 0xE0) == 0xC0) { base = (*p++ & 0x1F) << 6; if (base && (*p & 0xC0) == 0x80) { base |= *p++ & 0x3F; error = 0; }#if 0 /* not needed until chr supports the whole Unicode range */ } else if ((*p & 0xF0) == 0xE0) { base = (*p++ & 0x0F) << 12; if (base && (*p & 0xC0) == 0x80) { base |= (*p++ & 0x3F) << 6; if ((*p & 0xC0) == 0x80) { base |= *p++ & 0x3F; error = 0; } } } else if ((*p & 0xF8) == 0xF0) { base = (*p++ & 0x07) << 18; if (base && (*p & 0xC0) == 0x80) { base |= (*p++ & 0x3F) << 12; if ((*p & 0xC0) == 0x80) { base |= (*p++ & 0x3F) << 6; if ((*p & 0xC0) == 0x80) { base |= *p++ & 0x3F; error = 0; } } } } else if ((*p & 0xFC) == 0xF8) { base = (*p++ & 0x03) << 24; if (base && (*p & 0xC0) == 0x80) { base |= (*p++ & 0x3F) << 18; if ((*p & 0xC0) == 0x80) { base |= (*p++ & 0x3F) << 12; if ((*p & 0xC0) == 0x80) { base |= (*p++ & 0x3F) << 6; if ((*p & 0xC0) == 0x80) { base |= *p++ & 0x3F; error = 0; } } } } } else if ((*p & 0xFE) == 0xFC) { base = (*p++ & 0x01) << 30; if (base && (*p & 0xC0) == 0x80) { base |= (*p++ & 0x3F) << 24; if ((*p & 0xC0) == 0x80) { base |= (*p++ & 0x3F) << 18; if ((*p & 0xC0) == 0x80) { base |= (*p++ & 0x3F) << 12; if ((*p & 0xC0) == 0x80) { base |= (*p++ & 0x3F) << 6; if ((*p & 0xC0) == 0x80) { base |= *p++ & 0x3F; error = 0; } } } } }#endif#endif } if (!error && q && *p != '\'') error = 1;#ifdef ASCII_CHR if (!error && base >= 128) error = 1;#else if (!error && (base >= 256 || base == 128)) error = 1;#endif if (error) p = (unsigned char *) src; } **dst = error ? chr_nil : (chr) base; return (int) (p - (unsigned char *) src);}intchrToStr(str *dst, int *len, chr *src){ @:atommem(char,chrStrlen)@ if (*src == chr_nil) { strcpy(*dst, "nil"); return 3; } else { str p = *dst; *p++ = '\''; if (*src & 0x80) {#ifdef ASCII_CHR strcpy(*dst, "nil"); return 3;#else *p++ = 0xC0 | ((*src >> 6) & 0x03); *p++ = 0x80 | (*src & 0x3F);#endif } else { if (*src < ' ' || *src == 127) { snprintf(p, chrStrlen - 3, "\\%03o", * (unsigned char *) src); p += 4; } else if (*src == '\\' || *src == '\'') { *p++ = '\\'; *p++ = *src; } else { *p++ = *src; } } *p++ = '\''; *p = 0; return (int) (p - *dst); } return 1;}chr *chrRead(chr *a, stream *s, size_t cnt){ stream_read(s, (char *) a, 1, cnt);#ifdef ASCII_CHR /* only accept ASCII characters */ return stream_errnr(s) ? NULL : (*a & 0x80 ? NULL : a);#else /* effectively read latin-1 (ISO-8859-1) character data */ return stream_errnr(s) ? NULL : a;#endif}intchrWrite(chr *a, stream *s, size_t cnt){ if (stream_write(s, (char *) a, 1, cnt) == (ssize_t) cnt) return GDK_SUCCEED; else return GDK_FAIL;}intbitFromStr(str src, int *len, bit **dst){ char *p = src; @:atommem(bit,sizeof(bit))@ while (GDKisspace(*p)) p++; **dst = bit_nil; if (*p == '0') { **dst = FALSE; p++; } else if (*p == '1') { **dst = TRUE; p++; } else if (p[0] == 't' && p[1] == 'r' && p[2] == 'u' && p[3] == 'e') { **dst = TRUE; p += 4; } else if (p[0] == 'f' && p[1] == 'a' && p[2] == 'l' && p[3] == 's' && p[4] == 'e') { **dst = FALSE; p += 5; } else if (p[0] == 'n' && p[1] == 'i' && p[2] == 'l') { p += 3; } return (int) (p - src);}intbitToStr(char **dst, int *len, bit *src){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -