104 lines
3.5 KiB
C++
104 lines
3.5 KiB
C++
#include "stdafx.h"
|
|
|
|
|
|
#ifndef _WIN32
|
|
#error PORTME
|
|
#endif
|
|
|
|
#include "filetimetools.h"
|
|
|
|
static bool is_spacing(char c) {return c == ' ' || c==10 || c==13 || c == '\t';}
|
|
|
|
static bool is_spacing(const char * str, t_size len) {
|
|
for(t_size walk = 0; walk < len; ++walk) if (!is_spacing(str[walk])) return false;
|
|
return true;
|
|
}
|
|
|
|
typedef exception_io_data exception_time_error;
|
|
|
|
static unsigned ParseDateElem(const char * ptr, t_size len) {
|
|
unsigned ret = 0;
|
|
for(t_size walk = 0; walk < len; ++walk) {
|
|
const char c = ptr[walk];
|
|
if (c < '0' || c > '9') throw exception_time_error();
|
|
ret = ret * 10 + (unsigned)(c - '0');
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
t_filetimestamp foobar2000_io::filetimestamp_from_string(const char * date) {
|
|
// Accepted format
|
|
// YYYY-MM-DD HH:MM:SS
|
|
try {
|
|
t_size remaining = strlen(date);
|
|
SYSTEMTIME st = {};
|
|
st.wDay = 1; st.wMonth = 1;
|
|
for(;;) {
|
|
#define ADVANCE(n) { PFC_ASSERT( remaining >= n); date += n; remaining -= n; }
|
|
#define ADVANCE_TEST(n) { if (remaining < n) throw exception_time_error(); }
|
|
#define PARSE(var, digits) { ADVANCE_TEST(digits); var = (WORD) ParseDateElem(date, digits); ADVANCE(digits) ; }
|
|
#define TEST_END( durationIncrement )
|
|
#define SKIP(c) { ADVANCE_TEST(1); if (date[0] != c) throw exception_time_error(); ADVANCE(1); }
|
|
#define SKIP_SPACING() {while(remaining > 0 && is_spacing(*date)) ADVANCE(1);}
|
|
SKIP_SPACING();
|
|
PARSE( st.wYear, 4 ); if (st.wYear < 1601) throw exception_time_error();
|
|
TEST_END(wYear); SKIP('-');
|
|
PARSE( st.wMonth, 2 ); if (st.wMonth < 1 || st.wMonth > 12) throw exception_time_error();
|
|
TEST_END(wMonth); SKIP('-');
|
|
PARSE( st.wDay, 2); if (st.wDay < 1 || st.wDay > 31) throw exception_time_error();
|
|
TEST_END(wDay); SKIP(' ');
|
|
PARSE( st.wHour, 2); if (st.wHour >= 24) throw exception_time_error();
|
|
TEST_END(wHour); SKIP(':');
|
|
PARSE( st.wMinute, 2); if (st.wMinute >= 60) throw exception_time_error();
|
|
TEST_END(wMinute); SKIP(':');
|
|
PARSE( st.wSecond, 2); if (st.wSecond >= 60) throw exception_time_error();
|
|
SKIP_SPACING();
|
|
TEST_END( wSecond );
|
|
#undef ADVANCE
|
|
#undef ADVANCE_TEST
|
|
#undef PARSE
|
|
#undef TEST_END
|
|
#undef SKIP
|
|
#undef SKIP_SPACING
|
|
if (remaining > 0) throw exception_time_error();
|
|
break;
|
|
}
|
|
t_filetimestamp base, out;
|
|
if (!SystemTimeToFileTime(&st, (FILETIME*) &base)) throw exception_time_error();
|
|
if (!LocalFileTimeToFileTime((const FILETIME*)&base, (FILETIME*)&out)) throw exception_time_error();
|
|
return out;
|
|
} catch(exception_time_error) {
|
|
return filetimestamp_invalid;
|
|
}
|
|
}
|
|
|
|
static const char g_invalidMsg[] = "<invalid timestamp>";
|
|
|
|
format_filetimestamp::format_filetimestamp(t_filetimestamp p_timestamp) {
|
|
try {
|
|
SYSTEMTIME st; FILETIME ft;
|
|
if (FileTimeToLocalFileTime((FILETIME*)&p_timestamp,&ft)) {
|
|
if (FileTimeToSystemTime(&ft,&st)) {
|
|
m_buffer
|
|
<< pfc::format_uint(st.wYear,4) << "-" << pfc::format_uint(st.wMonth,2) << "-" << pfc::format_uint(st.wDay,2) << " "
|
|
<< pfc::format_uint(st.wHour,2) << ":" << pfc::format_uint(st.wMinute,2) << ":" << pfc::format_uint(st.wSecond,2);
|
|
return;
|
|
}
|
|
}
|
|
} catch(...) {}
|
|
m_buffer = g_invalidMsg;
|
|
}
|
|
|
|
format_filetimestamp_utc::format_filetimestamp_utc(t_filetimestamp p_timestamp) {
|
|
try {
|
|
SYSTEMTIME st;
|
|
if (FileTimeToSystemTime((const FILETIME*)&p_timestamp,&st)) {
|
|
m_buffer
|
|
<< pfc::format_uint(st.wYear,4) << "-" << pfc::format_uint(st.wMonth,2) << "-" << pfc::format_uint(st.wDay,2) << " "
|
|
<< pfc::format_uint(st.wHour,2) << ":" << pfc::format_uint(st.wMinute,2) << ":" << pfc::format_uint(st.wSecond,2);
|
|
return;
|
|
}
|
|
} catch(...) {}
|
|
m_buffer = g_invalidMsg;
|
|
}
|