nexmon – Blame information for rev 1
?pathlinks?
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 | */ |