1 // Debug-mode error formatting implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library 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 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file debug/formatter.h
26 * This file is a GNU debug extension to the Standard C++ Library.
29 #ifndef _GLIBCXX_DEBUG_FORMATTER_H
30 #define _GLIBCXX_DEBUG_FORMATTER_H 1
33 #include <debug/debug.h>
39 /** Determine if the two types are the same. */
40 template<typename _Type1
, typename _Type2
>
43 static const bool value
= false;
46 template<typename _Type
>
47 struct __is_same
<_Type
, _Type
>
49 static const bool value
= true;
52 template<bool> struct __truth
{ };
54 class _Safe_sequence_base
;
56 template<typename _Iterator
, typename _Sequence
>
59 template<typename _Sequence
>
66 __msg_insert_singular
,
67 __msg_insert_different
,
69 __msg_erase_different
,
73 __msg_unpartitioned_pred
,
79 __msg_bad_bitset_write
,
80 __msg_bad_bitset_read
,
81 __msg_bad_bitset_flip
,
90 __msg_init_copy_singular
,
91 __msg_init_const_singular
,
96 __msg_iter_subscript_oob
,
99 __msg_iter_compare_bad
,
100 __msg_compare_different
,
101 __msg_iter_order_bad
,
102 __msg_order_different
,
104 __msg_distance_different
,
109 __msg_output_ostream
,
110 // istreambuf_iterator
111 __msg_deref_istreambuf
,
115 class _Error_formatter
117 /// Whether an iterator is constant, mutable, or unknown
126 // The state of the iterator (fine-grained), if we know it.
130 __singular
, // singular, may still be attached to a sequence
131 __begin
, // dereferenceable, and at the beginning
132 __middle
, // dereferenceable, not at the beginning
133 __end
, // past-the-end, may be at beginning if sequence empty
137 // Tags denoting the type of parameter for construction
138 struct _Is_iterator
{ };
139 struct _Is_sequence
{ };
141 // A parameter that may be referenced by an error message
155 // When _M_kind == __iterator
159 const void* _M_address
;
160 const type_info
* _M_type
;
161 _Constness _M_constness
;
162 _Iterator_state _M_state
;
163 const void* _M_sequence
;
164 const type_info
* _M_seq_type
;
167 // When _M_kind == __sequence
171 const void* _M_address
;
172 const type_info
* _M_type
;
175 // When _M_kind == __integer
182 // When _M_kind == __string
186 const char* _M_value
;
190 _Parameter() : _M_kind(__unused_param
), _M_variant() { }
192 _Parameter(long __value
, const char* __name
)
193 : _M_kind(__integer
), _M_variant()
195 _M_variant
._M_integer
._M_name
= __name
;
196 _M_variant
._M_integer
._M_value
= __value
;
199 _Parameter(const char* __value
, const char* __name
)
200 : _M_kind(__string
), _M_variant()
202 _M_variant
._M_string
._M_name
= __name
;
203 _M_variant
._M_string
._M_value
= __value
;
206 template<typename _Iterator
, typename _Sequence
>
207 _Parameter(const _Safe_iterator
<_Iterator
, _Sequence
>& __it
,
208 const char* __name
, _Is_iterator
)
209 : _M_kind(__iterator
), _M_variant()
211 _M_variant
._M_iterator
._M_name
= __name
;
212 _M_variant
._M_iterator
._M_address
= &__it
;
213 _M_variant
._M_iterator
._M_type
= &typeid(__it
);
214 _M_variant
._M_iterator
._M_constness
=
215 __is_same
<_Safe_iterator
<_Iterator
, _Sequence
>,
216 typename
_Sequence::iterator
>::
217 value
? __mutable_iterator
: __const_iterator
;
218 _M_variant
._M_iterator
._M_sequence
= __it
._M_get_sequence();
219 _M_variant
._M_iterator
._M_seq_type
= &typeid(_Sequence
);
221 if (__it
._M_singular())
222 _M_variant
._M_iterator
._M_state
= __singular
;
225 bool __is_begin
= __it
._M_is_begin();
226 bool __is_end
= __it
._M_is_end();
228 _M_variant
._M_iterator
._M_state
= __end
;
230 _M_variant
._M_iterator
._M_state
= __begin
;
232 _M_variant
._M_iterator
._M_state
= __middle
;
236 template<typename _Type
>
237 _Parameter(const _Type
*& __it
, const char* __name
, _Is_iterator
)
238 : _M_kind(__iterator
), _M_variant()
240 _M_variant
._M_iterator
._M_name
= __name
;
241 _M_variant
._M_iterator
._M_address
= &__it
;
242 _M_variant
._M_iterator
._M_type
= &typeid(__it
);
243 _M_variant
._M_iterator
._M_constness
= __mutable_iterator
;
244 _M_variant
._M_iterator
._M_state
= __it
? __unknown_state
: __singular
;
245 _M_variant
._M_iterator
._M_sequence
= 0;
246 _M_variant
._M_iterator
._M_seq_type
= 0;
249 template<typename _Type
>
250 _Parameter(_Type
*& __it
, const char* __name
, _Is_iterator
)
251 : _M_kind(__iterator
), _M_variant()
253 _M_variant
._M_iterator
._M_name
= __name
;
254 _M_variant
._M_iterator
._M_address
= &__it
;
255 _M_variant
._M_iterator
._M_type
= &typeid(__it
);
256 _M_variant
._M_iterator
._M_constness
= __const_iterator
;
257 _M_variant
._M_iterator
._M_state
= __it
? __unknown_state
: __singular
;
258 _M_variant
._M_iterator
._M_sequence
= 0;
259 _M_variant
._M_iterator
._M_seq_type
= 0;
262 template<typename _Iterator
>
263 _Parameter(const _Iterator
& __it
, const char* __name
, _Is_iterator
)
264 : _M_kind(__iterator
), _M_variant()
266 _M_variant
._M_iterator
._M_name
= __name
;
267 _M_variant
._M_iterator
._M_address
= &__it
;
268 _M_variant
._M_iterator
._M_type
= &typeid(__it
);
269 _M_variant
._M_iterator
._M_constness
= __unknown_constness
;
270 _M_variant
._M_iterator
._M_state
=
271 __gnu_debug::__check_singular(__it
)? __singular
: __unknown_state
;
272 _M_variant
._M_iterator
._M_sequence
= 0;
273 _M_variant
._M_iterator
._M_seq_type
= 0;
276 template<typename _Sequence
>
277 _Parameter(const _Safe_sequence
<_Sequence
>& __seq
,
278 const char* __name
, _Is_sequence
)
279 : _M_kind(__sequence
), _M_variant()
281 _M_variant
._M_sequence
._M_name
= __name
;
282 _M_variant
._M_sequence
._M_address
=
283 static_cast<const _Sequence
*>(&__seq
);
284 _M_variant
._M_sequence
._M_type
= &typeid(_Sequence
);
287 template<typename _Sequence
>
288 _Parameter(const _Sequence
& __seq
, const char* __name
, _Is_sequence
)
289 : _M_kind(__sequence
), _M_variant()
291 _M_variant
._M_sequence
._M_name
= __name
;
292 _M_variant
._M_sequence
._M_address
= &__seq
;
293 _M_variant
._M_sequence
._M_type
= &typeid(_Sequence
);
297 _M_print_field(const _Error_formatter
* __formatter
,
298 const char* __name
) const;
301 _M_print_description(const _Error_formatter
* __formatter
) const;
304 friend struct _Parameter
;
307 template<typename _Iterator
>
308 const _Error_formatter
&
309 _M_iterator(const _Iterator
& __it
, const char* __name
= 0) const
311 if (_M_num_parameters
< size_t(__max_parameters
))
312 _M_parameters
[_M_num_parameters
++] = _Parameter(__it
, __name
,
317 const _Error_formatter
&
318 _M_integer(long __value
, const char* __name
= 0) const
320 if (_M_num_parameters
< size_t(__max_parameters
))
321 _M_parameters
[_M_num_parameters
++] = _Parameter(__value
, __name
);
325 const _Error_formatter
&
326 _M_string(const char* __value
, const char* __name
= 0) const
328 if (_M_num_parameters
< size_t(__max_parameters
))
329 _M_parameters
[_M_num_parameters
++] = _Parameter(__value
, __name
);
333 template<typename _Sequence
>
334 const _Error_formatter
&
335 _M_sequence(const _Sequence
& __seq
, const char* __name
= 0) const
337 if (_M_num_parameters
< size_t(__max_parameters
))
338 _M_parameters
[_M_num_parameters
++] = _Parameter(__seq
, __name
,
343 const _Error_formatter
&
344 _M_message(const char* __text
) const
345 { _M_text
= __text
; return *this; }
347 const _Error_formatter
&
348 _M_message(_Debug_msg_id __id
) const;
354 _Error_formatter(const char* __file
, size_t __line
)
355 : _M_file(__file
), _M_line(__line
), _M_num_parameters(0), _M_text(0),
356 _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false)
357 { _M_get_max_length(); }
359 template<typename _Tp
>
361 _M_format_word(char*, int, const char*, _Tp
) const;
364 _M_print_word(const char* __word
) const;
367 _M_print_string(const char* __string
) const;
370 _M_get_max_length() const;
372 enum { __max_parameters
= 9 };
376 mutable _Parameter _M_parameters
[__max_parameters
];
377 mutable size_t _M_num_parameters
;
378 mutable const char* _M_text
;
379 mutable size_t _M_max_length
;
380 enum { _M_indent
= 4 } ;
381 mutable size_t _M_column
;
382 mutable bool _M_first_line
;
383 mutable bool _M_wordwrap
;
386 static _Error_formatter
387 _M_at(const char* __file
, size_t __line
)
388 { return _Error_formatter(__file
, __line
); }
390 } // namespace __gnu_debug