Ignore:
Timestamp:
Jul 9, 2020, 8:51:43 AM (4 years ago)
Author:
coas-nagasima
Message:

mrubyを2.1.1に更新

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  
    1616typedef struct symbol_name {
    1717  mrb_bool lit : 1;
     18  uint8_t prev;
    1819  uint16_t len;
    1920  const char *name;
    2021} symbol_name;
    2122
    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
    3938
    4039static void
     
    4645}
    4746
     47#ifndef MRB_ENABLE_ALL_SYMBOLS
     48static const char pack_table[] = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
     49
     50static mrb_sym
     51sym_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
     91static const char*
     92sym_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
     110static uint8_t
     111symhash(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
     126static mrb_sym
     127find_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
    48163static mrb_sym
    49164sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
    50165{
    51   khash_t(n2s) *h = mrb->name2sym;
    52   symbol_name *sname = mrb->symtbl; /* symtbl[0] for working memory */
    53   khiter_t k;
    54166  mrb_sym sym;
    55   char *p;
     167  symbol_name *sname;
     168  uint8_t hash;
    56169
    57170  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;
    66173
    67174  /* registering a new symbol */
     
    69176  if (mrb->symcapa < sym) {
    70177    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);
    72179    mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(mrb->symcapa+1));
    73180  }
     
    79186  }
    80187  else {
    81     p = (char *)mrb_malloc(mrb, len+1);
     188    char *p = (char *)mrb_malloc(mrb, len+1);
    82189    memcpy(p, name, len);
    83190    p[len] = 0;
     
    85192    sname->lit = FALSE;
    86193  }
    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;
    90207}
    91208
     
    117234mrb_check_intern(mrb_state *mrb, const char *name, size_t len)
    118235{
    119   khash_t(n2s) *h = mrb->name2sym;
    120   symbol_name *sname = mrb->symtbl;
    121   khiter_t k;
     236  mrb_sym sym;
    122237
    123238  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);
    131241  return mrb_nil_value();
    132242}
     
    135245mrb_check_intern_cstr(mrb_state *mrb, const char *name)
    136246{
    137   return mrb_check_intern(mrb, name, (mrb_int)strlen(name));
     247  return mrb_check_intern(mrb, name, strlen(name));
    138248}
    139249
     
    144254}
    145255
    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 {
     256static const char*
     257sym2name_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;
    150262  if (sym == 0 || mrb->symidx < sym) {
    151263    if (lenp) *lenp = 0;
     
    155267  if (lenp) *lenp = mrb->symtbl[sym].len;
    156268  return mrb->symtbl[sym].name;
     269}
     270
     271MRB_API const char*
     272mrb_sym_name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)
     273{
     274  return sym2name_len(mrb, sym, mrb->symbuf, lenp);
    157275}
    158276
     
    168286  }
    169287  mrb_free(mrb, mrb->symtbl);
    170   kh_destroy(n2s, mrb, mrb->name2sym);
    171288}
    172289
     
    174291mrb_init_symtbl(mrb_state *mrb)
    175292{
    176   mrb->name2sym = kh_init(n2s, mrb);
    177293}
    178294
     
    210326 */
    211327
    212 
    213 /* 15.2.11.3.1  */
    214 /*
    215  *  call-seq:
    216  *     sym == obj   -> true or false
    217  *
    218  *  Equality---If <i>sym</i> and <i>obj</i> are exactly the same
    219  *  symbol, returns <code>true</code>.
    220  */
    221 
    222 static mrb_value
    223 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 
    232328/* 15.2.11.3.2  */
    233329/* 15.2.11.3.3  */
     
    242338 */
    243339static 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);
     340sym_to_s(mrb_state *mrb, mrb_value sym)
     341{
     342  return mrb_sym_str(mrb, mrb_symbol(sym));
    252343}
    253344
     
    388479          case '!': case '?': case '=': ++m;
    389480          default: break;
    390             }
    391481        }
     482      }
    392483      break;
    393484  }
     
    404495  char *sp;
    405496
    406   name = mrb_sym2name_len(mrb, id, &len);
     497  name = mrb_sym_name_len(mrb, id, &len);
    407498  str = mrb_str_new(mrb, 0, len+1);
    408499  sp = RSTRING_PTR(str);
    409   RSTRING_PTR(str)[0] = ':';
     500  sp[0] = ':';
    410501  memcpy(sp+1, name, len);
    411502  mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
    412503  if (!symname_p(name) || strlen(name) != (size_t)len) {
    413     str = mrb_str_dump(mrb, str);
     504    str = mrb_str_inspect(mrb, str);
    414505    sp = RSTRING_PTR(str);
    415506    sp[0] = ':';
    416507    sp[1] = '"';
    417508  }
     509#ifdef MRB_UTF8_STRING
     510  if (SYMBOL_INLINE_P(id)) RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
     511#endif
    418512  return str;
    419513}
    420514
    421515MRB_API mrb_value
    422 mrb_sym2str(mrb_state *mrb, mrb_sym sym)
     516mrb_sym_str(mrb_state *mrb, mrb_sym sym)
    423517{
    424518  mrb_int len;
    425   const char *name = mrb_sym2name_len(mrb, sym, &len);
     519  const char *name = mrb_sym_name_len(mrb, sym, &len);
    426520
    427521  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  }
    428527  return mrb_str_new_static(mrb, name, len);
    429528}
    430529
     530static const char*
     531sym_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
    431548MRB_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   }
     549mrb_sym_name(mrb_state *mrb, mrb_sym sym)
     550{
     551  return sym_name(mrb, sym, FALSE);
     552}
     553
     554MRB_API const char*
     555mrb_sym_dump(mrb_state *mrb, mrb_sym sym)
     556{
     557  return sym_name(mrb, sym, TRUE);
    445558}
    446559
     
    454567
    455568  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();
    457570  sym1 = mrb_symbol(s1);
    458571  sym2 = mrb_symbol(s2);
     
    462575    int retval;
    463576    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);
    467581    len = lesser(len1, len2);
    468582    retval = memcmp(p1, p2, len);
     
    482596  struct RClass *sym;
    483597
    484   mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class);                 /* 15.2.11 */
     598  mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class);  /* 15.2.11 */
    485599  MRB_SET_INSTANCE_TT(sym, MRB_TT_SYMBOL);
    486600  mrb_undef_class_method(mrb,  sym, "new");
    487601
    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.