2 * @brief Convert types to pretty representations
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
28 #include <string_view>
31 #include "api/smallvector.h"
33 #include "xapian/intrusive_ptr.h"
34 #include "xapian/types.h"
37 struct PrettyOStream
{
38 /// The std::ostream object we're outputting to.
41 PrettyOStream(S
& os_
) : os(os_
) { }
42 template<typename T
> PrettyOStream
& operator|(const T
& t
) {
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
)
63 /** Allow writing literal strings.
67 * PrettyOStream<std::ostream> ps(std::cout);
68 * ps << Literal("x = ") << x << Literal(", y = ") << y << endl;
71 inline PrettyOStream
<S
> &
72 operator<<(PrettyOStream
<S
> &ps
, const Literal
& t
)
78 template<class S
, class T
>
79 inline PrettyOStream
<S
> &
80 operator<<(PrettyOStream
<S
> &ps
, const T
* t
)
90 template<class S
, class T
>
91 inline PrettyOStream
<S
> &
92 operator<<(PrettyOStream
<S
> &ps
, const T
** t
)
99 inline PrettyOStream
<S
> &
100 operator<<(PrettyOStream
<S
> &ps
, const void * t
)
102 ps
.os
<< "(void*)" << t
;
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) {
112 if (ch
>= 7 && ch
<= 13) {
113 os
<< "abtnvfr"[ch
- 7];
115 os
<< char('0' | (ch
>> 6));
116 os
<< char('0' | ((ch
>> 3) & 7));
117 os
<< char('0' | (ch
& 7));
119 } else if (ch
== '\\') {
121 } else if (ch
== '"') {
129 inline PrettyOStream
<S
> &
130 operator<<(PrettyOStream
<S
> &ps
, const char * str
)
134 write_ch(ps
.os
, *str
++);
141 inline PrettyOStream
<S
> &
142 operator<<(PrettyOStream
<S
> &ps
, const std::string
& str
)
145 for (char ch
: str
) {
153 inline PrettyOStream
<S
> &
154 operator<<(PrettyOStream
<S
> &ps
, std::string
&)
156 ps
.os
<< "std::string&";
161 inline PrettyOStream
<S
> &
162 operator<<(PrettyOStream
<S
> &ps
, std::string
*)
164 ps
.os
<< "std::string*";
169 inline PrettyOStream
<S
>&
170 operator<<(PrettyOStream
<S
>& ps
, std::string_view str
)
173 for (char ch
: str
) {
181 inline PrettyOStream
<S
>&
182 operator<<(PrettyOStream
<S
>& ps
, const std::string_view
* p_str
)
192 inline PrettyOStream
<S
> &
193 operator<<(PrettyOStream
<S
> &ps
, unsigned char ch
)
196 if (ch
< 32 || ch
>= 127) {
198 if (ch
>= 7 && ch
<= 13) {
199 ps
.os
<< "abtnvfr"[ch
- 7];
200 } else if (ch
== '\0') {
203 ps
.os
<< "0123456789abcdef"[ch
>> 4];
204 ps
.os
<< "0123456789abcdef"[ch
& 0x0f];
206 } else if (ch
== '\\') {
208 } else if (ch
== '\'') {
218 inline PrettyOStream
<S
> &
219 operator<<(PrettyOStream
<S
> &ps
, bool b
)
221 ps
.os
<< (b
? "true" : "false");
227 inline PrettyOStream<S> &
228 operator<<(PrettyOStream<S> &ps, bool &)
236 inline PrettyOStream
<S
> &
237 operator<<(PrettyOStream
<S
> &ps
, Xapian::termcount
* p
)
239 ps
.os
<< "(Xapian::termcount*)" << (void*)p
;
243 template<class S
, typename T
>
244 inline PrettyOStream
<S
> &
245 operator<<(PrettyOStream
<S
> &ps
, std::list
<T
> &) {
246 ps
.os
<< "std::list&";
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.
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*";
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&";
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.
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.
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.
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.
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
<< ')';
339 class GlassFreeListChecker
;
344 #define XAPIAN_PRETTY_AS_CLASSNAME(C)\
346 inline PrettyOStream<S> &\
347 operator<<(PrettyOStream<S> &ps, const C &) {\
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
)
377 inline PrettyOStream
<S
> &
378 operator<<(PrettyOStream
<S
> &ps
, const Xapian::Weight
*p
) {
379 ps
.os
<< "(Xapian:Weight*)" << (const void*)p
;
383 class RemoteConnection
;
386 inline PrettyOStream
<S
> &
387 operator<<(PrettyOStream
<S
> &ps
, const RemoteConnection
&) {
388 ps
.os
<< "RemoteConnection";
392 #include "backends/databaseinternal.h"
395 inline PrettyOStream
<S
> &
396 operator<<(PrettyOStream
<S
> &ps
, const Xapian::Database::Internal
*p
) {
397 ps
.os
<< "(Database::Internal*)" << (const void*)p
;
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