📄 gdk_atoms.mx
字号:
str hash = (str) h->base;/* int cnt[GDK_STRHASHTABLE]; */ /* collect all values in one big linked list */ for(xx=0; xx<GDK_STRHASHTABLE; xx++) { var_t yy = ((var_t*) hash)[xx];/* cnt[xx]=0; */ ((var_t*) hash)[xx] = 0; /* clear hash table slot */ if (end) { *(var_t*) (hash + end) = yy; } else { cur = yy; } for(; yy; yy=*(var_t*) (hash + yy)) end = yy; } /* process the linked list, inserting the values again */ for(; cur; cur=end) { str val = hash + cur; GDK_STRHASH(val + sizeof(var_t), xx); xx &= GDK_STRHASHMASK; end = *(var_t*) val; *(var_t*) val = ((var_t*) hash)[xx]; ((var_t*) hash)[xx] = cur;/* cnt[xx]++; */ }/* for(xx=0; xx<GDK_STRHASHTABLE; xx++) if(cnt[xx]) stream_printf(GDKout, "%5d %6d", xx, cnt[xx]); */ } }@- The @%strPut@ routine. The routine @%strLocate@ can be used to identifythe location of a string in the heap if it exists. Otherwise it returnszero.@cvar_tstrLocate(Heap *h, str v){ var_t *htab = (var_t *) h->base; var_t *l, *e; hash_t idx; GDK_STRHASH(v, idx); e = htab + (idx & GDK_STRHASHMASK); if (*e) { for (l = e; *l && *l < h->free; l = (var_t *) ((char *) h->base + *l)) { str x = (str) ((char *) h->base + *l + sizeof(var_t)); if (GDK_STRCMP(v, x) == 0) { return *l + (var_t) sizeof(var_t); } } } return 0;}/* convert the integers in the implicit hash table structure */voidstrHeapConvert(Heap *h, int dir){ var_t *htab = (var_t *) h->base; var_t *l, i, j; if (dir == CONV_HTON) { for (i = 0; i < GDK_STRHASHTABLE; i++) { for (l = htab + i; (j = *l) != 0 && j < h->free; l = (var_t *) (h->base + j)) { *l = normal_vart_SWAP(j); } } } else { for (i = 0; i < GDK_STRHASHTABLE; i++) { for (l = htab + i; (j = *l) != 0 && j < h->free; l = (var_t *) (h->base + *l)) { *l = normal_vart_SWAP(j); } } }}var_tstrPut(Heap *h, var_t *dst, str v){ var_t *l; size_t i = GDK_STRLEN(v); hash_t off; /* round up to var_t-byte alignment + var_t (next pointer) */ size_t len = ((i + sizeof(var_t) - 1) & ~(sizeof(var_t) - 1)) + sizeof(var_t); size_t elimlimit = GDK_ELIMBASE(h->free) + GDK_ELIMLIMIT; /* search hash-table, if double-elimination is still in place */ GDK_STRHASH(v,off); off &= GDK_STRHASHMASK; for (l = ((var_t *) h->base) + off; *l && *l < h->free; l = (var_t *) (h->base + *l)) { str x = (str) (h->base + *l + sizeof(var_t)); if (GDK_STRCMP(v, x) == 0) { *dst = *l + (var_t) sizeof(var_t); /* already in heap; do not insert! */ if (GDK_ELIMDOUBLES(h) == 0 && GDK_STRHASHCREDIT(h)) GDK_STRHASHCREDIT(h) += 4; return *dst; } } /* flush the hash table if it becomes too big (implies !GDK_ELIMDOUBLES) */ if (h->free + len >= elimlimit) { /* if we are not hash-inserting anymore, h->free may no longer be var_t aligned */ int mask = h->free & (sizeof(var_t)-1); if (mask) h->free += sizeof(var_t) - mask; /* realign */ memset(h->base, 0, GDK_STRHASHSIZE); /* start over hash inserting in a pristine hash table */ GDK_STRHASHCREDIT(h) = 32; /* only tolerate limited misses in the future */ } /* check heap for space (limited to a certain maximum after which nils are inserted) */ if (h->free + len >= h->size) { /* Something really strange happens here, In a special case (Pentium II Klamath, gcc version 2.96 20000731, GNU assembler version 2.10.90 using BFD version 2.10.0.18) the fldl instruction to load BATMARGIN goes SOMETIMES (but reproducable) wrong (the register is filled with -NaN iso 1.5 (BATMARGIN)). So replaced this code: size_t newsize = len + h->size * BATMARGIN; */ float batmargin = (float) BATMARGIN; float hnewsize = h->size * batmargin; size_t newsize = len + (size_t) hnewsize; assert(newsize); if (h->free + len < h->maxsize) { /* if there is reserved space, first use the reserved space */ newsize = MIN(newsize, h->maxsize); } if (HEAPextend(h, newsize) < 0) { return 0; } /* fill should solve initialisation problems within valgrind */ memset(h->base+h->free, 0, h->size-h->free); } if (!GDK_ELIMDOUBLES(h)) { if (GDK_STRHASHCREDIT(h) == 0) { /* if credits are gone, we do not hash insert at all */ memcpy(h->base + (*dst = h->free), v, i); h->free += i; /* in this case, we do not round to var_t either */ return *dst; } GDK_STRHASHCREDIT(h)--; } /* insert string in hash table and copy into the heap */ l = (var_t *) (h->base + h->free); *(l++) = ((var_t *) h->base)[off]; ((var_t *) h->base)[off] = h->free; *dst = h->free + sizeof(var_t); h->free += len; memcpy((char *) l, v, i); return *dst;}@-Convert an "" separated string to a GDK string value, checking that the input is correct UTF-8.@c/* UTF-8 encoding is as follows:U-00000000 - U-0000007F: 0xxxxxxxU-00000080 - U-000007FF: 110xxxxx 10xxxxxxU-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxxU-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxxU-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxxU-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx*//* To be correctly coded UTF-8, the sequence should be the shortest possible encoding of the value being encoded. This means that for an encoding of length n+1 (1 <= n <= 5), at least one of the bits in utf8chkmsk[n] should be non-zero (else the encoding could be shorter).*/static int utf8chkmsk[] = { 0x0000007f, 0x00000780, 0x0000f800, 0x001f0000, 0x03e00000, 0x7c000000,};ssize_tGDKstrFromStr(unsigned char *dst, unsigned char *src, ssize_t len){ unsigned char *p = dst, *cur = src, *end = src + len; int escaped = FALSE, mask = 0, n, c, utf8char = 0; /* copy it in, while performing the correct escapes */ /* n is the number of follow-on bytes left in a multi-byte UTF-8 sequence */ for (cur = src, n = 0; cur < end || escaped; cur++) { /* first convert any \ escapes and store value in c */ if (escaped) { switch (*cur) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': /* \ with up to three octal digits */ c = base08(*cur); if (num08(cur[1])) { cur++; c = mult08(c) + base08(*cur); if (num08(cur[1])) { cur++; c = mult08(c) + base08(*cur); /* if three digits, only look at lower 8 bits */ c &= 0377; } } break; case 'x': /* \x with one or two hexadecimal digits */ if (num16(cur[1])) { cur++; c = base16(*cur); if (num16(cur[1])) { cur++; c = mult16(c) + base16(*cur); } } else c = 'x'; break; case 'a': c = '\a'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case '\0': c = '\\'; break; case '\'': case '\\': /* \' and \\ can be handled by the default case */ default: /* unrecognized \ escape, just copy the backslashed character */ c = *cur; break; } escaped = FALSE; } else if (*cur == '\\') { escaped = TRUE; continue; } else { c = *cur; } if (n > 0) { /* we're still expecting follow-up bytes in a UTF-8 sequence */ if ((c & 0xC0) != 0x80) { /* incorrect UTF-8 sequence: byte is not 10xxxxxx */ return -1; } utf8char = (utf8char << 6) | (c & 0x3F); n--; if (n == 0) { /* this was the last byte in the sequence */ if ((utf8char & mask) == 0) { /* incorrect UTF-8 sequence: not shortest possible */ return -1; } } } else if (c >= 0x80) { int m; /* start of multi-byte UTF-8 character */ for (n = 0, m = 0x40; c & m; n++, m >>= 1) ; /* n now is number of 10xxxxxx bytes that should follow */ if (n == 0 || n >= 6) { /* incorrect UTF-8 sequence */ /* n==0: c == 10xxxxxx */ /* n>=6: c == 1111111x */ return -1; } mask = utf8chkmsk[n]; /* collect the Unicode code point in utf8char */ utf8char = c & ~(0xFFC0 >> n); /* remove non-x bits */ } *p++ = c; } if (n > 0) { /* incomplete UTF-8 sequence */ return -1; } *p++ = 0; return len;}intstrFromStr(char *src, int *len, char **dst){ unsigned char *p, *start = NULL, *cur = (unsigned char *) src; ssize_t res; int l = 1, escaped = FALSE; while (GDKisspace(*cur)) cur++; if (*cur != '"') { if (*dst != NULL && *dst != str_nil) { GDKfree(*dst); } *dst = GDKstrdup(str_nil); *len = 2; return strncmp((char *) cur, "nil", 3) ? 0 : (int) (((char *) cur + 3) - src); } /* scout the string to find out its length and whether it was properly quoted */ for (start = ++cur; *cur != '"' || escaped; cur++) { if (*cur == 0) { goto error; } else if (*cur == '\\' && escaped == FALSE) { escaped = TRUE; } else { escaped = FALSE; l++; } } /* alloc new memory */ p = (unsigned char *) *dst; if (p != NULL && (char *) p != str_nil && *len < l) { GDKfree(p); p = NULL; } if (p == NULL || (char *) p == str_nil) p = GDKmalloc(*len = l); *dst = (char *) p; assert(cur - start <= INT_MAX); /* 64bit */ if ((res = GDKstrFromStr((unsigned char *) *dst, start, cur - start)) >= 0) return (int) res; error: if (*dst && *dst != str_nil) GDKfree(*dst); *dst = GDKstrdup(str_nil); *len = 2; return 0;}@-Convert a GDK string value to something printable.@c/*#define printable_chr(ch) ((ch)==0 || GDKisgraph((ch)) || GDKisspace((ch)) || \ GDKisspecial((ch)) || GDKisupperl((ch)) || GDKislowerl((ch)))*//* all but control characters (in range 0 to 31) and DEL */#ifdef ASCII_CHR/* ASCII printable characters */#define printable_chr(ch) (' ' <= (ch) && (ch) <= '~')#else/* everything except ASCII control characters */#define printable_chr(ch) ((' ' <= (ch) && (ch) <= '~') || ((ch) & 0x80) != 0)#endifintstrToStr(char **dst, int *len, char *src){ int l = 1; if (GDK_STRNIL((str) src)) { @:atommem(char,4)@ strcpy(*dst, "nil"); return 3; } else { char *s, *r = (char *) src; int cur = 0, end, sz = 0; for (end = 0; src[end]; end++) if (src[end] == '\t' || src[end] == '\n' || src[end] == '\\' || src[end] == '"') { sz += 2;#ifndef ASCII_CHR } else if (src[end] == (char) '\302' && 0200 <= ((int) src[end + 1] & 0377) && ((int) src[end + 1] & 0377) <= 0237) { /* Unicode control character (code point range U-00000080 through U-0000009F encoded in UTF-8 */ /* for the first one of the two UTF-8 bytes we count a width of 7 and for the second one 1, together that's 8, i.e. the width of two backslash-escaped octal coded characters */ sz += 7;#endif } else if (!printable_chr(src[end])) { sz += 4; } else { sz++; } @:atommem(char,sz+3)@ for (s = *dst; cur < end; cur++) if (r[cur] == '\t') { s[l++] = '\\'; s[l++] = 't'; } else if (r[cur] == '\n') { s[l++] = '\\'; s[l++] = 'n'; } else if (r[cur] == '\\') { s[l++] = '\\'; s[l++] = '\\'; } else if (r[cur] == '"') { s[l++] = '\\'; s[l++] = '"'; } else if (!printable_chr(r[cur])#ifndef ASCII_CHR || (r[cur] == (char) '\302' && 0200 <= ((int) r[cur + 1] & 0377) && ((int) r[cur + 1] & 0377) <= 0237) || (cur > 0 && r[cur - 1] == (char) '\302' && 0200 <= ((int) r[cur] & 0377) && ((int) r[cur] & 0377) <= 0237)#endif ) { sprintf(s + l, "\\%03o", (unsigned char) r[cur]); l += 4; } else { s[l++] = r[cur]; } s[0] = s[l++] = '"'; s[l] = 0; } return l;}strstrRead(str a, stream *s, size_t cnt){ int len; (void) cnt; assert(cnt == 1); if (!stream_readInt(s, &len)) return NULL; if ((a = GDKmalloc(len + 1)) == NULL) return NULL; if (len && stream_read(s, a, len, 1) != 1) { GDKfree(a); return NULL; } a[len] = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -