-
Notifications
You must be signed in to change notification settings - Fork 272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gimesketvirtadien's time requested changes #104
Changes from 17 commits
c9cee5d
2a632ff
0096d37
0f07288
fd8c3ed
ebcd6f7
8f449b0
b6fe945
000e382
50487bf
3d40861
73947c3
cfaffe3
4f8c7bd
141d955
03fc0e9
985ca75
59e00d5
4dc5580
bd9fd04
38b87b1
72e18de
12a5977
fe560ad
60c0081
2d4e900
b825886
f1439d3
3b90e26
e6c66c5
0c05e29
9d06bdd
af96b55
10bc655
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -117,9 +117,6 @@ namespace g3 { | |
} | ||
|
||
|
||
|
||
|
||
|
||
namespace internal { | ||
|
||
bool isLoggingInitialized() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,17 +2,53 @@ | |
* 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes | ||
* with no warranties. This code is yours to share, use and modify with no | ||
* strings attached and no restrictions or obligations. | ||
* | ||
* | ||
* For more information see g3log/LICENSE or refer refer to http://unlicense.org | ||
* ============================================================================*/ | ||
|
||
#include "g3log/time.hpp" | ||
|
||
#include <sstream> | ||
#include <string> | ||
#include <cstring> | ||
#include <cmath> | ||
#include <chrono> | ||
#include <cassert> | ||
#include <iomanip> | ||
#ifdef __MACH__ | ||
#include <sys/time.h> | ||
#endif | ||
|
||
|
||
namespace { | ||
const size_t kMsDigitsToCut = 1000000; // 3 digits left of 1000 000 000 | ||
const size_t kUsDigitsToCut = 1000; // 6 digits left | ||
const size_t kNsDigitsToCut = 1; // all digits left : divide by 1 | ||
const size_t kNsDefaultDigits = 0; | ||
const size_t kDigitIdentifier = 1; | ||
const size_t kNoDigitIdentifier = 0; | ||
|
||
const std::string kIdentifier = "%f"; | ||
const size_t kIdentifierSize = 2; | ||
|
||
|
||
std::string fractional_to_string(size_t fractional, size_t cutOffDivider) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this has to be moved to the .h/cpp so that it can be put under test |
||
auto zeroes = 9; // default ns | ||
if (kMsDigitsToCut == cutOffDivider) { | ||
zeroes = 3; | ||
} else if (kUsDigitsToCut == cutOffDivider) { | ||
zeroes = 6; | ||
} else { | ||
cutOffDivider = 1; | ||
} | ||
fractional /= cutOffDivider; | ||
|
||
// auto value = std::to_string(typeAdjustedValue); | ||
// return value; // std::string(fractional_digit, '0') + value; | ||
auto value = std::string(std::to_string(fractional)); | ||
return std::string(zeroes - value.size(), '0') + value; | ||
} | ||
} // anonymous | ||
|
||
|
||
namespace g3 { | ||
|
@@ -21,21 +57,21 @@ namespace g3 { | |
// This is needed since latest version (at time of writing) of gcc4.7 does not implement this library function yet. | ||
// return value is SIMPLIFIED to only return a std::string | ||
|
||
std::string put_time(const struct tm *tmb, const char *c_time_format) { | ||
std::string put_time(const struct tm* tmb, const char* c_time_format) { | ||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(__MINGW32__) | ||
std::ostringstream oss; | ||
oss.fill('0'); | ||
// BOGUS hack done for VS2012: C++11 non-conformant since it SHOULD take a "const struct tm* " | ||
oss << std::put_time(const_cast<struct tm *> (tmb), c_time_format); | ||
oss << std::put_time(const_cast<struct tm*> (tmb), c_time_format); | ||
return oss.str(); | ||
#else // LINUX | ||
const size_t size = 1024; | ||
char buffer[size]; // IMPORTANT: check now and then for when gcc will implement std::put_time. | ||
// ... also ... This is way more buffer space then we need | ||
|
||
auto success = std::strftime(buffer, size, c_time_format, tmb); | ||
if (0 == success) | ||
{ | ||
// TODO: incorrect code | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove erroneous comment There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider replacing the assert to something that will tricker process exit even for production code. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No code change but added a comment so that code readers that have not seen this pattern before will be less baffled by it. It is essentially a way of exiting with a clear message in debug mode. In production mode a safe value is instead returned. |
||
if (0 == success) { | ||
assert((0 != success) && "strftime fails with illegal formatting"); | ||
return c_time_format; | ||
} | ||
|
@@ -55,7 +91,33 @@ namespace g3 { | |
return std::chrono::system_clock::to_time_t(system_now); | ||
} | ||
|
||
tm localtime(const std::time_t &time) { | ||
|
||
int timespec_get(struct timespec* ts/*, int base*/) { | ||
#ifdef __MACH__ | ||
// std::timespec_get or posix clock_gettime)(...) are not | ||
// implemented on OSX | ||
// @return value of base if successful, else zero | ||
struct timeval now = {}; | ||
int rv = gettimeofday(&now, nullptr); | ||
if (-1 == rv) { | ||
return rv; | ||
} | ||
// error mode. just return sec, microsecond | ||
ts->tv_sec = now.tv_sec; | ||
ts->tv_nsec = now.tv_usec * 1000; | ||
return 0; | ||
#else | ||
// Linux | ||
return std::timespec_get(ts, TIME_UTC)); | ||
#endif | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
tm localtime(const std::time_t& time) { | ||
struct tm tm_snapshot; | ||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) && !defined(__GNUC__)) | ||
localtime_s(&tm_snapshot, &time); // windsows | ||
|
@@ -65,11 +127,40 @@ namespace g3 { | |
return tm_snapshot; | ||
} | ||
|
||
/// returns a std::string with content of time_t as localtime formatted by input format string | ||
/// * format string must conform to std::put_time | ||
/// This is similar to std::put_time(std::localtime(std::time_t*), time_format.c_str()); | ||
|
||
std::string localtime_formatted(const std::time_t &time_snapshot, const std::string &time_format) { | ||
|
||
size_t fractional_cutoff(const std::string& format_buffer, size_t pos) { | ||
char ch = (format_buffer.size() > pos + kIdentifierSize ? format_buffer.at(pos + kIdentifierSize) : '\0'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. make testable |
||
size_t cutOff = 0; | ||
switch (ch) { | ||
case '3': cutOff = kMsDigitsToCut; break; | ||
case '6': cutOff = kUsDigitsToCut; break; | ||
case '9': cutOff = kNsDigitsToCut; break; | ||
default: cutOff = kNsDefaultDigits; break; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider instead |
||
} | ||
return cutOff; | ||
} | ||
|
||
|
||
std::string localtime_formatted(const timespec& time_snapshot, const std::string& time_format) { | ||
auto format_buffer = time_format; // copying format string to a separate buffer | ||
|
||
// iterating through every "%f" instance in the format string | ||
auto identifierExtraSize = 0; | ||
for (size_t pos = 0; (pos = format_buffer.find(kIdentifier, pos)) != std::string::npos; pos += kIdentifierSize + identifierExtraSize) { | ||
// figuring out whether this is nano, micro or milli identifier | ||
auto cutoff = fractional_cutoff(format_buffer, pos); | ||
auto value = fractional_to_string(time_snapshot.tv_nsec, cutoff); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider having the function which makes more sense |
||
auto identifierExtraSize = cutoff == kNsDefaultDigits ? kNoDigitIdentifier : kDigitIdentifier; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. go through naming |
||
|
||
// replacing "%f[3|6|9]" with sec fractional part value | ||
format_buffer.replace(pos, kIdentifier.size() + identifierExtraSize, value); | ||
} | ||
|
||
return localtime_formatted(time_snapshot.tv_sec, format_buffer); | ||
} | ||
|
||
std::string localtime_formatted(const std::time_t& time_snapshot, const std::string& time_format) { | ||
std::tm t = localtime(time_snapshot); // could be const, but cannot due to VS2012 is non conformant for C++11's std::put_time (see above) | ||
return g3::internal::put_time(&t, time_format.c_str()); // format example: //"%Y/%m/%d %H:%M:%S"); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
think about the naming + what is needed to be here and what can be defined static namespace or in the function?