implement Filter; include "sys.m"; include "filter.m"; End: con byte 8r300;Esc: con byte 8r333;Eend: con byte 8r334; # encoded End byteEesc: con byte 8r335; # encoded Esc byte init(){} start(param: string): chan of ref Rq{ req := chan of ref Rq; if(param == "encode") spawn encode(req); else spawn decode(req); return req;} encode(reqs: chan of ref Rq){ sys := load Sys Sys->PATH; reqs <-= ref Rq.Start(sys->pctl(0, nil)); buf := array[8192] of byte; rc := chan of int; do{ reqs <-= ref Rq.Fill(buf, rc); if((n := <-rc) <= 0){ if(n == 0) reqs <-= ref Rq.Finished(nil); break; } b := array[2*n + 2] of byte; # optimise time not space o := 1; b[0] = End; for(i := 0; i < n; i++){ if((c := buf[i]) == End || c == Esc){ b[o++] = Esc; c = byte (Eend + (c& byte 1)); } b[o++] = c; } b[o++] = End; if(o != len b) b = b[0:o]; reqs <-= ref Rq.Result(b, rc); }while(<-rc != -1);} Slipesc, Slipend: con (1<<8) + iota;Slipsize: con 1006; # rfc's suggestion slipin(c: byte, esc: int): int{ if(esc == Slipesc){ # last byte was Esc if(c == Eend) c = End; else if(c == Eesc) c = Esc; }else{ if(c == Esc) return Slipesc; if(c == End) return Slipend; } return int c;} decode(reqs: chan of ref Rq){ sys := load Sys Sys->PATH; reqs <-= ref Rq.Start(sys->pctl(0, nil)); buf := array[8192] of byte; b := array[Slipsize] of byte; rc := chan of int; c := 0; o := 0; for(;;){ reqs <-= ref Rq.Fill(buf, rc); if((n := <-rc) <= 0){ if(n < 0) exit; break; } for(i := 0; i < n; i++){ c = slipin(buf[i], c); if(c == Slipend){ if(o != 0){ reqs <-= ref Rq.Result(b[0:o], rc); if(<-rc == -1) exit; b = array[Slipsize] of byte; o = 0; } }else if(c != Slipesc){ if(o >= len b){ t := array[3*len b/2] of byte; t[0:] = b; b = t; } b[o++] = byte c; } } } # partial block discarded reqs <-= ref Rq.Finished(nil);}
implement Filter;
include "sys.m";
include "filter.m";
End: con byte 8r300;
Esc: con byte 8r333;
Eend: con byte 8r334; # encoded End byte
Eesc: con byte 8r335; # encoded Esc byte
init()
{
}
start(param: string): chan of ref Rq
{
req := chan of ref Rq;
if(param == "encode")
spawn encode(req);
else
spawn decode(req);
return req;
}
encode(reqs: chan of ref Rq)
{
sys := load Sys Sys->PATH;
reqs <-= ref Rq.Start(sys->pctl(0, nil));
buf := array[8192] of byte;
rc := chan of int;
do{
reqs <-= ref Rq.Fill(buf, rc);
if((n := <-rc) <= 0){
if(n == 0)
reqs <-= ref Rq.Finished(nil);
break;
}
b := array[2*n + 2] of byte; # optimise time not space
o := 1;
b[0] = End;
for(i := 0; i < n; i++){
if((c := buf[i]) == End || c == Esc){
b[o++] = Esc;
c = byte (Eend + (c& byte 1));
}
b[o++] = c;
}
b[o++] = End;
if(o != len b)
b = b[0:o];
reqs <-= ref Rq.Result(b, rc);
}while(<-rc != -1);
}
Slipesc, Slipend: con (1<<8) + iota;
Slipsize: con 1006; # rfc's suggestion
slipin(c: byte, esc: int): int
{
if(esc == Slipesc){ # last byte was Esc
if(c == Eend)
c = End;
else if(c == Eesc)
c = Esc;
}else{
if(c == Esc)
return Slipesc;
if(c == End)
return Slipend;
}
return int c;
}
decode(reqs: chan of ref Rq)
{
sys := load Sys Sys->PATH;
reqs <-= ref Rq.Start(sys->pctl(0, nil));
buf := array[8192] of byte;
b := array[Slipsize] of byte;
rc := chan of int;
c := 0;
o := 0;
for(;;){
reqs <-= ref Rq.Fill(buf, rc);
if((n := <-rc) <= 0){
if(n < 0)
exit;
break;
}
for(i := 0; i < n; i++){
c = slipin(buf[i], c);
if(c == Slipend){
if(o != 0){
reqs <-= ref Rq.Result(b[0:o], rc);
if(<-rc == -1)
exit;
b = array[Slipsize] of byte;
o = 0;
}
}else if(c != Slipesc){
if(o >= len b){
t := array[3*len b/2] of byte;
t[0:] = b;
b = t;
}
b[o++] = byte c;
}
}
}
# partial block discarded
reqs <-= ref Rq.Finished(nil);
}