Fastboyz
Fastboyz

Reputation: 49

ctime_r on MSVC

I have this function, it will compile just fine if I am using g++. the problem is I have to use windows compiler, and it does not have ctime_r. I am a little bit new in C/C++. can anyone help me make this work with MSVC cl.exe?

The function:

void leaveWorld(const WorldDescription& desc)
{
    std::ostringstream os;
    const time_t current_date(time(0));
    char current_date_string[27];
    const size_t n = strlen(ctime_r(&current_date,current_date_string));
    if (n) {
        current_date_string[n-1] = '\0'; // remove the ending \n
    } else {
        current_date_string[0] = '\0'; // just in case...
    }
    os << totaltime;
    (*_o) << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" << endl;
    (*_o) << "<testsuite name=\"" << desc.worldName() << "\" ";
    (*_o) << "date=\"" << current_date_string;
    (*_o) << "\" tests=\"" << ntests
          << "\" errors=\"" << nerror
          << "\" failures=\"" << nfail
          << "\" time=\"" << os.str().c_str() << "\" >";
    _o->endl(*_o);
    (*_o) << _os->str().c_str();
    _os->clear();
    (*_o) << "</testsuite>" << endl;
    _o->flush();
}

Upvotes: 2

Views: 1692

Answers (2)

Yogev Neumann
Yogev Neumann

Reputation: 2231

I prefer macros, so you can use the same code on the two platforms.

#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#  define ctime_r(t, b) ctime_s(b, sizeof(b), t)
#endif /* _WIN32 || _WIN64 || __CYGWIN__ */

If you care about the return value, from the signature of the two functions:

char *ctime_r(const time_t *timep, char *buf);
errno_t ctime_s(char* buffer, size_t numberOfElements, const time_t *sourceTime);

You can write something like this:

#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#  define my_ctime_r(t, b) (0 == ctime_s(b, sizeof(b), t))
#else
#  define my_ctime_r(t, b) (NULL != ctime_s(b, sizeof(b), t))
#endif /* !_WIN32 && !_WIN64 && !__CYGWIN__ */

This will unify the return value of my_ctime_r(), return 1 if success and 0 if failed.

Upvotes: 0

Mats Petersson
Mats Petersson

Reputation: 129474

In MS library, there is a ctime_s, which allows for the same "not using a global" feature that ctime_r has in Linux/Unix OS's. You will probably have to wrap it like this:

const char *my_ctime_r(char *buffer, size_t bufsize, time_t cur_time)
{
#if WINDOWS
    errno_t e = ctime_s(buffer, bufsize, cur_time);
    assert(e == 0 && "Huh? ctime_s returned an error");
    return buffer;
#else 
    const char *res = ctime_r(buffer, cur_time);
    assert(res != NULL && "ctime_r failed...");
    return res;
#endif
}

Upvotes: 2

Related Questions