Annotation of libelwix/src/time.c, revision 1.5

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     ! misho       6: * $Id: time.c,v 1.4.20.1 2015/06/25 00:36:48 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     ! misho      15: Copyright 2004 - 2015
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: 
                    290:        clock_gettime(CLOCK_UPTIME_PRECISE, &ts);
                    291:        return ((uint64_t) ts.tv_sec * 1000000000 + ts.tv_nsec);
                    292: #endif
                    293: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>