Skip to content
This repository
Newer
Older
100644 707 lines (639 sloc) 16.706 kb
5f7de4c0 »
2010-01-26 finished Hash refactoring
1 /*
2 * MacRuby extensions to NSDictionary.
7d7d3e80 »
2012-04-22 Change ownership to The MacRuby Team and update copyrights
3 *
5f7de4c0 »
2010-01-26 finished Hash refactoring
4 * This file is covered by the Ruby license. See COPYING for more details.
5 *
7d7d3e80 »
2012-04-22 Change ownership to The MacRuby Team and update copyrights
6 * Copyright (C) 2012, The MacRuby Team. All rights reserved.
95957256 »
2011-01-15 update copyrights to 2011
7 * Copyright (C) 2010-2011, Apple Inc. All rights reserved.
5f7de4c0 »
2010-01-26 finished Hash refactoring
8 */
9
10 #import <Foundation/Foundation.h>
11
d0898dd2 »
2011-01-08 include/ruby/macruby.h -> macruby_internal.h
12 #include "macruby_internal.h"
5f7de4c0 »
2010-01-26 finished Hash refactoring
13 #include "ruby/node.h"
14 #include "objc.h"
15 #include "vm.h"
ae059217 »
2010-02-07 completed Array refactoring, cleaned out a few things
16 #include "hash.h"
5f7de4c0 »
2010-01-26 finished Hash refactoring
17
18 VALUE rb_cHash;
19 VALUE rb_cNSHash;
20 VALUE rb_cNSMutableHash;
21
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
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
5f7de4c0 »
2010-01-26 finished Hash refactoring
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 {
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
62 CHECK_MUTABLE(rcv);
5f7de4c0 »
2010-01-26 finished Hash refactoring
63 NSArray *keys = [rcv allKeys];
64 NSArray *values = [rcv allValues];
65 assert([keys count] == [values count]);
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
66 TRY_MOP([rcv removeAllObjects]);
5f7de4c0 »
2010-01-26 finished Hash refactoring
67 for (unsigned i = 0, count = [keys count]; i < count; i++) {
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
68 TRY_MOP([rcv setObject:[values objectAtIndex:i]
69 forKey:[keys objectAtIndex:i]]);
5f7de4c0 »
2010-01-26 finished Hash refactoring
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
be52d2b1 »
2011-01-21 fix a bug in -[NSArray ==:] and -[NSDictionary ==:] where a crash wou…
110 nshash_equal(id rcv, SEL sel, VALUE other)
5f7de4c0 »
2010-01-26 finished Hash refactoring
111 {
be52d2b1 »
2011-01-21 fix a bug in -[NSArray ==:] and -[NSDictionary ==:] where a crash wou…
112 if (TYPE(other) != T_HASH) {
72b8cbff »
2010-09-17 don't raise an exception when comparing an NSDictionary with a non-one
113 return Qfalse;
114 }
be52d2b1 »
2011-01-21 fix a bug in -[NSArray ==:] and -[NSDictionary ==:] where a crash wou…
115 return [rcv isEqualToDictionary:(id)other] ? Qtrue : Qfalse;
5f7de4c0 »
2010-01-26 finished Hash refactoring
116 }
117
ae059217 »
2010-02-07 completed Array refactoring, cleaned out a few things
118 static inline VALUE
119 nshash_lookup(id rcv, VALUE key)
120 {
121 return OC2RB([rcv objectForKey:RB2OC(key)]);
122 }
123
5f7de4c0 »
2010-01-26 finished Hash refactoring
124 static VALUE
125 nshash_aref(id rcv, SEL sel, VALUE key)
126 {
ae059217 »
2010-02-07 completed Array refactoring, cleaned out a few things
127 return nshash_lookup(rcv, key);
5f7de4c0 »
2010-01-26 finished Hash refactoring
128 }
129
130 static VALUE
131 nshash_aset(id rcv, SEL sel, VALUE key, VALUE val)
132 {
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
133 CHECK_MUTABLE(rcv);
134 TRY_MOP([rcv setObject:RB2OC(val) forKey:RB2OC(key)]);
5f7de4c0 »
2010-01-26 finished Hash refactoring
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);
73d6dc08 »
2012-07-06 [fix #124] get rid of uncatchable Objective-C exception, when modify …
216 // TODO: should handle the element which is inserted in iterator block.
217 for (id key in [rcv allKeys]) {
5f7de4c0 »
2010-01-26 finished Hash refactoring
218 rb_yield(OC2RB([rcv objectForKey:key]));
ae059217 »
2010-02-07 completed Array refactoring, cleaned out a few things
219 RETURN_IF_BROKEN();
5f7de4c0 »
2010-01-26 finished Hash refactoring
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);
73d6dc08 »
2012-07-06 [fix #124] get rid of uncatchable Objective-C exception, when modify …
228 // TODO: should handle the element which is inserted in iterator block.
229 for (id key in [rcv allKeys]) {
5f7de4c0 »
2010-01-26 finished Hash refactoring
230 rb_yield(OC2RB(key));
ae059217 »
2010-02-07 completed Array refactoring, cleaned out a few things
231 RETURN_IF_BROKEN();
5f7de4c0 »
2010-01-26 finished Hash refactoring
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);
73d6dc08 »
2012-07-06 [fix #124] get rid of uncatchable Objective-C exception, when modify …
240 // TODO: should handle the element which is inserted in iterator block.
241 for (id key in [rcv allKeys]) {
5f7de4c0 »
2010-01-26 finished Hash refactoring
242 id value = [rcv objectForKey:key];
243 rb_yield(rb_assoc_new(OC2RB(key), OC2RB(value)));
ae059217 »
2010-02-07 completed Array refactoring, cleaned out a few things
244 RETURN_IF_BROKEN();
5f7de4c0 »
2010-01-26 finished Hash refactoring
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])];
8e2d2331 »
2012-07-02 [fix #119] insert kCFNull instead of nil into result of array.
267 if (value == NULL) {
268 value = (id)kCFNull;
269 }
5f7de4c0 »
2010-01-26 finished Hash refactoring
270 [ary addObject:value];
271 }
272 return ary;
273 }
274
275 static VALUE
276 nshash_shift(id rcv, SEL sel)
277 {
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
278 CHECK_MUTABLE(rcv);
5f7de4c0 »
2010-01-26 finished Hash refactoring
279 if ([rcv count] > 0) {
280 id key = [[rcv keyEnumerator] nextObject];
281 assert(key != NULL);
282 id value = [rcv objectForKey:key];
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
283 TRY_MOP([rcv removeObjectForKey:key]);
5f7de4c0 »
2010-01-26 finished Hash refactoring
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 {
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
292 CHECK_MUTABLE(rcv);
5f7de4c0 »
2010-01-26 finished Hash refactoring
293 id ockey = RB2OC(key);
294 id value = [rcv objectForKey:ockey];
295 if (value != nil) {
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
296 TRY_MOP([rcv removeObjectForKey:ockey]);
5f7de4c0 »
2010-01-26 finished Hash refactoring
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 {
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
308 CHECK_MUTABLE(rcv);
5f7de4c0 »
2010-01-26 finished Hash refactoring
309 RETURN_ENUMERATOR(rcv, 0, 0);
310 NSMutableArray *ary = [NSMutableArray new];
7d8fcb42 »
2012-07-06 get rid of uncatchable Objective-C exception in NSDictionary#{delete_…
311 // TODO: should handle the element which is inserted in iterator block.
312 for (id key in [rcv allKeys]) {
5f7de4c0 »
2010-01-26 finished Hash refactoring
313 id value = [rcv objectForKey:key];
314 if (RTEST(rb_yield_values(2, OC2RB(key), OC2RB(value)))) {
315 [ary addObject:key];
316 }
ae059217 »
2010-02-07 completed Array refactoring, cleaned out a few things
317 RETURN_IF_BROKEN();
5f7de4c0 »
2010-01-26 finished Hash refactoring
318 }
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
319 TRY_MOP([rcv removeObjectsForKeys:ary]);
5f7de4c0 »
2010-01-26 finished Hash refactoring
320 return (VALUE)rcv;
321 }
322
323 static VALUE
324 nshash_select(id rcv, SEL sel)
325 {
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
326 CHECK_MUTABLE(rcv);
5f7de4c0 »
2010-01-26 finished Hash refactoring
327 RETURN_ENUMERATOR(rcv, 0, 0);
328 NSMutableDictionary *dict = [NSMutableDictionary new];
7d8fcb42 »
2012-07-06 get rid of uncatchable Objective-C exception in NSDictionary#{delete_…
329 // TODO: should handle the element which is inserted in iterator block.
330 for (id key in [rcv allKeys]) {
5f7de4c0 »
2010-01-26 finished Hash refactoring
331 id value = [rcv objectForKey:key];
332 if (RTEST(rb_yield_values(2, OC2RB(key), OC2RB(value)))) {
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
333 TRY_MOP([dict setObject:value forKey:key]);
5f7de4c0 »
2010-01-26 finished Hash refactoring
334 }
ae059217 »
2010-02-07 completed Array refactoring, cleaned out a few things
335 RETURN_IF_BROKEN();
5f7de4c0 »
2010-01-26 finished Hash refactoring
336 }
337 return (VALUE)dict;
338 }
339
340 static VALUE
13d23d32 »
2012-07-06 add the implementation of NSDictionary#keep_if
341 keep_if(id rcv)
342 {
343 CHECK_MUTABLE(rcv);
344 NSMutableDictionary *dict = [NSMutableDictionary new];
345 // TODO: should handle the element which is inserted in iterator block.
346 for (id key in [rcv allKeys]) {
347 id value = [rcv objectForKey:key];
348 if (RTEST(rb_yield_values(2, OC2RB(key), OC2RB(value)))) {
349 TRY_MOP([dict setObject:value forKey:key]);
350 }
351 RETURN_IF_BROKEN();
352 }
353 TRY_MOP([rcv setDictionary:dict]);
354 return (VALUE)rcv;
355 }
356
357 static VALUE
e50c7575 »
2012-07-06 add the implementation of NSDictionary#select!
358 nshash_select_bang(id rcv, SEL sel)
359 {
360 CHECK_MUTABLE(rcv);
361 RETURN_ENUMERATOR(rcv, 0, 0);
362 const long n = [rcv count];
363
364 keep_if(rcv);
365 if (n == [rcv count]) {
366 return Qnil;
367 }
368 return (VALUE)rcv;
369 }
370
371 static VALUE
13d23d32 »
2012-07-06 add the implementation of NSDictionary#keep_if
372 nshash_keep_if(id rcv, SEL sel)
373 {
374 CHECK_MUTABLE(rcv);
375 RETURN_ENUMERATOR(rcv, 0, 0);
376 keep_if(rcv);
377 return (VALUE)rcv;
378 }
379
380 static VALUE
5f7de4c0 »
2010-01-26 finished Hash refactoring
381 nshash_reject(id rcv, SEL sel)
382 {
383 RETURN_ENUMERATOR(rcv, 0, 0);
384 return nshash_delete_if([rcv mutableCopy], 0);
385 }
386
387 static VALUE
388 nshash_reject_bang(id rcv, SEL sel)
389 {
390 RETURN_ENUMERATOR(rcv, 0, 0);
391 unsigned size = [rcv count];
392 nshash_delete_if(rcv, 0);
393 return size != [rcv count] ? (VALUE)rcv : Qnil;
394 }
395
396 static id
397 nshash_clear(id rcv, SEL sel)
398 {
399 [rcv removeAllObjects];
400 return rcv;
401 }
402
403 static id
404 nshash_update(id rcv, SEL sel, id hash)
405 {
406 hash = to_hash(hash);
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
407 CHECK_MUTABLE(rcv);
5f7de4c0 »
2010-01-26 finished Hash refactoring
408 if (rb_block_given_p()) {
409 for (id key in hash) {
410 id value = [hash objectForKey:key];
411 id old_value = [rcv objectForKey:key];
412 if (old_value != nil) {
413 value = RB2OC(rb_yield_values(3, OC2RB(key), OC2RB(old_value),
414 OC2RB(value)));
415 }
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
416 TRY_MOP([rcv setObject:value forKey:key]);
5f7de4c0 »
2010-01-26 finished Hash refactoring
417 }
418 }
419 else {
420 for (id key in hash) {
421 id value = [hash objectForKey:key];
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
422 TRY_MOP([rcv setObject:value forKey:key]);
5f7de4c0 »
2010-01-26 finished Hash refactoring
423 }
424 }
425 return rcv;
426 }
427
428 static id
429 nshash_merge(id rcv, SEL sel, id hash)
430 {
431 return nshash_update([rcv mutableCopy], 0, hash);
432 }
433
434 static id
435 nshash_replace(id rcv, SEL sel, id hash)
436 {
437 hash = to_hash(hash);
7d2f92b8 »
2010-05-03 raising RuntimeError as in 0.5 in case we try to mutate a non-mutable…
438 CHECK_MUTABLE(rcv);
439 TRY_MOP([rcv setDictionary:hash]);
5f7de4c0 »
2010-01-26 finished Hash refactoring
440 return rcv;
441 }
442
443 static VALUE
444 nshash_assoc(id rcv, SEL sel, VALUE obj)
445 {
446 for (id key in rcv) {
447 if (rb_equal(OC2RB(key), obj)) {
448 id value = [rcv objectForKey:key];
449 return rb_assoc_new(obj, OC2RB(value));
450 }
451 }
452 return Qnil;
453 }
454
455 static VALUE
456 nshash_rassoc(id rcv, SEL sel, VALUE obj)
457 {
458 for (id key in rcv) {
459 id value = [rcv objectForKey:key];
460 if (rb_equal(OC2RB(value), obj)) {
461 return rb_assoc_new(OC2RB(key), obj);
462 }
463 }
464 return Qnil;
465 }
466
467 static id
468 nshash_flatten(id rcv, SEL sel, int argc, VALUE *argv)
469 {
470 id ary = nshash_to_a(rcv, 0);
471 VALUE tmp;
472 if (argc == 0) {
473 argc = 1;
474 tmp = INT2FIX(1);
475 argv = &tmp;
476 }
70ea0b5a »
2010-06-01 per-vm method cache + misc fixes/improvements
477 rb_vm_call((VALUE)ary, sel_registerName("flatten!:"), argc, argv);
5f7de4c0 »
2010-01-26 finished Hash refactoring
478 return ary;
479 }
480
481 static VALUE
482 nshash_has_key(id rcv, SEL sel, VALUE key)
483 {
484 return [rcv objectForKey:RB2OC(key)] == nil ? Qfalse : Qtrue;
485 }
486
487 static VALUE
488 nshash_has_value(id rcv, SEL sel, VALUE value)
489 {
490 return [[rcv allKeysForObject:RB2OC(value)] count] == 0 ? Qfalse : Qtrue;
491 }
492
493 static id
494 nshash_compare_by_id(id rcv, SEL sel)
495 {
496 // Not implemented.
497 return rcv;
498 }
499
500 static VALUE
501 nshash_compare_by_id_p(id rcv, SEL sel)
502 {
503 // Not implemented.
504 return Qfalse;
505 }
506
507 void
508 Init_NSDictionary(void)
509 {
510 rb_cHash = rb_cNSHash;
511 rb_cNSMutableHash = (VALUE)objc_getClass("NSMutableDictionary");
512 assert(rb_cNSMutableHash != 0);
513
514 rb_include_module(rb_cHash, rb_mEnumerable);
515
516 rb_objc_define_method(rb_cHash, "dup", nshash_dup, 0);
517 rb_objc_define_method(rb_cHash, "rehash", nshash_rehash, 0);
518 rb_objc_define_method(rb_cHash, "to_hash", nshash_to_hash, 0);
519 rb_objc_define_method(rb_cHash, "to_a", nshash_to_a, 0);
520 rb_objc_define_method(rb_cHash, "to_s", nshash_inspect, 0);
521 rb_objc_define_method(rb_cHash, "inspect", nshash_inspect, 0);
522 rb_objc_define_method(rb_cHash, "==", nshash_equal, 1);
523 rb_objc_define_method(rb_cHash, "eql?", nshash_equal, 1);
524 rb_objc_define_method(rb_cHash, "[]", nshash_aref, 1);
525 rb_objc_define_method(rb_cHash, "[]=", nshash_aset, 2);
526 rb_objc_define_method(rb_cHash, "fetch", nshash_fetch, -1);
527 rb_objc_define_method(rb_cHash, "store", nshash_aset, 2);
528 rb_objc_define_method(rb_cHash, "default", nshash_default, -1);
529 rb_objc_define_method(rb_cHash, "default=", nshash_set_default, 1);
530 rb_objc_define_method(rb_cHash, "default_proc", nshash_default_proc, 0);
531 rb_objc_define_method(rb_cHash, "key", nshash_key, 1);
532 rb_objc_define_method(rb_cHash, "index", nshash_index, 1);
533 rb_objc_define_method(rb_cHash, "size", nshash_size, 0);
534 rb_objc_define_method(rb_cHash, "length", nshash_size, 0);
535 rb_objc_define_method(rb_cHash, "empty?", nshash_empty, 0);
536 rb_objc_define_method(rb_cHash, "each_value", nshash_each_value, 0);
537 rb_objc_define_method(rb_cHash, "each_key", nshash_each_key, 0);
538 rb_objc_define_method(rb_cHash, "each_pair", nshash_each_pair, 0);
539 rb_objc_define_method(rb_cHash, "each", nshash_each_pair, 0);
540 rb_objc_define_method(rb_cHash, "keys", nshash_keys, 0);
541 rb_objc_define_method(rb_cHash, "values", nshash_values, 0);
542 rb_objc_define_method(rb_cHash, "values_at", nshash_values_at, -1);
543 rb_objc_define_method(rb_cHash, "shift", nshash_shift, 0);
544 rb_objc_define_method(rb_cHash, "delete", nshash_delete, 1);
545 rb_objc_define_method(rb_cHash, "delete_if", nshash_delete_if, 0);
13d23d32 »
2012-07-06 add the implementation of NSDictionary#keep_if
546 rb_objc_define_method(rb_cHash, "keep_if", nshash_keep_if, 0);
5f7de4c0 »
2010-01-26 finished Hash refactoring
547 rb_objc_define_method(rb_cHash, "select", nshash_select, 0);
e50c7575 »
2012-07-06 add the implementation of NSDictionary#select!
548 rb_objc_define_method(rb_cHash, "select!", nshash_select_bang, 0);
5f7de4c0 »
2010-01-26 finished Hash refactoring
549 rb_objc_define_method(rb_cHash, "reject", nshash_reject, 0);
550 rb_objc_define_method(rb_cHash, "reject!", nshash_reject_bang, 0);
551 rb_objc_define_method(rb_cHash, "clear", nshash_clear, 0);
552 // XXX: #invert is a private method on NSMutableDictionary, so to not
553 // break things we do not implement it.
554 rb_objc_define_method(rb_cHash, "update", nshash_update, 1);
555 rb_objc_define_method(rb_cHash, "merge!", nshash_update, 1);
556 rb_objc_define_method(rb_cHash, "merge", nshash_merge, 1);
557 rb_objc_define_method(rb_cHash, "replace", nshash_replace, 1);
558 rb_objc_define_method(rb_cHash, "assoc", nshash_assoc, 1);
559 rb_objc_define_method(rb_cHash, "rassoc", nshash_rassoc, 1);
560 rb_objc_define_method(rb_cHash, "flatten", nshash_flatten, -1);
561 rb_objc_define_method(rb_cHash, "include?", nshash_has_key, 1);
562 rb_objc_define_method(rb_cHash, "member?", nshash_has_key, 1);
563 rb_objc_define_method(rb_cHash, "key?", nshash_has_key, 1);
564 rb_objc_define_method(rb_cHash, "has_key?", nshash_has_key, 1);
565 rb_objc_define_method(rb_cHash, "value?", nshash_has_value, 1);
566 rb_objc_define_method(rb_cHash, "has_value?", nshash_has_value, 1);
567 rb_objc_define_method(rb_cHash, "compare_by_identity",
568 nshash_compare_by_id, 0);
569 rb_objc_define_method(rb_cHash, "compare_by_identity?",
570 nshash_compare_by_id_p, 0);
571 }
572
ae059217 »
2010-02-07 completed Array refactoring, cleaned out a few things
573 // MRI compatibility API.
574
575 VALUE
576 rb_hash_dup(VALUE rcv)
577 {
578 if (IS_RHASH(rcv)) {
579 return rhash_dup(rcv, 0);
580 }
581 else {
582 return (VALUE)nshash_dup((id)rcv, 0);
583 }
584 }
585
586 void
587 rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
588 {
589 if (IS_RHASH(hash)) {
590 rhash_foreach(hash, func, farg);
591 }
592 else {
593 for (id key in (id)hash) {
594 id value = [(id)hash objectForKey:key];
595 if ((*func)(OC2RB(key), OC2RB(value), farg) == ST_STOP) {
596 break;
597 }
598 }
599 }
600 }
601
602 VALUE
603 rb_hash_lookup(VALUE hash, VALUE key)
604 {
605 if (IS_RHASH(hash)) {
606 VALUE val = rhash_lookup(hash, key);
607 return val == Qundef ? Qnil : val;
608 }
609 else {
610 return nshash_lookup((id)hash, key);
611 }
612 }
613
614 VALUE
615 rb_hash_aref(VALUE hash, VALUE key)
616 {
617 if (IS_RHASH(hash)) {
618 return rhash_aref(hash, 0, key);
619 }
620 else {
621 return nshash_lookup((id)hash, key);
622 }
623 }
624
625 VALUE
626 rb_hash_delete_key(VALUE hash, VALUE key)
627 {
628 if (IS_RHASH(hash)) {
629 rhash_modify(hash);
630 return rhash_delete_key(hash, key);
631 }
632 else {
633 id ockey = RB2OC(key);
634 id value = [(id)hash objectForKey:ockey];
635 if (value != nil) {
636 [(id)hash removeObjectForKey:ockey];
637 return OC2RB(value);
638 }
639 return Qundef;
640 }
641 }
642
643 VALUE
644 rb_hash_delete(VALUE hash, VALUE key)
645 {
646 VALUE val = rb_hash_delete_key(hash, key);
647 if (val != Qundef) {
648 return val;
649 }
650 return Qnil;
651 }
652
653 VALUE
654 rb_hash_aset(VALUE hash, VALUE key, VALUE val)
655 {
656 if (IS_RHASH(hash)) {
657 return rhash_aset(hash, 0, key, val);
658 }
659 else {
660 return nshash_aset((id)hash, 0, key, val);
661 }
662 }
663
664 long
665 rb_hash_size(VALUE hash)
666 {
667 if (IS_RHASH(hash)) {
668 return rhash_len(hash);
669 }
670 else {
671 return [(id)hash count];
672 }
673 }
674
675 VALUE
676 rb_hash_keys(VALUE hash)
677 {
678 if (IS_RHASH(hash)) {
679 return rhash_keys(hash, 0);
680 }
681 else {
682 return (VALUE)nshash_keys((id)hash, 0);
683 }
684 }
685
686 VALUE
687 rb_hash_has_key(VALUE hash, VALUE key)
688 {
689 if (IS_RHASH(hash)) {
690 return rhash_has_key(hash, 0, key);
691 }
692 else {
693 return nshash_has_key((id)hash, 0, key);
694 }
695 }
696
697 VALUE
698 rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
699 {
700 if (IS_RHASH(hash)) {
701 return rhash_set_default(hash, 0, ifnone);
702 }
703 else {
704 return nshash_set_default((id)hash, 0, ifnone);
705 }
706 }
Something went wrong with that request. Please try again.