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