Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // Debug-mode error formatting implementation -*- C++ -*-
  2.  
  3. // Copyright (C) 2003-2015 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(const _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.     // others
  118.     __msg_equal_allocs,
  119.     __msg_insert_range_from_self
  120.   };
  121.  
  122.   class _Error_formatter
  123.   {
  124.     /// Whether an iterator is constant, mutable, or unknown
  125.     enum _Constness
  126.     {
  127.       __unknown_constness,
  128.       __const_iterator,
  129.       __mutable_iterator,
  130.       __last_constness
  131.     };
  132.  
  133.     // The state of the iterator (fine-grained), if we know it.
  134.     enum _Iterator_state
  135.     {
  136.       __unknown_state,
  137.       __singular,      // singular, may still be attached to a sequence
  138.       __begin,         // dereferenceable, and at the beginning
  139.       __middle,        // dereferenceable, not at the beginning
  140.       __end,           // past-the-end, may be at beginning if sequence empty
  141.       __before_begin,  // before begin
  142.       __last_state
  143.     };
  144.  
  145.     // Tags denoting the type of parameter for construction
  146.     struct _Is_iterator { };
  147.     struct _Is_sequence { };
  148.  
  149.     // A parameter that may be referenced by an error message
  150.     struct _Parameter
  151.     {
  152.       enum
  153.       {
  154.         __unused_param,
  155.         __iterator,
  156.         __sequence,
  157.         __integer,
  158.         __string
  159.       } _M_kind;
  160.  
  161.       union
  162.       {
  163.         // When _M_kind == __iterator
  164.         struct
  165.         {
  166.           const char*      _M_name;
  167.           const void*      _M_address;
  168.           const type_info* _M_type;
  169.           _Constness       _M_constness;
  170.           _Iterator_state  _M_state;
  171.           const void*      _M_sequence;
  172.           const type_info* _M_seq_type;
  173.         } _M_iterator;
  174.  
  175.         // When _M_kind == __sequence
  176.         struct
  177.         {
  178.           const char*      _M_name;
  179.           const void*      _M_address;
  180.           const type_info* _M_type;
  181.         } _M_sequence;
  182.  
  183.         // When _M_kind == __integer
  184.         struct
  185.         {
  186.           const char* _M_name;
  187.           long        _M_value;
  188.         } _M_integer;
  189.  
  190.         // When _M_kind == __string
  191.         struct
  192.         {
  193.           const char* _M_name;
  194.           const char* _M_value;
  195.         } _M_string;
  196.       } _M_variant;
  197.  
  198.       _Parameter() : _M_kind(__unused_param), _M_variant() { }
  199.  
  200.       _Parameter(long __value, const char* __name)
  201.       : _M_kind(__integer), _M_variant()
  202.       {
  203.         _M_variant._M_integer._M_name = __name;
  204.         _M_variant._M_integer._M_value = __value;
  205.       }
  206.  
  207.       _Parameter(const char* __value, const char* __name)
  208.       : _M_kind(__string), _M_variant()
  209.       {
  210.         _M_variant._M_string._M_name = __name;
  211.         _M_variant._M_string._M_value = __value;
  212.       }
  213.  
  214.       template<typename _Iterator, typename _Sequence>
  215.         _Parameter(const _Safe_iterator<_Iterator, _Sequence>& __it,
  216.                    const char* __name, _Is_iterator)
  217.         : _M_kind(__iterator),  _M_variant()
  218.         {
  219.           _M_variant._M_iterator._M_name = __name;
  220.           _M_variant._M_iterator._M_address = &__it;
  221. #if __cpp_rtti
  222.           _M_variant._M_iterator._M_type = &typeid(__it);
  223. #else
  224.           _M_variant._M_iterator._M_type = 0;
  225. #endif
  226.           _M_variant._M_iterator._M_constness =
  227.             std::__are_same<_Safe_iterator<_Iterator, _Sequence>,
  228.                             typename _Sequence::iterator>::
  229.               __value ? __mutable_iterator : __const_iterator;
  230.           _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
  231. #if __cpp_rtti
  232.           _M_variant._M_iterator._M_seq_type = &typeid(_Sequence);
  233. #else
  234.           _M_variant._M_iterator._M_seq_type = 0;
  235. #endif
  236.  
  237.           if (__it._M_singular())
  238.             _M_variant._M_iterator._M_state = __singular;
  239.           else
  240.             {
  241.               if (__it._M_is_before_begin())
  242.                 _M_variant._M_iterator._M_state = __before_begin;
  243.               else if (__it._M_is_end())
  244.                 _M_variant._M_iterator._M_state = __end;
  245.               else if (__it._M_is_begin())
  246.                 _M_variant._M_iterator._M_state = __begin;
  247.               else
  248.                 _M_variant._M_iterator._M_state = __middle;
  249.             }
  250.         }
  251.  
  252.       template<typename _Iterator, typename _Sequence>
  253.         _Parameter(const _Safe_local_iterator<_Iterator, _Sequence>& __it,
  254.                    const char* __name, _Is_iterator)
  255.         : _M_kind(__iterator),  _M_variant()
  256.         {
  257.           _M_variant._M_iterator._M_name = __name;
  258.           _M_variant._M_iterator._M_address = &__it;
  259. #if __cpp_rtti
  260.           _M_variant._M_iterator._M_type = &typeid(__it);
  261. #else
  262.           _M_variant._M_iterator._M_type = 0;
  263. #endif
  264.           _M_variant._M_iterator._M_constness =
  265.             std::__are_same<_Safe_local_iterator<_Iterator, _Sequence>,
  266.                             typename _Sequence::local_iterator>::
  267.               __value ? __mutable_iterator : __const_iterator;
  268.           _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
  269. #if __cpp_rtti
  270.           _M_variant._M_iterator._M_seq_type = &typeid(_Sequence);
  271. #else
  272.           _M_variant._M_iterator._M_seq_type = 0;
  273. #endif
  274.  
  275.           if (__it._M_singular())
  276.             _M_variant._M_iterator._M_state = __singular;
  277.           else
  278.             {
  279.               if (__it._M_is_end())
  280.                 _M_variant._M_iterator._M_state = __end;
  281.               else if (__it._M_is_begin())
  282.                 _M_variant._M_iterator._M_state = __begin;
  283.               else
  284.                 _M_variant._M_iterator._M_state = __middle;
  285.             }
  286.         }
  287.  
  288.       template<typename _Type>
  289.         _Parameter(const _Type*& __it, const char* __name, _Is_iterator)
  290.         : _M_kind(__iterator), _M_variant()
  291.         {
  292.           _M_variant._M_iterator._M_name = __name;
  293.           _M_variant._M_iterator._M_address = &__it;
  294. #if __cpp_rtti
  295.           _M_variant._M_iterator._M_type = &typeid(__it);
  296. #else
  297.           _M_variant._M_iterator._M_type = 0;
  298. #endif
  299.           _M_variant._M_iterator._M_constness = __mutable_iterator;
  300.           _M_variant._M_iterator._M_state = __it? __unknown_state : __singular;
  301.           _M_variant._M_iterator._M_sequence = 0;
  302.           _M_variant._M_iterator._M_seq_type = 0;
  303.         }
  304.  
  305.       template<typename _Type>
  306.         _Parameter(_Type*& __it, const char* __name, _Is_iterator)
  307.         : _M_kind(__iterator), _M_variant()
  308.         {
  309.           _M_variant._M_iterator._M_name = __name;
  310.           _M_variant._M_iterator._M_address = &__it;
  311. #if __cpp_rtti
  312.           _M_variant._M_iterator._M_type = &typeid(__it);
  313. #else
  314.           _M_variant._M_iterator._M_type = 0;
  315. #endif
  316.           _M_variant._M_iterator._M_constness = __const_iterator;
  317.           _M_variant._M_iterator._M_state = __it? __unknown_state : __singular;
  318.           _M_variant._M_iterator._M_sequence = 0;
  319.           _M_variant._M_iterator._M_seq_type = 0;
  320.         }
  321.  
  322.       template<typename _Iterator>
  323.         _Parameter(const _Iterator& __it, const char* __name, _Is_iterator)
  324.         : _M_kind(__iterator), _M_variant()
  325.         {
  326.           _M_variant._M_iterator._M_name = __name;
  327.           _M_variant._M_iterator._M_address = &__it;
  328. #if __cpp_rtti
  329.           _M_variant._M_iterator._M_type = &typeid(__it);
  330. #else
  331.           _M_variant._M_iterator._M_type = 0;
  332. #endif
  333.           _M_variant._M_iterator._M_constness = __unknown_constness;
  334.           _M_variant._M_iterator._M_state =
  335.             __gnu_debug::__check_singular(__it)? __singular : __unknown_state;
  336.           _M_variant._M_iterator._M_sequence = 0;
  337.           _M_variant._M_iterator._M_seq_type = 0;
  338.         }
  339.  
  340.       template<typename _Sequence>
  341.         _Parameter(const _Safe_sequence<_Sequence>& __seq,
  342.                    const char* __name, _Is_sequence)
  343.         : _M_kind(__sequence), _M_variant()
  344.         {
  345.           _M_variant._M_sequence._M_name = __name;
  346.           _M_variant._M_sequence._M_address =
  347.             static_cast<const _Sequence*>(&__seq);
  348. #if __cpp_rtti
  349.           _M_variant._M_sequence._M_type = &typeid(_Sequence);
  350. #else
  351.           _M_variant._M_sequence._M_type = 0;
  352. #endif
  353.         }
  354.  
  355.       template<typename _Sequence>
  356.         _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence)
  357.         : _M_kind(__sequence), _M_variant()
  358.         {
  359.           _M_variant._M_sequence._M_name = __name;
  360.           _M_variant._M_sequence._M_address = &__seq;
  361. #if __cpp_rtti
  362.           _M_variant._M_sequence._M_type = &typeid(_Sequence);
  363. #else
  364.           _M_variant._M_sequence._M_type = 0;
  365. #endif
  366.         }
  367.  
  368.       void
  369.       _M_print_field(const _Error_formatter* __formatter,
  370.                      const char* __name) const;
  371.  
  372.       void
  373.       _M_print_description(const _Error_formatter* __formatter) const;
  374.     };
  375.  
  376.     friend struct _Parameter;
  377.  
  378.   public:
  379.     template<typename _Iterator>
  380.       const _Error_formatter&
  381.       _M_iterator(const _Iterator& __it, const char* __name = 0)  const
  382.       {
  383.         if (_M_num_parameters < std::size_t(__max_parameters))
  384.           _M_parameters[_M_num_parameters++] = _Parameter(__it, __name,
  385.                                                           _Is_iterator());
  386.         return *this;
  387.       }
  388.  
  389.     const _Error_formatter&
  390.     _M_integer(long __value, const char* __name = 0) const
  391.     {
  392.       if (_M_num_parameters < std::size_t(__max_parameters))
  393.         _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
  394.       return *this;
  395.     }
  396.  
  397.     const _Error_formatter&
  398.     _M_string(const char* __value, const char* __name = 0) const
  399.     {
  400.       if (_M_num_parameters < std::size_t(__max_parameters))
  401.         _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
  402.       return *this;
  403.     }
  404.  
  405.     template<typename _Sequence>
  406.       const _Error_formatter&
  407.       _M_sequence(const _Sequence& __seq, const char* __name = 0) const
  408.       {
  409.         if (_M_num_parameters < std::size_t(__max_parameters))
  410.           _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name,
  411.                                                           _Is_sequence());
  412.         return *this;
  413.       }
  414.  
  415.     const _Error_formatter&
  416.     _M_message(const char* __text) const
  417.     { _M_text = __text; return *this; }
  418.  
  419.     const _Error_formatter&
  420.     _M_message(_Debug_msg_id __id) const throw ();
  421.  
  422.     _GLIBCXX_NORETURN void
  423.     _M_error() const;
  424.  
  425.   private:
  426.     _Error_formatter(const char* __file, std::size_t __line)
  427.     : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0),
  428.       _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false)
  429.     { _M_get_max_length(); }
  430.  
  431.     template<typename _Tp>
  432.       void
  433.       _M_format_word(char*, int, const char*, _Tp) const throw ();
  434.  
  435.     void
  436.     _M_print_word(const char* __word) const;
  437.  
  438.     void
  439.     _M_print_string(const char* __string) const;
  440.  
  441.     void
  442.     _M_get_max_length() const throw ();
  443.  
  444.     enum { __max_parameters = 9 };
  445.  
  446.     const char*         _M_file;
  447.     std::size_t         _M_line;
  448.     mutable _Parameter  _M_parameters[__max_parameters];
  449.     mutable std::size_t _M_num_parameters;
  450.     mutable const char* _M_text;
  451.     mutable std::size_t _M_max_length;
  452.     enum { _M_indent = 4 } ;
  453.     mutable std::size_t _M_column;
  454.     mutable bool        _M_first_line;
  455.     mutable bool        _M_wordwrap;
  456.  
  457.   public:
  458.     static _Error_formatter
  459.     _M_at(const char* __file, std::size_t __line)
  460.     { return _Error_formatter(__file, __line); }
  461.   };
  462. } // namespace __gnu_debug
  463.  
  464. #endif
  465.