Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // Debug-mode error formatting implementation -*- C++ -*-
  2.  
  3. // Copyright (C) 2003-2013 Free Software Foundation, Inc.
  4. //
  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)
  9. // any later version.
  10.  
  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.
  15.  
  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.
  19.  
  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/>.
  24.  
  25. /** @file debug/formatter.h
  26.  *  This file is a GNU debug extension to the Standard C++ Library.
  27.  */
  28.  
  29. #ifndef _GLIBCXX_DEBUG_FORMATTER_H
  30. #define _GLIBCXX_DEBUG_FORMATTER_H 1
  31.  
  32. #include <bits/c++config.h>
  33. #include <bits/cpp_type_traits.h>
  34. #include <typeinfo>
  35.  
  36. namespace __gnu_debug
  37. {
  38.   using std::type_info;
  39.  
  40.   template<typename _Iterator>
  41.     bool __check_singular(_Iterator&);
  42.  
  43.   class _Safe_sequence_base;
  44.  
  45.   template<typename _Iterator, typename _Sequence>
  46.     class _Safe_iterator;
  47.  
  48.   template<typename _Iterator, typename _Sequence>
  49.     class _Safe_local_iterator;
  50.  
  51.   template<typename _Sequence>
  52.     class _Safe_sequence;
  53.  
  54.   enum _Debug_msg_id
  55.   {
  56.     // General checks
  57.     __msg_valid_range,
  58.     __msg_insert_singular,
  59.     __msg_insert_different,
  60.     __msg_erase_bad,
  61.     __msg_erase_different,
  62.     __msg_subscript_oob,
  63.     __msg_empty,
  64.     __msg_unpartitioned,
  65.     __msg_unpartitioned_pred,
  66.     __msg_unsorted,
  67.     __msg_unsorted_pred,
  68.     __msg_not_heap,
  69.     __msg_not_heap_pred,
  70.     // std::bitset checks
  71.     __msg_bad_bitset_write,
  72.     __msg_bad_bitset_read,
  73.     __msg_bad_bitset_flip,
  74.     // std::list checks
  75.     __msg_self_splice,
  76.     __msg_splice_alloc,
  77.     __msg_splice_bad,
  78.     __msg_splice_other,
  79.     __msg_splice_overlap,
  80.     // iterator checks
  81.     __msg_init_singular,
  82.     __msg_init_copy_singular,
  83.     __msg_init_const_singular,
  84.     __msg_copy_singular,
  85.     __msg_bad_deref,
  86.     __msg_bad_inc,
  87.     __msg_bad_dec,
  88.     __msg_iter_subscript_oob,
  89.     __msg_advance_oob,
  90.     __msg_retreat_oob,
  91.     __msg_iter_compare_bad,
  92.     __msg_compare_different,
  93.     __msg_iter_order_bad,
  94.     __msg_order_different,
  95.     __msg_distance_bad,
  96.     __msg_distance_different,
  97.     // istream_iterator
  98.     __msg_deref_istream,
  99.     __msg_inc_istream,
  100.     // ostream_iterator
  101.     __msg_output_ostream,
  102.     // istreambuf_iterator
  103.     __msg_deref_istreambuf,
  104.     __msg_inc_istreambuf,
  105.     // forward_list
  106.     __msg_insert_after_end,
  107.     __msg_erase_after_bad,
  108.     __msg_valid_range2,
  109.     // unordered container local iterators
  110.     __msg_local_iter_compare_bad,
  111.     __msg_non_empty_range,
  112.     // self move assign
  113.     __msg_self_move_assign,
  114.     // unordered container buckets
  115.     __msg_bucket_index_oob,
  116.     __msg_valid_load_factor,
  117.     __msg_equal_allocs
  118.   };
  119.  
  120.   class _Error_formatter
  121.   {
  122.     /// Whether an iterator is constant, mutable, or unknown
  123.     enum _Constness
  124.     {
  125.       __unknown_constness,
  126.       __const_iterator,
  127.       __mutable_iterator,
  128.       __last_constness
  129.     };
  130.  
  131.     // The state of the iterator (fine-grained), if we know it.
  132.     enum _Iterator_state
  133.     {
  134.       __unknown_state,
  135.       __singular,      // singular, may still be attached to a sequence
  136.       __begin,         // dereferenceable, and at the beginning
  137.       __middle,        // dereferenceable, not at the beginning
  138.       __end,           // past-the-end, may be at beginning if sequence empty
  139.       __before_begin,  // before begin
  140.       __last_state
  141.     };
  142.  
  143.     // Tags denoting the type of parameter for construction
  144.     struct _Is_iterator { };
  145.     struct _Is_sequence { };
  146.  
  147.     // A parameter that may be referenced by an error message
  148.     struct _Parameter
  149.     {
  150.       enum
  151.       {
  152.         __unused_param,
  153.         __iterator,
  154.         __sequence,
  155.         __integer,
  156.         __string
  157.       } _M_kind;
  158.  
  159.       union
  160.       {
  161.         // When _M_kind == __iterator
  162.         struct
  163.         {
  164.           const char*      _M_name;
  165.           const void*      _M_address;
  166.           const type_info* _M_type;
  167.           _Constness       _M_constness;
  168.           _Iterator_state  _M_state;
  169.           const void*      _M_sequence;
  170.           const type_info* _M_seq_type;
  171.         } _M_iterator;
  172.  
  173.         // When _M_kind == __sequence
  174.         struct
  175.         {
  176.           const char*      _M_name;
  177.           const void*      _M_address;
  178.           const type_info* _M_type;
  179.         } _M_sequence;
  180.  
  181.         // When _M_kind == __integer
  182.         struct
  183.         {
  184.           const char* _M_name;
  185.           long        _M_value;
  186.         } _M_integer;
  187.  
  188.         // When _M_kind == __string
  189.         struct
  190.         {
  191.           const char* _M_name;
  192.           const char* _M_value;
  193.         } _M_string;
  194.       } _M_variant;
  195.  
  196.       _Parameter() : _M_kind(__unused_param), _M_variant() { }
  197.  
  198.       _Parameter(long __value, const char* __name)
  199.       : _M_kind(__integer), _M_variant()
  200.       {
  201.         _M_variant._M_integer._M_name = __name;
  202.         _M_variant._M_integer._M_value = __value;
  203.       }
  204.  
  205.       _Parameter(const char* __value, const char* __name)
  206.       : _M_kind(__string), _M_variant()
  207.       {
  208.         _M_variant._M_string._M_name = __name;
  209.         _M_variant._M_string._M_value = __value;
  210.       }
  211.  
  212.       template<typename _Iterator, typename _Sequence>
  213.         _Parameter(const _Safe_iterator<_Iterator, _Sequence>& __it,
  214.                    const char* __name, _Is_iterator)
  215.         : _M_kind(__iterator),  _M_variant()
  216.         {
  217.           _M_variant._M_iterator._M_name = __name;
  218.           _M_variant._M_iterator._M_address = &__it;
  219. #ifdef __GXX_RTTI
  220.           _M_variant._M_iterator._M_type = &typeid(__it);
  221. #else
  222.           _M_variant._M_iterator._M_type = 0;
  223. #endif
  224.           _M_variant._M_iterator._M_constness =
  225.             std::__are_same<_Safe_iterator<_Iterator, _Sequence>,
  226.                             typename _Sequence::iterator>::
  227.               __value ? __mutable_iterator : __const_iterator;
  228.           _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
  229. #ifdef __GXX_RTTI
  230.           _M_variant._M_iterator._M_seq_type = &typeid(_Sequence);
  231. #else
  232.           _M_variant._M_iterator._M_seq_type = 0;
  233. #endif
  234.  
  235.           if (__it._M_singular())
  236.             _M_variant._M_iterator._M_state = __singular;
  237.           else
  238.             {
  239.               if (__it._M_is_before_begin())
  240.                 _M_variant._M_iterator._M_state = __before_begin;
  241.               else if (__it._M_is_end())
  242.                 _M_variant._M_iterator._M_state = __end;
  243.               else if (__it._M_is_begin())
  244.                 _M_variant._M_iterator._M_state = __begin;
  245.               else
  246.                 _M_variant._M_iterator._M_state = __middle;
  247.             }
  248.         }
  249.  
  250.       template<typename _Iterator, typename _Sequence>
  251.         _Parameter(const _Safe_local_iterator<_Iterator, _Sequence>& __it,
  252.                    const char* __name, _Is_iterator)
  253.         : _M_kind(__iterator),  _M_variant()
  254.         {
  255.           _M_variant._M_iterator._M_name = __name;
  256.           _M_variant._M_iterator._M_address = &__it;
  257. #ifdef __GXX_RTTI
  258.           _M_variant._M_iterator._M_type = &typeid(__it);
  259. #else
  260.           _M_variant._M_iterator._M_type = 0;
  261. #endif
  262.           _M_variant._M_iterator._M_constness =
  263.             std::__are_same<_Safe_local_iterator<_Iterator, _Sequence>,
  264.                             typename _Sequence::local_iterator>::
  265.               __value ? __mutable_iterator : __const_iterator;
  266.           _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
  267. #ifdef __GXX_RTTI
  268.           _M_variant._M_iterator._M_seq_type = &typeid(_Sequence);
  269. #else
  270.           _M_variant._M_iterator._M_seq_type = 0;
  271. #endif
  272.  
  273.           if (__it._M_singular())
  274.             _M_variant._M_iterator._M_state = __singular;
  275.           else
  276.             {
  277.               if (__it._M_is_end())
  278.                 _M_variant._M_iterator._M_state = __end;
  279.               else if (__it._M_is_begin())
  280.                 _M_variant._M_iterator._M_state = __begin;
  281.               else
  282.                 _M_variant._M_iterator._M_state = __middle;
  283.             }
  284.         }
  285.  
  286.       template<typename _Type>
  287.         _Parameter(const _Type*& __it, const char* __name, _Is_iterator)
  288.         : _M_kind(__iterator), _M_variant()
  289.         {
  290.           _M_variant._M_iterator._M_name = __name;
  291.           _M_variant._M_iterator._M_address = &__it;
  292. #ifdef __GXX_RTTI
  293.           _M_variant._M_iterator._M_type = &typeid(__it);
  294. #else
  295.           _M_variant._M_iterator._M_type = 0;
  296. #endif
  297.           _M_variant._M_iterator._M_constness = __mutable_iterator;
  298.           _M_variant._M_iterator._M_state = __it? __unknown_state : __singular;
  299.           _M_variant._M_iterator._M_sequence = 0;
  300.           _M_variant._M_iterator._M_seq_type = 0;
  301.         }
  302.  
  303.       template<typename _Type>
  304.         _Parameter(_Type*& __it, const char* __name, _Is_iterator)
  305.         : _M_kind(__iterator), _M_variant()
  306.         {
  307.           _M_variant._M_iterator._M_name = __name;
  308.           _M_variant._M_iterator._M_address = &__it;
  309. #ifdef __GXX_RTTI
  310.           _M_variant._M_iterator._M_type = &typeid(__it);
  311. #else
  312.           _M_variant._M_iterator._M_type = 0;
  313. #endif
  314.           _M_variant._M_iterator._M_constness = __const_iterator;
  315.           _M_variant._M_iterator._M_state = __it? __unknown_state : __singular;
  316.           _M_variant._M_iterator._M_sequence = 0;
  317.           _M_variant._M_iterator._M_seq_type = 0;
  318.         }
  319.  
  320.       template<typename _Iterator>
  321.         _Parameter(const _Iterator& __it, const char* __name, _Is_iterator)
  322.         : _M_kind(__iterator), _M_variant()
  323.         {
  324.           _M_variant._M_iterator._M_name = __name;
  325.           _M_variant._M_iterator._M_address = &__it;
  326. #ifdef __GXX_RTTI
  327.           _M_variant._M_iterator._M_type = &typeid(__it);
  328. #else
  329.           _M_variant._M_iterator._M_type = 0;
  330. #endif
  331.           _M_variant._M_iterator._M_constness = __unknown_constness;
  332.           _M_variant._M_iterator._M_state =
  333.             __gnu_debug::__check_singular(__it)? __singular : __unknown_state;
  334.           _M_variant._M_iterator._M_sequence = 0;
  335.           _M_variant._M_iterator._M_seq_type = 0;
  336.         }
  337.  
  338.       template<typename _Sequence>
  339.         _Parameter(const _Safe_sequence<_Sequence>& __seq,
  340.                    const char* __name, _Is_sequence)
  341.         : _M_kind(__sequence), _M_variant()
  342.         {
  343.           _M_variant._M_sequence._M_name = __name;
  344.           _M_variant._M_sequence._M_address =
  345.             static_cast<const _Sequence*>(&__seq);
  346. #ifdef __GXX_RTTI
  347.           _M_variant._M_sequence._M_type = &typeid(_Sequence);
  348. #else
  349.           _M_variant._M_sequence._M_type = 0;
  350. #endif
  351.         }
  352.  
  353.       template<typename _Sequence>
  354.         _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence)
  355.         : _M_kind(__sequence), _M_variant()
  356.         {
  357.           _M_variant._M_sequence._M_name = __name;
  358.           _M_variant._M_sequence._M_address = &__seq;
  359. #ifdef __GXX_RTTI
  360.           _M_variant._M_sequence._M_type = &typeid(_Sequence);
  361. #else
  362.           _M_variant._M_sequence._M_type = 0;
  363. #endif
  364.         }
  365.  
  366.       void
  367.       _M_print_field(const _Error_formatter* __formatter,
  368.                      const char* __name) const;
  369.  
  370.       void
  371.       _M_print_description(const _Error_formatter* __formatter) const;
  372.     };
  373.  
  374.     friend struct _Parameter;
  375.  
  376.   public:
  377.     template<typename _Iterator>
  378.       const _Error_formatter&
  379.       _M_iterator(const _Iterator& __it, const char* __name = 0)  const
  380.       {
  381.         if (_M_num_parameters < std::size_t(__max_parameters))
  382.           _M_parameters[_M_num_parameters++] = _Parameter(__it, __name,
  383.                                                           _Is_iterator());
  384.         return *this;
  385.       }
  386.  
  387.     const _Error_formatter&
  388.     _M_integer(long __value, const char* __name = 0) const
  389.     {
  390.       if (_M_num_parameters < std::size_t(__max_parameters))
  391.         _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
  392.       return *this;
  393.     }
  394.  
  395.     const _Error_formatter&
  396.     _M_string(const char* __value, const char* __name = 0) const
  397.     {
  398.       if (_M_num_parameters < std::size_t(__max_parameters))
  399.         _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
  400.       return *this;
  401.     }
  402.  
  403.     template<typename _Sequence>
  404.       const _Error_formatter&
  405.       _M_sequence(const _Sequence& __seq, const char* __name = 0) const
  406.       {
  407.         if (_M_num_parameters < std::size_t(__max_parameters))
  408.           _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name,
  409.                                                           _Is_sequence());
  410.         return *this;
  411.       }
  412.  
  413.     const _Error_formatter&
  414.     _M_message(const char* __text) const
  415.     { _M_text = __text; return *this; }
  416.  
  417.     const _Error_formatter&
  418.     _M_message(_Debug_msg_id __id) const throw ();
  419.  
  420.     _GLIBCXX_NORETURN void
  421.     _M_error() const;
  422.  
  423.   private:
  424.     _Error_formatter(const char* __file, std::size_t __line)
  425.     : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0),
  426.       _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false)
  427.     { _M_get_max_length(); }
  428.  
  429.     template<typename _Tp>
  430.       void
  431.       _M_format_word(char*, int, const char*, _Tp) const throw ();
  432.  
  433.     void
  434.     _M_print_word(const char* __word) const;
  435.  
  436.     void
  437.     _M_print_string(const char* __string) const;
  438.  
  439.     void
  440.     _M_get_max_length() const throw ();
  441.  
  442.     enum { __max_parameters = 9 };
  443.  
  444.     const char*         _M_file;
  445.     std::size_t         _M_line;
  446.     mutable _Parameter  _M_parameters[__max_parameters];
  447.     mutable std::size_t _M_num_parameters;
  448.     mutable const char* _M_text;
  449.     mutable std::size_t _M_max_length;
  450.     enum { _M_indent = 4 } ;
  451.     mutable std::size_t _M_column;
  452.     mutable bool        _M_first_line;
  453.     mutable bool        _M_wordwrap;
  454.  
  455.   public:
  456.     static _Error_formatter
  457.     _M_at(const char* __file, std::size_t __line)
  458.     { return _Error_formatter(__file, __line); }
  459.   };
  460. } // namespace __gnu_debug
  461.  
  462. #endif
  463.