[ci] Update macos jobs
[xapian.git] / xapian-core / common / pretty.h
blob8eab12a23e381cae3502d296ae86ba868063ee3a
1 /** @file
2 * @brief Convert types to pretty representations
3 */
4 /* Copyright (C) 2010,2011,2012,2014,2016,2017,2019,2023,2024 Olly Betts
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifndef XAPIAN_INCLUDED_PRETTY_H
22 #define XAPIAN_INCLUDED_PRETTY_H
24 #include <list>
25 #include <map>
26 #include <ostream>
27 #include <string>
28 #include <string_view>
29 #include <vector>
31 #include "api/smallvector.h"
33 #include "xapian/intrusive_ptr.h"
34 #include "xapian/types.h"
36 template<class S>
37 struct PrettyOStream {
38 /// The std::ostream object we're outputting to.
39 S & os;
41 PrettyOStream(S & os_) : os(os_) { }
42 template<typename T> PrettyOStream & operator|(const T & t) {
43 os << ", ";
44 return *this << t;
48 struct Literal {
49 const char * _lit;
50 explicit Literal(const char * lit) : _lit(lit) { }
51 explicit Literal(const std::string & s) : _lit(s.c_str()) { }
54 /// Default is to output as std::ostream would.
55 template<class S, class T>
56 inline PrettyOStream<S> &
57 operator<<(PrettyOStream<S> &ps, const T & t)
59 ps.os << t;
60 return ps;
63 /** Allow writing literal strings.
65 * For example:
67 * PrettyOStream<std::ostream> ps(std::cout);
68 * ps << Literal("x = ") << x << Literal(", y = ") << y << endl;
70 template<class S>
71 inline PrettyOStream<S> &
72 operator<<(PrettyOStream<S> &ps, const Literal & t)
74 ps.os << t._lit;
75 return ps;
78 template<class S, class T>
79 inline PrettyOStream<S> &
80 operator<<(PrettyOStream<S> &ps, const T * t)
82 if (!t) {
83 ps.os << "NULL";
84 return ps;
86 ps.os << '&';
87 return ps << *t;
90 template<class S, class T>
91 inline PrettyOStream<S> &
92 operator<<(PrettyOStream<S> &ps, const T ** t)
94 ps.os << (void*)t;
95 return ps;
98 template<class S>
99 inline PrettyOStream<S> &
100 operator<<(PrettyOStream<S> &ps, const void * t)
102 ps.os << "(void*)" << t;
103 return ps;
106 // FIXME: We probably don't want to inline this, but need to arrange to
107 // put it somewhere sane out-of-line.
108 inline void write_ch(std::ostream & os, unsigned char ch)
110 if (ch < 32 || ch >= 127) {
111 os << '\\';
112 if (ch >= 7 && ch <= 13) {
113 os << "abtnvfr"[ch - 7];
114 } else {
115 os << char('0' | (ch >> 6));
116 os << char('0' | ((ch >> 3) & 7));
117 os << char('0' | (ch & 7));
119 } else if (ch == '\\') {
120 os << "\\\\";
121 } else if (ch == '"') {
122 os << "\\\"";
123 } else {
124 os << ch;
128 template<class S>
129 inline PrettyOStream<S> &
130 operator<<(PrettyOStream<S> &ps, const char * str)
132 ps.os << '"';
133 while (*str) {
134 write_ch(ps.os, *str++);
136 ps.os << '"';
137 return ps;
140 template<class S>
141 inline PrettyOStream<S> &
142 operator<<(PrettyOStream<S> &ps, const std::string & str)
144 ps.os << '"';
145 for (char ch : str) {
146 write_ch(ps.os, ch);
148 ps.os << '"';
149 return ps;
152 template<class S>
153 inline PrettyOStream<S> &
154 operator<<(PrettyOStream<S> &ps, std::string &)
156 ps.os << "std::string&";
157 return ps;
160 template<class S>
161 inline PrettyOStream<S> &
162 operator<<(PrettyOStream<S> &ps, std::string *)
164 ps.os << "std::string*";
165 return ps;
168 template<class S>
169 inline PrettyOStream<S>&
170 operator<<(PrettyOStream<S>& ps, std::string_view str)
172 ps.os << '"';
173 for (char ch : str) {
174 write_ch(ps.os, ch);
176 ps.os << '"';
177 return ps;
180 template<class S>
181 inline PrettyOStream<S>&
182 operator<<(PrettyOStream<S>& ps, const std::string_view* p_str)
184 if (p_str)
185 ps.os << *p_str;
186 else
187 ps.os << "NULL";
188 return ps;
191 template<class S>
192 inline PrettyOStream<S> &
193 operator<<(PrettyOStream<S> &ps, unsigned char ch)
195 ps.os << '\'';
196 if (ch < 32 || ch >= 127) {
197 ps.os << '\\';
198 if (ch >= 7 && ch <= 13) {
199 ps.os << "abtnvfr"[ch - 7];
200 } else if (ch == '\0') {
201 ps.os << "\\0";
202 } else {
203 ps.os << "0123456789abcdef"[ch >> 4];
204 ps.os << "0123456789abcdef"[ch & 0x0f];
206 } else if (ch == '\\') {
207 ps.os << "\\\\";
208 } else if (ch == '\'') {
209 ps.os << "\\'";
210 } else {
211 ps.os << ch;
213 ps.os << '\'';
214 return ps;
217 template<class S>
218 inline PrettyOStream<S> &
219 operator<<(PrettyOStream<S> &ps, bool b)
221 ps.os << (b ? "true" : "false");
222 return ps;
226 template<class S>
227 inline PrettyOStream<S> &
228 operator<<(PrettyOStream<S> &ps, bool &)
230 ps.os << "bool&";
231 return ps;
235 template<class S>
236 inline PrettyOStream<S> &
237 operator<<(PrettyOStream<S> &ps, Xapian::termcount * p)
239 ps.os << "(Xapian::termcount*)" << (void*)p;
240 return ps;
243 template<class S, typename T>
244 inline PrettyOStream<S> &
245 operator<<(PrettyOStream<S> &ps, std::list<T> &) {
246 ps.os << "std::list&";
247 return ps;
250 template<class S, typename T>
251 inline PrettyOStream<S> &
252 operator<<(PrettyOStream<S> &ps, const std::list<T> &) {
253 ps.os << "std::list";
254 // FIXME: could show first up to N elements.
255 return ps;
258 template<class S, typename K, typename V>
259 inline PrettyOStream<S> &
260 operator<<(PrettyOStream<S> &ps, std::map<K, V> *) {
261 ps.os << "std::map*";
262 return ps;
265 template<class S, typename K, typename V>
266 inline PrettyOStream<S> &
267 operator<<(PrettyOStream<S> &ps, std::map<K, V> &) {
268 ps.os << "std::map&";
269 return ps;
272 template<class S, typename K, typename V>
273 inline PrettyOStream<S> &
274 operator<<(PrettyOStream<S> &ps, const std::map<K, V> & m) {
275 ps.os << "std::map(" << m.size() << ')';
276 // FIXME: could show first up to N elements.
277 return ps;
280 template<class S, typename T>
281 inline PrettyOStream<S> &
282 operator<<(PrettyOStream<S> &ps, const std::vector<T> & v) {
283 ps.os << "std::vector(" << v.size() << ')';
284 // FIXME: could show first up to N elements.
285 return ps;
288 template<class S, typename T>
289 inline PrettyOStream<S> &
290 operator<<(PrettyOStream<S> &ps, const Xapian::Vec<T>& v) {
291 ps.os << "Vec(" << v.size() << ')';
292 // FIXME: could show first up to N elements.
293 return ps;
296 template<class S, typename T>
297 inline PrettyOStream<S> &
298 operator<<(PrettyOStream<S> &ps, const Xapian::VecCOW<T>& v) {
299 ps.os << "VecCOW(" << v.size() << ')';
300 // FIXME: could show first up to N elements.
301 return ps;
304 template<class S, typename T, typename U>
305 inline PrettyOStream<S> &
306 operator<<(PrettyOStream<S> &ps, const std::pair<T, U>& v) {
307 ps.os << "std::pair(" << v.first << ", " << v.second << ')';
308 return ps;
311 namespace Xapian {
312 class Centroid;
313 class Cluster;
314 class ClusterSet;
315 class ExpandDecider;
316 class FreqSource;
317 class KeyMaker;
318 class LatLongMetric;
319 class MatchDecider;
320 class Point;
321 class PointType;
322 class Registry;
323 class TermListGroup;
324 class Weight;
325 namespace Internal {
326 class AndContext;
327 class ExpandStats;
328 class ExpandWeight;
329 class OrContext;
333 namespace Glass {
334 class RootInfo;
337 class GlassCursor;
338 class GlassDatabase;
339 class GlassFreeListChecker;
340 class GlassTable;
342 class HoneyTable;
344 #define XAPIAN_PRETTY_AS_CLASSNAME(C)\
345 template<class S>\
346 inline PrettyOStream<S> &\
347 operator<<(PrettyOStream<S> &ps, const C &) {\
348 ps.os << #C;\
349 return ps;\
352 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::Centroid)
353 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::Cluster)
354 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::ClusterSet)
355 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::ExpandDecider)
356 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::FreqSource)
357 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::KeyMaker)
358 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::LatLongMetric)
359 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::MatchDecider)
360 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::Point)
361 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::PointType)
362 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::Registry)
363 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::TermListGroup)
364 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::Weight)
365 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::Internal::AndContext)
366 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::Internal::ExpandStats)
367 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::Internal::ExpandWeight)
368 XAPIAN_PRETTY_AS_CLASSNAME(Xapian::Internal::OrContext)
369 XAPIAN_PRETTY_AS_CLASSNAME(Glass::RootInfo)
370 XAPIAN_PRETTY_AS_CLASSNAME(GlassCursor)
371 XAPIAN_PRETTY_AS_CLASSNAME(GlassFreeListChecker)
372 XAPIAN_PRETTY_AS_CLASSNAME(GlassDatabase)
373 XAPIAN_PRETTY_AS_CLASSNAME(GlassTable)
374 XAPIAN_PRETTY_AS_CLASSNAME(HoneyTable)
376 template<class S>
377 inline PrettyOStream<S> &
378 operator<<(PrettyOStream<S> &ps, const Xapian::Weight *p) {
379 ps.os << "(Xapian:Weight*)" << (const void*)p;
380 return ps;
383 class RemoteConnection;
385 template<class S>
386 inline PrettyOStream<S> &
387 operator<<(PrettyOStream<S> &ps, const RemoteConnection &) {
388 ps.os << "RemoteConnection";
389 return ps;
392 #include "backends/databaseinternal.h"
394 template<class S>
395 inline PrettyOStream<S> &
396 operator<<(PrettyOStream<S> &ps, const Xapian::Database::Internal *p) {
397 ps.os << "(Database::Internal*)" << (const void*)p;
398 return ps;
401 template<class S, class T>
402 inline PrettyOStream<S> &
403 operator<<(PrettyOStream<S> &ps, Xapian::Internal::intrusive_ptr<const T> t) {
404 ps.os << "intrusive_ptr->";
405 return ps << t.get();
408 #endif // XAPIAN_INCLUDED_PRETTY_H