📄 strftime.c
字号:
/***
*_store_num() - Convert a number to ascii and copy it
*
*Purpose:
* Convert the supplied number to decimal and store
* in the output buffer. Update both the count and
* buffer pointers.
*
* *** For internal use with strftime() only ***
*
*Entry:
* int num = pointer to integer value
* int digits = # of ascii digits to put into string
* char **out = address of pointer to output string
* size_t *count = address of char count (space in output area)
* unsigned no_lead_zeros = flag indicating that padding by leading
* zeros is not necessary
*
*Exit:
* none
*Exceptions:
*
*******************************************************************************/
static void __cdecl _store_num (
int num,
int digits,
char **out,
size_t *count,
unsigned no_lead_zeros
)
{
int temp = 0;
if (no_lead_zeros) {
_store_number (num, out, count);
return;
}
if ((size_t)digits < *count) {
for (digits--; (digits+1); digits--) {
(*out)[digits] = (char)('0' + num % 10);
num /= 10;
temp++;
}
*out += temp;
*count -= temp;
}
else
*count = 0;
}
/***
*_store_number() - Convert positive integer to string
*
*Purpose:
* Convert positive integer to a string and store it in the output
* buffer with no null terminator. Update both the count and
* buffer pointers.
*
* Differs from _store_num in that the precision is not specified,
* and no leading zeros are added.
*
* *** For internal use with strftime() only ***
*
* Created from xtoi.c
*
*Entry:
* int num = pointer to integer value
* char **out = address of pointer to output string
* size_t *count = address of char count (space in output area)
*
*Exit:
* none
*
*Exceptions:
* The buffer is filled until it is out of space. There is no
* way to tell beforehand (as in _store_num) if the buffer will
* run out of space.
*
*******************************************************************************/
static void __cdecl _store_number (
int num,
char **out,
size_t *count
)
{
char *p; /* pointer to traverse string */
char *firstdig; /* pointer to first digit */
char temp; /* temp char */
p = *out;
/* put the digits in the buffer in reverse order */
if (*count > 1)
{
do {
*p++ = (char) (num % 10 + '0');
(*count)--;
} while ((num/=10) > 0 && *count > 1);
}
firstdig = *out; /* firstdig points to first digit */
*out = p; /* return pointer to next space */
p--; /* p points to last digit */
/* reverse the buffer */
do {
temp = *p;
*p-- = *firstdig;
*firstdig++ = temp; /* swap *p and *firstdig */
} while (firstdig < p); /* repeat until halfway */
}
/***
*_store_winword() - Store date/time in WinWord format
*
*Purpose:
* Format the date/time in the supplied WinWord format
* and store it in the supplied buffer.
*
* *** For internal use with strftime() only ***
*
* For simple localized Gregorian calendars (calendar type 1), the WinWord
* format is converted token by token to strftime conversion specifiers.
* _expandtime is then called to do the work. The WinWord format is
* expected to be a character string (not wide-chars).
*
* For other calendar types, the Win32 APIs GetDateFormat/GetTimeFormat
* are instead used to do all formatting, so that this routine doesn't
* have to know about era/period strings, year offsets, etc.
*
*
*Entry:
* int field_code = code for ww_* field with format
* const struct tm *tmptr = pointer to time/date structure
* char **out = address of pointer to output string
* size_t *count = address of char count (space in output area)
* struct __lc_time_data *lc_time = pointer to locale-specific info
*
*Exit:
* BOOL true for success, false for failure
*
*Exceptions:
*
*******************************************************************************/
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
)
{
const char *format;
char specifier;
const char *p;
int repeat;
char *ampmstr;
unsigned no_lead_zeros;
switch (field_code)
{
case WW_SDATEFMT:
format = lc_time->ww_sdatefmt;
break;
case WW_LDATEFMT:
format = lc_time->ww_ldatefmt;
break;
case WW_TIMEFMT:
default:
format = lc_time->ww_timefmt;
break;
}
if (lc_time->ww_caltype != 1)
{
/* We have something other than the basic Gregorian calendar */
SYSTEMTIME SystemTime;
int cch;
int (WINAPI * FormatFunc)(LCID, DWORD, const SYSTEMTIME *,
LPCSTR, LPSTR, int);
if (field_code != WW_TIMEFMT)
FormatFunc = GetDateFormat;
else
FormatFunc = GetTimeFormat;
/* We leave the verification of SystemTime up to GetDateFormat or GetTimeFormat;
if one of those function returns 0 to indicate error, we will fall through and
call _expandtime() again.
*/
SystemTime.wYear = (WORD)(tmptr->tm_year + 1900);
SystemTime.wMonth = (WORD)(tmptr->tm_mon + 1);
SystemTime.wDay = (WORD)(tmptr->tm_mday);
SystemTime.wHour = (WORD)(tmptr->tm_hour);
SystemTime.wMinute = (WORD)(tmptr->tm_min);
SystemTime.wSecond = (WORD)(tmptr->tm_sec);
SystemTime.wMilliseconds = 0;
/* Find buffer size required */
cch = FormatFunc(lc_time->ww_lcid, 0, &SystemTime,
format, NULL, 0);
if (cch != 0)
{
char *buffer;
/* Allocate buffer, first try stack, then heap */
buffer = (char *)_malloca(cch);
if (buffer != NULL)
{
/* Do actual date/time formatting */
cch = FormatFunc(lc_time->ww_lcid, 0, &SystemTime,
format, buffer, cch);
/* Copy to output buffer */
p = buffer;
while (--cch > 0 && *count > 0) {
*(*out)++ = *p++;
(*count)--;
}
_freea(buffer);
return TRUE;
}
}
/* In case of error, just fall through to localized Gregorian */
}
while (*format && *count != 0)
{
specifier = 0; /* indicate no match */
no_lead_zeros = 0; /* default is print leading zeros */
/* count the number of repetitions of this character */
for (repeat=0, p=format; *p++ == *format; repeat++);
/* leave p pointing to the beginning of the next token */
p--;
/* switch on ascii format character and determine specifier */
switch (*format)
{
case 'M':
switch (repeat)
{
case 1: no_lead_zeros = 1; /* fall thru */
case 2: specifier = 'm'; break;
case 3: specifier = 'b'; break;
case 4: specifier = 'B'; break;
} break;
case 'd':
switch (repeat)
{
case 1: no_lead_zeros = 1; /* fall thru */
case 2: specifier = 'd'; break;
case 3: specifier = 'a'; break;
case 4: specifier = 'A'; break;
} break;
case 'y':
switch (repeat)
{
case 2: specifier = 'y'; break;
case 4: specifier = 'Y'; break;
} break;
case 'h':
switch (repeat)
{
case 1: no_lead_zeros = 1; /* fall thru */
case 2: specifier = 'I'; break;
} break;
case 'H':
switch (repeat)
{
case 1: no_lead_zeros = 1; /* fall thru */
case 2: specifier = 'H'; break;
} break;
case 'm':
switch (repeat)
{
case 1: no_lead_zeros = 1; /* fall thru */
case 2: specifier = 'M'; break;
} break;
case 's': /* for compatibility; not strictly WinWord */
switch (repeat)
{
case 1: no_lead_zeros = 1; /* fall thru */
case 2: specifier = 'S'; break;
} break;
case 'A':
case 'a':
if (!__ascii_stricmp(format, "am/pm"))
p = format + 5;
else if (!__ascii_stricmp(format, "a/p"))
p = format + 3;
specifier = 'p';
break;
case 't': /* t or tt time marker suffix */
if ( tmptr->tm_hour <= 11 )
ampmstr = lc_time->ampm[0];
else
ampmstr = lc_time->ampm[1];
if ( (repeat == 1) && (*count > 0) ) {
if ( _isleadbyte_l((int)*ampmstr, plocinfo) && (*count > 1) )
{
/* catch \0 directly following leadbyte - invalid MBCS sequence, and do not copy to output */
if(ampmstr[1]=='\0')
{
_ASSERTE(("Invalid MBCS character sequence found in locale AMPM string",0));
return FALSE;
}
*(*out)++ = *ampmstr++;
(*count)--;
}
*(*out)++ = *ampmstr++;
(*count)--;
} else {
while (*ampmstr != 0 && *count > 0) {
if (_isleadbyte_l((int)*ampmstr, plocinfo) && *count > 1) {
/* handle dud string leadbyte, EOS */
if(ampmstr[1]=='\0')
{
_ASSERTE(("Invalid MBCS character sequence found in locale AMPM string",0));
return FALSE;
}
*(*out)++ = *ampmstr++;
(*count)--;
}
*(*out)++ = *ampmstr++;
(*count)--;
}
}
format = p;
continue;
case '\'': /* literal string */
if (repeat & 1) /* odd number */
{
format += repeat;
while (*format && *count != 0)
{
if (*format == '\'')
{
format++;
break;
}
if ( _isleadbyte_l((int)*format, plocinfo) && (*count > 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 into strftime",0));
return FALSE;
}
*(*out)++ = *format++;
(*count)--;
}
*(*out)++ = *format++;
(*count)--;
}
}
else { /* even number */
format += repeat;
}
continue;
default: /* non-control char, print it */
break;
} /* switch */
/* expand specifier, or copy literal if specifier not found */
if (specifier)
{
if (!_expandtime( plocinfo,
specifier,
tmptr,
out,
count,
lc_time,
no_lead_zeros))
{
return FALSE;
}
format = p; /* bump format up to the next token */
} else {
if ( _isleadbyte_l((int)*format, plocinfo) && (*count > 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 into strftime",0));
return FALSE;
}
*(*out)++ = *format++;
(*count)--;
}
*(*out)++ = *format++;
(*count)--;
}
} /* while */
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -