]> git.saurik.com Git - wxWidgets.git/blame - src/common/time.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / time.cpp
CommitLineData
59068d79
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/common/time.cpp
3// Purpose: Implementation of time-related functions.
4// Author: Vadim Zeitlin
5// Created: 2011-11-26
6// RCS-ID: $Id: wxhead.cpp,v 1.11 2010-04-22 12:44:51 zeitlin Exp $
7// Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// for compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#include "wx/time.h"
27
173a5ddc 28#ifndef WX_PRECOMP
d98a58c5 29 #ifdef __WINDOWS__
173a5ddc
VZ
30 #include "wx/msw/wrapwin.h"
31 #endif
32 #include "wx/intl.h"
33 #include "wx/log.h"
34#endif
35
59068d79
VZ
36#ifndef WX_GMTOFF_IN_TM
37 // Define it for some systems which don't (always) use configure but are
38 // known to have tm_gmtoff field.
bd362275 39 #if defined(__DARWIN__)
59068d79
VZ
40 #define WX_GMTOFF_IN_TM
41 #endif
42#endif
43
173a5ddc
VZ
44#if defined(__VISAGECPP__) && !defined(HAVE_FTIME)
45 #define HAVE_FTIME
46# if __IBMCPP__ >= 400
47 # define ftime(x) _ftime(x)
48# endif
49#endif
50
173a5ddc
VZ
51#ifndef __WXWINCE__
52#include <time.h>
53#else
54#include "wx/msw/private.h"
55#include "wx/msw/wince/time.h"
56#endif
173a5ddc
VZ
57
58
59#if !defined(__WXMAC__) && !defined(__WXWINCE__)
60 #include <sys/types.h> // for time_t
61#endif
62
63#if defined(HAVE_GETTIMEOFDAY)
64 #include <sys/time.h>
65 #include <unistd.h>
66#elif defined(HAVE_FTIME)
67 #include <sys/timeb.h>
68#endif
69
fb7ce3e8
VZ
70#if defined(__DJGPP__) || defined(__WINE__)
71 #include <sys/timeb.h>
72 #include <values.h>
73#endif
74
173a5ddc
VZ
75namespace
76{
77
78const int MILLISECONDS_PER_SECOND = 1000;
79const int MICROSECONDS_PER_MILLISECOND = 1000;
80const int MICROSECONDS_PER_SECOND = 1000*1000;
81
82} // anonymous namespace
83
59068d79
VZ
84// ============================================================================
85// implementation
86// ============================================================================
87
fb7ce3e8
VZ
88// NB: VC8 safe time functions could/should be used for wxMSW as well probably
89#if defined(__WXWINCE__) && defined(__VISUALC8__)
90
91struct tm *wxLocaltime_r(const time_t *t, struct tm* tm)
92{
93 __time64_t t64 = *t;
94 return _localtime64_s(tm, &t64) == 0 ? tm : NULL;
95}
96
97struct tm *wxGmtime_r(const time_t* t, struct tm* tm)
98{
99 __time64_t t64 = *t;
100 return _gmtime64_s(tm, &t64) == 0 ? tm : NULL;
101}
102
103#else // !wxWinCE with VC8
104
105#if (!defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)) && wxUSE_THREADS && !defined(__WINDOWS__)
106static wxMutex timeLock;
107#endif
108
109#ifndef HAVE_LOCALTIME_R
110struct tm *wxLocaltime_r(const time_t* ticks, struct tm* temp)
111{
112#if wxUSE_THREADS && !defined(__WINDOWS__)
113 // No need to waste time with a mutex on windows since it's using
114 // thread local storage for localtime anyway.
115 wxMutexLocker locker(timeLock);
116#endif
117
118 // Borland CRT crashes when passed 0 ticks for some reason, see SF bug 1704438
119#ifdef __BORLANDC__
120 if ( !*ticks )
121 return NULL;
122#endif
123
124 const tm * const t = localtime(ticks);
125 if ( !t )
126 return NULL;
127
128 memcpy(temp, t, sizeof(struct tm));
129 return temp;
130}
131#endif // !HAVE_LOCALTIME_R
132
133#ifndef HAVE_GMTIME_R
134struct tm *wxGmtime_r(const time_t* ticks, struct tm* temp)
135{
136#if wxUSE_THREADS && !defined(__WINDOWS__)
137 // No need to waste time with a mutex on windows since it's
138 // using thread local storage for gmtime anyway.
139 wxMutexLocker locker(timeLock);
140#endif
141
142#ifdef __BORLANDC__
143 if ( !*ticks )
144 return NULL;
145#endif
146
147 const tm * const t = gmtime(ticks);
148 if ( !t )
149 return NULL;
150
151 memcpy(temp, gmtime(ticks), sizeof(struct tm));
152 return temp;
153}
154#endif // !HAVE_GMTIME_R
155
156#endif // wxWinCE with VC8/other platforms
157
59068d79
VZ
158// returns the time zone in the C sense, i.e. the difference UTC - local
159// (in seconds)
160int wxGetTimeZone()
161{
162#ifdef WX_GMTOFF_IN_TM
163 // set to true when the timezone is set
164 static bool s_timezoneSet = false;
165 static long gmtoffset = LONG_MAX; // invalid timezone
166
167 // ensure that the timezone variable is set by calling wxLocaltime_r
168 if ( !s_timezoneSet )
169 {
170 // just call wxLocaltime_r() instead of figuring out whether this
171 // system supports tzset(), _tzset() or something else
172 time_t t = time(NULL);
173 struct tm tm;
174
175 wxLocaltime_r(&t, &tm);
176 s_timezoneSet = true;
177
178 // note that GMT offset is the opposite of time zone and so to return
179 // consistent results in both WX_GMTOFF_IN_TM and !WX_GMTOFF_IN_TM
180 // cases we have to negate it
181 gmtoffset = -tm.tm_gmtoff;
182
183 // this function is supposed to return the same value whether DST is
184 // enabled or not, so we need to use an additional offset if DST is on
185 // as tm_gmtoff already does include it
186 if ( tm.tm_isdst )
187 gmtoffset += 3600;
188 }
189 return (int)gmtoffset;
190#elif defined(__DJGPP__) || defined(__WINE__)
191 struct timeb tb;
192 ftime(&tb);
193 return tb.timezone*60;
194#elif defined(__VISUALC__)
195 // We must initialize the time zone information before using it (this will
196 // be done only once internally).
197 _tzset();
198
199 // Starting with VC++ 8 timezone variable is deprecated and is not even
200 // available in some standard library version so use the new function for
201 // accessing it instead.
202 #if wxCHECK_VISUALC_VERSION(8)
203 long t;
204 _get_timezone(&t);
205 return t;
206 #else // VC++ < 8
207 return timezone;
208 #endif
8c7114c2
VZ
209#else // Use some kind of time zone variable.
210 // In any case we must initialize the time zone before using it.
211 tzset();
212
213 #if defined(WX_TIMEZONE) // If WX_TIMEZONE was defined by configure, use it.
214 return WX_TIMEZONE;
215 #elif defined(__BORLANDC__) || defined(__MINGW32__) || defined(__VISAGECPP__)
216 return _timezone;
8c7114c2
VZ
217 #else // unknown platform -- assume it has timezone
218 return timezone;
219 #endif // different time zone variables
220#endif // different ways to determine time zone
59068d79 221}
173a5ddc
VZ
222
223// Get local time as seconds since 00:00:00, Jan 1st 1970
224long wxGetLocalTime()
225{
226 struct tm tm;
227 time_t t0, t1;
228
229 // This cannot be made static because mktime can overwrite it.
230 //
231 memset(&tm, 0, sizeof(tm));
232 tm.tm_year = 70;
233 tm.tm_mon = 0;
234 tm.tm_mday = 5; // not Jan 1st 1970 due to mktime 'feature'
235 tm.tm_hour = 0;
236 tm.tm_min = 0;
237 tm.tm_sec = 0;
238 tm.tm_isdst = -1; // let mktime guess
239
240 // Note that mktime assumes that the struct tm contains local time.
241 //
242 t1 = time(&t1); // now
243 t0 = mktime(&tm); // origin
244
245 // Return the difference in seconds.
246 //
247 if (( t0 != (time_t)-1 ) && ( t1 != (time_t)-1 ))
248 return (long)difftime(t1, t0) + (60 * 60 * 24 * 4);
249
250 wxLogSysError(_("Failed to get the local system time"));
251 return -1;
252}
253
254// Get UTC time as seconds since 00:00:00, Jan 1st 1970
255long wxGetUTCTime()
256{
257 return (long)time(NULL);
258}
259
260#if wxUSE_LONGLONG
261
262wxLongLong wxGetUTCTimeUSec()
263{
d98a58c5 264#if defined(__WINDOWS__)
173a5ddc
VZ
265 FILETIME ft;
266 ::GetSystemTimeAsFileTime(&ft);
267
268 // FILETIME is in 100ns or 0.1us since 1601-01-01, transform to us since
269 // 1970-01-01.
270 wxLongLong t(ft.dwHighDateTime, ft.dwLowDateTime);
271 t /= 10;
272 t -= wxLL(11644473600000000); // Unix - Windows epochs difference in us.
273 return t;
274#else // non-MSW
275
276#ifdef HAVE_GETTIMEOFDAY
277 timeval tv;
278 if ( wxGetTimeOfDay(&tv) != -1 )
279 {
280 wxLongLong val(tv.tv_sec);
281 val *= MICROSECONDS_PER_SECOND;
282 val += tv.tv_usec;
283 return val;
284 }
285#endif // HAVE_GETTIMEOFDAY
286
287 // Fall back to lesser precision function.
288 return wxGetUTCTimeMillis()*MICROSECONDS_PER_MILLISECOND;
289#endif // MSW/!MSW
290}
291
292// Get local time as milliseconds since 00:00:00, Jan 1st 1970
293wxLongLong wxGetUTCTimeMillis()
294{
173a5ddc
VZ
295 // If possible, use a function which avoids conversions from
296 // broken-up time structures to milliseconds
d98a58c5 297#if defined(__WINDOWS__)
173a5ddc
VZ
298 FILETIME ft;
299 ::GetSystemTimeAsFileTime(&ft);
300
301 // FILETIME is expressed in 100ns (or 0.1us) units since 1601-01-01,
302 // transform them to ms since 1970-01-01.
303 wxLongLong t(ft.dwHighDateTime, ft.dwLowDateTime);
304 t /= 10000;
305 t -= wxLL(11644473600000); // Unix - Windows epochs difference in ms.
306 return t;
85ad2fa7
VZ
307#else // !__WINDOWS__
308 wxLongLong val = MILLISECONDS_PER_SECOND;
309
310#if defined(HAVE_GETTIMEOFDAY)
173a5ddc
VZ
311 struct timeval tp;
312 if ( wxGetTimeOfDay(&tp) != -1 )
313 {
314 val *= tp.tv_sec;
315 return (val + (tp.tv_usec / MICROSECONDS_PER_MILLISECOND));
316 }
317 else
318 {
319 wxLogError(_("wxGetTimeOfDay failed."));
320 return 0;
321 }
322#elif defined(HAVE_FTIME)
323 struct timeb tp;
324
325 // ftime() is void and not int in some mingw32 headers, so don't
326 // test the return code (well, it shouldn't fail anyhow...)
327 (void)::ftime(&tp);
328 val *= tp.time;
329 return (val + tp.millitm);
330#else // no gettimeofday() nor ftime()
331 // If your platform/compiler does not support ms resolution please
332 // do NOT just shut off these warnings, drop me a line instead at
333 // <guille@iies.es>
334
335 #if defined(__VISUALC__) || defined (__WATCOMC__)
336 #pragma message("wxStopWatch will be up to second resolution!")
337 #elif defined(__BORLANDC__)
338 #pragma message "wxStopWatch will be up to second resolution!"
339 #else
340 #warning "wxStopWatch will be up to second resolution!"
341 #endif // compiler
342
343 val *= wxGetUTCTime();
344 return val;
345#endif // time functions
85ad2fa7
VZ
346
347#endif // __WINDOWS__/!__WINDOWS__
173a5ddc
VZ
348}
349
350wxLongLong wxGetLocalTimeMillis()
351{
352 return wxGetUTCTimeMillis() - wxGetTimeZone()*MILLISECONDS_PER_SECOND;
353}
354
355#else // !wxUSE_LONGLONG
356
357double wxGetLocalTimeMillis(void)
358{
359 return (double(clock()) / double(CLOCKS_PER_SEC)) * 1000.0;
360}
361
362#endif // wxUSE_LONGLONG/!wxUSE_LONGLONG