6 cell factorvm::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 factorvm::set_string_nth_fast(string *str, cell index, cell ch)
27 str->data()[index] = ch;
30 void factorvm::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 factorvm::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 *factorvm::allot_string_internal(cell capacity)
69 string *str = allot<string>(string_size(capacity));
71 str->length = tag_fixnum(capacity);
78 /* Allocates memory */
79 void factorvm::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 *factorvm::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 factorvm::primitive_string()
104 cell initial = to_cell(dpop());
105 cell length = unbox_array_size();
106 dpush(tag<string>(allot_string(length,initial)));
111 PRIMITIVE_GETVM()->primitive_string();
114 bool factorvm::reallot_string_in_place_p(string *str, cell capacity)
116 return in_zone(&nursery,str)
117 && (str->aux == F || in_zone(&nursery,untag<byte_array>(str->aux)))
118 && capacity <= string_capacity(str);
121 string* factorvm::reallot_string(string *str_, cell capacity)
123 gc_root<string> str(str_,this);
125 if(reallot_string_in_place_p(str.untagged(),capacity))
127 str->length = tag_fixnum(capacity);
131 byte_array *aux = untag<byte_array>(str->aux);
132 aux->capacity = tag_fixnum(capacity * 2);
135 return str.untagged();
139 cell to_copy = string_capacity(str.untagged());
140 if(capacity < to_copy)
143 gc_root<string> new_str(allot_string_internal(capacity),this);
145 memcpy(new_str->data(),str->data(),to_copy);
149 byte_array *new_aux = allot_byte_array(capacity * sizeof(u16));
151 write_barrier(new_str.untagged());
152 new_str->aux = tag<byte_array>(new_aux);
154 byte_array *aux = untag<byte_array>(str->aux);
155 memcpy(new_aux->data<u16>(),aux->data<u16>(),to_copy * sizeof(u16));
158 fill_string(new_str.untagged(),to_copy,capacity,'\0');
159 return new_str.untagged();
163 inline void factorvm::primitive_resize_string()
165 string* str = untag_check<string>(dpop());
166 cell capacity = unbox_array_size();
167 dpush(tag<string>(reallot_string(str,capacity)));
170 PRIMITIVE(resize_string)
172 PRIMITIVE_GETVM()->primitive_resize_string();
175 inline void factorvm::primitive_string_nth()
177 string *str = untag<string>(dpop());
178 cell index = untag_fixnum(dpop());
179 dpush(tag_fixnum(string_nth(str,index)));
182 PRIMITIVE(string_nth)
184 PRIMITIVE_GETVM()->primitive_string_nth();
187 inline void factorvm::primitive_set_string_nth_fast()
189 string *str = untag<string>(dpop());
190 cell index = untag_fixnum(dpop());
191 cell value = untag_fixnum(dpop());
192 set_string_nth_fast(str,index,value);
195 PRIMITIVE(set_string_nth_fast)
197 PRIMITIVE_GETVM()->primitive_set_string_nth_fast();
200 inline void factorvm::primitive_set_string_nth_slow()
202 string *str = untag<string>(dpop());
203 cell index = untag_fixnum(dpop());
204 cell value = untag_fixnum(dpop());
205 set_string_nth_slow(str,index,value);
208 PRIMITIVE(set_string_nth_slow)
210 PRIMITIVE_GETVM()->primitive_set_string_nth_slow();