#line 301 "/home/ubuntu/felix/src/packages/ucstring.fdoc"
open class UniqueCountedStrings
{
open CString;
open Memory;
private var debug = Env::issetenv "FLX_TRACE_UCSTR";
private type _ustr = new +char;
typedef ustr = uniq _ustr;
private fun unpack (var p: ustr) : +char => p.unbox._repr_;
private fun pack (p: +char) => p._make__ustr.box;
ctor ustr (var s:string) = {
var p = s._unsafe_cstr;
if debug perform
println$ "Creating " + p.repr + " @" + p.address.repr;
return pack p;
}
ctor ustr (s:+char) => s.strdup.pack;
fun dup (var s:ustr) : ustr * ustr = {
var p = unpack s;
var q = strdup p;
if debug perform
println$ "Creating " + q.repr + " @" + q.address.repr;
return p.pack,q.pack;
}
fun dup (s:&<ustr) : ustr = {
var p = s.peek._repr_.strdup;
if debug perform
println$ "Creating " + p.repr + " @" + p.address.repr;
return p.pack;
}
proc delete (var p:ustr) {
var q = unpack p;
if debug perform
println$ "Deleting " + q.address.repr;
free q;
}
inherit Str[_ustr];
inherit Repr[_ustr];
instance Str[_ustr] { fun str(p:_ustr)=>p._repr_.str; }
instance Repr[_ustr] { fun repr(p:_ustr)=>p._repr_.repr; }
fun len(var s:&<ustr) : size => s.peek._repr_.strlen;
fun set (var s:ustr, i:int, c:char) : ustr = {
var cs = unpack s;
Carray::set (cs, i, c);
return cs.pack;
}
private gen realloc : +char * !ints -> +char =
"(char*)::std::realloc($1,$2)"
requires Cxx_headers::cstdlib
;
fun reserve (var s:ustr, n:size) : ustr =>
pack (realloc (unpack s,n))
;
fun append (var x:ustr, var y:ustr): ustr = {
var cx = unpack x;
var cy = unpack y;
var lx = cx.len;
var ly = cy.len;
var r = realloc (cx, lx+ly+1);
strncpy (r+lx,cy,ly+1);
if debug do
println$ "Realloc @" + cx.address.repr + " -> " + r.address.repr;
println$ "Free @" + cy.address.repr;
done
free cy;
return pack r;
}
noinline fun append (var x:ustr, var py:&ustr): ustr = {
var cx = unpack x;
var cy = py.peek._repr_;
var lx = cx.len;
var ly = cy.len;
var r = realloc (cx, lx+ly+1);
if debug perform
println$ "Realloc @" + cx.address.repr + " -> " + r.address.repr;
strncpy (r+lx,cy,ly+1);
return pack r;
}
fun + (var x:ustr, var y:ustr) => append (x,y);
fun + (var x:ustr, var py:&ustr) => append (x,py);
proc += (var lhs: &ustr, var rhs: ustr) =>
lhs <- append (*lhs,rhs)
;
proc += (var lhs: &ustr, var rhs: &ustr) =>
lhs <- append (*lhs,rhs)
;
private fun strmov (var x:ustr, var f:int, var l:int) : ustr = {
var p = x.unpack;
var n = p.strlen.int;
if f < 0 perform f = 0;
if f > n perform f = n;
if l < 0 perform l = f;
if l > n perform l = n;
if f != l perform strcpy (p+f, p+l);
return pack p;
}
fun erase (var x: ustr, sl:slice[int]) : ustr =>
match sl with
| Slice_all => set (x,0,char "")
| Slice_from idx => set (x,idx, char "")
| Slice_from_counted (first,len) => strmov (x,first,first+len)
| Slice_to_incl incl => strmov (x, 0,incl)
| Slice_to_excl excl => strmov (x, 0, excl - 1)
| Slice_range_incl (first, last) => strmov (x, first, last+1)
| Slice_range_excl (first, last) => strmov (x,first, last)
| Slice_one pos => strmov (x, pos, pos+1)
;
fun insert (var x:ustr, var pos: int, var y:ustr) : ustr =
{
var px = unpack x;
var py = unpack y;
var n = px.strlen.int;
var m = py.strlen.int;
if pos < 0 perform pos = pos + n;
if pos > n perform pos = n;
if pos < 0 perform pos = 0;
px = realloc (px, m + n + 1);
memmove (px.address + pos, px.address + pos + m, m);
free py;
return pack px;
}
fun search (var s: &<ustr, var pat: &<ustr) : size =
{
var p = s*.unpack;
var q = pat*.unpack;
var n = strlen p;
var m = strlen q;
var pr = Memory::search (p.address,(p+n).address,q.address,(q+m).address);
val r = (pr - p.address).size;
return r;
}
}