1 /*
2 DSFML - The Simple and Fast Multimedia Library for D
3 
4 Copyright (c) 2013 - 2015 Jeremy DeHaan (dehaan.jeremiah@gmail.com)
5 
6 This software is provided 'as-is', without any express or implied warranty.
7 In no event will the authors be held liable for any damages arising from the use of this software.
8 
9 Permission is granted to anyone to use this software for any purpose, including commercial applications,
10 and to alter it and redistribute it freely, subject to the following restrictions:
11 
12 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
13 If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
14 
15 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
16 
17 3. This notice may not be removed or altered from any source distribution
18 */
19 
20 ///A module containing the Time struct
21 module dsfml.system.time;
22 
23 import std.traits;
24 
25 /**
26  *Represents a time value
27  *
28  *The Time struct encapsulates a time value in a flexible way.
29  *
30  *It allows to define a time value either as a number of seconds, milliseconds or microseconds. It also works the other way round: you can read a time value as either a number of seconds, milliseconds or microseconds.
31  *
32  *By using such a flexible interface, the API doesn't impose any fixed type or resolution for time values, and let the user choose its own favorite representation.
33  *
34  *Time values support the usual mathematical operations: you can add or subtract two times, multiply or divide a time by a number, compare two times, etc.
35  *
36  *Since they represent a time span and not an absolute time value, times can also be negative.
37  */
38 struct Time
39 {
40 	private long m_microseconds;
41 	
42 	//Internal constructor
43 	package this(long microseconds)
44 	{
45 		m_microseconds = microseconds;
46 	}
47 	
48 	///Return the time value as a number of seconds.
49 	///
50 	///Returns: Time in seconds.
51 	float asSeconds() const
52 	{
53 		return m_microseconds/1000000f;
54 	}
55 
56 	///Return the time value as a number of milliseconds.
57 	///
58 	///Returns: Time in milliseconds.
59 	int asMilliseconds() const
60 	{
61 		return cast(int)(m_microseconds / 1000);
62 	}
63 
64 	///Return the time value as a number of microseconds.
65 	///
66 	///Returns: Time in microseconds.
67 	long asMicroseconds() const
68 	{
69 		return m_microseconds;
70 	}
71 	
72 
73 	///Predefined "zero" time value.
74 	static immutable(Time) Zero;
75 	
76 	bool opEquals(const ref Time rhs)
77 	{
78 		return m_microseconds == rhs.m_microseconds;
79 	}
80 	
81 	int opCmp(const ref Time rhs)
82 	{
83 		if(opEquals(rhs))
84 		{
85 			return 0;
86 		}
87 		else if(m_microseconds < rhs.m_microseconds)
88 		{
89 			return -1;
90 		}
91 		else
92 		{
93 			return 1;
94 		}
95 
96 		
97 	}
98 	
99 	Time opUnary(string s)() const
100 	if (s == "-")
101 	{
102 		return microseconds(-m_microseconds);
103 	}
104 	
105 	
106 	Time opBinary(string op)(Time rhs) const
107 	if((op == "+") || (op == "-"))
108 	{
109 		static if (op == "+")
110 		{
111 			return microseconds(m_microseconds + rhs.m_microseconds);
112 		}
113 		static if(op == "-")
114 		{
115 			return microseconds(m_microseconds - rhs.m_microseconds);
116 		}
117 	}
118 	
119 	ref Time opOpAssign(string op)(Time rhs)
120 	if((op == "+") || (op == "-"))
121 	{
122 		static if(op == "+")
123 		{
124 			m_microseconds += rhs.m_microseconds;
125 			return this;
126 		}
127 		static if(op == "-")
128 		{
129 			m_microseconds -= rhs.m_microseconds;
130 			return this;
131 		}
132 	}
133 	
134 	
135 	Time opBinary (string op, E)(E num) const
136 	if(isNumeric!(E) && ((op == "*") || (op == "/")))
137 	{
138 		static if (op == "*")
139 		{
140 			return microseconds(m_microseconds * num);
141 		}
142 		static if(op == "/")
143 		{
144 			return microseconds(m_microseconds / num);
145 		}
146 	}
147 	
148 	
149 	ref Time opOpAssign(string op,E)(E num)
150 	if(isNumeric!(E) && ((op == "*") || (op == "/")))
151 	{
152 		static if(op == "*")
153 		{
154 			m_microseconds *= num;
155 			return this;
156 		}
157 		static if(op == "/")
158 		{
159 			m_microseconds /= num;
160 			return this;
161 		}
162 	}
163 	
164 }
165 
166 ///Construct a time value from a number of seconds.
167 ///
168 ///Params:
169 ///  amount = Number of seconds.
170 ///
171 ///Returns : Time value constructed from the amount of microseconds.
172 Time seconds(float amount)
173 {
174 	return Time(cast(long)(amount * 1000000));
175 }
176 
177 ///Construct a time value from a number of milliseconds.
178 ///
179 /// Params:
180 ///  	amount = Number of milliseconds.
181 ///
182 /// Returns: Time value constructed from the amount of microseconds.
183 Time milliseconds(int amount)
184 {
185 	return Time(amount*1000);
186 }
187 
188 ///Construct a time value from a number of microseconds.
189 ///
190 ///Params:
191 ///  amount = Number of microseconds.
192 ///
193 ///Returns : Time value constructed from the amount of microseconds.
194 Time microseconds(long amount)
195 {
196 	return Time( amount);
197 }
198 
199 unittest
200 {
201 	version(DSFML_Unittest_System)
202 	{
203 
204 		import std.stdio;
205 
206 		writeln("Unit test for Time Struct");
207 
208 		auto time = seconds(1);
209 
210 		assert(time.asSeconds() == 1);
211 
212 		assert((time*2).asSeconds() == 2);
213 
214 		assert((time/2).asSeconds() == .5f);
215 
216 		assert((time+seconds(1)).asSeconds() == 2);
217 
218 		assert((time-seconds(1)).asSeconds() == 0);
219 
220 		time += seconds(1);
221 
222 		assert(time.asSeconds() == 2);
223 
224 		time -= seconds(1);
225 
226 		assert(time.asSeconds() == 1);
227 
228 		time/=2;
229 
230 		assert(time.asSeconds() == .5f);
231 
232 		time*=2;
233 
234 		assert(time.asSeconds() == 1);
235 
236 		writeln("Time Struct passes all tests.");
237 		writeln();
238 	}
239 }