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