Squid Web Cache master
Loading...
Searching...
No Matches
IoManip.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9#ifndef SQUID_SRC_BASE_IOMANIP_H
10#define SQUID_SRC_BASE_IOMANIP_H
11
12#include "debug/Stream.h"
13
14#include <iostream>
15#include <iomanip>
16#include <optional>
17
46
49template <class Pointer>
51public:
52 RawPointerT(const char *aLabel, const Pointer &aPtr):
53 label(aLabel), ptr(aPtr) {}
54
56 RawPointerT<Pointer> &asExtra() { onExtraLine = true; return *this; }
57
59 RawPointerT<Pointer> &orNil(const char *nilTextToUse = "[nil]") { nilText = nilTextToUse; return *this; }
60
61 const char *label;
62
64 const char *nilText = nullptr;
65
66 const Pointer &ptr;
67 bool onExtraLine = false;
68};
69
71template <class Pointer>
73RawPointer(const char *label, const Pointer &ptr)
74{
75 return RawPointerT<Pointer>(label, ptr);
76}
77
79template <class Pointer>
81RawPointer(const Pointer &ptr)
82{
83 return RawPointerT<Pointer>(nullptr, ptr);
84}
85
87template <class Pointer>
88inline std::ostream &
89operator <<(std::ostream &os, const RawPointerT<Pointer> &pd)
90{
91 if (!pd.ptr) {
92 if (pd.nilText)
93 os << pd.nilText;
94 return os;
95 }
96
97 if (pd.onExtraLine)
98 os << Debug::Extra;
99
100 if (pd.label)
101 os << pd.label;
102
103 os << *pd.ptr;
104
105 return os;
106}
107
110template <class Integer>
111class AsHex
112{
113public:
114 // Without this assertion, asHex(pointer) and AsHex(3.14) compile, but their
115 // caller is likely confused about the actual argument type and expects
116 // different output. Enum values are not integral types but arguably do not
117 // cause similar problems.
118 static_assert(std::is_integral<Integer>::value || std::is_enum<Integer>::value);
119
120 explicit AsHex(const Integer n): io_manip(n) {}
121
125 auto &minDigits(const size_t w) { forcePadding = w; return *this; }
126
128 auto &upperCase(const bool u = true) { forceCase = u; return *this; }
129
130 Integer io_manip;
131
134 std::optional<size_t> forcePadding;
135
138 std::optional<bool> forceCase;
139};
140
141template <class Integer>
142inline std::ostream &
143operator <<(std::ostream &os, const AsHex<Integer> number)
144{
145 const auto oldFlags = os.flags();
146 const auto oldFill = os.fill();
147
148 if (number.forceCase)
149 os << (*number.forceCase ? std::uppercase : std::nouppercase);
150
151 if (number.forcePadding) {
152 os.width(*number.forcePadding);
153 os.fill('0');
154 }
155
156 // When Integer is smaller than int, the unary plus converts the stored
157 // value into an equivalent integer because C++ "arithmetic operators do not
158 // accept types smaller than int as arguments, and integral promotions are
159 // automatically applied". For larger integer types, plus is a no-op.
160 os << std::hex << +number.io_manip;
161
162 os.fill(oldFill);
163 os.flags(oldFlags);
164 return os;
165}
166
168template <class Integer>
169inline AsHex<Integer> asHex(const Integer n) { return AsHex<Integer>(n); }
170
172void PrintHex(std::ostream &, const char *data, size_t n);
173
175template <typename Container>
177{
178public:
179 explicit AsList(const Container &c): container(c) {}
180
182 auto &prefixedBy(const char * const p) { prefix = p; return *this; }
183
185 auto &suffixedBy(const char * const p) { suffix = p; return *this; }
186
188 auto &delimitedBy(const char * const d) { delimiter = d; return *this; }
189
191 auto &quoted(const char * const q = "\"") { preQuote = postQuote = q; return *this; }
192
194 auto &quoted(const char * const preQ, const char * const postQ) { preQuote = preQ; postQuote = postQ; return *this; }
195
197 void print(std::ostream &) const;
198
199public:
200 const Container &container;
201
202 const char *prefix = nullptr;
203 const char *suffix = nullptr;
204 const char *delimiter = nullptr;
205 const char *preQuote = nullptr;
206 const char *postQuote = nullptr;
207};
208
209template <typename Container>
210void
211AsList<Container>::print(std::ostream &os) const
212{
213 bool opened = false;
214
215 for (const auto &item: container) {
216 if (!opened) {
217 if (prefix)
218 os << prefix;
219 opened = true;
220 } else {
221 if (delimiter)
222 os << delimiter;
223 }
224
225 if (preQuote)
226 os << preQuote;
227 os << item;
228 if (postQuote)
229 os << postQuote;
230 }
231
232 if (opened && suffix)
233 os << suffix;
234}
235
236template <typename Container>
237inline std::ostream &
238operator <<(std::ostream &os, const AsList<Container> &manipulator)
239{
240 manipulator.print(os);
241 return os;
242}
243
245template <typename Container>
246inline auto asList(const Container &c) { return AsList<Container>(c); }
247
258template <class T>
260{
261public:
263 explicit AtMostOnce(const T &t): toPrint(t) {}
264
265 void print(std::ostream &os) {
266 if (!printed) {
267 os << toPrint;
268 printed = true;
269 }
270 }
271
272private:
273 const T &toPrint;
274 bool printed = false;
275};
276
284template <class T>
285inline auto &
286operator <<(std::ostream &os, AtMostOnce<T> &a) {
287 a.print(os);
288 return os;
289}
290
292template <class T>
294{
295public:
297 explicit WithExtras(const T &t): toPrint(t) {}
298 const T &toPrint;
299};
300
302template <class T>
303inline auto &
304operator <<(std::ostream &os, const WithExtras<T> &a) {
305 a.toPrint.printWithExtras(os);
306 return os;
307}
308
309#endif /* SQUID_SRC_BASE_IOMANIP_H */
310
void PrintHex(std::ostream &, const char *data, size_t n)
Prints the first n data bytes using hex notation. Does nothing if n is 0.
Definition IoManip.cc:16
std::ostream & operator<<(std::ostream &os, const RawPointerT< Pointer > &pd)
prints RawPointerT<>, dereferencing the io_manip pointer if possible
Definition IoManip.h:89
auto asList(const Container &c)
a helper to ease AsList object creation
Definition IoManip.h:246
RawPointerT< Pointer > RawPointer(const char *label, const Pointer &ptr)
convenience wrapper for creating RawPointerT<> objects
Definition IoManip.h:73
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
Definition IoManip.h:169
auto & minDigits(const size_t w)
Definition IoManip.h:125
std::optional< bool > forceCase
Print hex digits in upper (or, with a false parameter value, lower) case.
Definition IoManip.h:138
auto & upperCase(const bool u=true)
Print hex digits in upper (or, with a false parameter value, lower) case.
Definition IoManip.h:128
std::optional< size_t > forcePadding
Definition IoManip.h:134
AsHex(const Integer n)
Definition IoManip.h:120
Integer io_manip
the integer to print
Definition IoManip.h:130
std::ostream manipulator to print containers as flat lists
Definition IoManip.h:177
const char * suffix
a c-string to print after the last item (if any). Caller must ensure lifetime.
Definition IoManip.h:203
auto & prefixedBy(const char *const p)
a c-string to print before the first item (if any). Caller must ensure lifetime.
Definition IoManip.h:182
const Container & container
zero or more items to print
Definition IoManip.h:200
const char * delimiter
a c-string to print between consecutive items (if any). Caller must ensure lifetime.
Definition IoManip.h:204
auto & quoted(const char *const preQ, const char *const postQ)
c-strings to print before and after each item. Caller must ensure lifetime.
Definition IoManip.h:194
void print(std::ostream &) const
writes the container to the given stream
Definition IoManip.h:211
auto & delimitedBy(const char *const d)
a c-string to print between consecutive items (if any). Caller must ensure lifetime.
Definition IoManip.h:188
auto & quoted(const char *const q="\"")
c-string to print before and after each item. Caller must ensure lifetime.
Definition IoManip.h:191
const char * preQuote
optional c-string to print before each item;
Definition IoManip.h:205
const char * prefix
a c-string to print before the first item (if any). Caller must ensure lifetime.
Definition IoManip.h:202
AsList(const Container &c)
Definition IoManip.h:179
const char * postQuote
optional c-string to print after each item;
Definition IoManip.h:206
auto & suffixedBy(const char *const p)
a c-string to print after the last item (if any). Caller must ensure lifetime.
Definition IoManip.h:185
bool printed
Definition IoManip.h:274
const T & toPrint
Definition IoManip.h:273
AtMostOnce(const T &t)
caller must ensure t lifetime extends to the last use of this AtMostOnce instance
Definition IoManip.h:263
void print(std::ostream &os)
Definition IoManip.h:265
static std::ostream & Extra(std::ostream &)
Definition debug.cc:1316
RawPointerT(const char *aLabel, const Pointer &aPtr)
Definition IoManip.h:52
const Pointer & ptr
Definition IoManip.h:66
bool onExtraLine
a possibly nil pointer to the being-debugged object
Definition IoManip.h:67
const char * label
Definition IoManip.h:61
RawPointerT< Pointer > & orNil(const char *nilTextToUse="[nil]")
enable and, optionally, customize reporting of nil pointers
Definition IoManip.h:59
const char * nilText
the name or description of the being-debugged object
Definition IoManip.h:64
RawPointerT< Pointer > & asExtra()
Report the pointed-to-object on a dedicated Debug::Extra line.
Definition IoManip.h:56
Helps prints T object using object's T::printWithExtras() method.
Definition IoManip.h:294
const T & toPrint
Definition IoManip.h:298
WithExtras(const T &t)
caller must ensure t lifetime extends to the last use of this class instance
Definition IoManip.h:297
static const char * delimiter
number