Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 873 lines (763 sloc) 17.504 kb
7d7d3e8 Mark Rada 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 Mark Rada 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 Laurent Sansonetti better static mutex initialization (thanks Vincent)
lrz authored
22 static pthread_mutex_t local_lock = PTHREAD_MUTEX_INITIALIZER;
d08f39d Laurent Sansonetti fine-grained locking around global hashes
lrz 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
29 typedef struct {
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 wo...
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 wo...
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 Laurent Sansonetti optimize rb_intern()
lrz 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 Laurent Sansonetti fine-grained locking around global hashes
lrz 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 Laurent Sansonetti fine-grained locking around global hashes
lrz authored
60 UNLOCK();
94e3ea5 avoid grabbing the uchar buffer twice
Laurent Sansonetti authored
61 if (id != 0) {
62 goto return_id;
4285742 Laurent Sansonetti optimize rb_intern()
lrz 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 Laurent Sansonetti fine-grained locking around global hashes
lrz 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 Laurent Sansonetti fine-grained locking around global hashes
lrz 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 Laurent Sansonetti optimize rb_intern()
lrz 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 Laurent Sansonetti fine-grained locking around global hashes
lrz 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 Laurent Sansonetti fine-grained locking around global hashes
lrz 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 Laurent Sansonetti fine-grained locking around global hashes
lrz 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 Laurent Sansonetti fine-grained locking around global hashes
lrz 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 Laurent Sansonetti optimize rb_intern()
lrz 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 Laurent Sansonetti optimize rb_intern()
lrz 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 Laurent Sansonetti fine-grained locking around global hashes
lrz authored
306 assert(sym_id != NULL);
171f9c2 create symbols from the auto zone, allowing associative references to wo...
Laurent Sansonetti authored
307 id_str = CFDictionaryCreateMutable(NULL, 0, NULL,
308 &kCFTypeDictionaryValueCallBacks);
d08f39d Laurent Sansonetti fine-grained locking around global hashes
lrz 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 *
329 * str <=> other => -1, 0, +1 or nil
330 *
331 * Compares _sym_ with _other_ in string form.
332 */
333
334 static VALUE
335 rsym_cmp(VALUE sym, SEL sel, VALUE other)
336 {
337 if (TYPE(other) != T_SYMBOL) {
338 return Qnil;
339 }
340 return INT2FIX(rb_str_cmp(RSYM(sym)->str, RSYM(other)->str));
341 }
342
343 /*
ac2e5f6 added Symbol#casecmp, fixed a bug in String#casecmp
Laurent Sansonetti authored
344 * call-seq:
345 *
346 * sym.casecmp(other) => -1, 0, +1 or nil
347 *
348 * Case-insensitive version of <code>Symbol#<=></code>.
349 */
350
351 static VALUE
352 rsym_casecmp(VALUE sym, SEL sel, VALUE other)
353 {
354 if (TYPE(other) != T_SYMBOL) {
355 return Qnil;
356 }
357 return INT2FIX(rb_str_casecmp(RSYM(sym)->str, RSYM(other)->str));
358 }
359
360 /*
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
361 * call-seq:
362 * sym == obj => true or false
5629b0d Mark Rada Correct the Symbol#== docstring
ferrous26 authored
363 *
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
364 * Equality---If <i>sym</i> and <i>obj</i> are exactly the same
5629b0d Mark Rada Correct the Symbol#== docstring
ferrous26 authored
365 * symbol, returns <code>true</code>.
19f18d3 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
Laurent Sansonetti authored
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 re...
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 of...
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 Watson 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 a r...
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.