2009-01-19 22:05:27 +00:00
|
|
|
/*
|
2009-08-06 11:01:44 +00:00
|
|
|
* COPYRIGHT: LGPL, See LGPL.txt in the top level directory
|
2009-01-19 22:05:27 +00:00
|
|
|
* PROJECT: ReactOS CRT library
|
2015-09-19 13:50:57 +00:00
|
|
|
* FILE: lib/sdk/crt/time/asctime.c
|
2009-01-19 22:05:27 +00:00
|
|
|
* PURPOSE: Implementation of asctime(), _asctime_s()
|
|
|
|
* PROGRAMERS: Timo Kreuzer
|
|
|
|
*/
|
|
|
|
#include <precomp.h>
|
|
|
|
#include <tchar.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include "bitsfixup.h"
|
|
|
|
|
|
|
|
#define DAYSPERWEEK 7
|
|
|
|
#define MONSPERYEAR 12
|
2009-08-06 00:26:23 +00:00
|
|
|
#define HUNDREDYEAROFFSET 19
|
2009-01-19 22:05:27 +00:00
|
|
|
|
2009-08-06 12:45:11 +00:00
|
|
|
static const _TCHAR wday_name[DAYSPERWEEK][5] =
|
2009-01-19 22:05:27 +00:00
|
|
|
{
|
2021-06-11 12:29:21 +00:00
|
|
|
_T("Sun "), _T("Mon "), _T("Tue "), _T("Wed "),
|
2009-01-19 22:05:27 +00:00
|
|
|
_T("Thu "), _T("Fri "), _T("Sat ")
|
|
|
|
};
|
|
|
|
|
2021-06-11 12:29:21 +00:00
|
|
|
static const _TCHAR mon_name[MONSPERYEAR][5] =
|
2009-01-19 22:05:27 +00:00
|
|
|
{
|
|
|
|
_T("Jan "), _T("Feb "), _T("Mar "), _T("Apr "), _T("May "), _T("Jun "),
|
|
|
|
_T("Jul "), _T("Aug "), _T("Sep "), _T("Oct "), _T("Nov "), _T("Dec ")
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef _UNICODE
|
|
|
|
typedef unsigned long long _TCHAR4;
|
|
|
|
typedef unsigned long _TCHAR2;
|
|
|
|
#else
|
|
|
|
typedef unsigned long _TCHAR4;
|
|
|
|
typedef unsigned short _TCHAR2;
|
|
|
|
#endif
|
|
|
|
|
2009-08-06 00:26:23 +00:00
|
|
|
#pragma pack(push,1)
|
2009-01-19 22:05:27 +00:00
|
|
|
typedef union
|
|
|
|
{
|
|
|
|
_TCHAR text[26];
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
_TCHAR4 WeekDay;
|
|
|
|
_TCHAR4 Month;
|
|
|
|
_TCHAR2 Day;
|
|
|
|
_TCHAR Space1;
|
|
|
|
_TCHAR2 Hour;
|
|
|
|
_TCHAR Sep1;
|
|
|
|
_TCHAR2 Minute;
|
|
|
|
_TCHAR Sep2;
|
|
|
|
_TCHAR2 Second;
|
|
|
|
_TCHAR Space2;
|
|
|
|
_TCHAR2 Year[2];
|
|
|
|
_TCHAR lb;
|
|
|
|
_TCHAR zt;
|
|
|
|
};
|
|
|
|
} timebuf_t;
|
2009-08-06 00:26:23 +00:00
|
|
|
#pragma pack(pop)
|
2009-01-19 22:05:27 +00:00
|
|
|
|
2009-08-06 11:59:20 +00:00
|
|
|
FORCEINLINE
|
2009-01-19 22:05:27 +00:00
|
|
|
_TCHAR2
|
|
|
|
IntToChar2(int x)
|
|
|
|
{
|
|
|
|
union
|
|
|
|
{
|
|
|
|
_TCHAR2 char2;
|
|
|
|
_TCHAR array[2];
|
|
|
|
} u;
|
|
|
|
|
|
|
|
u.array[0] = '0' + (x / 10);
|
|
|
|
u.array[1] = '0' + (x % 10);
|
|
|
|
|
|
|
|
return u.char2;
|
|
|
|
}
|
|
|
|
|
2010-07-25 01:22:15 +00:00
|
|
|
static __inline
|
2009-01-19 22:05:27 +00:00
|
|
|
void
|
|
|
|
FillBuf(timebuf_t *buf, const struct tm *ptm)
|
|
|
|
{
|
2021-06-11 12:29:21 +00:00
|
|
|
/* Format looks like this:
|
2009-01-19 22:05:27 +00:00
|
|
|
* "Sun Mar 01 12:34:56 1902\n\0" */
|
|
|
|
buf->WeekDay = *(_TCHAR4*)wday_name[ptm->tm_wday];
|
|
|
|
buf->Month = *(_TCHAR4*)mon_name[ptm->tm_mon];
|
|
|
|
buf->Day = IntToChar2(ptm->tm_mday);
|
|
|
|
buf->Space1 = ' ';
|
2009-08-06 00:26:23 +00:00
|
|
|
buf->Hour = IntToChar2(ptm->tm_hour);
|
2009-01-19 22:05:27 +00:00
|
|
|
buf->Sep1 = ':';
|
2009-08-06 00:26:23 +00:00
|
|
|
buf->Minute = IntToChar2(ptm->tm_min);
|
2009-01-19 22:05:27 +00:00
|
|
|
buf->Sep2 = ':';
|
2009-08-06 00:26:23 +00:00
|
|
|
buf->Second = IntToChar2(ptm->tm_sec);
|
2009-01-19 22:05:27 +00:00
|
|
|
buf->Space2 = ' ';
|
2009-08-06 00:26:23 +00:00
|
|
|
buf->Year[0] = IntToChar2(ptm->tm_year / 100 + HUNDREDYEAROFFSET);
|
2009-01-19 22:05:27 +00:00
|
|
|
buf->Year[1] = IntToChar2(ptm->tm_year % 100);
|
|
|
|
buf->lb = '\n';
|
|
|
|
buf->zt = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* \name _tasctime_s
|
|
|
|
* \brief Converts a local time into a string and returns a pointer to it.
|
|
|
|
* \param buffer Buffer that receives the string (26 characters).
|
|
|
|
* \param numberOfElements Size of the buffer in characters.
|
|
|
|
* \param time Pointer to the UTC time.
|
|
|
|
*/
|
2021-06-11 12:29:21 +00:00
|
|
|
errno_t
|
|
|
|
_tasctime_s(
|
2009-01-19 22:05:27 +00:00
|
|
|
_TCHAR* buffer,
|
|
|
|
size_t numberOfElements,
|
|
|
|
const struct tm *ptm)
|
|
|
|
{
|
|
|
|
/* Validate parameters */
|
|
|
|
if (!buffer || numberOfElements < 26 || !ptm ||
|
|
|
|
(unsigned int)ptm->tm_sec > 59 ||
|
|
|
|
(unsigned int)ptm->tm_min > 59 ||
|
|
|
|
(unsigned int)ptm->tm_hour > 23 ||
|
|
|
|
(unsigned int)ptm->tm_mday > 31 ||
|
|
|
|
(unsigned int)ptm->tm_mon > 11 ||
|
|
|
|
(unsigned int)ptm->tm_year > 2038 ||
|
|
|
|
(unsigned int)ptm->tm_wday > 6 ||
|
|
|
|
(unsigned int)ptm->tm_yday > 365)
|
|
|
|
{
|
2009-08-06 00:26:23 +00:00
|
|
|
#if 0
|
2009-01-19 22:05:27 +00:00
|
|
|
_invalid_parameter(NULL,
|
|
|
|
#ifdef UNICODE
|
|
|
|
L"_wasctime",
|
|
|
|
#else
|
|
|
|
L"asctime",
|
|
|
|
#endif
|
|
|
|
_CRT_WIDE(__FILE__),
|
|
|
|
__LINE__,
|
|
|
|
0);
|
2009-08-06 00:26:23 +00:00
|
|
|
#endif
|
2009-01-19 22:05:27 +00:00
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill the buffer */
|
|
|
|
FillBuf((timebuf_t*)buffer, ptm);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* \name _tasctime
|
|
|
|
* \brief Converts a UTC time into a string and returns a pointer to it.
|
|
|
|
* \param ptm Pointer to the UTC time.
|
|
|
|
* \remarks The string is stored in thread local buffer, shared between
|
|
|
|
* ctime, gmtime and localtime (32 and 64 bit versions).
|
|
|
|
*/
|
|
|
|
_TCHAR *
|
|
|
|
_tasctime(const struct tm *ptm)
|
|
|
|
{
|
2011-12-02 21:18:42 +00:00
|
|
|
thread_data_t *data = msvcrt_get_thread_data();
|
2009-01-19 22:05:27 +00:00
|
|
|
_TCHAR *pstr;
|
|
|
|
|
|
|
|
#ifndef _UNICODE
|
2011-12-02 21:18:42 +00:00
|
|
|
pstr = data->asctime_buffer;
|
2009-01-19 22:05:27 +00:00
|
|
|
#else
|
2011-12-02 21:18:42 +00:00
|
|
|
pstr = data->wasctime_buffer;
|
2009-01-19 22:05:27 +00:00
|
|
|
#endif
|
|
|
|
|
2011-12-02 21:18:42 +00:00
|
|
|
if(!pstr)
|
|
|
|
pstr = malloc(sizeof(struct tm));
|
|
|
|
|
2009-01-19 22:05:27 +00:00
|
|
|
/* Fill the buffer */
|
|
|
|
FillBuf((timebuf_t*)pstr, ptm);
|
|
|
|
|
|
|
|
return pstr;
|
|
|
|
}
|