intstr.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
-------------------------> GNU Sather - sourcefile <-------------------------
-- Copyright (C) 2000 by K Hopper, University of Waikato, New Zealand --
-- This file is part of the GNU Sather library. It is free software; you may --
-- redistribute and/or modify it under the terms of the GNU Library General --
-- Public License (LGPL) as published by the Free Software Foundation; --
-- either version 2 of the license, or (at your option) any later version. --
-- This library is distributed in the hope that it will be useful, but --
-- WITHOUT ANY WARRANTY without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See Doc/LGPL for more details. --
-- The license text is also available from: Free Software Foundation, Inc., --
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
--------------> Please email comments to <bug-sather@gnu.org> <--------------
partial class INT_STR < $TEXT, $EXACT_FMT
partial class INT_STR < $TEXT, $EXACT_FMT is
-- This partial class provides integer whole number conversion routines,
-- to and from character strings.
-- Version 1.0 Sep 98. Copyright K Hopper, U of Waikato
-- Development History
-- -------------------
-- Date Who By Detail
-- ---- ------ ------
-- 15 Sep 98 kh Original from Modula-2 standard
private const Decimal_Base : CARD := 10 ;
private opt_sign(cursor : STR_CURSOR) : BOOL
pre ~void(cursor) and ~cursor.is_done
post true
is
-- This private routine checks to see if a minus or plus sign are in
-- the indicated string next. If and only if any such sign is negative then
-- true is returned! The sign (if present) has been skipped over on return.
loc_ch : CHAR := cursor.item ;
loc_lib : LIBCHARS := cursor.buffer.index_lib ;
res : BOOL := (loc_ch = loc_lib.Minus_Sign.char) ;
if (loc_ch = loc_lib.Minus_Sign.char) or (loc_ch = loc_lib.Plus_Sign.char) then
cursor.advance
end ;
return res
end ;
private skip_space(cursor:STR_CURSOR) is
loc_lib : LIBCHARS := cursor.buffer.index_lib ;
loop
loc_ch:CHAR:=cursor.item;
if loc_ch = loc_lib.Space.char then cursor.advance; else break!; end;
end;
end;
private scan(cursor : STR_CURSOR) : SAME
pre ~void(cursor) and ~cursor.is_done
post ((result = nil)
and (initial(cursor.index) = cursor.index))
or (initial(cursor.index) < cursor.index)
is
-- This routine is the integer number scanner. If a valid number has
-- not been found then the cursor is unchanged and zero returned if a format
-- error or INT::maxval if a range error.
skip_space(cursor);
start_index : CARD := cursor.index ;
negative : BOOL := opt_sign(cursor) ;
loc_max : CARD := INT::maxval.card ;
loc_format : NUMBER_FMT := cursor.buffer.index_lib.culture.numeric.format ;
if negative then -- assume two's-complement!!
loc_max := loc_max + 1
end ;
if ~cursor.item.is_digit(cursor.buffer.index_lib) then -- not a number!
cursor.set_index(start_index) ;
return INT::nil
end ;
loc_str : FLIST{CARD} := loc_format.digit_string(cursor,true,Decimal_Base) ;
loc_res : CARD := 0 ;
loop
loc_digit : CARD := loc_str.elt! ;
if (loc_max - loc_res) < loc_digit then -- out of range!
cursor.set_index(start_index) ;
return INT::nil
else
loc_res := loc_res * Decimal_Base + loc_digit
end
end ;
if negative then
if loc_res = (INT::maxval.card + 1) then -- special case!
return -((loc_res - 1).int) - INT::one
else
return - loc_res.int
end
else
return loc_res.int
end
end ;
is_int(str:STR):BOOL is
-- This predicate returns true if and only if str represents a number in decimal notation.
return is_whole(str) = CONVERSION_RESULTS::All_Right
end;
is_whole(str : STR ) : CONVERSION_RESULTS
pre true
post (result = CONVERSION_RESULTS::All_Right)
or (result = CONVERSION_RESULTS::Out_of_Range)
or (result = CONVERSION_RESULTS::Bad_Format)
or (result = CONVERSION_RESULTS::Empty)
is
-- This routine checks that the format of of the leading characters of
-- the given string in the given repertoire and encoding corresponds to that
-- required for a real number, returning the relevant result state.
if str.size = 0 then
return CONVERSION_RESULTS::Empty
end ;
loc_cursor : STR_CURSOR := str.cursor ;
start_index : CARD := 0 ;
val : SAME := scan(loc_cursor) ;
if start_index = loc_cursor.index then -- bad or too large
if val.is_zero then
return CONVERSION_RESULTS::Bad_Format
else
return CONVERSION_RESULTS::Out_of_Range
end
else
loc_cursor.set_index(start_index) ;
return CONVERSION_RESULTS::All_Right
end
end ;
build(loc_cursor : STR_CURSOR) : SAME
post
void(loc_cursor)
or ((result = maxval) and (initial(loc_cursor.index) = loc_cursor.index))
or (initial(loc_cursor.index) < loc_cursor.index)
is
-- This routine creates the integer number corresponding to the textual
-- representation contained in the string indicated. If the string indicated
-- does not contain an integer as the next non-blank item in the string then
-- zero is returned and the cursor has not been moved!
if void(loc_cursor) then return #(0); end;
--s:STR:=loc_cursor.buffer; i::=loc_cursor.index; v:SAME:=scan(loc_cursor);
--#OUT+"INT::build:"+s+":"+v.str+":initial.ind="+i.str+":ind="+(loc_cursor.index).str+"\n";
--OUT::flush;
return scan(loc_cursor);
end ;
create(str : STR) : SAME
pre (is_whole(str) = CONVERSION_RESULTS::All_Right)
post true
is
-- This routine creates the whole number corresponding to the textual
-- representation contained in str in the given repertoire and encoding.
return build(str.cursor)
end ;
num_chars : CARD
pre true
post ((result - CARD::one).exp10 < self.card)
-- (result.exp10 >= self) -- might not be representable!!
is
-- This routine returns the number of characters in the textual
-- representation of self as a decimal number. It uses binary search so
-- that small values take only 3 comparisons.
loc_val : CARD := abs.card ;
sign : CARD := 0 ;
if self < zero then
sign := 1
end ;
if loc_val < 10000 then
if loc_val < 100 then
if loc_val < 10 then
return sign + 1
else
return sign + 2
end
else
if loc_val < 1000 then
return sign + 3
else
return sign + 4
end
end
else
if loc_val < 1000000 then
if loc_val < 100000 then
return sign + 5
else
return sign + 6
end
else
return sign + (loc_val / 10000).num_chars + 4
end
end
end ;
str(
lib : LIBCHARS
) : STR
pre ~void(lib)
post (result.size > 0)
is
-- This routine returns a string representation of self using the given
-- repertoire and encoding.
signed : BOOL := true ; -- optimistic/pessimistic??
loc_val : CARD ;
if self = minint then
loc_val := INT::maxval.card + 1
else
if self >= zero then
signed := false
end ;
loc_val := self.abs.card
end ;
loc_str : STR := lib.culture.numeric.format.fmt(loc_val,10,lib).tgt_str ;
if signed then
return STR::create(lib) + lib.Minus_Sign.char + loc_str
else
return loc_str
end
end ;
str : STR
pre true
post (result.size > 0)
is
-- This routine returns a string representation of self using the given
-- repertoire and encoding. The format will be either fixed point or
-- floating point dependent upon which of the two is the shorter string.
return str(LIBCHARS::default)
end ;
fmt(
format : EXACT_DESCR,
lib : LIBCHARS
) : STR
pre ~void(format)
and ~void(lib)
post result.size > 0
is
-- This routine returns a formatted representation of self in the given
-- repertoire and encoding as dictated by the given format description.
res : STR := str(lib) ;
loc_fill : STR := STR::create(lib) + format.filler.char ;
if res.size < format.whole_digits then -- needs a filler
res := loc_fill.repeat(format.whole_digits - res.size) + res
end ;
return res
end ;
fmt(
format : EXACT_DESCR
) : STR
pre ~void(format)
post result.size > 0
is
-- This routine returns a formatted representation of self in the default
-- repertoire and encoding as dictated by the given format description.
return fmt(format,LIBCHARS::default)
end ;
end ; -- INT_STR