bitz-server  2.0.0
time.h
1 /*
2  Formatting library for C++ - time formatting
3 
4  Copyright (c) 2012 - 2016, Victor Zverovich
5  All rights reserved.
6 
7  For the license information refer to format.h.
8  */
9 
10 #ifndef FMT_TIME_H_
11 #define FMT_TIME_H_
12 
13 #include "format.h"
14 #include <ctime>
15 
16 #ifdef _MSC_VER
17 #pragma warning(push)
18 #pragma warning(disable : 4702) // unreachable code
19 #pragma warning(disable : 4996) // "deprecated" functions
20 #endif
21 
22 namespace fmt {
23 template<typename ArgFormatter>
24 void format_arg(BasicFormatter<char, ArgFormatter> &f, const char *&format_str, const std::tm &tm)
25 {
26  if (*format_str == ':')
27  ++format_str;
28  const char *end = format_str;
29  while (*end && *end != '}')
30  ++end;
31  if (*end != '}')
32  FMT_THROW(FormatError("missing '}' in format string"));
33  internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> format;
34  format.append(format_str, end + 1);
35  format[format.size() - 1] = '\0';
36  Buffer<char> &buffer = f.writer().buffer();
37  std::size_t start = buffer.size();
38  for (;;)
39  {
40  std::size_t size = buffer.capacity() - start;
41  std::size_t count = std::strftime(&buffer[start], size, &format[0], &tm);
42  if (count != 0)
43  {
44  buffer.resize(start + count);
45  break;
46  }
47  if (size >= format.size() * 256)
48  {
49  // If the buffer is 256 times larger than the format string, assume
50  // that `strftime` gives an empty result. There doesn't seem to be a
51  // better way to distinguish the two cases:
52  // https://github.com/fmtlib/fmt/issues/367
53  break;
54  }
55  const std::size_t MIN_GROWTH = 10;
56  buffer.reserve(buffer.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
57  }
58  format_str = end + 1;
59 }
60 
61 namespace internal {
62 inline Null<> localtime_r(...)
63 {
64  return Null<>();
65 }
66 inline Null<> localtime_s(...)
67 {
68  return Null<>();
69 }
70 inline Null<> gmtime_r(...)
71 {
72  return Null<>();
73 }
74 inline Null<> gmtime_s(...)
75 {
76  return Null<>();
77 }
78 } // namespace internal
79 
80 // Thread-safe replacement for std::localtime
81 inline std::tm localtime(std::time_t time)
82 {
83  struct LocalTime
84  {
85  std::time_t time_;
86  std::tm tm_;
87 
88  LocalTime(std::time_t t)
89  : time_(t)
90  {
91  }
92 
93  bool run()
94  {
95  using namespace fmt::internal;
96  return handle(localtime_r(&time_, &tm_));
97  }
98 
99  bool handle(std::tm *tm)
100  {
101  return tm != FMT_NULL;
102  }
103 
104  bool handle(internal::Null<>)
105  {
106  using namespace fmt::internal;
107  return fallback(localtime_s(&tm_, &time_));
108  }
109 
110  bool fallback(int res)
111  {
112  return res == 0;
113  }
114 
115  bool fallback(internal::Null<>)
116  {
117  using namespace fmt::internal;
118  std::tm *tm = std::localtime(&time_);
119  if (tm)
120  tm_ = *tm;
121  return tm != FMT_NULL;
122  }
123  };
124  LocalTime lt(time);
125  if (lt.run())
126  return lt.tm_;
127  // Too big time values may be unsupported.
128  FMT_THROW(fmt::FormatError("time_t value out of range"));
129  return std::tm();
130 }
131 
132 // Thread-safe replacement for std::gmtime
133 inline std::tm gmtime(std::time_t time)
134 {
135  struct GMTime
136  {
137  std::time_t time_;
138  std::tm tm_;
139 
140  GMTime(std::time_t t)
141  : time_(t)
142  {
143  }
144 
145  bool run()
146  {
147  using namespace fmt::internal;
148  return handle(gmtime_r(&time_, &tm_));
149  }
150 
151  bool handle(std::tm *tm)
152  {
153  return tm != FMT_NULL;
154  }
155 
156  bool handle(internal::Null<>)
157  {
158  using namespace fmt::internal;
159  return fallback(gmtime_s(&tm_, &time_));
160  }
161 
162  bool fallback(int res)
163  {
164  return res == 0;
165  }
166 
167  bool fallback(internal::Null<>)
168  {
169  std::tm *tm = std::gmtime(&time_);
170  if (tm != FMT_NULL)
171  tm_ = *tm;
172  return tm != FMT_NULL;
173  }
174  };
175  GMTime gt(time);
176  if (gt.run())
177  return gt.tm_;
178  // Too big time values may be unsupported.
179  FMT_THROW(fmt::FormatError("time_t value out of range"));
180  return std::tm();
181 }
182 } // namespace fmt
183 
184 #ifdef _MSC_VER
185 #pragma warning(pop)
186 #endif
187 
188 #endif // FMT_TIME_H_
Definition: format.h:400
Definition: format.h:739
Definition: format.cc:84