Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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