mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

mbed-mruby

How to use

Class

Committer:
mzta
Date:
Mon Apr 13 05:20:15 2015 +0000
Revision:
1:8ccd1d494a4b
Parent:
0:158c61bb030f
- code refactoring.; - add SPI, SPISlave, I2C class to mruby-mbed (Incomplete).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mzta 0:158c61bb030f 1 /*
mzta 0:158c61bb030f 2 ** hash.c - Hash class
mzta 0:158c61bb030f 3 **
mzta 0:158c61bb030f 4 ** See Copyright Notice in mruby.h
mzta 0:158c61bb030f 5 */
mzta 0:158c61bb030f 6
mzta 0:158c61bb030f 7 #include "mruby.h"
mzta 0:158c61bb030f 8 #include "mruby/array.h"
mzta 0:158c61bb030f 9 #include "mruby/class.h"
mzta 0:158c61bb030f 10 #include "mruby/hash.h"
mzta 0:158c61bb030f 11 #include "mruby/khash.h"
mzta 0:158c61bb030f 12 #include "mruby/string.h"
mzta 0:158c61bb030f 13 #include "mruby/variable.h"
mzta 0:158c61bb030f 14
mzta 0:158c61bb030f 15 /* a function to get hash value of a float number */
mzta 0:158c61bb030f 16 mrb_int mrb_float_id(mrb_float f);
mzta 0:158c61bb030f 17
mzta 0:158c61bb030f 18 static inline khint_t
mzta 0:158c61bb030f 19 mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key)
mzta 0:158c61bb030f 20 {
mzta 0:158c61bb030f 21 enum mrb_vtype t = mrb_type(key);
mzta 0:158c61bb030f 22 mrb_value hv;
mzta 0:158c61bb030f 23 const char *p;
mzta 0:158c61bb030f 24 mrb_int i, len;
mzta 0:158c61bb030f 25 khint_t h;
mzta 0:158c61bb030f 26
mzta 0:158c61bb030f 27 switch (t) {
mzta 0:158c61bb030f 28 case MRB_TT_STRING:
mzta 0:158c61bb030f 29 p = RSTRING_PTR(key);
mzta 0:158c61bb030f 30 len = RSTRING_LEN(key);
mzta 0:158c61bb030f 31 h = 0;
mzta 0:158c61bb030f 32 for (i=0; i<len; i++) {
mzta 0:158c61bb030f 33 h = (h << 5) - h + *p++;
mzta 0:158c61bb030f 34 }
mzta 0:158c61bb030f 35 return h;
mzta 0:158c61bb030f 36
mzta 0:158c61bb030f 37 case MRB_TT_SYMBOL:
mzta 0:158c61bb030f 38 h = (khint_t)mrb_symbol(key);
mzta 0:158c61bb030f 39 return kh_int_hash_func(mrb, h);
mzta 0:158c61bb030f 40
mzta 0:158c61bb030f 41 case MRB_TT_FIXNUM:
mzta 0:158c61bb030f 42 h = (khint_t)mrb_float_id((mrb_float)mrb_fixnum(key));
mzta 0:158c61bb030f 43 return kh_int_hash_func(mrb, h);
mzta 0:158c61bb030f 44
mzta 0:158c61bb030f 45 case MRB_TT_FLOAT:
mzta 0:158c61bb030f 46 h = (khint_t)mrb_float_id(mrb_float(key));
mzta 0:158c61bb030f 47 return kh_int_hash_func(mrb, h);
mzta 0:158c61bb030f 48
mzta 0:158c61bb030f 49 default:
mzta 0:158c61bb030f 50 hv = mrb_funcall(mrb, key, "hash", 0);
mzta 0:158c61bb030f 51 h = (khint_t)t ^ mrb_fixnum(hv);
mzta 0:158c61bb030f 52 return kh_int_hash_func(mrb, h);
mzta 0:158c61bb030f 53 }
mzta 0:158c61bb030f 54 }
mzta 0:158c61bb030f 55
mzta 0:158c61bb030f 56 static inline khint_t
mzta 0:158c61bb030f 57 mrb_hash_ht_hash_equal(mrb_state *mrb, mrb_value a, mrb_value b)
mzta 0:158c61bb030f 58 {
mzta 0:158c61bb030f 59 enum mrb_vtype t = mrb_type(a);
mzta 0:158c61bb030f 60
mzta 0:158c61bb030f 61 switch (t) {
mzta 0:158c61bb030f 62 case MRB_TT_STRING:
mzta 0:158c61bb030f 63 return mrb_str_equal(mrb, a, b);
mzta 0:158c61bb030f 64
mzta 0:158c61bb030f 65 case MRB_TT_SYMBOL:
mzta 0:158c61bb030f 66 if (mrb_type(b) != MRB_TT_SYMBOL) return FALSE;
mzta 0:158c61bb030f 67 return mrb_symbol(a) == mrb_symbol(b);
mzta 0:158c61bb030f 68
mzta 0:158c61bb030f 69 case MRB_TT_FIXNUM:
mzta 0:158c61bb030f 70 switch (mrb_type(b)) {
mzta 0:158c61bb030f 71 case MRB_TT_FIXNUM:
mzta 0:158c61bb030f 72 return mrb_fixnum(a) == mrb_fixnum(b);
mzta 0:158c61bb030f 73 case MRB_TT_FLOAT:
mzta 0:158c61bb030f 74 return (mrb_float)mrb_fixnum(a) == mrb_float(b);
mzta 0:158c61bb030f 75 default:
mzta 0:158c61bb030f 76 return FALSE;
mzta 0:158c61bb030f 77 }
mzta 0:158c61bb030f 78
mzta 0:158c61bb030f 79 case MRB_TT_FLOAT:
mzta 0:158c61bb030f 80 switch (mrb_type(b)) {
mzta 0:158c61bb030f 81 case MRB_TT_FIXNUM:
mzta 0:158c61bb030f 82 return mrb_float(a) == (mrb_float)mrb_fixnum(b);
mzta 0:158c61bb030f 83 case MRB_TT_FLOAT:
mzta 0:158c61bb030f 84 return mrb_float(a) == mrb_float(b);
mzta 0:158c61bb030f 85 default:
mzta 0:158c61bb030f 86 return FALSE;
mzta 0:158c61bb030f 87 }
mzta 0:158c61bb030f 88
mzta 0:158c61bb030f 89 default:
mzta 0:158c61bb030f 90 return mrb_eql(mrb, a, b);
mzta 0:158c61bb030f 91 }
mzta 0:158c61bb030f 92 }
mzta 0:158c61bb030f 93
mzta 0:158c61bb030f 94 typedef struct {
mzta 0:158c61bb030f 95 mrb_value v;
mzta 0:158c61bb030f 96 mrb_int n;
mzta 0:158c61bb030f 97 } mrb_hash_value;
mzta 0:158c61bb030f 98
mzta 0:158c61bb030f 99 KHASH_DECLARE(ht, mrb_value, mrb_hash_value, TRUE)
mzta 0:158c61bb030f 100 KHASH_DEFINE (ht, mrb_value, mrb_hash_value, TRUE, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal)
mzta 0:158c61bb030f 101
mzta 0:158c61bb030f 102 static void mrb_hash_modify(mrb_state *mrb, mrb_value hash);
mzta 0:158c61bb030f 103
mzta 0:158c61bb030f 104 static inline mrb_value
mzta 0:158c61bb030f 105 mrb_hash_ht_key(mrb_state *mrb, mrb_value key)
mzta 0:158c61bb030f 106 {
mzta 0:158c61bb030f 107 if (mrb_string_p(key))
mzta 0:158c61bb030f 108 return mrb_str_dup(mrb, key);
mzta 0:158c61bb030f 109 else
mzta 0:158c61bb030f 110 return key;
mzta 0:158c61bb030f 111 }
mzta 0:158c61bb030f 112
mzta 0:158c61bb030f 113 #define KEY(key) mrb_hash_ht_key(mrb, key)
mzta 0:158c61bb030f 114
mzta 0:158c61bb030f 115 void
mzta 0:158c61bb030f 116 mrb_gc_mark_hash(mrb_state *mrb, struct RHash *hash)
mzta 0:158c61bb030f 117 {
mzta 0:158c61bb030f 118 khiter_t k;
mzta 0:158c61bb030f 119 khash_t(ht) *h = hash->ht;
mzta 0:158c61bb030f 120
mzta 0:158c61bb030f 121 if (!h) return;
mzta 0:158c61bb030f 122 for (k = kh_begin(h); k != kh_end(h); k++) {
mzta 0:158c61bb030f 123 if (kh_exist(h, k)) {
mzta 0:158c61bb030f 124 mrb_value key = kh_key(h, k);
mzta 0:158c61bb030f 125 mrb_value val = kh_value(h, k).v;
mzta 0:158c61bb030f 126
mzta 0:158c61bb030f 127 mrb_gc_mark_value(mrb, key);
mzta 0:158c61bb030f 128 mrb_gc_mark_value(mrb, val);
mzta 0:158c61bb030f 129 }
mzta 0:158c61bb030f 130 }
mzta 0:158c61bb030f 131 }
mzta 0:158c61bb030f 132
mzta 0:158c61bb030f 133 size_t
mzta 0:158c61bb030f 134 mrb_gc_mark_hash_size(mrb_state *mrb, struct RHash *hash)
mzta 0:158c61bb030f 135 {
mzta 0:158c61bb030f 136 if (!hash->ht) return 0;
mzta 0:158c61bb030f 137 return kh_size(hash->ht)*2;
mzta 0:158c61bb030f 138 }
mzta 0:158c61bb030f 139
mzta 0:158c61bb030f 140 void
mzta 0:158c61bb030f 141 mrb_gc_free_hash(mrb_state *mrb, struct RHash *hash)
mzta 0:158c61bb030f 142 {
mzta 0:158c61bb030f 143 if (hash->ht) kh_destroy(ht, mrb, hash->ht);
mzta 0:158c61bb030f 144 }
mzta 0:158c61bb030f 145
mzta 0:158c61bb030f 146
mzta 0:158c61bb030f 147 MRB_API mrb_value
mzta 0:158c61bb030f 148 mrb_hash_new_capa(mrb_state *mrb, int capa)
mzta 0:158c61bb030f 149 {
mzta 0:158c61bb030f 150 struct RHash *h;
mzta 0:158c61bb030f 151
mzta 0:158c61bb030f 152 h = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
mzta 0:158c61bb030f 153 h->ht = kh_init(ht, mrb);
mzta 0:158c61bb030f 154 if (capa > 0) {
mzta 0:158c61bb030f 155 kh_resize(ht, mrb, h->ht, capa);
mzta 0:158c61bb030f 156 }
mzta 0:158c61bb030f 157 h->iv = 0;
mzta 0:158c61bb030f 158 return mrb_obj_value(h);
mzta 0:158c61bb030f 159 }
mzta 0:158c61bb030f 160
mzta 0:158c61bb030f 161 MRB_API mrb_value
mzta 0:158c61bb030f 162 mrb_hash_new(mrb_state *mrb)
mzta 0:158c61bb030f 163 {
mzta 0:158c61bb030f 164 return mrb_hash_new_capa(mrb, 0);
mzta 0:158c61bb030f 165 }
mzta 0:158c61bb030f 166
mzta 0:158c61bb030f 167 MRB_API mrb_value
mzta 0:158c61bb030f 168 mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key)
mzta 0:158c61bb030f 169 {
mzta 0:158c61bb030f 170 khash_t(ht) *h = RHASH_TBL(hash);
mzta 0:158c61bb030f 171 khiter_t k;
mzta 0:158c61bb030f 172
mzta 0:158c61bb030f 173 if (h) {
mzta 0:158c61bb030f 174 k = kh_get(ht, mrb, h, key);
mzta 0:158c61bb030f 175 if (k != kh_end(h))
mzta 0:158c61bb030f 176 return kh_value(h, k).v;
mzta 0:158c61bb030f 177 }
mzta 0:158c61bb030f 178
mzta 0:158c61bb030f 179 /* not found */
mzta 0:158c61bb030f 180 if (MRB_RHASH_PROCDEFAULT_P(hash)) {
mzta 0:158c61bb030f 181 return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key);
mzta 0:158c61bb030f 182 }
mzta 0:158c61bb030f 183 return RHASH_IFNONE(hash);
mzta 0:158c61bb030f 184 }
mzta 0:158c61bb030f 185
mzta 0:158c61bb030f 186 MRB_API mrb_value
mzta 0:158c61bb030f 187 mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def)
mzta 0:158c61bb030f 188 {
mzta 0:158c61bb030f 189 khash_t(ht) *h = RHASH_TBL(hash);
mzta 0:158c61bb030f 190 khiter_t k;
mzta 0:158c61bb030f 191
mzta 0:158c61bb030f 192 if (h) {
mzta 0:158c61bb030f 193 k = kh_get(ht, mrb, h, key);
mzta 0:158c61bb030f 194 if (k != kh_end(h))
mzta 0:158c61bb030f 195 return kh_value(h, k).v;
mzta 0:158c61bb030f 196 }
mzta 0:158c61bb030f 197
mzta 0:158c61bb030f 198 /* not found */
mzta 0:158c61bb030f 199 return def;
mzta 0:158c61bb030f 200 }
mzta 0:158c61bb030f 201
mzta 0:158c61bb030f 202 MRB_API void
mzta 0:158c61bb030f 203 mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val)
mzta 0:158c61bb030f 204 {
mzta 0:158c61bb030f 205 khash_t(ht) *h;
mzta 0:158c61bb030f 206 khiter_t k;
mzta 0:158c61bb030f 207 int r;
mzta 0:158c61bb030f 208
mzta 0:158c61bb030f 209 mrb_hash_modify(mrb, hash);
mzta 0:158c61bb030f 210 h = RHASH_TBL(hash);
mzta 0:158c61bb030f 211
mzta 0:158c61bb030f 212 if (!h) h = RHASH_TBL(hash) = kh_init(ht, mrb);
mzta 0:158c61bb030f 213 k = kh_put2(ht, mrb, h, key, &r);
mzta 0:158c61bb030f 214 kh_value(h, k).v = val;
mzta 0:158c61bb030f 215
mzta 0:158c61bb030f 216 if (r != 0) {
mzta 0:158c61bb030f 217 /* expand */
mzta 0:158c61bb030f 218 int ai = mrb_gc_arena_save(mrb);
mzta 0:158c61bb030f 219 key = kh_key(h, k) = KEY(key);
mzta 0:158c61bb030f 220 mrb_gc_arena_restore(mrb, ai);
mzta 0:158c61bb030f 221 kh_value(h, k).n = kh_size(h)-1;
mzta 0:158c61bb030f 222 }
mzta 0:158c61bb030f 223
mzta 0:158c61bb030f 224 mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), key);
mzta 0:158c61bb030f 225 mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), val);
mzta 0:158c61bb030f 226 return;
mzta 0:158c61bb030f 227 }
mzta 0:158c61bb030f 228
mzta 0:158c61bb030f 229 static mrb_value
mzta 0:158c61bb030f 230 mrb_hash_dup(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 231 {
mzta 0:158c61bb030f 232 struct RHash* ret;
mzta 0:158c61bb030f 233 khash_t(ht) *h, *ret_h;
mzta 0:158c61bb030f 234 khiter_t k, ret_k;
mzta 0:158c61bb030f 235
mzta 0:158c61bb030f 236 h = RHASH_TBL(hash);
mzta 0:158c61bb030f 237 ret = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
mzta 0:158c61bb030f 238 ret->ht = kh_init(ht, mrb);
mzta 0:158c61bb030f 239
mzta 0:158c61bb030f 240 if (kh_size(h) > 0) {
mzta 0:158c61bb030f 241 ret_h = ret->ht;
mzta 0:158c61bb030f 242
mzta 0:158c61bb030f 243 for (k = kh_begin(h); k != kh_end(h); k++) {
mzta 0:158c61bb030f 244 if (kh_exist(h, k)) {
mzta 0:158c61bb030f 245 int ai = mrb_gc_arena_save(mrb);
mzta 0:158c61bb030f 246 ret_k = kh_put(ht, mrb, ret_h, KEY(kh_key(h, k)));
mzta 0:158c61bb030f 247 mrb_gc_arena_restore(mrb, ai);
mzta 0:158c61bb030f 248 kh_val(ret_h, ret_k) = kh_val(h, k);
mzta 0:158c61bb030f 249 }
mzta 0:158c61bb030f 250 }
mzta 0:158c61bb030f 251 }
mzta 0:158c61bb030f 252
mzta 0:158c61bb030f 253 return mrb_obj_value(ret);
mzta 0:158c61bb030f 254 }
mzta 0:158c61bb030f 255
mzta 0:158c61bb030f 256 MRB_API mrb_value
mzta 0:158c61bb030f 257 mrb_check_hash_type(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 258 {
mzta 0:158c61bb030f 259 return mrb_check_convert_type(mrb, hash, MRB_TT_HASH, "Hash", "to_hash");
mzta 0:158c61bb030f 260 }
mzta 0:158c61bb030f 261
mzta 0:158c61bb030f 262 MRB_API khash_t(ht)*
mzta 0:158c61bb030f 263 mrb_hash_tbl(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 264 {
mzta 0:158c61bb030f 265 khash_t(ht) *h = RHASH_TBL(hash);
mzta 0:158c61bb030f 266
mzta 0:158c61bb030f 267 if (!h) {
mzta 0:158c61bb030f 268 return RHASH_TBL(hash) = kh_init(ht, mrb);
mzta 0:158c61bb030f 269 }
mzta 0:158c61bb030f 270 return h;
mzta 0:158c61bb030f 271 }
mzta 0:158c61bb030f 272
mzta 0:158c61bb030f 273 static void
mzta 0:158c61bb030f 274 mrb_hash_modify(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 275 {
mzta 0:158c61bb030f 276 mrb_hash_tbl(mrb, hash);
mzta 0:158c61bb030f 277 }
mzta 0:158c61bb030f 278
mzta 0:158c61bb030f 279 /* 15.2.13.4.16 */
mzta 0:158c61bb030f 280 /*
mzta 0:158c61bb030f 281 * call-seq:
mzta 0:158c61bb030f 282 * Hash.new -> new_hash
mzta 0:158c61bb030f 283 * Hash.new(obj) -> new_hash
mzta 0:158c61bb030f 284 * Hash.new {|hash, key| block } -> new_hash
mzta 0:158c61bb030f 285 *
mzta 0:158c61bb030f 286 * Returns a new, empty hash. If this hash is subsequently accessed by
mzta 0:158c61bb030f 287 * a key that doesn't correspond to a hash entry, the value returned
mzta 0:158c61bb030f 288 * depends on the style of <code>new</code> used to create the hash. In
mzta 0:158c61bb030f 289 * the first form, the access returns <code>nil</code>. If
mzta 0:158c61bb030f 290 * <i>obj</i> is specified, this single object will be used for
mzta 0:158c61bb030f 291 * all <em>default values</em>. If a block is specified, it will be
mzta 0:158c61bb030f 292 * called with the hash object and the key, and should return the
mzta 0:158c61bb030f 293 * default value. It is the block's responsibility to store the value
mzta 0:158c61bb030f 294 * in the hash if required.
mzta 0:158c61bb030f 295 *
mzta 0:158c61bb030f 296 * h = Hash.new("Go Fish")
mzta 0:158c61bb030f 297 * h["a"] = 100
mzta 0:158c61bb030f 298 * h["b"] = 200
mzta 0:158c61bb030f 299 * h["a"] #=> 100
mzta 0:158c61bb030f 300 * h["c"] #=> "Go Fish"
mzta 0:158c61bb030f 301 * # The following alters the single default object
mzta 0:158c61bb030f 302 * h["c"].upcase! #=> "GO FISH"
mzta 0:158c61bb030f 303 * h["d"] #=> "GO FISH"
mzta 0:158c61bb030f 304 * h.keys #=> ["a", "b"]
mzta 0:158c61bb030f 305 *
mzta 0:158c61bb030f 306 * # While this creates a new default object each time
mzta 0:158c61bb030f 307 * h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
mzta 0:158c61bb030f 308 * h["c"] #=> "Go Fish: c"
mzta 0:158c61bb030f 309 * h["c"].upcase! #=> "GO FISH: C"
mzta 0:158c61bb030f 310 * h["d"] #=> "Go Fish: d"
mzta 0:158c61bb030f 311 * h.keys #=> ["c", "d"]
mzta 0:158c61bb030f 312 *
mzta 0:158c61bb030f 313 */
mzta 0:158c61bb030f 314
mzta 0:158c61bb030f 315 static mrb_value
mzta 0:158c61bb030f 316 mrb_hash_init(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 317 {
mzta 0:158c61bb030f 318 mrb_value block, ifnone;
mzta 0:158c61bb030f 319 mrb_bool ifnone_p;
mzta 0:158c61bb030f 320
mzta 0:158c61bb030f 321 ifnone = mrb_nil_value();
mzta 0:158c61bb030f 322 mrb_get_args(mrb, "&|o?", &block, &ifnone, &ifnone_p);
mzta 0:158c61bb030f 323 mrb_hash_modify(mrb, hash);
mzta 0:158c61bb030f 324 if (!mrb_nil_p(block)) {
mzta 0:158c61bb030f 325 if (ifnone_p) {
mzta 0:158c61bb030f 326 mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
mzta 0:158c61bb030f 327 }
mzta 0:158c61bb030f 328 RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
mzta 0:158c61bb030f 329 ifnone = block;
mzta 0:158c61bb030f 330 }
mzta 0:158c61bb030f 331 mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone);
mzta 0:158c61bb030f 332 return hash;
mzta 0:158c61bb030f 333 }
mzta 0:158c61bb030f 334
mzta 0:158c61bb030f 335 /* 15.2.13.4.2 */
mzta 0:158c61bb030f 336 /*
mzta 0:158c61bb030f 337 * call-seq:
mzta 0:158c61bb030f 338 * hsh[key] -> value
mzta 0:158c61bb030f 339 *
mzta 0:158c61bb030f 340 * Element Reference---Retrieves the <i>value</i> object corresponding
mzta 0:158c61bb030f 341 * to the <i>key</i> object. If not found, returns the default value (see
mzta 0:158c61bb030f 342 * <code>Hash::new</code> for details).
mzta 0:158c61bb030f 343 *
mzta 0:158c61bb030f 344 * h = { "a" => 100, "b" => 200 }
mzta 0:158c61bb030f 345 * h["a"] #=> 100
mzta 0:158c61bb030f 346 * h["c"] #=> nil
mzta 0:158c61bb030f 347 *
mzta 0:158c61bb030f 348 */
mzta 0:158c61bb030f 349 static mrb_value
mzta 0:158c61bb030f 350 mrb_hash_aget(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 351 {
mzta 0:158c61bb030f 352 mrb_value key;
mzta 0:158c61bb030f 353
mzta 0:158c61bb030f 354 mrb_get_args(mrb, "o", &key);
mzta 0:158c61bb030f 355 return mrb_hash_get(mrb, self, key);
mzta 0:158c61bb030f 356 }
mzta 0:158c61bb030f 357
mzta 0:158c61bb030f 358 /* 15.2.13.4.5 */
mzta 0:158c61bb030f 359 /*
mzta 0:158c61bb030f 360 * call-seq:
mzta 0:158c61bb030f 361 * hsh.default(key=nil) -> obj
mzta 0:158c61bb030f 362 *
mzta 0:158c61bb030f 363 * Returns the default value, the value that would be returned by
mzta 0:158c61bb030f 364 * <i>hsh</i>[<i>key</i>] if <i>key</i> did not exist in <i>hsh</i>.
mzta 0:158c61bb030f 365 * See also <code>Hash::new</code> and <code>Hash#default=</code>.
mzta 0:158c61bb030f 366 *
mzta 0:158c61bb030f 367 * h = Hash.new #=> {}
mzta 0:158c61bb030f 368 * h.default #=> nil
mzta 0:158c61bb030f 369 * h.default(2) #=> nil
mzta 0:158c61bb030f 370 *
mzta 0:158c61bb030f 371 * h = Hash.new("cat") #=> {}
mzta 0:158c61bb030f 372 * h.default #=> "cat"
mzta 0:158c61bb030f 373 * h.default(2) #=> "cat"
mzta 0:158c61bb030f 374 *
mzta 0:158c61bb030f 375 * h = Hash.new {|h,k| h[k] = k.to_i*10} #=> {}
mzta 0:158c61bb030f 376 * h.default #=> nil
mzta 0:158c61bb030f 377 * h.default(2) #=> 20
mzta 0:158c61bb030f 378 */
mzta 0:158c61bb030f 379
mzta 0:158c61bb030f 380 static mrb_value
mzta 0:158c61bb030f 381 mrb_hash_default(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 382 {
mzta 0:158c61bb030f 383 mrb_value key;
mzta 0:158c61bb030f 384 mrb_bool given;
mzta 0:158c61bb030f 385
mzta 0:158c61bb030f 386 mrb_get_args(mrb, "|o?", &key, &given);
mzta 0:158c61bb030f 387 if (MRB_RHASH_PROCDEFAULT_P(hash)) {
mzta 0:158c61bb030f 388 if (!given) return mrb_nil_value();
mzta 0:158c61bb030f 389 return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key);
mzta 0:158c61bb030f 390 }
mzta 0:158c61bb030f 391 else {
mzta 0:158c61bb030f 392 return RHASH_IFNONE(hash);
mzta 0:158c61bb030f 393 }
mzta 0:158c61bb030f 394 }
mzta 0:158c61bb030f 395
mzta 0:158c61bb030f 396 /* 15.2.13.4.6 */
mzta 0:158c61bb030f 397 /*
mzta 0:158c61bb030f 398 * call-seq:
mzta 0:158c61bb030f 399 * hsh.default = obj -> obj
mzta 0:158c61bb030f 400 *
mzta 0:158c61bb030f 401 * Sets the default value, the value returned for a key that does not
mzta 0:158c61bb030f 402 * exist in the hash. It is not possible to set the default to a
mzta 0:158c61bb030f 403 * <code>Proc</code> that will be executed on each key lookup.
mzta 0:158c61bb030f 404 *
mzta 0:158c61bb030f 405 * h = { "a" => 100, "b" => 200 }
mzta 0:158c61bb030f 406 * h.default = "Go fish"
mzta 0:158c61bb030f 407 * h["a"] #=> 100
mzta 0:158c61bb030f 408 * h["z"] #=> "Go fish"
mzta 0:158c61bb030f 409 * # This doesn't do what you might hope...
mzta 0:158c61bb030f 410 * h.default = proc do |hash, key|
mzta 0:158c61bb030f 411 * hash[key] = key + key
mzta 0:158c61bb030f 412 * end
mzta 0:158c61bb030f 413 * h[2] #=> #<Proc:0x401b3948@-:6>
mzta 0:158c61bb030f 414 * h["cat"] #=> #<Proc:0x401b3948@-:6>
mzta 0:158c61bb030f 415 */
mzta 0:158c61bb030f 416
mzta 0:158c61bb030f 417 static mrb_value
mzta 0:158c61bb030f 418 mrb_hash_set_default(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 419 {
mzta 0:158c61bb030f 420 mrb_value ifnone;
mzta 0:158c61bb030f 421
mzta 0:158c61bb030f 422 mrb_get_args(mrb, "o", &ifnone);
mzta 0:158c61bb030f 423 mrb_hash_modify(mrb, hash);
mzta 0:158c61bb030f 424 mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone);
mzta 0:158c61bb030f 425 RHASH(hash)->flags &= ~(MRB_HASH_PROC_DEFAULT);
mzta 0:158c61bb030f 426
mzta 0:158c61bb030f 427 return ifnone;
mzta 0:158c61bb030f 428 }
mzta 0:158c61bb030f 429
mzta 0:158c61bb030f 430 /* 15.2.13.4.7 */
mzta 0:158c61bb030f 431 /*
mzta 0:158c61bb030f 432 * call-seq:
mzta 0:158c61bb030f 433 * hsh.default_proc -> anObject
mzta 0:158c61bb030f 434 *
mzta 0:158c61bb030f 435 * If <code>Hash::new</code> was invoked with a block, return that
mzta 0:158c61bb030f 436 * block, otherwise return <code>nil</code>.
mzta 0:158c61bb030f 437 *
mzta 0:158c61bb030f 438 * h = Hash.new {|h,k| h[k] = k*k } #=> {}
mzta 0:158c61bb030f 439 * p = h.default_proc #=> #<Proc:0x401b3d08@-:1>
mzta 0:158c61bb030f 440 * a = [] #=> []
mzta 0:158c61bb030f 441 * p.call(a, 2)
mzta 0:158c61bb030f 442 * a #=> [nil, nil, 4]
mzta 0:158c61bb030f 443 */
mzta 0:158c61bb030f 444
mzta 0:158c61bb030f 445
mzta 0:158c61bb030f 446 static mrb_value
mzta 0:158c61bb030f 447 mrb_hash_default_proc(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 448 {
mzta 0:158c61bb030f 449 if (MRB_RHASH_PROCDEFAULT_P(hash)) {
mzta 0:158c61bb030f 450 return RHASH_PROCDEFAULT(hash);
mzta 0:158c61bb030f 451 }
mzta 0:158c61bb030f 452 return mrb_nil_value();
mzta 0:158c61bb030f 453 }
mzta 0:158c61bb030f 454
mzta 0:158c61bb030f 455 /*
mzta 0:158c61bb030f 456 * call-seq:
mzta 0:158c61bb030f 457 * hsh.default_proc = proc_obj -> proc_obj
mzta 0:158c61bb030f 458 *
mzta 0:158c61bb030f 459 * Sets the default proc to be executed on each key lookup.
mzta 0:158c61bb030f 460 *
mzta 0:158c61bb030f 461 * h.default_proc = proc do |hash, key|
mzta 0:158c61bb030f 462 * hash[key] = key + key
mzta 0:158c61bb030f 463 * end
mzta 0:158c61bb030f 464 * h[2] #=> 4
mzta 0:158c61bb030f 465 * h["cat"] #=> "catcat"
mzta 0:158c61bb030f 466 */
mzta 0:158c61bb030f 467
mzta 0:158c61bb030f 468 static mrb_value
mzta 0:158c61bb030f 469 mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 470 {
mzta 0:158c61bb030f 471 mrb_value ifnone;
mzta 0:158c61bb030f 472
mzta 0:158c61bb030f 473 mrb_get_args(mrb, "o", &ifnone);
mzta 0:158c61bb030f 474 mrb_hash_modify(mrb, hash);
mzta 0:158c61bb030f 475 mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone);
mzta 0:158c61bb030f 476 RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
mzta 0:158c61bb030f 477
mzta 0:158c61bb030f 478 return ifnone;
mzta 0:158c61bb030f 479 }
mzta 0:158c61bb030f 480
mzta 0:158c61bb030f 481 MRB_API mrb_value
mzta 0:158c61bb030f 482 mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key)
mzta 0:158c61bb030f 483 {
mzta 0:158c61bb030f 484 khash_t(ht) *h = RHASH_TBL(hash);
mzta 0:158c61bb030f 485 khiter_t k;
mzta 0:158c61bb030f 486 mrb_value delVal;
mzta 0:158c61bb030f 487 mrb_int n;
mzta 0:158c61bb030f 488
mzta 0:158c61bb030f 489 if (h) {
mzta 0:158c61bb030f 490 k = kh_get(ht, mrb, h, key);
mzta 0:158c61bb030f 491 if (k != kh_end(h)) {
mzta 0:158c61bb030f 492 delVal = kh_value(h, k).v;
mzta 0:158c61bb030f 493 n = kh_value(h, k).n;
mzta 0:158c61bb030f 494 kh_del(ht, mrb, h, k);
mzta 0:158c61bb030f 495 for (k = kh_begin(h); k != kh_end(h); k++) {
mzta 0:158c61bb030f 496 if (!kh_exist(h, k)) continue;
mzta 0:158c61bb030f 497 if (kh_value(h, k).n > n) kh_value(h, k).n--;
mzta 0:158c61bb030f 498 }
mzta 0:158c61bb030f 499 return delVal;
mzta 0:158c61bb030f 500 }
mzta 0:158c61bb030f 501 }
mzta 0:158c61bb030f 502
mzta 0:158c61bb030f 503 /* not found */
mzta 0:158c61bb030f 504 return mrb_nil_value();
mzta 0:158c61bb030f 505 }
mzta 0:158c61bb030f 506
mzta 0:158c61bb030f 507 /* 15.2.13.4.8 */
mzta 0:158c61bb030f 508 /*
mzta 0:158c61bb030f 509 * call-seq:
mzta 0:158c61bb030f 510 * hsh.delete(key) -> value
mzta 0:158c61bb030f 511 * hsh.delete(key) {| key | block } -> value
mzta 0:158c61bb030f 512 *
mzta 0:158c61bb030f 513 * Deletes and returns a key-value pair from <i>hsh</i> whose key is
mzta 0:158c61bb030f 514 * equal to <i>key</i>. If the key is not found, returns the
mzta 0:158c61bb030f 515 * <em>default value</em>. If the optional code block is given and the
mzta 0:158c61bb030f 516 * key is not found, pass in the key and return the result of
mzta 0:158c61bb030f 517 * <i>block</i>.
mzta 0:158c61bb030f 518 *
mzta 0:158c61bb030f 519 * h = { "a" => 100, "b" => 200 }
mzta 0:158c61bb030f 520 * h.delete("a") #=> 100
mzta 0:158c61bb030f 521 * h.delete("z") #=> nil
mzta 0:158c61bb030f 522 * h.delete("z") { |el| "#{el} not found" } #=> "z not found"
mzta 0:158c61bb030f 523 *
mzta 0:158c61bb030f 524 */
mzta 0:158c61bb030f 525 static mrb_value
mzta 0:158c61bb030f 526 mrb_hash_delete(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 527 {
mzta 0:158c61bb030f 528 mrb_value key;
mzta 0:158c61bb030f 529
mzta 0:158c61bb030f 530 mrb_get_args(mrb, "o", &key);
mzta 0:158c61bb030f 531 return mrb_hash_delete_key(mrb, self, key);
mzta 0:158c61bb030f 532 }
mzta 0:158c61bb030f 533
mzta 0:158c61bb030f 534 /* 15.2.13.4.24 */
mzta 0:158c61bb030f 535 /*
mzta 0:158c61bb030f 536 * call-seq:
mzta 0:158c61bb030f 537 * hsh.shift -> anArray or obj
mzta 0:158c61bb030f 538 *
mzta 0:158c61bb030f 539 * Removes a key-value pair from <i>hsh</i> and returns it as the
mzta 0:158c61bb030f 540 * two-item array <code>[</code> <i>key, value</i> <code>]</code>, or
mzta 0:158c61bb030f 541 * the hash's default value if the hash is empty.
mzta 0:158c61bb030f 542 *
mzta 0:158c61bb030f 543 * h = { 1 => "a", 2 => "b", 3 => "c" }
mzta 0:158c61bb030f 544 * h.shift #=> [1, "a"]
mzta 0:158c61bb030f 545 * h #=> {2=>"b", 3=>"c"}
mzta 0:158c61bb030f 546 */
mzta 0:158c61bb030f 547
mzta 0:158c61bb030f 548 static mrb_value
mzta 0:158c61bb030f 549 mrb_hash_shift(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 550 {
mzta 0:158c61bb030f 551 khash_t(ht) *h = RHASH_TBL(hash);
mzta 0:158c61bb030f 552 khiter_t k;
mzta 0:158c61bb030f 553 mrb_value delKey, delVal;
mzta 0:158c61bb030f 554
mzta 0:158c61bb030f 555 mrb_hash_modify(mrb, hash);
mzta 0:158c61bb030f 556 if (h && kh_size(h) > 0) {
mzta 0:158c61bb030f 557 for (k = kh_begin(h); k != kh_end(h); k++) {
mzta 0:158c61bb030f 558 if (!kh_exist(h, k)) continue;
mzta 0:158c61bb030f 559
mzta 0:158c61bb030f 560 delKey = kh_key(h, k);
mzta 0:158c61bb030f 561 mrb_gc_protect(mrb, delKey);
mzta 0:158c61bb030f 562 delVal = mrb_hash_delete_key(mrb, hash, delKey);
mzta 0:158c61bb030f 563 mrb_gc_protect(mrb, delVal);
mzta 0:158c61bb030f 564
mzta 0:158c61bb030f 565 return mrb_assoc_new(mrb, delKey, delVal);
mzta 0:158c61bb030f 566 }
mzta 0:158c61bb030f 567 }
mzta 0:158c61bb030f 568
mzta 0:158c61bb030f 569 if (MRB_RHASH_PROCDEFAULT_P(hash)) {
mzta 0:158c61bb030f 570 return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, mrb_nil_value());
mzta 0:158c61bb030f 571 }
mzta 0:158c61bb030f 572 else {
mzta 0:158c61bb030f 573 return RHASH_IFNONE(hash);
mzta 0:158c61bb030f 574 }
mzta 0:158c61bb030f 575 }
mzta 0:158c61bb030f 576
mzta 0:158c61bb030f 577 /* 15.2.13.4.4 */
mzta 0:158c61bb030f 578 /*
mzta 0:158c61bb030f 579 * call-seq:
mzta 0:158c61bb030f 580 * hsh.clear -> hsh
mzta 0:158c61bb030f 581 *
mzta 0:158c61bb030f 582 * Removes all key-value pairs from <i>hsh</i>.
mzta 0:158c61bb030f 583 *
mzta 0:158c61bb030f 584 * h = { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200}
mzta 0:158c61bb030f 585 * h.clear #=> {}
mzta 0:158c61bb030f 586 *
mzta 0:158c61bb030f 587 */
mzta 0:158c61bb030f 588
mzta 0:158c61bb030f 589 MRB_API mrb_value
mzta 0:158c61bb030f 590 mrb_hash_clear(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 591 {
mzta 0:158c61bb030f 592 khash_t(ht) *h = RHASH_TBL(hash);
mzta 0:158c61bb030f 593
mzta 0:158c61bb030f 594 if (h) kh_clear(ht, mrb, h);
mzta 0:158c61bb030f 595 return hash;
mzta 0:158c61bb030f 596 }
mzta 0:158c61bb030f 597
mzta 0:158c61bb030f 598 /* 15.2.13.4.3 */
mzta 0:158c61bb030f 599 /* 15.2.13.4.26 */
mzta 0:158c61bb030f 600 /*
mzta 0:158c61bb030f 601 * call-seq:
mzta 0:158c61bb030f 602 * hsh[key] = value -> value
mzta 0:158c61bb030f 603 * hsh.store(key, value) -> value
mzta 0:158c61bb030f 604 *
mzta 0:158c61bb030f 605 * Element Assignment---Associates the value given by
mzta 0:158c61bb030f 606 * <i>value</i> with the key given by <i>key</i>.
mzta 0:158c61bb030f 607 * <i>key</i> should not have its value changed while it is in
mzta 0:158c61bb030f 608 * use as a key (a <code>String</code> passed as a key will be
mzta 0:158c61bb030f 609 * duplicated and frozen).
mzta 0:158c61bb030f 610 *
mzta 0:158c61bb030f 611 * h = { "a" => 100, "b" => 200 }
mzta 0:158c61bb030f 612 * h["a"] = 9
mzta 0:158c61bb030f 613 * h["c"] = 4
mzta 0:158c61bb030f 614 * h #=> {"a"=>9, "b"=>200, "c"=>4}
mzta 0:158c61bb030f 615 *
mzta 0:158c61bb030f 616 */
mzta 0:158c61bb030f 617 static mrb_value
mzta 0:158c61bb030f 618 mrb_hash_aset(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 619 {
mzta 0:158c61bb030f 620 mrb_value key, val;
mzta 0:158c61bb030f 621
mzta 0:158c61bb030f 622 mrb_get_args(mrb, "oo", &key, &val);
mzta 0:158c61bb030f 623 mrb_hash_set(mrb, self, key, val);
mzta 0:158c61bb030f 624 return val;
mzta 0:158c61bb030f 625 }
mzta 0:158c61bb030f 626
mzta 0:158c61bb030f 627 /* 15.2.13.4.20 */
mzta 0:158c61bb030f 628 /* 15.2.13.4.25 */
mzta 0:158c61bb030f 629 /*
mzta 0:158c61bb030f 630 * call-seq:
mzta 0:158c61bb030f 631 * hsh.length -> fixnum
mzta 0:158c61bb030f 632 * hsh.size -> fixnum
mzta 0:158c61bb030f 633 *
mzta 0:158c61bb030f 634 * Returns the number of key-value pairs in the hash.
mzta 0:158c61bb030f 635 *
mzta 0:158c61bb030f 636 * h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
mzta 0:158c61bb030f 637 * h.length #=> 4
mzta 0:158c61bb030f 638 * h.delete("a") #=> 200
mzta 0:158c61bb030f 639 * h.length #=> 3
mzta 0:158c61bb030f 640 */
mzta 0:158c61bb030f 641 static mrb_value
mzta 0:158c61bb030f 642 mrb_hash_size_m(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 643 {
mzta 0:158c61bb030f 644 khash_t(ht) *h = RHASH_TBL(self);
mzta 0:158c61bb030f 645
mzta 0:158c61bb030f 646 if (!h) return mrb_fixnum_value(0);
mzta 0:158c61bb030f 647 return mrb_fixnum_value(kh_size(h));
mzta 0:158c61bb030f 648 }
mzta 0:158c61bb030f 649
mzta 0:158c61bb030f 650 /* 15.2.13.4.12 */
mzta 0:158c61bb030f 651 /*
mzta 0:158c61bb030f 652 * call-seq:
mzta 0:158c61bb030f 653 * hsh.empty? -> true or false
mzta 0:158c61bb030f 654 *
mzta 0:158c61bb030f 655 * Returns <code>true</code> if <i>hsh</i> contains no key-value pairs.
mzta 0:158c61bb030f 656 *
mzta 0:158c61bb030f 657 * {}.empty? #=> true
mzta 0:158c61bb030f 658 *
mzta 0:158c61bb030f 659 */
mzta 0:158c61bb030f 660 MRB_API mrb_value
mzta 0:158c61bb030f 661 mrb_hash_empty_p(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 662 {
mzta 0:158c61bb030f 663 khash_t(ht) *h = RHASH_TBL(self);
mzta 0:158c61bb030f 664
mzta 0:158c61bb030f 665 if (h) return mrb_bool_value(kh_size(h) == 0);
mzta 0:158c61bb030f 666 return mrb_true_value();
mzta 0:158c61bb030f 667 }
mzta 0:158c61bb030f 668
mzta 0:158c61bb030f 669 /* 15.2.13.4.29 (x)*/
mzta 0:158c61bb030f 670 /*
mzta 0:158c61bb030f 671 * call-seq:
mzta 0:158c61bb030f 672 * hsh.to_hash => hsh
mzta 0:158c61bb030f 673 *
mzta 0:158c61bb030f 674 * Returns +self+.
mzta 0:158c61bb030f 675 */
mzta 0:158c61bb030f 676
mzta 0:158c61bb030f 677 static mrb_value
mzta 0:158c61bb030f 678 mrb_hash_to_hash(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 679 {
mzta 0:158c61bb030f 680 return hash;
mzta 0:158c61bb030f 681 }
mzta 0:158c61bb030f 682
mzta 0:158c61bb030f 683 /* 15.2.13.4.19 */
mzta 0:158c61bb030f 684 /*
mzta 0:158c61bb030f 685 * call-seq:
mzta 0:158c61bb030f 686 * hsh.keys -> array
mzta 0:158c61bb030f 687 *
mzta 0:158c61bb030f 688 * Returns a new array populated with the keys from this hash. See also
mzta 0:158c61bb030f 689 * <code>Hash#values</code>.
mzta 0:158c61bb030f 690 *
mzta 0:158c61bb030f 691 * h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
mzta 0:158c61bb030f 692 * h.keys #=> ["a", "b", "c", "d"]
mzta 0:158c61bb030f 693 *
mzta 0:158c61bb030f 694 */
mzta 0:158c61bb030f 695
mzta 0:158c61bb030f 696 MRB_API mrb_value
mzta 0:158c61bb030f 697 mrb_hash_keys(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 698 {
mzta 0:158c61bb030f 699 khash_t(ht) *h = RHASH_TBL(hash);
mzta 0:158c61bb030f 700 khiter_t k;
mzta 0:158c61bb030f 701 mrb_value ary;
mzta 0:158c61bb030f 702 mrb_value *p;
mzta 0:158c61bb030f 703
mzta 0:158c61bb030f 704 if (!h || kh_size(h) == 0) return mrb_ary_new(mrb);
mzta 0:158c61bb030f 705 ary = mrb_ary_new_capa(mrb, kh_size(h));
mzta 0:158c61bb030f 706 mrb_ary_set(mrb, ary, kh_size(h)-1, mrb_nil_value());
mzta 0:158c61bb030f 707 p = mrb_ary_ptr(ary)->ptr;
mzta 0:158c61bb030f 708 for (k = kh_begin(h); k != kh_end(h); k++) {
mzta 0:158c61bb030f 709 if (kh_exist(h, k)) {
mzta 0:158c61bb030f 710 mrb_value kv = kh_key(h, k);
mzta 0:158c61bb030f 711 mrb_hash_value hv = kh_value(h, k);
mzta 0:158c61bb030f 712
mzta 0:158c61bb030f 713 p[hv.n] = kv;
mzta 0:158c61bb030f 714 }
mzta 0:158c61bb030f 715 }
mzta 0:158c61bb030f 716 return ary;
mzta 0:158c61bb030f 717 }
mzta 0:158c61bb030f 718
mzta 0:158c61bb030f 719 /* 15.2.13.4.28 */
mzta 0:158c61bb030f 720 /*
mzta 0:158c61bb030f 721 * call-seq:
mzta 0:158c61bb030f 722 * hsh.values -> array
mzta 0:158c61bb030f 723 *
mzta 0:158c61bb030f 724 * Returns a new array populated with the values from <i>hsh</i>. See
mzta 0:158c61bb030f 725 * also <code>Hash#keys</code>.
mzta 0:158c61bb030f 726 *
mzta 0:158c61bb030f 727 * h = { "a" => 100, "b" => 200, "c" => 300 }
mzta 0:158c61bb030f 728 * h.values #=> [100, 200, 300]
mzta 0:158c61bb030f 729 *
mzta 0:158c61bb030f 730 */
mzta 0:158c61bb030f 731
mzta 0:158c61bb030f 732 static mrb_value
mzta 0:158c61bb030f 733 mrb_hash_values(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 734 {
mzta 0:158c61bb030f 735 khash_t(ht) *h = RHASH_TBL(hash);
mzta 0:158c61bb030f 736 khiter_t k;
mzta 0:158c61bb030f 737 mrb_value ary;
mzta 0:158c61bb030f 738
mzta 0:158c61bb030f 739 if (!h) return mrb_ary_new(mrb);
mzta 0:158c61bb030f 740 ary = mrb_ary_new_capa(mrb, kh_size(h));
mzta 0:158c61bb030f 741 for (k = kh_begin(h); k != kh_end(h); k++) {
mzta 0:158c61bb030f 742 if (kh_exist(h, k)) {
mzta 0:158c61bb030f 743 mrb_hash_value hv = kh_value(h, k);
mzta 0:158c61bb030f 744
mzta 0:158c61bb030f 745 mrb_ary_set(mrb, ary, hv.n, hv.v);
mzta 0:158c61bb030f 746 }
mzta 0:158c61bb030f 747 }
mzta 0:158c61bb030f 748 return ary;
mzta 0:158c61bb030f 749 }
mzta 0:158c61bb030f 750
mzta 0:158c61bb030f 751 /* 15.2.13.4.13 */
mzta 0:158c61bb030f 752 /* 15.2.13.4.15 */
mzta 0:158c61bb030f 753 /* 15.2.13.4.18 */
mzta 0:158c61bb030f 754 /* 15.2.13.4.21 */
mzta 0:158c61bb030f 755 /*
mzta 0:158c61bb030f 756 * call-seq:
mzta 0:158c61bb030f 757 * hsh.has_key?(key) -> true or false
mzta 0:158c61bb030f 758 * hsh.include?(key) -> true or false
mzta 0:158c61bb030f 759 * hsh.key?(key) -> true or false
mzta 0:158c61bb030f 760 * hsh.member?(key) -> true or false
mzta 0:158c61bb030f 761 *
mzta 0:158c61bb030f 762 * Returns <code>true</code> if the given key is present in <i>hsh</i>.
mzta 0:158c61bb030f 763 *
mzta 0:158c61bb030f 764 * h = { "a" => 100, "b" => 200 }
mzta 0:158c61bb030f 765 * h.has_key?("a") #=> true
mzta 0:158c61bb030f 766 * h.has_key?("z") #=> false
mzta 0:158c61bb030f 767 *
mzta 0:158c61bb030f 768 */
mzta 0:158c61bb030f 769
mzta 0:158c61bb030f 770 static mrb_value
mzta 0:158c61bb030f 771 mrb_hash_has_key(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 772 {
mzta 0:158c61bb030f 773 mrb_value key;
mzta 0:158c61bb030f 774 khash_t(ht) *h;
mzta 0:158c61bb030f 775 khiter_t k;
mzta 0:158c61bb030f 776
mzta 0:158c61bb030f 777 mrb_get_args(mrb, "o", &key);
mzta 0:158c61bb030f 778
mzta 0:158c61bb030f 779 h = RHASH_TBL(hash);
mzta 0:158c61bb030f 780 if (h) {
mzta 0:158c61bb030f 781 k = kh_get(ht, mrb, h, key);
mzta 0:158c61bb030f 782 return mrb_bool_value(k != kh_end(h));
mzta 0:158c61bb030f 783 }
mzta 0:158c61bb030f 784 return mrb_false_value();
mzta 0:158c61bb030f 785 }
mzta 0:158c61bb030f 786
mzta 0:158c61bb030f 787 /* 15.2.13.4.14 */
mzta 0:158c61bb030f 788 /* 15.2.13.4.27 */
mzta 0:158c61bb030f 789 /*
mzta 0:158c61bb030f 790 * call-seq:
mzta 0:158c61bb030f 791 * hsh.has_value?(value) -> true or false
mzta 0:158c61bb030f 792 * hsh.value?(value) -> true or false
mzta 0:158c61bb030f 793 *
mzta 0:158c61bb030f 794 * Returns <code>true</code> if the given value is present for some key
mzta 0:158c61bb030f 795 * in <i>hsh</i>.
mzta 0:158c61bb030f 796 *
mzta 0:158c61bb030f 797 * h = { "a" => 100, "b" => 200 }
mzta 0:158c61bb030f 798 * h.has_value?(100) #=> true
mzta 0:158c61bb030f 799 * h.has_value?(999) #=> false
mzta 0:158c61bb030f 800 */
mzta 0:158c61bb030f 801
mzta 0:158c61bb030f 802 static mrb_value
mzta 0:158c61bb030f 803 mrb_hash_has_value(mrb_state *mrb, mrb_value hash)
mzta 0:158c61bb030f 804 {
mzta 0:158c61bb030f 805 mrb_value val;
mzta 0:158c61bb030f 806 khash_t(ht) *h;
mzta 0:158c61bb030f 807 khiter_t k;
mzta 0:158c61bb030f 808
mzta 0:158c61bb030f 809 mrb_get_args(mrb, "o", &val);
mzta 0:158c61bb030f 810 h = RHASH_TBL(hash);
mzta 0:158c61bb030f 811
mzta 0:158c61bb030f 812 if (h) {
mzta 0:158c61bb030f 813 for (k = kh_begin(h); k != kh_end(h); k++) {
mzta 0:158c61bb030f 814 if (!kh_exist(h, k)) continue;
mzta 0:158c61bb030f 815
mzta 0:158c61bb030f 816 if (mrb_equal(mrb, kh_value(h, k).v, val)) {
mzta 0:158c61bb030f 817 return mrb_true_value();
mzta 0:158c61bb030f 818 }
mzta 0:158c61bb030f 819 }
mzta 0:158c61bb030f 820 }
mzta 0:158c61bb030f 821 return mrb_false_value();
mzta 0:158c61bb030f 822 }
mzta 0:158c61bb030f 823
mzta 0:158c61bb030f 824 void
mzta 0:158c61bb030f 825 mrb_init_hash(mrb_state *mrb)
mzta 0:158c61bb030f 826 {
mzta 0:158c61bb030f 827 struct RClass *h;
mzta 0:158c61bb030f 828
mzta 0:158c61bb030f 829 h = mrb->hash_class = mrb_define_class(mrb, "Hash", mrb->object_class); /* 15.2.13 */
mzta 0:158c61bb030f 830 MRB_SET_INSTANCE_TT(h, MRB_TT_HASH);
mzta 0:158c61bb030f 831
mzta 0:158c61bb030f 832 mrb_define_method(mrb, h, "[]", mrb_hash_aget, MRB_ARGS_REQ(1)); /* 15.2.13.4.2 */
mzta 0:158c61bb030f 833 mrb_define_method(mrb, h, "[]=", mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.3 */
mzta 0:158c61bb030f 834 mrb_define_method(mrb, h, "clear", mrb_hash_clear, MRB_ARGS_NONE()); /* 15.2.13.4.4 */
mzta 0:158c61bb030f 835 mrb_define_method(mrb, h, "default", mrb_hash_default, MRB_ARGS_ANY()); /* 15.2.13.4.5 */
mzta 0:158c61bb030f 836 mrb_define_method(mrb, h, "default=", mrb_hash_set_default, MRB_ARGS_REQ(1)); /* 15.2.13.4.6 */
mzta 0:158c61bb030f 837 mrb_define_method(mrb, h, "default_proc", mrb_hash_default_proc,MRB_ARGS_NONE()); /* 15.2.13.4.7 */
mzta 0:158c61bb030f 838 mrb_define_method(mrb, h, "default_proc=", mrb_hash_set_default_proc,MRB_ARGS_REQ(1)); /* 15.2.13.4.7 */
mzta 0:158c61bb030f 839 mrb_define_method(mrb, h, "__delete", mrb_hash_delete, MRB_ARGS_REQ(1)); /* core of 15.2.13.4.8 */
mzta 0:158c61bb030f 840 mrb_define_method(mrb, h, "empty?", mrb_hash_empty_p, MRB_ARGS_NONE()); /* 15.2.13.4.12 */
mzta 0:158c61bb030f 841 mrb_define_method(mrb, h, "has_key?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.13 */
mzta 0:158c61bb030f 842 mrb_define_method(mrb, h, "has_value?", mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.14 */
mzta 0:158c61bb030f 843 mrb_define_method(mrb, h, "include?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.15 */
mzta 0:158c61bb030f 844 mrb_define_method(mrb, h, "initialize", mrb_hash_init, MRB_ARGS_OPT(1)); /* 15.2.13.4.16 */
mzta 0:158c61bb030f 845 mrb_define_method(mrb, h, "key?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.18 */
mzta 0:158c61bb030f 846 mrb_define_method(mrb, h, "keys", mrb_hash_keys, MRB_ARGS_NONE()); /* 15.2.13.4.19 */
mzta 0:158c61bb030f 847 mrb_define_method(mrb, h, "length", mrb_hash_size_m, MRB_ARGS_NONE()); /* 15.2.13.4.20 */
mzta 0:158c61bb030f 848 mrb_define_method(mrb, h, "member?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.21 */
mzta 0:158c61bb030f 849 mrb_define_method(mrb, h, "shift", mrb_hash_shift, MRB_ARGS_NONE()); /* 15.2.13.4.24 */
mzta 0:158c61bb030f 850 mrb_define_method(mrb, h, "dup", mrb_hash_dup, MRB_ARGS_NONE());
mzta 0:158c61bb030f 851 mrb_define_method(mrb, h, "size", mrb_hash_size_m, MRB_ARGS_NONE()); /* 15.2.13.4.25 */
mzta 0:158c61bb030f 852 mrb_define_method(mrb, h, "store", mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.26 */
mzta 0:158c61bb030f 853 mrb_define_method(mrb, h, "value?", mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.27 */
mzta 0:158c61bb030f 854 mrb_define_method(mrb, h, "values", mrb_hash_values, MRB_ARGS_NONE()); /* 15.2.13.4.28 */
mzta 0:158c61bb030f 855
mzta 0:158c61bb030f 856 mrb_define_method(mrb, h, "to_hash", mrb_hash_to_hash, MRB_ARGS_NONE()); /* 15.2.13.4.29 (x)*/
mzta 0:158c61bb030f 857 }
mzta 0:158c61bb030f 858