cfad47cfa3/tads3/vmstr.h
Commiter: Nikos Chantziaras
Author: Nikos Chantziaras
Revision: cfad47cfa3
File Size: 16.6 KB
(June 01, 2009 20:54 UTC) Almost 3 years ago
Initial commit.
/* $Header: d:/cvsroot/tads/tads3/VMSTR.H,v 1.2 1999/05/17 02:52:28 MJRoberts Exp $ */
/*
* Copyright (c) 1998, 2002 Michael J. Roberts. All Rights Reserved.
*
* Please see the accompanying license file, LICENSE.TXT, for information
* on using and copying this software.
*/
/*
Name
vmstr.h - VM dynamic string implementation
Function
Notes
Modified
10/28/98 MJRoberts - Creation
*/
#ifndef VMSTR_H
#define VMSTR_H
#include "vmglob.h"
#include "vmobj.h"
class CVmObjString: public CVmObject
{
friend class CVmMetaclassString;
public:
/* metaclass registration object */
static class CVmMetaclass *metaclass_reg_;
class CVmMetaclass *get_metaclass_reg() const { return metaclass_reg_; }
/* am I of the given metaclass? */
virtual int is_of_metaclass(class CVmMetaclass *meta) const
{
/* try my own metaclass and my base class */
return (meta == metaclass_reg_
|| CVmObject::is_of_metaclass(meta));
}
/* create from stack arguments */
static vm_obj_id_t create_from_stack(VMG_ const uchar **pc_ptr,
uint argc);
/* reserve constant data */
virtual void reserve_const_data(VMG_ class CVmConstMapper *mapper,
vm_obj_id_t self);
/* convert to constant data */
virtual void convert_to_const_data(VMG_ class CVmConstMapper *mapper,
vm_obj_id_t self);
/* get my datatype when converted to constant data */
virtual vm_datatype_t get_convert_to_const_data_type() const
{ return VM_SSTRING; }
/* create a string with no initial contents */
static vm_obj_id_t create(VMG_ int in_root_set);
/* create a string to hold a string of the given byte length */
static vm_obj_id_t create(VMG_ int in_root_set, size_t bytelen);
/* create from a constant UTF-8 string */
static vm_obj_id_t create(VMG_ int in_root_set,
const char *str, size_t bytelen);
/*
* For construction: get a pointer to the string's underlying
* buffer. Returns a pointer into which the caller can write. The
* buffer starts after the length prefix.
*/
char *cons_get_buf() const { return ext_ + 2; }
/*
* For construction: set my length. This can be used if the string
* stored is smaller than the buffer allocated. This cannot be used
* to expand the buffer, since this merely writes the length prefix
* and does not reallocate the buffer.
*/
void cons_set_len(size_t len) { vmb_put_len(ext_, len); }
/* notify of deletion */
void notify_delete(VMG_ int in_root_set);
/* set a property */
void set_prop(VMG_ class CVmUndo *undo,
vm_obj_id_t self, vm_prop_id_t prop, const vm_val_t *val);
/*
* call a static property - we don't have any of our own, so simply
* "inherit" the base class handling
*/
static int call_stat_prop(VMG_ vm_val_t *result,
const uchar **pc_ptr, uint *argc,
vm_prop_id_t prop)
{ return CVmObject::call_stat_prop(vmg_ result, pc_ptr, argc, prop); }
/* undo operations - strings are immutable and hence keep no undo */
void notify_new_savept() { }
void apply_undo(VMG_ struct CVmUndoRecord *) { };
void mark_undo_ref(VMG_ struct CVmUndoRecord *) { }
void remove_stale_undo_weak_ref(VMG_ struct CVmUndoRecord *) { }
/* reference operations - strings reference no other objects */
void mark_refs(VMG_ uint state) { }
void remove_stale_weak_refs(VMG0_) { }
/* load from an image file */
void load_from_image(VMG_ vm_obj_id_t, const char *ptr, size_t)
{ ext_ = (char *)ptr; }
/* rebuild for image file */
virtual ulong rebuild_image(VMG_ char *buf, ulong buflen);
/* save to a file */
void save_to_file(VMG_ class CVmFile *fp);
/* restore from a file */
void restore_from_file(VMG_ vm_obj_id_t self,
class CVmFile *fp, class CVmObjFixup *fixups);
/*
* add a value to the string -- this creates a new string by
* appending the value to this string
*/
void add_val(VMG_ vm_val_t *result,
vm_obj_id_t self, const vm_val_t *val);
/*
* Get a string representation of the object. This is trivial for a
* string object - we simply return our extension, which contains
* the string in the required format.
*/
const char *cast_to_string(VMG_ vm_obj_id_t self,
vm_val_t *new_str) const
{
/* we are the string object */
new_str->set_obj(self);
/* return our extension directly */
return ext_;
}
/* get the underlying string */
const char *get_as_string(VMG0_) const { return ext_; }
/*
* Static routine to add a value to a string constant. Creates a
* new string by appending the given value to the given string
* constant. The string constant must be stored in portable format:
* the first two bytes are the length prefix, in UINT2 format,
* giving the length of the string's contents not counting the
* prefix itself; immediately following the length prefix are the
* bytes of the string's contents.
*/
static void add_to_str(VMG_ vm_val_t *result,
vm_obj_id_t self, const char *strval,
const vm_val_t *val);
/*
* Check a value for equality. We will match any constant string
* that contains the same text as our string, and any other string
* object with the same text.
*/
int equals(VMG_ vm_obj_id_t self, const vm_val_t *val, int depth) const;
/*
* Compare the string to another value. If the other value is a
* constant string or string object, we'll perform a lexical
* comparison of the string; other types are not comparable to
* strings, so we'll throw an error for any other type.
*/
int compare_to(VMG_ vm_obj_id_t self, const vm_val_t *val) const;
/* calculate a hash */
uint calc_hash(VMG_ vm_obj_id_t self, int depth) const;
/*
* Convert a value to a string. Throws an error if the value is not
* convertible to a string.
*
* The result is stored in the given buffer, if possible, in
* portable string format (with a portable UINT2 length prefix
* followed by the string's bytes). If the buffer is not provided
* or is not large enough to contain the result, we will allocate a
* new string object and return its contents; since the string
* object will never be referenced by anyone, it will be deleted in
* the next garbage collection pass. In any case, we will return a
* pointer to a buffer containing the result string.
*
* We'll fill in *new_obj with the new string object value, or nil
* if we don't create a new string; this allows the caller to
* protect the allocated object from garbage collection if
* necessary.
*/
static const char *cvt_to_str(VMG_ vm_val_t *new_obj,
char *result_buf, size_t result_buf_size,
const vm_val_t *val, int radix);
/*
* Convert an integer to a string, storing the result in the given
* buffer in portable string format (with length prefix). The radix
* must be 8, 10, or 16.
*
* Decimal numbers are treated as signed, and a leading dash is
* included if the number is negative. Octal and hex numbers are
* treated as unsigned.
*
* For efficiency, we store the number at the end of the buffer
* (this makes it easy to generate the number, since we need to
* generate numerals in reverse order). We return a pointer to the
* result, which may not start at the beginning of the buffer.
*/
static char *cvt_int_to_str(char *buf, size_t buflen,
int32 inval, int radix);
/*
* Allocate a string buffer large enough to hold a given value.
* We'll use the provided buffer if possible.
*
* If the provided buffer is null or is not large enough, we'll
* allocate a new string object with a large enough buffer to hold
* the value, and return the object's extension as the buffer.
*
* The buffer size and requested size are in bytes.
*
* If we allocate a new object, we'll set new_obj to the object
* value; otherwise we'll set new_obj to nil.
*/
static char *alloc_str_buf(VMG_ vm_val_t *new_obj,
char *buf, size_t buf_size,
size_t required_size);
/*
* Constant string equality test routine. Compares the given
* constant string (in portable format, with leading UINT2 length
* prefix followed by the string's text in UTF8 format) to the other
* value. Returns true if the values are lexically identical, false
* if not or if the other value is not a string of some kind.
*/
static int const_equals(VMG_ const char *str, const vm_val_t *val);
/*
* Constant string hash value calculation
*/
static uint const_calc_hash(const char *str);
/*
* Constant string magnitude comparison routine. Compares the given
* constant string (in portable format) to the other value. Returns
* a positive value if the constant string is lexically greater than
* the other value, a negative value if the constant string is
* lexically less than the other value, or zero if the two values
* are identical. Throws an error for any other type of value.
*/
static int const_compare(VMG_ const char *str, const vm_val_t *val);
/*
* Find a substring within a string. Returns a pointer to to the
* start of the substring within the string, or null if the
* substring isn't found. If 'idxp' is non-null, we'll fill in
* *idxp with the character index, starting at zero for the first
* character, of the substring within the string.
*
* Both strings are in standard constant string format, with UINT2
* length prefixes.
*/
static const char *find_substr(VMG_ const char *str, int start_idx,
const char *substr, size_t *idxp);
/*
* Evaluate a property of a constant string value. Returns true if
* we successfully evaluated the property, false if the property is
* not one of the properties that the string class defines.
*/
static int const_get_prop(VMG_ vm_val_t *retval, const vm_val_t *self_val,
const char *str, vm_prop_id_t prop,
vm_obj_id_t *srcobj, uint *argc);
/* evaluate a property */
virtual int get_prop(VMG_ vm_prop_id_t prop, vm_val_t *val,
vm_obj_id_t self, vm_obj_id_t *source_obj,
uint *argc);
/* property evaluator - undefined property */
static int getp_undef(VMG_ vm_val_t *, const vm_val_t *,
const char *, uint *)
{ return FALSE; }
/* property evaluator - get the length */
static int getp_len(VMG_ vm_val_t *retval, const vm_val_t *self_val,
const char *str, uint *argc);
/* property evaluator - extract a substring */
static int getp_substr(VMG_ vm_val_t *retval, const vm_val_t *self_val,
const char *str, uint *argc);
/* property evaluator - toUpper */
static int getp_upper(VMG_ vm_val_t *retval, const vm_val_t *self_val,
const char *str, uint *argc);
/* property evaluator - toLower */
static int getp_lower(VMG_ vm_val_t *retval, const vm_val_t *self_val,
const char *str, uint *argc);
/* property evaluator - find substring */
static int getp_find(VMG_ vm_val_t *retval, const vm_val_t *self_val,
const char *str, uint *argc);
/* property evaluator - convert to unicode */
static int getp_to_uni(VMG_ vm_val_t *retval, const vm_val_t *self_val,
const char *str, uint *argc);
/* property evaluator - htmlify */
static int getp_htmlify(VMG_ vm_val_t *retval, const vm_val_t *self_val,
const char *str, uint *argc);
/* property evaluator - startsWith */
static int getp_starts_with(VMG_ vm_val_t *retval,
const vm_val_t *self_val,
const char *str, uint *argc);
/* property evaluator - endsWith */
static int getp_ends_with(VMG_ vm_val_t *retval,
const vm_val_t *self_val,
const char *str, uint *argc);
/* property evaluator - mapToByteArray */
static int getp_to_byte_array(VMG_ vm_val_t *retval,
const vm_val_t *self_val,
const char *str, uint *argc);
/* property evaluator - replace substring */
static int getp_replace(VMG_ vm_val_t *retval, const vm_val_t *self_val,
const char *str, uint *argc);
protected:
/* create a string with no initial contents */
CVmObjString() { ext_ = 0; }
/* create with a given buffer size in bytes */
CVmObjString(VMG_ size_t bytelen);
/* create from a constant UTF-8 string */
CVmObjString(VMG_ const char *str, size_t bytelen);
/*
* Set the length of the string. This can be used after a string is
* constructed to set the size of the actual stored string.
*/
void set_length(size_t bytelen) { vmb_put_len(ext_, bytelen); }
/* copy bytes into the string buffer */
void copy_into_str(const char *str, size_t bytelen)
{ memcpy(ext_ + VMB_LEN, str, bytelen); }
/* copy bytes into the string buffer starting at the given byte offset */
void copy_into_str(size_t ofs, const char *str, size_t bytelen)
{ memcpy(ext_ + VMB_LEN + ofs, str, bytelen); }
/* property evaluation function table */
static int (*func_table_[])(VMG_ vm_val_t *retval,
const vm_val_t *self_val,
const char *str, uint *argc);
};
/* ------------------------------------------------------------------------ */
/*
* A constant string is exactly like an ordinary string, except that our
* contents come from the constant pool. We store a pointer directly to
* our constant pool data rather than making a separate copy. The only
* thing we have to do differently from an ordinary string is that we don't
* delete our extension when we're deleted, since our extension is really
* just a pointer into the constant pool.
*/
class CVmObjStringConst: public CVmObjString
{
public:
/* notify of deletion */
void notify_delete(VMG_ int /*in_root_set*/)
{
/*
* do nothing, since our extension is just a pointer into the
* constant pool
*/
}
/* create from constant pool data */
static vm_obj_id_t create(VMG_ const char *const_ptr);
protected:
/* construct from constant pool data */
CVmObjStringConst(VMG_ const char *const_ptr)
{
/* point our extension directly to the constant pool data */
ext_ = (char *)const_ptr;
}
};
/* ------------------------------------------------------------------------ */
/*
* Registration table object
*/
class CVmMetaclassString: public CVmMetaclass
{
public:
/* get the global name */
const char *get_meta_name() const { return "string/030005"; }
/* create from image file */
void create_for_image_load(VMG_ vm_obj_id_t id)
{
new (vmg_ id) CVmObjString();
G_obj_table->set_obj_gc_characteristics(id, FALSE, FALSE);
}
/* create from restoring from saved state */
void create_for_restore(VMG_ vm_obj_id_t id)
{
new (vmg_ id) CVmObjString();
G_obj_table->set_obj_gc_characteristics(id, FALSE, FALSE);
}
/* create dynamically using stack arguments */
vm_obj_id_t create_from_stack(VMG_ const uchar **pc_ptr, uint argc)
{ return CVmObjString::create_from_stack(vmg_ pc_ptr, argc); }
/* call a static property */
int call_stat_prop(VMG_ vm_val_t *result,
const uchar **pc_ptr, uint *argc,
vm_prop_id_t prop)
{
return CVmObjString::call_stat_prop(vmg_ result, pc_ptr, argc, prop);
}
};
#endif /* VMSTR_H */
/*
* Register the class
*/
VM_REGISTER_METACLASS(CVmObjString)
|