File Coverage

TZ.xs
Criterion Covered Total %
statement 62 62 100.0
branch 49 62 79.0
condition n/a
subroutine n/a
pod n/a
total 111 124 89.5


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4              
5             #include "ppport.h"
6              
7             #include
8             #include
9              
10              
11             #define TIME_STRING_SIZE 26
12              
13              
14             /* thanks to Michael Schout's Env::C module, this solves problem with FreeBSD */
15              
16             /* in order to work around system and perl implementation bugs/leaks, we need
17             * to sometimes force PERL_USE_SAFE_PUTENV mode.
18             */
19             #ifndef PERL_USE_SAFE_PUTENV
20             # if PERL_BCDVERSION >= 0x5009004 && defined(USE_ITHREADS) && defined(PERL_TRACK_MEMPOOL)
21             # define USE_SAFE_PUTENV 1
22             # elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
23             # define USE_SAFE_PUTENV 1
24             # endif
25             #endif
26              
27             #ifdef USE_SAFE_PUTENV
28             # define SAFE_PUTENV_ON() PL_use_safe_putenv = 1;
29             #else
30             # define SAFE_PUTENV_ON()
31             #endif
32              
33             #ifdef sun
34             #define asctime_r(a, b) asctime_r(a, b, TIME_STRING_SIZE)
35             #endif
36              
37             #ifdef WIN32
38             #define setenv(name, value, flag) _putenv_s(name, value)
39             #define unsetenv(name) _putenv_s(name, "")
40             #define localtime_r(time, tm) localtime_s(tm, time)
41             #define asctime_r(tm, time_string) asctime_s(time_string, TIME_STRING_SIZE, tm)
42             #define gmtime_r(time, tm) gmtime_s(tm, time)
43             #endif
44              
45             #define BACKUP_TZ() \
46             SAFE_PUTENV_ON(); \
47             char* old_tz_p = getenv("TZ"); \
48             int envsize = old_tz_p == NULL ? 1 : strlen(old_tz_p)+1; \
49             char old_tz[envsize]; \
50             if (old_tz_p != NULL) \
51             memcpy(old_tz, old_tz_p, envsize); \
52              
53             #define RESTORE_TZ() \
54             if (old_tz_p == NULL) { \
55             unsetenv("TZ"); \
56             } else { \
57             setenv("TZ", old_tz, 1); \
58             } \
59              
60              
61             MODULE = Time::Local::TZ PACKAGE = Time::Local::TZ
62             PROTOTYPES: DISABLE
63              
64             void
65             tz_localtime(tz, time)
66             char* tz
67             time_t time
68             PREINIT:
69             char time_string[TIME_STRING_SIZE];
70             struct tm tm;
71             PPCODE:
72 32 100         BACKUP_TZ();
    100          
73 32           setenv("TZ", tz, 1);
74 32           tzset();
75 32           localtime_r(&time, &tm);
76 32 100         RESTORE_TZ();
77              
78 32 50         if (GIMME_V == G_ARRAY) {
    100          
79 16 50         EXTEND(SP, 9);
80 16           ST(0) = sv_2mortal(newSViv(tm.tm_sec));
81 16           ST(1) = sv_2mortal(newSViv(tm.tm_min));
82 16           ST(2) = sv_2mortal(newSViv(tm.tm_hour));
83 16           ST(3) = sv_2mortal(newSViv(tm.tm_mday));
84 16           ST(4) = sv_2mortal(newSViv(tm.tm_mon));
85 16           ST(5) = sv_2mortal(newSViv(tm.tm_year));
86 16           ST(6) = sv_2mortal(newSViv(tm.tm_wday));
87 16           ST(7) = sv_2mortal(newSViv(tm.tm_yday));
88 16           ST(8) = sv_2mortal(newSViv(tm.tm_isdst));
89 16           XSRETURN(9);
90             } else {
91 16           asctime_r(&tm, time_string);
92 16           ST(0) = sv_2mortal(newSVpv(time_string, 24));
93 32           XSRETURN(1);
94             }
95              
96              
97             void
98             tz_timelocal(...)
99             PREINIT:
100             char* tz;
101             struct tm tm;
102             time_t time;
103             PPCODE:
104 24 100         if (items < 7 || items > 10)
    100          
105 8           croak("Usage: tz_timelocal(tz, sec, min, hour, mday, mon, year, [ wday, yday, is_dst ])");
106              
107 16 50         tz = SvPV_nolen(ST(0));
108 16 50         tm.tm_sec = SvIV(ST(1));
109 16 50         tm.tm_min = SvIV(ST(2));
110 16 50         tm.tm_hour = SvIV(ST(3));
111 16 50         tm.tm_mday = SvIV(ST(4));
112 16 50         tm.tm_mon = SvIV(ST(5));
113 16 50         tm.tm_year = SvIV(ST(6));
114 16           tm.tm_wday = -1;
115 16           tm.tm_yday = -1;
116 16           tm.tm_isdst = -1;
117              
118 16 100         BACKUP_TZ();
    100          
119 16           setenv("TZ", tz, 1);
120 16           tzset();
121 16           time = mktime(&tm);
122 16 100         RESTORE_TZ();
123              
124 16           ST(0) = sv_2mortal(newSViv((IV)time));
125 16           XSRETURN(1);
126              
127              
128             void
129             tz_truncate(tz, time, unit)
130             char* tz
131             time_t time
132             int unit
133             PREINIT:
134             struct tm tm;
135             PPCODE:
136 64 100         if (unit < 1 || unit > 5)
    100          
137 4           croak("Usage: tz_truncate(tz, time, unit), unit should be 1..5");
138              
139 60 100         BACKUP_TZ();
    100          
140 60           setenv("TZ", tz, 1);
141 60           tzset();
142 60           localtime_r(&time, &tm);
143 60 100         if (unit == 5) tm.tm_mon = 0;
144 60 100         if (unit >= 4) tm.tm_mday = 1;
145 60 100         if (unit >= 3) tm.tm_hour = 0;
146 60 100         if (unit >= 2) tm.tm_min = 0;
147 60 50         if (unit >= 1) tm.tm_sec = 0;
148 60           time = mktime(&tm);
149 60 100         RESTORE_TZ();
150              
151 60           ST(0) = sv_2mortal(newSViv((IV)time));
152 60           XSRETURN(1);
153              
154              
155             void
156             tz_offset(tz, time)
157             char* tz
158             time_t time
159             PREINIT:
160             struct tm tm;
161             time_t time_utc;
162             PPCODE:
163 7 50         BACKUP_TZ()
    50          
164 7           setenv("TZ", tz, 1);
165 7           tzset();
166 7           gmtime_r(&time, &tm);
167 7           time_utc = mktime(&tm);
168 7 50         RESTORE_TZ();
169              
170 7           ST(0) = sv_2mortal(newSViv((int)(time-time_utc)));
171 7           XSRETURN(1);