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