Skip to content
Newer
Older
100644 873 lines (763 sloc) 17.1 KB
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
1 /*
2 * MacRuby Symbols.
3 *
4 * This file is covered by the Ruby license. See COPYING for more details.
5 *
9595725 update copyrights to 2011
Laurent Sansonetti authored
6 * Copyright (C) 2010-2011, Apple Inc. All rights reserved.
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
7 */
8
9 #include <wctype.h>
10
d0898dd include/ruby/macruby.h -> macruby_internal.h
Laurent Sansonetti authored
11 #include "macruby_internal.h"
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
12 #include "ruby/encoding.h"
13 #include "encoding.h"
14 #include "symbol.h"
15 #include "ruby/node.h"
16 #include "vm.h"
b3f5932 added NSString primitives to Symbol
Laurent Sansonetti authored
17 #include "objc.h"
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
18
19 VALUE rb_cSymbol;
20
3b5da11 better static mutex initialization (thanks Vincent)
Laurent Sansonetti authored
21 static pthread_mutex_t local_lock = PTHREAD_MUTEX_INITIALIZER;
d08f39d fine-grained locking around global hashes
Laurent Sansonetti authored
22 #define LOCK() (assert(pthread_mutex_lock(&local_lock) == 0))
23 #define UNLOCK() (assert(pthread_mutex_unlock(&local_lock) == 0))
24
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
25 static CFMutableDictionaryRef sym_id = NULL, id_str = NULL;
26 static long last_id = 0;
27
28 typedef struct {
29 VALUE klass;
41240b4 misc fixes
Laurent Sansonetti authored
30 VALUE str;
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
31 ID id;
32 } rb_sym_t;
33
34 #define RSYM(obj) ((rb_sym_t *)(obj))
35
36 static rb_sym_t *
41240b4 misc fixes
Laurent Sansonetti authored
37 sym_alloc(VALUE str, ID id)
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
38 {
171f9c2 create symbols from the auto zone, allowing associative references to…
Laurent Sansonetti authored
39 rb_sym_t *sym = (rb_sym_t *)xmalloc(sizeof(rb_sym_t));
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
40 assert(rb_cSymbol != 0);
41 sym->klass = rb_cSymbol;
171f9c2 create symbols from the auto zone, allowing associative references to…
Laurent Sansonetti authored
42 GC_WB(&sym->str, str);
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
43 sym->id = id;
44 return sym;
45 }
46
1492094 better detect if symbols are printable
Laurent Sansonetti authored
47 static bool
48 is_identchar(UChar c)
49 {
50 return isalnum(c) || c == '_' || !isascii(c);
51 }
52
4285742 optimize rb_intern()
Laurent Sansonetti authored
53 static ID
54 rb_intern_uchars(const UChar *chars, const size_t chars_len, VALUE str)
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
55 {
94e3ea5 avoid grabbing the uchar buffer twice
Laurent Sansonetti authored
56 const unsigned long name_hash = rb_str_hash_uchars(chars, chars_len);
d08f39d fine-grained locking around global hashes
Laurent Sansonetti authored
57 LOCK();
94e3ea5 avoid grabbing the uchar buffer twice
Laurent Sansonetti authored
58 ID id = (ID)CFDictionaryGetValue(sym_id, (const void *)name_hash);
d08f39d fine-grained locking around global hashes
Laurent Sansonetti authored
59 UNLOCK();
94e3ea5 avoid grabbing the uchar buffer twice
Laurent Sansonetti authored
60 if (id != 0) {
61 goto return_id;
4285742 optimize rb_intern()
Laurent Sansonetti authored
62 }
63
64 if (str == Qnil) {
65 str = rb_unicode_str_new(chars, chars_len);
66 }
94e3ea5 avoid grabbing the uchar buffer twice
Laurent Sansonetti authored
67
68 rb_sym_t *sym = NULL;
b37c99d better symbols sanitization
Laurent Sansonetti authored
69 long pos = 0;
4ee0afb some misc fixes/cleanup
Laurent Sansonetti authored
70 if (chars_len > 0) {
b37c99d better symbols sanitization
Laurent Sansonetti authored
71 UChar c = chars[0];
4ee0afb some misc fixes/cleanup
Laurent Sansonetti authored
72 switch (c) {
73 case '$':
74 id = ID_GLOBAL;
b37c99d better symbols sanitization
Laurent Sansonetti authored
75 goto new_id;
4ee0afb some misc fixes/cleanup
Laurent Sansonetti authored
76
77 case '@':
b37c99d better symbols sanitization
Laurent Sansonetti authored
78 if (chars_len > 1 && chars[1] == '@') {
79 pos++;
4ee0afb some misc fixes/cleanup
Laurent Sansonetti authored
80 id = ID_CLASS;
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
81 }
4ee0afb some misc fixes/cleanup
Laurent Sansonetti authored
82 else {
83 id = ID_INSTANCE;
84 }
b37c99d better symbols sanitization
Laurent Sansonetti authored
85 pos++;
4ee0afb some misc fixes/cleanup
Laurent Sansonetti authored
86 break;
87
88 default:
b37c99d better symbols sanitization
Laurent Sansonetti authored
89 if (chars_len > 1 && chars[chars_len - 1] == '=') {
4ee0afb some misc fixes/cleanup
Laurent Sansonetti authored
90 // Attribute assignment.
91 id = rb_intern_str(rb_str_substr(str, 0, chars_len - 1));
92 if (!is_attrset_id(id)) {
93 id = rb_id_attrset(id);
94 goto id_register;
95 }
96 id = ID_ATTRSET;
97 }
98 else if (iswupper(c)) {
99 id = ID_CONST;
100 }
101 else {
102 id = ID_LOCAL;
103 }
104 break;
105 }
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
106 }
107
b37c99d better symbols sanitization
Laurent Sansonetti authored
108 if (pos < chars_len && !isdigit(chars[pos])) {
109 for (; pos < chars_len; pos++) {
1492094 better detect if symbols are printable
Laurent Sansonetti authored
110 if (!is_identchar(chars[pos])) {
111 break;
b37c99d better symbols sanitization
Laurent Sansonetti authored
112 }
113 }
114 }
115 if (pos < chars_len) {
116 id = ID_JUNK;
117 }
118
119 new_id:
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
120 id |= ++last_id << ID_SCOPE_SHIFT;
121
122 id_register:
123 //printf("register %s hash %ld id %ld\n", RSTRING_PTR(str), name_hash, id);
41240b4 misc fixes
Laurent Sansonetti authored
124 sym = sym_alloc(str, id);
d08f39d fine-grained locking around global hashes
Laurent Sansonetti authored
125 LOCK();
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
126 CFDictionarySetValue(sym_id, (const void *)name_hash, (const void *)id);
127 CFDictionarySetValue(id_str, (const void *)id, (const void *)sym);
d08f39d fine-grained locking around global hashes
Laurent Sansonetti authored
128 UNLOCK();
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
129
94e3ea5 avoid grabbing the uchar buffer twice
Laurent Sansonetti authored
130 return_id:
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
131 return id;
132 }
133
4285742 optimize rb_intern()
Laurent Sansonetti authored
134 ID
135 rb_intern_str(VALUE str)
136 {
137 RB_STR_GET_UCHARS(str, chars, chars_len);
138 return rb_intern_uchars(chars, chars_len, str);
139 }
140
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
141 VALUE
142 rb_id2str(ID id)
143 {
d08f39d fine-grained locking around global hashes
Laurent Sansonetti authored
144 LOCK();
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
145 VALUE sym = (VALUE)CFDictionaryGetValue(id_str, (const void *)id);
d08f39d fine-grained locking around global hashes
Laurent Sansonetti authored
146 UNLOCK();
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
147 if (sym != 0) {
148 //printf("lookup %ld -> %s\n", id, rb_sym2name(sym));
149 return sym;
150 }
151
152 if (is_attrset_id(id)) {
153 // Attribute assignment.
154 ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
155
156 while ((sym = rb_id2str(id2)) == 0) {
157 if (!is_local_id(id2)) {
158 //printf("lookup %ld -> FAIL\n", id);
159 return 0;
160 }
161 id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
162 }
163
41240b4 misc fixes
Laurent Sansonetti authored
164 VALUE str = rb_str_dup(RSYM(sym)->str);
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
165 rb_str_cat(str, "=", 1);
166 rb_intern_str(str);
167
168 // Retry one more time.
d08f39d fine-grained locking around global hashes
Laurent Sansonetti authored
169 LOCK();
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
170 sym = (VALUE)CFDictionaryGetValue(id_str, (const void *)id);
d08f39d fine-grained locking around global hashes
Laurent Sansonetti authored
171 UNLOCK();
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
172 if (sym != 0) {
173 //printf("lookup %ld -> %s\n", id, rb_sym2name(sym));
174 return sym;
175 }
176 }
177 //printf("lookup %ld -> FAIL\n", id);
178 return 0;
179 }
180
181 ID
182 rb_intern3(const char *name, long len, rb_encoding *enc)
183 {
184 VALUE str = rb_enc_str_new(name, len, enc);
185 return rb_intern_str(str);
186 }
187
188 ID
189 rb_intern2(const char *name, long len)
190 {
4285742 optimize rb_intern()
Laurent Sansonetti authored
191 UChar buf[64];
192 UChar *chars = len < 64
193 ? buf
194 : (UChar *)xmalloc(sizeof(UChar) * len);
195 for (long i = 0; i < len; i++) {
196 chars[i] = name[i];
197 }
198 return rb_intern_uchars(chars, len, Qnil);
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
199 }
200
201 ID
202 rb_intern(const char *name)
203 {
4285742 optimize rb_intern()
Laurent Sansonetti authored
204 return rb_intern2(name, strlen(name));
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
205 }
206
207 ID
208 rb_sym2id(VALUE sym)
209 {
210 return RSYM(sym)->id;
211 }
212
213 VALUE
214 rb_name2sym(const char *name)
215 {
216 return rb_id2str(rb_intern(name));
217 }
218
219 VALUE
220 rb_sym_to_s(VALUE sym)
221 {
41240b4 misc fixes
Laurent Sansonetti authored
222 return rb_str_dup(RSYM(sym)->str);
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
223 }
224
225 const char *
226 rb_sym2name(VALUE sym)
227 {
228 return RSTRING_PTR(RSYM(sym)->str);
229 }
230
231 /*
232 * call-seq:
233 * Symbol.all_symbols => array
234 *
235 * Returns an array of all the symbols currently in Ruby's symbol
236 * table.
237 *
238 * Symbol.all_symbols.size #=> 903
239 * Symbol.all_symbols[1,20] #=> [:floor, :ARGV, :Binding, :symlink,
240 * :chown, :EOFError, :$;, :String,
241 * :LOCK_SH, :"setuid?", :$<,
242 * :default_proc, :compact, :extend,
243 * :Tms, :getwd, :$=, :ThreadGroup,
244 * :wait2, :$>]
245 */
246
247 static VALUE
248 rsym_all_symbols(VALUE klass, SEL sel)
249 {
250 VALUE ary = rb_ary_new();
251 const long count = CFDictionaryGetCount(id_str);
252 if (count >= 0) {
253 const void **values = (const void **)malloc(sizeof(void *) * count);
254 CFDictionaryGetKeysAndValues(id_str, NULL, values);
255 for (long i = 0; i < count; i++) {
256 rb_ary_push(ary, (VALUE)values[i]);
257 }
258 free(values);
259 }
260 return ary;
261 }
262
e68823c trim the parser and command-line parsing from static
Laurent Sansonetti authored
263 #if MACRUBY_STATIC
264 struct rb_op_tbl_entry rb_op_tbl[] = {
265 {'+', "+"},
266 {'-', "-"},
267 {'*', "*"},
268 {'/', "/"},
269 {'%', "%"},
270 {'|', "|"},
271 {'^', "^"},
272 {'&', "&"},
273 {'!', "!"},
274 {'>', ">"},
275 {'<', "<"},
276 {'~', "~"},
277 {'!', "!"},
278 {'`', "`"},
279 {334, ".."},
280 {335, "..."},
281 {323, "**"},
282 {321, "+@"},
283 {322, "-@"},
284 {324, "<=>"},
285 {328, ">="},
286 {329, "<="},
287 {325, "=="},
288 {326, "==="},
289 {327, "!="},
290 {332, "=~"},
291 {333, "!~"},
292 {336, "[]"},
293 {337, "[]="},
294 {338, "<<"},
295 {339, ">>"},
296 {340, "::"},
297 {0, NULL}
298 };
299 #endif
300
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
301 void
302 Init_PreSymbol(void)
303 {
304 sym_id = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
d08f39d fine-grained locking around global hashes
Laurent Sansonetti authored
305 assert(sym_id != NULL);
171f9c2 create symbols from the auto zone, allowing associative references to…
Laurent Sansonetti authored
306 id_str = CFDictionaryCreateMutable(NULL, 0, NULL,
307 &kCFTypeDictionaryValueCallBacks);
d08f39d fine-grained locking around global hashes
Laurent Sansonetti authored
308 assert(id_str != NULL);
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
309 last_id = 1000;
310
311 // Pre-register parser symbols.
312 for (int i = 0; rb_op_tbl[i].token != 0; i++) {
313 ID id = rb_op_tbl[i].token;
4ee0afb some misc fixes/cleanup
Laurent Sansonetti authored
314 VALUE str = rb_str_new2(rb_op_tbl[i].name);
41240b4 misc fixes
Laurent Sansonetti authored
315 rb_sym_t *sym = sym_alloc(str, id);
4ee0afb some misc fixes/cleanup
Laurent Sansonetti authored
316 unsigned long name_hash = rb_str_hash(str);
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
317
318 //printf("pre-register %s hash %ld id %ld\n", RSTRING_PTR(str), name_hash, id);
319
320 CFDictionarySetValue(sym_id, (const void *)name_hash, (const void *)id);
321 CFDictionarySetValue(id_str, (const void *)id, (const void *)sym);
322 }
323 }
324
325 /*
3d2b558 added Symbol#<=>, fixed some bugs in String#<=>
Laurent Sansonetti authored
326 * call-seq:
327 *
328 * str <=> other => -1, 0, +1 or nil
329 *
330 * Compares _sym_ with _other_ in string form.
331 */
332
333 static VALUE
334 rsym_cmp(VALUE sym, SEL sel, VALUE other)
335 {
336 if (TYPE(other) != T_SYMBOL) {
337 return Qnil;
338 }
339 return INT2FIX(rb_str_cmp(RSYM(sym)->str, RSYM(other)->str));
340 }
341
342 /*
ac2e5f6 added Symbol#casecmp, fixed a bug in String#casecmp
Laurent Sansonetti authored
343 * call-seq:
344 *
345 * sym.casecmp(other) => -1, 0, +1 or nil
346 *
347 * Case-insensitive version of <code>Symbol#<=></code>.
348 */
349
350 static VALUE
351 rsym_casecmp(VALUE sym, SEL sel, VALUE other)
352 {
353 if (TYPE(other) != T_SYMBOL) {
354 return Qnil;
355 }
356 return INT2FIX(rb_str_casecmp(RSYM(sym)->str, RSYM(other)->str));
357 }
358
359 /*
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
360 * call-seq:
361 * sym == obj => true or false
362 *
363 * Equality---If <i>sym</i> and <i>obj</i> are exactly the same
364 * symbol, returns <code>true</code>. Otherwise, compares them
365 * as strings.
366 */
367
368 static VALUE
369 rsym_equal(VALUE sym, SEL sel, VALUE other)
370 {
371 return sym == other ? Qtrue : Qfalse;
372 }
373
374 /*
375 * call-seq:
376 * sym.inspect => string
377 *
378 * Returns the representation of <i>sym</i> as a symbol literal.
379 *
380 * :fred.inspect #=> ":fred"
381 */
382
41240b4 misc fixes
Laurent Sansonetti authored
383 static bool
1492094 better detect if symbols are printable
Laurent Sansonetti authored
384 is_special_global_name(UChar *ptr, long len)
385 {
386 if (len <= 0) {
387 return false;
388 }
389
390 long pos = 0;
391 switch (ptr[pos]) {
392 case '~': case '*': case '$': case '?': case '!':
393 case '@': case '/': case '\\': case ';': case ',':
394 case '.': case '=': case ':': case '<': case '>':
395 case '\"': case '&': case '`': case '\'': case '+': case '0':
396 pos++;
397 break;
398
399 case '-':
400 pos++;
401 if (pos < len && is_identchar(ptr[pos])) {
402 pos++;
403 }
404 break;
405
406 default:
407 if (!isdigit(ptr[pos])) {
408 return false;
409 }
410 do {
411 pos++;
412 }
413 while (pos < len && isdigit(ptr[pos]));
414 break;
415 }
416 return pos == len;
417 }
418
419 static bool
41240b4 misc fixes
Laurent Sansonetti authored
420 sym_should_be_escaped(VALUE sym)
421 {
d1673a2 introduce a better unichar API, which should be as fast as before the…
Laurent Sansonetti authored
422 RB_STR_GET_UCHARS(RSYM(sym)->str, chars, chars_len);
41240b4 misc fixes
Laurent Sansonetti authored
423
1492094 better detect if symbols are printable
Laurent Sansonetti authored
424 if (chars_len == 0) {
425 return true;
426 }
427
41240b4 misc fixes
Laurent Sansonetti authored
428 bool escape = false;
429 for (long i = 0; i < chars_len; i++) {
1492094 better detect if symbols are printable
Laurent Sansonetti authored
430 if (!isprint(chars[i])) {
41240b4 misc fixes
Laurent Sansonetti authored
431 escape = true;
432 break;
433 }
434 }
435
1492094 better detect if symbols are printable
Laurent Sansonetti authored
436 if (escape) {
437 goto bail;
438 }
439
440 long pos = 0;
441 bool localid = false;
442
443 switch (chars[pos]) {
444 case '\0':
445 escape = true;
446 break;
447
448 case '$':
449 pos++;
450 if (pos < chars_len && is_special_global_name(&chars[pos],
451 chars_len - pos)) {
452 goto bail;
453 }
454 goto id;
455
456 case '@':
457 pos++;
458 if (pos < chars_len && chars[pos] == '@') {
459 pos++;
460 }
461 goto id;
462
463 case '<':
464 pos++;
465 if (pos < chars_len) {
466 if (chars[pos] == '<') {
467 pos++;
468 }
469 else if (chars[pos] == '=') {
470 pos++;
471 if (pos < chars_len && chars[pos] == '>') {
472 pos++;
473 }
474 }
475 }
476 break;
477
478 case '>':
479 pos++;
480 if (pos < chars_len) {
481 if (chars[pos] == '>' || chars[pos] == '=') {
482 pos++;
483 }
484 }
485 break;
486
487 case '=':
488 pos++;
489 if (pos == chars_len) {
490 escape = true;
491 goto bail;
492 }
493 else {
494 if (chars[pos] == '~') {
495 pos++;
496 }
497 else if (chars[pos] == '=') {
498 pos++;
499 if (pos < chars_len && chars[pos] == '=') {
500 pos++;
501 }
502 }
503 else {
504 escape = true;
505 goto bail;
506 }
507 }
508 break;
509
510 case '*':
511 pos++;
512 if (pos < chars_len && chars[pos] == '*') {
513 pos++;
514 }
515 break;
516
517 case '+':
518 case '-':
519 pos++;
520 if (pos < chars_len && chars[pos] == '@') {
521 pos++;
522 }
523 break;
524
525 case '|': case '^': case '&': case '/':
526 case '%': case '~': case '`':
527 pos++;
528 break;
529
530 case '[':
531 pos++;
532 if (pos < chars_len && chars[pos] != ']') {
533 escape = true;
534 goto bail;
535 }
536 pos++;
537 if (pos < chars_len && chars[pos] == '=') {
538 pos++;
539 }
540 break;
541
542 case '!':
543 pos++;
544 if (pos == chars_len) {
545 goto bail;
546 }
547 else {
548 if (chars[pos] == '=' || chars[pos] == '~') {
549 pos++;
550 }
551 else {
552 escape = true;
553 goto bail;
554 }
555 }
556 break;
557
558 default:
559 localid = !isupper(chars[pos]);
560 // fall through
561
562 id:
563 if (pos >= chars_len
564 || (chars[pos] != '_' && !isalpha(chars[pos])
565 && isascii(chars[pos]))) {
566 escape = true;
567 goto bail;
568 }
569 while (pos < chars_len && is_identchar(chars[pos])) {
570 pos++;
571 }
572 if (localid) {
573 if (pos < chars_len
574 && (chars[pos] == '!' || chars[pos] == '?'
575 || chars[pos] == '=')) {
576 pos++;
577 }
578 }
579 break;
580 }
581
582 if (pos < chars_len) {
583 escape = true;
584 }
585
586 bail:
41240b4 misc fixes
Laurent Sansonetti authored
587 return escape;
588 }
589
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
590 static VALUE
591 rsym_inspect(VALUE sym, SEL sel)
592 {
593 VALUE str = rb_str_new2(":");
41240b4 misc fixes
Laurent Sansonetti authored
594 if (sym_should_be_escaped(sym)) {
595 rb_str_concat(str, rb_str_inspect(RSYM(sym)->str));
596 }
597 else {
598 rb_str_concat(str, RSYM(sym)->str);
599 }
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
600 return str;
601 }
602
603 /*
604 * call-seq:
605 * sym.to_proc
606 *
607 * Returns a _Proc_ object which respond to the given method by _sym_.
608 *
609 * (1..3).collect(&:to_s) #=> ["1", "2", "3"]
610 */
611
612 static VALUE
613 rsym_to_proc(VALUE sym, SEL sel)
614 {
dfec2d3 Symbol#to_proc now generates a Proc that can accept a variable number…
Laurent Sansonetti authored
615 ID mid = SYM2ID(sym);
616 rb_vm_block_t *b = rb_vm_create_block_calling_mid(mid);
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
617 return rb_proc_alloc_with_block(rb_cProc, b);
618 }
619
620 /*
621 * call-seq:
622 * sym.id2name => string
623 * sym.to_s => string
624 *
625 * Returns the name or string corresponding to <i>sym</i>.
626 *
627 * :fred.id2name #=> "fred"
628 */
629
630 static VALUE
631 rsym_to_s(VALUE sym, SEL sel)
632 {
633 return rb_sym_to_s(sym);
634 }
635
636 /*
637 * call-seq:
638 * sym.to_sym => sym
639 * sym.intern => sym
640 *
641 * In general, <code>to_sym</code> returns the <code>Symbol</code>
642 * corresponding to an object. As <i>sym</i> is already a symbol,
643 * <code>self</code> is returned in this case.
644 */
645
646 static VALUE
647 rsym_to_sym(VALUE sym, SEL sel)
648 {
649 return sym;
650 }
651
f501787 added #empty?
Laurent Sansonetti authored
652 /*
653 * call-seq:
654 * sym.empty? => true or false
655 *
656 * Returns that _sym_ is :"" or not.
657 */
658
659 static VALUE
660 rsym_empty(VALUE sym, SEL sel)
661 {
662 return rb_str_chars_len(RSYM(sym)->str) == 0 ? Qtrue : Qfalse;
663 }
664
d13c044 added Symbol#[]
Laurent Sansonetti authored
665 /*
666 * call-seq:
667 * sym[idx] => char
668 * sym[b, n] => char
669 *
670 * Returns <code>sym.to_s[]</code>.
671 */
672
673 static VALUE
674 rsym_aref(VALUE sym, SEL sel, int argc, VALUE *argv)
675 {
676 return rstr_aref(RSYM(sym)->str, sel, argc, argv);
677 }
678
af1c651 added Symbol #upcase, #downcase, #swapcase, #capitalize
Laurent Sansonetti authored
679 /*
680 * call-seq:
681 * sym.upcase => symbol
682 *
683 * Same as <code>sym.to_s.upcase.intern</code>.
684 */
685
686 static VALUE
687 rsym_upcase(VALUE sym, SEL sel)
688 {
689 return ID2SYM(rb_intern_str(rstr_upcase(RSYM(sym)->str, sel)));
690 }
691
692 /*
693 * call-seq:
694 * sym.downcase => symbol
695 *
696 * Same as <code>sym.to_s.downcase.intern</code>.
697 */
698
699 static VALUE
700 rsym_downcase(VALUE sym, SEL sel)
701 {
702 return ID2SYM(rb_intern_str(rstr_downcase(RSYM(sym)->str, sel)));
703 }
704
705 /*
706 * call-seq:
707 * sym.capitalize => symbol
708 *
709 * Same as <code>sym.to_s.capitalize.intern</code>.
710 */
711
712 static VALUE
713 rsym_capitalize(VALUE sym, SEL sel)
714 {
715 return ID2SYM(rb_intern_str(rstr_capitalize(RSYM(sym)->str, sel)));
716 }
717
718 /*
719 * call-seq:
720 * sym.swapcase => symbol
721 *
722 * Same as <code>sym.to_s.swapcase.intern</code>.
723 */
724
725 static VALUE
726 rsym_swapcase(VALUE sym, SEL sel)
727 {
728 return ID2SYM(rb_intern_str(rstr_swapcase(RSYM(sym)->str, sel)));
729 }
730
a8bd277 Make Symbol NSCoding compliant
Thibault Martin-Lagardette authored
731 // Cocoa primitives
732
733 static void *
734 rsym_imp_copy(void *rcv, SEL sel)
735 {
736 return rcv;
737 }
738
b3f5932 added NSString primitives to Symbol
Laurent Sansonetti authored
739 static CFIndex
740 rsym_imp_length(void *rcv, SEL sel)
741 {
742 return CFStringGetLength((CFStringRef)RSYM(rcv)->str);
743 }
744
745 static UniChar
746 rsym_imp_characterAtIndex(void *rcv, SEL sel, CFIndex idx)
747 {
748 return CFStringGetCharacterAtIndex((CFStringRef)RSYM(rcv)->str, idx);
749 }
750
a8bd277 Make Symbol NSCoding compliant
Thibault Martin-Lagardette authored
751 #define RSYM_NSCODER_KEY "MRSymbolStr"
752
753 static void
754 rsym_imp_encodeWithCoder(void *rcv, SEL sel, void *coder)
755 {
756 rb_str_NSCoder_encode(coder, RSYM(rcv)->str, RSYM_NSCODER_KEY);
757 }
758
759 static VALUE
760 rsym_imp_initWithCoder(void *rcv, SEL sel, void *coder)
761 {
762 return ID2SYM(rb_intern_str(rb_str_NSCoder_decode(coder, RSYM_NSCODER_KEY)));
763 }
764
765 static Class
766 rsym_imp_classForKeyedArchiver(void *rcv, SEL sel)
767 {
768 return (Class)rb_cSymbol;
769 }
770
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
771 void
772 Init_Symbol(void)
773 {
774 // rb_cSymbol is defined earlier in Init_PreVM().
775 rb_set_class_path(rb_cSymbol, rb_cObject, "Symbol");
776 rb_const_set(rb_cObject, rb_intern("Symbol"), rb_cSymbol);
777
778 rb_undef_alloc_func(rb_cSymbol);
779 rb_undef_method(*(VALUE *)rb_cSymbol, "new");
780 rb_objc_define_method(*(VALUE *)rb_cSymbol, "all_symbols",
781 rsym_all_symbols, 0);
782
98864a5 Symbol must not respond to #to_i and #to_f
Laurent Sansonetti authored
783 // Undefine methods defined on NSString.
784 rb_undef_method(rb_cSymbol, "to_i");
785 rb_undef_method(rb_cSymbol, "to_f");
e48fb26 @Watson1978 will not have the Symbol#to_str.
Watson1978 authored
786 rb_undef_method(rb_cSymbol, "to_str");
98864a5 Symbol must not respond to #to_i and #to_f
Laurent Sansonetti authored
787
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
788 rb_objc_define_method(rb_cSymbol, "==", rsym_equal, 1);
3d2b558 added Symbol#<=>, fixed some bugs in String#<=>
Laurent Sansonetti authored
789 rb_objc_define_method(rb_cSymbol, "<=>", rsym_cmp, 1);
ac2e5f6 added Symbol#casecmp, fixed a bug in String#casecmp
Laurent Sansonetti authored
790 rb_objc_define_method(rb_cSymbol, "casecmp", rsym_casecmp, 1);
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
791 rb_objc_define_method(rb_cSymbol, "eql?", rsym_equal, 1);
792 rb_objc_define_method(rb_cSymbol, "inspect", rsym_inspect, 0);
793 rb_objc_define_method(rb_cSymbol, "to_proc", rsym_to_proc, 0);
794 rb_objc_define_method(rb_cSymbol, "to_s", rsym_to_s, 0);
795 rb_objc_define_method(rb_cSymbol, "id2name", rsym_to_s, 0);
796 rb_objc_define_method(rb_cSymbol, "description", rsym_to_s, 0);
797 rb_objc_define_method(rb_cSymbol, "intern", rsym_to_sym, 0);
798 rb_objc_define_method(rb_cSymbol, "to_sym", rsym_to_sym, 0);
f501787 added #empty?
Laurent Sansonetti authored
799 rb_objc_define_method(rb_cSymbol, "empty?", rsym_empty, 0);
d13c044 added Symbol#[]
Laurent Sansonetti authored
800 rb_objc_define_method(rb_cSymbol, "[]", rsym_aref, -1);
af1c651 added Symbol #upcase, #downcase, #swapcase, #capitalize
Laurent Sansonetti authored
801 rb_objc_define_method(rb_cSymbol, "upcase", rsym_upcase, 0);
802 rb_objc_define_method(rb_cSymbol, "downcase", rsym_downcase, 0);
803 rb_objc_define_method(rb_cSymbol, "swapcase", rsym_swapcase, 0);
804 rb_objc_define_method(rb_cSymbol, "capitalize", rsym_capitalize, 0);
b3f5932 added NSString primitives to Symbol
Laurent Sansonetti authored
805
806 // Cocoa primitives.
a8bd277 Make Symbol NSCoding compliant
Thibault Martin-Lagardette authored
807 rb_objc_install_method2((Class)rb_cSymbol, "copy",
808 (IMP)rsym_imp_copy);
b3f5932 added NSString primitives to Symbol
Laurent Sansonetti authored
809 rb_objc_install_method2((Class)rb_cSymbol, "length",
810 (IMP)rsym_imp_length);
811 rb_objc_install_method2((Class)rb_cSymbol, "characterAtIndex:",
812 (IMP)rsym_imp_characterAtIndex);
a8bd277 Make Symbol NSCoding compliant
Thibault Martin-Lagardette authored
813 rb_objc_install_method2((Class)rb_cSymbol, "encodeWithCoder:",
814 (IMP)rsym_imp_encodeWithCoder);
815 rb_objc_install_method2((Class)rb_cSymbol, "initWithCoder:",
816 (IMP)rsym_imp_initWithCoder);
817 rb_objc_install_method2((Class)rb_cSymbol, "classForKeyedArchiver",
818 (IMP)rsym_imp_classForKeyedArchiver);
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
819 }
e68823c trim the parser and command-line parsing from static
Laurent Sansonetti authored
820
821 int
822 rb_is_const_id(ID id)
823 {
824 return is_const_id(id) ? Qtrue : Qfalse;
825 }
826
827 int
828 rb_is_class_id(ID id)
829 {
830 return is_class_id(id) ? Qtrue : Qfalse;
831 }
832
833 int
834 rb_is_instance_id(ID id)
835 {
836 return is_instance_id(id) ? Qtrue : Qfalse;
837 }
838
839 int
840 rb_is_local_id(ID id)
841 {
842 return is_local_id(id) ? Qtrue : Qfalse;
843 }
844
845 int
846 rb_is_junk_id(ID id)
847 {
848 return is_junk_id(id) ? Qtrue : Qfalse;
849 }
850
851 ID
852 rb_id_attrset(ID id)
853 {
854 id &= ~ID_SCOPE_MASK;
855 id |= ID_ATTRSET;
856 return id;
857 }
f738483 honor the original string encoding when generating substrings out of …
Laurent Sansonetti authored
858
859 VALUE
860 rb_sym_str(VALUE sym)
861 {
862 return RSYM(sym)->str;
863 }
00b147f add basic support for __method__ and __callee__
Laurent Sansonetti authored
864
865 VALUE
866 rb_sel_to_sym(SEL sel)
867 {
868 if (sel == 0) {
869 return Qnil;
870 }
871 return ID2SYM(rb_intern(sel_getName(sel)));
872 }
Something went wrong with that request. Please try again.