Nix 2.93.3
Lix: A modern, delicious implementation of the Nix package manager; unstable internal interfaces
Loading...
Searching...
No Matches
fmt.hh
Go to the documentation of this file.
1#pragma once
3
4#include <iostream>
5#include <string>
6#include <boost/format.hpp>
8
9// Explicit instantiation in fmt.cc
10extern template class boost::basic_format<char>;
11
12namespace nix {
13
15std::string getStackTrace();
16
24template<class T>
25struct Magenta
26{
27 Magenta(const T & s) : value(s) {}
28 const T & value;
29};
30
31template<class T>
32std::ostream & operator<<(std::ostream & out, const Magenta<T> & y)
33{
34 return out << ANSI_MAGENTA << y.value << ANSI_NORMAL;
35}
36
42template<class T>
43struct Uncolored
44{
45 Uncolored(const T & s) : value(s) {}
46 const T & value;
47};
48
49template<class T>
50std::ostream & operator<<(std::ostream & out, const Uncolored<T> & y)
51{
52 return out << ANSI_NORMAL << y.value;
53}
54
55namespace fmt_internal {
56
60inline void setExceptions(boost::format & fmt)
61{
62 fmt.exceptions(
63 boost::io::all_error_bits ^ boost::io::too_many_args_bit ^ boost::io::too_few_args_bit
64 );
65}
66
72struct HintFmt
73{
74 boost::format fmt;
75
76 template<typename... Args>
77 HintFmt(boost::format && fmt, const Args &... args) : fmt(std::move(fmt))
78 {
79 setExceptions(fmt);
80 (*this % ... % args);
81 }
82
83 template<class T>
84 HintFmt & operator%(const T & value)
85 {
86 fmt % Magenta(value);
87 return *this;
88 }
89
90 template<class T>
91 HintFmt & operator%(const Uncolored<T> & value)
92 {
93 fmt % value.value;
94 return *this;
95 }
96
97 boost::format into_format()
98 {
99 return std::move(fmt);
100 }
101};
102
103}
104
127inline std::string fmt(const std::string & s)
128{
129 return s;
130}
131
132inline std::string fmt(const char * s)
133{
134 return s;
135}
136
137template<typename... Args>
138inline std::string fmt(const std::string & fs, const Args &... args)
139try {
140 boost::format f(fs);
141 fmt_internal::setExceptions(f);
142 (f % ... % args);
143 return f.str();
144} catch (boost::io::format_error & fe) { // NOLINT(lix-foreign-exceptions)
145 // I don't care who catches this, we do not put up with boost format errors
146 // Give me a stack trace and a core dump
147 std::cerr << "nix::fmt threw format error. Original format string: '";
148 std::cerr << fs << "'; number of arguments: " << sizeof...(args) << "\n";
149 std::terminate();
150}
151
157{
158private:
159 boost::format fmt;
160
161public:
166 // Moved out of line because it was instantiating the template below in
167 // every file in the project.
168 HintFmt(const std::string & literal);
169
173 template<typename... Args>
174 HintFmt(const std::string & format, const Args &... args)
175 // Note the function try block.
176 try : fmt(fmt_internal::HintFmt(boost::format(format), args...).into_format())
177 {
178 if (this->fmt.remaining_args() != 0) {
179 // Abort. I don't want anything to catch this, I want a coredump.
180 std::cerr << "HintFmt received incorrect number of format args. Original format string: '";
181 std::cerr << format << "'; number of arguments: " << sizeof...(args) << "\n";
182 // And regardless of the coredump give me a damn stacktrace.
183 std::terminate();
184 }
185 } catch (boost::io::format_error & ex) { // NOLINT(lix-foreign-exceptions)
186 // Same thing, but for anything that happens in the member initializers.
187 std::cerr << "HintFmt received incorrect format string. Original format string: '";
188 std::cerr << format << "'; number of arguments: " << sizeof...(args) << "\n";
189 std::terminate();
190 }
191
192 HintFmt(const HintFmt & hf) : fmt(hf.fmt) {}
193
194 HintFmt & operator=(HintFmt const & rhs) = default;
195
196 std::string str() const
197 {
198 return fmt.str();
199 }
200};
201
202// Explicit instantiations in fmt.cc
203extern template HintFmt::HintFmt(const std::string &, const Uncolored<std::string> &s);
204extern template HintFmt::HintFmt(const std::string &, const std::string &s);
205extern template HintFmt::HintFmt(const std::string &, const uint64_t &, const char * const &);
206
207std::ostream & operator<<(std::ostream & os, const HintFmt & hf);
208
209}
Some ANSI escape sequences.
Definition args.hh:31
HintFmt(const std::string &format, const Args &... args)
Definition fmt.hh:174
HintFmt(const std::string &literal)
Definition fmt.cc:18
void setExceptions(boost::format &fmt)
Definition fmt.hh:60
std::string fmt(const std::string &s)
Definition fmt.hh:127
Definition fmt.hh:26
Definition fmt.hh:44