# formatter.h

Go to the documentation of this file.

    00001 // Debug-mode error formatting implementation -*- C++ -*-
    00002
    00003 // Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    00004 //
    00005 // This file is part of the GNU ISO C++ Library.  This library is free
    00006 // software; you can redistribute it and/or modify it under the
    00007 // terms of the GNU General Public License as published by the
    00008 // Free Software Foundation; either version 2, or (at your option)
    00009 // any later version.
    00010
    00011 // This library is distributed in the hope that it will be useful,
    00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00014 // GNU General Public License for more details.
    00015
    00016 // You should have received a copy of the GNU General Public License along
    00017 // with this library; see the file COPYING.  If not, write to the Free
    00018 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
    00019 // USA.
    00020
    00021 // As a special exception, you may use this file as part of a free software
    00022 // library without restriction.  Specifically, if other files instantiate
    00023 // templates or use macros or inline functions from this file, or you compile
    00024 // this file and link it with other files to produce an executable, this
    00025 // file does not by itself cause the resulting executable to be covered by
    00026 // the GNU General Public License.  This exception does not however
    00027 // invalidate any other reasons why the executable file might be covered by
    00028 // the GNU General Public License.
    00029
    00030 /** @file debug/formatter.h
    00031  *  This file is a GNU debug extension to the Standard C++ Library.
    00032  */
    00033
    00034 #ifndef _GLIBCXX_DEBUG_FORMATTER_H
    00035 #define _GLIBCXX_DEBUG_FORMATTER_H 1
    00036
    00037 #include <typeinfo>
    00038 #include <debug/debug.h>
    00039
    00040 namespace __gnu_debug
    00041 {
    00042   using std::type_info;
    00043
    00044   /** Determine if the two types are the same. */
    00045   template<typename _Type1, typename _Type2>
    00046     struct __is_same
    00047     {
    00048       static const bool value = false;
    00049     };
    00050
    00051   template<typename _Type>
    00052     struct __is_same<_Type, _Type>
    00053     {
    00054       static const bool value = true;
    00055     };
    00056
    00057   template<bool> struct __truth { };
    00058
    00059   class _Safe_sequence_base;
    00060
    00061   template<typename _Iterator, typename _Sequence>
    00062     class _Safe_iterator;
    00063
    00064   template<typename _Sequence>
    00065     class _Safe_sequence;
    00066
    00067   enum _Debug_msg_id
    00068   {
    00069     // General checks
    00070     __msg_valid_range,
    00071     __msg_insert_singular,
    00072     __msg_insert_different,
    00073     __msg_erase_bad,
    00074     __msg_erase_different,
    00075     __msg_subscript_oob,
    00076     __msg_empty,
    00077     __msg_unpartitioned,
    00078     __msg_unpartitioned_pred,
    00079     __msg_unsorted,
    00080     __msg_unsorted_pred,
    00081     __msg_not_heap,
    00082     __msg_not_heap_pred,
    00083     // std::bitset checks
    00084     __msg_bad_bitset_write,
    00085     __msg_bad_bitset_read,
    00086     __msg_bad_bitset_flip,
    00087     // std::list checks
    00088     __msg_self_splice,
    00089     __msg_splice_alloc,
    00090     __msg_splice_bad,
    00091     __msg_splice_other,
    00092     __msg_splice_overlap,
    00093     // iterator checks
    00094     __msg_init_singular,
    00095     __msg_init_copy_singular,
    00096     __msg_init_const_singular,
    00097     __msg_copy_singular,
    00098     __msg_bad_deref,
    00099     __msg_bad_inc,
    00100     __msg_bad_dec,
    00101     __msg_iter_subscript_oob,
    00102     __msg_advance_oob,
    00103     __msg_retreat_oob,
    00104     __msg_iter_compare_bad,
    00105     __msg_compare_different,
    00106     __msg_iter_order_bad,
    00107     __msg_order_different,
    00108     __msg_distance_bad,
    00109     __msg_distance_different,
    00110     // istream_iterator
    00111     __msg_deref_istream,
    00112     __msg_inc_istream,
    00113     // ostream_iterator
    00114     __msg_output_ostream,
    00115     // istreambuf_iterator
    00116     __msg_deref_istreambuf,
    00117     __msg_inc_istreambuf
    00118   };
    00119
    00120   class _Error_formatter
    00121   {
    00122     /// Whether an iterator is constant, mutable, or unknown
    00123     enum _Constness
    00124     {
    00125       __unknown_constness,
    00126       __const_iterator,
    00127       __mutable_iterator,
    00128       __last_constness
    00129     };
    00130
    00131     // The state of the iterator (fine-grained), if we know it.
    00132     enum _Iterator_state
    00133     {
    00134       __unknown_state,
    00135       __singular,      // singular, may still be attached to a sequence
    00136       __begin,         // dereferenceable, and at the beginning
    00137       __middle,        // dereferenceable, not at the beginning
    00138       __end,           // past-the-end, may be at beginning if sequence empty
    00139       __last_state
    00140     };
    00141
    00142     // Tags denoting the type of parameter for construction
    00143     struct _Is_iterator { };
    00144     struct _Is_sequence { };
    00145
    00146     // A parameter that may be referenced by an error message
    00147     struct _Parameter
    00148     {
    00149       enum
    00150       {
    00151     __unused_param,
    00152     __iterator,
    00153     __sequence,
    00154     __integer,
    00155     __string
    00156       } _M_kind;
    00157
    00158       union
    00159       {
    00160     // When _M_kind == __iterator
    00161     struct
    00162     {
    00163       const char*      _M_name;
    00164       const void*      _M_address;
    00165       const type_info* _M_type;
    00166       _Constness       _M_constness;
    00167       _Iterator_state  _M_state;
    00168       const void*      _M_sequence;
    00169       const type_info* _M_seq_type;
    00170     } _M_iterator;
    00171
    00172     // When _M_kind == __sequence
    00173     struct
    00174     {
    00175       const char*      _M_name;
    00176       const void*      _M_address;
    00177       const type_info* _M_type;
    00178     } _M_sequence;
    00179
    00180     // When _M_kind == __integer
    00181     struct
    00182     {
    00183       const char* _M_name;
    00184       long        _M_value;
    00185     } _M_integer;
    00186
    00187     // When _M_kind == __string
    00188     struct
    00189     {
    00190       const char* _M_name;
    00191       const char* _M_value;
    00192     } _M_string;
    00193       } _M_variant;
    00194
    00195       _Parameter() : _M_kind(__unused_param), _M_variant() { }
    00196
    00197       _Parameter(long __value, const char* __name)
    00198       : _M_kind(__integer), _M_variant()
    00199       {
    00200     _M_variant._M_integer._M_name = __name;
    00201     _M_variant._M_integer._M_value = __value;
    00202       }
    00203
    00204       _Parameter(const char* __value, const char* __name)
    00205       : _M_kind(__string), _M_variant()
    00206       {
    00207     _M_variant._M_string._M_name = __name;
    00208     _M_variant._M_string._M_value = __value;
    00209       }
    00210
    00211       template<typename _Iterator, typename _Sequence>
    00212         _Parameter(const _Safe_iterator<_Iterator, _Sequence>& __it,
    00213            const char* __name, _Is_iterator)
    00214     : _M_kind(__iterator),  _M_variant()
    00215         {
    00216       _M_variant._M_iterator._M_name = __name;
    00217       _M_variant._M_iterator._M_address = &__it;
    00218       _M_variant._M_iterator._M_type = &typeid(__it);
    00219       _M_variant._M_iterator._M_constness =
    00220         __is_same<_Safe_iterator<_Iterator, _Sequence>,
    00221                              typename _Sequence::iterator>::
    00222           value? __mutable_iterator : __const_iterator;
    00223       _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
    00224       _M_variant._M_iterator._M_seq_type = &typeid(_Sequence);
    00225
    00226       if (__it._M_singular())
    00227         _M_variant._M_iterator._M_state = __singular;
    00228       else
    00229         {
    00230           bool __is_begin = __it._M_is_begin();
    00231           bool __is_end = __it._M_is_end();
    00232           if (__is_end)
    00233         _M_variant._M_iterator._M_state = __end;
    00234           else if (__is_begin)
    00235         _M_variant._M_iterator._M_state = __begin;
    00236           else
    00237         _M_variant._M_iterator._M_state = __middle;
    00238         }
    00239     }
    00240
    00241       template<typename _Type>
    00242         _Parameter(const _Type*& __it, const char* __name, _Is_iterator)
    00243         : _M_kind(__iterator), _M_variant()
    00244         {
    00245       _M_variant._M_iterator._M_name = __name;
    00246       _M_variant._M_iterator._M_address = &__it;
    00247       _M_variant._M_iterator._M_type = &typeid(__it);
    00248       _M_variant._M_iterator._M_constness = __mutable_iterator;
    00249       _M_variant._M_iterator._M_state = __it? __unknown_state : __singular;
    00250       _M_variant._M_iterator._M_sequence = 0;
    00251       _M_variant._M_iterator._M_seq_type = 0;
    00252     }
    00253
    00254       template<typename _Type>
    00255         _Parameter(_Type*& __it, const char* __name, _Is_iterator)
    00256         : _M_kind(__iterator), _M_variant()
    00257         {
    00258       _M_variant._M_iterator._M_name = __name;
    00259       _M_variant._M_iterator._M_address = &__it;
    00260       _M_variant._M_iterator._M_type = &typeid(__it);
    00261       _M_variant._M_iterator._M_constness = __const_iterator;
    00262       _M_variant._M_iterator._M_state = __it? __unknown_state : __singular;
    00263       _M_variant._M_iterator._M_sequence = 0;
    00264       _M_variant._M_iterator._M_seq_type = 0;
    00265     }
    00266
    00267       template<typename _Iterator>
    00268         _Parameter(const _Iterator& __it, const char* __name, _Is_iterator)
    00269         : _M_kind(__iterator), _M_variant()
    00270         {
    00271       _M_variant._M_iterator._M_name = __name;
    00272       _M_variant._M_iterator._M_address = &__it;
    00273       _M_variant._M_iterator._M_type = &typeid(__it);
    00274       _M_variant._M_iterator._M_constness = __unknown_constness;
    00275       _M_variant._M_iterator._M_state =
    00276         __gnu_debug::__check_singular(__it)? __singular : __unknown_state;
    00277       _M_variant._M_iterator._M_sequence = 0;
    00278       _M_variant._M_iterator._M_seq_type = 0;
    00279     }
    00280
    00281       template<typename _Sequence>
    00282         _Parameter(const _Safe_sequence<_Sequence>& __seq,
    00283            const char* __name, _Is_sequence)
    00284         : _M_kind(__sequence), _M_variant()
    00285         {
    00286       _M_variant._M_sequence._M_name = __name;
    00287       _M_variant._M_sequence._M_address =
    00288         static_cast<const _Sequence*>(&__seq);
    00289       _M_variant._M_sequence._M_type = &typeid(_Sequence);
    00290     }
    00291
    00292       template<typename _Sequence>
    00293         _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence)
    00294         : _M_kind(__sequence), _M_variant()
    00295         {
    00296       _M_variant._M_sequence._M_name = __name;
    00297       _M_variant._M_sequence._M_address = &__seq;
    00298       _M_variant._M_sequence._M_type = &typeid(_Sequence);
    00299     }
    00300
    00301       void
    00302       _M_print_field(const _Error_formatter* __formatter,
    00303              const char* __name) const;
    00304
    00305       void
    00306       _M_print_description(const _Error_formatter* __formatter) const;
    00307     };
    00308
    00309     friend struct _Parameter;
    00310
    00311   public:
    00312     template<typename _Iterator>
    00313       const _Error_formatter&
    00314       _M_iterator(const _Iterator& __it, const char* __name = 0)  const
    00315       {
    00316     if (_M_num_parameters < size_t(__max_parameters))
    00317       _M_parameters[_M_num_parameters++] = _Parameter(__it, __name,
    00318                               _Is_iterator());
    00319     return *this;
    00320       }
    00321
    00322     const _Error_formatter&
    00323     _M_integer(long __value, const char* __name = 0) const
    00324     {
    00325       if (_M_num_parameters < size_t(__max_parameters))
    00326     _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
    00327       return *this;
    00328     }
    00329
    00330     const _Error_formatter&
    00331     _M_string(const char* __value, const char* __name = 0) const
    00332     {
    00333       if (_M_num_parameters < size_t(__max_parameters))
    00334     _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
    00335       return *this;
    00336     }
    00337
    00338     template<typename _Sequence>
    00339       const _Error_formatter&
    00340       _M_sequence(const _Sequence& __seq, const char* __name = 0) const
    00341       {
    00342     if (_M_num_parameters < size_t(__max_parameters))
    00343       _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name,
    00344                               _Is_sequence());
    00345     return *this;
    00346       }
    00347
    00348     const _Error_formatter&
    00349     _M_message(const char* __text) const
    00350     { _M_text = __text; return *this; }
    00351
    00352     const _Error_formatter&
    00353     _M_message(_Debug_msg_id __id) const;
    00354
    00355     void
    00356     _M_error() const;
    00357
    00358   private:
    00359     _Error_formatter(const char* __file, size_t __line)
    00360     : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0),
    00361       _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false)
    00362     { }
    00363
    00364     template<typename _Tp>
    00365       void
    00366       _M_format_word(char*, int, const char*, _Tp) const;
    00367
    00368     void
    00369     _M_print_word(const char* __word) const;
    00370
    00371     void
    00372     _M_print_string(const char* __string) const;
    00373
    00374     enum { __max_parameters = 9 };
    00375
    00376     const char*         _M_file;
    00377     size_t              _M_line;
    00378     mutable _Parameter  _M_parameters[__max_parameters];
    00379     mutable size_t      _M_num_parameters;
    00380     mutable const char* _M_text;
    00381     mutable size_t      _M_max_length;
    00382     enum { _M_indent = 4 } ;
    00383     mutable size_t      _M_column;
    00384     mutable bool        _M_first_line;
    00385     mutable bool        _M_wordwrap;
    00386
    00387   public:
    00388     static _Error_formatter
    00389     _M_at(const char* __file, size_t __line)
    00390     { return _Error_formatter(__file, __line); }
    00391   };
    00392 } // namespace __gnu_debug
    00393
    00394 #endif