xref: /reactos/sdk/lib/crt/time/asctime.c (revision 34593d93)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * COPYRIGHT:   LGPL, See LGPL.txt in the top level directory
3*c2c66affSColin Finck  * PROJECT:     ReactOS CRT library
4*c2c66affSColin Finck  * FILE:        lib/sdk/crt/time/asctime.c
5*c2c66affSColin Finck  * PURPOSE:     Implementation of asctime(), _asctime_s()
6*c2c66affSColin Finck  * PROGRAMERS:  Timo Kreuzer
7*c2c66affSColin Finck  */
8*c2c66affSColin Finck #include <precomp.h>
9*c2c66affSColin Finck #include <tchar.h>
10*c2c66affSColin Finck #include <time.h>
11*c2c66affSColin Finck #include "bitsfixup.h"
12*c2c66affSColin Finck 
13*c2c66affSColin Finck #define DAYSPERWEEK 7
14*c2c66affSColin Finck #define MONSPERYEAR 12
15*c2c66affSColin Finck #define HUNDREDYEAROFFSET 19
16*c2c66affSColin Finck 
17*c2c66affSColin Finck static const _TCHAR wday_name[DAYSPERWEEK][5] =
18*c2c66affSColin Finck {
19*c2c66affSColin Finck     _T("Sun "), _T("Mon "), _T("Tue "), _T("Wed "),
20*c2c66affSColin Finck     _T("Thu "), _T("Fri "), _T("Sat ")
21*c2c66affSColin Finck };
22*c2c66affSColin Finck 
23*c2c66affSColin Finck static const _TCHAR mon_name[MONSPERYEAR][5] =
24*c2c66affSColin Finck {
25*c2c66affSColin Finck     _T("Jan "), _T("Feb "), _T("Mar "), _T("Apr "), _T("May "), _T("Jun "),
26*c2c66affSColin Finck     _T("Jul "), _T("Aug "), _T("Sep "), _T("Oct "), _T("Nov "), _T("Dec ")
27*c2c66affSColin Finck };
28*c2c66affSColin Finck 
29*c2c66affSColin Finck #ifdef _UNICODE
30*c2c66affSColin Finck typedef unsigned long long _TCHAR4;
31*c2c66affSColin Finck typedef unsigned long _TCHAR2;
32*c2c66affSColin Finck #else
33*c2c66affSColin Finck typedef unsigned long _TCHAR4;
34*c2c66affSColin Finck typedef unsigned short _TCHAR2;
35*c2c66affSColin Finck #endif
36*c2c66affSColin Finck 
37*c2c66affSColin Finck #pragma pack(push,1)
38*c2c66affSColin Finck typedef union
39*c2c66affSColin Finck {
40*c2c66affSColin Finck     _TCHAR text[26];
41*c2c66affSColin Finck     struct
42*c2c66affSColin Finck     {
43*c2c66affSColin Finck         _TCHAR4 WeekDay;
44*c2c66affSColin Finck         _TCHAR4 Month;
45*c2c66affSColin Finck         _TCHAR2 Day;
46*c2c66affSColin Finck         _TCHAR Space1;
47*c2c66affSColin Finck         _TCHAR2 Hour;
48*c2c66affSColin Finck         _TCHAR Sep1;
49*c2c66affSColin Finck         _TCHAR2 Minute;
50*c2c66affSColin Finck         _TCHAR Sep2;
51*c2c66affSColin Finck         _TCHAR2 Second;
52*c2c66affSColin Finck         _TCHAR Space2;
53*c2c66affSColin Finck         _TCHAR2 Year[2];
54*c2c66affSColin Finck         _TCHAR lb;
55*c2c66affSColin Finck         _TCHAR zt;
56*c2c66affSColin Finck     };
57*c2c66affSColin Finck } timebuf_t;
58*c2c66affSColin Finck #pragma pack(pop)
59*c2c66affSColin Finck 
60*c2c66affSColin Finck FORCEINLINE
61*c2c66affSColin Finck _TCHAR2
IntToChar2(int x)62*c2c66affSColin Finck IntToChar2(int x)
63*c2c66affSColin Finck {
64*c2c66affSColin Finck     union
65*c2c66affSColin Finck     {
66*c2c66affSColin Finck         _TCHAR2 char2;
67*c2c66affSColin Finck         _TCHAR array[2];
68*c2c66affSColin Finck     } u;
69*c2c66affSColin Finck 
70*c2c66affSColin Finck     u.array[0] = '0' + (x / 10);
71*c2c66affSColin Finck     u.array[1] = '0' + (x % 10);
72*c2c66affSColin Finck 
73*c2c66affSColin Finck     return u.char2;
74*c2c66affSColin Finck }
75*c2c66affSColin Finck 
76*c2c66affSColin Finck static __inline
77*c2c66affSColin Finck void
FillBuf(timebuf_t * buf,const struct tm * ptm)78*c2c66affSColin Finck FillBuf(timebuf_t *buf, const struct tm *ptm)
79*c2c66affSColin Finck {
80*c2c66affSColin Finck     /* Format looks like this:
81*c2c66affSColin Finck      * "Sun Mar 01 12:34:56 1902\n\0" */
82*c2c66affSColin Finck     buf->WeekDay = *(_TCHAR4*)wday_name[ptm->tm_wday];
83*c2c66affSColin Finck     buf->Month = *(_TCHAR4*)mon_name[ptm->tm_mon];
84*c2c66affSColin Finck     buf->Day = IntToChar2(ptm->tm_mday);
85*c2c66affSColin Finck     buf->Space1 = ' ';
86*c2c66affSColin Finck     buf->Hour = IntToChar2(ptm->tm_hour);
87*c2c66affSColin Finck     buf->Sep1 = ':';
88*c2c66affSColin Finck     buf->Minute = IntToChar2(ptm->tm_min);
89*c2c66affSColin Finck     buf->Sep2 = ':';
90*c2c66affSColin Finck     buf->Second = IntToChar2(ptm->tm_sec);
91*c2c66affSColin Finck     buf->Space2 = ' ';
92*c2c66affSColin Finck     buf->Year[0] = IntToChar2(ptm->tm_year / 100 + HUNDREDYEAROFFSET);
93*c2c66affSColin Finck     buf->Year[1] = IntToChar2(ptm->tm_year % 100);
94*c2c66affSColin Finck     buf->lb = '\n';
95*c2c66affSColin Finck     buf->zt = '\0';
96*c2c66affSColin Finck }
97*c2c66affSColin Finck 
98*c2c66affSColin Finck /******************************************************************************
99*c2c66affSColin Finck  * \name _tasctime_s
100*c2c66affSColin Finck  * \brief Converts a local time into a string and returns a pointer to it.
101*c2c66affSColin Finck  * \param buffer Buffer that receives the string (26 characters).
102*c2c66affSColin Finck  * \param numberOfElements Size of the buffer in characters.
103*c2c66affSColin Finck  * \param time Pointer to the UTC time.
104*c2c66affSColin Finck  */
105*c2c66affSColin Finck errno_t
_tasctime_s(_TCHAR * buffer,size_t numberOfElements,const struct tm * ptm)106*c2c66affSColin Finck _tasctime_s(
107*c2c66affSColin Finck     _TCHAR* buffer,
108*c2c66affSColin Finck     size_t numberOfElements,
109*c2c66affSColin Finck     const struct tm *ptm)
110*c2c66affSColin Finck {
111*c2c66affSColin Finck     /* Validate parameters */
112*c2c66affSColin Finck     if (!buffer || numberOfElements < 26 || !ptm ||
113*c2c66affSColin Finck         (unsigned int)ptm->tm_sec > 59 ||
114*c2c66affSColin Finck         (unsigned int)ptm->tm_min > 59 ||
115*c2c66affSColin Finck         (unsigned int)ptm->tm_hour > 23 ||
116*c2c66affSColin Finck         (unsigned int)ptm->tm_mday > 31 ||
117*c2c66affSColin Finck         (unsigned int)ptm->tm_mon > 11 ||
118*c2c66affSColin Finck         (unsigned int)ptm->tm_year > 2038 ||
119*c2c66affSColin Finck         (unsigned int)ptm->tm_wday > 6 ||
120*c2c66affSColin Finck         (unsigned int)ptm->tm_yday > 365)
121*c2c66affSColin Finck     {
122*c2c66affSColin Finck #if 0
123*c2c66affSColin Finck         _invalid_parameter(NULL,
124*c2c66affSColin Finck #ifdef UNICODE
125*c2c66affSColin Finck                             L"_wasctime",
126*c2c66affSColin Finck #else
127*c2c66affSColin Finck                             L"asctime",
128*c2c66affSColin Finck #endif
129*c2c66affSColin Finck                            _CRT_WIDE(__FILE__),
130*c2c66affSColin Finck                            __LINE__,
131*c2c66affSColin Finck                            0);
132*c2c66affSColin Finck #endif
133*c2c66affSColin Finck         return EINVAL;
134*c2c66affSColin Finck     }
135*c2c66affSColin Finck 
136*c2c66affSColin Finck     /* Fill the buffer */
137*c2c66affSColin Finck     FillBuf((timebuf_t*)buffer, ptm);
138*c2c66affSColin Finck 
139*c2c66affSColin Finck     return 0;
140*c2c66affSColin Finck }
141*c2c66affSColin Finck 
142*c2c66affSColin Finck /******************************************************************************
143*c2c66affSColin Finck  * \name _tasctime
144*c2c66affSColin Finck  * \brief Converts a UTC time into a string and returns a pointer to it.
145*c2c66affSColin Finck  * \param ptm Pointer to the UTC time.
146*c2c66affSColin Finck  * \remarks The string is stored in thread local buffer, shared between
147*c2c66affSColin Finck  *          ctime, gmtime and localtime (32 and 64 bit versions).
148*c2c66affSColin Finck  */
149*c2c66affSColin Finck _TCHAR *
_tasctime(const struct tm * ptm)150*c2c66affSColin Finck _tasctime(const struct tm *ptm)
151*c2c66affSColin Finck {
152*c2c66affSColin Finck     thread_data_t *data = msvcrt_get_thread_data();
153*c2c66affSColin Finck     _TCHAR *pstr;
154*c2c66affSColin Finck 
155*c2c66affSColin Finck #ifndef _UNICODE
156*c2c66affSColin Finck     pstr = data->asctime_buffer;
157*c2c66affSColin Finck #else
158*c2c66affSColin Finck     pstr = data->wasctime_buffer;
159*c2c66affSColin Finck #endif
160*c2c66affSColin Finck 
161*c2c66affSColin Finck     if(!pstr)
162*c2c66affSColin Finck         pstr = malloc(sizeof(struct tm));
163*c2c66affSColin Finck 
164*c2c66affSColin Finck     /* Fill the buffer */
165*c2c66affSColin Finck     FillBuf((timebuf_t*)pstr, ptm);
166*c2c66affSColin Finck 
167*c2c66affSColin Finck     return pstr;
168*c2c66affSColin Finck }
169