Skip to content

Commit e444973

Browse files
committed
Refactoring: use libfmt for messages, warnings and errors
Replaces %s/%d/%f with {} placeholders, see https://fmt.dev/11.1/ - Was already used for tracing - Will become part of the standard in C++20/C++23. - Allows custom types like QCString to be printed without the need for qPrint().
1 parent c110208 commit e444973

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+17394
-1689
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
2727
endif()
2828
option(use_libclang "Add support for libclang parsing." OFF)
2929
option(use_sys_spdlog "Use system spdlog library instead of the one bundled." OFF)
30+
option(use_sys_fmt "Use system fmt library instead of the one bundled." OFF)
3031
option(use_sys_sqlite3 "Use system sqlite3 library instead of the one bundled." OFF)
3132
option(static_libclang "Link to a statically compiled version of LLVM/libclang." OFF)
3233
option(win_static "Link with /MT in stead of /MD on windows" OFF)

deps/fmt/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The include dir contains a copy of the files in deps/spdlog/include/spdlog/fmt/bundled
2+
which is based on fmt version 10.2.1 see https://github.com/fmtlib/fmt/releases

deps/fmt/include/fmt/args.h

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
// Formatting library for C++ - dynamic argument lists
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_ARGS_H_
9+
#define FMT_ARGS_H_
10+
11+
#include <functional> // std::reference_wrapper
12+
#include <memory> // std::unique_ptr
13+
#include <vector>
14+
15+
#include "core.h"
16+
17+
FMT_BEGIN_NAMESPACE
18+
19+
namespace detail {
20+
21+
template <typename T> struct is_reference_wrapper : std::false_type {};
22+
template <typename T>
23+
struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {};
24+
25+
template <typename T> auto unwrap(const T& v) -> const T& { return v; }
26+
template <typename T>
27+
auto unwrap(const std::reference_wrapper<T>& v) -> const T& {
28+
return static_cast<const T&>(v);
29+
}
30+
31+
class dynamic_arg_list {
32+
// Workaround for clang's -Wweak-vtables. Unlike for regular classes, for
33+
// templates it doesn't complain about inability to deduce single translation
34+
// unit for placing vtable. So storage_node_base is made a fake template.
35+
template <typename = void> struct node {
36+
virtual ~node() = default;
37+
std::unique_ptr<node<>> next;
38+
};
39+
40+
template <typename T> struct typed_node : node<> {
41+
T value;
42+
43+
template <typename Arg>
44+
FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {}
45+
46+
template <typename Char>
47+
FMT_CONSTEXPR typed_node(const basic_string_view<Char>& arg)
48+
: value(arg.data(), arg.size()) {}
49+
};
50+
51+
std::unique_ptr<node<>> head_;
52+
53+
public:
54+
template <typename T, typename Arg> auto push(const Arg& arg) -> const T& {
55+
auto new_node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg));
56+
auto& value = new_node->value;
57+
new_node->next = std::move(head_);
58+
head_ = std::move(new_node);
59+
return value;
60+
}
61+
};
62+
} // namespace detail
63+
64+
/**
65+
\rst
66+
A dynamic version of `fmt::format_arg_store`.
67+
It's equipped with a storage to potentially temporary objects which lifetimes
68+
could be shorter than the format arguments object.
69+
70+
It can be implicitly converted into `~fmt::basic_format_args` for passing
71+
into type-erased formatting functions such as `~fmt::vformat`.
72+
\endrst
73+
*/
74+
template <typename Context>
75+
class dynamic_format_arg_store
76+
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
77+
// Workaround a GCC template argument substitution bug.
78+
: public basic_format_args<Context>
79+
#endif
80+
{
81+
private:
82+
using char_type = typename Context::char_type;
83+
84+
template <typename T> struct need_copy {
85+
static constexpr detail::type mapped_type =
86+
detail::mapped_type_constant<T, Context>::value;
87+
88+
enum {
89+
value = !(detail::is_reference_wrapper<T>::value ||
90+
std::is_same<T, basic_string_view<char_type>>::value ||
91+
std::is_same<T, detail::std_string_view<char_type>>::value ||
92+
(mapped_type != detail::type::cstring_type &&
93+
mapped_type != detail::type::string_type &&
94+
mapped_type != detail::type::custom_type))
95+
};
96+
};
97+
98+
template <typename T>
99+
using stored_type = conditional_t<
100+
std::is_convertible<T, std::basic_string<char_type>>::value &&
101+
!detail::is_reference_wrapper<T>::value,
102+
std::basic_string<char_type>, T>;
103+
104+
// Storage of basic_format_arg must be contiguous.
105+
std::vector<basic_format_arg<Context>> data_;
106+
std::vector<detail::named_arg_info<char_type>> named_info_;
107+
108+
// Storage of arguments not fitting into basic_format_arg must grow
109+
// without relocation because items in data_ refer to it.
110+
detail::dynamic_arg_list dynamic_args_;
111+
112+
friend class basic_format_args<Context>;
113+
114+
auto get_types() const -> unsigned long long {
115+
return detail::is_unpacked_bit | data_.size() |
116+
(named_info_.empty()
117+
? 0ULL
118+
: static_cast<unsigned long long>(detail::has_named_args_bit));
119+
}
120+
121+
auto data() const -> const basic_format_arg<Context>* {
122+
return named_info_.empty() ? data_.data() : data_.data() + 1;
123+
}
124+
125+
template <typename T> void emplace_arg(const T& arg) {
126+
data_.emplace_back(detail::make_arg<Context>(arg));
127+
}
128+
129+
template <typename T>
130+
void emplace_arg(const detail::named_arg<char_type, T>& arg) {
131+
if (named_info_.empty()) {
132+
constexpr const detail::named_arg_info<char_type>* zero_ptr{nullptr};
133+
data_.insert(data_.begin(), {zero_ptr, 0});
134+
}
135+
data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value)));
136+
auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {
137+
data->pop_back();
138+
};
139+
std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)>
140+
guard{&data_, pop_one};
141+
named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)});
142+
data_[0].value_.named_args = {named_info_.data(), named_info_.size()};
143+
guard.release();
144+
}
145+
146+
public:
147+
constexpr dynamic_format_arg_store() = default;
148+
149+
/**
150+
\rst
151+
Adds an argument into the dynamic store for later passing to a formatting
152+
function.
153+
154+
Note that custom types and string types (but not string views) are copied
155+
into the store dynamically allocating memory if necessary.
156+
157+
**Example**::
158+
159+
fmt::dynamic_format_arg_store<fmt::format_context> store;
160+
store.push_back(42);
161+
store.push_back("abc");
162+
store.push_back(1.5f);
163+
std::string result = fmt::vformat("{} and {} and {}", store);
164+
\endrst
165+
*/
166+
template <typename T> void push_back(const T& arg) {
167+
if (detail::const_check(need_copy<T>::value))
168+
emplace_arg(dynamic_args_.push<stored_type<T>>(arg));
169+
else
170+
emplace_arg(detail::unwrap(arg));
171+
}
172+
173+
/**
174+
\rst
175+
Adds a reference to the argument into the dynamic store for later passing to
176+
a formatting function.
177+
178+
**Example**::
179+
180+
fmt::dynamic_format_arg_store<fmt::format_context> store;
181+
char band[] = "Rolling Stones";
182+
store.push_back(std::cref(band));
183+
band[9] = 'c'; // Changing str affects the output.
184+
std::string result = fmt::vformat("{}", store);
185+
// result == "Rolling Scones"
186+
\endrst
187+
*/
188+
template <typename T> void push_back(std::reference_wrapper<T> arg) {
189+
static_assert(
190+
need_copy<T>::value,
191+
"objects of built-in types and string views are always copied");
192+
emplace_arg(arg.get());
193+
}
194+
195+
/**
196+
Adds named argument into the dynamic store for later passing to a formatting
197+
function. ``std::reference_wrapper`` is supported to avoid copying of the
198+
argument. The name is always copied into the store.
199+
*/
200+
template <typename T>
201+
void push_back(const detail::named_arg<char_type, T>& arg) {
202+
const char_type* arg_name =
203+
dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();
204+
if (detail::const_check(need_copy<T>::value)) {
205+
emplace_arg(
206+
fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(arg.value)));
207+
} else {
208+
emplace_arg(fmt::arg(arg_name, arg.value));
209+
}
210+
}
211+
212+
/** Erase all elements from the store */
213+
void clear() {
214+
data_.clear();
215+
named_info_.clear();
216+
dynamic_args_ = detail::dynamic_arg_list();
217+
}
218+
219+
/**
220+
\rst
221+
Reserves space to store at least *new_cap* arguments including
222+
*new_cap_named* named arguments.
223+
\endrst
224+
*/
225+
void reserve(size_t new_cap, size_t new_cap_named) {
226+
FMT_ASSERT(new_cap >= new_cap_named,
227+
"Set of arguments includes set of named arguments");
228+
data_.reserve(new_cap);
229+
named_info_.reserve(new_cap_named);
230+
}
231+
};
232+
233+
FMT_END_NAMESPACE
234+
235+
#endif // FMT_ARGS_H_

0 commit comments

Comments
 (0)