1 /* $Header$ */ 2 3 /* 4 * Copyright (c) 2000, 2002 Michael J. Roberts. All Rights Reserved. 5 * 6 * Please see the accompanying license file, LICENSE.TXT, for information 7 * on using and copying this software. 8 */ 9 /* 10 Name 11 vmiter.h - Iterator metaclass 12 Function 13 14 Notes 15 16 Modified 17 04/22/00 MJRoberts - Creation 18 */ 19 20 #ifndef VMITER_H 21 #define VMITER_H 22 23 #include <stdlib.h> 24 #include "vmtype.h" 25 #include "vmobj.h" 26 #include "vmglob.h" 27 28 /* ------------------------------------------------------------------------ */ 29 /* 30 * Base Iterator class 31 */ 32 class CVmObjIter: public CVmObject 33 { 34 friend class CVmMetaclassIter; 35 36 public: 37 /* metaclass registration object */ 38 static class CVmMetaclass *metaclass_reg_; get_metaclass_reg()39 class CVmMetaclass *get_metaclass_reg() const { return metaclass_reg_; } 40 41 /* am I of the given metaclass? */ is_of_metaclass(class CVmMetaclass * meta)42 virtual int is_of_metaclass(class CVmMetaclass *meta) const 43 { 44 /* try my own metaclass and my base class */ 45 return (meta == metaclass_reg_ 46 || CVmObject::is_of_metaclass(meta)); 47 } 48 49 /* 50 * call a static property - we don't have any of our own, so simply 51 * "inherit" the base class handling 52 */ call_stat_prop(VMG_ vm_val_t * result,const uchar ** pc_ptr,uint * argc,vm_prop_id_t prop)53 static int call_stat_prop(VMG_ vm_val_t *result, 54 const uchar **pc_ptr, uint *argc, 55 vm_prop_id_t prop) 56 { return CVmObject::call_stat_prop(vmg_ result, pc_ptr, argc, prop); } 57 58 /* set a property */ set_prop(VMG_ class CVmUndo *,vm_obj_id_t,vm_prop_id_t,const vm_val_t *)59 void set_prop(VMG_ class CVmUndo *, 60 vm_obj_id_t, vm_prop_id_t, const vm_val_t *) 61 { 62 /* cannot set iterator properties */ 63 err_throw(VMERR_INVALID_SETPROP); 64 } 65 66 /* get a property */ 67 int get_prop(VMG_ vm_prop_id_t prop, vm_val_t *val, 68 vm_obj_id_t self, vm_obj_id_t *source_obj, uint *argc); 69 70 protected: 71 /* property evaluator - undefined property */ getp_undef(VMG_ vm_obj_id_t,vm_val_t *,uint *)72 int getp_undef(VMG_ vm_obj_id_t, vm_val_t *, uint *) { return FALSE; } 73 74 /* property evaluator - get next value */ 75 virtual int getp_get_next(VMG_ vm_obj_id_t self, vm_val_t *retval, 76 uint *argc) = 0; 77 78 /* property evaluator - is next value available? */ 79 virtual int getp_is_next_avail(VMG_ vm_obj_id_t self, vm_val_t *retval, 80 uint *argc) = 0; 81 82 /* property evaluator - reset to first item */ 83 virtual int getp_reset_iter(VMG_ vm_obj_id_t self, vm_val_t *retval, 84 uint *argc) = 0; 85 86 87 /* property evaluator - get current key */ 88 virtual int getp_get_cur_key(VMG_ vm_obj_id_t self, vm_val_t *retval, 89 uint *argc) = 0; 90 91 /* property evaluator - get current value */ 92 virtual int getp_get_cur_val(VMG_ vm_obj_id_t self, vm_val_t *retval, 93 uint *argc) = 0; 94 95 /* function table */ 96 static int (CVmObjIter::*func_table_[])(VMG_ vm_obj_id_t self, 97 vm_val_t *retval, uint *argc); 98 }; 99 100 101 /* ------------------------------------------------------------------------ */ 102 /* 103 * Indexed Iterator subclass. An indexed iterator works with arrays, 104 * lists, and other collections that can be accessed via an integer 105 * index. 106 */ 107 108 /* 109 * The extension data for an indexed iterator consists of a reference to 110 * the associated indexed collection, the index value of the next item 111 * to be retrieved, and the first and last valid index values: Note that 112 * the collection value can be an object ID or a constant VM_LIST value. 113 * 114 * DATAHOLDER collection_value 115 *. UINT4 cur_index 116 *. UINT4 first_valid 117 *. UINT4 last_valid 118 *. UINT4 flags 119 * 120 * The flag values are: 121 * 122 * VMOBJITERIDX_UNDO - we've saved undo for this savepoint. If this is 123 * set, we won't save additional undo for the same savepoint. 124 */ 125 126 /* total extension size */ 127 #define VMOBJITERIDX_EXT_SIZE (VMB_DATAHOLDER + 16) 128 129 /* 130 * flag bits 131 */ 132 133 /* we've saved undo for the current savepoint */ 134 #define VMOBJITERIDX_UNDO 0x0001 135 136 /* 137 * indexed iterator class 138 */ 139 class CVmObjIterIdx: public CVmObjIter 140 { 141 friend class CVmMetaclassIterIdx; 142 143 public: 144 /* metaclass registration object */ 145 static class CVmMetaclass *metaclass_reg_; get_metaclass_reg()146 class CVmMetaclass *get_metaclass_reg() const { return metaclass_reg_; } 147 148 /* am I of the given metaclass? */ is_of_metaclass(class CVmMetaclass * meta)149 virtual int is_of_metaclass(class CVmMetaclass *meta) const 150 { 151 /* try my own metaclass and my base class */ 152 return (meta == metaclass_reg_ 153 || CVmObjIter::is_of_metaclass(meta)); 154 } 155 156 /* 157 * call a static property - we don't have any of our own, so simply 158 * "inherit" the base class handling 159 */ call_stat_prop(VMG_ vm_val_t * result,const uchar ** pc_ptr,uint * argc,vm_prop_id_t prop)160 static int call_stat_prop(VMG_ vm_val_t *result, 161 const uchar **pc_ptr, uint *argc, 162 vm_prop_id_t prop) 163 { 164 return CVmObjIter::call_stat_prop(vmg_ result, pc_ptr, argc, prop); 165 } 166 167 /* 168 * Create an indexed iterator. This method is to be called by a 169 * list, array, or other indexed collection object to create an 170 * iterator for its value. 171 */ 172 static vm_obj_id_t create_for_coll(VMG_ const vm_val_t *coll, 173 long first_valid_index, 174 long last_valid_index); 175 176 /* notify of deletion */ 177 void notify_delete(VMG_ int in_root_set); 178 179 /* 180 * notify of a new savepoint - clear the 'undo' flag, since we 181 * cannot have created any undo information yet for the new 182 * savepoint 183 */ notify_new_savept()184 void notify_new_savept() 185 { set_flags(get_flags() & ~VMOBJITERIDX_UNDO); } 186 187 /* apply undo */ 188 void apply_undo(VMG_ struct CVmUndoRecord *rec); 189 190 /* mark references */ 191 void mark_refs(VMG_ uint state); 192 193 /* there are no references in our undo stream */ mark_undo_ref(VMG_ struct CVmUndoRecord *)194 void mark_undo_ref(VMG_ struct CVmUndoRecord *) { } 195 196 /* we keep only strong references */ remove_stale_weak_refs(VMG0_)197 void remove_stale_weak_refs(VMG0_) { } remove_stale_undo_weak_ref(VMG_ struct CVmUndoRecord *)198 void remove_stale_undo_weak_ref(VMG_ struct CVmUndoRecord *) { } 199 200 /* load from an image file */ 201 void load_from_image(VMG_ vm_obj_id_t self, const char *ptr, size_t siz); 202 203 /* restore to image file state */ 204 void reload_from_image(VMG_ vm_obj_id_t self, 205 const char *ptr, size_t siz); 206 207 /* 208 * determine if the object has been changed since it was loaded - 209 * assume we have, since saving and reloading are very cheap 210 */ is_changed_since_load()211 int is_changed_since_load() const { return TRUE; } 212 213 /* save to a file */ 214 void save_to_file(VMG_ class CVmFile *fp); 215 216 /* restore from a file */ 217 void restore_from_file(VMG_ vm_obj_id_t self, 218 class CVmFile *fp, class CVmObjFixup *fixups); 219 220 /* rebuild for image file */ 221 virtual ulong rebuild_image(VMG_ char *buf, ulong buflen); 222 223 /* convert to constant data */ 224 virtual void convert_to_const_data(VMG_ class CVmConstMapper *mapper, 225 vm_obj_id_t self); 226 227 protected: 228 /* create */ CVmObjIterIdx()229 CVmObjIterIdx() { ext_ = 0; } 230 231 /* create */ 232 CVmObjIterIdx(VMG_ const vm_val_t *coll, long first_valid_index, 233 long last_valid_index); 234 235 /* get the value from the collection for a given index */ 236 void get_indexed_val(VMG_ long idx, vm_val_t *retval); 237 238 /* property evaluator - get next value */ 239 virtual int getp_get_next(VMG_ vm_obj_id_t self, vm_val_t *retval, 240 uint *argc); 241 242 /* property evaluator - is next value available? */ 243 virtual int getp_is_next_avail(VMG_ vm_obj_id_t self, vm_val_t *retval, 244 uint *argc); 245 246 /* property evaluator - reset to first item */ 247 virtual int getp_reset_iter(VMG_ vm_obj_id_t self, vm_val_t *retval, 248 uint *argc); 249 250 /* property evaluator - get current key */ 251 virtual int getp_get_cur_key(VMG_ vm_obj_id_t self, vm_val_t *retval, 252 uint *argc); 253 254 /* property evaluator - get current value */ 255 virtual int getp_get_cur_val(VMG_ vm_obj_id_t self, vm_val_t *retval, 256 uint *argc); 257 258 /* get my collection value */ get_coll_val(vm_val_t * val)259 void get_coll_val(vm_val_t *val) { vmb_get_dh(ext_, val); } 260 261 /* get/set the current index (without saving undo) */ get_cur_index()262 long get_cur_index() const 263 { return osrp4(ext_ + VMB_DATAHOLDER); } set_cur_index_no_undo(long idx)264 void set_cur_index_no_undo(long idx) 265 { oswp4(ext_ + VMB_DATAHOLDER, idx); } 266 267 /* set the index value, saving undo if necessary */ 268 void set_cur_index(VMG_ vm_obj_id_t self, long idx); 269 270 /* get my first/last valid index values */ get_first_valid()271 long get_first_valid() const 272 { return osrp4(ext_ + VMB_DATAHOLDER + 4); } get_last_valid()273 long get_last_valid() const 274 { return osrp4(ext_ + VMB_DATAHOLDER + 8); } 275 276 /* set my first/last valid index values - for construction only */ set_first_valid(long idx)277 void set_first_valid(long idx) const 278 { oswp4(ext_ + VMB_DATAHOLDER + 4, idx); } set_last_valid(long idx)279 void set_last_valid(long idx) const 280 { oswp4(ext_ + VMB_DATAHOLDER + 8, idx); } 281 282 /* get/set the flags */ get_flags()283 unsigned long get_flags() const 284 { return osrp4(ext_ + VMB_DATAHOLDER + 12); } set_flags(unsigned long flags)285 void set_flags(unsigned long flags) const 286 { oswp4(ext_ + VMB_DATAHOLDER + 12, flags); } 287 }; 288 289 290 /* ------------------------------------------------------------------------ */ 291 /* 292 * Registration table object for the base iterator class 293 */ 294 class CVmMetaclassIter: public CVmMetaclass 295 { 296 public: 297 /* get the global name */ get_meta_name()298 const char *get_meta_name() const { return "iterator/030001"; } 299 300 /* create from image file */ create_for_image_load(VMG_ vm_obj_id_t id)301 void create_for_image_load(VMG_ vm_obj_id_t id) 302 { err_throw(VMERR_BAD_STATIC_NEW); } 303 304 /* create from restoring from saved state */ create_for_restore(VMG_ vm_obj_id_t id)305 void create_for_restore(VMG_ vm_obj_id_t id) 306 { err_throw(VMERR_BAD_STATIC_NEW); } 307 308 /* create dynamically using stack arguments */ create_from_stack(VMG_ const uchar ** pc_ptr,uint argc)309 vm_obj_id_t create_from_stack(VMG_ const uchar **pc_ptr, uint argc) 310 { 311 err_throw(VMERR_BAD_DYNAMIC_NEW); 312 return VM_INVALID_OBJ; 313 } 314 315 /* call a static property */ call_stat_prop(VMG_ vm_val_t * result,const uchar ** pc_ptr,uint * argc,vm_prop_id_t prop)316 int call_stat_prop(VMG_ vm_val_t *result, 317 const uchar **pc_ptr, uint *argc, 318 vm_prop_id_t prop) 319 { 320 return CVmObjIter::call_stat_prop(vmg_ result, pc_ptr, argc, prop); 321 } 322 }; 323 324 /* 325 * Registration table object for indexed iterators 326 */ 327 class CVmMetaclassIterIdx: public CVmMetaclass 328 { 329 public: 330 /* get the global name */ get_meta_name()331 const char *get_meta_name() const { return "indexed-iterator/030000"; } 332 333 /* create from image file */ create_for_image_load(VMG_ vm_obj_id_t id)334 void create_for_image_load(VMG_ vm_obj_id_t id) 335 { 336 new (vmg_ id) CVmObjIterIdx(); 337 G_obj_table->set_obj_gc_characteristics(id, TRUE, FALSE); 338 } 339 340 /* create from restoring from saved state */ create_for_restore(VMG_ vm_obj_id_t id)341 void create_for_restore(VMG_ vm_obj_id_t id) 342 { 343 new (vmg_ id) CVmObjIterIdx(); 344 G_obj_table->set_obj_gc_characteristics(id, TRUE, FALSE); 345 } 346 347 /* create dynamically using stack arguments */ create_from_stack(VMG_ const uchar ** pc_ptr,uint argc)348 vm_obj_id_t create_from_stack(VMG_ const uchar **pc_ptr, uint argc) 349 { 350 err_throw(VMERR_BAD_DYNAMIC_NEW); 351 return VM_INVALID_OBJ; 352 } 353 354 /* call a static property */ call_stat_prop(VMG_ vm_val_t * result,const uchar ** pc_ptr,uint * argc,vm_prop_id_t prop)355 int call_stat_prop(VMG_ vm_val_t *result, 356 const uchar **pc_ptr, uint *argc, 357 vm_prop_id_t prop) 358 { 359 return CVmObjIterIdx::call_stat_prop(vmg_ result, pc_ptr, argc, prop); 360 } 361 }; 362 363 #endif /* VMITER_H */ 364 365 /* 366 * Register the class 367 */ 368 VM_REGISTER_METACLASS(CVmObjIter) 369 VM_REGISTER_METACLASS(CVmObjIterIdx) 370 371