gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

ptime.cxx (7362B)


      1 /*
      2  *
      3  *  C++ Portable Types Library (PTypes)
      4  *  Version 2.1.1  Released 27-Jun-2007
      5  *
      6  *  Copyright (C) 2001-2007 Hovik Melikyan
      7  *
      8  *  http://www.melikyan.com/ptypes/
      9  *
     10  */
     11 
     12 // altzone fix for Sun/GCC 3.2. any better ideas?
     13 #if defined(__sun__) && defined(__GNUC__) && defined(_XOPEN_SOURCE)
     14 #  undef _XOPEN_SOURCE
     15 #endif
     16 
     17 #ifdef WIN32
     18 #  include <windows.h>
     19 #else
     20 #  include <sys/time.h>
     21 #endif
     22 
     23 #include <time.h>
     24 #include <string.h>
     25 
     26 #include "ptime.h"
     27 
     28 
     29 namespace ptypes {
     30 
     31 
     32 datetime ptdecl mkdt(int days, int msecs)
     33 {
     34     return large(days) * _msecsmax + msecs;
     35 }
     36 
     37 
     38 bool ptdecl isvalid(datetime d)
     39 {
     40     return d >= 0 && d < _datetimemax;
     41 }
     42 
     43 
     44 bool ptdecl isleapyear(int year)
     45 {
     46     return year > 0 && year % 4 == 0 
     47         && (year % 100 != 0 || year % 400 == 0);
     48 }
     49 
     50 
     51 int ptdecl daysinmonth(int year, int month)
     52 {
     53     if (month < 1 || month > 12)
     54         return 0;
     55     static const int mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
     56     int res = mdays[month - 1];
     57     if (month == 2)
     58         if (isleapyear(year))
     59             res++;
     60     return res;
     61 }
     62 
     63 
     64 int ptdecl daysinyear(int year, int month)
     65 {
     66     if (month < 1 || month > 12)
     67         return 0;
     68     static const int ndays[12] = {31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
     69     int res = ndays[month - 1];
     70     if (month > 1)
     71         if (isleapyear(year))
     72             res++;
     73     return res;
     74 }
     75 
     76 
     77 int ptdecl dayofweek(datetime d)
     78 {
     79     return (days(d) + 1) % 7;
     80 }
     81 
     82 
     83 bool ptdecl isdatevalid(int year, int month, int day)
     84 {
     85     return year >= 1 && year <= 9999 
     86         && month >= 1 && month <= 12
     87         && day >= 1 && day <= daysinmonth(year, month);
     88 }
     89 
     90 
     91 datetime ptdecl encodedate(int year, int month, int day)
     92 {
     93     if (!isdatevalid(year, month, day))
     94         return invdatetime;
     95     int y = year - 1;
     96     return mkdt(day                     // days in this month
     97         + daysinyear(year, month - 1)   // plus days since the beginning of the year
     98         + y * 365                       // plus "pure" days
     99         + y / 4 - y / 100 + y / 400     // plus leap year correction
    100         - 1, 0);                        // ... minus one (guess why :)
    101 }
    102 
    103 
    104 bool ptdecl decodedate(datetime date, int& year, int& month, int& day)
    105 {
    106     int d = days(date);
    107     if (d < 0 || d >= _daysmax)     // allowed date range is 01/01/0001 - 12/31/9999
    108     {
    109         year = 0;
    110         month = 0;
    111         day = 0;
    112         return false;
    113     }
    114 
    115     const int d1 = 365;             // number of days in 1 year
    116     const int d4 = d1 * 4 + 1;      // ... in 4 year period
    117     const int d100 = d4 * 25 - 1;   // ... in 100 year period
    118     const int d400 = d100 * 4 + 1;  // ... in 400 year period
    119 
    120     year = (d / d400) * 400 + 1;
    121     d %= d400;
    122 
    123     int t = d / d100;
    124     d %= d100;
    125     if (t == 4)
    126     {
    127         t--;
    128         d += d100;
    129     }
    130     year += t * 100;
    131 
    132     year += (d / d4) * 4;
    133     d %= d4;
    134 
    135     t = d / d1;
    136     d %= d1;
    137     if (t == 4)
    138     {
    139         t--;
    140         d += d1;
    141     }
    142     year += t;
    143 
    144     month = d / 29;                     // approximate month no. (to avoid loops)
    145     if (d < daysinyear(year, month))    // month no. correction
    146         month--;
    147 
    148     day = d - daysinyear(year, month) + 1;
    149     month++;
    150     return true;
    151 }
    152 
    153 
    154 bool ptdecl istimevalid(int hour, int min, int sec, int msec)
    155 {
    156     return hour >= 0 && hour < 24 
    157         && min >= 0 && min < 60 
    158         && sec >= 0 && sec < 60 
    159         && msec >= 0 && msec < 1000;
    160 }
    161 
    162 
    163 datetime ptdecl encodetime(int hour, int min, int sec, int msec)
    164 {
    165     large res = large(hour) * 3600000 + large(min) * 60000 + large(sec) * 1000 + msec;
    166     if (!isvalid(res))
    167         res = invdatetime;
    168     return res;
    169 }
    170 
    171 
    172 bool ptdecl decodetime(datetime t, int& hour, int& min, int& sec, int& msec)
    173 {
    174     if (!isvalid(t))
    175     {
    176         hour = 0;
    177         min = 0;
    178         sec = 0;
    179         msec = 0;
    180         return false;
    181     }
    182     int m = msecs(t);
    183     hour = m / 3600000;
    184     m %= 3600000;
    185     min = m / 60000;
    186     m %= 60000;
    187     sec = m / 1000;
    188     msec = m % 1000;
    189     return true;
    190 }
    191 
    192 
    193 bool ptdecl decodetime(datetime t, int& hour, int& min, int& sec)
    194 {
    195     int msec;
    196     return decodetime(t, hour, min, sec, msec);
    197 }
    198 
    199 
    200 tm* ptdecl dttotm(datetime dt, tm& t)
    201 {
    202     memset(&t, 0, sizeof(tm));
    203     if (!decodedate(dt, t.tm_year, t.tm_mon, t.tm_mday) 
    204         || !decodetime(dt, t.tm_hour, t.tm_min, t.tm_sec))
    205             return nil;
    206     t.tm_mon--;
    207     t.tm_yday = daysinyear(t.tm_year, t.tm_mon) + t.tm_mday - 1;
    208     t.tm_wday = dayofweek(dt);
    209     t.tm_year -= 1900;
    210     return &t;
    211 }
    212 
    213 
    214 string ptdecl dttostring(datetime dt, const char* fmt)
    215 {
    216     char buf[128];
    217     tm t;
    218     int r = (int)strftime(buf, sizeof(buf), fmt, dttotm(dt, t));
    219     buf[r] = 0;
    220     return string(buf);
    221 }
    222 
    223 
    224 datetime ptdecl now(bool utc)
    225 {
    226 #ifdef WIN32
    227     SYSTEMTIME t;
    228     if (utc)
    229         GetSystemTime(&t);
    230     else
    231         GetLocalTime(&t);
    232     return encodedate(t.wYear, t.wMonth, t.wDay) +
    233         encodetime(t.wHour, t.wMinute, t.wSecond, t.wMilliseconds);
    234 
    235 #else   // Unix
    236     // we can't use localtime() and gmtime() here as they don't return
    237     // milliseconds which are needed for our datetime format. instead,
    238     // we call gettimeofday() which have microsecond precision, and then
    239     // adjust the time according to timzone info returned by localtime()
    240     // on BSD and Linux, and global variables altzone/timezone on SunOS.
    241 
    242     // NOTE: at the moment of passing the DST adjustment (twice a year)
    243     // the local time value returned by now() may be incorrect.
    244     // the application should call tzupdate() from time to time if it
    245     // is supposed to be running infinitely, e.g. if it's a daemon.
    246 
    247     // always rely on UTC time inside your application whenever possible.
    248     timeval tv;
    249     gettimeofday(&tv, nil);
    250     int edays = tv.tv_sec / 86400  // days since Unix "Epoch", i.e. 01/01/1970
    251         + 719162;                  // plus days between 01/01/0001 and Unix Epoch
    252     int esecs = tv.tv_sec % 86400; // the remainder, i.e. seconds since midnight
    253     datetime res = mkdt(edays, esecs * 1000 + tv.tv_usec / 1000);
    254 
    255     if (!utc)
    256         res += tzoffset() * 60 * 1000;
    257     return res;
    258 #endif
    259 }
    260 
    261 
    262 void ptdecl tzupdate()
    263 {
    264     tzset();
    265 }
    266 
    267 
    268 int ptdecl tzoffset()
    269 {
    270 #if defined(WIN32)
    271     TIME_ZONE_INFORMATION tz;
    272     DWORD res = GetTimeZoneInformation(&tz);
    273     if ((res == TIME_ZONE_ID_DAYLIGHT) && (tz.DaylightDate.wMonth != 0))
    274         return - (tz.Bias +  tz.DaylightBias);
    275     else
    276         return - tz.Bias;
    277 
    278 #else   // UNIX
    279     time_t t0 = time(0);
    280 
    281 #if defined(__sun__)
    282 #ifdef PTYPES_ST
    283     // localtime_r() is not available without -D_REENTRANT
    284     tm* t = localtime(&t0);
    285     if(t->tm_isdst != 0 && daylight != 0) 
    286 #else
    287     tm t;
    288     localtime_r(&t0, &t); 
    289     if(t.tm_isdst != 0 && daylight != 0) 
    290 #endif
    291         return - altzone / 60; 
    292     else 
    293         return - timezone / 60; 
    294 
    295 #elif defined(__CYGWIN__)
    296     time_t local_time = time(NULL);
    297     tm gt;
    298     gmtime_r(&local_time, &gt);
    299     time_t gmt_time = mktime(&gt);
    300     return (local_time - gmt_time) / 60;
    301 
    302 #elif defined(__hpux)
    303     tm local;
    304     localtime_r(&t0, &local);
    305     local.tm_isdst = 0;
    306     time_t t1 = mktime(&local);
    307     return - (timezone - (t1 - t0)) / 60;
    308 
    309 #else   // other UNIX
    310     tm t;
    311     localtime_r(&t0, &t);
    312     return t.tm_gmtoff / 60;
    313 #endif
    314 
    315 #endif
    316 }
    317 
    318 
    319 datetime ptdecl utodatetime(time_t u)
    320 {
    321     return _unixepoch + large(u) * 1000;
    322 }
    323 
    324 
    325 }