summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2006-09-02 15:05:27 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2006-09-02 15:05:27 +0000
commitccf5372b252a229ddb6693db132edc013419ccdc (patch)
tree2d0619ed60d5749e05e9479c5aa1cab82959266e /string.c
parent2156870525be05f0bd769af141c3f6cff9fff8c4 (diff)
* object.c (Init_Object): move symbol related code to string.c
* string.c (Init_String): Symbol as subclass of String. * parse.y (rb_intern2): handle symbol as strings. * string.c (str_new): substring of symbols are mere strings, not symbols. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10834 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r--string.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/string.c b/string.c
index 05d0d32325..8bb3158917 100644
--- a/string.c
+++ b/string.c
@@ -26,6 +26,7 @@
#endif
VALUE rb_cString;
+VALUE rb_cSymbol;
#define STR_TMPLOCK FL_USER7
#define STR_NOEMBED FL_USER1
@@ -134,6 +135,7 @@ str_new(VALUE klass, const char *ptr, long len)
rb_raise(rb_eArgError, "negative string size (or size too big)");
}
+ if (klass == rb_cSymbol) klass = rb_cString;
str = str_alloc(klass);
if (len > RSTRING_EMBED_LEN_MAX) {
RSTRING(str)->as.heap.aux.capa = len;
@@ -4369,6 +4371,207 @@ rb_str_setter(VALUE val, ID id, VALUE *var)
}
+/**********************************************************************
+ * Document-class: Symbol
+ *
+ * <code>Symbol</code> objects represent names and some strings
+ * inside the Ruby
+ * interpreter. They are generated using the <code>:name</code> and
+ * <code>:"string"</code> literals
+ * syntax, and by the various <code>to_sym</code> methods. The same
+ * <code>Symbol</code> object will be created for a given name or string
+ * for the duration of a program's execution, regardless of the context
+ * or meaning of that name. Thus if <code>Fred</code> is a constant in
+ * one context, a method in another, and a class in a third, the
+ * <code>Symbol</code> <code>:Fred</code> will be the same object in
+ * all three contexts.
+ *
+ * module One
+ * class Fred
+ * end
+ * $f1 = :Fred
+ * end
+ * module Two
+ * Fred = 1
+ * $f2 = :Fred
+ * end
+ * def Fred()
+ * end
+ * $f3 = :Fred
+ * $f1.id #=> 2514190
+ * $f2.id #=> 2514190
+ * $f3.id #=> 2514190
+ *
+ */
+
+
+/*
+ * call-seq:
+ * Symbol.new(str) => new_sym
+ * Symbol.intern(str) => new_sym
+ *
+ * Returns a new symbol corresponding to <i>str</i>.
+ */
+
+static VALUE
+rb_sym_s_intern(VALUE s)
+{
+ if (rb_class_real(s) == rb_cSymbol) {
+ return s;
+ }
+ StringValue(s);
+ return rb_intern2(RSTRING_PTR(s), RSTRING_LEN(s));
+}
+
+/*
+ * call-seq:
+ * sym.to_i => fixnum
+ *
+ * Returns an integer that is unique for each symbol within a
+ * particular execution of a program.
+ *
+ * :fred.to_i #=> 9809
+ * "fred".to_sym.to_i #=> 9809
+ */
+
+static VALUE
+sym_to_i(VALUE sym)
+{
+ ID id = SYM2ID(sym);
+
+ return LONG2FIX(id);
+}
+
+
+/*
+ * call-seq:
+ * sym.inspect => string
+ *
+ * Returns the representation of <i>sym</i> as a symbol literal.
+ *
+ * :fred.inspect #=> ":fred"
+ */
+
+static VALUE
+sym_inspect(VALUE sym)
+{
+ VALUE str;
+
+ str = rb_str_new(0, RSTRING_LEN(sym)+1);
+ RSTRING_PTR(str)[0] = ':';
+ memcpy(RSTRING_PTR(str)+1, RSTRING_PTR(sym), RSTRING_LEN(sym));
+ if (!rb_symname_p(RSTRING_PTR(sym))) {
+ str = rb_str_dump(str);
+ strncpy(RSTRING_PTR(str), ":\"", 2);
+ }
+ return str;
+}
+
+
+/*
+ * call-seq:
+ * sym.id2name => string
+ * sym.to_s => string
+ *
+ * Returns the name or string corresponding to <i>sym</i>.
+ *
+ * :fred.id2name #=> "fred"
+ */
+
+
+static VALUE
+sym_to_s(VALUE sym)
+{
+ return rb_str_new(RSTRING_PTR(sym), RSTRING_LEN(sym));
+}
+
+
+/*
+ * call-seq:
+ * sym.to_sym => sym
+ * sym.intern => sym
+ *
+ * In general, <code>to_sym</code> returns the <code>Symbol</code> corresponding
+ * to an object. As <i>sym</i> is already a symbol, <code>self</code> is returned
+ * in this case.
+ */
+
+static VALUE
+sym_to_sym(VALUE sym)
+{
+ return sym;
+}
+
+static VALUE
+sym_call(VALUE args, VALUE sym)
+{
+ VALUE obj;
+
+ if (RARRAY_LEN(args) < 1) {
+ rb_raise(rb_eArgError, "no receiver given");
+ }
+ obj = RARRAY_PTR(args)[0];
+ return rb_funcall3(obj, (ID)sym,
+ RARRAY_LEN(args) - 1,
+ RARRAY_PTR(args) + 1);
+}
+
+/*
+ * call-seq:
+ * sym.to_proc
+ *
+ * Returns a _Proc_ object which respond to the given method by _sym_.
+ *
+ * (1..3).collect(&:to_s) #=> ["1", "2", "3"]
+ */
+
+static VALUE
+sym_to_proc(VALUE sym)
+{
+ return rb_proc_new(sym_call, (VALUE)SYM2ID(sym));
+}
+
+
+static ID
+str_to_id(VALUE str)
+{
+ if (!RSTRING_PTR(str) || RSTRING_LEN(str) == 0) {
+ rb_raise(rb_eArgError, "empty symbol string");
+ }
+ if (RBASIC(str)->klass == rb_cSymbol)
+ return str;
+ return rb_intern2(RSTRING_PTR(str), RSTRING_LEN(str));
+}
+
+ID
+rb_to_id(VALUE name)
+{
+ VALUE tmp;
+ ID id;
+
+ switch (TYPE(name)) {
+ case T_STRING:
+ return str_to_id(name);
+ case T_FIXNUM:
+ rb_warn("do not use Fixnums as Symbols");
+ id = FIX2LONG(name);
+ if (!rb_id2name(id)) {
+ rb_raise(rb_eArgError, "%ld is not a symbol", id);
+ }
+ break;
+ case T_SYMBOL:
+ id = SYM2ID(name);
+ break;
+ default:
+ tmp = rb_check_string_type(name);
+ if (!NIL_P(tmp)) {
+ return str_to_id(tmp);
+ }
+ rb_raise(rb_eTypeError, "%s is not a symbol", RSTRING_PTR(rb_inspect(name)));
+ }
+ return id;
+}
+
/*
* A <code>String</code> object holds and manipulates an arbitrary sequence of
* bytes, typically representing characters. String objects may be created
@@ -4496,4 +4699,17 @@ Init_String(void)
rb_fs = Qnil;
rb_define_variable("$;", &rb_fs);
rb_define_variable("$-F", &rb_fs);
+
+ rb_cSymbol = rb_define_class("Symbol", rb_cString);
+ rb_define_singleton_method(rb_cSymbol, "all_symbols", rb_sym_all_symbols, 0); /* in parse.y */
+ rb_define_singleton_method(rb_cSymbol, "intern", rb_sym_s_intern, 1);
+ rb_define_singleton_method(rb_cSymbol, "new", rb_sym_s_intern, 1);
+
+ rb_define_method(rb_cSymbol, "to_i", sym_to_i, 0);
+ rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
+ rb_define_method(rb_cSymbol, "to_s", sym_to_s, 0);
+ rb_define_method(rb_cSymbol, "id2name", sym_to_s, 0);
+ rb_define_method(rb_cSymbol, "intern", sym_to_sym, 0);
+ rb_define_method(rb_cSymbol, "to_sym", sym_to_sym, 0);
+ rb_define_method(rb_cSymbol, "to_proc", sym_to_proc, 0);
}