summaryrefslogtreecommitdiffhomepage
path: root/src/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/symbol.c')
-rw-r--r--src/symbol.c108
1 files changed, 68 insertions, 40 deletions
diff --git a/src/symbol.c b/src/symbol.c
index c145a4a1a..fd0b116bd 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -5,7 +5,6 @@
*/
#include <ctype.h>
-#include <limits.h>
#include <string.h>
#include "mruby.h"
#include "mruby/khash.h"
@@ -13,7 +12,8 @@
/* ------------------------------------------------------ */
typedef struct symbol_name {
- size_t len;
+ mrb_bool lit : 1;
+ uint16_t len;
const char *name;
} symbol_name;
@@ -31,11 +31,11 @@ sym_hash_func(mrb_state *mrb, const symbol_name s)
}
#define sym_hash_equal(mrb,a, b) (a.len == b.len && memcmp(a.name, b.name, a.len) == 0)
-KHASH_DECLARE(n2s, symbol_name, mrb_sym, 1)
-KHASH_DEFINE (n2s, symbol_name, mrb_sym, 1, sym_hash_func, sym_hash_equal)
+KHASH_DECLARE(n2s, symbol_name, mrb_sym, TRUE)
+KHASH_DEFINE (n2s, symbol_name, mrb_sym, TRUE, sym_hash_func, sym_hash_equal)
/* ------------------------------------------------------ */
-mrb_sym
-mrb_intern2(mrb_state *mrb, const char *name, size_t len)
+static mrb_sym
+sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
{
khash_t(n2s) *h = mrb->name2sym;
symbol_name sname;
@@ -43,46 +43,70 @@ mrb_intern2(mrb_state *mrb, const char *name, size_t len)
mrb_sym sym;
char *p;
+ if (len > UINT16_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long");
+ }
+ sname.lit = lit;
sname.len = len;
sname.name = name;
- k = kh_get(n2s, h, sname);
+ k = kh_get(n2s, mrb, h, sname);
if (k != kh_end(h))
return kh_value(h, k);
sym = ++mrb->symidx;
- p = (char *)mrb_malloc(mrb, len+1);
- memcpy(p, name, len);
- p[len] = 0;
- sname.name = (const char*)p;
- k = kh_put(n2s, h, sname);
+ if (lit) {
+ sname.name = name;
+ }
+ else {
+ p = (char *)mrb_malloc(mrb, len+1);
+ memcpy(p, name, len);
+ p[len] = 0;
+ sname.name = (const char*)p;
+ }
+ k = kh_put(n2s, mrb, h, sname);
kh_value(h, k) = sym;
return sym;
}
mrb_sym
+mrb_intern(mrb_state *mrb, const char *name, size_t len)
+{
+ return sym_intern(mrb, name, len, FALSE);
+}
+
+mrb_sym
+mrb_intern_static(mrb_state *mrb, const char *name, size_t len)
+{
+ return sym_intern(mrb, name, len, TRUE);
+}
+
+mrb_sym
mrb_intern_cstr(mrb_state *mrb, const char *name)
{
- return mrb_intern2(mrb, name, strlen(name));
+ return mrb_intern(mrb, name, strlen(name));
}
mrb_sym
mrb_intern_str(mrb_state *mrb, mrb_value str)
{
- return mrb_intern2(mrb, RSTRING_PTR(str), RSTRING_LEN(str));
+ return mrb_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str));
}
mrb_value
mrb_check_intern(mrb_state *mrb, const char *name, size_t len)
{
khash_t(n2s) *h = mrb->name2sym;
- symbol_name sname;
+ symbol_name sname = { 0 };
khiter_t k;
+ if (len > UINT16_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long");
+ }
sname.len = len;
sname.name = name;
- k = kh_get(n2s, h, sname);
+ k = kh_get(n2s, mrb, h, sname);
if (k != kh_end(h)) {
return mrb_symbol_value(kh_value(h, k));
}
@@ -92,7 +116,7 @@ mrb_check_intern(mrb_state *mrb, const char *name, size_t len)
mrb_value
mrb_check_intern_cstr(mrb_state *mrb, const char *name)
{
- return mrb_check_intern(mrb, name, strlen(name));
+ return mrb_check_intern(mrb, name, (mrb_int)strlen(name));
}
mrb_value
@@ -103,7 +127,7 @@ mrb_check_intern_str(mrb_state *mrb, mrb_value str)
/* lenp must be a pointer to a size_t variable */
const char*
-mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, size_t *lenp)
+mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)
{
khash_t(n2s) *h = mrb->name2sym;
khiter_t k;
@@ -113,12 +137,12 @@ mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, size_t *lenp)
if (kh_exist(h, k)) {
if (kh_value(h, k) == sym) {
sname = kh_key(h, k);
- *lenp = sname.len;
+ if (lenp) *lenp = sname.len;
return sname.name;
}
}
}
- *lenp = 0;
+ if (lenp) *lenp = 0;
return NULL; /* missing */
}
@@ -129,8 +153,14 @@ mrb_free_symtbl(mrb_state *mrb)
khiter_t k;
for (k = kh_begin(h); k != kh_end(h); k++)
- if (kh_exist(h, k)) mrb_free(mrb, (char*)kh_key(h, k).name);
- kh_destroy(n2s,mrb->name2sym);
+ if (kh_exist(h, k)) {
+ symbol_name s = kh_key(h, k);
+
+ if (!s.lit) {
+ mrb_free(mrb, (char*)s.name);
+ }
+ }
+ kh_destroy(n2s, mrb, mrb->name2sym);
}
void
@@ -210,7 +240,7 @@ mrb_sym_to_s(mrb_state *mrb, mrb_value sym)
{
mrb_sym id = mrb_symbol(sym);
const char *p;
- size_t len;
+ mrb_int len;
p = mrb_sym2name_len(mrb, id, &len);
return mrb_str_new_static(mrb, p, len);
@@ -278,7 +308,7 @@ static mrb_bool
symname_p(const char *name)
{
const char *m = name;
- int localid = FALSE;
+ mrb_bool localid = FALSE;
if (!m) return FALSE;
switch (*m) {
@@ -362,16 +392,20 @@ sym_inspect(mrb_state *mrb, mrb_value sym)
{
mrb_value str;
const char *name;
- size_t len;
+ mrb_int len;
mrb_sym id = mrb_symbol(sym);
+ char *sp;
name = mrb_sym2name_len(mrb, id, &len);
str = mrb_str_new(mrb, 0, len+1);
- RSTRING(str)->ptr[0] = ':';
- memcpy(RSTRING(str)->ptr+1, name, len);
+ sp = RSTRING_PTR(str);
+ RSTRING_PTR(str)[0] = ':';
+ memcpy(sp+1, name, len);
if (!symname_p(name) || strlen(name) != len) {
str = mrb_str_dump(mrb, str);
- memcpy(RSTRING(str)->ptr, ":\"", 2);
+ sp = RSTRING_PTR(str);
+ sp[0] = ':';
+ sp[1] = '"';
}
return str;
}
@@ -379,31 +413,26 @@ sym_inspect(mrb_state *mrb, mrb_value sym)
mrb_value
mrb_sym2str(mrb_state *mrb, mrb_sym sym)
{
- size_t len;
+ mrb_int len;
const char *name = mrb_sym2name_len(mrb, sym, &len);
- mrb_value str;
if (!name) return mrb_undef_value(); /* can't happen */
- str = mrb_str_new_static(mrb, name, len);
- if (symname_p(name) && strlen(name) == len) {
- return str;
- }
- return mrb_str_dump(mrb, str);
+ return mrb_str_new_static(mrb, name, len);
}
const char*
mrb_sym2name(mrb_state *mrb, mrb_sym sym)
{
- size_t len;
+ mrb_int len;
const char *name = mrb_sym2name_len(mrb, sym, &len);
if (!name) return NULL;
- if (symname_p(name) && strlen(name) == len) {
+ if (symname_p(name) && strlen(name) == (size_t)len) {
return name;
}
else {
mrb_value str = mrb_str_dump(mrb, mrb_str_new_static(mrb, name, len));
- return RSTRING(str)->ptr;
+ return RSTRING_PTR(str);
}
}
@@ -423,7 +452,7 @@ sym_cmp(mrb_state *mrb, mrb_value s1)
else {
const char *p1, *p2;
int retval;
- size_t len, len1, len2;
+ mrb_int len, len1, len2;
p1 = mrb_sym2name_len(mrb, sym1, &len1);
p2 = mrb_sym2name_len(mrb, sym2, &len2);
@@ -452,5 +481,4 @@ mrb_init_symbol(mrb_state *mrb)
mrb_define_method(mrb, sym, "to_sym", sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */
mrb_define_method(mrb, sym, "inspect", sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */
mrb_define_method(mrb, sym, "<=>", sym_cmp, MRB_ARGS_REQ(1));
- mrb->init_sym = mrb_intern2(mrb, "initialize", 10);
}