Skip to content
This repository
Newer
Older
100644 872 lines (763 sloc) 17.504 kb
7d7d3e80 » ferrous26
2012-04-22 Change ownership to The MacRuby Team and update copyrights
1 /*
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
2 * MacRuby Symbols.
3 *
4 * This file is covered by the Ruby license. See COPYING for more details.
7d7d3e80 » ferrous26
2012-04-22 Change ownership to The MacRuby Team and update copyrights
5 *
6 * Copyright (C) 2012, The MacRuby Team. All rights reserved.
95957256 » Laurent Sansonetti
2011-01-15 update copyrights to 2011
7 * Copyright (C) 2010-2011, Apple Inc. All rights reserved.
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
8 */
9
10 #include <wctype.h>
11
d0898dd2 » Laurent Sansonetti
2011-01-08 include/ruby/macruby.h -> macruby_internal.h
12 #include "macruby_internal.h"
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
13 #include "ruby/encoding.h"
14 #include "encoding.h"
15 #include "symbol.h"
16 #include "ruby/node.h"
17 #include "vm.h"
b3f59324 » Laurent Sansonetti
2010-02-28 added NSString primitives to Symbol
18 #include "objc.h"
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
19
20 VALUE rb_cSymbol;
21
3b5da11c » lrz
2011-07-06 better static mutex initialization (thanks Vincent)
22 static pthread_mutex_t local_lock = PTHREAD_MUTEX_INITIALIZER;
d08f39dd » lrz
2011-07-05 fine-grained locking around global hashes
23 #define LOCK() (assert(pthread_mutex_lock(&local_lock) == 0))
24 #define UNLOCK() (assert(pthread_mutex_unlock(&local_lock) == 0))
25
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
26 static CFMutableDictionaryRef sym_id = NULL, id_str = NULL;
27 static long last_id = 0;
28
29 typedef struct {
30 VALUE klass;
41240b43 » Laurent Sansonetti
2010-02-27 misc fixes
31 VALUE str;
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
32 ID id;
33 } rb_sym_t;
34
35 #define RSYM(obj) ((rb_sym_t *)(obj))
36
37 static rb_sym_t *
41240b43 » Laurent Sansonetti
2010-02-27 misc fixes
38 sym_alloc(VALUE str, ID id)
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
39 {
171f9c2a » Laurent Sansonetti
2010-05-11 create symbols from the auto zone, allowing associative references to…
40 rb_sym_t *sym = (rb_sym_t *)xmalloc(sizeof(rb_sym_t));
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
41 assert(rb_cSymbol != 0);
42 sym->klass = rb_cSymbol;
171f9c2a » Laurent Sansonetti
2010-05-11 create symbols from the auto zone, allowing associative references to…
43 GC_WB(&sym->str, str);
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
44 sym->id = id;
45 return sym;
46 }
47
14920942 » Laurent Sansonetti
2010-03-05 better detect if symbols are printable
48 static bool
49 is_identchar(UChar c)
50 {
51 return isalnum(c) || c == '_' || !isascii(c);
52 }
53
4285742f » lrz
2011-06-24 optimize rb_intern()
54 static ID
55 rb_intern_uchars(const UChar *chars, const size_t chars_len, VALUE str)
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
56 {
94e3ea5e » Laurent Sansonetti
2011-01-04 avoid grabbing the uchar buffer twice
57 const unsigned long name_hash = rb_str_hash_uchars(chars, chars_len);
d08f39dd » lrz
2011-07-05 fine-grained locking around global hashes
58 LOCK();
94e3ea5e » Laurent Sansonetti
2011-01-04 avoid grabbing the uchar buffer twice
59 ID id = (ID)CFDictionaryGetValue(sym_id, (const void *)name_hash);
d08f39dd » lrz
2011-07-05 fine-grained locking around global hashes
60 UNLOCK();
94e3ea5e » Laurent Sansonetti
2011-01-04 avoid grabbing the uchar buffer twice
61 if (id != 0) {
62 goto return_id;
4285742f » lrz
2011-06-24 optimize rb_intern()
63 }
64
65 if (str == Qnil) {
66 str = rb_unicode_str_new(chars, chars_len);
67 }
94e3ea5e » Laurent Sansonetti
2011-01-04 avoid grabbing the uchar buffer twice
68
69 rb_sym_t *sym = NULL;
b37c99d0 » Laurent Sansonetti
2010-03-05 better symbols sanitization
70 long pos = 0;
4ee0afb8 » Laurent Sansonetti
2010-02-26 some misc fixes/cleanup
71 if (chars_len > 0) {
b37c99d0 » Laurent Sansonetti
2010-03-05 better symbols sanitization
72 UChar c = chars[0];
4ee0afb8 » Laurent Sansonetti
2010-02-26 some misc fixes/cleanup
73 switch (c) {
74 case '$':
75 id = ID_GLOBAL;
b37c99d0 » Laurent Sansonetti
2010-03-05 better symbols sanitization
76 goto new_id;
4ee0afb8 » Laurent Sansonetti
2010-02-26 some misc fixes/cleanup
77
78 case '@':
b37c99d0 » Laurent Sansonetti
2010-03-05 better symbols sanitization
79 if (chars_len > 1 && chars[1] == '@') {
80 pos++;
4ee0afb8 » Laurent Sansonetti
2010-02-26 some misc fixes/cleanup
81 id = ID_CLASS;
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
82 }
4ee0afb8 » Laurent Sansonetti
2010-02-26 some misc fixes/cleanup
83 else {
84 id = ID_INSTANCE;
85 }
b37c99d0 » Laurent Sansonetti
2010-03-05 better symbols sanitization
86 pos++;
4ee0afb8 » Laurent Sansonetti
2010-02-26 some misc fixes/cleanup
87 break;
88
89 default:
b37c99d0 » Laurent Sansonetti
2010-03-05 better symbols sanitization
90 if (chars_len > 1 && chars[chars_len - 1] == '=') {
4ee0afb8 » Laurent Sansonetti
2010-02-26 some misc fixes/cleanup
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 }
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
107 }
108
b37c99d0 » Laurent Sansonetti
2010-03-05 better symbols sanitization
109 if (pos < chars_len && !isdigit(chars[pos])) {
110 for (; pos < chars_len; pos++) {
14920942 » Laurent Sansonetti
2010-03-05 better detect if symbols are printable
111 if (!is_identchar(chars[pos])) {
112 break;
b37c99d0 » Laurent Sansonetti
2010-03-05 better symbols sanitization
113 }
114 }
115 }
116 if (pos < chars_len) {
117 id = ID_JUNK;
118 }
119
120 new_id:
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
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);
41240b43 » Laurent Sansonetti
2010-02-27 misc fixes
125 sym = sym_alloc(str, id);
d08f39dd » lrz
2011-07-05 fine-grained locking around global hashes
126 LOCK();
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
127 CFDictionarySetValue(sym_id, (const void *)name_hash, (const void *)id);
128 CFDictionarySetValue(id_str, (const void *)id, (const void *)sym);
d08f39dd » lrz
2011-07-05 fine-grained locking around global hashes
129 UNLOCK();
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
130
94e3ea5e » Laurent Sansonetti
2011-01-04 avoid grabbing the uchar buffer twice
131 return_id:
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
132 return id;
133 }
134
4285742f » lrz
2011-06-24 optimize rb_intern()
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
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
142 VALUE
143 rb_id2str(ID id)
144 {
d08f39dd » lrz
2011-07-05 fine-grained locking around global hashes
145 LOCK();
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
146 VALUE sym = (VALUE)CFDictionaryGetValue(id_str, (const void *)id);
d08f39dd » lrz
2011-07-05 fine-grained locking around global hashes
147 UNLOCK();
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
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
41240b43 » Laurent Sansonetti
2010-02-27 misc fixes
165 VALUE str = rb_str_dup(RSYM(sym)->str);
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
166 rb_str_cat(str, "=", 1);
167 rb_intern_str(str);
168
169 // Retry one more time.
d08f39dd » lrz
2011-07-05 fine-grained locking around global hashes
170 LOCK();
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
171 sym = (VALUE)CFDictionaryGetValue(id_str, (const void *)id);
d08f39dd » lrz
2011-07-05 fine-grained locking around global hashes
172 UNLOCK();
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
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 {
4285742f » lrz
2011-06-24 optimize rb_intern()
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);
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
200 }
201
202 ID
203 rb_intern(const char *name)
204 {
4285742f » lrz
2011-06-24 optimize rb_intern()
205 return rb_intern2(name, strlen(name));
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
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 {
41240b43 » Laurent Sansonetti
2010-02-27 misc fixes
223 return rb_str_dup(RSYM(sym)->str);
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
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
e68823cd » Laurent Sansonetti
2010-06-19 trim the parser and command-line parsing from static
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
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
302 void
303 Init_PreSymbol(void)
304 {
305 sym_id = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
d08f39dd » lrz
2011-07-05 fine-grained locking around global hashes
306 assert(sym_id != NULL);
171f9c2a » Laurent Sansonetti
2010-05-11 create symbols from the auto zone, allowing associative references to…
307 id_str = CFDictionaryCreateMutable(NULL, 0, NULL,
308 &kCFTypeDictionaryValueCallBacks);
d08f39dd » lrz
2011-07-05 fine-grained locking around global hashes
309 assert(id_str != NULL);
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
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;
4ee0afb8 » Laurent Sansonetti
2010-02-26 some misc fixes/cleanup
315 VALUE str = rb_str_new2(rb_op_tbl[i].name);
41240b43 » Laurent Sansonetti
2010-02-27 misc fixes
316 rb_sym_t *sym = sym_alloc(str, id);
4ee0afb8 » Laurent Sansonetti
2010-02-26 some misc fixes/cleanup
317 unsigned long name_hash = rb_str_hash(str);
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
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 /*
3d2b5582 » Laurent Sansonetti
2010-03-02 added Symbol#<=>, fixed some bugs in String#<=>
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 /*
ac2e5f60 » Laurent Sansonetti
2010-03-04 added Symbol#casecmp, fixed a bug in String#casecmp
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 /*
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
361 * call-seq:
362 * sym == obj => true or false
5629b0db » ferrous26
2012-03-18 Correct the Symbol#== docstring
363 *
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
364 * Equality---If <i>sym</i> and <i>obj</i> are exactly the same
5629b0db » ferrous26
2012-03-18 Correct the Symbol#== docstring
365 * symbol, returns <code>true</code>.
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
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
41240b43 » Laurent Sansonetti
2010-02-27 misc fixes
383 static bool
14920942 » Laurent Sansonetti
2010-03-05 better detect if symbols are printable
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
41240b43 » Laurent Sansonetti
2010-02-27 misc fixes
420 sym_should_be_escaped(VALUE sym)
421 {
d1673a26 » Laurent Sansonetti
2011-01-05 introduce a better unichar API, which should be as fast as before the…
422 RB_STR_GET_UCHARS(RSYM(sym)->str, chars, chars_len);
41240b43 » Laurent Sansonetti
2010-02-27 misc fixes
423
14920942 » Laurent Sansonetti
2010-03-05 better detect if symbols are printable
424 if (chars_len == 0) {
425 return true;
426 }
427
41240b43 » Laurent Sansonetti
2010-02-27 misc fixes
428 bool escape = false;
429 for (long i = 0; i < chars_len; i++) {
14920942 » Laurent Sansonetti
2010-03-05 better detect if symbols are printable
430 if (!isprint(chars[i])) {
41240b43 » Laurent Sansonetti
2010-02-27 misc fixes
431 escape = true;
432 break;
433 }
434 }
435
14920942 » Laurent Sansonetti
2010-03-05 better detect if symbols are printable
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:
41240b43 » Laurent Sansonetti
2010-02-27 misc fixes
587 return escape;
588 }
589
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
590 static VALUE
591 rsym_inspect(VALUE sym, SEL sel)
592 {
593 VALUE str = rb_str_new2(":");
41240b43 » Laurent Sansonetti
2010-02-27 misc fixes
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 }
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
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 {
dfec2d3e » Laurent Sansonetti
2010-05-08 Symbol#to_proc now generates a Proc that can accept a variable number…
615 ID mid = SYM2ID(sym);
616 rb_vm_block_t *b = rb_vm_create_block_calling_mid(mid);
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
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
f5017871 » Laurent Sansonetti
2010-03-03 added #empty?
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
d13c0441 » Laurent Sansonetti
2010-03-12 added Symbol#[]
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
af1c6516 » Laurent Sansonetti
2010-03-20 added Symbol #upcase, #downcase, #swapcase, #capitalize
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
a8bd277f » Thibault Martin-Lagardette
2010-03-25 Make Symbol NSCoding compliant
731 // Cocoa primitives
732
733 static void *
734 rsym_imp_copy(void *rcv, SEL sel)
735 {
736 return rcv;
737 }
738
b3f59324 » Laurent Sansonetti
2010-02-28 added NSString primitives to Symbol
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
a8bd277f » Thibault Martin-Lagardette
2010-03-25 Make Symbol NSCoding compliant
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
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
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
98864a55 » Laurent Sansonetti
2010-03-24 Symbol must not respond to #to_i and #to_f
783 // Undefine methods defined on NSString.
784 rb_undef_method(rb_cSymbol, "to_i");
785 rb_undef_method(rb_cSymbol, "to_f");
e48fb267 » Watson1978
2010-12-02 will not have the Symbol#to_str.
786 rb_undef_method(rb_cSymbol, "to_str");
98864a55 » Laurent Sansonetti
2010-03-24 Symbol must not respond to #to_i and #to_f
787
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
788 rb_objc_define_method(rb_cSymbol, "==", rsym_equal, 1);
3d2b5582 » Laurent Sansonetti
2010-03-02 added Symbol#<=>, fixed some bugs in String#<=>
789 rb_objc_define_method(rb_cSymbol, "<=>", rsym_cmp, 1);
ac2e5f60 » Laurent Sansonetti
2010-03-04 added Symbol#casecmp, fixed a bug in String#casecmp
790 rb_objc_define_method(rb_cSymbol, "casecmp", rsym_casecmp, 1);
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
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);
f5017871 » Laurent Sansonetti
2010-03-03 added #empty?
799 rb_objc_define_method(rb_cSymbol, "empty?", rsym_empty, 0);
d13c0441 » Laurent Sansonetti
2010-03-12 added Symbol#[]
800 rb_objc_define_method(rb_cSymbol, "[]", rsym_aref, -1);
af1c6516 » Laurent Sansonetti
2010-03-20 added Symbol #upcase, #downcase, #swapcase, #capitalize
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);
b3f59324 » Laurent Sansonetti
2010-02-28 added NSString primitives to Symbol
805
806 // Cocoa primitives.
a8bd277f » Thibault Martin-Lagardette
2010-03-25 Make Symbol NSCoding compliant
807 rb_objc_install_method2((Class)rb_cSymbol, "copy",
808 (IMP)rsym_imp_copy);
b3f59324 » Laurent Sansonetti
2010-02-28 added NSString primitives to Symbol
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);
a8bd277f » Thibault Martin-Lagardette
2010-03-25 Make Symbol NSCoding compliant
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);
19f18d3b » Laurent Sansonetti
2010-02-25 a new Symbol class, unicode-aware + refactored/cleaned symbol generation
819 }
e68823cd » Laurent Sansonetti
2010-06-19 trim the parser and command-line parsing from static
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 }
f7384831 » Laurent Sansonetti
2010-08-03 honor the original string encoding when generating substrings out of …
858
859 VALUE
860 rb_sym_str(VALUE sym)
861 {
862 return RSYM(sym)->str;
863 }
00b147f0 » Laurent Sansonetti
2010-09-29 add basic support for __method__ and __callee__
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.