]> gitweb.factorcode.org Git - factor.git/blob - vm/strings.cpp
Moved PRIMITIVE and PRIMITIVE_FORWARDs to primitives.[ch]pp
[factor.git] / vm / strings.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 cell factor_vm::string_nth(string* str, cell index)
7 {
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
12         back. */
13         cell lo_bits = str->data()[index];
14
15         if((lo_bits & 0x80) == 0)
16                 return lo_bits;
17         else
18         {
19                 byte_array *aux = untag<byte_array>(str->aux);
20                 cell hi_bits = aux->data<u16>()[index];
21                 return (hi_bits << 7) ^ lo_bits;
22         }
23 }
24
25 void factor_vm::set_string_nth_fast(string *str, cell index, cell ch)
26 {
27         str->data()[index] = ch;
28 }
29
30 void factor_vm::set_string_nth_slow(string *str_, cell index, cell ch)
31 {
32         gc_root<string> str(str_,this);
33
34         byte_array *aux;
35
36         str->data()[index] = ((ch & 0x7f) | 0x80);
37
38         if(str->aux == F)
39         {
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));
47
48                 write_barrier(str.untagged());
49                 str->aux = tag<byte_array>(aux);
50         }
51         else
52                 aux = untag<byte_array>(str->aux);
53
54         aux->data<u16>()[index] = ((ch >> 7) ^ 1);
55 }
56
57 /* allocates memory */
58 void factor_vm::set_string_nth(string *str, cell index, cell ch)
59 {
60         if(ch <= 0x7f)
61                 set_string_nth_fast(str,index,ch);
62         else
63                 set_string_nth_slow(str,index,ch);
64 }
65
66 /* Allocates memory */
67 string *factor_vm::allot_string_internal(cell capacity)
68 {
69         string *str = allot<string>(string_size(capacity));
70
71         str->length = tag_fixnum(capacity);
72         str->hashcode = F;
73         str->aux = F;
74
75         return str;
76 }
77
78 /* Allocates memory */
79 void factor_vm::fill_string(string *str_, cell start, cell capacity, cell fill)
80 {
81         gc_root<string> str(str_,this);
82
83         if(fill <= 0x7f)
84                 memset(&str->data()[start],fill,capacity - start);
85         else
86         {
87                 cell i;
88
89                 for(i = start; i < capacity; i++)
90                         set_string_nth(str.untagged(),i,fill);
91         }
92 }
93
94 /* Allocates memory */
95 string *factor_vm::allot_string(cell capacity, cell fill)
96 {
97         gc_root<string> str(allot_string_internal(capacity),this);
98         fill_string(str.untagged(),0,capacity,fill);
99         return str.untagged();
100 }
101
102 void factor_vm::primitive_string()
103 {
104         cell initial = to_cell(dpop());
105         cell length = unbox_array_size();
106         dpush(tag<string>(allot_string(length,initial)));
107 }
108
109 bool factor_vm::reallot_string_in_place_p(string *str, cell capacity)
110 {
111         return in_zone(&nursery,str)
112                 && (str->aux == F || in_zone(&nursery,untag<byte_array>(str->aux)))
113                 && capacity <= string_capacity(str);
114 }
115
116 string* factor_vm::reallot_string(string *str_, cell capacity)
117 {
118         gc_root<string> str(str_,this);
119
120         if(reallot_string_in_place_p(str.untagged(),capacity))
121         {
122                 str->length = tag_fixnum(capacity);
123
124                 if(str->aux != F)
125                 {
126                         byte_array *aux = untag<byte_array>(str->aux);
127                         aux->capacity = tag_fixnum(capacity * 2);
128                 }
129
130                 return str.untagged();
131         }
132         else
133         {
134                 cell to_copy = string_capacity(str.untagged());
135                 if(capacity < to_copy)
136                         to_copy = capacity;
137
138                 gc_root<string> new_str(allot_string_internal(capacity),this);
139
140                 memcpy(new_str->data(),str->data(),to_copy);
141
142                 if(str->aux != F)
143                 {
144                         byte_array *new_aux = allot_byte_array(capacity * sizeof(u16));
145
146                         write_barrier(new_str.untagged());
147                         new_str->aux = tag<byte_array>(new_aux);
148
149                         byte_array *aux = untag<byte_array>(str->aux);
150                         memcpy(new_aux->data<u16>(),aux->data<u16>(),to_copy * sizeof(u16));
151                 }
152
153                 fill_string(new_str.untagged(),to_copy,capacity,'\0');
154                 return new_str.untagged();
155         }
156 }
157
158 void factor_vm::primitive_resize_string()
159 {
160         string* str = untag_check<string>(dpop());
161         cell capacity = unbox_array_size();
162         dpush(tag<string>(reallot_string(str,capacity)));
163 }
164
165 void factor_vm::primitive_string_nth()
166 {
167         string *str = untag<string>(dpop());
168         cell index = untag_fixnum(dpop());
169         dpush(tag_fixnum(string_nth(str,index)));
170 }
171
172 void factor_vm::primitive_set_string_nth_fast()
173 {
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);
178 }
179
180 void factor_vm::primitive_set_string_nth_slow()
181 {
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);
186 }
187
188 }