Differences From
Artifact [c8d105a016]:
1 1 -- vim: ft=terra
2 2 -- string.t: string classes
3 3 local util = dofile('common.lua')
4 +local pstr = lib.mem.ptr(int8)
5 +local pref = lib.mem.ref(int8)
4 6
5 7 local m = {
6 8 sz = terralib.externfunction('strlen', rawstring -> intptr);
7 9 cmp = terralib.externfunction('strcmp', {rawstring, rawstring} -> int);
8 10 ncmp = terralib.externfunction('strncmp', {rawstring, rawstring, intptr} -> int);
9 11 cpy = terralib.externfunction('stpcpy',{rawstring, rawstring} -> rawstring);
10 12 ncpy = terralib.externfunction('stpncpy',{rawstring, rawstring, intptr} -> rawstring);
................................................................................
14 16 terralib.types.funcpointer({&rawstring,rawstring},{int},true));
15 17 bfmt = terralib.externfunction('sprintf',
16 18 terralib.types.funcpointer({rawstring,rawstring},{int},true));
17 19 span = terralib.externfunction('strspn',{rawstring, rawstring} -> rawstring);
18 20 }
19 21
20 22 do local strptr = (lib.mem.ptr(int8))
23 + local strref = (lib.mem.ref(int8))
21 24 local byteptr = (lib.mem.ptr(uint8))
22 25 strptr.metamethods.__cast = function(from,to,e)
23 26 if from == &int8 then
24 27 return `strptr {ptr = e, ct = m.sz(e)}
25 28 elseif to == &int8 then
26 29 return e.ptr
27 30 end
28 31 end
29 32
30 33 terra strptr:cmp(other: strptr)
34 + if self.ptr == nil and other.ptr == nil then return true end
35 + if self.ptr == nil or other.ptr == nil then return false end
36 +
37 + var sz = lib.math.biggest(self.ct, other.ct)
38 + for i = 0, sz do
39 + if self.ptr[i] == 0 and other.ptr[i] == 0 then return true end
40 + if self.ptr[i] ~= other.ptr[i] then return false end
41 + end
42 + return true
43 + end
44 + terra strref:cmp(other: strref)
45 + if self.ptr == nil and other.ptr == nil then return true end
46 + if self.ptr == nil or other.ptr == nil then return false end
47 +
31 48 var sz = lib.math.biggest(self.ct, other.ct)
32 49 for i = 0, sz do
33 50 if self.ptr[i] == 0 and other.ptr[i] == 0 then return true end
34 51 if self.ptr[i] ~= other.ptr[i] then return false end
35 52 end
36 53 return true
37 54 end
55 +
56 + strptr.methods.cmpl = macro(function(self,other)
57 + return `self:cmp(strptr { ptr = [other:asvalue()], ct = [#(other:asvalue())] })
58 + end)
59 + strref.methods.cmpl = macro(function(self,other)
60 + return `self:cmp(strref { ptr = [other:asvalue()], ct = [#(other:asvalue())] })
61 + end)
38 62
39 63 terra byteptr:cmp(other: byteptr)
40 64 var sz = lib.math.biggest(self.ct, other.ct)
41 65 for i = 0, sz do
42 66 if self.ptr[i] == 0 and other.ptr[i] == 0 then return true end
43 67 if self.ptr[i] ~= other.ptr[i] then return false end
44 68 end
45 69 return true
46 70 end
47 71 end
72 +
73 +terra m.normalize(s: pstr)
74 + var c: rawstring = s.ptr
75 + var n: rawstring = s.ptr
76 + while n < s.ptr + s.ct do
77 + while @n == 0 or @n == @'\r' do
78 + n = n + 1
79 + if n > s.ptr + s.ct then
80 + c = c + 1 goto done
81 + end
82 + end
83 + @c = @n
84 + c = c + 1
85 + n = n + 1
86 + end ::done::
87 + @c = 0
88 + return pstr { ptr = s.ptr, ct = c - s.ptr }
89 +end
48 90
49 91 struct m.acc {
50 92 buf: rawstring
51 93 sz: intptr
52 94 run: intptr
53 95 space: intptr
54 96 }
................................................................................
70 112 --lib.dbg('freeing string accumulator')
71 113 if self.buf ~= nil and self.space > 0 then
72 114 lib.mem.heapf(self.buf)
73 115 end
74 116 end;
75 117
76 118 terra m.acc:crush()
77 - lib.dbg('crushing string accumulator')
119 + --lib.dbg('crushing string accumulator')
78 120 self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.sz))
79 121 self.space = self.sz
80 122 return self
81 123 end;
82 124
83 125 terra m.acc:finalize()
84 - lib.dbg('finalizing string accumulator')
126 + --lib.dbg('finalizing string accumulator')
85 127 self:crush()
86 128 var pt: lib.mem.ptr(int8)
87 129 pt.ptr = self.buf
88 130 pt.ct = self.sz
89 131 self.buf = nil
90 132 self.sz = 0
91 133 return pt
................................................................................
114 156 lib.mem.cpy(self.buf + self.sz, str, len)
115 157 self.sz = self.sz + len
116 158 self.buf[self.sz] = 0
117 159 return self
118 160 end;
119 161
120 162 m.lit = macro(function(str)
121 - return `[lib.mem.ref(int8)] {ptr = [str:asvalue()], ct = [#(str:asvalue())]}
163 + if str:asvalue() ~= nil then
164 + return `[lib.mem.ref(int8)] {ptr = [str:asvalue()], ct = [#(str:asvalue())]}
165 + else
166 + return `[lib.mem.ref(int8)] {ptr = nil, ct = 0}
167 + end
168 +end)
169 +
170 +m.plit = macro(function(str)
171 + if str:asvalue() ~= nil then
172 + return `[lib.mem.ptr(int8)] {ptr = [str:asvalue()], ct = [#(str:asvalue())]}
173 + else
174 + return `[lib.mem.ptr(int8)] {ptr = nil, ct = 0}
175 + end
122 176 end)
123 177
124 178 m.acc.methods.lpush = macro(function(self,str)
125 179 return `self:push([str:asvalue()], [#(str:asvalue())]) end)
126 180 m.acc.methods.ppush = terra(self: &m.acc, str: lib.mem.ptr(int8))
127 181 self:push(str.ptr, str.ct) return self end;
128 182 m.acc.methods.merge = terra(self: &m.acc, str: lib.mem.ptr(int8))
................................................................................
212 266 local str,sz = v[1],v[2]
213 267 if type(sz) == 'number' then
214 268 memreq_const = memreq_const + sz
215 269 elseif type(sz:asvalue()) == 'number' then
216 270 memreq_const = memreq_const + sz:asvalue()
217 271 else memreq_exp = `[sz] + [memreq_exp] end
218 272
219 - cpy = quote [kp] ; [ptr] = [&int8](lib.mem.cpy([ptr], str, sz)) end
273 + cpy = quote [kp] ;
274 + --lib.io.fmt('encapsulating string %p → %p [%s] sz %llu\n', str, [ptr], str, sz)
275 + [ptr] = [&int8](lib.mem.cpy([ptr], str, sz))
276 + --lib.io.fmt(' :: encapsulated string %p [%s]\n', box.obj.[k],box.obj.[k])
277 + end
220 278 if ty.ptr_basetype then
221 279 cpy = quote [cpy]; [box].obj.[k].ct = sz end
222 280 end
223 281 isnull = `[str] == nil
224 282 else
225 283 memreq_exp = `(m.sz(v) + 1) + [memreq_exp] -- make room for NUL
226 284 isnull = `v == nil