Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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