-- vim: ft=terra
-- string.t: string classes
local m = {}
struct m.acc {
buf: rawstring
sz: intptr
run: intptr
space: intptr
}
local terra biggest(a: intptr, b: intptr)
if a > b then return a else return b end
end
m.acc.methods = {
init = terra(self: &m.acc, run: intptr)
lib.dbg('initializing string accumulator')
self.buf = [rawstring](lib.mem.heapa_raw(run))
self.run = run
self.space = run
self.sz = 0
end;
free = terra(self: &m.acc)
lib.dbg('freeing string accumulator')
if self.buf ~= nil and self.space > 0 then
lib.mem.heapf(self.buf)
end
end;
crush = terra(self: &m.acc)
lib.dbg('crushing string accumulator')
self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.sz))
self.space = self.sz
return self
end;
}
m.acc.methods.finalize = terra(self: &m.acc)
lib.dbg('finalizing string accumulator')
self:crush()
var pt: lib.mem.ptr(int8)
pt.ptr = self.buf
pt.ct = self.sz
self.buf = nil
self.sz = 0
return pt
end;
m.acc.methods.push = terra(self: &m.acc, str: rawstring, len: intptr)
lib.dbg('pushing "',str,'" onto accumulator')
if self.buf == nil then self:init(self.run) end
if len == 0 then len = lib.str.sz(str) end
if len >= self.space - self.sz then
self.space = self.space + biggest(self.run,len + 1)
self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.space))
end
lib.mem.cpy(self.buf + self.sz, str, len)
self.sz = self.sz + len
self.buf[self.sz] = 0
return self
end;
m.acc.methods.ppush = terra(self: &m.acc, str: lib.mem.ptr(int8))
self:push(str.ptr, str.ct) return self end;
m.acc.methods.merge = terra(self: &m.acc, str: lib.mem.ptr(int8))
self:push(str.ptr, str.ct) str:free() return self end;
return m