Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 758 lines (679 sloc) 17.469 kB
5f7de4c finished Hash refactoring
Laurent Sansonetti authored
1 /*
2 * MacRuby extensions to NSDictionary.
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 #import <Foundation/Foundation.h>
10
11 #include "ruby/ruby.h"
12 #include "ruby/node.h"
13 #include "objc.h"
14 #include "vm.h"
ae05921 completed Array refactoring, cleaned out a few things
Laurent Sansonetti authored
15 #include "hash.h"
5f7de4c finished Hash refactoring
Laurent Sansonetti authored
16
17 VALUE rb_cHash;
18 VALUE rb_cNSHash;
19 VALUE rb_cNSMutableHash;
20 static VALUE rb_cCFHash;
21
22 static id
23 to_hash(id hash)
24 {
25 return (id)rb_convert_type((VALUE)hash, T_HASH, "Hash", "to_hash");
26 }
27
28 static id
29 nshash_dup(id rcv, SEL sel)
30 {
31 id dup = [rcv mutableCopy];
32 if (OBJ_TAINTED(rcv)) {
33 OBJ_TAINT(dup);
34 }
35 return dup;
36 }
37
38 static id
39 nshash_clone(id rcv, SEL sel)
40 {
41 id clone = nshash_dup(rcv, 0);
42 if (OBJ_FROZEN(rcv)) {
43 OBJ_FREEZE(clone);
44 }
45 return clone;
46 }
47
48 static id
49 nshash_rehash(id rcv, SEL sel)
50 {
51 NSArray *keys = [rcv allKeys];
52 NSArray *values = [rcv allValues];
53 assert([keys count] == [values count]);
54 [rcv removeAllObjects];
55 for (unsigned i = 0, count = [keys count]; i < count; i++) {
56 [rcv setObject:[values objectAtIndex:i] forKey:[keys objectAtIndex:i]];
57 }
58 return rcv;
59 }
60
61 static id
62 nshash_to_hash(id rcv, SEL sel)
63 {
64 return rcv;
65 }
66
67 static id
68 nshash_to_a(id rcv, SEL sel)
69 {
70 NSMutableArray *ary = [NSMutableArray new];
71 for (id key in rcv) {
72 id value = [rcv objectForKey:key];
73 [ary addObject:[NSArray arrayWithObjects:key, value, nil]];
74 }
75 return ary;
76 }
77
78 static id
79 nshash_inspect(id rcv, SEL sel)
80 {
81 NSMutableString *str = [NSMutableString new];
82 [str appendString:@"{"];
83 for (id key in rcv) {
84 if ([str length] > 1) {
85 [str appendString:@", "];
86 }
87 id value = [rcv objectForKey:key];
88 [str appendString:(NSString *)rb_inspect(OC2RB(key))];
89 [str appendString:@"=>"];
90 [str appendString:(NSString *)rb_inspect(OC2RB(value))];
91 }
92 [str appendString:@"}"];
93 return str;
94 }
95
96 static VALUE
97 nshash_equal(id rcv, SEL sel, id other)
98 {
99 return [rcv isEqualToDictionary:other] ? Qtrue : Qfalse;
100 }
101
ae05921 completed Array refactoring, cleaned out a few things
Laurent Sansonetti authored
102 static inline VALUE
103 nshash_lookup(id rcv, VALUE key)
104 {
105 return OC2RB([rcv objectForKey:RB2OC(key)]);
106 }
107
5f7de4c finished Hash refactoring
Laurent Sansonetti authored
108 static VALUE
109 nshash_aref(id rcv, SEL sel, VALUE key)
110 {
ae05921 completed Array refactoring, cleaned out a few things
Laurent Sansonetti authored
111 return nshash_lookup(rcv, key);
5f7de4c finished Hash refactoring
Laurent Sansonetti authored
112 }
113
114 static VALUE
115 nshash_aset(id rcv, SEL sel, VALUE key, VALUE val)
116 {
117 [rcv setObject:RB2OC(val) forKey:RB2OC(key)];
118 return val;
119 }
120
121 static VALUE
122 nshash_fetch(id rcv, SEL sel, int argc, VALUE *argv)
123 {
124 VALUE key, if_none;
125 rb_scan_args(argc, argv, "11", &key, &if_none);
126
127 const bool block_given = rb_block_given_p();
128 if (block_given && argc == 2) {
129 rb_warn("block supersedes default value argument");
130 }
131
132 id value = [rcv objectForKey:RB2OC(key)];
133 if (value != nil) {
134 return OC2RB(value);
135 }
136 if (block_given) {
137 return rb_yield(key);
138 }
139 if (argc == 1) {
140 rb_raise(rb_eKeyError, "key not found");
141 }
142 return if_none;
143 }
144
145 static VALUE
146 nshash_default(id rcv, SEL sel, int argc, VALUE *argv)
147 {
148 // TODO
149 return Qnil;
150 }
151
152 static VALUE
153 nshash_set_default(id rcv, SEL sel, VALUE default_value)
154 {
155 // TODO
156 return Qnil;
157 }
158
159 static VALUE
160 nshash_default_proc(id rcv, SEL sel)
161 {
162 // Default procs are never possible with NSDictionaries.
163 return Qnil;
164 }
165
166 static VALUE
167 nshash_key(id rcv, SEL sel, VALUE value)
168 {
169 NSArray *keys = [rcv allKeysForObject:RB2OC(value)];
170 if ([keys count] > 0) {
171 return OC2RB([keys objectAtIndex:0]);
172 }
173 return Qnil;
174 }
175
176 static VALUE
177 nshash_index(id rcv, SEL sel, VALUE value)
178 {
179 rb_warn("Hash#index is deprecated; use Hash#key");
180 return nshash_key(rcv, 0, value);
181 }
182
183 static VALUE
184 nshash_size(id rcv, SEL sel)
185 {
186 return LONG2FIX([rcv count]);
187 }
188
189 static VALUE
190 nshash_empty(id rcv, SEL sel)
191 {
192 return [rcv count] == 0 ? Qtrue : Qfalse;
193 }
194
195 static VALUE
196 nshash_each_value(id rcv, SEL sel)
197 {
198 RETURN_ENUMERATOR(rcv, 0, 0);
199 for (id key in rcv) {
200 rb_yield(OC2RB([rcv objectForKey:key]));
ae05921 completed Array refactoring, cleaned out a few things
Laurent Sansonetti authored
201 RETURN_IF_BROKEN();
5f7de4c finished Hash refactoring
Laurent Sansonetti authored
202 }
203 return (VALUE)rcv;
204 }
205
206 static VALUE
207 nshash_each_key(id rcv, SEL sel)
208 {
209 RETURN_ENUMERATOR(rcv, 0, 0);
210 for (id key in rcv) {
211 rb_yield(OC2RB(key));
ae05921 completed Array refactoring, cleaned out a few things
Laurent Sansonetti authored
212 RETURN_IF_BROKEN();
5f7de4c finished Hash refactoring
Laurent Sansonetti authored
213 }
214 return (VALUE)rcv;
215 }
216
217 static VALUE
218 nshash_each_pair(id rcv, SEL sel)
219 {
220 RETURN_ENUMERATOR(rcv, 0, 0);
221 for (id key in rcv) {
222 id value = [rcv objectForKey:key];
223 rb_yield(rb_assoc_new(OC2RB(key), OC2RB(value)));
ae05921 completed Array refactoring, cleaned out a few things
Laurent Sansonetti authored
224 RETURN_IF_BROKEN();
5f7de4c finished Hash refactoring
Laurent Sansonetti authored
225 }
226 return (VALUE)rcv;
227 }
228
229 static id
230 nshash_keys(id rcv, SEL sel)
231 {
232 return [[rcv allKeys] mutableCopy];
233 }
234
235 static id
236 nshash_values(id rcv, SEL sel)
237 {
238 return [[rcv allValues] mutableCopy];
239 }
240
241 static id
242 nshash_values_at(id rcv, SEL sel, int argc, VALUE *argv)
243 {
244 NSMutableArray *ary = [NSMutableArray new];
245 for (int i = 0; i < argc; i++) {
246 id value = [rcv objectForKey:RB2OC(argv[i])];
247 [ary addObject:value];
248 }
249 return ary;
250 }
251
252 static VALUE
253 nshash_shift(id rcv, SEL sel)
254 {
255 if ([rcv count] > 0) {
256 id key = [[rcv keyEnumerator] nextObject];
257 assert(key != NULL);
258 id value = [rcv objectForKey:key];
259 [rcv removeObjectForKey:key];
260 return rb_assoc_new(OC2RB(key), OC2RB(value));
261 }
262 return nshash_default(rcv, 0, 0, NULL);
263 }
264
265 static VALUE
266 nshash_delete(id rcv, SEL sel, VALUE key)
267 {
268 id ockey = RB2OC(key);
269 id value = [rcv objectForKey:ockey];
270 if (value != nil) {
271 [rcv removeObjectForKey:ockey];
272 return OC2RB(value);
273 }
274 if (rb_block_given_p()) {
275 return rb_yield(key);
276 }
277 return Qnil;
278 }
279
280 static VALUE
281 nshash_delete_if(id rcv, SEL sel)
282 {
283 RETURN_ENUMERATOR(rcv, 0, 0);
284 NSMutableArray *ary = [NSMutableArray new];
285 for (id key in rcv) {
286 id value = [rcv objectForKey:key];
287 if (RTEST(rb_yield_values(2, OC2RB(key), OC2RB(value)))) {
288 [ary addObject:key];
289 }
ae05921 completed Array refactoring, cleaned out a few things
Laurent Sansonetti authored
290 RETURN_IF_BROKEN();
5f7de4c finished Hash refactoring
Laurent Sansonetti authored
291 }
292 [rcv removeObjectsForKeys:ary];
293 return (VALUE)rcv;
294 }
295
296 static VALUE
297 nshash_select(id rcv, SEL sel)
298 {
299 RETURN_ENUMERATOR(rcv, 0, 0);
300 NSMutableDictionary *dict = [NSMutableDictionary new];
301 for (id key in rcv) {
302 id value = [rcv objectForKey:key];
303 if (RTEST(rb_yield_values(2, OC2RB(key), OC2RB(value)))) {
304 [dict setObject:value forKey:key];
305 }
ae05921 completed Array refactoring, cleaned out a few things
Laurent Sansonetti authored
306 RETURN_IF_BROKEN();
5f7de4c finished Hash refactoring
Laurent Sansonetti authored
307 }
308 return (VALUE)dict;
309 }
310
311 static VALUE
312 nshash_reject(id rcv, SEL sel)
313 {
314 RETURN_ENUMERATOR(rcv, 0, 0);
315 return nshash_delete_if([rcv mutableCopy], 0);
316 }
317
318 static VALUE
319 nshash_reject_bang(id rcv, SEL sel)
320 {
321 RETURN_ENUMERATOR(rcv, 0, 0);
322 unsigned size = [rcv count];
323 nshash_delete_if(rcv, 0);
324 return size != [rcv count] ? (VALUE)rcv : Qnil;
325 }
326
327 static id
328 nshash_clear(id rcv, SEL sel)
329 {
330 [rcv removeAllObjects];
331 return rcv;
332 }
333
334 static id
335 nshash_update(id rcv, SEL sel, id hash)
336 {
337 hash = to_hash(hash);
338 if (rb_block_given_p()) {
339 for (id key in hash) {
340 id value = [hash objectForKey:key];
341 id old_value = [rcv objectForKey:key];
342 if (old_value != nil) {
343 value = RB2OC(rb_yield_values(3, OC2RB(key), OC2RB(old_value),
344 OC2RB(value)));
345 }
346 [rcv setObject:value forKey:key];
347 }
348 }
349 else {
350 for (id key in hash) {
351 id value = [hash objectForKey:key];
352 [rcv setObject:value forKey:key];
353 }
354 }
355 return rcv;
356 }
357
358 static id
359 nshash_merge(id rcv, SEL sel, id hash)
360 {
361 return nshash_update([rcv mutableCopy], 0, hash);
362 }
363
364 static id
365 nshash_replace(id rcv, SEL sel, id hash)
366 {
367 hash = to_hash(hash);
368 [rcv setDictionary:hash];
369 return rcv;
370 }
371
372 static VALUE
373 nshash_assoc(id rcv, SEL sel, VALUE obj)
374 {
375 for (id key in rcv) {
376 if (rb_equal(OC2RB(key), obj)) {
377 id value = [rcv objectForKey:key];
378 return rb_assoc_new(obj, OC2RB(value));
379 }
380 }
381 return Qnil;
382 }
383
384 static VALUE
385 nshash_rassoc(id rcv, SEL sel, VALUE obj)
386 {
387 for (id key in rcv) {
388 id value = [rcv objectForKey:key];
389 if (rb_equal(OC2RB(value), obj)) {
390 return rb_assoc_new(OC2RB(key), obj);
391 }
392 }
393 return Qnil;
394 }
395
396 static id
397 nshash_flatten(id rcv, SEL sel, int argc, VALUE *argv)
398 {
399 id ary = nshash_to_a(rcv, 0);
400 VALUE tmp;
401 if (argc == 0) {
402 argc = 1;
403 tmp = INT2FIX(1);
404 argv = &tmp;
405 }
406 rb_vm_call((VALUE)ary, sel_registerName("flatten!:"), argc, argv, false);
407 return ary;
408 }
409
410 static VALUE
411 nshash_has_key(id rcv, SEL sel, VALUE key)
412 {
413 return [rcv objectForKey:RB2OC(key)] == nil ? Qfalse : Qtrue;
414 }
415
416 static VALUE
417 nshash_has_value(id rcv, SEL sel, VALUE value)
418 {
419 return [[rcv allKeysForObject:RB2OC(value)] count] == 0 ? Qfalse : Qtrue;
420 }
421
422 static id
423 nshash_compare_by_id(id rcv, SEL sel)
424 {
425 // Not implemented.
426 return rcv;
427 }
428
429 static VALUE
430 nshash_compare_by_id_p(id rcv, SEL sel)
431 {
432 // Not implemented.
433 return Qfalse;
434 }
435
436 void
437 Init_NSDictionary(void)
438 {
439 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
440 rb_cCFHash = (VALUE)objc_getClass("NSCFDictionary");
441 #else
442 rb_cCFHash = (VALUE)objc_getClass("__NSCFDictionary");
443 #endif
444 assert(rb_cCFHash != 0);
445 rb_cNSHash = (VALUE)objc_getClass("NSDictionary");
446 assert(rb_cNSHash != 0);
447 rb_cHash = rb_cNSHash;
448 rb_cNSMutableHash = (VALUE)objc_getClass("NSMutableDictionary");
449 assert(rb_cNSMutableHash != 0);
450
451 rb_include_module(rb_cHash, rb_mEnumerable);
452
453 rb_objc_define_method(rb_cHash, "dup", nshash_dup, 0);
454 rb_objc_define_method(rb_cHash, "clone", nshash_clone, 0);
455 rb_objc_define_method(rb_cHash, "rehash", nshash_rehash, 0);
456 rb_objc_define_method(rb_cHash, "to_hash", nshash_to_hash, 0);
457 rb_objc_define_method(rb_cHash, "to_a", nshash_to_a, 0);
458 rb_objc_define_method(rb_cHash, "to_s", nshash_inspect, 0);
459 rb_objc_define_method(rb_cHash, "inspect", nshash_inspect, 0);
460 rb_objc_define_method(rb_cHash, "==", nshash_equal, 1);
461 rb_objc_define_method(rb_cHash, "eql?", nshash_equal, 1);
462 rb_objc_define_method(rb_cHash, "[]", nshash_aref, 1);
463 rb_objc_define_method(rb_cHash, "[]=", nshash_aset, 2);
464 rb_objc_define_method(rb_cHash, "fetch", nshash_fetch, -1);
465 rb_objc_define_method(rb_cHash, "store", nshash_aset, 2);
466 rb_objc_define_method(rb_cHash, "default", nshash_default, -1);
467 rb_objc_define_method(rb_cHash, "default=", nshash_set_default, 1);
468 rb_objc_define_method(rb_cHash, "default_proc", nshash_default_proc, 0);
469 rb_objc_define_method(rb_cHash, "key", nshash_key, 1);
470 rb_objc_define_method(rb_cHash, "index", nshash_index, 1);
471 rb_objc_define_method(rb_cHash, "size", nshash_size, 0);
472 rb_objc_define_method(rb_cHash, "length", nshash_size, 0);
473 rb_objc_define_method(rb_cHash, "empty?", nshash_empty, 0);
474 rb_objc_define_method(rb_cHash, "each_value", nshash_each_value, 0);
475 rb_objc_define_method(rb_cHash, "each_key", nshash_each_key, 0);
476 rb_objc_define_method(rb_cHash, "each_pair", nshash_each_pair, 0);
477 rb_objc_define_method(rb_cHash, "each", nshash_each_pair, 0);
478 rb_objc_define_method(rb_cHash, "keys", nshash_keys, 0);
479 rb_objc_define_method(rb_cHash, "values", nshash_values, 0);
480 rb_objc_define_method(rb_cHash, "values_at", nshash_values_at, -1);
481 rb_objc_define_method(rb_cHash, "shift", nshash_shift, 0);
482 rb_objc_define_method(rb_cHash, "delete", nshash_delete, 1);
483 rb_objc_define_method(rb_cHash, "delete_if", nshash_delete_if, 0);
484 rb_objc_define_method(rb_cHash, "select", nshash_select, 0);
485 rb_objc_define_method(rb_cHash, "reject", nshash_reject, 0);
486 rb_objc_define_method(rb_cHash, "reject!", nshash_reject_bang, 0);
487 rb_objc_define_method(rb_cHash, "clear", nshash_clear, 0);
488 // XXX: #invert is a private method on NSMutableDictionary, so to not
489 // break things we do not implement it.
490 rb_objc_define_method(rb_cHash, "update", nshash_update, 1);
491 rb_objc_define_method(rb_cHash, "merge!", nshash_update, 1);
492 rb_objc_define_method(rb_cHash, "merge", nshash_merge, 1);
493 rb_objc_define_method(rb_cHash, "replace", nshash_replace, 1);
494 rb_objc_define_method(rb_cHash, "assoc", nshash_assoc, 1);
495 rb_objc_define_method(rb_cHash, "rassoc", nshash_rassoc, 1);
496 rb_objc_define_method(rb_cHash, "flatten", nshash_flatten, -1);
497 rb_objc_define_method(rb_cHash, "include?", nshash_has_key, 1);
498 rb_objc_define_method(rb_cHash, "member?", nshash_has_key, 1);
499 rb_objc_define_method(rb_cHash, "key?", nshash_has_key, 1);
500 rb_objc_define_method(rb_cHash, "has_key?", nshash_has_key, 1);
501 rb_objc_define_method(rb_cHash, "value?", nshash_has_value, 1);
502 rb_objc_define_method(rb_cHash, "has_value?", nshash_has_value, 1);
503 rb_objc_define_method(rb_cHash, "compare_by_identity",
504 nshash_compare_by_id, 0);
505 rb_objc_define_method(rb_cHash, "compare_by_identity?",
506 nshash_compare_by_id_p, 0);
507 }
508
509 // NSDictionary + NSMutableDictionary primitives. These are added automatically
510 // on singleton classes of pure NSDictionaries. Our implementation just calls
511 // the original methods, by tricking the receiver's class.
512
513 #define PREPARE_RCV(x) \
514 Class __old = *(Class *)x; \
515 *(Class *)x = (Class)rb_cCFHash;
516
517 #define RESTORE_RCV(x) \
518 *(Class *)x = __old;
519
520 static unsigned
521 nshash_count(id rcv, SEL sel)
522 {
523 PREPARE_RCV(rcv);
524 const unsigned count = [rcv count];
525 RESTORE_RCV(rcv);
526 return count;
527 }
528
529 static id
530 nshash_keyEnumerator(id rcv, SEL sel)
531 {
532 PREPARE_RCV(rcv);
533 id keys = [rcv allKeys];
534 RESTORE_RCV(rcv);
535 return [keys objectEnumerator];
536 }
537
538 static id
539 nshash_objectForKey(id rcv, SEL sel, id key)
540 {
541 PREPARE_RCV(rcv);
542 id value = [rcv objectForKey:key];
543 RESTORE_RCV(rcv);
544 return value;
545 }
546
547 static void
548 nshash_setObjectForKey(id rcv, SEL sel, id value, id key)
549 {
550 PREPARE_RCV(rcv);
551 [rcv setObject:value forKey:key];
552 RESTORE_RCV(rcv);
553 }
554
555 static void
556 nshash_getObjectsAndKeys(id rcv, SEL sel, id *objs, id *keys)
557 {
558 PREPARE_RCV(rcv);
559 [rcv getObjects:objs andKeys:keys];
560 RESTORE_RCV(rcv);
561 }
562
563 static void
564 nshash_removeObjectForKey(id rcv, SEL sel, id key)
565 {
566 PREPARE_RCV(rcv);
567 [rcv removeObjectForKey:key];
568 RESTORE_RCV(rcv);
569 }
570
571 static void
572 nshash_removeAllObjects(id rcv, SEL sel)
573 {
574 PREPARE_RCV(rcv);
575 [rcv removeAllObjects];
576 RESTORE_RCV(rcv);
577 }
578
579 static bool
580 nshash_isEqual(id rcv, SEL sel, id other)
581 {
582 PREPARE_RCV(rcv);
583 const bool res = [rcv isEqualToDictionary:other];
584 RESTORE_RCV(rcv);
585 return res;
586 }
587
588 static bool
589 nshash_containsObject(id rcv, SEL sel, id value)
590 {
591 PREPARE_RCV(rcv);
592 const bool res = [[rcv allKeysForObject:value] count] > 0;
593 RESTORE_RCV(rcv);
594 return res;
595 }
596
597 void
598 rb_objc_install_hash_primitives(Class klass)
599 {
600 rb_objc_install_method2(klass, "count", (IMP)nshash_count);
601 rb_objc_install_method2(klass, "keyEnumerator", (IMP)nshash_keyEnumerator);
602 rb_objc_install_method2(klass, "objectForKey:", (IMP)nshash_objectForKey);
603 rb_objc_install_method2(klass, "getObjects:andKeys:",
604 (IMP)nshash_getObjectsAndKeys);
605 rb_objc_install_method2(klass, "isEqual:", (IMP)nshash_isEqual);
606 rb_objc_install_method2(klass, "containsObject:",
607 (IMP)nshash_containsObject);
608
609 const bool mutable =
610 class_getSuperclass(klass) == (Class)rb_cNSMutableHash;
611
612 if (mutable) {
613 rb_objc_install_method2(klass, "setObject:forKey:",
614 (IMP)nshash_setObjectForKey);
615 rb_objc_install_method2(klass, "removeObjectForKey:",
616 (IMP)nshash_removeObjectForKey);
617 rb_objc_install_method2(klass, "removeAllObjects",
618 (IMP)nshash_removeAllObjects);
619 }
620
621 //rb_objc_define_method(*(VALUE *)klass, "alloc", hash_alloc, 0);
622 }
ae05921 completed Array refactoring, cleaned out a few things
Laurent Sansonetti authored
623
624 // MRI compatibility API.
625
626 VALUE
627 rb_hash_dup(VALUE rcv)
628 {
629 if (IS_RHASH(rcv)) {
630 return rhash_dup(rcv, 0);
631 }
632 else {
633 return (VALUE)nshash_dup((id)rcv, 0);
634 }
635 }
636
637 void
638 rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
639 {
640 if (IS_RHASH(hash)) {
641 rhash_foreach(hash, func, farg);
642 }
643 else {
644 for (id key in (id)hash) {
645 id value = [(id)hash objectForKey:key];
646 if ((*func)(OC2RB(key), OC2RB(value), farg) == ST_STOP) {
647 break;
648 }
649 }
650 }
651 }
652
653 VALUE
654 rb_hash_lookup(VALUE hash, VALUE key)
655 {
656 if (IS_RHASH(hash)) {
657 VALUE val = rhash_lookup(hash, key);
658 return val == Qundef ? Qnil : val;
659 }
660 else {
661 return nshash_lookup((id)hash, key);
662 }
663 }
664
665 VALUE
666 rb_hash_aref(VALUE hash, VALUE key)
667 {
668 if (IS_RHASH(hash)) {
669 return rhash_aref(hash, 0, key);
670 }
671 else {
672 return nshash_lookup((id)hash, key);
673 }
674 }
675
676 VALUE
677 rb_hash_delete_key(VALUE hash, VALUE key)
678 {
679 if (IS_RHASH(hash)) {
680 rhash_modify(hash);
681 return rhash_delete_key(hash, key);
682 }
683 else {
684 id ockey = RB2OC(key);
685 id value = [(id)hash objectForKey:ockey];
686 if (value != nil) {
687 [(id)hash removeObjectForKey:ockey];
688 return OC2RB(value);
689 }
690 return Qundef;
691 }
692 }
693
694 VALUE
695 rb_hash_delete(VALUE hash, VALUE key)
696 {
697 VALUE val = rb_hash_delete_key(hash, key);
698 if (val != Qundef) {
699 return val;
700 }
701 return Qnil;
702 }
703
704 VALUE
705 rb_hash_aset(VALUE hash, VALUE key, VALUE val)
706 {
707 if (IS_RHASH(hash)) {
708 return rhash_aset(hash, 0, key, val);
709 }
710 else {
711 return nshash_aset((id)hash, 0, key, val);
712 }
713 }
714
715 long
716 rb_hash_size(VALUE hash)
717 {
718 if (IS_RHASH(hash)) {
719 return rhash_len(hash);
720 }
721 else {
722 return [(id)hash count];
723 }
724 }
725
726 VALUE
727 rb_hash_keys(VALUE hash)
728 {
729 if (IS_RHASH(hash)) {
730 return rhash_keys(hash, 0);
731 }
732 else {
733 return (VALUE)nshash_keys((id)hash, 0);
734 }
735 }
736
737 VALUE
738 rb_hash_has_key(VALUE hash, VALUE key)
739 {
740 if (IS_RHASH(hash)) {
741 return rhash_has_key(hash, 0, key);
742 }
743 else {
744 return nshash_has_key((id)hash, 0, key);
745 }
746 }
747
748 VALUE
749 rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
750 {
751 if (IS_RHASH(hash)) {
752 return rhash_set_default(hash, 0, ifnone);
753 }
754 else {
755 return nshash_set_default((id)hash, 0, ifnone);
756 }
757 }
Something went wrong with that request. Please try again.