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;
26 void factorvm::set_string_nth_fast(string *str, cell index, cell ch)
28 str->data()[index] = ch;
32 void factorvm::set_string_nth_slow(string *str_, cell index, cell ch)
34 gc_root<string> str(str_,this);
38 str->data()[index] = ((ch & 0x7f) | 0x80);
42 /* We don't need to pre-initialize the
43 byte array with any data, since we
44 only ever read from the aux vector
45 if the most significant bit of a
46 character is set. Initially all of
47 the bits are clear. */
48 aux = allot_array_internal<byte_array>(untag_fixnum(str->length) * sizeof(u16));
50 write_barrier(str.untagged());
51 str->aux = tag<byte_array>(aux);
54 aux = untag<byte_array>(str->aux);
56 aux->data<u16>()[index] = ((ch >> 7) ^ 1);
60 /* allocates memory */
61 void factorvm::set_string_nth(string *str, cell index, cell ch)
64 set_string_nth_fast(str,index,ch);
66 set_string_nth_slow(str,index,ch);
70 /* Allocates memory */
71 string *factorvm::allot_string_internal(cell capacity)
73 string *str = allot<string>(string_size(capacity));
75 str->length = tag_fixnum(capacity);
83 /* Allocates memory */
84 void factorvm::fill_string(string *str_, cell start, cell capacity, cell fill)
86 gc_root<string> str(str_,this);
89 memset(&str->data()[start],fill,capacity - start);
94 for(i = start; i < capacity; i++)
95 set_string_nth(str.untagged(),i,fill);
100 /* Allocates memory */
101 string *factorvm::allot_string(cell capacity, cell fill)
103 gc_root<string> str(allot_string_internal(capacity),this);
104 fill_string(str.untagged(),0,capacity,fill);
105 return str.untagged();
109 inline void factorvm::primitive_string()
111 cell initial = to_cell(dpop());
112 cell length = unbox_array_size();
113 dpush(tag<string>(allot_string(length,initial)));
118 PRIMITIVE_GETVM()->primitive_string();
121 bool factorvm::reallot_string_in_place_p(string *str, cell capacity)
123 return in_zone(&nursery,str)
124 && (str->aux == F || in_zone(&nursery,untag<byte_array>(str->aux)))
125 && capacity <= string_capacity(str);
129 string* factorvm::reallot_string(string *str_, cell capacity)
131 gc_root<string> str(str_,this);
133 if(reallot_string_in_place_p(str.untagged(),capacity))
135 str->length = tag_fixnum(capacity);
139 byte_array *aux = untag<byte_array>(str->aux);
140 aux->capacity = tag_fixnum(capacity * 2);
143 return str.untagged();
147 cell to_copy = string_capacity(str.untagged());
148 if(capacity < to_copy)
151 gc_root<string> new_str(allot_string_internal(capacity),this);
153 memcpy(new_str->data(),str->data(),to_copy);
157 byte_array *new_aux = allot_byte_array(capacity * sizeof(u16));
159 write_barrier(new_str.untagged());
160 new_str->aux = tag<byte_array>(new_aux);
162 byte_array *aux = untag<byte_array>(str->aux);
163 memcpy(new_aux->data<u16>(),aux->data<u16>(),to_copy * sizeof(u16));
166 fill_string(new_str.untagged(),to_copy,capacity,'\0');
167 return new_str.untagged();
172 inline void factorvm::primitive_resize_string()
174 string* str = untag_check<string>(dpop());
175 cell capacity = unbox_array_size();
176 dpush(tag<string>(reallot_string(str,capacity)));
179 PRIMITIVE(resize_string)
181 PRIMITIVE_GETVM()->primitive_resize_string();
184 inline void factorvm::primitive_string_nth()
186 string *str = untag<string>(dpop());
187 cell index = untag_fixnum(dpop());
188 dpush(tag_fixnum(string_nth(str,index)));
191 PRIMITIVE(string_nth)
193 PRIMITIVE_GETVM()->primitive_string_nth();
196 inline void factorvm::primitive_set_string_nth_fast()
198 string *str = untag<string>(dpop());
199 cell index = untag_fixnum(dpop());
200 cell value = untag_fixnum(dpop());
201 set_string_nth_fast(str,index,value);
204 PRIMITIVE(set_string_nth_fast)
206 PRIMITIVE_GETVM()->primitive_set_string_nth_fast();
209 inline void factorvm::primitive_set_string_nth_slow()
211 string *str = untag<string>(dpop());
212 cell index = untag_fixnum(dpop());
213 cell value = untag_fixnum(dpop());
214 set_string_nth_slow(str,index,value);
217 PRIMITIVE(set_string_nth_slow)
219 PRIMITIVE_GETVM()->primitive_set_string_nth_slow();