File:  [ELWIX - Embedded LightWeight unIX -] / libelwix / src / time.c
Revision 1.4: download - view: text, annotated - select for diffs - revision graph
Wed Jan 29 14:16:54 2014 UTC (10 years, 3 months ago) by misho
Branches: MAIN
CVS tags: elwix3_7, elwix3_6, elwix3_5, elwix3_4, elwix3_3, elwix3_2, elwix3_1, elwix3_0, elwix2_9, elwix2_8, HEAD, ELWIX3_6, ELWIX3_5, ELWIX3_4, ELWIX3_3, ELWIX3_2, ELWIX3_1, ELWIX3_0, ELWIX2_9, ELWIX2_8, ELWIX2_7
version 2.7

    1: /*************************************************************************
    2: * (C) 2013 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
    3: *  by Michael Pounov <misho@elwix.org>
    4: *
    5: * $Author: misho $
    6: * $Id: time.c,v 1.4 2014/01/29 14:16:54 misho Exp $
    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: 
   15: Copyright 2004 - 2014
   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: }
  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;
  286: #else
  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>