foobar2000 SDK  2015-08-03
filetimetools.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 
3 
4 #ifndef _WIN32
5 #error PORTME
6 #endif
7 
8 static bool is_spacing(char c) {return c == ' ' || c==10 || c==13 || c == '\t';}
9 
10 static bool is_spacing(const char * str, t_size len) {
11  for(t_size walk = 0; walk < len; ++walk) if (!is_spacing(str[walk])) return false;
12  return true;
13 }
14 
15 typedef exception_io_data exception_time_error;
16 
17 static unsigned ParseDateElem(const char * ptr, t_size len) {
18  unsigned ret = 0;
19  for(t_size walk = 0; walk < len; ++walk) {
20  const char c = ptr[walk];
21  if (c < '0' || c > '9') throw exception_time_error();
22  ret = ret * 10 + (unsigned)(c - '0');
23  }
24  return ret;
25 }
26 
28  // Accepted format
29  // YYYY-MM-DD HH:MM:SS
30  try {
31  t_size remaining = strlen(date);
32  SYSTEMTIME st = {};
33  st.wDay = 1; st.wMonth = 1;
34  for(;;) {
35 #define ADVANCE(n) { PFC_ASSERT( remaining >= n); date += n; remaining -= n; }
36 #define ADVANCE_TEST(n) { if (remaining < n) throw exception_time_error(); }
37 #define PARSE(var, digits) { ADVANCE_TEST(digits); var = (WORD) ParseDateElem(date, digits); ADVANCE(digits) ; }
38 #define TEST_END( durationIncrement )
39 #define SKIP(c) { ADVANCE_TEST(1); if (date[0] != c) throw exception_time_error(); ADVANCE(1); }
40 #define SKIP_SPACING() {while(remaining > 0 && is_spacing(*date)) ADVANCE(1);}
41  SKIP_SPACING();
42  PARSE( st.wYear, 4 ); if (st.wYear < 1601) throw exception_time_error();
43  TEST_END(wYear); SKIP('-');
44  PARSE( st.wMonth, 2 ); if (st.wMonth < 1 || st.wMonth > 12) throw exception_time_error();
45  TEST_END(wMonth); SKIP('-');
46  PARSE( st.wDay, 2); if (st.wDay < 1 || st.wDay > 31) throw exception_time_error();
47  TEST_END(wDay); SKIP(' ');
48  PARSE( st.wHour, 2); if (st.wHour >= 24) throw exception_time_error();
49  TEST_END(wHour); SKIP(':');
50  PARSE( st.wMinute, 2); if (st.wMinute >= 60) throw exception_time_error();
51  TEST_END(wMinute); SKIP(':');
52  PARSE( st.wSecond, 2); if (st.wSecond >= 60) throw exception_time_error();
53  SKIP_SPACING();
54  TEST_END( wSecond );
55 #undef ADVANCE
56 #undef ADVANCE_TEST
57 #undef PARSE
58 #undef TEST_END
59 #undef SKIP
60 #undef SKIP_SPACING
61  if (remaining > 0) throw exception_time_error();
62  break;
63  }
64  t_filetimestamp base, out;
65  if (!SystemTimeToFileTime(&st, (FILETIME*) &base)) throw exception_time_error();
66  if (!LocalFileTimeToFileTime((const FILETIME*)&base, (FILETIME*)&out)) throw exception_time_error();
67  return out;
68  } catch(exception_time_error) {
69  return filetimestamp_invalid;
70  }
71 }
72 
73 static const char g_invalidMsg[] = "<invalid timestamp>";
74 
75 format_filetimestamp::format_filetimestamp(t_filetimestamp p_timestamp) {
76  try {
77  SYSTEMTIME st; FILETIME ft;
78  if (FileTimeToLocalFileTime((FILETIME*)&p_timestamp,&ft)) {
79  if (FileTimeToSystemTime(&ft,&st)) {
80  m_buffer
81  << pfc::format_uint(st.wYear,4) << "-" << pfc::format_uint(st.wMonth,2) << "-" << pfc::format_uint(st.wDay,2) << " "
82  << pfc::format_uint(st.wHour,2) << ":" << pfc::format_uint(st.wMinute,2) << ":" << pfc::format_uint(st.wSecond,2);
83  return;
84  }
85  }
86  } catch(...) {}
87  m_buffer = g_invalidMsg;
88 }
89 
90 format_filetimestamp_utc::format_filetimestamp_utc(t_filetimestamp p_timestamp) {
91  try {
92  SYSTEMTIME st;
93  if (FileTimeToSystemTime((const FILETIME*)&p_timestamp,&st)) {
94  m_buffer
95  << pfc::format_uint(st.wYear,4) << "-" << pfc::format_uint(st.wMonth,2) << "-" << pfc::format_uint(st.wDay,2) << " "
96  << pfc::format_uint(st.wHour,2) << ":" << pfc::format_uint(st.wMinute,2) << ":" << pfc::format_uint(st.wSecond,2);
97  return;
98  }
99  } catch(...) {}
100  m_buffer = g_invalidMsg;
101 }
static const char g_invalidMsg[]
static unsigned ParseDateElem(const char *ptr, t_size len)
static bool is_spacing(char c)
const t_filetimestamp filetimestamp_invalid
Invalid/unknown file timestamp constant. Also see: t_filetimestamp.
Definition: filesystem.h:14
size_t t_size
Definition: int_types.h:48
t_uint64 t_filetimestamp
Type used for file timestamp related variables. 64-bit value representing the number of 100-nanosecon...
Definition: filesystem.h:12
t_filetimestamp filetimestamp_from_string(const char *date)
exception_io_data exception_time_error