Differences
This shows you the differences between two versions of the page.
ada.calendar.clock_to_string [2012/01/02 20:24] thomaslocke [One Solution] |
ada.calendar.clock_to_string [2012/01/03 21:48] (current) thomaslocke [A Full Program] |
||
---|---|---|---|
Line 1: | Line 1: | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | While messing around with [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3741|Ada.Calendar]], a need to output the return value of [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Ada.Calendar.Clock]] as a [[http://adaic.org/standards/05rm/html/RM-3-6-3.html#I1889|String]], took me on an adventure in the land of [[http://adaic.org/standards/05rm/html/RM-11-4-2.html|pragma Assert]], [[http://adaic.org/standards/05rm/html/RM-13-3.html#I4496|the Address attribute]], [[http://adaic.org/standards/05rm/html/RM-13-3.html#I4513|the 'Size attribute]] and the fact that not all Ada compilers are created equal. | + | While messing around with [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3741|Ada.Calendar]], a need to output the return value of [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Ada.Calendar.Clock]] as a [[http://adaic.org/standards/05rm/html/RM-3-6-3.html#I1889|String]], took me on an adventure in the land of [[http://adaic.org/standards/05rm/html/RM-11-4-2.html|pragma Assert]], [[http://adaic.org/standards/05rm/html/RM-13-3.html#I4496|the 'Address attribute]], [[http://adaic.org/standards/05rm/html/RM-13-3.html#I4513|the 'Size attribute]], [[http://www.adaic.org/resources/add_content/standards/05rm/html/RM-13-9.html|Ada.Unchecked_Conversion]] and the fact that not all Ada compilers are created equal. |
===== Caveat ===== | ===== Caveat ===== | ||
- | The following is an example of how to do something. It's not meant to be used in any real capacity. If you need a portable [[http://adaic.org/standards/05rm/html/RM-3-6-3.html#I1889|String]] representation of [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Ada.Calendar.Clock]], then you're better off using the many nice features of [[http://adaic.org/standards/05rm/html/RM-9-6-1.html#I3773|Ada.Calendar.Formatting]]. | + | The following are examples of how to do something. It's not meant to be used in any real capacity. If you need a portable [[http://adaic.org/standards/05rm/html/RM-3-6-3.html#I1889|String]] representation of [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Ada.Calendar.Clock]], then you're better off using the many nice features of [[http://adaic.org/standards/05rm/html/RM-9-6-1.html#I3773|Ada.Calendar.Formatting]]. |
===== The Problem ===== | ===== The Problem ===== | ||
Line 11: | Line 11: | ||
The problem of outputting the return value from [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Ada.Calendar.Clock]] as a string is one of privacy. The returned type, [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Time]], is declared //private//. Also it's implementation defined: | The problem of outputting the return value from [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Ada.Calendar.Clock]] as a string is one of privacy. The returned type, [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Time]], is declared //private//. Also it's implementation defined: | ||
- | <blockquote> | + | |
- | The time base associated with the type Time of package Calendar is implementation defined. The function Clock of package Calendar returns a value representing the current time for this time base. The implementation-defined value of the named number System.Tick (see 13.7) is an approximation of the length of the real-time interval during which the value of Calendar.Clock remains constant. | + | > The time base associated with the type Time of package Calendar is implementation defined. The function Clock of package Calendar returns a value representing the current time for this time base. The implementation-defined value of the named number System.Tick (see 13.7) is an approximation of the length of the real-time interval during which the value of Calendar.Clock remains constant. |
- | </blockquote> | + | |
So we can't see it, and we don't know how it's implemented. But there are ways around these issues. | So we can't see it, and we don't know how it's implemented. But there are ways around these issues. | ||
- | ===== One Solution ===== | + | ===== One Solution ===== |
- | For my experiment I've used the [[http://libre.adacore.com/libre/|GNAT GPL 2010]] compiler, and in this compiler the [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Time]] type is declared as: | + | In this first solution, we're going to make use of the //'Address// attribute. For my experiment I've used the [[http://libre.adacore.com/libre/|GNAT GPL 2010]] compiler, and in this compiler the [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Time]] type is declared as: |
<code ada> | <code ada> | ||
Line 29: | Line 28: | ||
<code ada> | <code ada> | ||
- | function Time_Image | + | function Time_Image_One |
(Item : in Ada.Calendar.Time) | (Item : in Ada.Calendar.Time) | ||
return String | return String | ||
is | is | ||
- | type Time is mod 2 ** 64; | + | type New_Time is mod 2 ** 64; |
- | pragma Assert (Time'Size = Item'Size); | + | pragma Assert (New_Time'Size = Item'Size); |
- | | + | |
- | Time_Stamp : Time; | + | Time_Stamp : New_Time; |
for Time_Stamp'Address use Item'Address; | for Time_Stamp'Address use Item'Address; | ||
begin | begin | ||
- | return Trim (Source => Time'Image (Time_Stamp), | + | return Trim (Source => New_Time'Image (Time_Stamp), |
Side => Ada.Strings.Left); | Side => Ada.Strings.Left); | ||
- | end Time_Image; | + | end Time_Image_One; |
</code> | </code> | ||
Line 49: | Line 48: | ||
<code ada> | <code ada> | ||
- | type Time is mod 2 ** 64; | + | type New_Time is mod 2 ** 64; |
</code> | </code> | ||
- | We declare a new //Time// type with the same size as the [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Ada.Calendar.Time]] type (as defined by the GNAT GPL 2010 compiler). I've used //mod 2 <nowiki>**</nowiki> 64// instead of //range -2 ** 63 .. +2 ** 63 -1//, but that's mostly because I don't care about the sign. You can just as well go with //range -2 ** 63 .. +2 ** 63 -1//. The important thing to bear in mind, is that the two types should have the same size. Which brings us to this: | + | We declare a new //Time// type with the same size as the [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Ada.Calendar.Time]] type (as defined by the GNAT GPL 2010 compiler). I've used //mod 2 <nowiki>**</nowiki> 64// instead of //range -2 <nowiki>**</nowiki> 63 .. +2 <nowiki>**</nowiki> 63 -1//, but that's mostly because I don't care about the sign. You can just as well go with //range -2 <nowiki>**</nowiki> 63 .. +2 <nowiki>**</nowiki> 63 -1//. The important thing to bear in mind, is that the two types should have the same size. Which brings us to this: |
<code ada> | <code ada> | ||
- | pragma Assert (Time'Size = Item'Size); | + | pragma Assert (New_Time'Size = Item'Size); |
</code> | </code> | ||
Line 65: | Line 64: | ||
<code ada> | <code ada> | ||
- | Time_Stamp : Time; | + | Time_Stamp : New_Time; |
for Time_Stamp'Address use Item'Address; | for Time_Stamp'Address use Item'Address; | ||
</code> | </code> | ||
Line 74: | Line 73: | ||
<code ada> | <code ada> | ||
- | return Trim (Source => Time'Image (Time_Stamp), | + | return Trim (Source => New_Time'Image (Time_Stamp), |
Side => Ada.Strings.Left); | Side => Ada.Strings.Left); | ||
</code> | </code> | ||
Line 80: | Line 79: | ||
And voila! We have a neat [[http://adaic.org/standards/05rm/html/RM-3-6-3.html#I1889|String]] representation of the [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Ada.Calendar.Clock]] return value. Whether or not this is useful for anything, well, I'll leave that decision to the reader. | And voila! We have a neat [[http://adaic.org/standards/05rm/html/RM-3-6-3.html#I1889|String]] representation of the [[http://adaic.org/standards/05rm/html/RM-9-6.html#I3747|Ada.Calendar.Clock]] return value. Whether or not this is useful for anything, well, I'll leave that decision to the reader. | ||
- | ===== Thanks ===== | + | ===== Another Solution ===== |
+ | |||
+ | The above solution is not the only way to accomplish the goal of outputting the return value of //Ada.Calendar.Clock//. There's another, and probably better, method: Using [[http://www.adaic.org/resources/add_content/standards/05rm/html/RM-13-9.html|Ada.Unchecked_Conversion]]. Here's how the above //Time_Image_One// function would look if we used //Ada.Unchecked_Conversion// instead: | ||
+ | |||
+ | <code ada> | ||
+ | function Time_Image_Two | ||
+ | (Item : in Ada.Calendar.Time) | ||
+ | return String | ||
+ | is | ||
+ | type New_Time is mod 2 ** 64; | ||
+ | pragma Assert (New_Time'Size = Ada.Calendar.Time'Size); | ||
+ | |||
+ | function To_Time | ||
+ | is new Ada.Unchecked_Conversion (Source => Ada.Calendar.Time, | ||
+ | Target => New_Time); | ||
+ | |||
+ | Time_Stamp : constant New_Time := To_Time (Item); | ||
+ | begin | ||
+ | return Trim (Source => New_Time'Image (Time_Stamp), | ||
+ | Side => Ada.Strings.Left); | ||
+ | end Time_Image_Two; | ||
+ | </code> | ||
+ | |||
+ | A great boon of this method over the first one, is this fantastic warning message the GNAT compiler will dump on you when you compile the program: | ||
+ | |||
+ | warning: representation of Time values may change between GNAT versions | ||
+ | |||
+ | You're not going to get that with the first method, and in my humble opinion that warning alone makes it worthwhile to use //Ada.Unchecked_Conversion// instead of the //'Address// attribute used in the first solution. | ||
+ | ===== The Full Program ===== | ||
+ | |||
+ | Lets end with a little program that utilizes both solutions to output the value of //Ada.Calendar.Clock//: | ||
+ | |||
+ | <code ada> | ||
+ | with Ada.Calendar; | ||
+ | with Ada.Strings.Fixed; | ||
+ | with Ada.Text_IO; | ||
+ | with Ada.Unchecked_Conversion; | ||
+ | |||
+ | procedure Time_Image_Test is | ||
+ | use Ada.Strings.Fixed; | ||
+ | use Ada.Text_IO; | ||
+ | |||
+ | ---------------------- | ||
+ | -- Time_Image_One -- | ||
+ | ---------------------- | ||
+ | |||
+ | function Time_Image_One | ||
+ | (Item : in Ada.Calendar.Time) | ||
+ | return String | ||
+ | is | ||
+ | type New_Time is mod 2 ** 64; | ||
+ | pragma Assert (New_Time'Size = Item'Size); | ||
+ | |||
+ | Time_Stamp : New_Time; | ||
+ | for Time_Stamp'Address use Item'Address; | ||
+ | begin | ||
+ | return Trim (Source => New_Time'Image (Time_Stamp), | ||
+ | Side => Ada.Strings.Left); | ||
+ | end Time_Image_One; | ||
+ | |||
+ | ---------------------- | ||
+ | -- Time_Image_Two -- | ||
+ | ---------------------- | ||
+ | |||
+ | function Time_Image_Two | ||
+ | (Item : in Ada.Calendar.Time) | ||
+ | return String | ||
+ | is | ||
+ | type New_Time is mod 2 ** 64; | ||
+ | pragma Assert (New_Time'Size = Ada.Calendar.Time'Size); | ||
+ | |||
+ | function To_Time | ||
+ | is new Ada.Unchecked_Conversion (Source => Ada.Calendar.Time, | ||
+ | Target => New_Time); | ||
+ | |||
+ | Time_Stamp : constant New_Time := To_Time (Item); | ||
+ | begin | ||
+ | return Trim (Source => New_Time'Image (Time_Stamp), | ||
+ | Side => Ada.Strings.Left); | ||
+ | end Time_Image_Two; | ||
+ | |||
+ | Now : Ada.Calendar.Time := Ada.Calendar.Clock; | ||
+ | begin | ||
+ | Put_Line (Time_Image_One (Now)); | ||
+ | Put_Line (Time_Image_Two (Now)); | ||
+ | end Time_Image_Test; | ||
+ | </code> | ||
+ | |||
+ | Elegant stuff! | ||
+ | |||
+ | ===== Thanks ===== | ||
- | I'd like to extend my thanks to [[http://edb.jacob-sparre.dk/Ada/|Jacob Sparre]] for gently pushing me in the right direction. As usual the [[http://freenode.net/|freenode #ada IRC channel]] proved an invaluable help in learning something new. | + | I'd like to extend my thanks to [[http://edb.jacob-sparre.dk/Ada/|Jacob Sparre]] for gently pushing me in the right direction in regards to solution one, and [[http://identi.ca/simonj|Simon J. Wright]] for giving me the second solution. As usual the [[http://freenode.net/|freenode #ada IRC channel]] and the [[http://identi.ca/thomaslocke/all/ada| identi.ca Ada group]] proved an invaluable help in learning something new. |