elapsedstr.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 ELAPSED_STR < $TEXT, $ANCHORED_FMT
partial class ELAPSED_STR < $TEXT, $ANCHORED_FMT is
-- This partial class provides conversions applicable to elapsed time
-- classes.
-- Version 1.2 Mar 01. Copyright K Hopper, U of Waikato
-- Development History
-- -------------------
-- Date Who By Detail
-- ---- ------ ------
-- 1 Oct 98 kh Original from TIMES class
-- 29 Mar 99 kh Revised for V8 text classes.
-- 4 Mar 01 kh Added full_str feature
private const Days, Hours, Minutes, Seconds ;
private shared Messages : ARRAY{STR} ;
private check_names(loc_lib : LIBCHARS) is
-- This routine reads the culturally-defined names for days/hours/
-- minutes/seconds if Messages has not already been read.
if void(Messages) then
lib : LIBCHARS := loc_lib ;
loc_res : RESOURCES := lib.culture.resources ;
loc_msgs : ARRAY{STR} :=
loc_res.read(SYS::rune_name(self),(Seconds + 1)) ;
Messages := loc_msgs
end
end ;
private scan(cursor : STR_CURSOR) : CARD
pre ~void(cursor) and ~cursor.is_done
post ((result = 0)and (initial(cursor.index) = cursor.index))
or (initial(cursor.index) < cursor.index)
is
-- This routine is the one which does the work of both building and
-- of checking the string. If cursor.index is the same on exit as entry
-- then the string indicated is not valid. If this is accompanied by
-- the return value of CARD::nil then there is a range error, otherwise
-- there is a format error.
dummy : CARD ;
start_index : CARD := cursor.index ;
loc_lib : LIBCHARS := cursor.buffer.index_lib ;
loc_cursor.skip_space ; -- skip padding
if ~loc_cursor.is_digit then
dummy : CARD := cursor.set_index(start_index) ;
return 0
end ;
nums : ARRAY{CARD} := ARRAY{CARD}::create(5) ;
-- the five possible components
field_cnt : CARD := 0 ;
decimal_after : CARD := CARD::maxval ;
loop
loc_str : STR := cursor.get_upto(bind(_.is_digit(loc_lib))) ;
nums[field_cnt] := CARD::create(loc_str) ;
field_cnt := field_cnt + 1 ;
if field_cnt = 5 then break!
elsif loc_cursor.is_done then break!
else
loc_str := cursor.get_upto(bind(_.is_punct(loc_lib))) ;
if loc_str[0] = loc_lib.Decimal_Mark.char then
decimal_after := field_cnt
elsif loc_str.size > 1 then -- can't be a separator
dummy := cursor.set_index(start_index) ;
return days(0).millisecs(0)
end
end
end ;
if (decimal_after < field_cnt) then
if (decimal_after /= (field_cnt - 1)) then -- format error!
dummy := cursor.set_index(start_index) ;
return days(0).millisecs(0)
end
else
if field_cnt = 5 then -- should have had a decimal mark!
dummy := cursor.set_index(start_index) ;
return days(0).millisecs(0)
end
end ;
case field_cnt
when 1 then -- treat value as seconds
if nums[0] > Seconds_per_Min then
dummy := cursor.set_index(start_index) ;
return days(CARD::nil).millisecs(0)
else
return days(0).millisecs(nums[0] * Millisecs_per_Sec)
end
when 2 then
if decimal_after < field_cnt then -- seconds and millisecs
if nums[0] > Seconds_per_Min
or nums[1] > Millisecs_per_Sec then
dummy := cursor.set_index(start_index) ;
return days(CARD::nil).millisecs(0)
else
return days(0).millisecs(
nums[0] * Millisecs_per_Sec + nums[1])
end
else -- hours and minutes
if nums[0] > Hours_per_Day
or nums[1] > Minutes_per_Hour then
dummy := cursor.set_index(start_index) ;
return days(CARD::nil).millisecs(0)
else
return days(0).millisecs(nums[0] * Millisecs_per_Hr +
nums[1] * Millisecs_per_Min)
end
end
when 3 then
if decimal_after < field_cnt then -- minutes, seconds and millisecs
if (nums[0] > Minutes_per_Hr)
or (nums[1] > Seconds-per_Min)
or (nums[2] > millisecs_per_Sec) then
dummy := cursor.set_index(start_index) ;
return days(CARD::nil).millisecs(0)
else
return days(0).millisecs(
nums[0] * Millisecs_per_Min +
nums[1] * Millisecs_per_Sec + nums[2])
end
else -- hours, minutes & seconds
if nums[0] > Hours_per_Day
or nums[1] > Minutes_per_Hour
or nums[2] > Seconds_per_Min then
dummy := cursor.set_index(start_index) ;
return days(CARD::nil).millisecs(0)
else
return days(0).millisecs(
nums[0] * Millisecs_per_Hr +
nums[1] * Millisecs_per_Min +
nums[2] * Milliseconds_per_Sec)
end
end
when 4 then -- all except number of days
if (nums[0] > Hours_per_Day)
or (nums[1] > Minutes_per_Hour)
or (nums[2] > Seconds_per_Min)
or (nums[3] > Millisecs_per_Sec) then
dummy := cursor.set_index(start_index) ;
return days(CARD::nil).millisecs(0)
else
return days(0).millisecs(
nums[0] * Millisecs_per_Hr +
nums[1] * Millisecs_per_Min +
nums[2] * Milliseconds_per_Sec +
nums[3])
end
when 5 then -- all five
if (nums[1] > Hours_per_Day)
or (nums[2] > Minutes_per_Hour)
or (nums[3] > Seconds_per_Min)
or (nums[4] > Millisecs_per_Sec) then
dummy := cursor.set_index(start_index) ;
return days(CARD::nil).millisecs(0)
else
return days(nums[0]).millisecs(
nums[1] * Millisecs_per_Hr +
nums[2] * Millisecs_per_Min +
nums[3] * Milliseconds_per_Sec + nums[4])
end
else
-- cannot reach here!
end
end ;
is_elapsed( 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 ;
start_index : CARD := 0 ; -- just the given string!
loc_cursor : STR_CURSOR := str.cursor ;
val : CARD := scan(loc_cursor) ;
if loc_cursor.index = start_index then -- an error
if val = CARD::maxval then
return CONVERSION_RESULTS::Out_of_Range
else
return CONVERSION_RESULTS::Bad_Format
end
else
return CONVERSION_RESULTS::All_Right
end
end ;
build(loc_cursor : STR_CURSOR) : SAME
pre ~void(loc_cursor)
and (loc_cursor.remaining > 1)
post ((result.days = 0)
and (result.millisecs =0)
and (initial(loc_cursor.index) = loc_cursor.index))
or (initial(loc_cursor.index) < loc_cursor.index)
is
-- This routine creates a time value from the indicated string, returning
-- an unchanged cursor if there was some error together with a value of 0 to
-- mean a bad format or CARD::maxval to indicate some range error.
total : CARD := scan(loc_cursor) ;
return days(total / Millisecs_per_Day).millisecs(total % Millisecs_per_Day)
end ;
create(str : STR) : SAME
pre (is_elapsed(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 ;
str(lib : LIBCHARS) : STR
pre ~void(lib)
post (result.size > 0)
is
-- This routine returns a string representation of self using the given
-- encoding and repertoire. The string does not include the fraction of
-- a second (but see full_str below).
check_names(lib) ;
started : BOOL := false ; -- no components yet produced
res : STR := STR::create(lib) ;
if days > 0 then
started := true ;
res := res + days.str(lib) + Messages[Days] + lib.Space.char
end ;
if hours > 0
or started then
res := res + hours.str(lib) + Messages[Hours] + lib.Space.char
end ;
if minutes > 0
or started then
res := res + minutes_in_hour.str(lib) + Messages[Minutes] +
lib.Space.char
end ;
if seconds > 0
or started then
res := res + seconds_in_minute.str(lib)
end ;
if res.size = 0 then
res := res + lib.digit(0).char
end ;
res := res + Messages[Seconds] ;
return res
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 ;
full_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. The format includes the milliseconds component
-- of the time (if non-zero). This is the only string conversion routine
-- to do so.
check_names(lib) ;
started : BOOL := false ; -- no components yet produced
res : STR := STR::create(lib) ;
if days > 0 then
started := true ;
res := res + days.str(lib) + Messages[Days] + lib.Space.char
end ;
if hours > 0 or started then
res := res + hours.str(lib) + Messages[Hours] + lib.Space.char
end ;
if minutes > 0 or started then
res := res + minutes_in_hour.str(lib) + Messages[Minutes] + lib.Space.char
end ;
if seconds > 0 or started then
res := res + seconds_in_minute.str(lib)
end ;
if res.size = 0 then
res := res + lib.digit(0).char
end ;
if milliseconds > 0 then -- only if not zero
res := res + lib.Decimal_Mark.char + milliseconds.decimal_str(3)
end ;
res := res + Messages[Seconds] ;
return res
end ;
full_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 includes the milliseconds component
-- of the time. This is the only string conversion routine to do so.
return full_str(LIBCHARS::default)
end ;
fmt(format : ANCHORED_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) ;
if res.size < format.leading then -- needs a filler
res := format.filler.str.repeat(format.leading - res.size) + res
end ;
return res
end ;
fmt(format : ANCHORED_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; -- ELAPSED_STR