Differences From
Artifact [4b8724b0aa]:
1 1 -- vim: ft=terra
2 2 -- string.t: string classes
3 +local util = dofile('common.lua')
3 4
4 5 local m = {
5 6 sz = terralib.externfunction('strlen', rawstring -> intptr);
6 7 cmp = terralib.externfunction('strcmp', {rawstring, rawstring} -> int);
7 8 ncmp = terralib.externfunction('strncmp', {rawstring, rawstring, intptr} -> int);
8 9 cpy = terralib.externfunction('stpcpy',{rawstring, rawstring} -> rawstring);
9 10 ncpy = terralib.externfunction('stpncpy',{rawstring, rawstring, intptr} -> rawstring);
10 11 dup = terralib.externfunction('strdup',rawstring -> rawstring);
11 12 ndup = terralib.externfunction('strndup',{rawstring, intptr} -> rawstring);
12 13 fmt = terralib.externfunction('asprintf',
13 14 terralib.types.funcpointer({&rawstring,rawstring},{int},true));
14 15 bfmt = terralib.externfunction('sprintf',
15 16 terralib.types.funcpointer({rawstring,rawstring},{int},true));
17 + span = terralib.externfunction('strspn',{rawstring, rawstring} -> rawstring);
16 18 }
17 19
18 20 (lib.mem.ptr(int8)).metamethods.__cast = function(from,to,e)
19 21 if from == &int8 then
20 22 return `[lib.mem.ptr(int8)]{ptr = e, ct = m.sz(e)}
21 23 elseif to == &int8 then
22 24 return e.ptr
................................................................................
31 33 }
32 34
33 35 local terra biggest(a: intptr, b: intptr)
34 36 if a > b then return a else return b end
35 37 end
36 38
37 39 terra m.acc:init(run: intptr)
38 - lib.dbg('initializing string accumulator')
40 + --lib.dbg('initializing string accumulator')
39 41 self.buf = [rawstring](lib.mem.heapa_raw(run))
40 42 self.run = run
41 43 self.space = run
42 44 self.sz = 0
43 45 return self
44 46 end;
45 47
46 48 terra m.acc:free()
47 - lib.dbg('freeing string accumulator')
49 + --lib.dbg('freeing string accumulator')
48 50 if self.buf ~= nil and self.space > 0 then
49 51 lib.mem.heapf(self.buf)
50 52 end
51 53 end;
52 54
53 55 terra m.acc:crush()
54 56 lib.dbg('crushing string accumulator')
................................................................................
65 67 pt.ct = self.sz
66 68 self.buf = nil
67 69 self.sz = 0
68 70 return pt
69 71 end;
70 72
71 73 terra m.acc:push(str: rawstring, len: intptr)
72 - var llen = len
74 + --var llen = len
73 75 if str == nil then return self end
74 - if str[len - 1] == 0xA then llen = llen - 1 end -- don't display newlines in debug output
75 - lib.dbg('pushing "',{str,llen},'" onto accumulator')
76 + --if str[len - 1] == 0xA then llen = llen - 1 end -- don't display newlines in debug output
77 + -- lib.dbg('pushing "',{str,llen},'" onto accumulator')
76 78 if self.buf == nil then self:init(self.run) end
77 79 if len == 0 then len = m.sz(str) end
78 80 if len >= self.space - self.sz then
79 81 self.space = self.space + biggest(self.run,len + 1)
80 82 self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.space))
81 83 end
82 84 lib.mem.cpy(self.buf + self.sz, str, len)
83 85 self.sz = self.sz + len
84 86 self.buf[self.sz] = 0
85 87 return self
86 88 end;
89 +
90 +m.lit = macro(function(str)
91 + return `[lib.mem.ref(int8)] {ptr = [str:asvalue()], ct = [#(str:asvalue())]}
92 +end)
93 +
87 94 m.acc.methods.ppush = terra(self: &m.acc, str: lib.mem.ptr(int8))
88 95 self:push(str.ptr, str.ct) return self end;
89 96 m.acc.methods.merge = terra(self: &m.acc, str: lib.mem.ptr(int8))
90 97 self:push(str.ptr, str.ct) str:free() return self end;
91 98 m.acc.methods.compose = macro(function(self, ...)
92 99 local minlen = 0
93 100 local pstrs = {}
................................................................................
138 145 local ptr = symbol(&int8)
139 146 local box = symbol(&m.box(ty))
140 147 local memreq_exp = `0
141 148 local copiers = {}
142 149 for k,v in pairs(vals) do
143 150 local ty = (`box.obj.[k]).tree.type
144 151 local kp
152 + local isnull, nullify
145 153 if ty.ptr_basetype then
146 - kp = quote [box].obj.[k] = [ty] { [ptr] = [&ty.ptr_basetype]([ptr]) } ; end
154 + kp = quote [box].obj.[k] = [ty] { ptr = [&ty.ptr_basetype]([ptr]) } ; end
155 + nullify = quote [box].obj.[k] = [ty] { ptr = nil, ct = 0 } end
147 156 else
148 157 kp = quote [box].obj.[k] = [ty]([ptr]) ; end
158 + nullify = quote [box].obj.[k] = nil end
149 159 end
150 160
151 161 local cpy
152 162 if type(v) ~= 'table' or #v ~= 2 then
153 163 cpy = quote [kp] ; [ptr] = m.cpy(ptr, v) end
164 + isnull = `v == nil
154 165 end
155 166 if type(v) == 'string' then
156 167 memreq_const = memreq_const + #v + 1
168 + isnull = `false
157 169 elseif type(v) == 'table' and v.tree and (v.tree.type.ptr_basetype == int8 or v.tree.type.ptr_basetype == uint8) then
158 170 cpy = quote [kp]; [ptr] = [&int8](lib.mem.cpy([ptr], [v].ptr, [v].ct)) end
159 171 if ty.ptr_basetype then
160 172 cpy = quote [cpy]; [box].obj.[k].ct = [v].ct end
161 173 end
174 + isnull = `[v].ptr == nil
162 175 elseif type(v) == 'table' and v.asvalue and type(v:asvalue()) == 'string' then
163 176 local str = tostring(v:asvalue())
164 177 memreq_const = memreq_const + #str + 1
178 + isnull = `false
165 179 elseif type(v) == 'table' and #v == 2 then
166 180 local str,sz = v[1],v[2]
167 181 if type(sz) == 'number' then
168 182 memreq_const = memreq_const + sz
169 183 elseif type(sz:asvalue()) == 'number' then
170 184 memreq_const = memreq_const + sz:asvalue()
171 185 else memreq_exp = `[sz] + [memreq_exp] end
172 186
173 187 cpy = quote [kp] ; [ptr] = [&int8](lib.mem.cpy([ptr], str, sz)) end
174 188 if ty.ptr_basetype then
175 189 cpy = quote [cpy]; [box].obj.[k].ct = sz end
176 190 end
191 + isnull = `[str] == nil
177 192 else
178 193 memreq_exp = `(m.sz(v) + 1) + [memreq_exp] -- make room for NUL
194 + isnull = `v == nil
179 195 if ty.ptr_basetype then
180 196 cpy = quote [cpy]; [box].obj.[k].ct = m.sz(v) end
181 197 end
182 198 end
183 - copiers[#copiers + 1] = cpy
199 +
200 + copiers[#copiers + 1] = quote
201 + if [isnull] then [nullify]
202 + else [cpy] end
203 + end
184 204 end
185 205
186 206 return quote
187 207 var sz: intptr = memreq_const + [memreq_exp]
188 208 var [box] = [&m.box(ty)](lib.mem.heapa_raw(sz))
189 209 var [ptr] = [box].storage
190 210 [copiers]
191 211 in [lib.mem.ptr(ty)] { ct = 1, ptr = &([box].obj) } end
192 212 end
213 +
214 +terra m.cspan(str: lib.mem.ptr(int8), reject: lib.mem.ref(int8), maxlen: intptr)
215 + for i=0, lib.math.smallest(maxlen,str.ct) do
216 + if str.ptr[i] == 0 then return 0 end
217 + for j=0, reject.ct do
218 + if str.ptr[i] == reject.ptr[j] then return i end
219 + end
220 + end
221 + return maxlen
222 +end
223 +
224 +terra m.ffw(str: &int8, maxlen: intptr)
225 + while maxlen > 0 and @str ~= 0 and
226 + (@str == @' ' or @str == @'\t' or @str == @'\n') do
227 + str = str + 1
228 + maxlen = maxlen - 1
229 + end
230 + return str
231 +end
232 +
233 +terra m.ffw_unsafe(str: &int8)
234 + while @str ~= 0 and
235 + (@str == @' ' or @str == @'\t' or @str == @'\n') do
236 + str = str + 1
237 + end
238 + return str
239 +end
193 240
194 241 return m