[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: New Package Maintainer
From: |
Sather User |
Subject: |
Re: New Package Maintainer |
Date: |
Fri, 2 Sep 2011 23:25:45 +0930 (CST) |
On Sat, 18 Dec 2010, address@hidden wrote:
> There is a bug in the browser. ("May crash later:") I think I'll
> start by looking at that (3-4 weeks?)... I have a lot to learn, and
> I think finding and fixing a bug is the best way to "get one's hands
> dirty".
Hi, Sadi. Wondering how you went with the browser.
Here is a PGM class. Unsophisticated, like me, no doubt, but may be
useful to someone. There are different creates for reading/validating
and writing a PGM file. Maybe not ready for release. Use at your own
risk.
class PGM is
shared errno:INT;
shared strerr:STR;
attr tag:FMAP{STR,STR};
attr comment:FLIST{FSTR};
attr f:FILE;
attr height, width, maxval, prod, imsize, start_loc, end_loc:INT;
attr deep:BOOL;
attr writer:BOOL;
oferr(n:INT) is
strerr:="could not open file";
errno := n
end;
ferr(n:INT) is
-- format error
strerr:="bad file format";
errno := n;
end;
create(filename:STR, old:SAME, deep:BOOL):SAME is
-- Writer create. See comments below.
return create(filename, old, deep, void, void)
end;
create(filename:STR, old:SAME, deep:BOOL, newwidth, newheight:INT):SAME is
-- Create a PGM to write from a PGM that was read.
-- Assumes we are modifying some PGM or more than one, whose
-- headers must be copied. The writing uses self.f which is
-- here advanced to the point following the header so
-- the first pixel can be written. Can't use old.deep because we
-- need the option of converting 16-bit input to 8-bit output.
res:SAME:=new;
res.writer:=true;
if void(filename) then
res.f:=FILE::stdout
else
res.f:=FILE::open_for_write(filename);
if res.f.error then oferr(2); return void end;
end;
res.f+"P5\n";
-- If there were multiple input PGMs, e.g. for noise reduction,
-- the header data, comments, specific to all but the last are lost.
-- The comments, width and height of the last input PGM only are used.
if ~void(old.comment) and old.comment.size > 0 then
loop
res.f+("#"+old.comment.elt!+"\n")
end
end;
-- Not old.deep: the parameter deep.
if deep then res.maxval := 65535 else res.maxval := 255 end;
if void(newwidth) then res.width:=old.width else res.width:=newwidth end;
if void(newheight) then
res.height:=old.height
else
res.height:=newheight
end;
res.f+res.width.str+" "+res.height.str+"\n"+res.maxval.str+"\n";
return res
end;
create(filename, directory:STR):SAME is
-- A reader create which does open_for_read of an existing PGM file,
-- and some other things.
res::=new;
if ~void(directory) then
filename := directory + "/" + filename
end;
f::=FILE::open_for_read(filename);
if f.error then oferr(2); return void end;
res.f:=f;
-----------------------------------------------------------
c:CHAR;
c:=res.material_next;
if c /= 'P' then ferr(29); return void end;
c:=res.f.get_char;
if c /= '5' then ferr(3); return void end;
c:=res.material_next;
if ~c.is_digit then ferr(5); return void end;
Width ::= res.my_sense(c).t2;
c:=res.material_next;
if ~c.is_digit then ferr(6); return void end;
Height::=res.my_sense(c).t2;
c:=res.material_next;
if ~c.is_digit then ferr(7); return void end;
Maxval_tup::=res.my_sense(c);
Maxval::=Maxval_tup.t2;
if Maxval_tup.t1.is_space.not then ferr(8); return void end;
res.start_loc:=res.f.current_loc;
res.f.seek_from_end(0);
res.end_loc:=res.f.current_loc;
res.f.seek_from_front(res.start_loc);
res.width:=#INT(Width);
res.height:=#INT(Height);
res.maxval:=#INT(Maxval);
res.deep:=res.maxval>255;
prod::=res.width*res.height;
if res.deep then prod:=prod+prod end;
res.prod := prod;
imsize::=res.end_loc-res.start_loc;
res.imsize := imsize;
if MAIN::dbg_header then
#ERR+"width="+Width+"\theight="+Height+"\tmaxval="+Maxval+"\n";
#ERR+"start_loc="+res.start_loc+"\tend_loc="+res.end_loc+"\n";
#ERR+"prod="+res.prod+"\timsize="+res.imsize;
#ERR+"\tprod-imsize="+(res.prod-res.imsize)+"\n";
ferr(0);
return void
end;
-- Final header test: more than 1 char between Maxval and 1st pixel?
if prod/=imsize then ferr(9); return void end;
-- These must set shared errno:INT and return void
return res
end;
my_sense(n:CHAR):TUP{CHAR,STR} is
-- Place the arg in a new string buffer.
-- Make it FSTR.
-- Read the next character.
-- If it is whitespace return the string buffer.
-- If it is '#'step over it (saving comment) and return the
-- string buffer.
-- Otherwise append it to the string buffer and start again.
c:CHAR;
sb:FSTR:=#;
sb:=sb.push(n);
loop
c:=f.get_char;
if c.is_space then return #(c,sb.str) end;
if c='#' then comment_collect_skip; return #(c,sb.str) end;
sb:=sb.push(c)
end
end;
stepover:CHAR is
-- If the next item is a whitespace character or comment
-- step over it and return '\0' else step over it and return it
c:CHAR;
c:=f.get_char;
if c.is_space then return '\0' end;
if c='#' then comment_collect_skip; return '\0' end;
return c
end;
material_next:CHAR is
-- Look for the next character that is not whitespace (inc blank
-- lines) and not a comment. Return the character.
c:CHAR;
loop
c:=stepover;
while!(c='\0')
end;
return c
end;
comment_collect_skip
-- A "#" was found. Advance to end of line, putting everthing
-- before \n into a new comment item.
is
s:FSTR;
loop
c::=f.get_char;
until!(c='\n');
s:=s.push(c)
end;
comment:=comment.push(s)
end;
plus(i:INT) is
-- append a character to new file
if ~writer then
#ERR+"Not a writer.\n"
else
if deep then
f+i.urshift(8).char;
f+i.band(255).char
else
f+i.char
end
end
end;
plus(n:FLT) is
plus(n.round.int)
end;
get_int:INT is
if writer then
#ERR+"Not a reader.\n";
return 0
end;
if deep then
return f.get_char.int.utimes(256).uplus(f.get_char.int)
end;
return f.get_char.int
end;
pixnum_read_hexstr:STR is
s::=get_int.hex_str;
w::=s.size-2;
return s.tail(w)
end;
close is f.close end;
end;
--
Michael Talbot-Wilson
- Re: New Package Maintainer,
Sather User <=