encoding: avoid doing any work if we don't have to
[iv.d.git] / timer.d
blob1e83c2df5b2b70d2d7bd37bc2977e73f40ed5cbf
1 /* Invisible Vector Library
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 // this essentially duplicates std.datetime.StopWatch, but meh...
18 module iv.timer;
20 import iv.pxclock;
23 struct Timer {
24 private:
25 ulong mSTimeMicro;
26 ulong mAccumMicro;
27 State mState = State.Stopped;
29 public:
30 enum State {
31 Stopped,
32 Running,
33 Paused,
36 public:
37 string toString () const @trusted {
38 char[128] buf = void;
39 auto t = toBuffer(buf[]);
40 return t.idup;
43 nothrow @trusted @nogc:
44 this (State initState) @trusted {
45 if (initState == State.Running) start();
48 this (bool startit) @trusted {
49 if (startit) start();
52 @property const pure {
53 auto state () { pragma(inline, true); return mState; }
54 bool stopped () { pragma(inline, true); return (mState == State.Stopped); }
55 bool running () { pragma(inline, true); return (mState == State.Running); }
56 bool paused () { pragma(inline, true); return (mState == State.Paused); }
59 @property ulong micro () const {
60 final switch (mState) {
61 case State.Stopped: case State.Paused: return mAccumMicro;
62 case State.Running: return mAccumMicro+(clockMicro-mSTimeMicro);
66 @property ulong milli () const { pragma(inline, true); return micro/1000; }
68 void reset () {
69 mAccumMicro = 0;
70 mSTimeMicro = clockMicro;
73 void restart () {
74 mAccumMicro = 0;
75 mState = State.Running;
76 mSTimeMicro = clockMicro;
79 void start () {
80 mAccumMicro = 0;
81 mState = State.Running;
82 mSTimeMicro = clockMicro;
85 void stop () {
86 if (mState == State.Running) {
87 mAccumMicro += clockMicro-mSTimeMicro;
88 mState = State.Stopped;
92 void pause () {
93 if (mState == State.Running) {
94 mAccumMicro += clockMicro-mSTimeMicro;
95 mState = State.Paused;
99 void resume () {
100 if (mState == State.Paused) {
101 mState = State.Running;
102 mSTimeMicro = clockMicro;
103 } else if (mState == State.Stopped) {
104 start();
108 // 128 chars should be enough for everyone
109 char[] toBuffer (char[] dest) const nothrow @trusted @nogc {
110 import core.stdc.stdio : snprintf;
111 char[128] buf = void;
112 ulong d;
113 final switch (mState) {
114 case State.Stopped: case State.Paused: d = mAccumMicro; break;
115 case State.Running: d = mAccumMicro+(clockMicro-mSTimeMicro); break;
117 immutable uint micro = cast(uint)(d%1000);
118 d /= 1000;
119 immutable uint milli = cast(uint)(d%1000);
120 d /= 1000;
121 immutable uint seconds = cast(uint)(d%60);
122 d /= 60;
123 immutable uint minutes = cast(uint)(d%60);
124 d /= 60;
125 immutable uint hours = cast(uint)d;
126 uint len;
127 if (hours) len = cast(uint)snprintf(buf.ptr, buf.length, "%u:%02u:%02u.%03u", hours, minutes, seconds, milli);
128 else if (minutes) len = cast(uint)snprintf(buf.ptr, buf.length, "%u:%02u.%03u", minutes, seconds, milli);
129 else if (seconds) len = cast(uint)snprintf(buf.ptr, buf.length, "%u.%03u", seconds, milli);
130 else if (micro != 0) len = cast(uint)snprintf(buf.ptr, buf.length, "%ums:%umcs", milli, micro);
131 else len = cast(uint)snprintf(buf.ptr, buf.length, "%ums", milli);
132 if (len > dest.length) len = cast(uint)dest.length;
133 dest.ptr[0..len] = buf.ptr[0..len];
134 return dest.ptr[0..len];