nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* nstime.c
2 * Routines for manipulating nstime_t structures
3 *
4 * Copyright (c) 2005 MX Telecom Ltd. <richardv@mxtelecom.com>
5 *
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 *
24 */
25  
26 #include <glib.h>
27 #include "nstime.h"
28  
29 /* this is #defined so that we can clearly see that we have the right number of
30 zeros, rather than as a guard against the number of nanoseconds in a second
31 changing ;) */
32 #define NS_PER_S 1000000000
33  
34 /* set the given nstime_t to zero */
35 void nstime_set_zero(nstime_t *nstime)
36 {
37 nstime->secs = 0;
38 nstime->nsecs = 0;
39 }
40  
41 /* is the given nstime_t currently zero? */
42 gboolean nstime_is_zero(nstime_t *nstime)
43 {
44 if(nstime->secs == 0 && nstime->nsecs == 0) {
45 return TRUE;
46 } else {
47 return FALSE;
48 }
49 }
50  
51 /* set the given nstime_t to (0,maxint) to mark it as "unset"
52 * That way we can find the first frame even when a timestamp
53 * is zero (fix for bug 1056)
54 */
55 void nstime_set_unset(nstime_t *nstime)
56 {
57 nstime->secs = 0;
58 nstime->nsecs = G_MAXINT;
59 }
60  
61 /* is the given nstime_t currently (0,maxint)? */
62 gboolean nstime_is_unset(const nstime_t *nstime)
63 {
64 if(nstime->secs == 0 && nstime->nsecs == G_MAXINT) {
65 return TRUE;
66 } else {
67 return FALSE;
68 }
69 }
70  
71  
72 /** funcion: nstime_copy
73 *
74 * a = b
75 */
76 void nstime_copy(nstime_t *a, const nstime_t *b)
77 {
78 a->secs = b->secs;
79 a->nsecs = b->nsecs;
80 }
81  
82 /*
83 * function: nstime_delta
84 * delta = b - a
85 */
86  
87 void nstime_delta(nstime_t *delta, const nstime_t *b, const nstime_t *a )
88 {
89 if (b->secs == a->secs) {
90 /* The seconds part of b is the same as the seconds part of a, so if
91 the nanoseconds part of the first time is less than the nanoseconds
92 part of a, b is before a. The nanoseconds part of the delta should
93 just be the difference between the nanoseconds part of b and the
94 nanoseconds part of a; don't adjust the seconds part of the delta,
95 as it's OK if the nanoseconds part is negative, and an overflow
96 can never result. */
97 delta->secs = 0;
98 delta->nsecs = b->nsecs - a->nsecs;
99 } else if (b->secs < a->secs) {
100 /* The seconds part of b is less than the seconds part of a, so b is
101 before a.
102  
103 Both the "seconds" and "nanoseconds" value of the delta
104 should have the same sign, so if the difference between the
105 nanoseconds values would be *positive*, subtract 1,000,000,000
106 from it, and add one to the seconds value. */
107 delta->secs = b->secs - a->secs;
108 delta->nsecs = b->nsecs - a->nsecs;
109 if(delta->nsecs > 0) {
110 delta->nsecs -= NS_PER_S;
111 delta->secs ++;
112 }
113 } else {
114 delta->secs = b->secs - a->secs;
115 delta->nsecs = b->nsecs - a->nsecs;
116 if(delta->nsecs < 0) {
117 delta->nsecs += NS_PER_S;
118 delta->secs --;
119 }
120 }
121 }
122  
123 /*
124 * function: nstime_sum
125 * sum = a + b
126 */
127  
128 void nstime_sum(nstime_t *sum, const nstime_t *a, const nstime_t *b)
129 {
130 sum->secs = a->secs + b->secs;
131 sum->nsecs = a->nsecs + b->nsecs;
132 if(sum->nsecs>=NS_PER_S || (sum->nsecs>0 && sum->secs<0)){
133 sum->nsecs-=NS_PER_S;
134 sum->secs++;
135 } else if(sum->nsecs<=-NS_PER_S || (sum->nsecs<0 && sum->secs>0)) {
136 sum->nsecs+=NS_PER_S;
137 sum->secs--;
138 }
139 }
140  
141 /*
142 * function: nstime_cmp
143 *
144 * a > b : > 0
145 * a = b : 0
146 * a < b : < 0
147 */
148  
149 int nstime_cmp (const nstime_t *a, const nstime_t *b )
150 {
151 if (G_UNLIKELY(nstime_is_unset(a))) {
152 if (G_UNLIKELY(nstime_is_unset(b))) {
153 return 0; /* "no time stamp" is "equal" to "no time stamp" */
154 } else {
155 return -1; /* and is less than all time stamps */
156 }
157 } else {
158 if (G_UNLIKELY(nstime_is_unset(b))) {
159 return 1;
160 }
161 }
162 if (a->secs == b->secs) {
163 return a->nsecs - b->nsecs;
164 } else {
165 return (int) (a->secs - b->secs);
166 }
167 }
168  
169 /*
170 * function: nstime_to_msec
171 * converts nstime to double, time base is milli seconds
172 */
173  
174 double nstime_to_msec(const nstime_t *nstime)
175 {
176 return ((double)nstime->secs*1000 + (double)nstime->nsecs/1000000);
177 }
178  
179 /*
180 * function: nstime_to_sec
181 * converts nstime to double, time base is seconds
182 */
183  
184 double nstime_to_sec(const nstime_t *nstime)
185 {
186 return ((double)nstime->secs + (double)nstime->nsecs/NS_PER_S);
187 }
188  
189 /*
190 * This code is based on the Samba code:
191 *
192 * Unix SMB/Netbios implementation.
193 * Version 1.9.
194 * time handling functions
195 * Copyright (C) Andrew Tridgell 1992-1998
196 */
197  
198 /*
199 * Number of seconds between the UN*X epoch (January 1, 1970, 00:00:00 GMT)
200 * and the Windows NT epoch (January 1, 1601 in the proleptic Gregorian
201 * calendar, 00:00:00 "GMT")
202 *
203 * This is
204 *
205 * 369*365.25*24*60*60-(3*24*60*60+6*60*60)
206 *
207 * 1970-1601 is 369; 365.25 is the average length of a year in days,
208 * including leap years.
209 *
210 * 3 days are subtracted because 1700, 1800, and 1900 were not leap
211 * years, as, while they're all evenly divisible by 4, they're also
212 * evently divisible by 100, but not evently divisible by 400, so
213 * we need to compensate for using the average length of a year in
214 * days, which assumes a leap year every 4 years, *including* every
215 * 100 years.
216 *
217 * I'm not sure what the extra 6 hours are that are being subtracted.
218 */
219 #define TIME_FIXUP_CONSTANT G_GUINT64_CONSTANT(11644473600)
220  
221 #ifndef TIME_T_MIN
222 #define TIME_T_MIN ((time_t) ((time_t)0 < (time_t) -1 ? (time_t) 0 \
223 : (time_t) (~0ULL << (sizeof (time_t) * CHAR_BIT - 1))))
224 #endif
225 #ifndef TIME_T_MAX
226 #define TIME_T_MAX ((time_t) (~ (time_t) 0 - TIME_T_MIN))
227 #endif
228  
229 static gboolean
230 common_filetime_to_nstime(nstime_t *nstime, guint64 ftsecs, int nsecs)
231 {
232 gint64 secs;
233  
234 /*
235 * Shift the seconds from the Windows epoch to the UN*X epoch.
236 * ftsecs's value should fit in a 64-bit signed variable, as
237 * ftsecs is derived from a 64-bit fractions-of-a-second value,
238 * and is far from the maximum 64-bit signed value, and
239 * TIME_FIXUP_CONSTANT is also far from the maximum 64-bit
240 * signed value, so the difference between them should also
241 * fit in a 64-bit signed value.
242 */
243 secs = (gint64)ftsecs - TIME_FIXUP_CONSTANT;
244  
245 if (!(TIME_T_MIN <= secs && secs <= TIME_T_MAX)) {
246 /* The result won't fit in a time_t */
247 return FALSE;
248 }
249  
250 /*
251 * Get the time as seconds and nanoseconds.
252 */
253 nstime->secs = (time_t) secs;
254 nstime->nsecs = nsecs;
255 return TRUE;
256 }
257  
258 /*
259 * function: filetime_to_nstime
260 * converts a Windows FILETIME value to an nstime_t
261 * returns TRUE if the conversion succeeds, FALSE if it doesn't
262 * (for example, with a 32-bit time_t, the time overflows or
263 * underflows time_t)
264 */
265 gboolean
266 filetime_to_nstime(nstime_t *nstime, guint64 filetime)
267 {
268 guint64 ftsecs;
269 int nsecs;
270  
271 /*
272 * Split into seconds and tenths of microseconds, and
273 * then convert tenths of microseconds to nanoseconds.
274 */
275 ftsecs = filetime / 10000000;
276 nsecs = (int)((filetime % 10000000)*100);
277  
278 return common_filetime_to_nstime(nstime, ftsecs, nsecs);
279 }
280  
281 /*
282 * function: nsfiletime_to_nstime
283 * converts a Windows FILETIME-like value, but given in nanoseconds
284 * rather than 10ths of microseconds, to an nstime_t
285 * returns TRUE if the conversion succeeds, FALSE if it doesn't
286 * (for example, with a 32-bit time_t, the time overflows or
287 * underflows time_t)
288 */
289 gboolean
290 nsfiletime_to_nstime(nstime_t *nstime, guint64 nsfiletime)
291 {
292 guint64 ftsecs;
293 int nsecs;
294  
295 /* Split into seconds and nanoseconds. */
296 ftsecs = nsfiletime / NS_PER_S;
297 nsecs = (int)(nsfiletime % NS_PER_S);
298  
299 return common_filetime_to_nstime(nstime, ftsecs, nsecs);
300 }
301  
302 /*
303 * Editor modelines
304 *
305 * Local Variables:
306 * c-basic-offset: 4
307 * tab-width: 8
308 * indent-tabs-mode: nil
309 * End:
310 *
311 * ex: set shiftwidth=4 tabstop=8 expandtab:
312 * :indentSize=4:tabSize=8:noTabs=true:
313 */