6 cell factor_vm::string_nth(string* str, cell index)
8 /* If high bit is set, the most significant 16 bits of the char
9 come from the aux vector. The least significant bit of the
10 corresponding aux vector entry is negated, so that we can
11 XOR the two components together and get the original code point
13 cell lo_bits = str->data()[index];
15 if((lo_bits & 0x80) == 0)
19 byte_array *aux = untag<byte_array>(str->aux);
20 cell hi_bits = aux->data<u16>()[index];
21 return (hi_bits << 7) ^ lo_bits;
25 void factor_vm::set_string_nth_fast(string *str, cell index, cell ch)
27 str->data()[index] = ch;
30 void factor_vm::set_string_nth_slow(string *str_, cell index, cell ch)
32 gc_root<string> str(str_,this);
36 str->data()[index] = ((ch & 0x7f) | 0x80);
40 /* We don't need to pre-initialize the
41 byte array with any data, since we
42 only ever read from the aux vector
43 if the most significant bit of a
44 character is set. Initially all of
45 the bits are clear. */
46 aux = allot_array_internal<byte_array>(untag_fixnum(str->length) * sizeof(u16));
48 write_barrier(str.untagged());
49 str->aux = tag<byte_array>(aux);
52 aux = untag<byte_array>(str->aux);
54 aux->data<u16>()[index] = ((ch >> 7) ^ 1);
57 /* allocates memory */
58 void factor_vm::set_string_nth(string *str, cell index, cell ch)
61 set_string_nth_fast(str,index,ch);
63 set_string_nth_slow(str,index,ch);
66 /* Allocates memory */
67 string *factor_vm::allot_string_internal(cell capacity)
69 string *str = allot<string>(string_size(capacity));
71 str->length = tag_fixnum(capacity);
78 /* Allocates memory */
79 void factor_vm::fill_string(string *str_, cell start, cell capacity, cell fill)
81 gc_root<string> str(str_,this);
84 memset(&str->data()[start],fill,capacity - start);
89 for(i = start; i < capacity; i++)
90 set_string_nth(str.untagged(),i,fill);
94 /* Allocates memory */
95 string *factor_vm::allot_string(cell capacity, cell fill)
97 gc_root<string> str(allot_string_internal(capacity),this);
98 fill_string(str.untagged(),0,capacity,fill);
99 return str.untagged();
102 inline void factor_vm::primitive_string()
104 cell initial = to_cell(dpop());
105 cell length = unbox_array_size();
106 dpush(tag<string>(allot_string(length,initial)));
109 PRIMITIVE_FORWARD(string)
111 bool factor_vm::reallot_string_in_place_p(string *str, cell capacity)
113 return in_zone(&nursery,str)
114 && (str->aux == F || in_zone(&nursery,untag<byte_array>(str->aux)))
115 && capacity <= string_capacity(str);
118 string* factor_vm::reallot_string(string *str_, cell capacity)
120 gc_root<string> str(str_,this);
122 if(reallot_string_in_place_p(str.untagged(),capacity))
124 str->length = tag_fixnum(capacity);
128 byte_array *aux = untag<byte_array>(str->aux);
129 aux->capacity = tag_fixnum(capacity * 2);
132 return str.untagged();
136 cell to_copy = string_capacity(str.untagged());
137 if(capacity < to_copy)
140 gc_root<string> new_str(allot_string_internal(capacity),this);
142 memcpy(new_str->data(),str->data(),to_copy);
146 byte_array *new_aux = allot_byte_array(capacity * sizeof(u16));
148 write_barrier(new_str.untagged());
149 new_str->aux = tag<byte_array>(new_aux);
151 byte_array *aux = untag<byte_array>(str->aux);
152 memcpy(new_aux->data<u16>(),aux->data<u16>(),to_copy * sizeof(u16));
155 fill_string(new_str.untagged(),to_copy,capacity,'\0');
156 return new_str.untagged();
160 inline void factor_vm::primitive_resize_string()
162 string* str = untag_check<string>(dpop());
163 cell capacity = unbox_array_size();
164 dpush(tag<string>(reallot_string(str,capacity)));
167 PRIMITIVE_FORWARD(resize_string)
169 inline void factor_vm::primitive_string_nth()
171 string *str = untag<string>(dpop());
172 cell index = untag_fixnum(dpop());
173 dpush(tag_fixnum(string_nth(str,index)));
176 PRIMITIVE_FORWARD(string_nth)
178 inline void factor_vm::primitive_set_string_nth_fast()
180 string *str = untag<string>(dpop());
181 cell index = untag_fixnum(dpop());
182 cell value = untag_fixnum(dpop());
183 set_string_nth_fast(str,index,value);
186 PRIMITIVE_FORWARD(set_string_nth_fast)
188 inline void factor_vm::primitive_set_string_nth_slow()
190 string *str = untag<string>(dpop());
191 cell index = untag_fixnum(dpop());
192 cell value = untag_fixnum(dpop());
193 set_string_nth_slow(str,index,value);
196 PRIMITIVE_FORWARD(set_string_nth_slow)