parsav  Diff

Differences From Artifact [c8d105a016]:

To Artifact [c5ea2451a4]:


     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