Annotation of libelwix/src/time.c, revision 1.5.72.2
1.2 misho 1: /*************************************************************************
2: * (C) 2013 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
3: * by Michael Pounov <misho@elwix.org>
4: *
5: * $Author: misho $
1.5.72.2! misho 6: * $Id: time.c,v 1.5.72.1 2022/12/01 19:50:46 misho Exp $
1.2 misho 7: *
8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
1.5.72.1 misho 15: Copyright 2004 - 2022
1.2 misho 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
46: #include "global.h"
47:
48:
49: struct stridx {
50: char *str;
51: int id;
52: };
53:
54: static struct stridx months[] = {
55: { "jan", 0 }, { "january", 0 },
56: { "feb", 1 }, { "february", 1 },
57: { "mar", 2 }, { "march", 2 },
58: { "apr", 3 }, { "april", 3 },
59: { "may", 4 },
60: { "jun", 5 }, { "june", 5 },
61: { "jul", 6 }, { "july", 6 },
62: { "aug", 7 }, { "august", 7 },
63: { "sep", 8 }, { "september", 8 },
64: { "oct", 9 }, { "october", 9 },
65: { "nov", 10 }, { "november", 10 },
66: { "dec", 11 }, { "december", 11 },
67: };
68:
69: static struct stridx wdays[] = {
70: { "sun", 0 }, { "sunday", 0 },
71: { "mon", 1 }, { "monday", 1 },
72: { "tue", 2 }, { "tuesday", 2 },
73: { "wed", 3 }, { "wednesday", 3 },
74: { "thu", 4 }, { "thursday", 4 },
75: { "fri", 5 }, { "friday", 5 },
76: { "sat", 6 }, { "saturday", 6 },
77: };
78:
79: static int
80: stridx_compare(struct stridx * __restrict a, struct stridx * __restrict b)
81: {
82: return strcmp(a->str, b->str);
83: }
84:
85: static int
86: search4month(char * psMonth, int * __restrict id)
87: {
88: static int sorted = 0;
89: struct stridx *el, item = { psMonth, 0 };
90:
91: if (!psMonth)
92: return -1;
93:
94: if (!sorted) {
95: qsort(months, sizeof(months) / sizeof(struct stridx), sizeof(struct stridx),
96: (int (*)(const void*, const void*)) stridx_compare);
97: sorted++;
98: }
99:
100: str_Lower(psMonth);
101: el = bsearch(&item, months, sizeof(months) / sizeof(struct stridx), sizeof(struct stridx),
102: (int (*)(const void*, const void*)) stridx_compare);
103: if (el && id)
104: *id = el->id;
105:
106: return !!el;
107: }
108:
109: static int
110: search4wday(char * __restrict psWDay, int * __restrict id)
111: {
112: static int sorted = 0;
113: struct stridx *el, item = { psWDay, 0 };
114:
115: if (!psWDay)
116: return -1;
117:
118: if (!sorted) {
119: qsort(wdays, sizeof(wdays) / sizeof(struct stridx), sizeof(struct stridx),
120: (int (*)(const void*, const void*)) stridx_compare);
121: sorted++;
122: }
123:
124: str_Lower(psWDay);
125: el = bsearch(&item, wdays, sizeof(wdays) / sizeof(struct stridx), sizeof(struct stridx),
126: (int (*)(const void*, const void*)) stridx_compare);
127: if (el && id)
128: *id = el->id;
129:
130: return !!el;
131: }
132:
133:
134: /*
135: * time_Parse() - Parse and make unix time from standart time strings ...
136: *
137: * @csTime = Time string
138: * return: =-1 error or !=-1 converted time
139: */
140: time_t
141: time_Parse(const char *csTime)
142: {
143: struct tm tm;
144: char *s;
145: int tm_sec, tm_min, tm_hour, tm_mday, tm_year, tm_mon, tm_wday;
146: char str_mon[512], str_wday[512];
147: time_t tim;
148:
149: memset(&tm, 0, sizeof tm);
150: memset(&str_mon, 0, sizeof str_mon);
151: memset(&str_wday, 0, sizeof str_wday);
152:
153: for (s = (char*) csTime; isspace(*s); s++);
154:
155: /*
156: * And do the sscanfs. WARNING: you can add more formats here,
157: * but be careful! You can easily screw up the parsing of existing
158: * formats when you add new ones. The order is important.
159: */
160:
161: /* DD-mth-YY HH:MM:SS GMT */
162: if (sscanf(s, "%d-%400[a-zA-Z]-%d %d:%d:%d GMT",
163: &tm_mday, str_mon, &tm_year,
164: &tm_hour, &tm_min, &tm_sec) == 6 &&
165: search4month(str_mon, &tm_mon)) {
166: tm.tm_mday = tm_mday;
167: tm.tm_mon = tm_mon;
168: tm.tm_year = tm_year;
169: tm.tm_hour = tm_hour;
170: tm.tm_min = tm_min;
171: tm.tm_sec = tm_sec;
172: }
173: /* DD mth YY HH:MM:SS GMT */
174: else if (sscanf(s, "%d %400[a-zA-Z] %d %d:%d:%d GMT",
175: &tm_mday, str_mon, &tm_year,
176: &tm_hour, &tm_min, &tm_sec) == 6 &&
177: search4month(str_mon, &tm_mon)) {
178: tm.tm_mday = tm_mday;
179: tm.tm_mon = tm_mon;
180: tm.tm_year = tm_year;
181: tm.tm_hour = tm_hour;
182: tm.tm_min = tm_min;
183: tm.tm_sec = tm_sec;
184: }
185: /* HH:MM:SS GMT DD-mth-YY */
186: else if (sscanf(s, "%d:%d:%d GMT %d-%400[a-zA-Z]-%d",
187: &tm_hour, &tm_min, &tm_sec,
188: &tm_mday, str_mon, &tm_year) == 6 &&
189: search4month(str_mon, &tm_mon)) {
190: tm.tm_hour = tm_hour;
191: tm.tm_min = tm_min;
192: tm.tm_sec = tm_sec;
193: tm.tm_mday = tm_mday;
194: tm.tm_mon = tm_mon;
195: tm.tm_year = tm_year;
196: }
197: /* HH:MM:SS GMT DD mth YY */
198: else if (sscanf(s, "%d:%d:%d GMT %d %400[a-zA-Z] %d",
199: &tm_hour, &tm_min, &tm_sec,
200: &tm_mday, str_mon, &tm_year) == 6 &&
201: search4month(str_mon, &tm_mon)) {
202: tm.tm_hour = tm_hour;
203: tm.tm_min = tm_min;
204: tm.tm_sec = tm_sec;
205: tm.tm_mday = tm_mday;
206: tm.tm_mon = tm_mon;
207: tm.tm_year = tm_year;
208: }
209: /* wdy, DD-mth-YY HH:MM:SS GMT */
210: else if (sscanf(s, "%400[a-zA-Z], %d-%400[a-zA-Z]-%d %d:%d:%d GMT",
211: str_wday, &tm_mday, str_mon,
212: &tm_year, &tm_hour, &tm_min, &tm_sec) == 7 &&
213: search4wday(str_wday, &tm_wday) &&
214: search4month(str_mon, &tm_mon)) {
215: tm.tm_wday = tm_wday;
216: tm.tm_mday = tm_mday;
217: tm.tm_mon = tm_mon;
218: tm.tm_year = tm_year;
219: tm.tm_hour = tm_hour;
220: tm.tm_min = tm_min;
221: tm.tm_sec = tm_sec;
222: }
223: /* wdy, DD mth YY HH:MM:SS GMT */
224: else if (sscanf(s, "%400[a-zA-Z], %d %400[a-zA-Z] %d %d:%d:%d GMT",
225: str_wday, &tm_mday, str_mon,
226: &tm_year, &tm_hour, &tm_min, &tm_sec) == 7 &&
227: search4wday(str_wday, &tm_wday) &&
228: search4month(str_mon, &tm_mon)) {
229: tm.tm_wday = tm_wday;
230: tm.tm_mday = tm_mday;
231: tm.tm_mon = tm_mon;
232: tm.tm_year = tm_year;
233: tm.tm_hour = tm_hour;
234: tm.tm_min = tm_min;
235: tm.tm_sec = tm_sec;
236: }
237: /* wdy mth DD HH:MM:SS GMT YY */
238: else if (sscanf(s, "%400[a-zA-Z] %400[a-zA-Z] %d %d:%d:%d GMT %d",
239: str_wday, str_mon, &tm_mday,
240: &tm_hour, &tm_min, &tm_sec, &tm_year) == 7 &&
241: search4wday(str_wday, &tm_wday) &&
242: search4month(str_mon, &tm_mon)) {
243: tm.tm_wday = tm_wday;
244: tm.tm_mon = tm_mon;
245: tm.tm_mday = tm_mday;
246: tm.tm_hour = tm_hour;
247: tm.tm_min = tm_min;
248: tm.tm_sec = tm_sec;
249: tm.tm_year = tm_year;
250: } else {
251: elwix_SetErr(EINVAL, "Invalid date/time format");
252: return (time_t) -1;
253: }
254:
255: if (tm.tm_year > 1900)
256: tm.tm_year -= 1900;
257: else if (tm.tm_year < 70)
258: tm.tm_year += 100;
259:
260: if ((tim = timegm(&tm)) == (time_t) -1)
261: elwix_SetErr(EINVAL, "Invalid date/time format");
262: return tim;
263: }
1.3 misho 264:
265: /*
266: * time_rdtsc() - Get TSC timer value from CPU
267: *
268: * return: TSC in nanoseconds
269: */
270: uint64_t
271: time_rdtsc(void)
272: {
273: #if defined(i386) || defined(__i386__)
274: /* i386 */
275: uint32_t hi, lo;
276:
277: asm volatile("rdtsc" : "=d" (hi), "=a" (lo));
278: return (((uint64_t) hi << 32) | (uint64_t) lo);
279: #elif defined(amd64) || defined(__amd64__) || \
280: defined(x86_64) || defined(__x86_64__)
281: /* amd64 */
282: uint64_t res;
283:
284: asm volatile("rdtsc" : "=a" (res));
285: return res;
1.4 misho 286: #else
1.3 misho 287: /* unsupported for this architecture, get time by ordinary way */
288: struct timespec ts = { 0, 0LL };
289:
1.5.72.1 misho 290: #ifndef CLOCK_UPTIME_PRECISE
1.5.72.2! misho 291: #define CLOCK_UPTIME_PRECISE CLOCK_MONOTONIC
1.5.72.1 misho 292: #endif
1.5.72.2! misho 293: clock_gettime(CLOCK_UPTIME_PRECISE, &ts);
! 294:
1.3 misho 295: return ((uint64_t) ts.tv_sec * 1000000000 + ts.tv_nsec);
296: #endif
297: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>