IoManip.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 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 
49 template <class Pointer>
50 class RawPointerT {
51 public:
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 
71 template <class Pointer>
73 RawPointer(const char *label, const Pointer &ptr)
74 {
75  return RawPointerT<Pointer>(label, ptr);
76 }
77 
79 template <class Pointer>
81 RawPointer(const Pointer &ptr)
82 {
83  return RawPointerT<Pointer>(nullptr, ptr);
84 }
85 
87 template <class Pointer>
88 inline std::ostream &
89 operator <<(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 
110 template <class Integer>
111 class AsHex
112 {
113 public:
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 
141 template <class Integer>
142 inline std::ostream &
143 operator <<(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 
168 template <class Integer>
169 inline AsHex<Integer> asHex(const Integer n) { return AsHex<Integer>(n); }
170 
172 void PrintHex(std::ostream &, const char *data, size_t n);
173 
175 template <typename Container>
176 class AsList
177 {
178 public:
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 
199 public:
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 
209 template <typename Container>
210 void
211 AsList<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 
236 template <typename Container>
237 inline std::ostream &
238 operator <<(std::ostream &os, const AsList<Container> &manipulator)
239 {
240  manipulator.print(os);
241  return os;
242 }
243 
245 template <typename Container>
246 inline auto asList(const Container &c) { return AsList<Container>(c); }
247 
258 template <class T>
260 {
261 public:
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 
272 private:
273  const T &toPrint;
274  bool printed = false;
275 };
276 
284 template <class T>
285 inline auto &
286 operator <<(std::ostream &os, AtMostOnce<T> &a) {
287  a.print(os);
288  return os;
289 }
290 
292 template <class T>
294 {
295 public:
297  explicit WithExtras(const T &t): toPrint(t) {}
298  const T &toPrint;
299 };
300 
302 template <class T>
303 inline auto &
304 operator <<(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 
Integer io_manip
the integer to print
Definition: IoManip.h:130
bool printed
Definition: IoManip.h:274
const T & toPrint
Definition: IoManip.h:273
const char * suffix
a c-string to print after the last item (if any). Caller must ensure lifetime.
Definition: IoManip.h:203
std::ostream & operator<<(std::ostream &os, const RawPointerT< Pointer > &pd)
prints RawPointerT<>, dereferencing the io_manip pointer if possible
Definition: IoManip.h:89
const char * label
Definition: IoManip.h:61
AsList(const Container &c)
Definition: IoManip.h:179
static const char * delimiter
Definition: ldap_backend.cc:65
const T & toPrint
Definition: IoManip.h:298
const Pointer & ptr
Definition: IoManip.h:66
number
Definition: testStatHist.cc:32
auto & upperCase(const bool u=true)
Print hex digits in upper (or, with a false parameter value, lower) case.
Definition: IoManip.h:128
RawPointerT(const char *aLabel, const Pointer &aPtr)
Definition: IoManip.h:52
RawPointerT< Pointer > & orNil(const char *nilTextToUse="[nil]")
enable and, optionally, customize reporting of nil pointers
Definition: IoManip.h:59
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
const char * nilText
the name or description of the being-debugged object
Definition: IoManip.h:64
std::optional< size_t > forcePadding
Definition: IoManip.h:134
auto & quoted(const char *const q="\"")
c-string to print before and after each item. Caller must ensure lifetime.
Definition: IoManip.h:191
const Container & container
zero or more items to print
Definition: IoManip.h:200
void print(std::ostream &os)
Definition: IoManip.h:265
const char * delimiter
a c-string to print between consecutive items (if any). Caller must ensure lifetime.
Definition: IoManip.h:204
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
Definition: IoManip.h:169
auto & delimitedBy(const char *const d)
a c-string to print between consecutive items (if any). Caller must ensure lifetime.
Definition: IoManip.h:188
std::ostream manipulator to print containers as flat lists
Definition: IoManip.h:176
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
const char * prefix
a c-string to print before the first item (if any). Caller must ensure lifetime.
Definition: IoManip.h:202
std::optional< bool > forceCase
Print hex digits in upper (or, with a false parameter value, lower) case.
Definition: IoManip.h:138
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
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
const char * postQuote
optional c-string to print after each item;
Definition: IoManip.h:206
static std::ostream & Extra(std::ostream &)
Definition: debug.cc:1316
const char * preQuote
optional c-string to print before each item;
Definition: IoManip.h:205
AtMostOnce(const T &t)
caller must ensure t lifetime extends to the last use of this AtMostOnce instance
Definition: IoManip.h:263
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:293
AsHex(const Integer n)
Definition: IoManip.h:120
auto asList(const Container &c)
a helper to ease AsList object creation
Definition: IoManip.h:246
bool onExtraLine
a possibly nil pointer to the being-debugged object
Definition: IoManip.h:67
auto & minDigits(const size_t w)
Definition: IoManip.h:125
void print(std::ostream &) const
writes the container to the given stream
Definition: IoManip.h:211
Definition: IoManip.h:111
RawPointerT< Pointer > RawPointer(const char *label, const Pointer &ptr)
convenience wrapper for creating RawPointerT<> objects
Definition: IoManip.h:73
WithExtras(const T &t)
caller must ensure t lifetime extends to the last use of this class instance
Definition: IoManip.h:297

 

Introduction

Documentation

Support

Miscellaneous