ReactOS  0.4.14-dev-583-g2a1ba2c
strftime.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: LGPL, See LGPL.txt in the top level directory
3  * PROJECT: ReactOS CRT library
4  * FILE: lib/sdk/crt/time/strftime.c
5  * PURPOSE:
6  * PROGRAMER:
7  */
8 #include <precomp.h>
9 
10 static inline BOOL strftime_date(char *str, size_t *pos, size_t max,
11  BOOL alternate, const struct tm *mstm, MSVCRT___lc_time_data *time_data)
12 {
13  char *format;
14  SYSTEMTIME st;
15  size_t ret;
16 
17  st.wYear = mstm->tm_year + 1900;
18  st.wMonth = mstm->tm_mon + 1;
19  st.wDayOfWeek = mstm->tm_wday;
20  st.wDay = mstm->tm_mday;
21  st.wHour = mstm->tm_hour;
22  st.wMinute = mstm->tm_min;
23  st.wSecond = mstm->tm_sec;
24  st.wMilliseconds = 0;
25 
26  format = alternate ? time_data->str.names.date : time_data->str.names.short_date;
27  ret = GetDateFormatA(time_data->lcid, 0, &st, format, NULL, 0);
28  if(ret && ret<max-*pos)
29  ret = GetDateFormatA(time_data->lcid, 0, &st, format, str+*pos, max-*pos);
30  if(!ret) {
31  *str = 0;
32  *_errno() = EINVAL;
33  return FALSE;
34  }else if(ret > max-*pos) {
35  *str = 0;
36  *_errno() = ERANGE;
37  return FALSE;
38  }
39  *pos += ret-1;
40  return TRUE;
41 }
42 
43 static inline BOOL strftime_time(char *str, size_t *pos, size_t max,
44  const struct tm *mstm, MSVCRT___lc_time_data *time_data)
45 {
46  SYSTEMTIME st;
47  size_t ret;
48 
49  st.wYear = mstm->tm_year + 1900;
50  st.wMonth = mstm->tm_mon + 1;
51  st.wDayOfWeek = mstm->tm_wday;
52  st.wDay = mstm->tm_mday;
53  st.wHour = mstm->tm_hour;
54  st.wMinute = mstm->tm_min;
55  st.wSecond = mstm->tm_sec;
56  st.wMilliseconds = 0;
57 
58  ret = GetTimeFormatA(time_data->lcid, 0, &st, time_data->str.names.time, NULL, 0);
59  if(ret && ret<max-*pos)
60  ret = GetTimeFormatA(time_data->lcid, 0, &st, time_data->str.names.time,
61  str+*pos, max-*pos);
62  if(!ret) {
63  *str = 0;
64  *_errno() = EINVAL;
65  return FALSE;
66  }else if(ret > max-*pos) {
67  *str = 0;
68  *_errno() = ERANGE;
69  return FALSE;
70  }
71  *pos += ret-1;
72  return TRUE;
73 }
74 
75 static inline BOOL strftime_str(char *str, size_t *pos, size_t max, char *src)
76 {
77  size_t len = strlen(src);
78  if(len > max-*pos) {
79  *str = 0;
80  *_errno() = ERANGE;
81  return FALSE;
82  }
83 
84  memcpy(str+*pos, src, len);
85  *pos += len;
86  return TRUE;
87 }
88 
89 static inline BOOL strftime_int(char *str, size_t *pos, size_t max,
90  int src, int prec, int l, int h)
91 {
92  size_t len;
93 
94  if(src<l || src>h) {
95  *str = 0;
96  *_errno() = EINVAL;
97  return FALSE;
98  }
99 
100  len = _snprintf(str+*pos, max-*pos, "%0*d", prec, src);
101  if(len == -1) {
102  *str = 0;
103  *_errno() = ERANGE;
104  return FALSE;
105  }
106 
107  *pos += len;
108  return TRUE;
109 }
110 
111 /*********************************************************************
112  * _Strftime (MSVCRT.@)
113  */
114 size_t CDECL _Strftime(char *str, size_t max, const char *format,
115  const struct tm *mstm, MSVCRT___lc_time_data *time_data)
116 {
117  size_t ret, tmp;
118  BOOL alternate;
119 
120  TRACE("(%p %ld %s %p %p)\n", str, max, format, mstm, time_data);
121 
122  if(!str || !format) {
123  if(str && max)
124  *str = 0;
125  *_errno() = EINVAL;
126  return 0;
127  }
128 
129  if(!time_data)
130  time_data = get_locinfo()->lc_time_curr;
131 
132  for(ret=0; *format && ret<max; format++) {
133  if(*format != '%') {
134  str[ret++] = *format;
135  continue;
136  }
137 
138  format++;
139  if(*format == '#') {
140  alternate = TRUE;
141  format++;
142  }else {
143  alternate = FALSE;
144  }
145 
146  if(!mstm)
147  goto einval_error;
148 
149  switch(*format) {
150  case 'c':
151  if(!strftime_date(str, &ret, max, alternate, mstm, time_data))
152  return 0;
153  if(ret < max)
154  str[ret++] = ' ';
155  if(!strftime_time(str, &ret, max, mstm, time_data))
156  return 0;
157  break;
158  case 'x':
159  if(!strftime_date(str, &ret, max, alternate, mstm, time_data))
160  return 0;
161  break;
162  case 'X':
163  if(!strftime_time(str, &ret, max, mstm, time_data))
164  return 0;
165  break;
166  case 'a':
167  if(mstm->tm_wday<0 || mstm->tm_wday>6)
168  goto einval_error;
169  if(!strftime_str(str, &ret, max, time_data->str.names.short_wday[mstm->tm_wday]))
170  return 0;
171  break;
172  case 'A':
173  if(mstm->tm_wday<0 || mstm->tm_wday>6)
174  goto einval_error;
175  if(!strftime_str(str, &ret, max, time_data->str.names.wday[mstm->tm_wday]))
176  return 0;
177  break;
178  case 'b':
179  if(mstm->tm_mon<0 || mstm->tm_mon>11)
180  goto einval_error;
181  if(!strftime_str(str, &ret, max, time_data->str.names.short_mon[mstm->tm_mon]))
182  return 0;
183  break;
184  case 'B':
185  if(mstm->tm_mon<0 || mstm->tm_mon>11)
186  goto einval_error;
187  if(!strftime_str(str, &ret, max, time_data->str.names.mon[mstm->tm_mon]))
188  return 0;
189  break;
190  case 'd':
191  if(!strftime_int(str, &ret, max, mstm->tm_mday, alternate ? 0 : 2, 0, 31))
192  return 0;
193  break;
194  case 'H':
195  if(!strftime_int(str, &ret, max, mstm->tm_hour, alternate ? 0 : 2, 0, 23))
196  return 0;
197  break;
198  case 'I':
199  tmp = mstm->tm_hour;
200  if(tmp > 12)
201  tmp -= 12;
202  else if(!tmp)
203  tmp = 12;
204  if(!strftime_int(str, &ret, max, tmp, alternate ? 0 : 2, 1, 12))
205  return 0;
206  break;
207  case 'j':
208  if(!strftime_int(str, &ret, max, mstm->tm_yday+1, alternate ? 0 : 3, 1, 366))
209  return 0;
210  break;
211  case 'm':
212  if(!strftime_int(str, &ret, max, mstm->tm_mon+1, alternate ? 0 : 2, 1, 12))
213  return 0;
214  break;
215  case 'M':
216  if(!strftime_int(str, &ret, max, mstm->tm_min, alternate ? 0 : 2, 0, 59))
217  return 0;
218  break;
219  case 'p':
220  if(mstm->tm_hour<0 || mstm->tm_hour>23)
221  goto einval_error;
222  if(!strftime_str(str, &ret, max, mstm->tm_hour<12 ?
223  time_data->str.names.am : time_data->str.names.pm))
224  return 0;
225  break;
226  case 'S':
227  if(!strftime_int(str, &ret, max, mstm->tm_sec, alternate ? 0 : 2, 0, 59))
228  return 0;
229  break;
230  case 'w':
231  if(!strftime_int(str, &ret, max, mstm->tm_wday, 0, 0, 6))
232  return 0;
233  break;
234  case 'y':
235  if(!strftime_int(str, &ret, max, mstm->tm_year%100, alternate ? 0 : 2, 0, 99))
236  return 0;
237  break;
238  case 'Y':
239  tmp = 1900+mstm->tm_year;
240  if(!strftime_int(str, &ret, max, tmp, alternate ? 0 : 4, 0, 9999))
241  return 0;
242  break;
243  case 'z':
244  case 'Z':
245  _tzset();
246  if(_get_tzname(&tmp, str+ret, max-ret, mstm->tm_isdst ? 1 : 0))
247  return 0;
248  ret += tmp;
249  break;
250  case 'U':
251  case 'W':
252  if(mstm->tm_wday<0 || mstm->tm_wday>6 || mstm->tm_yday<0 || mstm->tm_yday>365)
253  goto einval_error;
254  if(*format == 'U')
255  tmp = mstm->tm_wday;
256  else if(!mstm->tm_wday)
257  tmp = 6;
258  else
259  tmp = mstm->tm_wday-1;
260 
261  tmp = mstm->tm_yday/7 + (tmp <= ((unsigned)mstm->tm_yday%7));
262  if(!strftime_int(str, &ret, max, tmp, alternate ? 0 : 2, 0, 53))
263  return 0;
264  break;
265  case '%':
266  str[ret++] = '%';
267  break;
268  default:
269  WARN("unknown format %c\n", *format);
270  goto einval_error;
271  }
272  }
273 
274  if(ret == max) {
275  if(max)
276  *str = 0;
277  *_errno() = ERANGE;
278  return 0;
279  }
280 
281  str[ret] = 0;
282  return ret;
283 
284 einval_error:
285  *str = 0;
286  *_errno() = EINVAL;
287  return 0;
288 }
289 
290 /*********************************************************************
291  * strftime (MSVCRT.@)
292  */
293 size_t CDECL strftime( char *str, size_t max, const char *format,
294  const struct tm *mstm )
295 {
296  return _Strftime(str, max, format, mstm, NULL);
297 }
298 
299 /*********************************************************************
300  * wcsftime (MSVCRT.@)
301  */
302 size_t CDECL wcsftime( wchar_t *str, size_t max,
303  const wchar_t *format, const struct tm *mstm )
304 {
305  char *s, *fmt;
306  size_t len;
307 
308  TRACE("%p %ld %s %p\n", str, max, debugstr_w(format), mstm );
309 
310  len = WideCharToMultiByte( CP_ACP, 0, format, -1, NULL, 0, NULL, NULL );
311  if (!(fmt = malloc( len ))) return 0;
313 
314  if ((s = malloc( max*4 )))
315  {
316  if (!strftime( s, max*4, fmt, mstm )) s[0] = 0;
317  len = MultiByteToWideChar( CP_ACP, 0, s, -1, str, max );
318  if (len) len--;
319  free( s );
320  }
321  else len = 0;
322 
323  free( fmt );
324  return len;
325 }
#define max(a, b)
Definition: svc.c:63
int tm_min
Definition: time.h:78
#define TRUE
Definition: types.h:120
#define WideCharToMultiByte
Definition: compat.h:101
WORD wMonth
Definition: winbase.h:878
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
INT WINAPI GetDateFormatA(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCSTR lpFormat, LPSTR lpDateStr, INT cchOut)
Definition: lcformat.c:922
_CRTIMP void __cdecl _tzset(void)
Definition: timezone.c:92
#define CP_ACP
Definition: compat.h:99
Definition: arc.h:39
WORD wDayOfWeek
Definition: winbase.h:879
#define free
Definition: debug_ros.c:5
#define WARN(fmt,...)
Definition: debug.h:111
int tm_mday
Definition: time.h:80
const char * fmt
Definition: wsprintf.c:30
char * str[43]
Definition: locale.h:53
int tm_year
Definition: time.h:82
size_t CDECL wcsftime(wchar_t *str, size_t max, const wchar_t *format, const struct tm *mstm)
Definition: strftime.c:302
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
static BOOL strftime_date(char *str, size_t *pos, size_t max, BOOL alternate, const struct tm *mstm, MSVCRT___lc_time_data *time_data)
Definition: strftime.c:10
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
INT WINAPI GetTimeFormatA(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCSTR lpFormat, LPSTR lpTimeStr, INT cchOut)
Definition: lcformat.c:1030
WORD wYear
Definition: winbase.h:877
#define _snprintf
Definition: xmlstorage.h:200
unsigned int BOOL
Definition: ntddk_ex.h:94
#define debugstr_w
Definition: kernel32.h:32
const WCHAR * str
WORD wMinute
Definition: winbase.h:882
smooth NULL
Definition: ftsmooth.c:416
#define get_locinfo()
Definition: winesup.h:25
static BOOL strftime_time(char *str, size_t *pos, size_t max, const struct tm *mstm, MSVCRT___lc_time_data *time_data)
Definition: strftime.c:43
int tm_mon
Definition: time.h:81
r l[0]
Definition: byte_order.h:167
size_t CDECL strftime(char *str, size_t max, const char *format, const struct tm *mstm)
Definition: strftime.c:293
#define TRACE(s)
Definition: solgame.cpp:4
static BOOL strftime_str(char *str, size_t *pos, size_t max, char *src)
Definition: strftime.c:75
size_t CDECL _Strftime(char *str, size_t max, const char *format, const struct tm *mstm, MSVCRT___lc_time_data *time_data)
Definition: strftime.c:114
WORD wSecond
Definition: winbase.h:883
_CRTIMP int *__cdecl _errno(void)
Definition: errno.c:19
WORD wMilliseconds
Definition: winbase.h:884
#define ERANGE
Definition: acclib.h:92
int ret
LCID lcid
Definition: locale.h:66
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
Definition: time.h:76
GLenum src
Definition: glext.h:6340
int tm_wday
Definition: time.h:83
int tm_yday
Definition: time.h:84
WORD wDay
Definition: winbase.h:880
_CRTIMP errno_t __cdecl _get_tzname(_Out_ size_t *_ReturnValue, _Out_writes_z_(_SizeInBytes) char *_Buffer, _In_ size_t _SizeInBytes, _In_ int _Index)
#define CDECL
Definition: compat.h:21
WORD wHour
Definition: winbase.h:881
#define MultiByteToWideChar
Definition: compat.h:100
int tm_sec
Definition: time.h:77
int tm_hour
Definition: time.h:79
#define malloc
Definition: debug_ros.c:4
static BOOL strftime_int(char *str, size_t *pos, size_t max, int src, int prec, int l, int h)
Definition: strftime.c:89
int tm_isdst
Definition: time.h:85
Definition: dsound.c:943
static unsigned(__cdecl *hash_bstr)(bstr_t s)