Skip to content

HTTPS clone URL

Subversion checkout URL

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