Changeset 439 for EcnlProtoTool/trunk/mruby-2.1.1/src/symbol.c
- Timestamp:
- Jul 9, 2020, 8:51:43 AM (4 years ago)
- Location:
- EcnlProtoTool/trunk/mruby-2.1.1
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/mruby-2.1.1/src/symbol.c
r331 r439 16 16 typedef struct symbol_name { 17 17 mrb_bool lit : 1; 18 uint8_t prev; 18 19 uint16_t len; 19 20 const char *name; 20 21 } symbol_name; 21 22 22 static inline khint_t 23 sym_hash_func(mrb_state *mrb, mrb_sym s) 24 { 25 khint_t h = 0; 26 size_t i, len = mrb->symtbl[s].len; 27 const char *p = mrb->symtbl[s].name; 28 29 for (i=0; i<len; i++) { 30 h = (h << 5) - h + *p++; 31 } 32 return h; 33 } 34 #define sym_hash_equal(mrb,a, b) (mrb->symtbl[a].len == mrb->symtbl[b].len && memcmp(mrb->symtbl[a].name, mrb->symtbl[b].name, mrb->symtbl[a].len) == 0) 35 36 KHASH_DECLARE(n2s, mrb_sym, mrb_sym, FALSE) 37 KHASH_DEFINE (n2s, mrb_sym, mrb_sym, FALSE, sym_hash_func, sym_hash_equal) 38 /* ------------------------------------------------------ */ 23 #define SYMBOL_INLINE_BIT_POS 1 24 #define SYMBOL_INLINE_LOWER_BIT_POS 2 25 #define SYMBOL_INLINE (1 << (SYMBOL_INLINE_BIT_POS - 1)) 26 #define SYMBOL_INLINE_LOWER (1 << (SYMBOL_INLINE_LOWER_BIT_POS - 1)) 27 #define SYMBOL_NORMAL_SHIFT SYMBOL_INLINE_BIT_POS 28 #define SYMBOL_INLINE_SHIFT SYMBOL_INLINE_LOWER_BIT_POS 29 #ifdef MRB_ENABLE_ALL_SYMBOLS 30 # define SYMBOL_INLINE_P(sym) FALSE 31 # define SYMBOL_INLINE_LOWER_P(sym) FALSE 32 # define sym_inline_pack(name, len) 0 33 # define sym_inline_unpack(sym, buf, lenp) NULL 34 #else 35 # define SYMBOL_INLINE_P(sym) ((sym) & SYMBOL_INLINE) 36 # define SYMBOL_INLINE_LOWER_P(sym) ((sym) & SYMBOL_INLINE_LOWER) 37 #endif 39 38 40 39 static void … … 46 45 } 47 46 47 #ifndef MRB_ENABLE_ALL_SYMBOLS 48 static const char pack_table[] = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 49 50 static mrb_sym 51 sym_inline_pack(const char *name, size_t len) 52 { 53 const size_t lower_length_max = (MRB_SYMBOL_BIT - 2) / 5; 54 const size_t mix_length_max = (MRB_SYMBOL_BIT - 2) / 6; 55 56 char c; 57 const char *p; 58 size_t i; 59 mrb_sym sym = 0; 60 mrb_bool lower = TRUE; 61 62 if (len > lower_length_max) return 0; /* too long */ 63 for (i=0; i<len; i++) { 64 uint32_t bits; 65 66 c = name[i]; 67 if (c == 0) return 0; /* NUL in name */ 68 p = strchr(pack_table, (int)c); 69 if (p == 0) return 0; /* non alnum char */ 70 bits = (uint32_t)(p - pack_table)+1; 71 if (bits > 27) lower = FALSE; 72 if (i >= mix_length_max) break; 73 sym |= bits<<(i*6+SYMBOL_INLINE_SHIFT); 74 } 75 if (lower) { 76 sym = 0; 77 for (i=0; i<len; i++) { 78 uint32_t bits; 79 80 c = name[i]; 81 p = strchr(pack_table, (int)c); 82 bits = (uint32_t)(p - pack_table)+1; 83 sym |= bits<<(i*5+SYMBOL_INLINE_SHIFT); 84 } 85 return sym | SYMBOL_INLINE | SYMBOL_INLINE_LOWER; 86 } 87 if (len > mix_length_max) return 0; 88 return sym | SYMBOL_INLINE; 89 } 90 91 static const char* 92 sym_inline_unpack(mrb_sym sym, char *buf, mrb_int *lenp) 93 { 94 int bit_per_char = SYMBOL_INLINE_LOWER_P(sym) ? 5 : 6; 95 int i; 96 97 mrb_assert(SYMBOL_INLINE_P(sym)); 98 99 for (i=0; i<30/bit_per_char; i++) { 100 uint32_t bits = sym>>(i*bit_per_char+SYMBOL_INLINE_SHIFT) & ((1<<bit_per_char)-1); 101 if (bits == 0) break; 102 buf[i] = pack_table[bits-1];; 103 } 104 buf[i] = '\0'; 105 if (lenp) *lenp = i; 106 return buf; 107 } 108 #endif 109 110 static uint8_t 111 symhash(const char *key, size_t len) 112 { 113 uint32_t hash, i; 114 115 for(hash = i = 0; i < len; ++i) { 116 hash += key[i]; 117 hash += (hash << 10); 118 hash ^= (hash >> 6); 119 } 120 hash += (hash << 3); 121 hash ^= (hash >> 11); 122 hash += (hash << 15); 123 return hash & 0xff; 124 } 125 126 static mrb_sym 127 find_symbol(mrb_state *mrb, const char *name, size_t len, uint8_t *hashp) 128 { 129 mrb_sym i; 130 symbol_name *sname; 131 uint8_t hash; 132 133 /* inline symbol */ 134 i = sym_inline_pack(name, len); 135 if (i > 0) return i; 136 137 hash = symhash(name, len); 138 if (hashp) *hashp = hash; 139 140 i = mrb->symhash[hash]; 141 if (i == 0) return 0; 142 do { 143 sname = &mrb->symtbl[i]; 144 if (sname->len == len && memcmp(sname->name, name, len) == 0) { 145 return i<<SYMBOL_NORMAL_SHIFT; 146 } 147 if (sname->prev == 0xff) { 148 i -= 0xff; 149 sname = &mrb->symtbl[i]; 150 while (mrb->symtbl < sname) { 151 if (sname->len == len && memcmp(sname->name, name, len) == 0) { 152 return (mrb_sym)(sname - mrb->symtbl)<<SYMBOL_NORMAL_SHIFT; 153 } 154 sname--; 155 } 156 return 0; 157 } 158 i -= sname->prev; 159 } while (sname->prev > 0); 160 return 0; 161 } 162 48 163 static mrb_sym 49 164 sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit) 50 165 { 51 khash_t(n2s) *h = mrb->name2sym;52 symbol_name *sname = mrb->symtbl; /* symtbl[0] for working memory */53 khiter_t k;54 166 mrb_sym sym; 55 char *p; 167 symbol_name *sname; 168 uint8_t hash; 56 169 57 170 sym_validate_len(mrb, len); 58 if (sname) { 59 sname->lit = lit; 60 sname->len = (uint16_t)len; 61 sname->name = name; 62 k = kh_get(n2s, mrb, h, 0); 63 if (k != kh_end(h)) 64 return kh_key(h, k); 65 } 171 sym = find_symbol(mrb, name, len, &hash); 172 if (sym > 0) return sym; 66 173 67 174 /* registering a new symbol */ … … 69 176 if (mrb->symcapa < sym) { 70 177 if (mrb->symcapa == 0) mrb->symcapa = 100; 71 else mrb->symcapa = (size_t)(mrb->symcapa * 1.2);178 else mrb->symcapa = (size_t)(mrb->symcapa * 6 / 5); 72 179 mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(mrb->symcapa+1)); 73 180 } … … 79 186 } 80 187 else { 81 p = (char *)mrb_malloc(mrb, len+1);188 char *p = (char *)mrb_malloc(mrb, len+1); 82 189 memcpy(p, name, len); 83 190 p[len] = 0; … … 85 192 sname->lit = FALSE; 86 193 } 87 kh_put(n2s, mrb, h, sym); 88 89 return sym; 194 if (mrb->symhash[hash]) { 195 mrb_sym i = sym - mrb->symhash[hash]; 196 if (i > 0xff) 197 sname->prev = 0xff; 198 else 199 sname->prev = i; 200 } 201 else { 202 sname->prev = 0; 203 } 204 mrb->symhash[hash] = sym; 205 206 return sym<<SYMBOL_NORMAL_SHIFT; 90 207 } 91 208 … … 117 234 mrb_check_intern(mrb_state *mrb, const char *name, size_t len) 118 235 { 119 khash_t(n2s) *h = mrb->name2sym; 120 symbol_name *sname = mrb->symtbl; 121 khiter_t k; 236 mrb_sym sym; 122 237 123 238 sym_validate_len(mrb, len); 124 sname->len = (uint16_t)len; 125 sname->name = name; 126 127 k = kh_get(n2s, mrb, h, 0); 128 if (k != kh_end(h)) { 129 return mrb_symbol_value(kh_key(h, k)); 130 } 239 sym = find_symbol(mrb, name, len, NULL); 240 if (sym > 0) return mrb_symbol_value(sym); 131 241 return mrb_nil_value(); 132 242 } … … 135 245 mrb_check_intern_cstr(mrb_state *mrb, const char *name) 136 246 { 137 return mrb_check_intern(mrb, name, (mrb_int)strlen(name));247 return mrb_check_intern(mrb, name, strlen(name)); 138 248 } 139 249 … … 144 254 } 145 255 146 /* lenp must be a pointer to a size_t variable */ 147 MRB_API const char* 148 mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp) 149 { 256 static const char* 257 sym2name_len(mrb_state *mrb, mrb_sym sym, char *buf, mrb_int *lenp) 258 { 259 if (SYMBOL_INLINE_P(sym)) return sym_inline_unpack(sym, buf, lenp); 260 261 sym >>= SYMBOL_NORMAL_SHIFT; 150 262 if (sym == 0 || mrb->symidx < sym) { 151 263 if (lenp) *lenp = 0; … … 155 267 if (lenp) *lenp = mrb->symtbl[sym].len; 156 268 return mrb->symtbl[sym].name; 269 } 270 271 MRB_API const char* 272 mrb_sym_name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp) 273 { 274 return sym2name_len(mrb, sym, mrb->symbuf, lenp); 157 275 } 158 276 … … 168 286 } 169 287 mrb_free(mrb, mrb->symtbl); 170 kh_destroy(n2s, mrb, mrb->name2sym);171 288 } 172 289 … … 174 291 mrb_init_symtbl(mrb_state *mrb) 175 292 { 176 mrb->name2sym = kh_init(n2s, mrb);177 293 } 178 294 … … 210 326 */ 211 327 212 213 /* 15.2.11.3.1 */214 /*215 * call-seq:216 * sym == obj -> true or false217 *218 * Equality---If <i>sym</i> and <i>obj</i> are exactly the same219 * symbol, returns <code>true</code>.220 */221 222 static mrb_value223 sym_equal(mrb_state *mrb, mrb_value sym1)224 {225 mrb_value sym2;226 227 mrb_get_args(mrb, "o", &sym2);228 229 return mrb_bool_value(mrb_obj_equal(mrb, sym1, sym2));230 }231 232 328 /* 15.2.11.3.2 */ 233 329 /* 15.2.11.3.3 */ … … 242 338 */ 243 339 static mrb_value 244 mrb_sym_to_s(mrb_state *mrb, mrb_value sym) 245 { 246 mrb_sym id = mrb_symbol(sym); 247 const char *p; 248 mrb_int len; 249 250 p = mrb_sym2name_len(mrb, id, &len); 251 return mrb_str_new_static(mrb, p, len); 340 sym_to_s(mrb_state *mrb, mrb_value sym) 341 { 342 return mrb_sym_str(mrb, mrb_symbol(sym)); 252 343 } 253 344 … … 388 479 case '!': case '?': case '=': ++m; 389 480 default: break; 390 }391 481 } 482 } 392 483 break; 393 484 } … … 404 495 char *sp; 405 496 406 name = mrb_sym 2name_len(mrb, id, &len);497 name = mrb_sym_name_len(mrb, id, &len); 407 498 str = mrb_str_new(mrb, 0, len+1); 408 499 sp = RSTRING_PTR(str); 409 RSTRING_PTR(str)[0] = ':';500 sp[0] = ':'; 410 501 memcpy(sp+1, name, len); 411 502 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); 412 503 if (!symname_p(name) || strlen(name) != (size_t)len) { 413 str = mrb_str_ dump(mrb, str);504 str = mrb_str_inspect(mrb, str); 414 505 sp = RSTRING_PTR(str); 415 506 sp[0] = ':'; 416 507 sp[1] = '"'; 417 508 } 509 #ifdef MRB_UTF8_STRING 510 if (SYMBOL_INLINE_P(id)) RSTR_SET_ASCII_FLAG(mrb_str_ptr(str)); 511 #endif 418 512 return str; 419 513 } 420 514 421 515 MRB_API mrb_value 422 mrb_sym 2str(mrb_state *mrb, mrb_sym sym)516 mrb_sym_str(mrb_state *mrb, mrb_sym sym) 423 517 { 424 518 mrb_int len; 425 const char *name = mrb_sym 2name_len(mrb, sym, &len);519 const char *name = mrb_sym_name_len(mrb, sym, &len); 426 520 427 521 if (!name) return mrb_undef_value(); /* can't happen */ 522 if (SYMBOL_INLINE_P(sym)) { 523 mrb_value str = mrb_str_new(mrb, name, len); 524 RSTR_SET_ASCII_FLAG(mrb_str_ptr(str)); 525 return str; 526 } 428 527 return mrb_str_new_static(mrb, name, len); 429 528 } 430 529 530 static const char* 531 sym_name(mrb_state *mrb, mrb_sym sym, mrb_bool dump) 532 { 533 mrb_int len; 534 const char *name = mrb_sym_name_len(mrb, sym, &len); 535 536 if (!name) return NULL; 537 if (strlen(name) == (size_t)len && (!dump || symname_p(name))) { 538 return name; 539 } 540 else { 541 mrb_value str = SYMBOL_INLINE_P(sym) ? 542 mrb_str_new(mrb, name, len) : mrb_str_new_static(mrb, name, len); 543 str = mrb_str_dump(mrb, str); 544 return RSTRING_PTR(str); 545 } 546 } 547 431 548 MRB_API const char* 432 mrb_sym2name(mrb_state *mrb, mrb_sym sym) 433 { 434 mrb_int len; 435 const char *name = mrb_sym2name_len(mrb, sym, &len); 436 437 if (!name) return NULL; 438 if (symname_p(name) && strlen(name) == (size_t)len) { 439 return name; 440 } 441 else { 442 mrb_value str = mrb_str_dump(mrb, mrb_str_new_static(mrb, name, len)); 443 return RSTRING_PTR(str); 444 } 549 mrb_sym_name(mrb_state *mrb, mrb_sym sym) 550 { 551 return sym_name(mrb, sym, FALSE); 552 } 553 554 MRB_API const char* 555 mrb_sym_dump(mrb_state *mrb, mrb_sym sym) 556 { 557 return sym_name(mrb, sym, TRUE); 445 558 } 446 559 … … 454 567 455 568 mrb_get_args(mrb, "o", &s2); 456 if ( mrb_type(s2) != MRB_TT_SYMBOL) return mrb_nil_value();569 if (!mrb_symbol_p(s2)) return mrb_nil_value(); 457 570 sym1 = mrb_symbol(s1); 458 571 sym2 = mrb_symbol(s2); … … 462 575 int retval; 463 576 mrb_int len, len1, len2; 464 465 p1 = mrb_sym2name_len(mrb, sym1, &len1); 466 p2 = mrb_sym2name_len(mrb, sym2, &len2); 577 char buf1[8], buf2[8]; 578 579 p1 = sym2name_len(mrb, sym1, buf1, &len1); 580 p2 = sym2name_len(mrb, sym2, buf2, &len2); 467 581 len = lesser(len1, len2); 468 582 retval = memcmp(p1, p2, len); … … 482 596 struct RClass *sym; 483 597 484 mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class); 598 mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class); /* 15.2.11 */ 485 599 MRB_SET_INSTANCE_TT(sym, MRB_TT_SYMBOL); 486 600 mrb_undef_class_method(mrb, sym, "new"); 487 601 488 mrb_define_method(mrb, sym, "===", sym_equal, MRB_ARGS_REQ(1)); /* 15.2.11.3.1 */ 489 mrb_define_method(mrb, sym, "id2name", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.2 */ 490 mrb_define_method(mrb, sym, "to_s", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.3 */ 491 mrb_define_method(mrb, sym, "to_sym", sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */ 492 mrb_define_method(mrb, sym, "inspect", sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */ 493 mrb_define_method(mrb, sym, "<=>", sym_cmp, MRB_ARGS_REQ(1)); 494 } 602 mrb_define_method(mrb, sym, "id2name", sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.2 */ 603 mrb_define_method(mrb, sym, "to_s", sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.3 */ 604 mrb_define_method(mrb, sym, "to_sym", sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */ 605 mrb_define_method(mrb, sym, "inspect", sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */ 606 mrb_define_method(mrb, sym, "<=>", sym_cmp, MRB_ARGS_REQ(1)); 607 }
Note:
See TracChangeset
for help on using the changeset viewer.