1 // Debug-mode error formatting implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
4 // Free Software Foundation, Inc.
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 // <http://www.gnu.org/licenses/>.
26 /** @file debug/formatter.h
27 * This file is a GNU debug extension to the Standard C++ Library.
30 #ifndef _GLIBCXX_DEBUG_FORMATTER_H
31 #define _GLIBCXX_DEBUG_FORMATTER_H 1
33 #include <bits/c++config.h>
40 template<typename _Iterator
>
41 bool __check_singular(_Iterator
&);
43 /** Determine if the two types are the same. */
44 template<typename _Type1
, typename _Type2
>
47 static const bool value
= false;
50 template<typename _Type
>
51 struct __is_same
<_Type
, _Type
>
53 static const bool value
= true;
56 template<bool> struct __truth
{ };
58 class _Safe_sequence_base
;
60 template<typename _Iterator
, typename _Sequence
>
63 template<typename _Sequence
>
70 __msg_insert_singular
,
71 __msg_insert_different
,
73 __msg_erase_different
,
77 __msg_unpartitioned_pred
,
83 __msg_bad_bitset_write
,
84 __msg_bad_bitset_read
,
85 __msg_bad_bitset_flip
,
94 __msg_init_copy_singular
,
95 __msg_init_const_singular
,
100 __msg_iter_subscript_oob
,
103 __msg_iter_compare_bad
,
104 __msg_compare_different
,
105 __msg_iter_order_bad
,
106 __msg_order_different
,
108 __msg_distance_different
,
113 __msg_output_ostream
,
114 // istreambuf_iterator
115 __msg_deref_istreambuf
,
119 class _Error_formatter
121 /// Whether an iterator is constant, mutable, or unknown
130 // The state of the iterator (fine-grained), if we know it.
134 __singular
, // singular, may still be attached to a sequence
135 __begin
, // dereferenceable, and at the beginning
136 __middle
, // dereferenceable, not at the beginning
137 __end
, // past-the-end, may be at beginning if sequence empty
141 // Tags denoting the type of parameter for construction
142 struct _Is_iterator
{ };
143 struct _Is_sequence
{ };
145 // A parameter that may be referenced by an error message
159 // When _M_kind == __iterator
163 const void* _M_address
;
164 const type_info
* _M_type
;
165 _Constness _M_constness
;
166 _Iterator_state _M_state
;
167 const void* _M_sequence
;
168 const type_info
* _M_seq_type
;
171 // When _M_kind == __sequence
175 const void* _M_address
;
176 const type_info
* _M_type
;
179 // When _M_kind == __integer
186 // When _M_kind == __string
190 const char* _M_value
;
194 _Parameter() : _M_kind(__unused_param
), _M_variant() { }
196 _Parameter(long __value
, const char* __name
)
197 : _M_kind(__integer
), _M_variant()
199 _M_variant
._M_integer
._M_name
= __name
;
200 _M_variant
._M_integer
._M_value
= __value
;
203 _Parameter(const char* __value
, const char* __name
)
204 : _M_kind(__string
), _M_variant()
206 _M_variant
._M_string
._M_name
= __name
;
207 _M_variant
._M_string
._M_value
= __value
;
210 template<typename _Iterator
, typename _Sequence
>
211 _Parameter(const _Safe_iterator
<_Iterator
, _Sequence
>& __it
,
212 const char* __name
, _Is_iterator
)
213 : _M_kind(__iterator
), _M_variant()
215 _M_variant
._M_iterator
._M_name
= __name
;
216 _M_variant
._M_iterator
._M_address
= &__it
;
218 _M_variant
._M_iterator
._M_type
= &typeid(__it
);
220 _M_variant
._M_iterator
._M_type
= 0;
222 _M_variant
._M_iterator
._M_constness
=
223 __is_same
<_Safe_iterator
<_Iterator
, _Sequence
>,
224 typename
_Sequence::iterator
>::
225 value
? __mutable_iterator
: __const_iterator
;
226 _M_variant
._M_iterator
._M_sequence
= __it
._M_get_sequence();
228 _M_variant
._M_iterator
._M_seq_type
= &typeid(_Sequence
);
230 _M_variant
._M_iterator
._M_seq_type
= 0;
233 if (__it
._M_singular())
234 _M_variant
._M_iterator
._M_state
= __singular
;
237 bool __is_begin
= __it
._M_is_begin();
238 bool __is_end
= __it
._M_is_end();
240 _M_variant
._M_iterator
._M_state
= __end
;
242 _M_variant
._M_iterator
._M_state
= __begin
;
244 _M_variant
._M_iterator
._M_state
= __middle
;
248 template<typename _Type
>
249 _Parameter(const _Type
*& __it
, const char* __name
, _Is_iterator
)
250 : _M_kind(__iterator
), _M_variant()
252 _M_variant
._M_iterator
._M_name
= __name
;
253 _M_variant
._M_iterator
._M_address
= &__it
;
255 _M_variant
._M_iterator
._M_type
= &typeid(__it
);
257 _M_variant
._M_iterator
._M_type
= 0;
259 _M_variant
._M_iterator
._M_constness
= __mutable_iterator
;
260 _M_variant
._M_iterator
._M_state
= __it
? __unknown_state
: __singular
;
261 _M_variant
._M_iterator
._M_sequence
= 0;
262 _M_variant
._M_iterator
._M_seq_type
= 0;
265 template<typename _Type
>
266 _Parameter(_Type
*& __it
, const char* __name
, _Is_iterator
)
267 : _M_kind(__iterator
), _M_variant()
269 _M_variant
._M_iterator
._M_name
= __name
;
270 _M_variant
._M_iterator
._M_address
= &__it
;
272 _M_variant
._M_iterator
._M_type
= &typeid(__it
);
274 _M_variant
._M_iterator
._M_type
= 0;
276 _M_variant
._M_iterator
._M_constness
= __const_iterator
;
277 _M_variant
._M_iterator
._M_state
= __it
? __unknown_state
: __singular
;
278 _M_variant
._M_iterator
._M_sequence
= 0;
279 _M_variant
._M_iterator
._M_seq_type
= 0;
282 template<typename _Iterator
>
283 _Parameter(const _Iterator
& __it
, const char* __name
, _Is_iterator
)
284 : _M_kind(__iterator
), _M_variant()
286 _M_variant
._M_iterator
._M_name
= __name
;
287 _M_variant
._M_iterator
._M_address
= &__it
;
289 _M_variant
._M_iterator
._M_type
= &typeid(__it
);
291 _M_variant
._M_iterator
._M_type
= 0;
293 _M_variant
._M_iterator
._M_constness
= __unknown_constness
;
294 _M_variant
._M_iterator
._M_state
=
295 __gnu_debug::__check_singular(__it
)? __singular
: __unknown_state
;
296 _M_variant
._M_iterator
._M_sequence
= 0;
297 _M_variant
._M_iterator
._M_seq_type
= 0;
300 template<typename _Sequence
>
301 _Parameter(const _Safe_sequence
<_Sequence
>& __seq
,
302 const char* __name
, _Is_sequence
)
303 : _M_kind(__sequence
), _M_variant()
305 _M_variant
._M_sequence
._M_name
= __name
;
306 _M_variant
._M_sequence
._M_address
=
307 static_cast<const _Sequence
*>(&__seq
);
309 _M_variant
._M_sequence
._M_type
= &typeid(_Sequence
);
311 _M_variant
._M_sequence
._M_type
= 0;
315 template<typename _Sequence
>
316 _Parameter(const _Sequence
& __seq
, const char* __name
, _Is_sequence
)
317 : _M_kind(__sequence
), _M_variant()
319 _M_variant
._M_sequence
._M_name
= __name
;
320 _M_variant
._M_sequence
._M_address
= &__seq
;
322 _M_variant
._M_sequence
._M_type
= &typeid(_Sequence
);
324 _M_variant
._M_sequence
._M_type
= 0;
329 _M_print_field(const _Error_formatter
* __formatter
,
330 const char* __name
) const;
333 _M_print_description(const _Error_formatter
* __formatter
) const;
336 friend struct _Parameter
;
339 template<typename _Iterator
>
340 const _Error_formatter
&
341 _M_iterator(const _Iterator
& __it
, const char* __name
= 0) const
343 if (_M_num_parameters
< std::size_t(__max_parameters
))
344 _M_parameters
[_M_num_parameters
++] = _Parameter(__it
, __name
,
349 const _Error_formatter
&
350 _M_integer(long __value
, const char* __name
= 0) const
352 if (_M_num_parameters
< std::size_t(__max_parameters
))
353 _M_parameters
[_M_num_parameters
++] = _Parameter(__value
, __name
);
357 const _Error_formatter
&
358 _M_string(const char* __value
, const char* __name
= 0) const
360 if (_M_num_parameters
< std::size_t(__max_parameters
))
361 _M_parameters
[_M_num_parameters
++] = _Parameter(__value
, __name
);
365 template<typename _Sequence
>
366 const _Error_formatter
&
367 _M_sequence(const _Sequence
& __seq
, const char* __name
= 0) const
369 if (_M_num_parameters
< std::size_t(__max_parameters
))
370 _M_parameters
[_M_num_parameters
++] = _Parameter(__seq
, __name
,
375 const _Error_formatter
&
376 _M_message(const char* __text
) const
377 { _M_text
= __text
; return *this; }
379 const _Error_formatter
&
380 _M_message(_Debug_msg_id __id
) const throw ();
382 _GLIBCXX_NORETURN
void
386 _Error_formatter(const char* __file
, std::size_t __line
)
387 : _M_file(__file
), _M_line(__line
), _M_num_parameters(0), _M_text(0),
388 _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false)
389 { _M_get_max_length(); }
391 template<typename _Tp
>
393 _M_format_word(char*, int, const char*, _Tp
) const throw ();
396 _M_print_word(const char* __word
) const;
399 _M_print_string(const char* __string
) const;
402 _M_get_max_length() const throw ();
404 enum { __max_parameters
= 9 };
408 mutable _Parameter _M_parameters
[__max_parameters
];
409 mutable std::size_t _M_num_parameters
;
410 mutable const char* _M_text
;
411 mutable std::size_t _M_max_length
;
412 enum { _M_indent
= 4 } ;
413 mutable std::size_t _M_column
;
414 mutable bool _M_first_line
;
415 mutable bool _M_wordwrap
;
418 static _Error_formatter
419 _M_at(const char* __file
, std::size_t __line
)
420 { return _Error_formatter(__file
, __line
); }
422 } // namespace __gnu_debug