Skip to content

HTTPS clone URL

Subversion checkout URL

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