factor/vm/strings.cpp

199 lines
4.5 KiB
C++
Raw Normal View History

2009-05-02 05:04:19 -04:00
#include "master.hpp"
2009-05-04 02:46:13 -04:00
namespace factor
{
2009-09-23 14:05:46 -04:00
cell factor_vm::string_nth(string* str, cell index)
2009-05-02 05:04:19 -04:00
{
/* If high bit is set, the most significant 16 bits of the char
come from the aux vector. The least significant bit of the
corresponding aux vector entry is negated, so that we can
XOR the two components together and get the original code point
back. */
2009-05-04 05:50:24 -04:00
cell lo_bits = str->data()[index];
if((lo_bits & 0x80) == 0)
return lo_bits;
2009-05-02 05:04:19 -04:00
else
{
2009-05-04 05:50:24 -04:00
byte_array *aux = untag<byte_array>(str->aux);
cell hi_bits = aux->data<u16>()[index];
return (hi_bits << 7) ^ lo_bits;
2009-05-02 05:04:19 -04:00
}
}
2009-09-23 14:05:46 -04:00
void factor_vm::set_string_nth_fast(string *str, cell index, cell ch)
2009-05-02 05:04:19 -04:00
{
2009-05-04 05:50:24 -04:00
str->data()[index] = ch;
2009-05-02 05:04:19 -04:00
}
2009-09-23 14:05:46 -04:00
void factor_vm::set_string_nth_slow(string *str_, cell index, cell ch)
2009-05-02 05:04:19 -04:00
{
gc_root<string> str(str_,this);
2009-05-02 10:19:09 -04:00
2009-05-04 05:50:24 -04:00
byte_array *aux;
2009-05-02 05:04:19 -04:00
2009-05-04 05:50:24 -04:00
str->data()[index] = ((ch & 0x7f) | 0x80);
2009-05-02 05:04:19 -04:00
2009-05-04 05:50:24 -04:00
if(str->aux == F)
2009-05-02 05:04:19 -04:00
{
/* We don't need to pre-initialize the
byte array with any data, since we
only ever read from the aux vector
if the most significant bit of a
character is set. Initially all of
the bits are clear. */
2009-05-04 05:50:24 -04:00
aux = allot_array_internal<byte_array>(untag_fixnum(str->length) * sizeof(u16));
2009-05-02 05:04:19 -04:00
2009-05-04 05:50:24 -04:00
write_barrier(str.untagged());
str->aux = tag<byte_array>(aux);
2009-05-02 05:04:19 -04:00
}
else
2009-05-04 05:50:24 -04:00
aux = untag<byte_array>(str->aux);
2009-05-02 05:04:19 -04:00
aux->data<u16>()[index] = ((ch >> 7) ^ 1);
2009-05-02 05:04:19 -04:00
}
/* allocates memory */
2009-09-23 14:05:46 -04:00
void factor_vm::set_string_nth(string *str, cell index, cell ch)
2009-05-02 05:04:19 -04:00
{
if(ch <= 0x7f)
2009-05-04 05:50:24 -04:00
set_string_nth_fast(str,index,ch);
2009-05-02 05:04:19 -04:00
else
2009-05-04 05:50:24 -04:00
set_string_nth_slow(str,index,ch);
2009-05-02 05:04:19 -04:00
}
2009-05-02 10:19:09 -04:00
/* Allocates memory */
2009-09-23 14:05:46 -04:00
string *factor_vm::allot_string_internal(cell capacity)
2009-05-02 05:04:19 -04:00
{
2009-05-04 05:50:24 -04:00
string *str = allot<string>(string_size(capacity));
2009-05-02 05:04:19 -04:00
2009-05-04 05:50:24 -04:00
str->length = tag_fixnum(capacity);
str->hashcode = F;
str->aux = F;
2009-05-02 05:04:19 -04:00
2009-05-04 05:50:24 -04:00
return str;
2009-05-02 05:04:19 -04:00
}
2009-05-02 10:19:09 -04:00
/* Allocates memory */
2009-09-23 14:05:46 -04:00
void factor_vm::fill_string(string *str_, cell start, cell capacity, cell fill)
2009-05-02 05:04:19 -04:00
{
gc_root<string> str(str_,this);
2009-05-02 10:19:09 -04:00
2009-05-02 05:04:19 -04:00
if(fill <= 0x7f)
2009-05-04 05:50:24 -04:00
memset(&str->data()[start],fill,capacity - start);
2009-05-02 05:04:19 -04:00
else
{
2009-05-04 05:50:24 -04:00
cell i;
2009-05-02 05:04:19 -04:00
for(i = start; i < capacity; i++)
2009-05-04 05:50:24 -04:00
set_string_nth(str.untagged(),i,fill);
2009-05-02 05:04:19 -04:00
}
}
2009-05-02 10:19:09 -04:00
/* Allocates memory */
2009-09-23 14:05:46 -04:00
string *factor_vm::allot_string(cell capacity, cell fill)
2009-05-02 05:04:19 -04:00
{
gc_root<string> str(allot_string_internal(capacity),this);
2009-05-04 05:50:24 -04:00
fill_string(str.untagged(),0,capacity,fill);
return str.untagged();
2009-05-02 05:04:19 -04:00
}
2009-09-23 14:05:46 -04:00
inline void factor_vm::primitive_string()
2009-05-02 05:04:19 -04:00
{
2009-05-04 05:50:24 -04:00
cell initial = to_cell(dpop());
cell length = unbox_array_size();
dpush(tag<string>(allot_string(length,initial)));
2009-05-02 05:04:19 -04:00
}
PRIMITIVE_FORWARD(string)
2009-08-17 16:37:06 -04:00
2009-09-23 14:05:46 -04:00
bool factor_vm::reallot_string_in_place_p(string *str, cell capacity)
2009-05-02 05:04:19 -04:00
{
2009-05-04 16:11:31 -04:00
return in_zone(&nursery,str)
&& (str->aux == F || in_zone(&nursery,untag<byte_array>(str->aux)))
&& capacity <= string_capacity(str);
2009-05-02 05:04:19 -04:00
}
2009-09-23 14:05:46 -04:00
string* factor_vm::reallot_string(string *str_, cell capacity)
2009-05-02 05:04:19 -04:00
{
gc_root<string> str(str_,this);
2009-05-02 10:19:09 -04:00
2009-05-04 05:50:24 -04:00
if(reallot_string_in_place_p(str.untagged(),capacity))
2009-05-02 05:04:19 -04:00
{
2009-05-04 05:50:24 -04:00
str->length = tag_fixnum(capacity);
2009-05-02 05:04:19 -04:00
2009-05-04 05:50:24 -04:00
if(str->aux != F)
2009-05-02 05:04:19 -04:00
{
2009-05-04 05:50:24 -04:00
byte_array *aux = untag<byte_array>(str->aux);
2009-05-02 05:04:19 -04:00
aux->capacity = tag_fixnum(capacity * 2);
}
2009-05-04 05:50:24 -04:00
return str.untagged();
2009-05-02 05:04:19 -04:00
}
else
{
2009-05-04 05:50:24 -04:00
cell to_copy = string_capacity(str.untagged());
2009-05-02 05:04:19 -04:00
if(capacity < to_copy)
to_copy = capacity;
gc_root<string> new_str(allot_string_internal(capacity),this);
2009-05-02 05:04:19 -04:00
2009-05-04 05:50:24 -04:00
memcpy(new_str->data(),str->data(),to_copy);
2009-05-02 05:04:19 -04:00
2009-05-04 05:50:24 -04:00
if(str->aux != F)
2009-05-02 05:04:19 -04:00
{
2009-05-04 05:50:24 -04:00
byte_array *new_aux = allot_byte_array(capacity * sizeof(u16));
2009-05-02 05:04:19 -04:00
2009-05-04 05:50:24 -04:00
write_barrier(new_str.untagged());
new_str->aux = tag<byte_array>(new_aux);
2009-05-02 05:04:19 -04:00
2009-05-04 05:50:24 -04:00
byte_array *aux = untag<byte_array>(str->aux);
memcpy(new_aux->data<u16>(),aux->data<u16>(),to_copy * sizeof(u16));
2009-05-02 05:04:19 -04:00
}
2009-05-04 05:50:24 -04:00
fill_string(new_str.untagged(),to_copy,capacity,'\0');
return new_str.untagged();
2009-05-02 05:04:19 -04:00
}
}
2009-09-23 14:05:46 -04:00
inline void factor_vm::primitive_resize_string()
2009-05-02 05:04:19 -04:00
{
2009-05-04 05:50:24 -04:00
string* str = untag_check<string>(dpop());
cell capacity = unbox_array_size();
dpush(tag<string>(reallot_string(str,capacity)));
2009-05-02 05:04:19 -04:00
}
PRIMITIVE_FORWARD(resize_string)
2009-08-17 16:37:06 -04:00
2009-09-23 14:05:46 -04:00
inline void factor_vm::primitive_string_nth()
2009-05-02 05:04:19 -04:00
{
2009-05-04 05:50:24 -04:00
string *str = untag<string>(dpop());
cell index = untag_fixnum(dpop());
dpush(tag_fixnum(string_nth(str,index)));
2009-05-02 05:04:19 -04:00
}
PRIMITIVE_FORWARD(string_nth)
2009-08-17 16:37:06 -04:00
2009-09-23 14:05:46 -04:00
inline void factor_vm::primitive_set_string_nth_fast()
2009-05-02 05:04:19 -04:00
{
2009-05-04 05:50:24 -04:00
string *str = untag<string>(dpop());
cell index = untag_fixnum(dpop());
cell value = untag_fixnum(dpop());
set_string_nth_fast(str,index,value);
2009-05-02 05:04:19 -04:00
}
PRIMITIVE_FORWARD(set_string_nth_fast)
2009-08-17 16:37:06 -04:00
2009-09-23 14:05:46 -04:00
inline void factor_vm::primitive_set_string_nth_slow()
2009-05-02 05:04:19 -04:00
{
2009-05-04 05:50:24 -04:00
string *str = untag<string>(dpop());
cell index = untag_fixnum(dpop());
cell value = untag_fixnum(dpop());
set_string_nth_slow(str,index,value);
2009-05-02 05:04:19 -04:00
}
2009-05-04 02:46:13 -04:00
PRIMITIVE_FORWARD(set_string_nth_slow)
2009-08-17 16:37:06 -04:00
2009-05-04 02:46:13 -04:00
}