Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
S
spdlog
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
spdlog
Commits
cdbf2e36
Commit
cdbf2e36
authored
Jun 12, 2018
by
gabime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Upgrade to fmt 5.x
parent
378c7789
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
138 additions
and
2418 deletions
+138
-2418
common.h
include/spdlog/common.h
+3
-3
log_msg.h
include/spdlog/details/log_msg.h
+2
-2
logger_impl.h
include/spdlog/details/logger_impl.h
+3
-8
pattern_formatter_impl.h
include/spdlog/details/pattern_formatter_impl.h
+107
-67
thread_pool.h
include/spdlog/details/thread_pool.h
+3
-5
format.cc
include/spdlog/fmt/bundled/format.cc
+0
-495
format.h
include/spdlog/fmt/bundled/format.h
+0
-0
ostream.cc
include/spdlog/fmt/bundled/ostream.cc
+0
-35
ostream.h
include/spdlog/fmt/bundled/ostream.h
+0
-117
posix.cc
include/spdlog/fmt/bundled/posix.cc
+0
-241
posix.h
include/spdlog/fmt/bundled/posix.h
+0
-423
printf.cc
include/spdlog/fmt/bundled/printf.cc
+0
-32
printf.h
include/spdlog/fmt/bundled/printf.h
+0
-723
time.h
include/spdlog/fmt/bundled/time.h
+0
-188
fmt.h
include/spdlog/fmt/fmt.h
+3
-8
daily_file_sink.h
include/spdlog/sinks/daily_file_sink.h
+7
-7
rotating_file_sink.h
include/spdlog/sinks/rotating_file_sink.h
+4
-4
syslog_sink.h
include/spdlog/sinks/syslog_sink.h
+1
-1
Makefile
tests/Makefile
+1
-7
errors.cpp
tests/errors.cpp
+1
-13
file_log.cpp
tests/file_log.cpp
+3
-30
test_macros.cpp
tests/test_macros.cpp
+0
-7
tests.sln
tests/tests.sln
+0
-2
No files found.
include/spdlog/common.h
View file @
cdbf2e36
...
...
@@ -158,9 +158,9 @@ public:
spdlog_ex
(
const
std
::
string
&
msg
,
int
last_errno
)
{
fmt
::
MemoryWriter
writer
;
fmt
::
format_system_error
(
writer
,
last_errno
,
msg
);
_msg
=
writer
.
str
(
);
fmt
::
memory_buffer
buf
;
fmt
::
format_system_error
(
buf
,
last_errno
,
msg
);
_msg
=
fmt
::
to_string
(
buf
);
}
const
char
*
what
()
const
SPDLOG_NOEXCEPT
override
...
...
include/spdlog/details/log_msg.h
View file @
cdbf2e36
...
...
@@ -37,8 +37,8 @@ struct log_msg
level
::
level_enum
level
;
log_clock
::
time_point
time
;
size_t
thread_id
;
fmt
::
MemoryWrit
er
raw
;
fmt
::
MemoryWrit
er
formatted
;
fmt
::
memory_buff
er
raw
;
fmt
::
memory_buff
er
formatted
;
size_t
msg_id
{
0
};
// info about wrapping the formatted text with color
size_t
color_range_start
{
0
};
...
...
include/spdlog/details/logger_impl.h
View file @
cdbf2e36
...
...
@@ -58,12 +58,7 @@ inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Ar
try
{
details
::
log_msg
log_msg
(
&
name_
,
lvl
);
#if defined(SPDLOG_FMT_PRINTF)
fmt
::
printf
(
log_msg
.
raw
,
fmt
,
args
...);
#else
log_msg
.
raw
.
write
(
fmt
,
args
...);
#endif
fmt
::
format_to
(
log_msg
.
raw
,
fmt
,
args
...);
sink_it_
(
log_msg
);
}
SPDLOG_CATCH_AND_HANDLE
...
...
@@ -79,7 +74,7 @@ inline void spdlog::logger::log(level::level_enum lvl, const char *msg)
try
{
details
::
log_msg
log_msg
(
&
name_
,
lvl
);
log_msg
.
raw
<<
msg
;
fmt
::
format_to
(
log_msg
.
raw
,
"{}"
,
msg
)
;
sink_it_
(
log_msg
);
}
SPDLOG_CATCH_AND_HANDLE
...
...
@@ -95,7 +90,7 @@ inline void spdlog::logger::log(level::level_enum lvl, const T &msg)
try
{
details
::
log_msg
log_msg
(
&
name_
,
lvl
);
log_msg
.
raw
<<
msg
;
fmt
::
format_to
(
log_msg
.
raw
,
"{}"
,
msg
)
;
sink_it_
(
log_msg
);
}
SPDLOG_CATCH_AND_HANDLE
...
...
include/spdlog/details/pattern_formatter_impl.h
View file @
cdbf2e36
...
...
@@ -20,8 +20,23 @@
#include <utility>
#include <vector>
namespace
{
inline
void
append_str
(
const
std
::
string
&
str
,
fmt
::
memory_buffer
&
dest
)
{
const
char
*
str_ptr
=
str
.
data
();
dest
.
append
(
str_ptr
,
str_ptr
+
str
.
size
());
}
inline
void
append_buf
(
const
fmt
::
memory_buffer
&
buf
,
fmt
::
memory_buffer
&
dest
)
{
const
char
*
buf_ptr
=
buf
.
data
();
dest
.
append
(
buf_ptr
,
buf_ptr
+
buf
.
size
());
}
}
// namespace
namespace
spdlog
{
namespace
details
{
class
flag_formatter
{
public
:
...
...
@@ -36,7 +51,8 @@ class name_formatter : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
)
override
{
msg
.
formatted
<<
*
msg
.
logger_name
;
// fmt::format_to(msg.formatted, *msg.logger_name);
append_str
(
*
msg
.
logger_name
,
msg
.
formatted
);
}
};
...
...
@@ -45,7 +61,9 @@ class level_formatter : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
)
override
{
msg
.
formatted
<<
level
::
to_str
(
msg
.
level
);
// msg.formatted << level::to_str(msg.level);
auto
level_str
=
level
::
to_str
(
msg
.
level
);
fmt
::
format_to
(
msg
.
formatted
,
"{}"
,
level_str
);
}
};
...
...
@@ -54,7 +72,9 @@ class short_level_formatter : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
)
override
{
msg
.
formatted
<<
level
::
to_short_str
(
msg
.
level
);
// msg.formatted << level::to_short_str(msg.level);
auto
level_str
=
level
::
to_short_str
(
msg
.
level
);
fmt
::
format_to
(
msg
.
formatted
,
"{}"
,
level_str
);
}
};
...
...
@@ -78,7 +98,8 @@ class a_formatter : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
days
[
tm_time
.
tm_wday
];
// msg.formatted << days[tm_time.tm_wday];
fmt
::
format_to
(
msg
.
formatted
,
"{}"
,
days
[
tm_time
.
tm_wday
]);
}
};
...
...
@@ -88,7 +109,8 @@ class A_formatter : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
full_days
[
tm_time
.
tm_wday
];
// msg.formatted << full_days[tm_time.tm_wday];
fmt
::
format_to
(
msg
.
formatted
,
"{}"
,
full_days
[
tm_time
.
tm_wday
]);
}
};
...
...
@@ -98,7 +120,8 @@ class b_formatter : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
months
[
tm_time
.
tm_mon
];
// msg.formatted << months[tm_time.tm_mon];
append_str
(
months
[
tm_time
.
tm_mon
],
msg
.
formatted
);
}
};
...
...
@@ -109,31 +132,21 @@ class B_formatter : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
full_months
[
tm_time
.
tm_mon
];
// msg.formatted << full_months[tm_time.tm_mon];
append_str
(
full_months
[
tm_time
.
tm_mon
],
msg
.
formatted
);
}
};
// write 2 ints separated by sep with padding of 2
static
fmt
::
MemoryWriter
&
pad_n_join
(
fmt
::
MemoryWriter
&
w
,
int
v1
,
int
v2
,
char
sep
)
{
w
<<
fmt
::
pad
(
v1
,
2
,
'0'
)
<<
sep
<<
fmt
::
pad
(
v2
,
2
,
'0'
);
return
w
;
}
// write 3 ints separated by sep with padding of 2
static
fmt
::
MemoryWriter
&
pad_n_join
(
fmt
::
MemoryWriter
&
w
,
int
v1
,
int
v2
,
int
v3
,
char
sep
)
{
w
<<
fmt
::
pad
(
v1
,
2
,
'0'
)
<<
sep
<<
fmt
::
pad
(
v2
,
2
,
'0'
)
<<
sep
<<
fmt
::
pad
(
v3
,
2
,
'0'
);
return
w
;
}
// Date and time representation (Thu Aug 23 15:35:46 2014)
class
c_formatter
SPDLOG_FINAL
:
public
flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
days
[
tm_time
.
tm_wday
]
<<
' '
<<
months
[
tm_time
.
tm_mon
]
<<
' '
<<
tm_time
.
tm_mday
<<
' '
;
pad_n_join
(
msg
.
formatted
,
tm_time
.
tm_hour
,
tm_time
.
tm_min
,
tm_time
.
tm_sec
,
':'
)
<<
' '
<<
tm_time
.
tm_year
+
1900
;
// msg.formatted << days[tm_time.tm_wday] << ' ' << months[tm_time.tm_mon] << ' ' << tm_time.tm_mday << ' ';
// pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << tm_time.tm_year + 1900;
fmt
::
format_to
(
msg
.
formatted
,
"{} {} {} {:02}:{:02}:{:02} {}"
,
days
[
tm_time
.
tm_wday
],
months
[
tm_time
.
tm_mon
],
tm_time
.
tm_mday
,
tm_time
.
tm_hour
,
tm_time
.
tm_min
,
tm_time
.
tm_sec
,
tm_time
.
tm_year
+
1900
);
}
};
...
...
@@ -142,7 +155,8 @@ class C_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
fmt
::
pad
(
tm_time
.
tm_year
%
100
,
2
,
'0'
);
// msg.formatted << fmt::pad(tm_time.tm_year % 100, 2, '0');
fmt
::
format_to
(
msg
.
formatted
,
"{:02}"
,
tm_time
.
tm_year
%
100
);
}
};
...
...
@@ -151,7 +165,8 @@ class D_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
pad_n_join
(
msg
.
formatted
,
tm_time
.
tm_mon
+
1
,
tm_time
.
tm_mday
,
tm_time
.
tm_year
%
100
,
'/'
);
// pad_n_join(msg.formatted, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_year % 100, '/');
fmt
::
format_to
(
msg
.
formatted
,
"{:02}/{:02}/{:02}"
,
tm_time
.
tm_mon
+
1
,
tm_time
.
tm_mday
,
tm_time
.
tm_year
%
100
);
}
};
...
...
@@ -160,7 +175,8 @@ class Y_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
tm_time
.
tm_year
+
1900
;
// msg.formatted << tm_time.tm_year + 1900;
fmt
::
format_to
(
msg
.
formatted
,
"{}"
,
tm_time
.
tm_year
+
1900
);
}
};
...
...
@@ -169,7 +185,8 @@ class m_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
fmt
::
pad
(
tm_time
.
tm_mon
+
1
,
2
,
'0'
);
// msg.formatted << fmt::pad(tm_time.tm_mon + 1, 2, '0');
fmt
::
format_to
(
msg
.
formatted
,
"{:02}"
,
tm_time
.
tm_mon
+
1
);
}
};
...
...
@@ -178,7 +195,8 @@ class d_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
fmt
::
pad
(
tm_time
.
tm_mday
,
2
,
'0'
);
// msg.formatted << fmt::pad(tm_time.tm_mday, 2, '0');
fmt
::
format_to
(
msg
.
formatted
,
"{:02}"
,
tm_time
.
tm_mday
);
}
};
...
...
@@ -187,7 +205,8 @@ class H_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
fmt
::
pad
(
tm_time
.
tm_hour
,
2
,
'0'
);
// msg.formatted << fmt::pad(tm_time.tm_hour, 2, '0');
fmt
::
format_to
(
msg
.
formatted
,
"{:02}"
,
tm_time
.
tm_hour
);
}
};
...
...
@@ -196,7 +215,8 @@ class I_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
fmt
::
pad
(
to12h
(
tm_time
),
2
,
'0'
);
// msg.formatted << fmt::pad(to12h(tm_time), 2, '0');
fmt
::
format_to
(
msg
.
formatted
,
"{:02}"
,
to12h
(
tm_time
));
}
};
...
...
@@ -205,7 +225,8 @@ class M_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
fmt
::
pad
(
tm_time
.
tm_min
,
2
,
'0'
);
// msg.formatted << fmt::pad(tm_time.tm_min, 2, '0');
fmt
::
format_to
(
msg
.
formatted
,
"{:02}"
,
tm_time
.
tm_min
);
}
};
...
...
@@ -214,7 +235,8 @@ class S_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
fmt
::
pad
(
tm_time
.
tm_sec
,
2
,
'0'
);
// msg.formatted << fmt::pad(tm_time.tm_sec, 2, '0');
fmt
::
format_to
(
msg
.
formatted
,
"{:02}"
,
tm_time
.
tm_sec
);
}
};
...
...
@@ -225,7 +247,8 @@ class e_formatter SPDLOG_FINAL : public flag_formatter
{
auto
duration
=
msg
.
time
.
time_since_epoch
();
auto
millis
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
milliseconds
>
(
duration
).
count
()
%
1000
;
msg
.
formatted
<<
fmt
::
pad
(
static_cast
<
int
>
(
millis
),
3
,
'0'
);
// msg.formatted << fmt::pad(static_cast<int>(millis), 3, '0');
fmt
::
format_to
(
msg
.
formatted
,
"{:03}"
,
static_cast
<
int
>
(
millis
));
}
};
...
...
@@ -236,7 +259,8 @@ class f_formatter SPDLOG_FINAL : public flag_formatter
{
auto
duration
=
msg
.
time
.
time_since_epoch
();
auto
micros
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
microseconds
>
(
duration
).
count
()
%
1000000
;
msg
.
formatted
<<
fmt
::
pad
(
static_cast
<
int
>
(
micros
),
6
,
'0'
);
// msg.formatted << fmt::pad(static_cast<int>(micros), 6, '0');
fmt
::
format_to
(
msg
.
formatted
,
"{:06}"
,
static_cast
<
int
>
(
micros
));
}
};
...
...
@@ -247,7 +271,8 @@ class F_formatter SPDLOG_FINAL : public flag_formatter
{
auto
duration
=
msg
.
time
.
time_since_epoch
();
auto
ns
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
nanoseconds
>
(
duration
).
count
()
%
1000000000
;
msg
.
formatted
<<
fmt
::
pad
(
static_cast
<
int
>
(
ns
),
9
,
'0'
);
// msg.formatted << fmt::pad(static_cast<int>(ns), 9, '0');
fmt
::
format_to
(
msg
.
formatted
,
"{:06}"
,
static_cast
<
int
>
(
ns
));
}
};
...
...
@@ -257,7 +282,8 @@ class E_formatter SPDLOG_FINAL : public flag_formatter
{
auto
duration
=
msg
.
time
.
time_since_epoch
();
auto
seconds
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
seconds
>
(
duration
).
count
();
msg
.
formatted
<<
seconds
;
// msg.formatted << seconds;
fmt
::
format_to
(
msg
.
formatted
,
"{}"
,
seconds
);
}
};
...
...
@@ -266,7 +292,8 @@ class p_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
msg
.
formatted
<<
ampm
(
tm_time
);
// msg.formatted << ampm(tm_time);
fmt
::
format_to
(
msg
.
formatted
,
"{}"
,
ampm
(
tm_time
));
}
};
...
...
@@ -275,7 +302,8 @@ class r_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
pad_n_join
(
msg
.
formatted
,
to12h
(
tm_time
),
tm_time
.
tm_min
,
tm_time
.
tm_sec
,
':'
)
<<
' '
<<
ampm
(
tm_time
);
// pad_n_join(msg.formatted, to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << ampm(tm_time);
fmt
::
format_to
(
msg
.
formatted
,
"{:02}:{:02}:{02} {}"
,
tm_time
.
tm_min
,
tm_time
.
tm_sec
,
ampm
(
tm_time
));
}
};
...
...
@@ -284,7 +312,8 @@ class R_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
pad_n_join
(
msg
.
formatted
,
tm_time
.
tm_hour
,
tm_time
.
tm_min
,
':'
);
// pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, ':');
fmt
::
format_to
(
msg
.
formatted
,
"{:02}:{:02}"
,
tm_time
.
tm_hour
,
tm_time
.
tm_min
);
}
};
...
...
@@ -293,7 +322,8 @@ class T_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
tm_time
)
override
{
pad_n_join
(
msg
.
formatted
,
tm_time
.
tm_hour
,
tm_time
.
tm_min
,
tm_time
.
tm_sec
,
':'
);
// pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':');
fmt
::
format_to
(
msg
.
formatted
,
"{:02}:{:02}"
,
tm_time
.
tm_min
,
tm_time
.
tm_sec
);
}
};
...
...
@@ -330,8 +360,9 @@ public:
int
h
=
total_minutes
/
60
;
int
m
=
total_minutes
%
60
;
msg
.
formatted
<<
sign
;
pad_n_join
(
msg
.
formatted
,
h
,
m
,
':'
);
// msg.formatted << sign;
// pad_n_join(msg.formatted, h, m, ':');
fmt
::
format_to
(
msg
.
formatted
,
"{}{:02}:{:02}"
,
sign
,
h
,
m
);
}
private
:
...
...
@@ -356,7 +387,8 @@ class t_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
)
override
{
msg
.
formatted
<<
msg
.
thread_id
;
// msg.formatted << msg.thread_id;
fmt
::
format_to
(
msg
.
formatted
,
"{}"
,
msg
.
thread_id
);
}
};
...
...
@@ -365,7 +397,8 @@ class pid_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
)
override
{
msg
.
formatted
<<
details
::
os
::
pid
();
// msg.formatted << details::os::pid();
fmt
::
format_to
(
msg
.
formatted
,
"{}"
,
details
::
os
::
pid
());
}
};
...
...
@@ -374,7 +407,8 @@ class i_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
)
override
{
msg
.
formatted
<<
fmt
::
pad
(
msg
.
msg_id
,
6
,
'0'
);
// msg.formatted << fmt::pad(msg.msg_id, 6, '0');
fmt
::
format_to
(
msg
.
formatted
,
"{:06}"
,
msg
.
msg_id
);
}
};
...
...
@@ -382,7 +416,8 @@ class v_formatter SPDLOG_FINAL : public flag_formatter
{
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
)
override
{
msg
.
formatted
<<
fmt
::
StringRef
(
msg
.
raw
.
data
(),
msg
.
raw
.
size
());
// msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size());
append_buf
(
msg
.
raw
,
msg
.
formatted
);
}
};
...
...
@@ -395,7 +430,8 @@ public:
}
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
)
override
{
msg
.
formatted
<<
ch_
;
// msg.formatted << ch_;
msg
.
formatted
.
push_back
(
ch_
);
}
private
:
...
...
@@ -414,7 +450,8 @@ public:
}
void
format
(
details
::
log_msg
&
msg
,
const
std
::
tm
&
)
override
{
msg
.
formatted
<<
str_
;
// msg.formatted << str_;
append_str
(
str_
,
msg
.
formatted
);
}
private
:
...
...
@@ -447,20 +484,7 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
auto
duration
=
msg
.
time
.
time_since_epoch
();
auto
millis
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
milliseconds
>
(
duration
).
count
()
%
1000
;
/* Slower version(while still very fast - about 3.2 million lines/sec under 10 threads),
msg.formatted.write("[{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}.{:03d}] [{}] [{}] {} ",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec,
static_cast<int>(millis),
msg.logger_name,
level::to_str(msg.level),
msg.raw.str());*/
// Faster (albeit uglier) way to format the line (5.6 million lines/sec under 10 threads)
/*
msg.formatted << '[' << static_cast<unsigned int>(tm_time.tm_year + 1900) << '-'
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_mon + 1), 2, '0') << '-'
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_mday), 2, '0') << ' '
...
...
@@ -468,6 +492,11 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_min), 2, '0') << ':'
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_sec), 2, '0') << '.'
<< fmt::pad(static_cast<unsigned int>(millis), 3, '0') << "] ";
*/
// fmt::format_to(msg.formatted, "[{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}.{:03d}] [{}] [{}] ",
fmt
::
format_to
(
msg
.
formatted
,
"[{}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}] "
,
tm_time
.
tm_year
+
1900
,
tm_time
.
tm_mon
+
1
,
tm_time
.
tm_mday
,
tm_time
.
tm_hour
,
tm_time
.
tm_min
,
tm_time
.
tm_sec
,
static_cast
<
int
>
(
millis
));
// no datetime needed
#else
...
...
@@ -475,15 +504,24 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
#endif
#ifndef SPDLOG_NO_NAME
msg
.
formatted
<<
'['
<<
*
msg
.
logger_name
<<
"] "
;
// msg.formatted << '[' << *msg.logger_name << "] ";
fmt
::
format_to
(
msg
.
formatted
,
"[{}] "
,
*
msg
.
logger_name
);
#endif
msg
.
formatted
<<
'['
;
// msg.formatted << '[';
msg
.
formatted
.
push_back
(
'['
);
// wrap the level name with color
msg
.
color_range_start
=
msg
.
formatted
.
size
();
msg
.
formatted
<<
level
::
to_str
(
msg
.
level
);
// msg.formatted << level::to_str(msg.level);
append_str
(
level
::
to_str
(
msg
.
level
),
msg
.
formatted
);
msg
.
color_range_end
=
msg
.
formatted
.
size
();
msg
.
formatted
<<
"] "
<<
fmt
::
StringRef
(
msg
.
raw
.
data
(),
msg
.
raw
.
size
());
// msg.formatted << "] " << fmt::StringRef(msg.raw.data(), msg.raw.size());
msg
.
formatted
.
push_back
(
']'
);
msg
.
formatted
.
push_back
(
' '
);
append_buf
(
msg
.
raw
,
msg
.
formatted
);
}
};
...
...
@@ -703,5 +741,7 @@ inline void spdlog::pattern_formatter::format(details::log_msg &msg)
f
->
format
(
msg
,
tm_time
);
}
// write eol
msg
.
formatted
<<
eol_
;
// msg.formatted << eol_;
append_str
(
eol_
,
msg
.
formatted
);
}
include/spdlog/details/thread_pool.h
View file @
cdbf2e36
...
...
@@ -65,15 +65,13 @@ struct async_msg
}
// copy into log_msg
void
to_log_msg
(
log_msg
&
&
msg
)
void
to_log_msg
(
log_msg
&
msg
)
{
msg
.
logger_name
=
&
worker_ptr
->
name
();
msg
.
level
=
level
;
msg
.
time
=
time
;
msg
.
thread_id
=
thread_id
;
msg
.
raw
.
clear
();
msg
.
raw
<<
txt
;
msg
.
formatted
.
clear
();
msg
.
raw
.
append
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
());
msg
.
msg_id
=
msg_id
;
msg
.
color_range_start
=
0
;
msg
.
color_range_end
=
0
;
...
...
@@ -182,7 +180,7 @@ private:
default:
{
log_msg
msg
;
incoming_async_msg
.
to_log_msg
(
std
::
move
(
msg
)
);
incoming_async_msg
.
to_log_msg
(
msg
);
incoming_async_msg
.
worker_ptr
->
backend_log_
(
msg
);
return
true
;
}
...
...
include/spdlog/fmt/bundled/format.cc
deleted
100644 → 0
View file @
378c7789
/*
Formatting library for C++
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "format.h"
#include <string.h>
#include <cctype>
#include <cerrno>
#include <climits>
#include <cmath>
#include <cstdarg>
#include <cstddef> // for std::ptrdiff_t
#if defined(_WIN32) && defined(__MINGW32__)
# include <cstring>
#endif
#if FMT_USE_WINDOWS_H
# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
# define WIN32_LEAN_AND_MEAN
# endif
# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
# include <windows.h>
# else
# define NOMINMAX
# include <windows.h>
# undef NOMINMAX
# endif
#endif
#if FMT_EXCEPTIONS
# define FMT_TRY try
# define FMT_CATCH(x) catch (x)
#else
# define FMT_TRY if (true)
# define FMT_CATCH(x) if (false)
#endif
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4127) // conditional expression is constant
# pragma warning(disable: 4702) // unreachable code
// Disable deprecation warning for strerror. The latter is not called but
// MSVC fails to detect it.
# pragma warning(disable: 4996)
#endif
// Dummy implementations of strerror_r and strerror_s called if corresponding
// system functions are not available.
FMT_MAYBE_UNUSED
static
inline
fmt
::
internal
::
Null
<>
strerror_r
(
int
,
char
*
,
...)
{
return
fmt
::
internal
::
Null
<>
();
}
FMT_MAYBE_UNUSED
static
inline
fmt
::
internal
::
Null
<>
strerror_s
(
char
*
,
std
::
size_t
,
...)
{
return
fmt
::
internal
::
Null
<>
();
}
namespace
fmt
{
FMT_FUNC
internal
::
RuntimeError
::~
RuntimeError
()
FMT_DTOR_NOEXCEPT
{}
FMT_FUNC
FormatError
::~
FormatError
()
FMT_DTOR_NOEXCEPT
{}
FMT_FUNC
SystemError
::~
SystemError
()
FMT_DTOR_NOEXCEPT
{}
namespace
{
#ifndef _MSC_VER
# define FMT_SNPRINTF snprintf
#else // _MSC_VER
inline
int
fmt_snprintf
(
char
*
buffer
,
size_t
size
,
const
char
*
format
,
...)
{
va_list
args
;
va_start
(
args
,
format
);
int
result
=
vsnprintf_s
(
buffer
,
size
,
_TRUNCATE
,
format
,
args
);
va_end
(
args
);
return
result
;
}
# define FMT_SNPRINTF fmt_snprintf
#endif // _MSC_VER
#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
# define FMT_SWPRINTF snwprintf
#else
# define FMT_SWPRINTF swprintf
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
const
char
RESET_COLOR
[]
=
"
\x1b
[0m"
;
typedef
void
(
*
FormatFunc
)(
Writer
&
,
int
,
StringRef
);
// Portable thread-safe version of strerror.
// Sets buffer to point to a string describing the error code.
// This can be either a pointer to a string stored in buffer,
// or a pointer to some static immutable string.
// Returns one of the following values:
// 0 - success
// ERANGE - buffer is not large enough to store the error message
// other - failure
// Buffer should be at least of size 1.
int
safe_strerror
(
int
error_code
,
char
*&
buffer
,
std
::
size_t
buffer_size
)
FMT_NOEXCEPT
{
FMT_ASSERT
(
buffer
!=
FMT_NULL
&&
buffer_size
!=
0
,
"invalid buffer"
);
class
StrError
{
private
:
int
error_code_
;
char
*&
buffer_
;
std
::
size_t
buffer_size_
;
// A noop assignment operator to avoid bogus warnings.
void
operator
=
(
const
StrError
&
)
{}
// Handle the result of XSI-compliant version of strerror_r.
int
handle
(
int
result
)
{
// glibc versions before 2.13 return result in errno.
return
result
==
-
1
?
errno
:
result
;
}
// Handle the result of GNU-specific version of strerror_r.
int
handle
(
char
*
message
)
{
// If the buffer is full then the message is probably truncated.
if
(
message
==
buffer_
&&
strlen
(
buffer_
)
==
buffer_size_
-
1
)
return
ERANGE
;
buffer_
=
message
;
return
0
;
}
// Handle the case when strerror_r is not available.
int
handle
(
internal
::
Null
<>
)
{
return
fallback
(
strerror_s
(
buffer_
,
buffer_size_
,
error_code_
));
}
// Fallback to strerror_s when strerror_r is not available.
int
fallback
(
int
result
)
{
// If the buffer is full then the message is probably truncated.
return
result
==
0
&&
strlen
(
buffer_
)
==
buffer_size_
-
1
?
ERANGE
:
result
;
}
#ifdef __c2__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
// Fallback to strerror if strerror_r and strerror_s are not available.
int
fallback
(
internal
::
Null
<>
)
{
errno
=
0
;
buffer_
=
strerror
(
error_code_
);
return
errno
;
}
#ifdef __c2__
# pragma clang diagnostic pop
#endif
public
:
StrError
(
int
err_code
,
char
*&
buf
,
std
::
size_t
buf_size
)
:
error_code_
(
err_code
),
buffer_
(
buf
),
buffer_size_
(
buf_size
)
{}
int
run
()
{
return
handle
(
strerror_r
(
error_code_
,
buffer_
,
buffer_size_
));
}
};
return
StrError
(
error_code
,
buffer
,
buffer_size
).
run
();
}
void
format_error_code
(
Writer
&
out
,
int
error_code
,
StringRef
message
)
FMT_NOEXCEPT
{
// Report error code making sure that the output fits into
// INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
// bad_alloc.
out
.
clear
();
static
const
char
SEP
[]
=
": "
;
static
const
char
ERROR_STR
[]
=
"error "
;
// Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
std
::
size_t
error_code_size
=
sizeof
(
SEP
)
+
sizeof
(
ERROR_STR
)
-
2
;
typedef
internal
::
IntTraits
<
int
>::
MainType
MainType
;
MainType
abs_value
=
static_cast
<
MainType
>
(
error_code
);
if
(
internal
::
is_negative
(
error_code
))
{
abs_value
=
0
-
abs_value
;
++
error_code_size
;
}
error_code_size
+=
internal
::
count_digits
(
abs_value
);
if
(
message
.
size
()
<=
internal
::
INLINE_BUFFER_SIZE
-
error_code_size
)
out
<<
message
<<
SEP
;
out
<<
ERROR_STR
<<
error_code
;
assert
(
out
.
size
()
<=
internal
::
INLINE_BUFFER_SIZE
);
}
void
report_error
(
FormatFunc
func
,
int
error_code
,
StringRef
message
)
FMT_NOEXCEPT
{
MemoryWriter
full_message
;
func
(
full_message
,
error_code
,
message
);
// Use Writer::data instead of Writer::c_str to avoid potential memory
// allocation.
std
::
fwrite
(
full_message
.
data
(),
full_message
.
size
(),
1
,
stderr
);
std
::
fputc
(
'\n'
,
stderr
);
}
}
// namespace
FMT_FUNC
void
SystemError
::
init
(
int
err_code
,
CStringRef
format_str
,
ArgList
args
)
{
error_code_
=
err_code
;
MemoryWriter
w
;
format_system_error
(
w
,
err_code
,
format
(
format_str
,
args
));
std
::
runtime_error
&
base
=
*
this
;
base
=
std
::
runtime_error
(
w
.
str
());
}
template
<
typename
T
>
int
internal
::
CharTraits
<
char
>::
format_float
(
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
unsigned
width
,
int
precision
,
T
value
)
{
if
(
width
==
0
)
{
return
precision
<
0
?
FMT_SNPRINTF
(
buffer
,
size
,
format
,
value
)
:
FMT_SNPRINTF
(
buffer
,
size
,
format
,
precision
,
value
);
}
return
precision
<
0
?
FMT_SNPRINTF
(
buffer
,
size
,
format
,
width
,
value
)
:
FMT_SNPRINTF
(
buffer
,
size
,
format
,
width
,
precision
,
value
);
}
template
<
typename
T
>
int
internal
::
CharTraits
<
wchar_t
>::
format_float
(
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
unsigned
width
,
int
precision
,
T
value
)
{
if
(
width
==
0
)
{
return
precision
<
0
?
FMT_SWPRINTF
(
buffer
,
size
,
format
,
value
)
:
FMT_SWPRINTF
(
buffer
,
size
,
format
,
precision
,
value
);
}
return
precision
<
0
?
FMT_SWPRINTF
(
buffer
,
size
,
format
,
width
,
value
)
:
FMT_SWPRINTF
(
buffer
,
size
,
format
,
width
,
precision
,
value
);
}
template
<
typename
T
>
const
char
internal
::
BasicData
<
T
>::
DIGITS
[]
=
"0001020304050607080910111213141516171819"
"2021222324252627282930313233343536373839"
"4041424344454647484950515253545556575859"
"6061626364656667686970717273747576777879"
"8081828384858687888990919293949596979899"
;
#define FMT_POWERS_OF_10(factor) \
factor * 10, \
factor * 100, \
factor * 1000, \
factor * 10000, \
factor * 100000, \
factor * 1000000, \
factor * 10000000, \
factor * 100000000, \
factor * 1000000000
template
<
typename
T
>
const
uint32_t
internal
::
BasicData
<
T
>::
POWERS_OF_10_32
[]
=
{
0
,
FMT_POWERS_OF_10
(
1
)
};
template
<
typename
T
>
const
uint64_t
internal
::
BasicData
<
T
>::
POWERS_OF_10_64
[]
=
{
0
,
FMT_POWERS_OF_10
(
1
),
FMT_POWERS_OF_10
(
ULongLong
(
1000000000
)),
// Multiply several constants instead of using a single long long constant
// to avoid warnings about C++98 not supporting long long.
ULongLong
(
1000000000
)
*
ULongLong
(
1000000000
)
*
10
};
FMT_FUNC
void
internal
::
report_unknown_type
(
char
code
,
const
char
*
type
)
{
(
void
)
type
;
if
(
std
::
isprint
(
static_cast
<
unsigned
char
>
(
code
)))
{
FMT_THROW
(
FormatError
(
format
(
"unknown format code '{}' for {}"
,
code
,
type
)));
}
FMT_THROW
(
FormatError
(
format
(
"unknown format code '
\\
x{:02x}' for {}"
,
static_cast
<
unsigned
>
(
code
),
type
)));
}
#if FMT_USE_WINDOWS_H
FMT_FUNC
internal
::
UTF8ToUTF16
::
UTF8ToUTF16
(
StringRef
s
)
{
static
const
char
ERROR_MSG
[]
=
"cannot convert string from UTF-8 to UTF-16"
;
if
(
s
.
size
()
>
INT_MAX
)
FMT_THROW
(
WindowsError
(
ERROR_INVALID_PARAMETER
,
ERROR_MSG
));
int
s_size
=
static_cast
<
int
>
(
s
.
size
());
int
length
=
MultiByteToWideChar
(
CP_UTF8
,
MB_ERR_INVALID_CHARS
,
s
.
data
(),
s_size
,
FMT_NULL
,
0
);
if
(
length
==
0
)
FMT_THROW
(
WindowsError
(
GetLastError
(),
ERROR_MSG
));
buffer_
.
resize
(
length
+
1
);
length
=
MultiByteToWideChar
(
CP_UTF8
,
MB_ERR_INVALID_CHARS
,
s
.
data
(),
s_size
,
&
buffer_
[
0
],
length
);
if
(
length
==
0
)
FMT_THROW
(
WindowsError
(
GetLastError
(),
ERROR_MSG
));
buffer_
[
length
]
=
0
;
}
FMT_FUNC
internal
::
UTF16ToUTF8
::
UTF16ToUTF8
(
WStringRef
s
)
{
if
(
int
error_code
=
convert
(
s
))
{
FMT_THROW
(
WindowsError
(
error_code
,
"cannot convert string from UTF-16 to UTF-8"
));
}
}
FMT_FUNC
int
internal
::
UTF16ToUTF8
::
convert
(
WStringRef
s
)
{
if
(
s
.
size
()
>
INT_MAX
)
return
ERROR_INVALID_PARAMETER
;
int
s_size
=
static_cast
<
int
>
(
s
.
size
());
int
length
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
s
.
data
(),
s_size
,
FMT_NULL
,
0
,
FMT_NULL
,
FMT_NULL
);
if
(
length
==
0
)
return
GetLastError
();
buffer_
.
resize
(
length
+
1
);
length
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
s
.
data
(),
s_size
,
&
buffer_
[
0
],
length
,
FMT_NULL
,
FMT_NULL
);
if
(
length
==
0
)
return
GetLastError
();
buffer_
[
length
]
=
0
;
return
0
;
}
FMT_FUNC
void
WindowsError
::
init
(
int
err_code
,
CStringRef
format_str
,
ArgList
args
)
{
error_code_
=
err_code
;
MemoryWriter
w
;
internal
::
format_windows_error
(
w
,
err_code
,
format
(
format_str
,
args
));
std
::
runtime_error
&
base
=
*
this
;
base
=
std
::
runtime_error
(
w
.
str
());
}
FMT_FUNC
void
internal
::
format_windows_error
(
Writer
&
out
,
int
error_code
,
StringRef
message
)
FMT_NOEXCEPT
{
FMT_TRY
{
MemoryBuffer
<
wchar_t
,
INLINE_BUFFER_SIZE
>
buffer
;
buffer
.
resize
(
INLINE_BUFFER_SIZE
);
for
(;;)
{
wchar_t
*
system_message
=
&
buffer
[
0
];
int
result
=
FormatMessageW
(
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
,
FMT_NULL
,
error_code
,
MAKELANGID
(
LANG_NEUTRAL
,
SUBLANG_DEFAULT
),
system_message
,
static_cast
<
uint32_t
>
(
buffer
.
size
()),
FMT_NULL
);
if
(
result
!=
0
)
{
UTF16ToUTF8
utf8_message
;
if
(
utf8_message
.
convert
(
system_message
)
==
ERROR_SUCCESS
)
{
out
<<
message
<<
": "
<<
utf8_message
;
return
;
}
break
;
}
if
(
GetLastError
()
!=
ERROR_INSUFFICIENT_BUFFER
)
break
;
// Can't get error message, report error code instead.
buffer
.
resize
(
buffer
.
size
()
*
2
);
}
}
FMT_CATCH
(...)
{}
fmt
::
format_error_code
(
out
,
error_code
,
message
);
// 'fmt::' is for bcc32.
}
#endif // FMT_USE_WINDOWS_H
FMT_FUNC
void
format_system_error
(
Writer
&
out
,
int
error_code
,
StringRef
message
)
FMT_NOEXCEPT
{
FMT_TRY
{
internal
::
MemoryBuffer
<
char
,
internal
::
INLINE_BUFFER_SIZE
>
buffer
;
buffer
.
resize
(
internal
::
INLINE_BUFFER_SIZE
);
for
(;;)
{
char
*
system_message
=
&
buffer
[
0
];
int
result
=
safe_strerror
(
error_code
,
system_message
,
buffer
.
size
());
if
(
result
==
0
)
{
out
<<
message
<<
": "
<<
system_message
;
return
;
}
if
(
result
!=
ERANGE
)
break
;
// Can't get error message, report error code instead.
buffer
.
resize
(
buffer
.
size
()
*
2
);
}
}
FMT_CATCH
(...)
{}
fmt
::
format_error_code
(
out
,
error_code
,
message
);
// 'fmt::' is for bcc32.
}
template
<
typename
Char
>
void
internal
::
FixedBuffer
<
Char
>::
grow
(
std
::
size_t
)
{
FMT_THROW
(
std
::
runtime_error
(
"buffer overflow"
));
}
FMT_FUNC
internal
::
Arg
internal
::
FormatterBase
::
do_get_arg
(
unsigned
arg_index
,
const
char
*&
error
)
{
internal
::
Arg
arg
=
args_
[
arg_index
];
switch
(
arg
.
type
)
{
case
internal
:
:
Arg
::
NONE
:
error
=
"argument index out of range"
;
break
;
case
internal
:
:
Arg
::
NAMED_ARG
:
arg
=
*
static_cast
<
const
internal
::
Arg
*>
(
arg
.
pointer
);
break
;
default
:
/*nothing*/
;
}
return
arg
;
}
FMT_FUNC
void
report_system_error
(
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
// 'fmt::' is for bcc32.
report_error
(
format_system_error
,
error_code
,
message
);
}
#if FMT_USE_WINDOWS_H
FMT_FUNC
void
report_windows_error
(
int
error_code
,
fmt
::
StringRef
message
)
FMT_NOEXCEPT
{
// 'fmt::' is for bcc32.
report_error
(
internal
::
format_windows_error
,
error_code
,
message
);
}
#endif
FMT_FUNC
void
print
(
std
::
FILE
*
f
,
CStringRef
format_str
,
ArgList
args
)
{
MemoryWriter
w
;
w
.
write
(
format_str
,
args
);
std
::
fwrite
(
w
.
data
(),
1
,
w
.
size
(),
f
);
}
FMT_FUNC
void
print
(
CStringRef
format_str
,
ArgList
args
)
{
print
(
stdout
,
format_str
,
args
);
}
FMT_FUNC
void
print_colored
(
Color
c
,
CStringRef
format
,
ArgList
args
)
{
char
escape
[]
=
"
\x1b
[30m"
;
escape
[
3
]
=
static_cast
<
char
>
(
'0'
+
c
);
std
::
fputs
(
escape
,
stdout
);
print
(
format
,
args
);
std
::
fputs
(
RESET_COLOR
,
stdout
);
}
#ifndef FMT_HEADER_ONLY
template
struct
internal
::
BasicData
<
void
>
;
// Explicit instantiations for char.
template
void
internal
::
FixedBuffer
<
char
>::
grow
(
std
::
size_t
);
template
FMT_API
int
internal
::
CharTraits
<
char
>::
format_float
(
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
unsigned
width
,
int
precision
,
double
value
);
template
FMT_API
int
internal
::
CharTraits
<
char
>::
format_float
(
char
*
buffer
,
std
::
size_t
size
,
const
char
*
format
,
unsigned
width
,
int
precision
,
long
double
value
);
// Explicit instantiations for wchar_t.
template
void
internal
::
FixedBuffer
<
wchar_t
>::
grow
(
std
::
size_t
);
template
FMT_API
int
internal
::
CharTraits
<
wchar_t
>::
format_float
(
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
unsigned
width
,
int
precision
,
double
value
);
template
FMT_API
int
internal
::
CharTraits
<
wchar_t
>::
format_float
(
wchar_t
*
buffer
,
std
::
size_t
size
,
const
wchar_t
*
format
,
unsigned
width
,
int
precision
,
long
double
value
);
#endif // FMT_HEADER_ONLY
}
// namespace fmt
#ifdef _MSC_VER
# pragma warning(pop)
#endif
include/spdlog/fmt/bundled/format.h
deleted
100644 → 0
View file @
378c7789
This source diff could not be displayed because it is too large. You can
view the blob
instead.
include/spdlog/fmt/bundled/ostream.cc
deleted
100644 → 0
View file @
378c7789
/*
Formatting library for C++ - std::ostream support
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#include "ostream.h"
namespace
fmt
{
namespace
internal
{
FMT_FUNC
void
write
(
std
::
ostream
&
os
,
Writer
&
w
)
{
const
char
*
data
=
w
.
data
();
typedef
internal
::
MakeUnsigned
<
std
::
streamsize
>::
Type
UnsignedStreamSize
;
UnsignedStreamSize
size
=
w
.
size
();
UnsignedStreamSize
max_size
=
internal
::
to_unsigned
((
std
::
numeric_limits
<
std
::
streamsize
>::
max
)());
do
{
UnsignedStreamSize
n
=
size
<=
max_size
?
size
:
max_size
;
os
.
write
(
data
,
static_cast
<
std
::
streamsize
>
(
n
));
data
+=
n
;
size
-=
n
;
}
while
(
size
!=
0
);
}
}
FMT_FUNC
void
print
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
)
{
MemoryWriter
w
;
w
.
write
(
format_str
,
args
);
internal
::
write
(
os
,
w
);
}
}
// namespace fmt
include/spdlog/fmt/bundled/ostream.h
deleted
100644 → 0
View file @
378c7789
/*
Formatting library for C++ - std::ostream support
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#ifndef FMT_OSTREAM_H_
#define FMT_OSTREAM_H_
#include "format.h"
#include <ostream>
namespace
fmt
{
namespace
internal
{
template
<
class
Char
>
class
FormatBuf
:
public
std
::
basic_streambuf
<
Char
>
{
private
:
typedef
typename
std
::
basic_streambuf
<
Char
>::
int_type
int_type
;
typedef
typename
std
::
basic_streambuf
<
Char
>::
traits_type
traits_type
;
Buffer
<
Char
>
&
buffer_
;
public
:
FormatBuf
(
Buffer
<
Char
>
&
buffer
)
:
buffer_
(
buffer
)
{
}
protected
:
// The put-area is actually always empty. This makes the implementation
// simpler and has the advantage that the streambuf and the buffer are always
// in sync and sputc never writes into uninitialized memory. The obvious
// disadvantage is that each call to sputc always results in a (virtual) call
// to overflow. There is no disadvantage here for sputn since this always
// results in a call to xsputn.
int_type
overflow
(
int_type
ch
=
traits_type
::
eof
())
FMT_OVERRIDE
{
if
(
!
traits_type
::
eq_int_type
(
ch
,
traits_type
::
eof
()))
buffer_
.
push_back
(
static_cast
<
Char
>
(
ch
));
return
ch
;
}
std
::
streamsize
xsputn
(
const
Char
*
s
,
std
::
streamsize
count
)
FMT_OVERRIDE
{
buffer_
.
append
(
s
,
s
+
count
);
return
count
;
}
};
Yes
&
convert
(
std
::
ostream
&
);
struct
DummyStream
:
std
::
ostream
{
DummyStream
();
// Suppress a bogus warning in MSVC.
// Hide all operator<< overloads from std::ostream.
template
<
typename
T
>
typename
EnableIf
<
sizeof
(
T
)
==
0
>::
type
operator
<<
(
const
T
&
);
};
No
&
operator
<<
(
std
::
ostream
&
,
int
);
template
<
typename
T
>
struct
ConvertToIntImpl
<
T
,
true
>
{
// Convert to int only if T doesn't have an overloaded operator<<.
enum
{
value
=
sizeof
(
convert
(
get
<
DummyStream
>
()
<<
get
<
T
>
()))
==
sizeof
(
No
)
};
};
// Write the content of w to os.
FMT_API
void
write
(
std
::
ostream
&
os
,
Writer
&
w
);
}
// namespace internal
// Formats a value.
template
<
typename
Char
,
typename
ArgFormatter_
,
typename
T
>
void
format_arg
(
BasicFormatter
<
Char
,
ArgFormatter_
>
&
f
,
const
Char
*&
format_str
,
const
T
&
value
)
{
internal
::
MemoryBuffer
<
Char
,
internal
::
INLINE_BUFFER_SIZE
>
buffer
;
internal
::
FormatBuf
<
Char
>
format_buf
(
buffer
);
std
::
basic_ostream
<
Char
>
output
(
&
format_buf
);
output
.
exceptions
(
std
::
ios_base
::
failbit
|
std
::
ios_base
::
badbit
);
output
<<
value
;
BasicStringRef
<
Char
>
str
(
&
buffer
[
0
],
buffer
.
size
());
typedef
internal
::
MakeArg
<
BasicFormatter
<
Char
>>
MakeArg
;
format_str
=
f
.
format
(
format_str
,
MakeArg
(
str
));
}
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
print(cerr, "Don't {}!", "panic");
\endrst
*/
FMT_API
void
print
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
);
FMT_VARIADIC
(
void
,
print
,
std
::
ostream
&
,
CStringRef
)
}
// namespace fmt
#ifdef FMT_HEADER_ONLY
#include "ostream.cc"
#endif
#endif // FMT_OSTREAM_H_
include/spdlog/fmt/bundled/posix.cc
deleted
100644 → 0
View file @
378c7789
/*
A C++ interface to POSIX functions.
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
// Disable bogus MSVC warnings.
#ifndef _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS
#endif
#include "posix.h"
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef _WIN32
# include <unistd.h>
#else
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# include <io.h>
# define O_CREAT _O_CREAT
# define O_TRUNC _O_TRUNC
# ifndef S_IRUSR
# define S_IRUSR _S_IREAD
# endif
# ifndef S_IWUSR
# define S_IWUSR _S_IWRITE
# endif
# ifdef __MINGW32__
# define _SH_DENYNO 0x40
# endif
#endif // _WIN32
#ifdef fileno
# undef fileno
#endif
namespace
{
#ifdef _WIN32
// Return type of read and write functions.
typedef
int
RWResult
;
// On Windows the count argument to read and write is unsigned, so convert
// it from size_t preventing integer overflow.
inline
unsigned
convert_rwcount
(
std
::
size_t
count
)
{
return
count
<=
UINT_MAX
?
static_cast
<
unsigned
>
(
count
)
:
UINT_MAX
;
}
#else
// Return type of read and write functions.
typedef
ssize_t
RWResult
;
inline
std
::
size_t
convert_rwcount
(
std
::
size_t
count
)
{
return
count
;
}
#endif
}
fmt
::
BufferedFile
::~
BufferedFile
()
FMT_NOEXCEPT
{
if
(
file_
&&
FMT_SYSTEM
(
fclose
(
file_
))
!=
0
)
fmt
::
report_system_error
(
errno
,
"cannot close file"
);
}
fmt
::
BufferedFile
::
BufferedFile
(
fmt
::
CStringRef
filename
,
fmt
::
CStringRef
mode
)
{
FMT_RETRY_VAL
(
file_
,
FMT_SYSTEM
(
fopen
(
filename
.
c_str
(),
mode
.
c_str
())),
0
);
if
(
!
file_
)
FMT_THROW
(
SystemError
(
errno
,
"cannot open file {}"
,
filename
));
}
void
fmt
::
BufferedFile
::
close
()
{
if
(
!
file_
)
return
;
int
result
=
FMT_SYSTEM
(
fclose
(
file_
));
file_
=
FMT_NULL
;
if
(
result
!=
0
)
FMT_THROW
(
SystemError
(
errno
,
"cannot close file"
));
}
// A macro used to prevent expansion of fileno on broken versions of MinGW.
#define FMT_ARGS
int
fmt
::
BufferedFile
::
fileno
()
const
{
int
fd
=
FMT_POSIX_CALL
(
fileno
FMT_ARGS
(
file_
));
if
(
fd
==
-
1
)
FMT_THROW
(
SystemError
(
errno
,
"cannot get file descriptor"
));
return
fd
;
}
fmt
::
File
::
File
(
fmt
::
CStringRef
path
,
int
oflag
)
{
int
mode
=
S_IRUSR
|
S_IWUSR
;
#if defined(_WIN32) && !defined(__MINGW32__)
fd_
=
-
1
;
FMT_POSIX_CALL
(
sopen_s
(
&
fd_
,
path
.
c_str
(),
oflag
,
_SH_DENYNO
,
mode
));
#else
FMT_RETRY
(
fd_
,
FMT_POSIX_CALL
(
open
(
path
.
c_str
(),
oflag
,
mode
)));
#endif
if
(
fd_
==
-
1
)
FMT_THROW
(
SystemError
(
errno
,
"cannot open file {}"
,
path
));
}
fmt
::
File
::~
File
()
FMT_NOEXCEPT
{
// Don't retry close in case of EINTR!
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
if
(
fd_
!=
-
1
&&
FMT_POSIX_CALL
(
close
(
fd_
))
!=
0
)
fmt
::
report_system_error
(
errno
,
"cannot close file"
);
}
void
fmt
::
File
::
close
()
{
if
(
fd_
==
-
1
)
return
;
// Don't retry close in case of EINTR!
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
int
result
=
FMT_POSIX_CALL
(
close
(
fd_
));
fd_
=
-
1
;
if
(
result
!=
0
)
FMT_THROW
(
SystemError
(
errno
,
"cannot close file"
));
}
fmt
::
LongLong
fmt
::
File
::
size
()
const
{
#ifdef _WIN32
// Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT
// is less than 0x0500 as is the case with some default MinGW builds.
// Both functions support large file sizes.
DWORD
size_upper
=
0
;
HANDLE
handle
=
reinterpret_cast
<
HANDLE
>
(
_get_osfhandle
(
fd_
));
DWORD
size_lower
=
FMT_SYSTEM
(
GetFileSize
(
handle
,
&
size_upper
));
if
(
size_lower
==
INVALID_FILE_SIZE
)
{
DWORD
error
=
GetLastError
();
if
(
error
!=
NO_ERROR
)
FMT_THROW
(
WindowsError
(
GetLastError
(),
"cannot get file size"
));
}
fmt
::
ULongLong
long_size
=
size_upper
;
return
(
long_size
<<
sizeof
(
DWORD
)
*
CHAR_BIT
)
|
size_lower
;
#else
typedef
struct
stat
Stat
;
Stat
file_stat
=
Stat
();
if
(
FMT_POSIX_CALL
(
fstat
(
fd_
,
&
file_stat
))
==
-
1
)
FMT_THROW
(
SystemError
(
errno
,
"cannot get file attributes"
));
FMT_STATIC_ASSERT
(
sizeof
(
fmt
::
LongLong
)
>=
sizeof
(
file_stat
.
st_size
),
"return type of File::size is not large enough"
);
return
file_stat
.
st_size
;
#endif
}
std
::
size_t
fmt
::
File
::
read
(
void
*
buffer
,
std
::
size_t
count
)
{
RWResult
result
=
0
;
FMT_RETRY
(
result
,
FMT_POSIX_CALL
(
read
(
fd_
,
buffer
,
convert_rwcount
(
count
))));
if
(
result
<
0
)
FMT_THROW
(
SystemError
(
errno
,
"cannot read from file"
));
return
internal
::
to_unsigned
(
result
);
}
std
::
size_t
fmt
::
File
::
write
(
const
void
*
buffer
,
std
::
size_t
count
)
{
RWResult
result
=
0
;
FMT_RETRY
(
result
,
FMT_POSIX_CALL
(
write
(
fd_
,
buffer
,
convert_rwcount
(
count
))));
if
(
result
<
0
)
FMT_THROW
(
SystemError
(
errno
,
"cannot write to file"
));
return
internal
::
to_unsigned
(
result
);
}
fmt
::
File
fmt
::
File
::
dup
(
int
fd
)
{
// Don't retry as dup doesn't return EINTR.
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
int
new_fd
=
FMT_POSIX_CALL
(
dup
(
fd
));
if
(
new_fd
==
-
1
)
FMT_THROW
(
SystemError
(
errno
,
"cannot duplicate file descriptor {}"
,
fd
));
return
File
(
new_fd
);
}
void
fmt
::
File
::
dup2
(
int
fd
)
{
int
result
=
0
;
FMT_RETRY
(
result
,
FMT_POSIX_CALL
(
dup2
(
fd_
,
fd
)));
if
(
result
==
-
1
)
{
FMT_THROW
(
SystemError
(
errno
,
"cannot duplicate file descriptor {} to {}"
,
fd_
,
fd
));
}
}
void
fmt
::
File
::
dup2
(
int
fd
,
ErrorCode
&
ec
)
FMT_NOEXCEPT
{
int
result
=
0
;
FMT_RETRY
(
result
,
FMT_POSIX_CALL
(
dup2
(
fd_
,
fd
)));
if
(
result
==
-
1
)
ec
=
ErrorCode
(
errno
);
}
void
fmt
::
File
::
pipe
(
File
&
read_end
,
File
&
write_end
)
{
// Close the descriptors first to make sure that assignments don't throw
// and there are no leaks.
read_end
.
close
();
write_end
.
close
();
int
fds
[
2
]
=
{};
#ifdef _WIN32
// Make the default pipe capacity same as on Linux 2.6.11+.
enum
{
DEFAULT_CAPACITY
=
65536
};
int
result
=
FMT_POSIX_CALL
(
pipe
(
fds
,
DEFAULT_CAPACITY
,
_O_BINARY
));
#else
// Don't retry as the pipe function doesn't return EINTR.
// http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
int
result
=
FMT_POSIX_CALL
(
pipe
(
fds
));
#endif
if
(
result
!=
0
)
FMT_THROW
(
SystemError
(
errno
,
"cannot create pipe"
));
// The following assignments don't throw because read_fd and write_fd
// are closed.
read_end
=
File
(
fds
[
0
]);
write_end
=
File
(
fds
[
1
]);
}
fmt
::
BufferedFile
fmt
::
File
::
fdopen
(
const
char
*
mode
)
{
// Don't retry as fdopen doesn't return EINTR.
FILE
*
f
=
FMT_POSIX_CALL
(
fdopen
(
fd_
,
mode
));
if
(
!
f
)
FMT_THROW
(
SystemError
(
errno
,
"cannot associate stream with file descriptor"
));
BufferedFile
file
(
f
);
fd_
=
-
1
;
return
file
;
}
long
fmt
::
getpagesize
()
{
#ifdef _WIN32
SYSTEM_INFO
si
;
GetSystemInfo
(
&
si
);
return
si
.
dwPageSize
;
#else
long
size
=
FMT_POSIX_CALL
(
sysconf
(
_SC_PAGESIZE
));
if
(
size
<
0
)
FMT_THROW
(
SystemError
(
errno
,
"cannot get memory page size"
));
return
size
;
#endif
}
include/spdlog/fmt/bundled/posix.h
deleted
100644 → 0
View file @
378c7789
/*
A C++ interface to POSIX functions.
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#ifndef FMT_POSIX_H_
#define FMT_POSIX_H_
#if defined(__MINGW32__) || defined(__CYGWIN__)
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
#undef __STRICT_ANSI__
#endif
#include <errno.h>
#include <fcntl.h> // for O_RDONLY
#include <locale.h> // for locale_t
#include <stdio.h>
#include <stdlib.h> // for strtod_l
#include <cstddef>
#if defined __APPLE__ || defined(__FreeBSD__)
#include <xlocale.h> // for LC_NUMERIC_MASK on OS X
#endif
#include "format.h"
#ifndef FMT_POSIX
#if defined(_WIN32) && !defined(__MINGW32__)
// Fix warnings about deprecated symbols.
#define FMT_POSIX(call) _##call
#else
#define FMT_POSIX(call) call
#endif
#endif
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
#ifdef FMT_SYSTEM
#define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#else
#define FMT_SYSTEM(call) call
#ifdef _WIN32
// Fix warnings about deprecated symbols.
#define FMT_POSIX_CALL(call) ::_##call
#else
#define FMT_POSIX_CALL(call) ::call
#endif
#endif
// Retries the expression while it evaluates to error_result and errno
// equals to EINTR.
#ifndef _WIN32
#define FMT_RETRY_VAL(result, expression, error_result) \
do \
{ \
result = (expression); \
} while (result == error_result && errno == EINTR)
#else
#define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#endif
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
namespace
fmt
{
// An error code.
class
ErrorCode
{
private
:
int
value_
;
public
:
explicit
ErrorCode
(
int
value
=
0
)
FMT_NOEXCEPT
:
value_
(
value
)
{}
int
get
()
const
FMT_NOEXCEPT
{
return
value_
;
}
};
// A buffered file.
class
BufferedFile
{
private
:
FILE
*
file_
;
friend
class
File
;
explicit
BufferedFile
(
FILE
*
f
)
:
file_
(
f
)
{
}
public
:
// Constructs a BufferedFile object which doesn't represent any file.
BufferedFile
()
FMT_NOEXCEPT
:
file_
(
FMT_NULL
)
{}
// Destroys the object closing the file it represents if any.
FMT_API
~
BufferedFile
()
FMT_NOEXCEPT
;
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private
:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct
Proxy
{
FILE
*
file
;
};
public
:
// A "move constructor" for moving from a temporary.
BufferedFile
(
Proxy
p
)
FMT_NOEXCEPT
:
file_
(
p
.
file
)
{}
// A "move constructor" for moving from an lvalue.
BufferedFile
(
BufferedFile
&
f
)
FMT_NOEXCEPT
:
file_
(
f
.
file_
)
{
f
.
file_
=
FMT_NULL
;
}
// A "move assignment operator" for moving from a temporary.
BufferedFile
&
operator
=
(
Proxy
p
)
{
close
();
file_
=
p
.
file
;
return
*
this
;
}
// A "move assignment operator" for moving from an lvalue.
BufferedFile
&
operator
=
(
BufferedFile
&
other
)
{
close
();
file_
=
other
.
file_
;
other
.
file_
=
FMT_NULL
;
return
*
this
;
}
// Returns a proxy object for moving from a temporary:
// BufferedFile file = BufferedFile(...);
operator
Proxy
()
FMT_NOEXCEPT
{
Proxy
p
=
{
file_
};
file_
=
FMT_NULL
;
return
p
;
}
#else
private
:
FMT_DISALLOW_COPY_AND_ASSIGN
(
BufferedFile
);
public
:
BufferedFile
(
BufferedFile
&&
other
)
FMT_NOEXCEPT
:
file_
(
other
.
file_
)
{
other
.
file_
=
FMT_NULL
;
}
BufferedFile
&
operator
=
(
BufferedFile
&&
other
)
{
close
();
file_
=
other
.
file_
;
other
.
file_
=
FMT_NULL
;
return
*
this
;
}
#endif
// Opens a file.
FMT_API
BufferedFile
(
CStringRef
filename
,
CStringRef
mode
);
// Closes the file.
FMT_API
void
close
();
// Returns the pointer to a FILE object representing this file.
FILE
*
get
()
const
FMT_NOEXCEPT
{
return
file_
;
}
// We place parentheses around fileno to workaround a bug in some versions
// of MinGW that define fileno as a macro.
FMT_API
int
(
fileno
)()
const
;
void
print
(
CStringRef
format_str
,
const
ArgList
&
args
)
{
fmt
::
print
(
file_
,
format_str
,
args
);
}
FMT_VARIADIC
(
void
,
print
,
CStringRef
)
};
// A file. Closed file is represented by a File object with descriptor -1.
// Methods that are not declared with FMT_NOEXCEPT may throw
// fmt::SystemError in case of failure. Note that some errors such as
// closing the file multiple times will cause a crash on Windows rather
// than an exception. You can get standard behavior by overriding the
// invalid parameter handler with _set_invalid_parameter_handler.
class
File
{
private
:
int
fd_
;
// File descriptor.
// Constructs a File object with a given descriptor.
explicit
File
(
int
fd
)
:
fd_
(
fd
)
{
}
public
:
// Possible values for the oflag argument to the constructor.
enum
{
RDONLY
=
FMT_POSIX
(
O_RDONLY
),
// Open for reading only.
WRONLY
=
FMT_POSIX
(
O_WRONLY
),
// Open for writing only.
RDWR
=
FMT_POSIX
(
O_RDWR
)
// Open for reading and writing.
};
// Constructs a File object which doesn't represent any file.
File
()
FMT_NOEXCEPT
:
fd_
(
-
1
)
{}
// Opens a file and constructs a File object representing this file.
FMT_API
File
(
CStringRef
path
,
int
oflag
);
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private
:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct
Proxy
{
int
fd
;
};
public
:
// A "move constructor" for moving from a temporary.
File
(
Proxy
p
)
FMT_NOEXCEPT
:
fd_
(
p
.
fd
)
{}
// A "move constructor" for moving from an lvalue.
File
(
File
&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
{
other
.
fd_
=
-
1
;
}
// A "move assignment operator" for moving from a temporary.
File
&
operator
=
(
Proxy
p
)
{
close
();
fd_
=
p
.
fd
;
return
*
this
;
}
// A "move assignment operator" for moving from an lvalue.
File
&
operator
=
(
File
&
other
)
{
close
();
fd_
=
other
.
fd_
;
other
.
fd_
=
-
1
;
return
*
this
;
}
// Returns a proxy object for moving from a temporary:
// File file = File(...);
operator
Proxy
()
FMT_NOEXCEPT
{
Proxy
p
=
{
fd_
};
fd_
=
-
1
;
return
p
;
}
#else
private
:
FMT_DISALLOW_COPY_AND_ASSIGN
(
File
);
public
:
File
(
File
&&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
{
other
.
fd_
=
-
1
;
}
File
&
operator
=
(
File
&&
other
)
{
close
();
fd_
=
other
.
fd_
;
other
.
fd_
=
-
1
;
return
*
this
;
}
#endif
// Destroys the object closing the file it represents if any.
FMT_API
~
File
()
FMT_NOEXCEPT
;
// Returns the file descriptor.
int
descriptor
()
const
FMT_NOEXCEPT
{
return
fd_
;
}
// Closes the file.
FMT_API
void
close
();
// Returns the file size. The size has signed type for consistency with
// stat::st_size.
FMT_API
LongLong
size
()
const
;
// Attempts to read count bytes from the file into the specified buffer.
FMT_API
std
::
size_t
read
(
void
*
buffer
,
std
::
size_t
count
);
// Attempts to write count bytes from the specified buffer to the file.
FMT_API
std
::
size_t
write
(
const
void
*
buffer
,
std
::
size_t
count
);
// Duplicates a file descriptor with the dup function and returns
// the duplicate as a file object.
FMT_API
static
File
dup
(
int
fd
);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
FMT_API
void
dup2
(
int
fd
);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
FMT_API
void
dup2
(
int
fd
,
ErrorCode
&
ec
)
FMT_NOEXCEPT
;
// Creates a pipe setting up read_end and write_end file objects for reading
// and writing respectively.
FMT_API
static
void
pipe
(
File
&
read_end
,
File
&
write_end
);
// Creates a BufferedFile object associated with this file and detaches
// this File object from the file.
FMT_API
BufferedFile
fdopen
(
const
char
*
mode
);
};
// Returns the memory page size.
long
getpagesize
();
#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && !defined(__ANDROID__) && !defined(__CYGWIN__)
#define FMT_LOCALE
#endif
#ifdef FMT_LOCALE
// A "C" numeric locale.
class
Locale
{
private
:
#ifdef _MSC_VER
typedef
_locale_t
locale_t
;
enum
{
LC_NUMERIC_MASK
=
LC_NUMERIC
};
static
locale_t
newlocale
(
int
category_mask
,
const
char
*
locale
,
locale_t
)
{
return
_create_locale
(
category_mask
,
locale
);
}
static
void
freelocale
(
locale_t
locale
)
{
_free_locale
(
locale
);
}
static
double
strtod_l
(
const
char
*
nptr
,
char
**
endptr
,
_locale_t
locale
)
{
return
_strtod_l
(
nptr
,
endptr
,
locale
);
}
#endif
locale_t
locale_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
Locale
);
public
:
typedef
locale_t
Type
;
Locale
()
:
locale_
(
newlocale
(
LC_NUMERIC_MASK
,
"C"
,
FMT_NULL
))
{
if
(
!
locale_
)
FMT_THROW
(
fmt
::
SystemError
(
errno
,
"cannot create locale"
));
}
~
Locale
()
{
freelocale
(
locale_
);
}
Type
get
()
const
{
return
locale_
;
}
// Converts string to floating-point number and advances str past the end
// of the parsed input.
double
strtod
(
const
char
*&
str
)
const
{
char
*
end
=
FMT_NULL
;
double
result
=
strtod_l
(
str
,
&
end
,
locale_
);
str
=
end
;
return
result
;
}
};
#endif // FMT_LOCALE
}
// namespace fmt
#if !FMT_USE_RVALUE_REFERENCES
namespace
std
{
// For compatibility with C++98.
inline
fmt
::
BufferedFile
&
move
(
fmt
::
BufferedFile
&
f
)
{
return
f
;
}
inline
fmt
::
File
&
move
(
fmt
::
File
&
f
)
{
return
f
;
}
}
// namespace std
#endif
#endif // FMT_POSIX_H_
include/spdlog/fmt/bundled/printf.cc
deleted
100644 → 0
View file @
378c7789
/*
Formatting library for C++
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#include "format.h"
#include "printf.h"
namespace
fmt
{
template
<
typename
Char
>
void
printf
(
BasicWriter
<
Char
>
&
w
,
BasicCStringRef
<
Char
>
format
,
ArgList
args
);
FMT_FUNC
int
fprintf
(
std
::
FILE
*
f
,
CStringRef
format
,
ArgList
args
)
{
MemoryWriter
w
;
printf
(
w
,
format
,
args
);
std
::
size_t
size
=
w
.
size
();
return
std
::
fwrite
(
w
.
data
(),
1
,
size
,
f
)
<
size
?
-
1
:
static_cast
<
int
>
(
size
);
}
#ifndef FMT_HEADER_ONLY
template
void
PrintfFormatter
<
char
>::
format
(
CStringRef
format
);
template
void
PrintfFormatter
<
wchar_t
>::
format
(
WCStringRef
format
);
#endif // FMT_HEADER_ONLY
}
// namespace fmt
include/spdlog/fmt/bundled/printf.h
deleted
100644 → 0
View file @
378c7789
/*
Formatting library for C++
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#ifndef FMT_PRINTF_H_
#define FMT_PRINTF_H_
#include <algorithm> // std::fill_n
#include <limits> // std::numeric_limits
#include "ostream.h"
namespace
fmt
{
namespace
internal
{
// Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers.
template
<
bool
IsSigned
>
struct
IntChecker
{
template
<
typename
T
>
static
bool
fits_in_int
(
T
value
)
{
unsigned
max
=
std
::
numeric_limits
<
int
>::
max
();
return
value
<=
max
;
}
static
bool
fits_in_int
(
bool
)
{
return
true
;
}
};
template
<>
struct
IntChecker
<
true
>
{
template
<
typename
T
>
static
bool
fits_in_int
(
T
value
)
{
return
value
>=
std
::
numeric_limits
<
int
>::
min
()
&&
value
<=
std
::
numeric_limits
<
int
>::
max
();
}
static
bool
fits_in_int
(
int
)
{
return
true
;
}
};
class
PrecisionHandler
:
public
ArgVisitor
<
PrecisionHandler
,
int
>
{
public
:
void
report_unhandled_arg
()
{
FMT_THROW
(
FormatError
(
"precision is not integer"
));
}
template
<
typename
T
>
int
visit_any_int
(
T
value
)
{
if
(
!
IntChecker
<
std
::
numeric_limits
<
T
>::
is_signed
>::
fits_in_int
(
value
))
FMT_THROW
(
FormatError
(
"number is too big"
));
return
static_cast
<
int
>
(
value
);
}
};
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
class
IsZeroInt
:
public
ArgVisitor
<
IsZeroInt
,
bool
>
{
public
:
template
<
typename
T
>
bool
visit_any_int
(
T
value
)
{
return
value
==
0
;
}
};
// returns the default type for format specific "%s"
class
DefaultType
:
public
ArgVisitor
<
DefaultType
,
char
>
{
public
:
char
visit_char
(
int
)
{
return
'c'
;
}
char
visit_bool
(
bool
)
{
return
's'
;
}
char
visit_pointer
(
const
void
*
)
{
return
'p'
;
}
template
<
typename
T
>
char
visit_any_int
(
T
)
{
return
'd'
;
}
template
<
typename
T
>
char
visit_any_double
(
T
)
{
return
'g'
;
}
char
visit_unhandled_arg
()
{
return
's'
;
}
};
template
<
typename
T
,
typename
U
>
struct
is_same
{
enum
{
value
=
0
};
};
template
<
typename
T
>
struct
is_same
<
T
,
T
>
{
enum
{
value
=
1
};
};
// An argument visitor that converts an integer argument to T for printf,
// if T is an integral type. If T is void, the argument is converted to
// corresponding signed or unsigned type depending on the type specifier:
// 'd' and 'i' - signed, other - unsigned)
template
<
typename
T
=
void
>
class
ArgConverter
:
public
ArgVisitor
<
ArgConverter
<
T
>
,
void
>
{
private
:
internal
::
Arg
&
arg_
;
wchar_t
type_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
ArgConverter
);
public
:
ArgConverter
(
internal
::
Arg
&
arg
,
wchar_t
type
)
:
arg_
(
arg
)
,
type_
(
type
)
{
}
void
visit_bool
(
bool
value
)
{
if
(
type_
!=
's'
)
visit_any_int
(
value
);
}
void
visit_char
(
int
value
)
{
if
(
type_
!=
's'
)
visit_any_int
(
value
);
}
template
<
typename
U
>
void
visit_any_int
(
U
value
)
{
bool
is_signed
=
type_
==
'd'
||
type_
==
'i'
;
if
(
type_
==
's'
)
{
is_signed
=
std
::
numeric_limits
<
U
>::
is_signed
;
}
using
internal
::
Arg
;
typedef
typename
internal
::
Conditional
<
is_same
<
T
,
void
>::
value
,
U
,
T
>::
type
TargetType
;
if
(
const_check
(
sizeof
(
TargetType
)
<=
sizeof
(
int
)))
{
// Extra casts are used to silence warnings.
if
(
is_signed
)
{
arg_
.
type
=
Arg
::
INT
;
arg_
.
int_value
=
static_cast
<
int
>
(
static_cast
<
TargetType
>
(
value
));
}
else
{
arg_
.
type
=
Arg
::
UINT
;
typedef
typename
internal
::
MakeUnsigned
<
TargetType
>::
Type
Unsigned
;
arg_
.
uint_value
=
static_cast
<
unsigned
>
(
static_cast
<
Unsigned
>
(
value
));
}
}
else
{
if
(
is_signed
)
{
arg_
.
type
=
Arg
::
LONG_LONG
;
// glibc's printf doesn't sign extend arguments of smaller types:
// std::printf("%lld", -42); // prints "4294967254"
// but we don't have to do the same because it's a UB.
arg_
.
long_long_value
=
static_cast
<
LongLong
>
(
value
);
}
else
{
arg_
.
type
=
Arg
::
ULONG_LONG
;
arg_
.
ulong_long_value
=
static_cast
<
typename
internal
::
MakeUnsigned
<
U
>::
Type
>
(
value
);
}
}
}
};
// Converts an integer argument to char for printf.
class
CharConverter
:
public
ArgVisitor
<
CharConverter
,
void
>
{
private
:
internal
::
Arg
&
arg_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
CharConverter
);
public
:
explicit
CharConverter
(
internal
::
Arg
&
arg
)
:
arg_
(
arg
)
{
}
template
<
typename
T
>
void
visit_any_int
(
T
value
)
{
arg_
.
type
=
internal
::
Arg
::
CHAR
;
arg_
.
int_value
=
static_cast
<
char
>
(
value
);
}
};
// Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative.
class
WidthHandler
:
public
ArgVisitor
<
WidthHandler
,
unsigned
>
{
private
:
FormatSpec
&
spec_
;
FMT_DISALLOW_COPY_AND_ASSIGN
(
WidthHandler
);
public
:
explicit
WidthHandler
(
FormatSpec
&
spec
)
:
spec_
(
spec
)
{
}
void
report_unhandled_arg
()
{
FMT_THROW
(
FormatError
(
"width is not integer"
));
}
template
<
typename
T
>
unsigned
visit_any_int
(
T
value
)
{
typedef
typename
internal
::
IntTraits
<
T
>::
MainType
UnsignedType
;
UnsignedType
width
=
static_cast
<
UnsignedType
>
(
value
);
if
(
internal
::
is_negative
(
value
))
{
spec_
.
align_
=
ALIGN_LEFT
;
width
=
0
-
width
;
}
unsigned
int_max
=
std
::
numeric_limits
<
int
>::
max
();
if
(
width
>
int_max
)
FMT_THROW
(
FormatError
(
"number is too big"
));
return
static_cast
<
unsigned
>
(
width
);
}
};
}
// namespace internal
/**
\rst
A ``printf`` argument formatter based on the `curiously recurring template
pattern <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_.
To use `~fmt::BasicPrintfArgFormatter` define a subclass that implements some
or all of the visit methods with the same signatures as the methods in
`~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`.
Pass the subclass as the *Impl* template parameter. When a formatting
function processes an argument, it will dispatch to a visit method
specific to the argument type. For example, if the argument type is
``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass
will be called. If the subclass doesn't contain a method with this signature,
then a corresponding method of `~fmt::BasicPrintfArgFormatter` or its
superclass will be called.
\endrst
*/
template
<
typename
Impl
,
typename
Char
,
typename
Spec
>
class
BasicPrintfArgFormatter
:
public
internal
::
ArgFormatterBase
<
Impl
,
Char
,
Spec
>
{
private
:
void
write_null_pointer
()
{
this
->
spec
().
type_
=
0
;
this
->
write
(
"(nil)"
);
}
typedef
internal
::
ArgFormatterBase
<
Impl
,
Char
,
Spec
>
Base
;
public
:
/**
\rst
Constructs an argument formatter object.
*writer* is a reference to the output writer and *spec* contains format
specifier information for standard argument types.
\endrst
*/
BasicPrintfArgFormatter
(
BasicWriter
<
Char
>
&
w
,
Spec
&
s
)
:
internal
::
ArgFormatterBase
<
Impl
,
Char
,
Spec
>
(
w
,
s
)
{
}
/** Formats an argument of type ``bool``. */
void
visit_bool
(
bool
value
)
{
Spec
&
fmt_spec
=
this
->
spec
();
if
(
fmt_spec
.
type_
!=
's'
)
return
this
->
visit_any_int
(
value
);
fmt_spec
.
type_
=
0
;
this
->
write
(
value
);
}
/** Formats a character. */
void
visit_char
(
int
value
)
{
const
Spec
&
fmt_spec
=
this
->
spec
();
BasicWriter
<
Char
>
&
w
=
this
->
writer
();
if
(
fmt_spec
.
type_
&&
fmt_spec
.
type_
!=
'c'
)
w
.
write_int
(
value
,
fmt_spec
);
typedef
typename
BasicWriter
<
Char
>::
CharPtr
CharPtr
;
CharPtr
out
=
CharPtr
();
if
(
fmt_spec
.
width_
>
1
)
{
Char
fill
=
' '
;
out
=
w
.
grow_buffer
(
fmt_spec
.
width_
);
if
(
fmt_spec
.
align_
!=
ALIGN_LEFT
)
{
std
::
fill_n
(
out
,
fmt_spec
.
width_
-
1
,
fill
);
out
+=
fmt_spec
.
width_
-
1
;
}
else
{
std
::
fill_n
(
out
+
1
,
fmt_spec
.
width_
-
1
,
fill
);
}
}
else
{
out
=
w
.
grow_buffer
(
1
);
}
*
out
=
static_cast
<
Char
>
(
value
);
}
/** Formats a null-terminated C string. */
void
visit_cstring
(
const
char
*
value
)
{
if
(
value
)
Base
::
visit_cstring
(
value
);
else
if
(
this
->
spec
().
type_
==
'p'
)
write_null_pointer
();
else
this
->
write
(
"(null)"
);
}
/** Formats a pointer. */
void
visit_pointer
(
const
void
*
value
)
{
if
(
value
)
return
Base
::
visit_pointer
(
value
);
this
->
spec
().
type_
=
0
;
write_null_pointer
();
}
/** Formats an argument of a custom (user-defined) type. */
void
visit_custom
(
internal
::
Arg
::
CustomValue
c
)
{
BasicFormatter
<
Char
>
formatter
(
ArgList
(),
this
->
writer
());
const
Char
format_str
[]
=
{
'}'
,
0
};
const
Char
*
format
=
format_str
;
c
.
format
(
&
formatter
,
c
.
value
,
&
format
);
}
};
/** The default printf argument formatter. */
template
<
typename
Char
>
class
PrintfArgFormatter
:
public
BasicPrintfArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
,
FormatSpec
>
{
public
:
/** Constructs an argument formatter object. */
PrintfArgFormatter
(
BasicWriter
<
Char
>
&
w
,
FormatSpec
&
s
)
:
BasicPrintfArgFormatter
<
PrintfArgFormatter
<
Char
>
,
Char
,
FormatSpec
>
(
w
,
s
)
{
}
};
/** This template formats data and writes the output to a writer. */
template
<
typename
Char
,
typename
ArgFormatter
=
PrintfArgFormatter
<
Char
>>
class
PrintfFormatter
:
private
internal
::
FormatterBase
{
private
:
BasicWriter
<
Char
>
&
writer_
;
void
parse_flags
(
FormatSpec
&
spec
,
const
Char
*&
s
);
// Returns the argument with specified index or, if arg_index is equal
// to the maximum unsigned value, the next argument.
internal
::
Arg
get_arg
(
const
Char
*
s
,
unsigned
arg_index
=
(
std
::
numeric_limits
<
unsigned
>::
max
)());
// Parses argument index, flags and width and returns the argument index.
unsigned
parse_header
(
const
Char
*&
s
,
FormatSpec
&
spec
);
public
:
/**
\rst
Constructs a ``PrintfFormatter`` object. References to the arguments and
the writer are stored in the formatter object so make sure they have
appropriate lifetimes.
\endrst
*/
explicit
PrintfFormatter
(
const
ArgList
&
al
,
BasicWriter
<
Char
>
&
w
)
:
FormatterBase
(
al
)
,
writer_
(
w
)
{
}
/** Formats stored arguments and writes the output to the writer. */
void
format
(
BasicCStringRef
<
Char
>
format_str
);
};
template
<
typename
Char
,
typename
AF
>
void
PrintfFormatter
<
Char
,
AF
>::
parse_flags
(
FormatSpec
&
spec
,
const
Char
*&
s
)
{
for
(;;)
{
switch
(
*
s
++
)
{
case
'-'
:
spec
.
align_
=
ALIGN_LEFT
;
break
;
case
'+'
:
spec
.
flags_
|=
SIGN_FLAG
|
PLUS_FLAG
;
break
;
case
'0'
:
spec
.
fill_
=
'0'
;
break
;
case
' '
:
spec
.
flags_
|=
SIGN_FLAG
;
break
;
case
'#'
:
spec
.
flags_
|=
HASH_FLAG
;
break
;
default
:
--
s
;
return
;
}
}
}
template
<
typename
Char
,
typename
AF
>
internal
::
Arg
PrintfFormatter
<
Char
,
AF
>::
get_arg
(
const
Char
*
s
,
unsigned
arg_index
)
{
(
void
)
s
;
const
char
*
error
=
FMT_NULL
;
internal
::
Arg
arg
=
arg_index
==
std
::
numeric_limits
<
unsigned
>::
max
()
?
next_arg
(
error
)
:
FormatterBase
::
get_arg
(
arg_index
-
1
,
error
);
if
(
error
)
FMT_THROW
(
FormatError
(
!*
s
?
"invalid format string"
:
error
));
return
arg
;
}
template
<
typename
Char
,
typename
AF
>
unsigned
PrintfFormatter
<
Char
,
AF
>::
parse_header
(
const
Char
*&
s
,
FormatSpec
&
spec
)
{
unsigned
arg_index
=
std
::
numeric_limits
<
unsigned
>::
max
();
Char
c
=
*
s
;
if
(
c
>=
'0'
&&
c
<=
'9'
)
{
// Parse an argument index (if followed by '$') or a width possibly
// preceded with '0' flag(s).
unsigned
value
=
internal
::
parse_nonnegative_int
(
s
);
if
(
*
s
==
'$'
)
// value is an argument index
{
++
s
;
arg_index
=
value
;
}
else
{
if
(
c
==
'0'
)
spec
.
fill_
=
'0'
;
if
(
value
!=
0
)
{
// Nonzero value means that we parsed width and don't need to
// parse it or flags again, so return now.
spec
.
width_
=
value
;
return
arg_index
;
}
}
}
parse_flags
(
spec
,
s
);
// Parse width.
if
(
*
s
>=
'0'
&&
*
s
<=
'9'
)
{
spec
.
width_
=
internal
::
parse_nonnegative_int
(
s
);
}
else
if
(
*
s
==
'*'
)
{
++
s
;
spec
.
width_
=
internal
::
WidthHandler
(
spec
).
visit
(
get_arg
(
s
));
}
return
arg_index
;
}
template
<
typename
Char
,
typename
AF
>
void
PrintfFormatter
<
Char
,
AF
>::
format
(
BasicCStringRef
<
Char
>
format_str
)
{
const
Char
*
start
=
format_str
.
c_str
();
const
Char
*
s
=
start
;
while
(
*
s
)
{
Char
c
=
*
s
++
;
if
(
c
!=
'%'
)
continue
;
if
(
*
s
==
c
)
{
write
(
writer_
,
start
,
s
);
start
=
++
s
;
continue
;
}
write
(
writer_
,
start
,
s
-
1
);
FormatSpec
spec
;
spec
.
align_
=
ALIGN_RIGHT
;
// Parse argument index, flags and width.
unsigned
arg_index
=
parse_header
(
s
,
spec
);
// Parse precision.
if
(
*
s
==
'.'
)
{
++
s
;
if
(
'0'
<=
*
s
&&
*
s
<=
'9'
)
{
spec
.
precision_
=
static_cast
<
int
>
(
internal
::
parse_nonnegative_int
(
s
));
}
else
if
(
*
s
==
'*'
)
{
++
s
;
spec
.
precision_
=
internal
::
PrecisionHandler
().
visit
(
get_arg
(
s
));
}
else
{
spec
.
precision_
=
0
;
}
}
using
internal
::
Arg
;
Arg
arg
=
get_arg
(
s
,
arg_index
);
if
(
spec
.
flag
(
HASH_FLAG
)
&&
internal
::
IsZeroInt
().
visit
(
arg
))
spec
.
flags_
&=
~
internal
::
to_unsigned
<
int
>
(
HASH_FLAG
);
if
(
spec
.
fill_
==
'0'
)
{
if
(
arg
.
type
<=
Arg
::
LAST_NUMERIC_TYPE
)
spec
.
align_
=
ALIGN_NUMERIC
;
else
spec
.
fill_
=
' '
;
// Ignore '0' flag for non-numeric types.
}
// Parse length and convert the argument to the required type.
using
internal
::
ArgConverter
;
switch
(
*
s
++
)
{
case
'h'
:
if
(
*
s
==
'h'
)
ArgConverter
<
signed
char
>
(
arg
,
*++
s
).
visit
(
arg
);
else
ArgConverter
<
short
>
(
arg
,
*
s
).
visit
(
arg
);
break
;
case
'l'
:
if
(
*
s
==
'l'
)
ArgConverter
<
fmt
::
LongLong
>
(
arg
,
*++
s
).
visit
(
arg
);
else
ArgConverter
<
long
>
(
arg
,
*
s
).
visit
(
arg
);
break
;
case
'j'
:
ArgConverter
<
intmax_t
>
(
arg
,
*
s
).
visit
(
arg
);
break
;
case
'z'
:
ArgConverter
<
std
::
size_t
>
(
arg
,
*
s
).
visit
(
arg
);
break
;
case
't'
:
ArgConverter
<
std
::
ptrdiff_t
>
(
arg
,
*
s
).
visit
(
arg
);
break
;
case
'L'
:
// printf produces garbage when 'L' is omitted for long double, no
// need to do the same.
break
;
default
:
--
s
;
ArgConverter
<
void
>
(
arg
,
*
s
).
visit
(
arg
);
}
// Parse type.
if
(
!*
s
)
FMT_THROW
(
FormatError
(
"invalid format string"
));
spec
.
type_
=
static_cast
<
char
>
(
*
s
++
);
if
(
spec
.
type_
==
's'
)
{
// set the format type to the default if 's' is specified
spec
.
type_
=
internal
::
DefaultType
().
visit
(
arg
);
}
if
(
arg
.
type
<=
Arg
::
LAST_INTEGER_TYPE
)
{
// Normalize type.
switch
(
spec
.
type_
)
{
case
'i'
:
case
'u'
:
spec
.
type_
=
'd'
;
break
;
case
'c'
:
// TODO: handle wchar_t
internal
::
CharConverter
(
arg
).
visit
(
arg
);
break
;
}
}
start
=
s
;
// Format argument.
AF
(
writer_
,
spec
).
visit
(
arg
);
}
write
(
writer_
,
start
,
s
);
}
inline
void
printf
(
Writer
&
w
,
CStringRef
format
,
ArgList
args
)
{
PrintfFormatter
<
char
>
(
args
,
w
).
format
(
format
);
}
FMT_VARIADIC
(
void
,
printf
,
Writer
&
,
CStringRef
)
inline
void
printf
(
WWriter
&
w
,
WCStringRef
format
,
ArgList
args
)
{
PrintfFormatter
<
wchar_t
>
(
args
,
w
).
format
(
format
);
}
FMT_VARIADIC
(
void
,
printf
,
WWriter
&
,
WCStringRef
)
/**
\rst
Formats arguments and returns the result as a string.
**Example**::
std::string message = fmt::sprintf("The answer is %d", 42);
\endrst
*/
inline
std
::
string
sprintf
(
CStringRef
format
,
ArgList
args
)
{
MemoryWriter
w
;
printf
(
w
,
format
,
args
);
return
w
.
str
();
}
FMT_VARIADIC
(
std
::
string
,
sprintf
,
CStringRef
)
inline
std
::
wstring
sprintf
(
WCStringRef
format
,
ArgList
args
)
{
WMemoryWriter
w
;
printf
(
w
,
format
,
args
);
return
w
.
str
();
}
FMT_VARIADIC_W
(
std
::
wstring
,
sprintf
,
WCStringRef
)
/**
\rst
Prints formatted data to the file *f*.
**Example**::
fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst
*/
FMT_API
int
fprintf
(
std
::
FILE
*
f
,
CStringRef
format
,
ArgList
args
);
FMT_VARIADIC
(
int
,
fprintf
,
std
::
FILE
*
,
CStringRef
)
/**
\rst
Prints formatted data to ``stdout``.
**Example**::
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
*/
inline
int
printf
(
CStringRef
format
,
ArgList
args
)
{
return
fprintf
(
stdout
,
format
,
args
);
}
FMT_VARIADIC
(
int
,
printf
,
CStringRef
)
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fprintf(cerr, "Don't %s!", "panic");
\endrst
*/
inline
int
fprintf
(
std
::
ostream
&
os
,
CStringRef
format_str
,
ArgList
args
)
{
MemoryWriter
w
;
printf
(
w
,
format_str
,
args
);
internal
::
write
(
os
,
w
);
return
static_cast
<
int
>
(
w
.
size
());
}
FMT_VARIADIC
(
int
,
fprintf
,
std
::
ostream
&
,
CStringRef
)
}
// namespace fmt
#ifdef FMT_HEADER_ONLY
#include "printf.cc"
#endif
#endif // FMT_PRINTF_H_
include/spdlog/fmt/bundled/time.h
deleted
100644 → 0
View file @
378c7789
/*
Formatting library for C++ - time formatting
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#ifndef FMT_TIME_H_
#define FMT_TIME_H_
#include "format.h"
#include <ctime>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4702) // unreachable code
#pragma warning(disable : 4996) // "deprecated" functions
#endif
namespace
fmt
{
template
<
typename
ArgFormatter
>
void
format_arg
(
BasicFormatter
<
char
,
ArgFormatter
>
&
f
,
const
char
*&
format_str
,
const
std
::
tm
&
tm
)
{
if
(
*
format_str
==
':'
)
++
format_str
;
const
char
*
end
=
format_str
;
while
(
*
end
&&
*
end
!=
'}'
)
++
end
;
if
(
*
end
!=
'}'
)
FMT_THROW
(
FormatError
(
"missing '}' in format string"
));
internal
::
MemoryBuffer
<
char
,
internal
::
INLINE_BUFFER_SIZE
>
format
;
format
.
append
(
format_str
,
end
+
1
);
format
[
format
.
size
()
-
1
]
=
'\0'
;
Buffer
<
char
>
&
buffer
=
f
.
writer
().
buffer
();
std
::
size_t
start
=
buffer
.
size
();
for
(;;)
{
std
::
size_t
size
=
buffer
.
capacity
()
-
start
;
std
::
size_t
count
=
std
::
strftime
(
&
buffer
[
start
],
size
,
&
format
[
0
],
&
tm
);
if
(
count
!=
0
)
{
buffer
.
resize
(
start
+
count
);
break
;
}
if
(
size
>=
format
.
size
()
*
256
)
{
// If the buffer is 256 times larger than the format string, assume
// that `strftime` gives an empty result. There doesn't seem to be a
// better way to distinguish the two cases:
// https://github.com/fmtlib/fmt/issues/367
break
;
}
const
std
::
size_t
MIN_GROWTH
=
10
;
buffer
.
reserve
(
buffer
.
capacity
()
+
(
size
>
MIN_GROWTH
?
size
:
MIN_GROWTH
));
}
format_str
=
end
+
1
;
}
namespace
internal
{
inline
Null
<>
localtime_r
(...)
{
return
Null
<>
();
}
inline
Null
<>
localtime_s
(...)
{
return
Null
<>
();
}
inline
Null
<>
gmtime_r
(...)
{
return
Null
<>
();
}
inline
Null
<>
gmtime_s
(...)
{
return
Null
<>
();
}
}
// namespace internal
// Thread-safe replacement for std::localtime
inline
std
::
tm
localtime
(
std
::
time_t
time
)
{
struct
LocalTime
{
std
::
time_t
time_
;
std
::
tm
tm_
;
LocalTime
(
std
::
time_t
t
)
:
time_
(
t
)
{
}
bool
run
()
{
using
namespace
fmt
::
internal
;
return
handle
(
localtime_r
(
&
time_
,
&
tm_
));
}
bool
handle
(
std
::
tm
*
tm
)
{
return
tm
!=
FMT_NULL
;
}
bool
handle
(
internal
::
Null
<>
)
{
using
namespace
fmt
::
internal
;
return
fallback
(
localtime_s
(
&
tm_
,
&
time_
));
}
bool
fallback
(
int
res
)
{
return
res
==
0
;
}
bool
fallback
(
internal
::
Null
<>
)
{
using
namespace
fmt
::
internal
;
std
::
tm
*
tm
=
std
::
localtime
(
&
time_
);
if
(
tm
)
tm_
=
*
tm
;
return
tm
!=
FMT_NULL
;
}
};
LocalTime
lt
(
time
);
if
(
lt
.
run
())
return
lt
.
tm_
;
// Too big time values may be unsupported.
FMT_THROW
(
fmt
::
FormatError
(
"time_t value out of range"
));
return
std
::
tm
();
}
// Thread-safe replacement for std::gmtime
inline
std
::
tm
gmtime
(
std
::
time_t
time
)
{
struct
GMTime
{
std
::
time_t
time_
;
std
::
tm
tm_
;
GMTime
(
std
::
time_t
t
)
:
time_
(
t
)
{
}
bool
run
()
{
using
namespace
fmt
::
internal
;
return
handle
(
gmtime_r
(
&
time_
,
&
tm_
));
}
bool
handle
(
std
::
tm
*
tm
)
{
return
tm
!=
FMT_NULL
;
}
bool
handle
(
internal
::
Null
<>
)
{
using
namespace
fmt
::
internal
;
return
fallback
(
gmtime_s
(
&
tm_
,
&
time_
));
}
bool
fallback
(
int
res
)
{
return
res
==
0
;
}
bool
fallback
(
internal
::
Null
<>
)
{
std
::
tm
*
tm
=
std
::
gmtime
(
&
time_
);
if
(
tm
!=
FMT_NULL
)
tm_
=
*
tm
;
return
tm
!=
FMT_NULL
;
}
};
GMTime
gt
(
time
);
if
(
gt
.
run
())
return
gt
.
tm_
;
// Too big time values may be unsupported.
FMT_THROW
(
fmt
::
FormatError
(
"time_t value out of range"
));
return
std
::
tm
();
}
}
// namespace fmt
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif // FMT_TIME_H_
include/spdlog/fmt/fmt.h
View file @
cdbf2e36
//
// Copyright(c) 2016 Gabi Melman.
// Copyright(c) 2016
-2018
Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
...
...
@@ -11,23 +11,18 @@
//
#if !defined(SPDLOG_FMT_EXTERNAL)
#ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY
#endif
#ifndef FMT_USE_WINDOWS_H
#define FMT_USE_WINDOWS_H 0
#endif
#include "bundled/core.h"
#include "bundled/format.h"
#if defined(SPDLOG_FMT_PRINTF)
#include "bundled/printf.h"
#endif
#else // external fmtlib
#include <fmt/core.h>
#include <fmt/format.h>
#if defined(SPDLOG_FMT_PRINTF)
#include <fmt/printf.h>
#endif
#endif
include/spdlog/sinks/daily_file_sink.h
View file @
cdbf2e36
...
...
@@ -30,10 +30,10 @@ struct default_daily_file_name_calculator
std
::
tm
tm
=
spdlog
::
details
::
os
::
localtime
();
filename_t
basename
,
ext
;
std
::
tie
(
basename
,
ext
)
=
details
::
file_helper
::
split_by_extenstion
(
filename
);
std
::
conditional
<
std
::
is_same
<
filename_t
::
value_type
,
char
>::
value
,
fmt
::
MemoryWriter
,
fmt
::
WMemoryWrit
er
>::
type
w
;
w
.
write
(
SPDLOG_FILENAME_T
(
"{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}{}"
),
basename
,
tm
.
tm_year
+
1900
,
tm
.
tm_mon
+
1
,
tm
.
tm_mday
,
tm
.
tm_hour
,
tm
.
tm_min
,
ext
);
return
w
.
str
(
);
std
::
conditional
<
std
::
is_same
<
filename_t
::
value_type
,
char
>::
value
,
fmt
::
memory_buffer
,
fmt
::
wmemory_buff
er
>::
type
w
;
fmt
::
format_to
(
w
,
SPDLOG_FILENAME_T
(
"{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}{}"
),
basename
,
tm
.
tm_year
+
1900
,
tm
.
tm_mon
+
1
,
tm
.
tm_
mday
,
tm
.
tm_
hour
,
tm
.
tm_min
,
ext
);
return
fmt
::
to_string
(
w
);
}
};
...
...
@@ -48,9 +48,9 @@ struct dateonly_daily_file_name_calculator
std
::
tm
tm
=
spdlog
::
details
::
os
::
localtime
();
filename_t
basename
,
ext
;
std
::
tie
(
basename
,
ext
)
=
details
::
file_helper
::
split_by_extenstion
(
filename
);
std
::
conditional
<
std
::
is_same
<
filename_t
::
value_type
,
char
>::
value
,
fmt
::
MemoryWriter
,
fmt
::
WMemoryWrit
er
>::
type
w
;
w
.
write
(
SPDLOG_FILENAME_T
(
"{}_{:04d}-{:02d}-{:02d}{}"
),
basename
,
tm
.
tm_year
+
1900
,
tm
.
tm_mon
+
1
,
tm
.
tm_mday
,
ext
);
return
w
.
str
(
);
std
::
conditional
<
std
::
is_same
<
filename_t
::
value_type
,
char
>::
value
,
fmt
::
memory_buffer
,
fmt
::
wmemory_buff
er
>::
type
w
;
fmt
::
format_to
(
w
,
SPDLOG_FILENAME_T
(
"{}_{:04d}-{:02d}-{:02d}{}"
),
basename
,
tm
.
tm_year
+
1900
,
tm
.
tm_mon
+
1
,
tm
.
tm_mday
,
ext
);
return
fmt
::
to_string
(
w
);
}
};
...
...
include/spdlog/sinks/rotating_file_sink.h
View file @
cdbf2e36
...
...
@@ -40,18 +40,18 @@ public:
// e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt".
static
filename_t
calc_filename
(
const
filename_t
&
filename
,
std
::
size_t
index
)
{
typename
std
::
conditional
<
std
::
is_same
<
filename_t
::
value_type
,
char
>::
value
,
fmt
::
MemoryWriter
,
fmt
::
WMemoryWrit
er
>::
type
w
;
typename
std
::
conditional
<
std
::
is_same
<
filename_t
::
value_type
,
char
>::
value
,
fmt
::
memory_buffer
,
fmt
::
wmemory_buff
er
>::
type
w
;
if
(
index
!=
0u
)
{
filename_t
basename
,
ext
;
std
::
tie
(
basename
,
ext
)
=
details
::
file_helper
::
split_by_extenstion
(
filename
);
w
.
write
(
SPDLOG_FILENAME_T
(
"{}.{}{}"
),
basename
,
index
,
ext
);
fmt
::
format_to
(
w
,
SPDLOG_FILENAME_T
(
"{}.{}{}"
),
basename
,
index
,
ext
);
}
else
{
w
.
write
(
SPDLOG_FILENAME_T
(
"{}"
),
filename
);
fmt
::
format_to
(
w
,
SPDLOG_FILENAME_T
(
"{}"
),
filename
);
}
return
w
.
str
(
);
return
fmt
::
to_string
(
w
);
}
protected
:
...
...
include/spdlog/sinks/syslog_sink.h
View file @
cdbf2e36
...
...
@@ -50,7 +50,7 @@ public:
void
log
(
const
details
::
log_msg
&
msg
)
override
{
::
syslog
(
syslog_prio_from_level
(
msg
),
"%s"
,
msg
.
raw
.
str
(
).
c_str
());
::
syslog
(
syslog_prio_from_level
(
msg
),
"%s"
,
fmt
::
to_string
(
msg
.
raw
).
c_str
());
}
void
flush
()
override
{}
...
...
tests/Makefile
View file @
cdbf2e36
CXX
?=
g++
ifeq
($(STYLE),printf)
$(info
***
PRINTF
STYLE
***)
CXXFLAGS
=
-DSPDLOG_FMT_PRINTF
-Wall
-pedantic
-std
=
c++11
-pthread
-O3
-I
../include
else
$(info
***
FORMAT
STYLE
***)
CXXFLAGS
=
-Wall
-pedantic
-std
=
c++11
-pthread
-O3
-I
../include
endif
CXXFLAGS
=
-Wall
-pedantic
-std
=
c++11
-pthread
-O3
-I
../include
LDPFALGS
=
-pthread
CPP_FILES
:=
$
(
wildcard
*
.cpp
)
...
...
tests/errors.cpp
View file @
cdbf2e36
...
...
@@ -26,13 +26,8 @@ TEST_CASE("default_error_handler", "[errors]]")
auto
logger
=
spdlog
::
create
<
spdlog
::
sinks
::
simple_file_sink_mt
>
(
"test-error"
,
filename
,
true
);
logger
->
set_pattern
(
"%v"
);
#if !defined(SPDLOG_FMT_PRINTF)
logger
->
info
(
"Test message {} {}"
,
1
);
logger
->
info
(
"Test message {}"
,
2
);
#else
logger
->
info
(
"Test message %d %d"
,
1
);
logger
->
info
(
"Test message %d"
,
2
);
#endif
logger
->
flush
();
REQUIRE
(
file_contents
(
filename
)
==
std
::
string
(
"Test message 2
\n
"
));
...
...
@@ -50,11 +45,8 @@ TEST_CASE("custom_error_handler", "[errors]]")
logger
->
flush_on
(
spdlog
::
level
::
info
);
logger
->
set_error_handler
([
=
](
const
std
::
string
&
)
{
throw
custom_ex
();
});
logger
->
info
(
"Good message #1"
);
#if !defined(SPDLOG_FMT_PRINTF)
REQUIRE_THROWS_AS
(
logger
->
info
(
"Bad format msg {} {}"
,
"xxx"
),
custom_ex
);
#else
REQUIRE_THROWS_AS
(
logger
->
info
(
"Bad format msg %s %s"
,
"xxx"
),
custom_ex
);
#endif
logger
->
info
(
"Good message #2"
);
REQUIRE
(
count_lines
(
filename
)
==
2
);
}
...
...
@@ -91,11 +83,7 @@ TEST_CASE("async_error_handler", "[errors]]")
ofs
<<
err_msg
;
});
logger
->
info
(
"Good message #1"
);
#if !defined(SPDLOG_FMT_PRINTF)
logger
->
info
(
"Bad format msg {} {}"
,
"xxx"
);
#else
logger
->
info
(
"Bad format msg %s %s"
,
"xxx"
);
#endif
logger
->
info
(
"Good message #2"
);
spdlog
::
drop
(
"logger"
);
// force logger to drain the queue and shutdown
}
...
...
tests/file_log.cpp
View file @
cdbf2e36
...
...
@@ -11,13 +11,9 @@ TEST_CASE("simple_file_logger", "[simple_logger]]")
auto
logger
=
spdlog
::
create
<
spdlog
::
sinks
::
simple_file_sink_mt
>
(
"logger"
,
filename
);
logger
->
set_pattern
(
"%v"
);
#if !defined(SPDLOG_FMT_PRINTF)
logger
->
info
(
"Test message {}"
,
1
);
logger
->
info
(
"Test message {}"
,
2
);
#else
logger
->
info
(
"Test message %d"
,
1
);
logger
->
info
(
"Test message %d"
,
2
);
#endif
logger
->
flush
();
REQUIRE
(
file_contents
(
filename
)
==
std
::
string
(
"Test message 1
\n
Test message 2
\n
"
));
REQUIRE
(
count_lines
(
filename
)
==
2
);
...
...
@@ -35,13 +31,8 @@ TEST_CASE("flush_on", "[flush_on]]")
logger
->
trace
(
"Should not be flushed"
);
REQUIRE
(
count_lines
(
filename
)
==
0
);
#if !defined(SPDLOG_FMT_PRINTF)
logger
->
info
(
"Test message {}"
,
1
);
logger
->
info
(
"Test message {}"
,
2
);
#else
logger
->
info
(
"Test message %d"
,
1
);
logger
->
info
(
"Test message %d"
,
2
);
#endif
logger
->
flush
();
REQUIRE
(
file_contents
(
filename
)
==
std
::
string
(
"Should not be flushed
\n
Test message 1
\n
Test message 2
\n
"
));
REQUIRE
(
count_lines
(
filename
)
==
3
);
...
...
@@ -56,11 +47,7 @@ TEST_CASE("rotating_file_logger1", "[rotating_logger]]")
for
(
int
i
=
0
;
i
<
10
;
++
i
)
{
#if !defined(SPDLOG_FMT_PRINTF)
logger
->
info
(
"Test message {}"
,
i
);
#else
logger
->
info
(
"Test message %d"
,
i
);
#endif
}
logger
->
flush
();
...
...
@@ -82,11 +69,8 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
REQUIRE
(
count_lines
(
filename
)
==
10
);
for
(
int
i
=
0
;
i
<
1000
;
i
++
)
{
#if !defined(SPDLOG_FMT_PRINTF)
logger
->
info
(
"Test message {}"
,
i
);
#else
logger
->
info
(
"Test message %d"
,
i
);
#endif
}
logger
->
flush
();
...
...
@@ -108,11 +92,7 @@ TEST_CASE("daily_logger", "[daily_logger]]")
logger
->
flush_on
(
spdlog
::
level
::
info
);
for
(
int
i
=
0
;
i
<
10
;
++
i
)
{
#if !defined(SPDLOG_FMT_PRINTF)
logger
->
info
(
"Test message {}"
,
i
);
#else
logger
->
info
(
"Test message %d"
,
i
);
#endif
}
auto
filename
=
w
.
str
();
...
...
@@ -133,11 +113,8 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger_dateonly]]")
auto
logger
=
spdlog
::
create
<
sink_type
>
(
"logger"
,
basename
,
0
,
0
);
for
(
int
i
=
0
;
i
<
10
;
++
i
)
{
#if !defined(SPDLOG_FMT_PRINTF)
logger
->
info
(
"Test message {}"
,
i
);
#else
logger
->
info
(
"Test message %d"
,
i
);
#endif
}
logger
->
flush
();
auto
filename
=
w
.
str
();
...
...
@@ -169,11 +146,7 @@ TEST_CASE("daily_logger with custom calculator", "[daily_logger_custom]]")
auto
logger
=
spdlog
::
create
<
sink_type
>
(
"logger"
,
basename
,
0
,
0
);
for
(
int
i
=
0
;
i
<
10
;
++
i
)
{
#if !defined(SPDLOG_FMT_PRINTF)
logger
->
info
(
"Test message {}"
,
i
);
#else
logger
->
info
(
"Test message %d"
,
i
);
#endif
}
logger
->
flush
();
...
...
tests/test_macros.cpp
View file @
cdbf2e36
...
...
@@ -31,16 +31,9 @@ TEST_CASE("debug and trace with format strings", "[macros]]")
logger
->
set_pattern
(
"%v"
);
logger
->
set_level
(
spdlog
::
level
::
trace
);
#if !defined(SPDLOG_FMT_PRINTF)
SPDLOG_TRACE
(
logger
,
"Test message {}"
,
1
);
// SPDLOG_DEBUG(logger, "Test message 2");
SPDLOG_DEBUG
(
logger
,
"Test message {}"
,
222
);
#else
SPDLOG_TRACE
(
logger
,
"Test message %d"
,
1
);
// SPDLOG_DEBUG(logger, "Test message 2");
SPDLOG_DEBUG
(
logger
,
"Test message %d"
,
222
);
#endif
logger
->
flush
();
REQUIRE
(
ends_with
(
file_contents
(
filename
),
"Test message 222
\n
"
));
...
...
tests/tests.sln
View file @
cdbf2e36
...
...
@@ -47,8 +47,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bundled", "bundled", "{F0D4
..\include\spdlog\fmt\bundled\ostream.h = ..\include\spdlog\fmt\bundled\ostream.h
..\include\spdlog\fmt\bundled\posix.cc = ..\include\spdlog\fmt\bundled\posix.cc
..\include\spdlog\fmt\bundled\posix.h = ..\include\spdlog\fmt\bundled\posix.h
..\include\spdlog\fmt\bundled\printf.cc = ..\include\spdlog\fmt\bundled\printf.cc
..\include\spdlog\fmt\bundled\printf.h = ..\include\spdlog\fmt\bundled\printf.h
..\include\spdlog\fmt\bundled\time.h = ..\include\spdlog\fmt\bundled\time.h
EndProjectSection
EndProject
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment