cfad47cfa3/tads3/vmiter.h

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
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_;
39
    class CVmMetaclass *get_metaclass_reg() const { return metaclass_reg_; }
40
41
    /* am I of the given metaclass? */
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
     */
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 */
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 */
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_;
146
    class CVmMetaclass *get_metaclass_reg() const { return metaclass_reg_; }
147
148
    /* am I of the given metaclass? */
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
     */
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
     */
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 */
194
    void mark_undo_ref(VMG_ struct CVmUndoRecord *) { }
195
196
    /* we keep only strong references */
197
    void remove_stale_weak_refs(VMG0_) { }
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
     */
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 */
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 */
259
    void get_coll_val(vm_val_t *val) { vmb_get_dh(ext_, val); }
260
261
    /* get/set the current index (without saving undo) */
262
    long get_cur_index() const
263
        { return t3rp4u(ext_ + VMB_DATAHOLDER); }
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 */
271
    long get_first_valid() const
272
        { return t3rp4u(ext_ + VMB_DATAHOLDER + 4); }
273
    long get_last_valid() const
274
        { return t3rp4u(ext_ + VMB_DATAHOLDER + 8); }
275
276
    /* set my first/last valid index values - for construction only */
277
    void set_first_valid(long idx) const
278
        { oswp4(ext_ + VMB_DATAHOLDER + 4, idx); }
279
    void set_last_valid(long idx) const
280
        { oswp4(ext_ + VMB_DATAHOLDER + 8, idx); }
281
282
    /* get/set the flags */
283
    unsigned long get_flags() const
284
        { return t3rp4u(ext_ + VMB_DATAHOLDER + 12); }
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 */
298
    const char *get_meta_name() const { return "iterator/030001"; }
299
300
    /* create from image file */
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 */
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 */
309
    vm_obj_id_t create_from_stack(VMG_ const uchar **pc_ptr, uint argc)
310
    {
311
        err_throw(VMERR_BAD_DYNAMIC_NEW);
312
        AFTER_ERR_THROW(return VM_INVALID_OBJ;)
313
    }
314
315
    /* call a static property */
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 */
331
    const char *get_meta_name() const { return "indexed-iterator/030000"; }
332
333
    /* create from image file */
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 */
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 */
348
    vm_obj_id_t create_from_stack(VMG_ const uchar **pc_ptr, uint argc)
349
    {
350
        err_throw(VMERR_BAD_DYNAMIC_NEW);
351
        AFTER_ERR_THROW(return VM_INVALID_OBJ;)
352
    }
353
354
    /* call a static property */
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