1 /** 2 ** @file mruby/array.h - Array class 3 ** 4 ** See Copyright Notice in mruby.h 5 */ 6 7 #ifndef MRUBY_ARRAY_H 8 #define MRUBY_ARRAY_H 9 10 #include "common.h" 11 12 /* 13 * Array class 14 */ 15 MRB_BEGIN_DECL 16 17 18 typedef struct mrb_shared_array { 19 int refcnt; 20 mrb_ssize len; 21 mrb_value *ptr; 22 } mrb_shared_array; 23 24 #define MRB_ARY_EMBED_LEN_MAX ((mrb_int)(sizeof(void*)*3/sizeof(mrb_value))) 25 struct RArray { 26 MRB_OBJECT_HEADER; 27 union { 28 struct { 29 mrb_ssize len; 30 union { 31 mrb_ssize capa; 32 mrb_shared_array *shared; 33 } aux; 34 mrb_value *ptr; 35 } heap; 36 void *ary[3]; 37 } as; 38 }; 39 40 #define mrb_ary_ptr(v) ((struct RArray*)(mrb_ptr(v))) 41 #define mrb_ary_value(p) mrb_obj_value((void*)(p)) 42 #define RARRAY(v) ((struct RArray*)(mrb_ptr(v))) 43 44 #define MRB_ARY_EMBED_MASK 7 45 #define ARY_EMBED_P(a) ((a)->flags & MRB_ARY_EMBED_MASK) 46 #define ARY_UNSET_EMBED_FLAG(a) ((a)->flags &= ~(MRB_ARY_EMBED_MASK)) 47 #define ARY_EMBED_LEN(a) ((mrb_int)(((a)->flags & MRB_ARY_EMBED_MASK) - 1)) 48 #define ARY_SET_EMBED_LEN(a,len) ((a)->flags = ((a)->flags&~MRB_ARY_EMBED_MASK) | ((uint32_t)(len) + 1)) 49 #define ARY_EMBED_PTR(a) ((mrb_value*)(&(a)->as.ary)) 50 51 #define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(a)->as.heap.len) 52 #define ARY_PTR(a) (ARY_EMBED_P(a)?ARY_EMBED_PTR(a):(a)->as.heap.ptr) 53 #define RARRAY_LEN(a) ARY_LEN(RARRAY(a)) 54 #define RARRAY_PTR(a) ARY_PTR(RARRAY(a)) 55 #define ARY_SET_LEN(a,n) do {\ 56 if (ARY_EMBED_P(a)) {\ 57 mrb_assert((n) <= MRB_ARY_EMBED_LEN_MAX); \ 58 ARY_SET_EMBED_LEN(a,n);\ 59 }\ 60 else\ 61 (a)->as.heap.len = (n);\ 62 } while (0) 63 #define ARY_CAPA(a) (ARY_EMBED_P(a)?MRB_ARY_EMBED_LEN_MAX:(a)->as.heap.aux.capa) 64 #define MRB_ARY_SHARED 256 65 #define ARY_SHARED_P(a) ((a)->flags & MRB_ARY_SHARED) 66 #define ARY_SET_SHARED_FLAG(a) ((a)->flags |= MRB_ARY_SHARED) 67 #define ARY_UNSET_SHARED_FLAG(a) ((a)->flags &= ~MRB_ARY_SHARED) 68 69 void mrb_ary_decref(mrb_state*, mrb_shared_array*); 70 MRB_API void mrb_ary_modify(mrb_state*, struct RArray*); 71 MRB_API mrb_value mrb_ary_new_capa(mrb_state*, mrb_int); 72 73 /* 74 * Initializes a new array. 75 * 76 * Equivalent to: 77 * 78 * Array.new 79 * 80 * @param mrb The mruby state reference. 81 * @return The initialized array. 82 */ 83 MRB_API mrb_value mrb_ary_new(mrb_state *mrb); 84 85 /* 86 * Initializes a new array with initial values 87 * 88 * Equivalent to: 89 * 90 * Array[value1, value2, ...] 91 * 92 * @param mrb The mruby state reference. 93 * @param size The numer of values. 94 * @param vals The actual values. 95 * @return The initialized array. 96 */ 97 MRB_API mrb_value mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals); 98 99 /* 100 * Initializes a new array with two initial values 101 * 102 * Equivalent to: 103 * 104 * Array[car, cdr] 105 * 106 * @param mrb The mruby state reference. 107 * @param car The first value. 108 * @param cdr The second value. 109 * @return The initialized array. 110 */ 111 MRB_API mrb_value mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr); 112 113 /* 114 * Concatenate two arrays. The target array will be modified 115 * 116 * Equivalent to: 117 * ary.concat(other) 118 * 119 * @param mrb The mruby state reference. 120 * @param self The target array. 121 * @param other The array that will be concatenated to self. 122 */ 123 MRB_API void mrb_ary_concat(mrb_state *mrb, mrb_value self, mrb_value other); 124 125 /* 126 * Create an array from the input. It tries calling to_a on the 127 * value. If value does not respond to that, it creates a new 128 * array with just this value. 129 * 130 * @param mrb The mruby state reference. 131 * @param value The value to change into an array. 132 * @return An array representation of value. 133 */ 134 MRB_API mrb_value mrb_ary_splat(mrb_state *mrb, mrb_value value); 135 136 /* 137 * Pushes value into array. 138 * 139 * Equivalent to: 140 * 141 * ary << value 142 * 143 * @param mrb The mruby state reference. 144 * @param ary The array in which the value will be pushed 145 * @param value The value to be pushed into array 146 */ 147 MRB_API void mrb_ary_push(mrb_state *mrb, mrb_value array, mrb_value value); 148 149 /* 150 * Pops the last element from the array. 151 * 152 * Equivalent to: 153 * 154 * ary.pop 155 * 156 * @param mrb The mruby state reference. 157 * @param ary The array from which the value will be popped. 158 * @return The popped value. 159 */ 160 MRB_API mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary); 161 162 /* 163 * Returns a reference to an element of the array on the given index. 164 * 165 * Equivalent to: 166 * 167 * ary[n] 168 * 169 * @param mrb The mruby state reference. 170 * @param ary The target array. 171 * @param n The array index being referenced 172 * @return The referenced value. 173 */ 174 MRB_API mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n); 175 176 /* 177 * Sets a value on an array at the given index 178 * 179 * Equivalent to: 180 * 181 * ary[n] = val 182 * 183 * @param mrb The mruby state reference. 184 * @param ary The target array. 185 * @param n The array index being referenced. 186 * @param val The value being setted. 187 */ 188 MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val); 189 190 /* 191 * Replace the array with another array 192 * 193 * Equivalent to: 194 * 195 * ary.replace(other) 196 * 197 * @param mrb The mruby state reference 198 * @param self The target array. 199 * @param other The array to replace it with. 200 */ 201 MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other); 202 MRB_API mrb_value mrb_ensure_array_type(mrb_state *mrb, mrb_value self); 203 MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self); 204 205 /* 206 * Unshift an element into the array 207 * 208 * Equivalent to: 209 * 210 * ary.unshift(item) 211 * 212 * @param mrb The mruby state reference. 213 * @param self The target array. 214 * @param item The item to unshift. 215 */ 216 MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item); 217 218 /* 219 * Get nth element in the array 220 * 221 * Equivalent to: 222 * 223 * ary[offset] 224 * 225 * @param ary The target array. 226 * @param offset The element position (negative counts from the tail). 227 */ 228 MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset); 229 230 /* 231 * Replace subsequence of an array. 232 * 233 * Equivalent to: 234 * 235 * ary.shift 236 * 237 * @param mrb The mruby state reference. 238 * @param self The array from which the value will be shifted. 239 * @param head Beginning position of a replacement subsequence. 240 * @param len Length of a replacement subsequence. 241 * @param rpl The array of replacement elements. 242 * It is possible to pass `mrb_undef_value()` instead of an empty array. 243 * @return The receiver array. 244 */ 245 MRB_API mrb_value mrb_ary_splice(mrb_state *mrb, mrb_value self, mrb_int head, mrb_int len, mrb_value rpl); 246 247 /* 248 * Shifts the first element from the array. 249 * 250 * Equivalent to: 251 * 252 * ary.shift 253 * 254 * @param mrb The mruby state reference. 255 * @param self The array from which the value will be shifted. 256 * @return The shifted value. 257 */ 258 MRB_API mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self); 259 260 /* 261 * Removes all elements from the array 262 * 263 * Equivalent to: 264 * 265 * ary.clear 266 * 267 * @param mrb The mruby state reference. 268 * @param self The target array. 269 * @return self 270 */ 271 MRB_API mrb_value mrb_ary_clear(mrb_state *mrb, mrb_value self); 272 273 /* 274 * Join the array elements together in a string 275 * 276 * Equivalent to: 277 * 278 * ary.join(sep="") 279 * 280 * @param mrb The mruby state reference. 281 * @param ary The target array 282 * @param sep The separater, can be NULL 283 */ 284 MRB_API mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep); 285 286 /* 287 * Update the capacity of the array 288 * 289 * @param mrb The mruby state reference. 290 * @param ary The target array. 291 * @param new_len The new capacity of the array 292 */ 293 MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len); 294 295 /* helper functions */ 296 mrb_value mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len); 297 298 MRB_END_DECL 299 300 #endif /* MRUBY_ARRAY_H */ 301