parsav  Diff

Differences From Artifact [4b8724b0aa]:

To Artifact [c91733fef5]:


     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