]> gitweb.factorcode.org Git - factor.git/blob - vm/strings.cpp
Update Win64 support
[factor.git] / vm / strings.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 cell string::nth(cell index) const
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 = data()[index];
14
15         if((lo_bits & 0x80) == 0)
16                 return lo_bits;
17         else
18         {
19                 byte_array *aux = untag<byte_array>(this->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] = (u8)ch;
28 }
29
30 void factor_vm::set_string_nth_slow(string *str_, cell index, cell ch)
31 {
32         data_root<string> str(str_,this);
33
34         byte_array *aux;
35
36         str->data()[index] = ((ch & 0x7f) | 0x80);
37
38         if(to_boolean(str->aux))
39                 aux = untag<byte_array>(str->aux);
40         else
41         {
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));
49
50                 str->aux = tag<byte_array>(aux);
51                 write_barrier(&str->aux);
52         }
53
54         aux->data<u16>()[index] = (u16)((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 = false_object;
73         str->aux = false_object;
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         data_root<string> str(str_,this);
82
83         if(fill <= 0x7f)
84                 memset(&str->data()[start],(int)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         data_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(ctx->pop());
105         cell length = unbox_array_size();
106         ctx->push(tag<string>(allot_string(length,initial)));
107 }
108
109 bool factor_vm::reallot_string_in_place_p(string *str, cell capacity)
110 {
111         return nursery.contains_p(str)
112                 && (!to_boolean(str->aux) || nursery.contains_p(untag<byte_array>(str->aux)))
113                 && capacity <= string_capacity(str);
114 }
115
116 string* factor_vm::reallot_string(string *str_, cell capacity)
117 {
118         data_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(to_boolean(str->aux))
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                 data_root<string> new_str(allot_string_internal(capacity),this);
139
140                 memcpy(new_str->data(),str->data(),to_copy);
141
142                 if(to_boolean(str->aux))
143                 {
144                         byte_array *new_aux = allot_byte_array(capacity * sizeof(u16));
145
146                         new_str->aux = tag<byte_array>(new_aux);
147                         write_barrier(&new_str->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         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)));
164 }
165
166 void factor_vm::primitive_string_nth()
167 {
168         string *str = untag<string>(ctx->pop());
169         cell index = untag_fixnum(ctx->pop());
170         ctx->push(tag_fixnum(str->nth(index)));
171 }
172
173 void factor_vm::primitive_set_string_nth_fast()
174 {
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);
179 }
180
181 void factor_vm::primitive_set_string_nth_slow()
182 {
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);
187 }
188
189 }