1
0
forked from 0ad/0ad

swscanf is an insane mess of bugs and incompatibilities, so stop using it for fancy parsing

This was SVN commit r7800.
This commit is contained in:
Ykkrosh 2010-07-24 20:48:18 +00:00
parent bc704b288a
commit bfcb278bf0

View File

@ -54,32 +54,34 @@ TraceEntry::TraceEntry(EAction action, const fs::wpath& pathname, size_t size)
TraceEntry::TraceEntry(const std::wstring& text)
{
wchar_t pathname[PATH_MAX+1] = L""; // includes space for terminator
// swscanf is far too awkward to get working cross-platform,
// so use iostreams here instead
wchar_t dummy;
wchar_t action;
#if EMULATE_SECURE_CRT
// The desired code:
// #define TRACE_FORMAT L"%f: %lc \"%" STRINGIZE(PATH_MAX) "l[^\"]\" %zd\n" /* use a macro to allow compile-time type-checking */
// const int fieldsRead = swscanf(text.c_str(), TRACE_FORMAT, &m_timestamp, &action, pathname, &m_size);
// but that hits http://sources.redhat.com/bugzilla/show_bug.cgi?id=5225 and crashes on glibc 2.7
// We need to avoid reading any numbers after the %[]
#define TRACE_FORMAT_1 L"%f: %lc \"%" STRINGIZE(PATH_MAX) "l[^\"]\" %n"
#define TRACE_FORMAT_2 L"%zd\n"
int charsRead = 0;
int fieldsRead = swscanf(text.c_str(), TRACE_FORMAT_1, &m_timestamp, &action, pathname, &charsRead);
debug_assert(fieldsRead == 3);
if (fieldsRead == 3) // first part parsed okay
{
fieldsRead = swscanf(text.c_str() + charsRead, TRACE_FORMAT_2, &m_size);
debug_assert(fieldsRead == 1);
}
#else
#define TRACE_FORMAT L"%f: %lc \"%l[^\"]\" %d\n"
const int fieldsRead = swscanf_s(text.c_str(), TRACE_FORMAT, &m_timestamp, &action, 1, pathname, ARRAY_SIZE(pathname), &m_size);
debug_assert(fieldsRead == 4);
#endif
std::wstringstream stream(text);
stream >> m_timestamp;
stream >> dummy;
debug_assert(dummy == ':');
stream >> action;
debug_assert(action == 'L' || action == 'S');
m_action = (EAction)action;
stream >> dummy;
debug_assert(dummy == '"');
std::wstring pathname;
std::getline(stream, pathname, L'"');
m_pathname = pathname;
stream >> m_size;
debug_assert(stream.get() == '\n');
debug_assert(stream.good());
debug_assert((int)stream.get() == EOF);
}