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