source: trunk/GDE/SINA/builddir/include/spdlog/fmt/bundled/time.h

Last change on this file was 19170, checked in by westram, 2 years ago
  • sina source
    • unpack + remove tarball
    • no longer ignore sina builddir.
File size: 4.2 KB
Line 
1// Formatting library for C++ - time formatting
2//
3// Copyright (c) 2012 - present, Victor Zverovich
4// All rights reserved.
5//
6// For the license information refer to format.h.
7
8#ifndef FMT_TIME_H_
9#define FMT_TIME_H_
10
11#include "format.h"
12#include <ctime>
13#include <locale>
14
15FMT_BEGIN_NAMESPACE
16
17// Prevents expansion of a preceding token as a function-style macro.
18// Usage: f FMT_NOMACRO()
19#define FMT_NOMACRO
20
21namespace internal{
22inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); }
23inline null<> localtime_s(...) { return null<>(); }
24inline null<> gmtime_r(...) { return null<>(); }
25inline null<> gmtime_s(...) { return null<>(); }
26}  // namespace internal
27
28// Thread-safe replacement for std::localtime
29inline std::tm localtime(std::time_t time) {
30  struct dispatcher {
31    std::time_t time_;
32    std::tm tm_;
33
34    dispatcher(std::time_t t): time_(t) {}
35
36    bool run() {
37      using namespace fmt::internal;
38      return handle(localtime_r(&time_, &tm_));
39    }
40
41    bool handle(std::tm *tm) { return tm != FMT_NULL; }
42
43    bool handle(internal::null<>) {
44      using namespace fmt::internal;
45      return fallback(localtime_s(&tm_, &time_));
46    }
47
48    bool fallback(int res) { return res == 0; }
49
50#if !FMT_MSC_VER
51    bool fallback(internal::null<>) {
52      using namespace fmt::internal;
53      std::tm *tm = std::localtime(&time_);
54      if (tm) tm_ = *tm;
55      return tm != FMT_NULL;
56    }
57#endif
58  };
59  dispatcher lt(time);
60  // Too big time values may be unsupported.
61  if (!lt.run())
62    FMT_THROW(format_error("time_t value out of range"));
63  return lt.tm_;
64}
65
66// Thread-safe replacement for std::gmtime
67inline std::tm gmtime(std::time_t time) {
68  struct dispatcher {
69    std::time_t time_;
70    std::tm tm_;
71
72    dispatcher(std::time_t t): time_(t) {}
73
74    bool run() {
75      using namespace fmt::internal;
76      return handle(gmtime_r(&time_, &tm_));
77    }
78
79    bool handle(std::tm *tm) { return tm != FMT_NULL; }
80
81    bool handle(internal::null<>) {
82      using namespace fmt::internal;
83      return fallback(gmtime_s(&tm_, &time_));
84    }
85
86    bool fallback(int res) { return res == 0; }
87
88#if !FMT_MSC_VER
89    bool fallback(internal::null<>) {
90      std::tm *tm = std::gmtime(&time_);
91      if (tm) tm_ = *tm;
92      return tm != FMT_NULL;
93    }
94#endif
95  };
96  dispatcher gt(time);
97  // Too big time values may be unsupported.
98  if (!gt.run())
99    FMT_THROW(format_error("time_t value out of range"));
100  return gt.tm_;
101}
102
103namespace internal {
104inline std::size_t strftime(char *str, std::size_t count, const char *format,
105                            const std::tm *time) {
106  return std::strftime(str, count, format, time);
107}
108
109inline std::size_t strftime(wchar_t *str, std::size_t count,
110                            const wchar_t *format, const std::tm *time) {
111  return std::wcsftime(str, count, format, time);
112}
113}
114
115template <typename Char>
116struct formatter<std::tm, Char> {
117  template <typename ParseContext>
118  auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
119    auto it = ctx.begin();
120    if (it != ctx.end() && *it == ':')
121      ++it;
122    auto end = it;
123    while (end != ctx.end() && *end != '}')
124      ++end;
125    tm_format.reserve(internal::to_unsigned(end - it + 1));
126    tm_format.append(it, end);
127    tm_format.push_back('\0');
128    return end;
129  }
130
131  template <typename FormatContext>
132  auto format(const std::tm &tm, FormatContext &ctx) -> decltype(ctx.out()) {
133    basic_memory_buffer<Char> buf;
134    std::size_t start = buf.size();
135    for (;;) {
136      std::size_t size = buf.capacity() - start;
137      std::size_t count =
138        internal::strftime(&buf[start], size, &tm_format[0], &tm);
139      if (count != 0) {
140        buf.resize(start + count);
141        break;
142      }
143      if (size >= tm_format.size() * 256) {
144        // If the buffer is 256 times larger than the format string, assume
145        // that `strftime` gives an empty result. There doesn't seem to be a
146        // better way to distinguish the two cases:
147        // https://github.com/fmtlib/fmt/issues/367
148        break;
149      }
150      const std::size_t MIN_GROWTH = 10;
151      buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
152    }
153    return std::copy(buf.begin(), buf.end(), ctx.out());
154  }
155
156  basic_memory_buffer<Char> tm_format;
157};
158FMT_END_NAMESPACE
159
160#endif  // FMT_TIME_H_
Note: See TracBrowser for help on using the repository browser.