| version 1.1.2.1, 2013/03/05 13:09:51 | version 1.5, 2015/06/25 17:53:50 | 
| Line 1 | Line 1 | 
 |  | /************************************************************************* | 
 |  | * (C) 2013 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org> | 
 |  | *  by Michael Pounov <misho@elwix.org> | 
 |  | * | 
 |  | * $Author$ | 
 |  | * $Id$ | 
 |  | * | 
 |  | ************************************************************************** | 
 |  | The ELWIX and AITNET software is distributed under the following | 
 |  | terms: | 
 |  |  | 
 |  | All of the documentation and software included in the ELWIX and AITNET | 
 |  | Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org> | 
 |  |  | 
 |  | Copyright 2004 - 2015 | 
 |  | by Michael Pounov <misho@elwix.org>.  All rights reserved. | 
 |  |  | 
 |  | Redistribution and use in source and binary forms, with or without | 
 |  | modification, are permitted provided that the following conditions | 
 |  | are met: | 
 |  | 1. Redistributions of source code must retain the above copyright | 
 |  | notice, this list of conditions and the following disclaimer. | 
 |  | 2. Redistributions in binary form must reproduce the above copyright | 
 |  | notice, this list of conditions and the following disclaimer in the | 
 |  | documentation and/or other materials provided with the distribution. | 
 |  | 3. All advertising materials mentioning features or use of this software | 
 |  | must display the following acknowledgement: | 
 |  | This product includes software developed by Michael Pounov <misho@elwix.org> | 
 |  | ELWIX - Embedded LightWeight unIX and its contributors. | 
 |  | 4. Neither the name of AITNET nor the names of its contributors | 
 |  | may be used to endorse or promote products derived from this software | 
 |  | without specific prior written permission. | 
 |  |  | 
 |  | THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND | 
 |  | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
 |  | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
 |  | ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 
 |  | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
 |  | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
 |  | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
 |  | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
 |  | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 
 |  | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
 |  | SUCH DAMAGE. | 
 |  | */ | 
 | #include "global.h" | #include "global.h" | 
 |  |  | 
 |  |  | 
 |  | struct stridx { | 
 |  | char    *str; | 
 |  | int     id; | 
 |  | }; | 
 |  |  | 
 |  | static struct stridx months[] = { | 
 |  | { "jan", 0 }, { "january", 0 }, | 
 |  | { "feb", 1 }, { "february", 1 }, | 
 |  | { "mar", 2 }, { "march", 2 }, | 
 |  | { "apr", 3 }, { "april", 3 }, | 
 |  | { "may", 4 }, | 
 |  | { "jun", 5 }, { "june", 5 }, | 
 |  | { "jul", 6 }, { "july", 6 }, | 
 |  | { "aug", 7 }, { "august", 7 }, | 
 |  | { "sep", 8 }, { "september", 8 }, | 
 |  | { "oct", 9 }, { "october", 9 }, | 
 |  | { "nov", 10 }, { "november", 10 }, | 
 |  | { "dec", 11 }, { "december", 11 }, | 
 |  | }; | 
 |  |  | 
 |  | static struct stridx wdays[] = { | 
 |  | { "sun", 0 }, { "sunday", 0 }, | 
 |  | { "mon", 1 }, { "monday", 1 }, | 
 |  | { "tue", 2 }, { "tuesday", 2 }, | 
 |  | { "wed", 3 }, { "wednesday", 3 }, | 
 |  | { "thu", 4 }, { "thursday", 4 }, | 
 |  | { "fri", 5 }, { "friday", 5 }, | 
 |  | { "sat", 6 }, { "saturday", 6 }, | 
 |  | }; | 
 |  |  | 
 |  | static int | 
 |  | stridx_compare(struct stridx * __restrict a, struct stridx * __restrict b) | 
 |  | { | 
 |  | return strcmp(a->str, b->str); | 
 |  | } | 
 |  |  | 
 |  | static int | 
 |  | search4month(char * psMonth, int * __restrict id) | 
 |  | { | 
 |  | static int sorted = 0; | 
 |  | struct stridx *el, item = { psMonth, 0 }; | 
 |  |  | 
 |  | if (!psMonth) | 
 |  | return -1; | 
 |  |  | 
 |  | if (!sorted) { | 
 |  | qsort(months, sizeof(months) / sizeof(struct stridx), sizeof(struct stridx), | 
 |  | (int (*)(const void*, const void*)) stridx_compare); | 
 |  | sorted++; | 
 |  | } | 
 |  |  | 
 |  | str_Lower(psMonth); | 
 |  | el = bsearch(&item, months, sizeof(months) / sizeof(struct stridx), sizeof(struct stridx), | 
 |  | (int (*)(const void*, const void*)) stridx_compare); | 
 |  | if (el && id) | 
 |  | *id = el->id; | 
 |  |  | 
 |  | return !!el; | 
 |  | } | 
 |  |  | 
 |  | static int | 
 |  | search4wday(char * __restrict psWDay, int * __restrict id) | 
 |  | { | 
 |  | static int sorted = 0; | 
 |  | struct stridx *el, item = { psWDay, 0 }; | 
 |  |  | 
 |  | if (!psWDay) | 
 |  | return -1; | 
 |  |  | 
 |  | if (!sorted) { | 
 |  | qsort(wdays, sizeof(wdays) / sizeof(struct stridx), sizeof(struct stridx), | 
 |  | (int (*)(const void*, const void*)) stridx_compare); | 
 |  | sorted++; | 
 |  | } | 
 |  |  | 
 |  | str_Lower(psWDay); | 
 |  | el = bsearch(&item, wdays, sizeof(wdays) / sizeof(struct stridx), sizeof(struct stridx), | 
 |  | (int (*)(const void*, const void*)) stridx_compare); | 
 |  | if (el && id) | 
 |  | *id = el->id; | 
 |  |  | 
 |  | return !!el; | 
 |  | } | 
 |  |  | 
 |  |  | 
 |  | /* | 
 |  | * time_Parse() - Parse and make unix time from standart time strings ... | 
 |  | * | 
 |  | * @csTime = Time string | 
 |  | * return: =-1 error or !=-1 converted time | 
 |  | */ | 
 |  | time_t | 
 |  | time_Parse(const char *csTime) | 
 |  | { | 
 |  | struct tm tm; | 
 |  | char *s; | 
 |  | int tm_sec, tm_min, tm_hour, tm_mday, tm_year, tm_mon, tm_wday; | 
 |  | char str_mon[512], str_wday[512]; | 
 |  | time_t tim; | 
 |  |  | 
 |  | memset(&tm, 0, sizeof tm); | 
 |  | memset(&str_mon, 0, sizeof str_mon); | 
 |  | memset(&str_wday, 0, sizeof str_wday); | 
 |  |  | 
 |  | for (s = (char*) csTime; isspace(*s); s++); | 
 |  |  | 
 |  | /* | 
 |  | * And do the sscanfs.  WARNING: you can add more formats here, | 
 |  | * but be careful!  You can easily screw up the parsing of existing | 
 |  | * formats when you add new ones.  The order is important. | 
 |  | */ | 
 |  |  | 
 |  | /* DD-mth-YY HH:MM:SS GMT */ | 
 |  | if (sscanf(s, "%d-%400[a-zA-Z]-%d %d:%d:%d GMT", | 
 |  | &tm_mday, str_mon, &tm_year, | 
 |  | &tm_hour, &tm_min, &tm_sec) == 6 && | 
 |  | search4month(str_mon, &tm_mon)) { | 
 |  | tm.tm_mday = tm_mday; | 
 |  | tm.tm_mon = tm_mon; | 
 |  | tm.tm_year = tm_year; | 
 |  | tm.tm_hour = tm_hour; | 
 |  | tm.tm_min = tm_min; | 
 |  | tm.tm_sec = tm_sec; | 
 |  | } | 
 |  | /* DD mth YY HH:MM:SS GMT */ | 
 |  | else if (sscanf(s, "%d %400[a-zA-Z] %d %d:%d:%d GMT", | 
 |  | &tm_mday, str_mon, &tm_year, | 
 |  | &tm_hour, &tm_min, &tm_sec) == 6 && | 
 |  | search4month(str_mon, &tm_mon)) { | 
 |  | tm.tm_mday = tm_mday; | 
 |  | tm.tm_mon = tm_mon; | 
 |  | tm.tm_year = tm_year; | 
 |  | tm.tm_hour = tm_hour; | 
 |  | tm.tm_min = tm_min; | 
 |  | tm.tm_sec = tm_sec; | 
 |  | } | 
 |  | /* HH:MM:SS GMT DD-mth-YY */ | 
 |  | else if (sscanf(s, "%d:%d:%d GMT %d-%400[a-zA-Z]-%d", | 
 |  | &tm_hour, &tm_min, &tm_sec, | 
 |  | &tm_mday, str_mon, &tm_year) == 6 && | 
 |  | search4month(str_mon, &tm_mon)) { | 
 |  | tm.tm_hour = tm_hour; | 
 |  | tm.tm_min = tm_min; | 
 |  | tm.tm_sec = tm_sec; | 
 |  | tm.tm_mday = tm_mday; | 
 |  | tm.tm_mon = tm_mon; | 
 |  | tm.tm_year = tm_year; | 
 |  | } | 
 |  | /* HH:MM:SS GMT DD mth YY */ | 
 |  | else if (sscanf(s, "%d:%d:%d GMT %d %400[a-zA-Z] %d", | 
 |  | &tm_hour, &tm_min, &tm_sec, | 
 |  | &tm_mday, str_mon, &tm_year) == 6 && | 
 |  | search4month(str_mon, &tm_mon)) { | 
 |  | tm.tm_hour = tm_hour; | 
 |  | tm.tm_min = tm_min; | 
 |  | tm.tm_sec = tm_sec; | 
 |  | tm.tm_mday = tm_mday; | 
 |  | tm.tm_mon = tm_mon; | 
 |  | tm.tm_year = tm_year; | 
 |  | } | 
 |  | /* wdy, DD-mth-YY HH:MM:SS GMT */ | 
 |  | else if (sscanf(s, "%400[a-zA-Z], %d-%400[a-zA-Z]-%d %d:%d:%d GMT", | 
 |  | str_wday, &tm_mday, str_mon, | 
 |  | &tm_year, &tm_hour, &tm_min, &tm_sec) == 7 && | 
 |  | search4wday(str_wday, &tm_wday) && | 
 |  | search4month(str_mon, &tm_mon)) { | 
 |  | tm.tm_wday = tm_wday; | 
 |  | tm.tm_mday = tm_mday; | 
 |  | tm.tm_mon = tm_mon; | 
 |  | tm.tm_year = tm_year; | 
 |  | tm.tm_hour = tm_hour; | 
 |  | tm.tm_min = tm_min; | 
 |  | tm.tm_sec = tm_sec; | 
 |  | } | 
 |  | /* wdy, DD mth YY HH:MM:SS GMT */ | 
 |  | else if (sscanf(s, "%400[a-zA-Z], %d %400[a-zA-Z] %d %d:%d:%d GMT", | 
 |  | str_wday, &tm_mday, str_mon, | 
 |  | &tm_year, &tm_hour, &tm_min, &tm_sec) == 7 && | 
 |  | search4wday(str_wday, &tm_wday) && | 
 |  | search4month(str_mon, &tm_mon)) { | 
 |  | tm.tm_wday = tm_wday; | 
 |  | tm.tm_mday = tm_mday; | 
 |  | tm.tm_mon = tm_mon; | 
 |  | tm.tm_year = tm_year; | 
 |  | tm.tm_hour = tm_hour; | 
 |  | tm.tm_min = tm_min; | 
 |  | tm.tm_sec = tm_sec; | 
 |  | } | 
 |  | /* wdy mth DD HH:MM:SS GMT YY */ | 
 |  | else if (sscanf(s, "%400[a-zA-Z] %400[a-zA-Z] %d %d:%d:%d GMT %d", | 
 |  | str_wday, str_mon, &tm_mday, | 
 |  | &tm_hour, &tm_min, &tm_sec, &tm_year) == 7 && | 
 |  | search4wday(str_wday, &tm_wday) && | 
 |  | search4month(str_mon, &tm_mon)) { | 
 |  | tm.tm_wday = tm_wday; | 
 |  | tm.tm_mon = tm_mon; | 
 |  | tm.tm_mday = tm_mday; | 
 |  | tm.tm_hour = tm_hour; | 
 |  | tm.tm_min = tm_min; | 
 |  | tm.tm_sec = tm_sec; | 
 |  | tm.tm_year = tm_year; | 
 |  | } else { | 
 |  | elwix_SetErr(EINVAL, "Invalid date/time format"); | 
 |  | return (time_t) -1; | 
 |  | } | 
 |  |  | 
 |  | if (tm.tm_year > 1900) | 
 |  | tm.tm_year -= 1900; | 
 |  | else if (tm.tm_year < 70) | 
 |  | tm.tm_year += 100; | 
 |  |  | 
 |  | if ((tim = timegm(&tm)) == (time_t) -1) | 
 |  | elwix_SetErr(EINVAL, "Invalid date/time format"); | 
 |  | return tim; | 
 |  | } | 
 |  |  | 
 |  | /* | 
 |  | * time_rdtsc() - Get TSC timer value from CPU | 
 |  | * | 
 |  | * return: TSC in nanoseconds | 
 |  | */ | 
 |  | uint64_t | 
 |  | time_rdtsc(void) | 
 |  | { | 
 |  | #if defined(i386) || defined(__i386__) | 
 |  | /* i386 */ | 
 |  | uint32_t hi, lo; | 
 |  |  | 
 |  | asm volatile("rdtsc" : "=d" (hi), "=a" (lo)); | 
 |  | return (((uint64_t) hi << 32) | (uint64_t) lo); | 
 |  | #elif defined(amd64) || defined(__amd64__) || \ | 
 |  | defined(x86_64) || defined(__x86_64__) | 
 |  | /* amd64 */ | 
 |  | uint64_t res; | 
 |  |  | 
 |  | asm volatile("rdtsc" : "=a" (res)); | 
 |  | return res; | 
 |  | #else | 
 |  | /* unsupported for this architecture, get time by ordinary way */ | 
 |  | struct timespec ts = { 0, 0LL }; | 
 |  |  | 
 |  | clock_gettime(CLOCK_UPTIME_PRECISE, &ts); | 
 |  | return ((uint64_t) ts.tv_sec * 1000000000 + ts.tv_nsec); | 
 |  | #endif | 
 |  | } |