1 /*
2  *   Copyright (c) 2001, 2002 Michael J. Roberts.  All Rights Reserved.
3  *
4  *   Please see the accompanying license file, LICENSE.TXT, for information
5  *   on using and copying this software.
6  */
7 /*
8 Name
9   vmcset.h - T3 CharacterSet metaclass
10 Function
11 
12 Notes
13 
14 Modified
15   06/06/01 MJRoberts  - Creation
16 */
17 
18 #ifndef VMCSET_H
19 #define VMCSET_H
20 
21 #include <stdlib.h>
22 #include "vmtype.h"
23 #include "vmobj.h"
24 #include "vmglob.h"
25 
26 /* ------------------------------------------------------------------------ */
27 /*
28  *   A CharacterSet is a simple encapsulation of a pair of CCharmap
29  *   character mappings: one mapping from Unicode to a local character set,
30  *   and one mapping in the reverse direction.  A CharacterSet is
31  *   parameterized on creation by the name of the mapping, using the
32  *   standard CCharmap names.
33  *
34  *   In an image file, a CharacterSet contains simply the standard CCharmap
35  *   name of the mapping:
36  *
37  *   UINT2 length-in-bytes
38  *.  BYTE name[]
39  *
40  *   On creation, we will create the pair of CCharmap objects, if the name
41  *   of the mapping is valid.  It is legal to create a CharacterSet with an
42  *   unknown mapping, but such a character set object cannot be used to
43  *   perform mappings.
44  *
45  *   CharacterSet objects are constants at run-time.
46  */
47 class CVmObjCharSet: public CVmObject
48 {
49     friend class CVmMetaclassCharSet;
50 
51 public:
52     /* metaclass registration object */
53     static class CVmMetaclass *metaclass_reg_;
get_metaclass_reg()54     class CVmMetaclass *get_metaclass_reg() const { return metaclass_reg_; }
55 
56     /* am I of the given metaclass? */
is_of_metaclass(class CVmMetaclass * meta)57     virtual int is_of_metaclass(class CVmMetaclass *meta) const
58     {
59         /* try my own metaclass and my base class */
60         return (meta == metaclass_reg_
61                 || CVmObject::is_of_metaclass(meta));
62     }
63 
64     /* create dynamically using stack arguments */
65     static vm_obj_id_t create_from_stack(VMG_ const uchar **pc_ptr,
66                                          uint argc);
67 
68     /*
69      *   call a static property - we don't have any of our own, so simply
70      *   "inherit" the base class handling
71      */
call_stat_prop(VMG_ vm_val_t * result,const uchar ** pc_ptr,uint * argc,vm_prop_id_t prop)72     static int call_stat_prop(VMG_ vm_val_t *result,
73                               const uchar **pc_ptr, uint *argc,
74                               vm_prop_id_t prop)
75     {
76         /* explicitly inherit our superclass handling */
77         return CVmObject::call_stat_prop(vmg_ result, pc_ptr, argc, prop);
78     }
79 
80     /* reserve constant data */
reserve_const_data(VMG_ class CVmConstMapper *,vm_obj_id_t)81     virtual void reserve_const_data(VMG_ class CVmConstMapper *,
82                                     vm_obj_id_t /*self*/)
83     {
84         /* we can't be converted to constant data */
85     }
86 
87     /* convert to constant data */
convert_to_const_data(VMG_ class CVmConstMapper *,vm_obj_id_t)88     virtual void convert_to_const_data(VMG_ class CVmConstMapper *,
89                                        vm_obj_id_t /*self*/)
90     {
91         /*
92          *   we don't reference any data and can't be converted to constant
93          *   data ourselves, so there's nothing to do here
94          */
95     }
96 
97     /* create with no initial contents */
98     static vm_obj_id_t create(VMG_ int in_root_set);
99 
100     /* create with the given character set name */
101     static vm_obj_id_t create(VMG_ int in_root_set, const char *charset_name,
102                               size_t charset_name_len);
103 
104     /* determine if an object is a CharacterSet */
is_charset(VMG_ vm_obj_id_t obj)105     static int is_charset(VMG_ vm_obj_id_t obj)
106         { return vm_objp(vmg_ obj)->is_of_metaclass(metaclass_reg_); }
107 
108     /* notify of deletion */
109     void notify_delete(VMG_ int in_root_set);
110 
111     /* set a property */
112     void set_prop(VMG_ class CVmUndo *undo,
113                   vm_obj_id_t self, vm_prop_id_t prop, const vm_val_t *val);
114 
115     /* get a property */
116     int get_prop(VMG_ vm_prop_id_t prop, vm_val_t *val,
117                  vm_obj_id_t self, vm_obj_id_t *source_obj, uint *argc);
118 
119     /* undo operations */
notify_new_savept()120     void notify_new_savept() { }
apply_undo(VMG_ struct CVmUndoRecord *)121     void apply_undo(VMG_ struct CVmUndoRecord *) { }
122 
123     /* we reference nothing */
mark_undo_ref(VMG_ struct CVmUndoRecord *)124     void mark_undo_ref(VMG_ struct CVmUndoRecord *) { }
remove_stale_undo_weak_ref(VMG_ struct CVmUndoRecord *)125     void remove_stale_undo_weak_ref(VMG_ struct CVmUndoRecord *) { }
mark_refs(VMG_ uint)126     void mark_refs(VMG_ uint /*state*/) { }
remove_stale_weak_refs(VMG0_)127     void remove_stale_weak_refs(VMG0_) { }
128 
129     /* load from an image file */
130     void load_from_image(VMG_ vm_obj_id_t self, const char *ptr, size_t siz);
131 
132     /* rebuild for image file */
133     virtual ulong rebuild_image(VMG_ char *buf, ulong buflen);
134 
135     /* save to a file */
136     void save_to_file(VMG_ class CVmFile *fp);
137 
138     /* restore from a file */
139     void restore_from_file(VMG_ vm_obj_id_t self,
140                            class CVmFile *fp, class CVmObjFixup *fixups);
141 
142     /*
143      *   Check a value for equality.  We will match another byte array with
144      *   the same number of elements and the same value for each element.
145      */
146     int equals(VMG_ vm_obj_id_t self, const vm_val_t *val, int depth) const;
147 
148     /* calculate a hash value for the array */
149     uint calc_hash(VMG_ vm_obj_id_t self, int depth) const;
150 
151     /* our data are constant - we never change */
is_changed_since_load()152     int is_changed_since_load() const { return FALSE; }
153 
154     /*
155      *   Get the to-local and to-unicode mappers.  If the mapper isn't
156      *   available, we'll throw an UnknownCharacterSetException.
157      */
158     class CCharmapToLocal *get_to_local(VMG0_) const;
159     class CCharmapToUni *get_to_uni(VMG0_) const;
160 
161 protected:
162     /* create with no initial contents */
CVmObjCharSet()163     CVmObjCharSet() { ext_ = 0; }
164 
165     /* create from the given character set name */
166     CVmObjCharSet(VMG_ const char *charset_name, size_t charset_name_len);
167 
168     /* allocate and initialize */
169     void alloc_ext(VMG_ const char *charset_name, size_t charset_name_len);
170 
171     /* get a pointer to my extension */
get_ext_ptr()172     const struct vmobj_charset_ext_t *get_ext_ptr() const
173         { return (vmobj_charset_ext_t *)ext_; }
174 
175     /* does the given unicode character have a round-trip mapping? */
176     static int is_rt_mappable(wchar_t c, class CCharmapToLocal *to_local,
177                               class CCharmapToUni *to_uni);
178 
179     /* property evaluator - undefined function */
getp_undef(VMG_ vm_obj_id_t,vm_val_t *,uint *)180     int getp_undef(VMG_ vm_obj_id_t, vm_val_t *, uint *) { return FALSE; }
181 
182     /* property evaluator - get the character set name */
183     int getp_get_name(VMG_ vm_obj_id_t self, vm_val_t *val, uint *argc);
184 
185     /* determine if the mapping is known */
186     int getp_is_known(VMG_ vm_obj_id_t self, vm_val_t *val, uint *argc);
187 
188     /*
189      *   property evaluator - determine if the a character code (given as an
190      *   integer) or the characters in a string can be mapped from Unicode
191      *   to this local character set
192      */
193     int getp_is_mappable(VMG_ vm_obj_id_t self, vm_val_t *val, uint *argc);
194 
195     /*
196      *   property evaluator - determine if the character code (given as an
197      *   integer) or the characters in a string have a round-trip mapping
198      *   from Unicode to local and back
199      */
200     int getp_is_rt_mappable(VMG_ vm_obj_id_t self, vm_val_t *val, uint *argc);
201 
202     /* property evaluation function table */
203     static int (CVmObjCharSet::*func_table_[])(
204         VMG_ vm_obj_id_t self, vm_val_t *retval, uint *argc);
205 };
206 
207 /*
208  *   Our extension structure
209  */
210 struct vmobj_charset_ext_t
211 {
212     /* unicode-to-local mapping object */
213     class CCharmapToLocal *to_local;
214 
215     /* local-to-unicode mapping object */
216     class CCharmapToUni *to_uni;
217 
218     /* length of character set name */
219     size_t charset_name_len;
220 
221     /* name of the character set */
222     char charset_name[1];
223 };
224 
225 /* ------------------------------------------------------------------------ */
226 /*
227  *   Registration table object
228  */
229 class CVmMetaclassCharSet: public CVmMetaclass
230 {
231 public:
232     /* get the global name */
get_meta_name()233     const char *get_meta_name() const { return "character-set/030001"; }
234 
235     /* create from image file */
create_for_image_load(VMG_ vm_obj_id_t id)236     void create_for_image_load(VMG_ vm_obj_id_t id)
237     {
238         new (vmg_ id) CVmObjCharSet();
239         G_obj_table->set_obj_gc_characteristics(id, FALSE, FALSE);
240     }
241 
242     /* create from restoring from saved state */
create_for_restore(VMG_ vm_obj_id_t id)243     void create_for_restore(VMG_ vm_obj_id_t id)
244     {
245         new (vmg_ id) CVmObjCharSet();
246         G_obj_table->set_obj_gc_characteristics(id, FALSE, FALSE);
247     }
248 
249     /* create dynamically using stack arguments */
create_from_stack(VMG_ const uchar ** pc_ptr,uint argc)250     vm_obj_id_t create_from_stack(VMG_ const uchar **pc_ptr, uint argc)
251         { return CVmObjCharSet::create_from_stack(vmg_ pc_ptr, argc); }
252 
253     /* call a static property */
call_stat_prop(VMG_ vm_val_t * result,const uchar ** pc_ptr,uint * argc,vm_prop_id_t prop)254     int call_stat_prop(VMG_ vm_val_t *result,
255                        const uchar **pc_ptr, uint *argc,
256                        vm_prop_id_t prop)
257     {
258         return CVmObjCharSet::call_stat_prop(vmg_ result, pc_ptr, argc, prop);
259     }
260 };
261 
262 #endif /* VMCSET_H */
263 
264 /*
265  *   Register the class
266  */
267 VM_REGISTER_METACLASS(CVmObjCharSet)
268