mbed I/F binding for mruby
Dependents: mruby_mbed_web mirb_mbed
mbed-mruby
How to use
Class
src/hash.c@1:8ccd1d494a4b, 2015-04-13 (annotated)
- 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?
User | Revision | Line number | New 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 |