formatter.h revision 132720
1151497Sru// Debug-mode error formatting implementation -*- C++ -*- 275584Sru 375584Sru// Copyright (C) 2003, 2004 475584Sru// Free Software Foundation, Inc. 575584Sru// 675584Sru// This file is part of the GNU ISO C++ Library. This library is free 775584Sru// software; you can redistribute it and/or modify it under the 875584Sru// terms of the GNU General Public License as published by the 975584Sru// Free Software Foundation; either version 2, or (at your option) 10151497Sru// any later version. 11151497Sru 1275584Sru// This library is distributed in the hope that it will be useful, 13151497Sru// but WITHOUT ANY WARRANTY; without even the implied warranty of 1475584Sru// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15151497Sru// GNU General Public License for more details. 1675584Sru 17151497Sru// You should have received a copy of the GNU General Public License along 18151497Sru// with this library; see the file COPYING. If not, write to the Free 19151497Sru// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 2075584Sru// USA. 21151497Sru 22151497Sru// As a special exception, you may use this file as part of a free software 23151497Sru// library without restriction. Specifically, if other files instantiate 24151497Sru// templates or use macros or inline functions from this file, or you compile 25151497Sru// this file and link it with other files to produce an executable, this 26151497Sru// file does not by itself cause the resulting executable to be covered by 2775584Sru// the GNU General Public License. This exception does not however 28151497Sru// invalidate any other reasons why the executable file might be covered by 29151497Sru// the GNU General Public License. 3075584Sru 31151497Sru#ifndef _GLIBCXX_DEBUG_FORMATTER_H 32151497Sru#define _GLIBCXX_DEBUG_FORMATTER_H 1 33151497Sru 34151497Sru#include <typeinfo> 35151497Sru#include <debug/debug.h> 36151497Sru 37151497Srunamespace __gnu_debug 38151497Sru{ 39151497Sru using std::type_info; 40151497Sru 41151497Sru /** Determine if the two types are the same. */ 42151497Sru template<typename _Type1, typename _Type2> 43151497Sru struct __is_same 44151497Sru { 45151497Sru static const bool value = false; 46151497Sru }; 47151497Sru 4875584Sru template<typename _Type> 49151497Sru struct __is_same<_Type, _Type> 50151497Sru { 51151497Sru static const bool value = true; 52151497Sru }; 53151497Sru 54151497Sru template<bool> struct __truth { }; 55151497Sru 56151497Sru class _Safe_sequence_base; 57151497Sru 58151497Sru template<typename _Iterator, typename _Sequence> 59151497Sru class _Safe_iterator; 60151497Sru 61151497Sru template<typename _Sequence> 62151497Sru class _Safe_sequence; 63151497Sru 64151497Sru enum _Debug_msg_id 65151497Sru { 66151497Sru // General checks 67151497Sru __msg_valid_range, 68151497Sru __msg_insert_singular, 69151497Sru __msg_insert_different, 70151497Sru __msg_erase_bad, 71151497Sru __msg_erase_different, 72151497Sru __msg_subscript_oob, 73151497Sru __msg_empty, 74151497Sru __msg_unpartitioned, 75151497Sru __msg_unpartitioned_pred, 7675584Sru __msg_unsorted, 77151497Sru __msg_unsorted_pred, 7875584Sru __msg_not_heap, 79151497Sru __msg_not_heap_pred, 8075584Sru // std::bitset checks 81151497Sru __msg_bad_bitset_write, 82151497Sru __msg_bad_bitset_read, 83151497Sru __msg_bad_bitset_flip, 8475584Sru // std::list checks 85151497Sru __msg_self_splice, 86151497Sru __msg_splice_alloc, 87151497Sru __msg_splice_bad, 88151497Sru __msg_splice_other, 89151497Sru __msg_splice_overlap, 90151497Sru // iterator checks 91151497Sru __msg_init_singular, 92151497Sru __msg_init_copy_singular, 93151497Sru __msg_init_const_singular, 94151497Sru __msg_copy_singular, 95151497Sru __msg_bad_deref, 96151497Sru __msg_bad_inc, 97151497Sru __msg_bad_dec, 98151497Sru __msg_iter_subscript_oob, 99151497Sru __msg_advance_oob, 100151497Sru __msg_retreat_oob, 101151497Sru __msg_iter_compare_bad, 102151497Sru __msg_compare_different, 103151497Sru __msg_iter_order_bad, 104151497Sru __msg_order_different, 105151497Sru __msg_distance_bad, 106151497Sru __msg_distance_different, 107151497Sru // istream_iterator 108151497Sru __msg_deref_istream, 109151497Sru __msg_inc_istream, 110151497Sru // ostream_iterator 111151497Sru __msg_output_ostream, 112151497Sru // istreambuf_iterator 113151497Sru __msg_deref_istreambuf, 114151497Sru __msg_inc_istreambuf 115151497Sru }; 116151497Sru 117151497Sru class _Error_formatter 118151497Sru { 119151497Sru /// Whether an iterator is constant, mutable, or unknown 120151497Sru enum _Constness 121151497Sru { 122151497Sru __unknown_constness, 123151497Sru __const_iterator, 124151497Sru __mutable_iterator, 125151497Sru __last_constness 126151497Sru }; 127151497Sru 12875584Sru // The state of the iterator (fine-grained), if we know it. 129151497Sru enum _Iterator_state 130151497Sru { 131151497Sru __unknown_state, 132151497Sru __singular, // singular, may still be attached to a sequence 133151497Sru __begin, // dereferenceable, and at the beginning 134151497Sru __middle, // dereferenceable, not at the beginning 135151497Sru __end, // past-the-end, may be at beginning if sequence empty 136151497Sru __last_state 137151497Sru }; 138151497Sru 139151497Sru // Tags denoting the type of parameter for construction 140151497Sru struct _Is_iterator { }; 141151497Sru struct _Is_sequence { }; 142151497Sru 143151497Sru // A parameter that may be referenced by an error message 144151497Sru struct _Parameter 145151497Sru { 146151497Sru enum 147151497Sru { 148151497Sru __unused_param, 149151497Sru __iterator, 150151497Sru __sequence, 151151497Sru __integer, 152151497Sru __string 153151497Sru } _M_kind; 154151497Sru 155151497Sru union 156151497Sru { 157151497Sru // When _M_kind == __iterator 158151497Sru struct 159151497Sru { 160151497Sru const char* _M_name; 161151497Sru const void* _M_address; 162151497Sru const type_info* _M_type; 163151497Sru _Constness _M_constness; 164151497Sru _Iterator_state _M_state; 165151497Sru const void* _M_sequence; 166151497Sru const type_info* _M_seq_type; 167151497Sru } _M_iterator; 168151497Sru 169151497Sru // When _M_kind == __sequence 170151497Sru struct 171151497Sru { 172151497Sru const char* _M_name; 173151497Sru const void* _M_address; 174151497Sru const type_info* _M_type; 175151497Sru } _M_sequence; 176151497Sru 177151497Sru // When _M_kind == __integer 178151497Sru struct 179151497Sru { 180151497Sru const char* _M_name; 181151497Sru long _M_value; 182151497Sru } _M_integer; 183151497Sru 184151497Sru // When _M_kind == __string 185151497Sru struct 186151497Sru { 187151497Sru const char* _M_name; 188151497Sru const char* _M_value; 189151497Sru } _M_string; 190151497Sru } _M_variant; 191151497Sru 192151497Sru _Parameter() : _M_kind(__unused_param), _M_variant() { } 193151497Sru 194151497Sru _Parameter(long __value, const char* __name) 195151497Sru : _M_kind(__integer), _M_variant() 196151497Sru { 197151497Sru _M_variant._M_integer._M_name = __name; 198151497Sru _M_variant._M_integer._M_value = __value; 199151497Sru } 200151497Sru 201151497Sru _Parameter(const char* __value, const char* __name) 202151497Sru : _M_kind(__string), _M_variant() 203151497Sru { 204151497Sru _M_variant._M_string._M_name = __name; 205151497Sru _M_variant._M_string._M_value = __value; 206151497Sru } 207151497Sru 208151497Sru template<typename _Iterator, typename _Sequence> 209151497Sru _Parameter(const _Safe_iterator<_Iterator, _Sequence>& __it, 210151497Sru const char* __name, _Is_iterator) 211151497Sru : _M_kind(__iterator), _M_variant() 212151497Sru { 213151497Sru _M_variant._M_iterator._M_name = __name; 214151497Sru _M_variant._M_iterator._M_address = &__it; 215151497Sru _M_variant._M_iterator._M_type = &typeid(__it); 216151497Sru _M_variant._M_iterator._M_constness = 217151497Sru __is_same<_Safe_iterator<_Iterator, _Sequence>, 218151497Sru typename _Sequence::iterator>:: 219151497Sru value? __mutable_iterator : __const_iterator; 220151497Sru _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); 221151497Sru _M_variant._M_iterator._M_seq_type = &typeid(_Sequence); 222151497Sru 223151497Sru if (__it._M_singular()) 224151497Sru _M_variant._M_iterator._M_state = __singular; 225151497Sru else 226151497Sru { 227151497Sru bool __is_begin = __it._M_is_begin(); 228151497Sru bool __is_end = __it._M_is_end(); 229151497Sru if (__is_end) 230151497Sru _M_variant._M_iterator._M_state = __end; 231151497Sru else if (__is_begin) 232151497Sru _M_variant._M_iterator._M_state = __begin; 233151497Sru else 234151497Sru _M_variant._M_iterator._M_state = __middle; 235151497Sru } 236151497Sru } 237151497Sru 238151497Sru template<typename _Type> 239151497Sru _Parameter(const _Type*& __it, const char* __name, _Is_iterator) 240151497Sru : _M_kind(__iterator), _M_variant() 241151497Sru { 242151497Sru _M_variant._M_iterator._M_name = __name; 243151497Sru _M_variant._M_iterator._M_address = &__it; 244151497Sru _M_variant._M_iterator._M_type = &typeid(__it); 245151497Sru _M_variant._M_iterator._M_constness = __mutable_iterator; 246151497Sru _M_variant._M_iterator._M_state = __it? __unknown_state : __singular; 247151497Sru _M_variant._M_iterator._M_sequence = 0; 248151497Sru _M_variant._M_iterator._M_seq_type = 0; 249151497Sru } 250151497Sru 251151497Sru template<typename _Type> 252151497Sru _Parameter(_Type*& __it, const char* __name, _Is_iterator) 253151497Sru : _M_kind(__iterator), _M_variant() 254151497Sru { 255151497Sru _M_variant._M_iterator._M_name = __name; 256151497Sru _M_variant._M_iterator._M_address = &__it; 257151497Sru _M_variant._M_iterator._M_type = &typeid(__it); 258151497Sru _M_variant._M_iterator._M_constness = __const_iterator; 259151497Sru _M_variant._M_iterator._M_state = __it? __unknown_state : __singular; 260151497Sru _M_variant._M_iterator._M_sequence = 0; 261151497Sru _M_variant._M_iterator._M_seq_type = 0; 262151497Sru } 263151497Sru 264151497Sru template<typename _Iterator> 265151497Sru _Parameter(const _Iterator& __it, const char* __name, _Is_iterator) 266151497Sru : _M_kind(__iterator), _M_variant() 267151497Sru { 268151497Sru _M_variant._M_iterator._M_name = __name; 269151497Sru _M_variant._M_iterator._M_address = &__it; 270151497Sru _M_variant._M_iterator._M_type = &typeid(__it); 271151497Sru _M_variant._M_iterator._M_constness = __unknown_constness; 272151497Sru _M_variant._M_iterator._M_state = 273151497Sru __gnu_debug::__check_singular(__it)? __singular : __unknown_state; 274151497Sru _M_variant._M_iterator._M_sequence = 0; 275151497Sru _M_variant._M_iterator._M_seq_type = 0; 276151497Sru } 277151497Sru 278151497Sru template<typename _Sequence> 279151497Sru _Parameter(const _Safe_sequence<_Sequence>& __seq, 280151497Sru const char* __name, _Is_sequence) 281151497Sru : _M_kind(__sequence), _M_variant() 282151497Sru { 283151497Sru _M_variant._M_sequence._M_name = __name; 284151497Sru _M_variant._M_sequence._M_address = 285151497Sru static_cast<const _Sequence*>(&__seq); 286151497Sru _M_variant._M_sequence._M_type = &typeid(_Sequence); 287151497Sru } 288151497Sru 289151497Sru template<typename _Sequence> 290151497Sru _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence) 291151497Sru : _M_kind(__sequence), _M_variant() 292151497Sru { 293151497Sru _M_variant._M_sequence._M_name = __name; 294151497Sru _M_variant._M_sequence._M_address = &__seq; 295151497Sru _M_variant._M_sequence._M_type = &typeid(_Sequence); 296151497Sru } 297151497Sru 298151497Sru void 299151497Sru _M_print_field(const _Error_formatter* __formatter, 300151497Sru const char* __name) const; 301151497Sru 302151497Sru void 303151497Sru _M_print_description(const _Error_formatter* __formatter) const; 304151497Sru }; 305151497Sru 306151497Sru friend struct _Parameter; 307151497Sru 308151497Sru public: 309151497Sru template<typename _Iterator> 310151497Sru const _Error_formatter& 311151497Sru _M_iterator(const _Iterator& __it, const char* __name = 0) const 312151497Sru { 313151497Sru if (_M_num_parameters < __max_parameters) 314151497Sru _M_parameters[_M_num_parameters++] = _Parameter(__it, __name, 315151497Sru _Is_iterator()); 316151497Sru return *this; 317151497Sru } 318151497Sru 319151497Sru const _Error_formatter& 320151497Sru _M_integer(long __value, const char* __name = 0) const 321151497Sru { 322151497Sru if (_M_num_parameters < __max_parameters) 323151497Sru _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 324151497Sru return *this; 325151497Sru } 326151497Sru 327151497Sru const _Error_formatter& 328151497Sru _M_string(const char* __value, const char* __name = 0) const 329151497Sru { 330151497Sru if (_M_num_parameters < __max_parameters) 331151497Sru _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 332 return *this; 333 } 334 335 template<typename _Sequence> 336 const _Error_formatter& 337 _M_sequence(const _Sequence& __seq, const char* __name = 0) const 338 { 339 if (_M_num_parameters < __max_parameters) 340 _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name, 341 _Is_sequence()); 342 return *this; 343 } 344 345 const _Error_formatter& 346 _M_message(const char* __text) const 347 { _M_text = __text; return *this; } 348 349 const _Error_formatter& 350 _M_message(_Debug_msg_id __id) const; 351 352 void 353 _M_error() const; 354 355 private: 356 _Error_formatter(const char* __file, size_t __line) 357 : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0), 358 _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false) 359 { } 360 361 template<typename _Tp> 362 void 363 _M_format_word(char*, int, const char*, _Tp) const; 364 365 void 366 _M_print_word(const char* __word) const; 367 368 void 369 _M_print_string(const char* __string) const; 370 371 enum { __max_parameters = 9 }; 372 373 const char* _M_file; 374 size_t _M_line; 375 mutable _Parameter _M_parameters[__max_parameters]; 376 mutable size_t _M_num_parameters; 377 mutable const char* _M_text; 378 mutable size_t _M_max_length; 379 enum { _M_indent = 4 } ; 380 mutable size_t _M_column; 381 mutable bool _M_first_line; 382 mutable bool _M_wordwrap; 383 384 public: 385 static _Error_formatter 386 _M_at(const char* __file, size_t __line) 387 { return _Error_formatter(__file, __line); } 388 }; 389} // namespace __gnu_debug 390 391#endif 392