Vault  4.1
vinstant_platform.cpp
00001 /*
00002 Copyright c1997-2014 Trygve Isaacson. All rights reserved.
00003 This file is part of the Code Vault version 4.1
00004 http://www.bombaydigital.com/
00005 License: MIT. See LICENSE.md in the Vault top level directory.
00006 */
00007 
00008 #include "vinstant.h"
00009 #include "vtypes_internal.h"
00010 #include "vexception.h"
00011 
00012 #include <sys/time.h>
00013 
00014 /*
00015 These are the platform-specific implementations of these required
00016 core time functions.
00017 */
00018 
00019 #ifdef VLIBRARY_METROWERKS
00020 static Vs64 _getMSLLocalTimeZoneOffsetMilliseconds() {
00021     /*
00022     When compiling with Metrowerks CodeWarrior on Mac, the MSL library's version of mktime() is incorrect
00023     in that it does not actually do the local time zone conversion. That is, it behaves like timegm().
00024     We need to work around this bug by subtracting the local time zone offset.
00025     This is sort of the inverse of the problem with VC++ in the other conditionally compiled code above.
00026     FIXME: The remaining issue is that we are referencing the CURRENT tz offset, not the offset at the
00027     time that is being queried; and this seems to always be standard time -- e.g., 8hrs in Oakland,
00028     never 7hrs even in summertime DST. So in summertime this makes us off by 1 hr.
00029     */
00030 
00031     int offsetSeconds = 0;
00032 
00033     struct timezone zone;
00034 
00035     if (::gettimeofday(NULL, &zone) == 0) {
00036         offsetSeconds = (zone.tz_minuteswest * 60);
00037     }
00038 
00039     return CONST_S64(1000) * static_cast<Vs64>(offsetSeconds);
00040 }
00041 #endif
00042 
00043 #define INSTANT_STRUCT_FORMAT "%d-%02d-%02d %02d:%02d:%02d.%03d"
00044 
00045 // static
00046 Vs64 VInstantStruct::_platform_offsetFromLocalStruct(const VInstantStruct& when) {
00047     struct tm fields;
00048 
00049     when.getTmStruct(fields);
00050 
00051     //lint -e421 "Caution -- function 'mktime(struct tm *)' is considered dangerous [MISRA Rule 127]"
00052     Vs64 mktimeSeconds = static_cast<Vs64>(::mktime(&fields));
00053 
00054     if (mktimeSeconds == CONST_S64(-1)) {
00055         throw VStackTraceException(VSTRING_FORMAT("VInstantStruct::_platform_offsetFromLocalStruct: time value '" INSTANT_STRUCT_FORMAT "' is out of range.",
00056             when.mYear, when.mMonth, when.mDay, when.mHour, when.mMinute, when.mSecond, when.mMillisecond));
00057     }
00058     
00059     Vs64 resultOffsetMilliseconds = CONST_S64(1000) * mktimeSeconds;
00060 
00061 #ifdef VLIBRARY_METROWERKS
00062     resultOffsetMilliseconds += _getMSLLocalTimeZoneOffsetMilliseconds();
00063 #endif
00064 
00065     // tm struct has no milliseconds, so restore input value milliseconds
00066     resultOffsetMilliseconds += (Vs64) when.mMillisecond;
00067 
00068     return resultOffsetMilliseconds;
00069 }
00070 
00071 // static
00072 void VInstantStruct::_platform_offsetToLocalStruct(Vs64 offset, VInstantStruct& when) {
00073     struct tm fields;
00074     ::memset(&fields, 0, sizeof(fields));
00075 
00076 #ifdef VLIBRARY_METROWERKS
00077     offset -= _getMSLLocalTimeZoneOffsetMilliseconds();
00078 #endif
00079 
00080     VInstantStruct::_threadsafe_localtime(static_cast<time_t>(offset / 1000), &fields);
00081 
00082     when.setFromTmStruct(fields, (int)(offset % 1000));
00083 }
00084 
00085 // static
00086 void VInstantStruct::_platform_offsetToUTCStruct(Vs64 offset, VInstantStruct& when) {
00087     struct tm fields;
00088     ::memset(&fields, 0, sizeof(fields));
00089 
00090     VInstantStruct::_threadsafe_gmtime(static_cast<time_t>(offset / 1000), &fields);
00091 
00092     when.setFromTmStruct(fields, (int)(offset % 1000));
00093 }
00094 
00095 // static
00096 Vs64 VInstant::_platform_now() {
00097 #ifdef V_INSTANT_SNAPSHOT_IS_UTC
00098 
00099     // This means we can get millisecond resolution for VInstant values.
00100     return VInstant::_platform_snapshot();
00101 
00102 #else
00103 
00104     // This means we can only get second resolution for VInstant values.
00105     //lint -e418 -e421 "Passing null pointer to function 'time(long *)'" [OK: IEEE POSIX disagrees with lint. NULL is meaningful.]
00106     return (CONST_S64(1000) * static_cast<Vs64>(::time(NULL)));
00107 
00108 #endif /* V_INSTANT_SNAPSHOT_IS_UTC */
00109 }
00110 
00111 // static
00112 Vs64 VInstant::_platform_snapshot() {
00113     struct timeval tv;
00114     (void) ::gettimeofday(&tv, NULL);
00115 
00116     // We need to be careful to cast to Vs64 or we risk truncation to 32 bits.
00117     return (((Vs64)(tv.tv_sec)) * CONST_S64(1000)) + (Vs64)(tv.tv_usec / 1000);
00118 }
00119 

Copyright ©1997-2014 Trygve Isaacson. All rights reserved. This documentation was generated with Doxygen.