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);
38 if(to_boolean(str->aux))
39 aux = untag<byte_array>(str->aux);
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 str->aux = tag<byte_array>(aux);
51 write_barrier(&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);
72 str->hashcode = false_object;
73 str->aux = false_object;
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 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 bool factor_vm::reallot_string_in_place_p(string *str, cell capacity)
111 return nursery.contains_p(str)
112 && (!to_boolean(str->aux) || nursery.contains_p(untag<byte_array>(str->aux)))
113 && capacity <= string_capacity(str);
116 string* factor_vm::reallot_string(string *str_, cell capacity)
118 gc_root<string> str(str_,this);
120 if(reallot_string_in_place_p(str.untagged(),capacity))
122 str->length = tag_fixnum(capacity);
124 if(to_boolean(str->aux))
126 byte_array *aux = untag<byte_array>(str->aux);
127 aux->capacity = tag_fixnum(capacity * 2);
130 return str.untagged();
134 cell to_copy = string_capacity(str.untagged());
135 if(capacity < to_copy)
138 gc_root<string> new_str(allot_string_internal(capacity),this);
140 memcpy(new_str->data(),str->data(),to_copy);
142 if(to_boolean(str->aux))
144 byte_array *new_aux = allot_byte_array(capacity * sizeof(u16));
146 new_str->aux = tag<byte_array>(new_aux);
147 write_barrier(&new_str->aux);
149 byte_array *aux = untag<byte_array>(str->aux);
150 memcpy(new_aux->data<u16>(),aux->data<u16>(),to_copy * sizeof(u16));
153 fill_string(new_str.untagged(),to_copy,capacity,'\0');
154 return new_str.untagged();
158 void factor_vm::primitive_resize_string()
160 string* str = untag_check<string>(dpop());
161 cell capacity = unbox_array_size();
162 dpush(tag<string>(reallot_string(str,capacity)));
165 void factor_vm::primitive_string_nth()
167 string *str = untag<string>(dpop());
168 cell index = untag_fixnum(dpop());
169 dpush(tag_fixnum(string_nth(str,index)));
172 void factor_vm::primitive_set_string_nth_fast()
174 string *str = untag<string>(dpop());
175 cell index = untag_fixnum(dpop());
176 cell value = untag_fixnum(dpop());
177 set_string_nth_fast(str,index,value);
180 void factor_vm::primitive_set_string_nth_slow()
182 string *str = untag<string>(dpop());
183 cell index = untag_fixnum(dpop());
184 cell value = untag_fixnum(dpop());
185 set_string_nth_slow(str,index,value);