⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 localtime.c

📁 asterisk 是一个很有知名度开源软件
💻 C
📖 第 1 页 / 共 4 页
字号:
		tdays -= leapdays;		y = newy;	}	seconds = tdays * SECSPERDAY + 0.5;	tdays = seconds / SECSPERDAY;	rem += seconds - tdays * SECSPERDAY;	/*	** Given the range, we can now fearlessly cast...	*/	idays = tdays;	rem += offset - corr;	while (rem < 0) {		rem += SECSPERDAY;		--idays;	}	while (rem >= SECSPERDAY) {		rem -= SECSPERDAY;		++idays;	}	while (idays < 0) {		if (increment_overflow(&y, -1))			return NULL;		idays += year_lengths[isleap(y)];	}	while (idays >= year_lengths[isleap(y)]) {		idays -= year_lengths[isleap(y)];		if (increment_overflow(&y, 1))			return NULL;	}	tmp->tm_year = y;	if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))		return NULL;	tmp->tm_yday = idays;	/*	** The "extra" mods below avoid overflow problems.	*/	tmp->tm_wday = EPOCH_WDAY +		((y - EPOCH_YEAR) % DAYSPERWEEK) *		(DAYSPERNYEAR % DAYSPERWEEK) +		leaps_thru_end_of(y - 1) -		leaps_thru_end_of(EPOCH_YEAR - 1) +		idays;	tmp->tm_wday %= DAYSPERWEEK;	if (tmp->tm_wday < 0)		tmp->tm_wday += DAYSPERWEEK;	tmp->tm_hour = (int) (rem / SECSPERHOUR);	rem %= SECSPERHOUR;	tmp->tm_min = (int) (rem / SECSPERMIN);	/*	** A positive leap second requires a special	** representation. This uses "... ??:59:60" et seq.	*/	tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;	ip = mon_lengths[isleap(y)];	for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))		idays -= ip[tmp->tm_mon];	tmp->tm_mday = (int) (idays + 1);	tmp->tm_isdst = 0;#ifdef TM_GMTOFF	tmp->TM_GMTOFF = offset;#endif /* defined TM_GMTOFF */	tmp->tm_usec = timep->tv_usec;	return tmp;}/*! \note** Adapted from code provided by Robert Elz, who writes:**	The "best" way to do mktime I think is based on an idea of Bob**	Kridle's (so its said...) from a long time ago.**	It does a binary search of the time_t space. Since time_t's are**	just 32 bits, its a max of 32 iterations (even at 64 bits it**	would still be very reasonable).*//*! \brief** Simplified normalize logic courtesy Paul Eggert.*/static int increment_overflow(int *number, int delta){	int	number0;	number0 = *number;	*number += delta;	return (*number < number0) != (delta < 0);}static int long_increment_overflow(long *number, int delta){	long	number0;	number0 = *number;	*number += delta;	return (*number < number0) != (delta < 0);}static int normalize_overflow(int *tensptr, int *unitsptr, const int base){	int	tensdelta;	tensdelta = (*unitsptr >= 0) ?		(*unitsptr / base) :		(-1 - (-1 - *unitsptr) / base);	*unitsptr -= tensdelta * base;	return increment_overflow(tensptr, tensdelta);}static int long_normalize_overflow(long *tensptr, int *unitsptr, const int base){	int	tensdelta;	tensdelta = (*unitsptr >= 0) ?		(*unitsptr / base) :		(-1 - (-1 - *unitsptr) / base);	*unitsptr -= tensdelta * base;	return long_increment_overflow(tensptr, tensdelta);}static int tmcomp(const struct ast_tm *atmp, const struct ast_tm *btmp){	int	result;	if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&		(result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&		(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&		(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&		(result = (atmp->tm_min - btmp->tm_min)) == 0 &&		(result = (atmp->tm_sec - btmp->tm_sec)) == 0)			result = atmp->tm_usec - btmp->tm_usec;	return result;}static struct timeval time2sub(struct ast_tm *tmp, struct ast_tm * (* const funcp) (const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, int *okayp, const int do_norm_secs, const struct state *sp){	int			dir;	int			i, j;	int			saved_seconds;	long			li;	time_t			lo;	time_t			hi;	long				y;	struct timeval			newt = { 0, 0 };	struct timeval			t = { 0, 0 };	struct ast_tm			yourtm, mytm;	*okayp = FALSE;	yourtm = *tmp;	if (do_norm_secs) {		if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,			SECSPERMIN))				return WRONG;	}	if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))		return WRONG;	if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))		return WRONG;	y = yourtm.tm_year;	if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))		return WRONG;	/*	** Turn y into an actual year number for now.	** It is converted back to an offset from TM_YEAR_BASE later.	*/	if (long_increment_overflow(&y, TM_YEAR_BASE))		return WRONG;	while (yourtm.tm_mday <= 0) {		if (long_increment_overflow(&y, -1))			return WRONG;		li = y + (1 < yourtm.tm_mon);		yourtm.tm_mday += year_lengths[isleap(li)];	}	while (yourtm.tm_mday > DAYSPERLYEAR) {		li = y + (1 < yourtm.tm_mon);		yourtm.tm_mday -= year_lengths[isleap(li)];		if (long_increment_overflow(&y, 1))			return WRONG;	}	for ( ; ; ) {		i = mon_lengths[isleap(y)][yourtm.tm_mon];		if (yourtm.tm_mday <= i)			break;		yourtm.tm_mday -= i;		if (++yourtm.tm_mon >= MONSPERYEAR) {			yourtm.tm_mon = 0;			if (long_increment_overflow(&y, 1))				return WRONG;		}	}	if (long_increment_overflow(&y, -TM_YEAR_BASE))		return WRONG;	yourtm.tm_year = y;	if (yourtm.tm_year != y)		return WRONG;	if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)		saved_seconds = 0;	else if (y + TM_YEAR_BASE < EPOCH_YEAR) {		/*		** We can't set tm_sec to 0, because that might push the		** time below the minimum representable time.		** Set tm_sec to 59 instead.		** This assumes that the minimum representable time is		** not in the same minute that a leap second was deleted from,		** which is a safer assumption than using 58 would be.		*/		if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))			return WRONG;		saved_seconds = yourtm.tm_sec;		yourtm.tm_sec = SECSPERMIN - 1;	} else {		saved_seconds = yourtm.tm_sec;		yourtm.tm_sec = 0;	}	/*	** Do a binary search (this works whatever time_t's type is).	*/	if (!TYPE_SIGNED(time_t)) {		lo = 0;		hi = lo - 1;	} else if (!TYPE_INTEGRAL(time_t)) {		if (sizeof(time_t) > sizeof(float))			hi = (time_t) DBL_MAX;		else	hi = (time_t) FLT_MAX;		lo = -hi;	} else {		lo = 1;		for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)			lo *= 2;		hi = -(lo + 1);	}	for ( ; ; ) {		t.tv_sec = lo / 2 + hi / 2;		if (t.tv_sec < lo)			t.tv_sec = lo;		else if (t.tv_sec > hi)			t.tv_sec = hi;		if ((*funcp)(&t, offset, &mytm, sp) == NULL) {			/*			** Assume that t is too extreme to be represented in			** a struct ast_tm; arrange things so that it is less			** extreme on the next pass.			*/			dir = (t.tv_sec > 0) ? 1 : -1;		} else	dir = tmcomp(&mytm, &yourtm);		if (dir != 0) {			if (t.tv_sec == lo) {				++t.tv_sec;				if (t.tv_sec <= lo)					return WRONG;				++lo;			} else if (t.tv_sec == hi) {				--t.tv_sec;				if (t.tv_sec >= hi)					return WRONG;				--hi;			}			if (lo > hi)				return WRONG;			if (dir > 0)				hi = t.tv_sec;			else	lo = t.tv_sec;			continue;		}		if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)			break;		/*		** Right time, wrong type.		** Hunt for right time, right type.		** It's okay to guess wrong since the guess		** gets checked.		*/		/*		** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.		*/		for (i = sp->typecnt - 1; i >= 0; --i) {			if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)				continue;			for (j = sp->typecnt - 1; j >= 0; --j) {				if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)					continue;				newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff -					sp->ttis[i].tt_gmtoff;				if ((*funcp)(&newt, offset, &mytm, sp) == NULL)					continue;				if (tmcomp(&mytm, &yourtm) != 0)					continue;				if (mytm.tm_isdst != yourtm.tm_isdst)					continue;				/*				** We have a match.				*/				t = newt;				goto label;			}		}		return WRONG;	}label:	newt.tv_sec = t.tv_sec + saved_seconds;	if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0))		return WRONG;	t.tv_sec = newt.tv_sec;	if ((*funcp)(&t, offset, tmp, sp))		*okayp = TRUE;	return t;}static struct timeval time2(struct ast_tm *tmp, struct ast_tm * (* const funcp) (const struct timeval *, long, struct ast_tm*, const struct state *sp), const long offset, int *okayp, const struct state *sp){	struct timeval	t;	/*! \note	** First try without normalization of seconds	** (in case tm_sec contains a value associated with a leap second).	** If that fails, try with normalization of seconds.	*/	t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);	return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);}static struct timeval time1(struct ast_tm *tmp, struct ast_tm * (* const funcp) (const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, const struct state *sp){	struct timeval			t;	int			samei, otheri;	int			sameind, otherind;	int			i;	int			nseen;	int				seen[TZ_MAX_TYPES];	int				types[TZ_MAX_TYPES];	int				okay;	if (tmp->tm_isdst > 1)		tmp->tm_isdst = 1;	t = time2(tmp, funcp, offset, &okay, sp);#ifdef PCTS	/*	** PCTS code courtesy Grant Sullivan.	*/	if (okay)		return t;	if (tmp->tm_isdst < 0)		tmp->tm_isdst = 0;	/* reset to std and try again */#endif /* defined PCTS */#ifndef PCTS	if (okay || tmp->tm_isdst < 0)		return t;#endif /* !defined PCTS */	/*	** We're supposed to assume that somebody took a time of one type	** and did some math on it that yielded a "struct ast_tm" that's bad.	** We try to divine the type they started from and adjust to the	** type they need.	*/	if (sp == NULL)		return WRONG;	for (i = 0; i < sp->typecnt; ++i)		seen[i] = FALSE;	nseen = 0;	for (i = sp->timecnt - 1; i >= 0; --i)		if (!seen[sp->types[i]]) {			seen[sp->types[i]] = TRUE;			types[nseen++] = sp->types[i];		}	for (sameind = 0; sameind < nseen; ++sameind) {		samei = types[sameind];		if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)			continue;		for (otherind = 0; otherind < nseen; ++otherind) {			otheri = types[otherind];			if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)				continue;			tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -					sp->ttis[samei].tt_gmtoff;			tmp->tm_isdst = !tmp->tm_isdst;			t = time2(tmp, funcp, offset, &okay, sp);			if (okay)				return t;			tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -					sp->ttis[samei].tt_gmtoff;			tmp->tm_isdst = !tmp->tm_isdst;		}	}	return WRONG;}struct timeval ast_mktime(struct ast_tm *tmp, const char *zone){	const struct state *sp;	if (!(sp = ast_tzset(zone)))		return WRONG;	return time1(tmp, localsub, 0L, sp);}int ast_strftime(char *buf, size_t len, const char *tmp, const struct ast_tm *tm){	size_t fmtlen = strlen(tmp) + 1;	char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt;	int decimals = -1, i, res;	long fraction;	if (!format)		return -1;	for (; *tmp; tmp++) {		if (*tmp == '%') {			switch (tmp[1]) {			case '1':			case '2':			case '3':			case '4':			case '5':			case '6':				if (tmp[2] != 'q')					goto defcase;				decimals = tmp[1] - '0';				tmp++;				/* Fall through */			case 'q': /* Milliseconds */				if (decimals == -1)					decimals = 3;				/* Juggle some memory to fit the item */				newfmt = ast_realloc(format, fmtlen + decimals);				if (!newfmt) {					ast_free(format);					return -1;				}				fptr = fptr - format + newfmt;				format = newfmt;				fmtlen += decimals;				/* Reduce the fraction of time to the accuracy needed */				for (i = 6, fraction = tm->tm_usec; i > decimals; i--)					fraction /= 10;				fptr += sprintf(fptr, "%0*ld", decimals, fraction);				/* Reset, in case more than one 'q' specifier exists */				decimals = -1;				tmp++;				break;			default:				goto defcase;			}		} elsedefcase:	*fptr++ = *tmp;	}	*fptr = '\0';#undef strftime	res = (int)strftime(buf, len, format, (struct tm *)tm);	ast_free(format);	return res;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -