Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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 Mark Rada 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 Mark Rada 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 co...
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 co...
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 co...
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 co...
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 would ...
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 would ...
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 would ...
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 co...
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 Watson [fix #124] get rid of uncatchable Objective-C exception, when modify rec...
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 Watson [fix #124] get rid of uncatchable Objective-C exception, when modify rec...
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 Watson [fix #124] get rid of uncatchable Objective-C exception, when modify rec...
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 Watson [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 co...
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 co...
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 co...
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 co...
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 co...
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 co...
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 co...
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 co...
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 co...
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 co...
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 co...
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 co...
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.