📄 strftime.c
字号:
/***
*strftime.c - String Format Time
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
*
*
*******************************************************************************/
#include <cruntime.h>
#include <internal.h>
#include <mtdll.h>
#include <time.h>
#include <locale.h>
#include <setlocal.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <dbgint.h>
#include <malloc.h>
#include <errno.h>
/* Prototypes for local routines */
static BOOL __cdecl _expandtime(
_locale_t plocinfo,
char specifier,
const struct tm *tmptr,
char **out,
size_t *count,
struct __lc_time_data *lc_time,
unsigned alternate_form);
static void __cdecl _store_str (char *in, char **out, size_t *count);
static void __cdecl _store_num (int num, int digits, char **out, size_t *count,
unsigned no_lead_zeros);
static void __cdecl _store_number (int num, char **out, size_t *count);
static BOOL __cdecl _store_winword (
_locale_t plocinfo,
int field_code,
const struct tm *tmptr,
char **out,
size_t *count,
struct __lc_time_data *lc_time);
extern "C" size_t __cdecl _Strftime (
char *string,
size_t maxsize,
const char *format,
const struct tm *timeptr,
void *lc_time_arg
);
extern "C" size_t __cdecl _Strftime_l (
char *string,
size_t maxsize,
const char *format,
const struct tm *timeptr,
void *lc_time_arg,
_locale_t plocinfo
);
/* Codes for __lc_time_data ww_* fields for _store_winword */
#define WW_SDATEFMT 0
#define WW_LDATEFMT 1
#define WW_TIMEFMT 2
#define TIME_SEP ':'
/* get a copy of the current day names */
extern "C" char * __cdecl _Getdays_l (
_locale_t plocinfo
)
{
const struct __lc_time_data *pt;
size_t n, len = 0;
char *p;
_LocaleUpdate _loc_update(plocinfo);
pt = __LC_TIME_CURR(_loc_update.GetLocaleT()->locinfo);
for (n = 0; n < 7; ++n)
len += strlen(pt->wday_abbr[n]) + strlen(pt->wday[n]) + 2;
p = (char *)_malloc_crt(len + 1);
if (p != 0) {
char *s = p;
for (n = 0; n < 7; ++n) {
*s++ = TIME_SEP;
_ERRCHECK(strcpy_s(s, (len + 1) - (s - p), pt->wday_abbr[n]));
s += strlen(s);
*s++ = TIME_SEP;
_ERRCHECK(strcpy_s(s, (len + 1) - (s - p), pt->wday[n]));
s += strlen(s);
}
*s++ = '\0';
}
return (p);
}
extern "C" char * __cdecl _Getdays (
void
)
{
return _Getdays_l(NULL);
}
/* get a copy of the current month names */
extern "C" char * __cdecl _Getmonths_l (
_locale_t plocinfo
)
{
const struct __lc_time_data *pt;
size_t n, len = 0;
char *p;
_LocaleUpdate _loc_update(plocinfo);
pt = __LC_TIME_CURR(_loc_update.GetLocaleT()->locinfo);
for (n = 0; n < 12; ++n)
len += strlen(pt->month_abbr[n]) + strlen(pt->month[n]) + 2;
p = (char *)_malloc_crt(len + 1);
if (p != 0) {
char *s = p;
for (n = 0; n < 12; ++n) {
*s++ = TIME_SEP;
_ERRCHECK(strcpy_s(s, (len + 1) - (s - p), pt->month_abbr[n]));
s += strlen(s);
*s++ = TIME_SEP;
_ERRCHECK(strcpy_s(s, (len + 1) - (s - p), pt->month[n]));
s += strlen(s);
}
*s++ = '\0';
}
return (p);
}
extern "C" char * __cdecl _Getmonths (
void
)
{
return _Getmonths_l(NULL);
}
/* get a copy of the current time locale information */
extern "C" void * __cdecl _Gettnames_l (
_locale_t plocinfo
)
{
const struct __lc_time_data *pt;
size_t n, len = 0;
char *p;
_LocaleUpdate _loc_update(plocinfo);
pt = __LC_TIME_CURR(_loc_update.GetLocaleT()->locinfo);
for (n = 0; n < 7; ++n)
len += strlen(pt->wday_abbr[n]) + strlen(pt->wday[n]) + 2;
for (n = 0; n < 12; ++n)
len += strlen(pt->month_abbr[n]) + strlen(pt->month[n]) + 2;
len += strlen(pt->ampm[0]) + strlen(pt->ampm[1]) + 2;
len += strlen(pt->ww_sdatefmt) + 1;
len += strlen(pt->ww_ldatefmt) + 1;
len += strlen(pt->ww_timefmt) + 1;
len += sizeof (*pt);
p = (char *)_malloc_crt(len);
if (p != 0) {
struct __lc_time_data *pn = (struct __lc_time_data *)p;
char *s = (char *)p + sizeof (*pt);
memcpy(p, pt, sizeof (*pt));
for (n = 0; n < 7; ++n) {
pn->wday_abbr[n] = s;
_ERRCHECK(strcpy_s(s, len - (s - p), pt->wday_abbr[n]));
s += strlen(s) + 1;
pn->wday[n] = s;
_ERRCHECK(strcpy_s(s, len - (s - p), pt->wday[n]));
s += strlen(s) + 1;
}
for (n = 0; n < 12; ++n) {
pn->month_abbr[n] = s;
_ERRCHECK(strcpy_s(s, len - (s - p), pt->month_abbr[n]));
s += strlen(s) + 1;
pn->month[n] = s;
_ERRCHECK(strcpy_s(s, len - (s - p), pt->month[n]));
s += strlen(s) + 1;
}
pn->ampm[0] = s;
_ERRCHECK(strcpy_s(s, len - (s - p), pt->ampm[0]));
s += strlen(s) + 1;
pn->ampm[1] = s;
_ERRCHECK(strcpy_s(s, len - (s - p), pt->ampm[1]));
s += strlen(s) + 1;
pn->ww_sdatefmt = s;
_ERRCHECK(strcpy_s(s, len - (s - p), pt->ww_sdatefmt));
s += strlen(s) + 1;
pn->ww_ldatefmt = s;
_ERRCHECK(strcpy_s(s, len - (s - p), pt->ww_ldatefmt));
s += strlen(s) + 1;
pn->ww_timefmt = s;
_ERRCHECK(strcpy_s(s, len - (s - p), pt->ww_timefmt));
}
return (p);
}
extern "C" void * __cdecl _Gettnames (
void
)
{
return _Gettnames_l(NULL);
}
/***
*size_t strftime(string, maxsize, format, timeptr) - Format a time string
*
*Purpose:
* Place characters into the user's output buffer expanding time
* format directives as described in the user's control string.
* Use the supplied 'tm' structure for time data when expanding
* the format directives.
* [ANSI]
*
*Entry:
* char *string = pointer to output string
* size_t maxsize = max length of string
* const char *format = format control string
* const struct tm *timeptr = pointer to tb data structure
*
*Exit:
* !0 = If the total number of resulting characters including the
* terminating null is not more than 'maxsize', then return the
* number of chars placed in the 'string' array (not including the
* null terminator).
*
* 0 = Otherwise, return 0 and the contents of the string are
* indeterminate.
*
*Exceptions:
*
*******************************************************************************/
extern "C" size_t __cdecl _strftime_l (
char *string,
size_t maxsize,
const char *format,
const struct tm *timeptr,
_locale_t plocinfo
)
{
return (_Strftime_l(string, maxsize, format, timeptr, 0, plocinfo));
}
extern "C" size_t __cdecl strftime (
char *string,
size_t maxsize,
const char *format,
const struct tm *timeptr
)
{
return (_Strftime_l(string, maxsize, format, timeptr, 0, NULL));
}
/***
*size_t _Strftime(string, maxsize, format,
* timeptr, lc_time) - Format a time string for a given locale
*
*Purpose:
* Place characters into the user's output buffer expanding time
* format directives as described in the user's control string.
* Use the supplied 'tm' structure for time data when expanding
* the format directives. use the locale information at lc_time.
* [ANSI]
*
*Entry:
* char *string = pointer to output string
* size_t maxsize = max length of string
* const char *format = format control string
* const struct tm *timeptr = pointer to tb data structure
* struct __lc_time_data *lc_time = pointer to locale-specific info
* (passed as void * to avoid type mismatch with C++)
*
*Exit:
* !0 = If the total number of resulting characters including the
* terminating null is not more than 'maxsize', then return the
* number of chars placed in the 'string' array (not including the
* null terminator).
*
* 0 = Otherwise, return 0 and the contents of the string are
* indeterminate.
*
*Exceptions:
*
*******************************************************************************/
extern "C" size_t __cdecl _Strftime (
char *string,
size_t maxsize,
const char *format,
const struct tm *timeptr,
void *lc_time_arg
)
{
return _Strftime_l(string, maxsize, format, timeptr,
lc_time_arg, NULL);
}
extern "C" size_t __cdecl _Strftime_l (
char *string,
size_t maxsize,
const char *format,
const struct tm *timeptr,
void *lc_time_arg,
_locale_t plocinfo
)
{
unsigned alternate_form;
struct __lc_time_data *lc_time;
BOOL failed=FALSE; /* true if a failure was reported to us */
size_t left; /* space left in output string */
char* strstart = string;
_LocaleUpdate _loc_update(plocinfo);
_VALIDATE_RETURN( ( string != NULL ), EINVAL, 0)
_VALIDATE_RETURN( ( maxsize != 0 ), EINVAL, 0)
*string = '\0';
_VALIDATE_RETURN( ( format != NULL ), EINVAL, 0)
// Validated below
// _VALIDATE_RETURN( ( timeptr != NULL ), EINVAL, 0)
lc_time = lc_time_arg == 0 ? _loc_update.GetLocaleT()->locinfo->lc_time_curr :
(struct __lc_time_data *)lc_time_arg;
/* Copy maxsize into temp. */
left = maxsize;
/* Copy the input string to the output string expanding the format
designations appropriately. Stop copying when one of the following
is true: (1) we hit a null char in the input stream, or (2) there's
no room left in the output stream. */
while (left > 0)
{
switch(*format)
{
case('\0'):
/* end of format input string */
goto done;
case('%'):
/* Format directive. Take appropriate action based
on format control character. */
/* validation section */
_VALIDATE_RETURN(timeptr != NULL, EINVAL, 0);
format++; /* skip over % char */
/* process flags */
alternate_form = 0;
if (*format == '#')
{
alternate_form = 1;
format++;
}
if(!_expandtime (_loc_update.GetLocaleT(), *format, timeptr, &string,
&left,lc_time, alternate_form))
{
/* if we don't have any space left, do not set the failure flag:
* we will simply return ERANGE and do not call _invalid_parameter_handler
* (see below)
*/
if (left > 0)
{
failed=TRUE;
}
goto done;
}
format++; /* skip format char */
break;
default:
/* store character, bump pointers, dec the char count */
if( _isleadbyte_l((int)(*format), _loc_update.GetLocaleT()) && left > 1)
{
/* catch \0 directly following leadbyte - invalid MBCS sequence, and do not copy to output */
if(format[1]=='\0')
{
_ASSERTE(("Invalid MBCS character sequence passed to strftime",0));
failed=TRUE;
goto done;
}
else
{
*string++ = *format++;
left--;
}
}
*string++ = *format++;
left--;
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -