3 CELL string_nth(F_STRING* string, CELL index)
5 /* If high bit is set, the most significant 16 bits of the char
6 come from the aux vector. The least significant bit of the
7 corresponding aux vector entry is negated, so that we can
8 XOR the two components together and get the original code point
10 CELL ch = bget(SREF(string,index));
15 F_BYTE_ARRAY *aux = untag_byte_array_fast(string->aux);
16 return (cget(BREF(aux,index * sizeof(u16))) << 7) ^ ch;
20 void set_string_nth_fast(F_STRING *string, CELL index, CELL ch)
22 bput(SREF(string,index),ch);
25 void set_string_nth_slow(F_STRING *string_, CELL index, CELL ch)
27 gc_root<F_STRING> string(string_);
31 bput(SREF(string.untagged(),index),(ch & 0x7f) | 0x80);
35 /* We don't need to pre-initialize the
36 byte array with any data, since we
37 only ever read from the aux vector
38 if the most significant bit of a
39 character is set. Initially all of
40 the bits are clear. */
41 aux = allot_array_internal<F_BYTE_ARRAY>(
42 untag_fixnum_fast(string->length)
45 write_barrier(string.value());
46 string->aux = tag_object(aux);
49 aux = untag_byte_array_fast(string->aux);
51 cput(BREF(aux,index * sizeof(u16)),(ch >> 7) ^ 1);
54 /* allocates memory */
55 void set_string_nth(F_STRING* string, CELL index, CELL ch)
58 set_string_nth_fast(string,index,ch);
60 set_string_nth_slow(string,index,ch);
63 /* Allocates memory */
64 F_STRING *allot_string_internal(CELL capacity)
66 F_STRING *string = allot<F_STRING>(string_size(capacity));
68 string->length = tag_fixnum(capacity);
75 /* Allocates memory */
76 void fill_string(F_STRING *string_, CELL start, CELL capacity, CELL fill)
78 gc_root<F_STRING> string(string_);
81 memset((void *)SREF(string.untagged(),start),fill,capacity - start);
86 for(i = start; i < capacity; i++)
87 set_string_nth(string.untagged(),i,fill);
91 /* Allocates memory */
92 F_STRING *allot_string(CELL capacity, CELL fill)
94 gc_root<F_STRING> string(allot_string_internal(capacity));
95 fill_string(string.untagged(),0,capacity,fill);
96 return string.untagged();
99 void primitive_string(void)
101 CELL initial = to_cell(dpop());
102 CELL length = unbox_array_size();
103 dpush(tag_object(allot_string(length,initial)));
106 static bool reallot_string_in_place_p(F_STRING *string, CELL capacity)
108 return in_zone(&nursery,(CELL)string) && capacity <= string_capacity(string);
111 F_STRING* reallot_string(F_STRING *string_, CELL capacity)
113 gc_root<F_STRING> string(string_);
115 if(reallot_string_in_place_p(string.untagged(),capacity))
117 string->length = tag_fixnum(capacity);
121 F_BYTE_ARRAY *aux = untag_byte_array_fast(string->aux);
122 aux->capacity = tag_fixnum(capacity * 2);
125 return string.untagged();
129 CELL to_copy = string_capacity(string.untagged());
130 if(capacity < to_copy)
133 gc_root<F_STRING> new_string(allot_string_internal(capacity));
135 memcpy(new_string.untagged() + 1,string.untagged() + 1,to_copy);
139 F_BYTE_ARRAY *new_aux = allot_byte_array(capacity * sizeof(u16));
141 write_barrier(new_string.value());
142 new_string->aux = tag_object(new_aux);
144 F_BYTE_ARRAY *aux = untag_byte_array_fast(string->aux);
145 memcpy(new_aux + 1,aux + 1,to_copy * sizeof(u16));
148 fill_string(new_string.untagged(),to_copy,capacity,'\0');
149 return new_string.untagged();
153 void primitive_resize_string(void)
155 F_STRING* string = untag_string(dpop());
156 CELL capacity = unbox_array_size();
157 dpush(tag_object(reallot_string(string,capacity)));
160 /* Some ugly macros to prevent a 2x code duplication */
162 #define MEMORY_TO_STRING(type,utype) \
163 F_STRING *memory_to_##type##_string(const type *string, CELL length) \
165 REGISTER_C_STRING(string); \
166 gc_root<F_STRING> s(allot_string_internal(length)); \
167 UNREGISTER_C_STRING(type,string); \
169 for(i = 0; i < length; i++) \
171 set_string_nth(s.untagged(),i,(utype)*string); \
174 return s.untagged(); \
176 F_STRING *from_##type##_string(const type *str) \
179 const type *scan = str; \
180 while(*scan++) length++; \
181 return memory_to_##type##_string(str,length); \
183 void box_##type##_string(const type *str) \
185 dpush(str ? tag_object(from_##type##_string(str)) : F); \
188 MEMORY_TO_STRING(char,u8)
189 MEMORY_TO_STRING(u16,u16)
190 MEMORY_TO_STRING(u32,u32)
192 bool check_string(F_STRING *s, CELL max)
194 CELL capacity = string_capacity(s);
196 for(i = 0; i < capacity; i++)
198 CELL ch = string_nth(s,i);
199 if(ch == 0 || ch >= ((CELL)1 << (max * 8)))
205 F_BYTE_ARRAY *allot_c_string(CELL capacity, CELL size)
207 return allot_byte_array((capacity + 1) * size);
210 #define STRING_TO_MEMORY(type) \
211 void type##_string_to_memory(F_STRING *s, type *string) \
214 CELL capacity = string_capacity(s); \
215 for(i = 0; i < capacity; i++) \
216 string[i] = string_nth(s,i); \
218 void primitive_##type##_string_to_memory(void) \
220 type *address = (type *)unbox_alien(); \
221 F_STRING *str = untag_string(dpop()); \
222 type##_string_to_memory(str,address); \
224 F_BYTE_ARRAY *string_to_##type##_alien(F_STRING *s_, bool check) \
226 gc_root<F_STRING> s(s_); \
227 CELL capacity = string_capacity(s.untagged()); \
228 F_BYTE_ARRAY *_c_str; \
229 if(check && !check_string(s.untagged(),sizeof(type))) \
230 general_error(ERROR_C_STRING,s.value(),F,NULL); \
231 _c_str = allot_c_string(capacity,sizeof(type)); \
232 type *c_str = (type*)(_c_str + 1); \
233 type##_string_to_memory(s.untagged(),c_str); \
234 c_str[capacity] = 0; \
237 type *to_##type##_string(F_STRING *s, bool check) \
239 return (type*)(string_to_##type##_alien(s,check) + 1); \
241 type *unbox_##type##_string(void) \
243 return to_##type##_string(untag_string(dpop()),true); \
246 STRING_TO_MEMORY(char);
247 STRING_TO_MEMORY(u16);
249 void primitive_string_nth(void)
251 F_STRING *string = untag_string_fast(dpop());
252 CELL index = untag_fixnum_fast(dpop());
253 dpush(tag_fixnum(string_nth(string,index)));
256 void primitive_set_string_nth(void)
258 F_STRING *string = untag_string_fast(dpop());
259 CELL index = untag_fixnum_fast(dpop());
260 CELL value = untag_fixnum_fast(dpop());
261 set_string_nth(string,index,value);
264 void primitive_set_string_nth_fast(void)
266 F_STRING *string = untag_string_fast(dpop());
267 CELL index = untag_fixnum_fast(dpop());
268 CELL value = untag_fixnum_fast(dpop());
269 set_string_nth_fast(string,index,value);
272 void primitive_set_string_nth_slow(void)
274 F_STRING *string = untag_string_fast(dpop());
275 CELL index = untag_fixnum_fast(dpop());
276 CELL value = untag_fixnum_fast(dpop());
277 set_string_nth_slow(string,index,value);