6 cell string::nth(cell index) const
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 = data()[index];
15 if((lo_bits & 0x80) == 0)
19 byte_array *aux = untag<byte_array>(this->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] = (u8)ch;
30 void factor_vm::set_string_nth_slow(string *str_, cell index, cell ch)
32 data_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_uninitialized_array<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] = (u16)((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 data_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 data_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(ctx->pop());
105 cell length = unbox_array_size();
106 ctx->push(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 data_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 data_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 data_root<string> str(ctx->pop(),this);
161 str.untag_check(this);
162 cell capacity = unbox_array_size();
163 ctx->push(tag<string>(reallot_string(str.untagged(),capacity)));
166 void factor_vm::primitive_string_nth()
168 string *str = untag<string>(ctx->pop());
169 cell index = untag_fixnum(ctx->pop());
170 ctx->push(tag_fixnum(str->nth(index)));
173 void factor_vm::primitive_set_string_nth_fast()
175 string *str = untag<string>(ctx->pop());
176 cell index = untag_fixnum(ctx->pop());
177 cell value = untag_fixnum(ctx->pop());
178 set_string_nth_fast(str,index,value);
181 void factor_vm::primitive_set_string_nth_slow()
183 string *str = untag<string>(ctx->pop());
184 cell index = untag_fixnum(ctx->pop());
185 cell value = untag_fixnum(ctx->pop());
186 set_string_nth_slow(str,index,value);